blob: 252f2e488fe22be1805ead87eeef15c3acbe43e0 [file] [log] [blame]
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.7
/// TODO(johnniwinther): Move this test to the codegen folder.
import "package:async_helper/async_helper.dart";
import "package:compiler/src/commandline_options.dart";
import "package:compiler/src/common_elements.dart";
import "package:compiler/src/compiler.dart";
import "package:compiler/src/constants/values.dart";
import "package:compiler/src/elements/entities.dart";
import "package:compiler/src/inferrer/abstract_value_domain.dart";
import "package:compiler/src/inferrer/types.dart";
import 'package:compiler/src/inferrer/typemasks/masks.dart';
import 'package:compiler/src/js_model/js_strategy.dart';
import "package:compiler/src/world.dart";
import "package:expect/expect.dart";
import '../helpers/memory_compiler.dart';
import 'dart:async';
const String TEST1 = r"""
foo(x) {
return x;
}
bar(x) {
if (x) {
print("aaa");
} else {
print("bbb");
}
}
main() {
bar(foo(false));
bar(foo(foo(false)));
}
""";
Future runTest1() async {
CompilationResult result = await runCompiler(
memorySourceFiles: {'main.dart': TEST1},
options: [Flags.disableInlining]);
Compiler compiler = result.compiler;
JsBackendStrategy backendStrategy = compiler.backendStrategy;
GlobalTypeInferenceResults results =
compiler.globalInference.resultsForTesting;
JClosedWorld closedWorld = results.closedWorld;
JElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
AbstractValueDomain commonMasks = closedWorld.abstractValueDomain;
MemberEntity element = elementEnvironment.lookupLibraryMember(
elementEnvironment.mainLibrary, 'foo');
AbstractValue mask = results.resultOfMember(element).returnType;
AbstractValue falseType =
new ValueTypeMask(commonMasks.boolType, new FalseConstantValue());
// 'foo' should always return false
Expect.equals(falseType, mask);
// the argument to 'bar' is always false
MemberEntity bar = elementEnvironment.lookupLibraryMember(
elementEnvironment.mainLibrary, 'bar');
elementEnvironment.forEachParameterAsLocal(results.globalLocalsMap, bar,
(barArg) {
AbstractValue barArgMask = results.resultOfParameter(barArg);
Expect.equals(falseType, barArgMask);
});
String barCode = backendStrategy.getGeneratedCodeForTesting(bar);
Expect.isTrue(barCode.contains('"bbb"'));
Expect.isFalse(barCode.contains('"aaa"'));
}
const String TEST2 = r"""
foo(x) {
if (x > 3) return true;
return false;
}
bar(x) {
if (x) {
print("aaa");
} else {
print("bbb");
}
}
main() {
bar(foo(5));
bar(foo(6));
}
""";
Future runTest2() async {
CompilationResult result = await runCompiler(
memorySourceFiles: {'main.dart': TEST2},
options: [Flags.disableInlining]);
Compiler compiler = result.compiler;
JsBackendStrategy backendStrategy = compiler.backendStrategy;
GlobalTypeInferenceResults results =
compiler.globalInference.resultsForTesting;
JClosedWorld closedWorld = results.closedWorld;
AbstractValueDomain commonMasks = closedWorld.abstractValueDomain;
JElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
MemberEntity element = elementEnvironment.lookupLibraryMember(
elementEnvironment.mainLibrary, 'foo');
AbstractValue mask = results.resultOfMember(element).returnType;
// Can't infer value for foo's return type, it could be either true or false
Expect.identical(commonMasks.boolType, mask);
MemberEntity bar = elementEnvironment.lookupLibraryMember(
elementEnvironment.mainLibrary, 'bar');
elementEnvironment.forEachParameterAsLocal(results.globalLocalsMap, bar,
(barArg) {
AbstractValue barArgMask = results.resultOfParameter(barArg);
// The argument to bar should have the same type as the return type of foo
Expect.identical(commonMasks.boolType, barArgMask);
});
String barCode = backendStrategy.getGeneratedCodeForTesting(bar);
Expect.isTrue(barCode.contains('"bbb"'));
// Still must output the print for "aaa"
Expect.isTrue(barCode.contains('"aaa"'));
}
main() {
asyncTest(() async {
;
await runTest1();
await runTest2();
});
}