Version 2.0.0-dev.19.0
Merge commit '1065b683888b4578caa435a5b45f4095b9afbe64' into dev
diff --git a/BUILD.gn b/BUILD.gn
index e621934..3f93c69 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -4,9 +4,11 @@
import("build/dart_host_sdk_toolchain.gni")
+targetting_fuchsia = target_os == "fuchsia"
+
# This target will be built if no target is specified when invoking ninja.
group("default") {
- if (is_fuchsia || is_fuchsia_host) {
+ if (targetting_fuchsia) {
# Fuchsia has run_vm_tests marked testonly.
testonly = true
}
@@ -16,7 +18,7 @@
}
group("most") {
- if (is_fuchsia || is_fuchsia_host) {
+ if (targetting_fuchsia) {
# Fuchsia has run_vm_tests marked testonly.
testonly = true
}
@@ -32,7 +34,7 @@
}
group("runtime") {
- if (is_fuchsia || is_fuchsia_host) {
+ if (targetting_fuchsia) {
# Fuchsia has run_vm_tests marked testonly.
testonly = true
}
@@ -47,7 +49,7 @@
}
group("runtime_kernel") {
- if (is_fuchsia || is_fuchsia_host) {
+ if (targetting_fuchsia) {
# Fuchsia has run_vm_tests marked testonly.
testonly = true
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ad5a4f0..16177c9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,10 @@
some breaking API changes. See https://goo.gl/y9mW2x for more information.
* Renamed `Zone.ROOT` to `Zone.root`.
+* `dart:cli`
+ * Added function `waitFor` that suspends a stack to wait for a `Future` to
+ complete.
+
* `dart:core`
* The `Uri` class now correctly handles paths while running on Node.js on
Windows.
@@ -167,6 +171,11 @@
configure the number of dartdevc/analyzer workers that are used when compiling
with `--web-compiler=dartdevc`.
+* The Flutter `sdk` source will now look for packages in
+ `flutter/bin/cache/pkg/` as well as `flutter/packages/`. In particular, this
+ means that packages can depend on the `sky_engine` package from the `sdk`
+ source ([issue 1775][pub#1775]).
+
* Pub will now automatically retry HTTP requests that fail with a 502, 503, of
504 error code ([issue 1556][pub#1556]).
@@ -178,6 +187,7 @@
[pub#1556]: https://github.com/dart-lang/pub/issues/1556
[pub#1747]: https://github.com/dart-lang/pub/issues/1747
[pub#1769]: https://github.com/dart-lang/pub/issues/1769
+[pub#1775]: https://github.com/dart-lang/pub/issues/1775
##### Bug Fixes
diff --git a/DEPS b/DEPS
index 46b2c54..ce9dfaa 100644
--- a/DEPS
+++ b/DEPS
@@ -55,7 +55,7 @@
"barback-0.14.0_rev": "@36398",
"barback-0.14.1_rev": "@38525",
"barback_tag" : "@0.15.2+14",
- "bazel_worker_tag": "@v0.1.4",
+ "bazel_worker_tag": "@v0.1.9",
"boolean_selector_tag" : "@1.0.2",
"boringssl_gen_rev": "@d2b56d1b7657e52eb5a1f075968c773aa3e53614",
"boringssl_rev" : "@d519bf6be0b447fb80fbc539d4bff4479b5482a2",
@@ -82,7 +82,7 @@
# For more details, see https://github.com/dart-lang/sdk/issues/30164
"dart_style_tag": "@1.0.9", # Please see the note above before updating.
- "dartdoc_tag" : "@v0.15.0+1",
+ "dartdoc_tag" : "@v0.15.1",
"fixnum_tag": "@0.10.5",
"func_rev": "@25eec48146a58967d75330075ab376b3838b18a8",
"glob_tag": "@1.1.5",
@@ -108,12 +108,12 @@
"observatory_pub_packages_rev": "@4c282bb240b68f407c8c7779a65c68eeb0139dc6",
"package_config_tag": "@1.0.3",
"package_resolver_tag": "@1.0.2+1",
- "path_tag": "@1.4.2",
+ "path_tag": "@1.5.1",
"plugin_tag": "@0.2.0+2",
"ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
"pool_tag": "@1.3.4",
- "protobuf_tag": "@0.6.0",
- "pub_rev": "@ca0d52f5d4058e7b9ef7b5091e407ff3ac05198d",
+ "protobuf_tag": "@0.7.0",
+ "pub_rev": "@64c5f40adf6828da1b63320dd39bcedbef1354c6",
"pub_semver_tag": "@1.3.2",
"quiver_tag": "@0.27.0",
"resource_rev":"@af5a5bf65511943398146cf146e466e5f0b95cb9",
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 4dfbaf6..ff7b42f 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -154,7 +154,6 @@
is_android = false
is_chromeos = false
is_fuchsia = false
- is_fuchsia_host = false
is_ios = false
is_linux = false
is_mac = false
@@ -165,7 +164,6 @@
is_android = false
is_chromeos = false
is_fuchsia = false
- is_fuchsia_host = false
is_ios = false
is_linux = false
is_mac = true
@@ -176,7 +174,6 @@
is_android = true
is_chromeos = false
is_fuchsia = false
- is_fuchsia_host = false
is_ios = false
is_linux = false
is_mac = false
@@ -187,7 +184,6 @@
is_android = false
is_chromeos = false
is_fuchsia = false
- is_fuchsia_host = false
is_ios = false
is_linux = true
is_mac = false
@@ -252,9 +248,7 @@
}
if (is_clang) {
- _native_compiler_configs += [
- "//build/config/clang:extra_warnings",
- ]
+ _native_compiler_configs += [ "//build/config/clang:extra_warnings" ]
}
# Optimizations and debug checking.
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 5a92034..451bee0 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -7,7 +7,7 @@
sdk: '>=1.12.0 <2.0.0'
dependencies:
analyzer: ^0.30.0
- args: '>=0.13.0 <0.14.0'
+ args: '>=0.13.0 <2.0.0'
dart_style: '^1.0.6'
intl: ^0.15.0
isolate: '>=0.2.2 <2.0.0'
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 883a143..19df163 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -299,7 +299,6 @@
HintCode.UNUSED_IMPORT,
HintCode.UNUSED_LOCAL_VARIABLE,
HintCode.UNUSED_SHOWN_NAME,
- HintCode.USES_DYNAMIC_AS_BOTTOM,
HintCode.USE_OF_VOID_RESULT,
HintCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD,
HtmlErrorCode.PARSE_ERROR,
@@ -669,6 +668,7 @@
StrongModeCode.TOP_LEVEL_INSTANCE_GETTER,
StrongModeCode.TOP_LEVEL_TYPE_ARGUMENTS,
StrongModeCode.TOP_LEVEL_UNSUPPORTED,
+ StrongModeCode.USES_DYNAMIC_AS_BOTTOM,
TodoCode.TODO,
];
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index d1a4712..c2315b3 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -2250,7 +2250,7 @@
ConstructorElementImpl.forKernel(ClassElementImpl enclosingClass,
this._kernelConstructor, this._kernelFactory)
: super.forKernel(enclosingClass, _kernelConstructor ?? _kernelFactory) {
- isSynthetic = _kernelConstructor?.isSyntheticDefault ?? false;
+ isSynthetic = _kernelConstructor?.isSynthetic ?? false;
}
/**
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index eb7771a..54ad677 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -38,18 +38,6 @@
"The argument type '{0}' can't be assigned to the parameter type '{1}'.");
/**
- * This hint is generated when a function type is assigned to a function
- * typed location, and the assignment will be invalid after fuzzy arrows
- * (the treatment of dynamic as bottom in certain locations) is removed.
- *
- */
- static const HintCode USES_DYNAMIC_AS_BOTTOM = const HintCode(
- 'USES_DYNAMIC_AS_BOTTOM',
- "A function of type '{0}' can't be assigned to a variable of type '{1}'.",
- "Try changing the type of the function, or "
- "casting the right-hand type to '{1}'.");
-
- /**
* When the target expression uses '?.' operator, it can be `null`, so all the
* subsequent invocations should also use '?.' operator.
*/
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 56e0f25..381296e 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -5052,10 +5052,11 @@
"Try adding an explicit type to either the variable '{0}' or the variable '{1}'.");
static const StrongModeCode TOP_LEVEL_INSTANCE_GETTER = const StrongModeCode(
- ErrorType.HINT,
+ ErrorType.STATIC_WARNING,
'TOP_LEVEL_INSTANCE_GETTER',
- "The type of '{0}' can't be inferred because of the use of the instance getter '{1}'.",
- "Try removing the use of the instance getter {1}, or add an explicit type for '{0}'.");
+ "The type of '{0}' can't be inferred because it refers to an instance "
+ "getter, '{1}', which has an implicit type.",
+ "Add an explicit type for either '{0}' or '{1}'.");
static const StrongModeCode TOP_LEVEL_TYPE_ARGUMENTS = const StrongModeCode(
ErrorType.HINT,
@@ -5069,6 +5070,19 @@
"The type of '{0}' can't be inferred because {1} expressions aren't supported.",
"Try adding an explicit type for '{0}'.");
+ /**
+ * This warning is generated when a function type is assigned to a function
+ * typed location, and the assignment will be invalid after fuzzy arrows
+ * (the treatment of dynamic as bottom in certain locations) is removed.
+ *
+ */
+ static const StrongModeCode USES_DYNAMIC_AS_BOTTOM = const StrongModeCode(
+ ErrorType.STATIC_TYPE_WARNING,
+ 'USES_DYNAMIC_AS_BOTTOM',
+ "A function of type '{0}' can't be assigned to a location of type '{1}'.",
+ "Try changing the parameter types of the function or of the "
+ " receiving location.");
+
@override
final ErrorType type;
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart
index d0fe70f..1a944e0 100644
--- a/pkg/analyzer/lib/src/fasta/error_converter.dart
+++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -235,6 +235,10 @@
errorReporter?.reportErrorForOffset(
StaticWarningCode.FINAL_NOT_INITIALIZED, offset, length, [name]);
return;
+ case "FUNCTION_TYPED_PARAMETER_VAR":
+ errorReporter?.reportErrorForOffset(
+ ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, offset, length);
+ return;
case "GETTER_WITH_PARAMETERS":
errorReporter?.reportErrorForOffset(
ParserErrorCode.GETTER_WITH_PARAMETERS, offset, length);
diff --git a/pkg/analyzer/lib/src/kernel/loader.dart b/pkg/analyzer/lib/src/kernel/loader.dart
index 525e5aa..24808f0 100644
--- a/pkg/analyzer/lib/src/kernel/loader.dart
+++ b/pkg/analyzer/lib/src/kernel/loader.dart
@@ -527,7 +527,7 @@
name: _nameOfMember(element),
isConst: constructor.isConst,
isExternal: constructor.isExternal,
- isSyntheticDefault: constructor.isSynthetic)
+ isSynthetic: constructor.isSynthetic)
..fileOffset = element.nameOffset;
case ElementKind.FIELD:
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 395dd83..445e54a 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -1123,7 +1123,7 @@
var cTo = rules.typeToConcreteType(to);
// If still true, no warning needed
if (rules.isSubtypeOf(cFrom, cTo)) return;
- _recordMessage(expr, HintCode.USES_DYNAMIC_AS_BOTTOM, [from, to]);
+ _recordMessage(expr, StrongModeCode.USES_DYNAMIC_AS_BOTTOM, [from, to]);
}
}
@@ -1276,9 +1276,7 @@
errorCode.name.startsWith('STRONG_MODE_TOP_LEVEL_')) {
severity = ErrorSeverity.ERROR;
}
- if (severity != ErrorSeverity.INFO ||
- _options.strongModeHints ||
- errorCode == HintCode.USES_DYNAMIC_AS_BOTTOM) {
+ if (severity != ErrorSeverity.INFO || _options.strongModeHints) {
int begin = node is AnnotatedNode
? node.firstTokenAfterCommentAndMetadata.offset
: node.offset;
@@ -1314,8 +1312,20 @@
return;
}
- if (e is PropertyAccessorElement) {
- validateHasType(e);
+ Element enclosing = e.enclosingElement;
+ if (enclosing is CompilationUnitElement) {
+ if (e is PropertyAccessorElement) {
+ validateHasType(e);
+ }
+ } else if (enclosing is ClassElement) {
+ if (e is PropertyAccessorElement) {
+ if (e.isStatic) {
+ validateHasType(e);
+ } else if (e.hasImplicitReturnType) {
+ _recordMessage(
+ n, StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, [name, e.name]);
+ }
+ }
}
}
@@ -1393,6 +1403,7 @@
} else if (n is FunctionExpressionInvocation) {
_validateTopLevelInitializer(name, n.function);
} else if (n is MethodInvocation) {
+ _validateTopLevelInitializer(name, n.methodName);
_validateTopLevelInitializer(name, n.target);
} else if (n is CascadeExpression) {
_validateTopLevelInitializer(name, n.target);
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
index 9db22ac..cd35af5 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
@@ -3087,6 +3087,18 @@
// Test passes, even though if fails in the superclass
await super.test_yieldInNonGenerator_async();
}
+
+ @override
+ @failingTest
+ test_implementsDisallowedClass_class_String_num() async {
+ await super.test_implementsDisallowedClass_class_String_num();
+ }
+
+ @override
+ @failingTest
+ test_implementsDisallowedClass_classTypeAlias_String_num() async {
+ await super.test_implementsDisallowedClass_classTypeAlias_String_num();
+ }
}
/// Tests marked with this annotation fail because of a Fasta problem.
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index de88150..89b011f 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -2859,8 +2859,15 @@
final y = x;
}''');
await computeAnalysisResult(source);
- assertErrors(
- source, [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
+ if (enableKernelDriver) {
+ assertErrors(source,
+ [CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER]);
+ } else {
+ assertErrors(source, [
+ CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER,
+ StrongModeCode.TOP_LEVEL_INSTANCE_GETTER
+ ]);
+ }
verify([source]);
}
diff --git a/pkg/analyzer/test/generated/hint_code_kernel_test.dart b/pkg/analyzer/test/generated/hint_code_kernel_test.dart
index ccab1d2..9662e18 100644
--- a/pkg/analyzer/test/generated/hint_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_kernel_test.dart
@@ -470,4 +470,10 @@
// Expected 1 errors of type HintCode.UNUSED_SHOWN_NAME, found 0
return super.test_unusedShownName_topLevelVariable();
}
+
+ @failingTest
+ @override
+ test_importDeferredLibraryWithLoadFunction() async {
+ await super.test_importDeferredLibraryWithLoadFunction();
+ }
}
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 4b5f6f7..40f3c65 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -4,6 +4,7 @@
library analyzer.test.generated.hint_code_test;
+import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -2898,6 +2899,206 @@
verify([source]);
}
+ test_strongMode_topLevelInstanceGetter() async {
+ resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+ Source source = addSource('''
+class A {
+ int get g => 0;
+}
+var b = new A().g;
+''');
+ var analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ TopLevelVariableDeclaration b = analysisResult.unit.declarations[1];
+ expect(b.variables.variables[0].element.type.toString(), 'int');
+ verify([source]);
+ }
+
+ test_strongMode_topLevelInstanceGetter_call() async {
+ resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+ Source source = addSource('''
+class A {
+ int Function() get g => () => 0;
+}
+var a = new A();
+var b = a.g();
+''');
+ var analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ TopLevelVariableDeclaration b = analysisResult.unit.declarations[2];
+ expect(b.variables.variables[0].element.type.toString(), 'int');
+ verify([source]);
+ }
+
+ test_strongMode_topLevelInstanceGetter_field() async {
+ resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+ Source source = addSource('''
+class A {
+ int g;
+}
+var b = new A().g;
+''');
+ var analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ TopLevelVariableDeclaration b = analysisResult.unit.declarations[1];
+ expect(b.variables.variables[0].element.type.toString(), 'int');
+ verify([source]);
+ }
+
+ test_strongMode_topLevelInstanceGetter_field_call() async {
+ resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+ Source source = addSource('''
+class A {
+ int Function() g;
+}
+var a = new A();
+var b = a.g();
+''');
+ var analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ TopLevelVariableDeclaration b = analysisResult.unit.declarations[2];
+ expect(b.variables.variables[0].element.type.toString(), 'int');
+ verify([source]);
+ }
+
+ test_strongMode_topLevelInstanceGetter_field_prefixedIdentifier() async {
+ resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+ Source source = addSource('''
+class A {
+ int g;
+}
+var a = new A();
+var b = a.g;
+''');
+ var analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ TopLevelVariableDeclaration b = analysisResult.unit.declarations[2];
+ expect(b.variables.variables[0].element.type.toString(), 'int');
+ verify([source]);
+ }
+
+ test_strongMode_topLevelInstanceGetter_implicitlyTyped() async {
+ resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+ Source source = addSource('''
+class A {
+ get g => 0;
+}
+var b = new A().g;
+''');
+ await computeAnalysisResult(source);
+ if (enableKernelDriver) {
+ assertNoErrors(source);
+ } else {
+ assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+ }
+ verify([source]);
+ }
+
+ test_strongMode_topLevelInstanceGetter_implicitlyTyped_call() async {
+ resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+ Source source = addSource('''
+class A {
+ get g => () => 0;
+}
+var a = new A();
+var b = a.g();
+''');
+ await computeAnalysisResult(source);
+ if (enableKernelDriver) {
+ assertNoErrors(source);
+ } else {
+ assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+ }
+ verify([source]);
+ }
+
+ test_strongMode_topLevelInstanceGetter_implicitlyTyped_field() async {
+ resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+ Source source = addSource('''
+class A {
+ var g = 0;
+}
+var b = new A().g;
+''');
+ await computeAnalysisResult(source);
+ if (enableKernelDriver) {
+ assertNoErrors(source);
+ } else {
+ assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+ }
+ verify([source]);
+ }
+
+ test_strongMode_topLevelInstanceGetter_implicitlyTyped_field_call() async {
+ resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+ Source source = addSource('''
+class A {
+ var g = () => 0;
+}
+var a = new A();
+var b = a.g();
+''');
+ await computeAnalysisResult(source);
+ if (enableKernelDriver) {
+ assertNoErrors(source);
+ } else {
+ assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+ }
+ verify([source]);
+ }
+
+ test_strongMode_topLevelInstanceGetter_implicitlyTyped_field_prefixedIdentifier() async {
+ resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+ Source source = addSource('''
+class A {
+ var g = 0;
+}
+var a = new A();
+var b = a.g;
+''');
+ await computeAnalysisResult(source);
+ if (enableKernelDriver) {
+ assertNoErrors(source);
+ } else {
+ assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+ }
+ verify([source]);
+ }
+
+ test_strongMode_topLevelInstanceGetter_implicitlyTyped_prefixedIdentifier() async {
+ resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+ Source source = addSource('''
+class A {
+ get g => 0;
+}
+var a = new A();
+var b = a.g;
+''');
+ await computeAnalysisResult(source);
+ if (enableKernelDriver) {
+ assertNoErrors(source);
+ } else {
+ assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+ }
+ verify([source]);
+ }
+
+ test_strongMode_topLevelInstanceGetter_prefixedIdentifier() async {
+ resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+ Source source = addSource('''
+class A {
+ int get g => 0;
+}
+var a = new A();
+var b = a.g;
+''');
+ var analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ TopLevelVariableDeclaration b = analysisResult.unit.declarations[2];
+ expect(b.variables.variables[0].element.type.toString(), 'int');
+ verify([source]);
+ }
+
test_typeCheck_type_is_Null() async {
Source source = addSource(r'''
m(i) {
diff --git a/pkg/analyzer/test/generated/non_hint_code_kernel_test.dart b/pkg/analyzer/test/generated/non_hint_code_kernel_test.dart
index e8a95d5..62c81bc 100644
--- a/pkg/analyzer/test/generated/non_hint_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_kernel_test.dart
@@ -126,4 +126,11 @@
test_unusedImport_metadata() async {
await super.test_unusedImport_metadata();
}
+
+ @failingTest
+ @override
+ @potentialAnalyzerProblem
+ test_importDeferredLibraryWithLoadFunction() async {
+ await super.test_importDeferredLibraryWithLoadFunction();
+ }
}
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index b5f10f5..bd0444f 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -389,42 +389,6 @@
@override
@failingTest
- void test_functionTypedParameter_final() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 1 errors of type ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, found 0
- super.test_functionTypedParameter_final();
- }
-
- @override
- @failingTest
- void test_functionTypedParameter_incomplete1() {
- // TODO(brianwilkerson) Does not recover.
- // type 'FormalParameterListImpl' is not a subtype of type 'TypeParameterList' of 'typeParameters' where
- // FormalParameterListImpl is from package:analyzer/src/dart/ast/ast.dart
- // TypeParameterList is from package:analyzer/dart/ast/ast.dart
- //
- // package:analyzer/src/fasta/ast_builder.dart 1122:40 AstBuilder.endTopLevelMethod
- // package:front_end/src/fasta/parser/parser.dart 1741:14 Parser.parseTopLevelMethod
- // package:front_end/src/fasta/parser/parser.dart 1646:11 Parser.parseTopLevelMember
- // package:front_end/src/fasta/parser/parser.dart 298:14 Parser._parseTopLevelDeclaration
- // package:front_end/src/fasta/parser/parser.dart 263:13 Parser.parseTopLevelDeclaration
- // package:front_end/src/fasta/parser/parser.dart 252:15 Parser.parseUnit
- // package:analyzer/src/generated/parser_fasta.dart 77:33 _Parser2.parseCompilationUnit2
- // package:analyzer/src/generated/parser_fasta.dart 72:12 _Parser2.parseCompilationUnit
- // test/generated/parser_fasta_test.dart 2543:35 FastaParserTestCase.parseCompilationUnit
- super.test_functionTypedParameter_incomplete1();
- }
-
- @override
- @failingTest
- void test_functionTypedParameter_var() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 1 errors of type ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, found 0
- super.test_functionTypedParameter_var();
- }
-
- @override
- @failingTest
void test_getterInFunction_block_noReturnType() {
// TODO(brianwilkerson) Does not recover.
// type 'ExpressionStatementImpl' is not a subtype of type 'FunctionDeclarationStatement' of 'statement' where
@@ -1464,18 +1428,6 @@
}
@override
- void test_varAndType_local() {
- // The inherited test is marked as failing.
- super.test_varAndType_local();
- }
-
- @override
- void test_varAndType_parameter() {
- // The inherited test is marked as failing.
- super.test_varAndType_parameter();
- }
-
- @override
// @failingTest
void test_voidVariable_parseClassMember_initializer() {
// TODO(brianwilkerson) Passes, but ought to fail.
@@ -2130,36 +2082,6 @@
class FormalParameterParserTest_Fasta extends FastaParserTestCase
with FormalParameterParserTestMixin {
@override
- @failingTest
- void test_parseNormalFormalParameter_field_const_noType() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 0 errors of type ParserErrorCode.EXTRANEOUS_MODIFIER, found 1 (1)
- super.test_parseNormalFormalParameter_field_const_noType();
- }
-
- @failingTest
- void test_parseNormalFormalParameter_field_const_noType2() {
- // TODO(danrubel): should not be generating an error
- super.test_parseNormalFormalParameter_field_const_noType();
- assertNoErrors();
- }
-
- @override
- @failingTest
- void test_parseNormalFormalParameter_field_const_type() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 0 errors of type ParserErrorCode.EXTRANEOUS_MODIFIER, found 1 (1)
- super.test_parseNormalFormalParameter_field_const_type();
- }
-
- @failingTest
- void test_parseNormalFormalParameter_field_const_type2() {
- // TODO(danrubel): should not be generating an error
- super.test_parseNormalFormalParameter_field_const_type();
- assertNoErrors();
- }
-
- @override
void test_parseNormalFormalParameter_function_noType_typeParameterComments() {
// Ignored: Fasta does not support the generic comment syntax.
}
@@ -2173,36 +2095,6 @@
void test_parseNormalFormalParameter_function_void_typeParameterComments() {
// Ignored: Fasta does not support the generic comment syntax.
}
-
- @override
- @failingTest
- void test_parseNormalFormalParameter_simple_const_noType() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 0 errors of type ParserErrorCode.EXTRANEOUS_MODIFIER, found 1 (1)
- super.test_parseNormalFormalParameter_simple_const_noType();
- }
-
- @failingTest
- void test_parseNormalFormalParameter_simple_const_noType2() {
- // TODO(danrubel): should not be generating an error
- super.test_parseNormalFormalParameter_simple_const_noType();
- assertNoErrors();
- }
-
- @override
- @failingTest
- void test_parseNormalFormalParameter_simple_const_type() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 0 errors of type ParserErrorCode.EXTRANEOUS_MODIFIER, found 1 (1)
- super.test_parseNormalFormalParameter_simple_const_type();
- }
-
- @failingTest
- void test_parseNormalFormalParameter_simple_const_type2() {
- // TODO(danrubel): should not be generating an error
- super.test_parseNormalFormalParameter_simple_const_type();
- assertNoErrors();
- }
}
/**
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index e371ddd..8cbebc2 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -2686,6 +2686,15 @@
]);
}
+ void test_covariantAndType_local() {
+ // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
+ // this would be a better error message.
+ parseStatement("covariant int x;");
+ listener.assertErrors(usingFastaParser
+ ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 9)]
+ : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 9)]);
+ }
+
void test_covariantMember_getter_noReturnType() {
createParser('static covariant get x => 0;');
ClassMember member = parser.parseClassMember('C');
@@ -3480,43 +3489,43 @@
void test_functionTypedParameter_const() {
parseCompilationUnit("void f(const x()) {}",
errors: usingFastaParser
- ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 7, 5)]
+ ? [
+ expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 7, 5),
+ expectedError(
+ ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
+ ]
: [
expectedError(
- ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 9)
+ ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
]);
}
void test_functionTypedParameter_final() {
parseCompilationUnit("void f(final x()) {}", errors: [
- expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 9)
+ expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
]);
}
void test_functionTypedParameter_incomplete1() {
- // This caused an exception at one point.
- if (fe.Scanner.useFasta) {
- parseCompilationUnit("void f(int Function(", errors: [
- expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 0),
- expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 0),
- expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 20, 0),
- ]);
- } else {
- parseCompilationUnit("void f(int Function(", codes: [
- ParserErrorCode.MISSING_FUNCTION_BODY,
- ParserErrorCode.MISSING_CLOSING_PARENTHESIS,
- ParserErrorCode.EXPECTED_EXECUTABLE,
- ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN
- ]);
- }
+ parseCompilationUnit("void f(int Function(",
+ errors: usingFastaParser
+ ? [
+ expectedError(ScannerErrorCode.EXPECTED_TOKEN, 6, 1),
+ expectedError(ScannerErrorCode.EXPECTED_TOKEN, 19, 1),
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 8),
+ expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
+ ]
+ : [
+ expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 0),
+ expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 0),
+ expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 20, 0),
+ ]);
}
void test_functionTypedParameter_var() {
parseCompilationUnit("void f(var x()) {}", errors: [
- expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 7)
+ expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 3)
]);
}
@@ -5242,22 +5251,24 @@
errors: [expectedError(ParserErrorCode.VAR_AND_TYPE, 14, 3)]);
}
- @failingTest
void test_varAndType_local() {
// This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
// this would be a better error message.
parseStatement("var int x;");
- listener.assertErrors([expectedError(ParserErrorCode.VAR_AND_TYPE, 4, 3)]);
+ listener.assertErrors(usingFastaParser
+ ? [expectedError(ParserErrorCode.VAR_AND_TYPE, 4, 3)]
+ : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 8, 1)]);
}
- @failingTest
void test_varAndType_parameter() {
// This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
// this would be a better error message.
createParser('(var int x)');
FormalParameterList list = parser.parseFormalParameterList();
expectNotNullIfNoErrors(list);
- listener.assertErrors([expectedError(ParserErrorCode.VAR_AND_TYPE, 5, 3)]);
+ listener.assertErrors(usingFastaParser
+ ? [expectedError(ParserErrorCode.VAR_AND_TYPE, 5, 3)]
+ : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
}
void test_varAndType_topLevelVariable() {
@@ -8815,8 +8826,9 @@
}
void test_parseNormalFormalParameter_field_const_noType() {
- NormalFormalParameter parameter =
- parseNormalFormalParameter('const this.a');
+ NormalFormalParameter parameter = parseNormalFormalParameter('const this.a',
+ errorCodes:
+ usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
expect(parameter, isNotNull);
expect(parameter, new isInstanceOf<FieldFormalParameter>());
FieldFormalParameter fieldParameter = parameter;
@@ -8827,15 +8839,11 @@
}
void test_parseNormalFormalParameter_field_const_type() {
- NormalFormalParameter parameter =
- parseNormalFormalParameter('const A this.a');
+ NormalFormalParameter parameter = parseNormalFormalParameter(
+ 'const A this.a',
+ errorCodes:
+ usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
expect(parameter, isNotNull);
- if (usingFastaParser) {
- // TODO(danrubel): should not be generating an error
- assertErrorsWithCodes([ParserErrorCode.EXTRANEOUS_MODIFIER]);
- } else {
- assertNoErrors();
- }
expect(parameter, new isInstanceOf<FieldFormalParameter>());
FieldFormalParameter fieldParameter = parameter;
expect(fieldParameter.keyword, isNotNull);
@@ -9116,14 +9124,10 @@
}
void test_parseNormalFormalParameter_simple_const_noType() {
- NormalFormalParameter parameter = parseNormalFormalParameter('const a');
+ NormalFormalParameter parameter = parseNormalFormalParameter('const a',
+ errorCodes:
+ usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
expect(parameter, isNotNull);
- if (usingFastaParser) {
- // TODO(danrubel): should not be generating an error
- assertErrorsWithCodes([ParserErrorCode.EXTRANEOUS_MODIFIER]);
- } else {
- assertNoErrors();
- }
expect(parameter, new isInstanceOf<SimpleFormalParameter>());
SimpleFormalParameter simpleParameter = parameter;
expect(simpleParameter.keyword, isNotNull);
@@ -9132,14 +9136,10 @@
}
void test_parseNormalFormalParameter_simple_const_type() {
- NormalFormalParameter parameter = parseNormalFormalParameter('const A a');
+ NormalFormalParameter parameter = parseNormalFormalParameter('const A a',
+ errorCodes:
+ usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
expect(parameter, isNotNull);
- if (usingFastaParser) {
- // TODO(danrubel): should not be generating an error
- assertErrorsWithCodes([ParserErrorCode.EXTRANEOUS_MODIFIER]);
- } else {
- assertNoErrors();
- }
expect(parameter, new isInstanceOf<SimpleFormalParameter>());
SimpleFormalParameter simpleParameter = parameter;
expect(simpleParameter.keyword, isNotNull);
diff --git a/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart b/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
index 2173912..e6af706 100644
--- a/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
@@ -136,12 +136,10 @@
*/
@reflectiveTest
class BracketsTest extends AbstractRecoveryTest {
- @failingTest
void test_indexOperator() {
- // Parser crashes
testRecovery('''
f(x) => l[x
-''', [ScannerErrorCode.EXPECTED_TOKEN, ScannerErrorCode.EXPECTED_TOKEN], '''
+''', [ScannerErrorCode.EXPECTED_TOKEN, ParserErrorCode.EXPECTED_TOKEN], '''
f(x) => l[x];
''');
}
@@ -166,12 +164,10 @@
''');
}
- @failingTest
void test_listLiteral_outer_last() {
- // Parser crashes
testRecovery('''
var x = [0, 1
-''', [ScannerErrorCode.EXPECTED_TOKEN, ScannerErrorCode.EXPECTED_TOKEN], '''
+''', [ScannerErrorCode.EXPECTED_TOKEN, ParserErrorCode.EXPECTED_TOKEN], '''
var x = [0, 1];
''');
}
@@ -224,12 +220,11 @@
''');
}
- @failingTest
void test_parameterList_eof() {
- // Parser crashes
testRecovery('''
f(x
-''', [ScannerErrorCode.EXPECTED_TOKEN], '''
+''', [ScannerErrorCode.EXPECTED_TOKEN, ParserErrorCode.MISSING_FUNCTION_BODY],
+ '''
f(x) {}
''');
}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 58cc888..4c392b1 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -1152,7 +1152,9 @@
void compareVariableElements(
VariableElement resynthesized, VariableElement original, String desc) {
compareElements(resynthesized, original, desc);
- compareTypes(resynthesized.type, original.type, '$desc.type');
+ if ((resynthesized as VariableElementImpl).typeInferenceError == null) {
+ compareTypes(resynthesized.type, original.type, '$desc.type');
+ }
VariableElementImpl resynthesizedActual =
getActualElement(resynthesized, desc);
VariableElementImpl originalActual = getActualElement(original, desc);
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index 9479152..fa4342b 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -270,6 +270,7 @@
removeCode(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER);
removeCode(StrongModeCode.TOP_LEVEL_TYPE_ARGUMENTS);
removeCode(StrongModeCode.TOP_LEVEL_UNSUPPORTED);
+ removeCode(StrongModeCode.USES_DYNAMIC_AS_BOTTOM);
} else if (errorType == TodoCode) {
declaredNames.remove('TODO_REGEX');
}
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 2ed061e..7b914d9 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -489,7 +489,7 @@
f1("hello");
dynamic f2 = foo;
(/*info:DYNAMIC_INVOKE*/f2("hello"));
- DynFun f3 = /*info:USES_DYNAMIC_AS_BOTTOM*/foo;
+ DynFun f3 = /*warning:USES_DYNAMIC_AS_BOTTOM*/foo;
(/*info:DYNAMIC_INVOKE*/f3("hello"));
(/*info:DYNAMIC_INVOKE*/f3(42));
StrFun f4 = foo;
@@ -673,7 +673,7 @@
/*info:DYNAMIC_INVOKE*/f./*error:UNDEFINED_METHOD*/col(3);
}
{
- A f = /*info:USES_DYNAMIC_AS_BOTTOM*/new B();
+ A f = /*warning:USES_DYNAMIC_AS_BOTTOM*/new B();
int x;
double y;
x = /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/f(3);
@@ -686,7 +686,7 @@
/*info:DYNAMIC_INVOKE*/g.col(42.0);
/*info:DYNAMIC_INVOKE*/g.foo(42.0);
/*info:DYNAMIC_INVOKE*/g.x;
- A f = /*info:USES_DYNAMIC_AS_BOTTOM*/new B();
+ A f = /*warning:USES_DYNAMIC_AS_BOTTOM*/new B();
/*info:DYNAMIC_INVOKE*/f./*error:UNDEFINED_METHOD*/col(42.0);
/*info:DYNAMIC_INVOKE*/f./*error:UNDEFINED_METHOD*/foo(42.0);
/*info:DYNAMIC_INVOKE*/f./*error:UNDEFINED_GETTER*/x;
@@ -3091,7 +3091,7 @@
TakesA<int> f;
TakesA<dynamic> g;
TakesA<String> h;
- g = /*info:USES_DYNAMIC_AS_BOTTOM*/h;
+ g = /*warning:USES_DYNAMIC_AS_BOTTOM*/h;
f = /*info:DOWN_CAST_COMPOSITE*/f ?? g;
}
''');
diff --git a/pkg/analyzer_cli/pubspec.yaml b/pkg/analyzer_cli/pubspec.yaml
index baf4e6f..8de598f 100644
--- a/pkg/analyzer_cli/pubspec.yaml
+++ b/pkg/analyzer_cli/pubspec.yaml
@@ -7,7 +7,7 @@
sdk: '>=1.12.0 <2.0.0'
dependencies:
analyzer: ^0.27.0
- args: ^0.13.0
+ args: '>=0.13.0 <2.0.0'
bazel_worker: ^0.1.0
cli_util: ^0.1.0
collection: ^1.14.1
diff --git a/pkg/analyzer_cli/tool/perf.dart b/pkg/analyzer_cli/tool/perf.dart
index f8a7803..4aa3aa6 100644
--- a/pkg/analyzer_cli/tool/perf.dart
+++ b/pkg/analyzer_cli/tool/perf.dart
@@ -149,6 +149,7 @@
var libs = [
"dart:async",
+ "dart:cli",
"dart:collection",
"dart:convert",
"dart:core",
@@ -158,7 +159,7 @@
"dart:math",
"dart:mirrors",
"dart:typed_data",
- "dart:io"
+ "dart:io",
];
for (var lib in libs) {
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index c1755d7..bd60f84 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -1486,40 +1486,12 @@
MessageKind.FINAL_FUNCTION_TYPE_PARAMETER: const MessageTemplate(
MessageKind.FINAL_FUNCTION_TYPE_PARAMETER,
"A function type parameter can't be declared final.",
- howToFix: "Try removing 'final'.",
- examples: const [
- """
-foo(final int x(int a)) {}
-main() => foo((y) => 42);
-""",
- """
-foo({final int x(int a)}) {}
-main() => foo((y) => 42);
-""",
- """
-foo([final int x(int a)]) {}
-main() => foo((y) => 42);
-"""
- ]),
+ howToFix: "Try removing 'final'."),
MessageKind.VAR_FUNCTION_TYPE_PARAMETER: const MessageTemplate(
MessageKind.VAR_FUNCTION_TYPE_PARAMETER,
"A function type parameter can't be declared with 'var'.",
- howToFix: "Try removing 'var'.",
- examples: const [
- """
-foo(var int x(int a)) {}
-main() => foo((y) => 42);
-""",
- """
-foo({var int x(int a)}) {}
-main() => foo((y) => 42);
-""",
- """
-foo([var int x(int a)]) {}
-main() => foo((y) => 42);
-"""
- ]),
+ howToFix: "Try removing 'var'."),
MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE: const MessageTemplate(
MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index e508a0c..a02087a 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -1680,6 +1680,11 @@
}
@override
+ TypeInformation visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded node) {
+ return _types.nonNullEmpty();
+ }
+
+ @override
TypeInformation visitInvalidExpression(ir.InvalidExpression node) {
// TODO(johnniwinther): Maybe this should be [empty] instead?
return _types.dynamicType;
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index 097def4..21cb15e 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -116,6 +116,9 @@
// used in impact builder for symbol constants.
ConstantValue getConstantValue(ir.Expression expression,
{bool requireConstant: true, bool implicitNull: false});
+
+ /// Return the [ImportEntity] corresponding to [node].
+ ImportEntity getImport(ir.LibraryDependency node);
}
/// Interface that translates between Kernel IR nodes and entities used for
@@ -182,9 +185,6 @@
/// Returns the definition information for [cls].
ClassDefinition getClassDefinition(covariant ClassEntity cls);
-
- /// Return the [ImportEntity] corresponding to [node].
- ImportEntity getImport(ir.LibraryDependency node);
}
/// Interface that translates between Kernel IR nodes and entities used for
@@ -229,11 +229,6 @@
/// Returns the constructor body entity corresponding to [constructor].
FunctionEntity getConstructorBody(ir.Constructor node);
- /// Returns the uri for the deferred import [node].
- // TODO(johnniwinther): Avoid this method by deriving the uri directly from
- // the node.
- String getDeferredUri(ir.LibraryDependency node);
-
/// Make a record to ensure variables that are are declared in one scope and
/// modified in another get their values updated correctly.
Map<Local, JRecordField> makeRecordContainer(
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index c9e1de2..4734f47 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -796,6 +796,13 @@
assert(checkFamily(cls));
return _classes.getData(cls).definition;
}
+
+ @override
+ ImportEntity getImport(ir.LibraryDependency node) {
+ ir.Library library = node.parent;
+ LibraryData data = _libraries.getData(_getLibrary(library));
+ return data.imports[node];
+ }
}
/// Mixin that implements the abstract methods in [KernelToElementMapBase].
@@ -1285,13 +1292,6 @@
}
@override
- ImportEntity getImport(ir.LibraryDependency node) {
- ir.Library library = node.parent;
- LibraryData data = _libraries.getData(_getLibrary(library));
- return data.imports[node];
- }
-
- @override
MemberDefinition getMemberDefinition(MemberEntity member) {
return _getMemberDefinition(member);
}
@@ -2721,10 +2721,6 @@
String _getClosureVariableName(String name, int id) {
return "_captured_${name}_$id";
}
-
- String getDeferredUri(ir.LibraryDependency node) {
- throw new UnimplementedError('JsKernelToElementMap.getDeferredUri');
- }
}
class KernelClassQueries extends ClassQueries {
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 8d9f0d6..8e99d15 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -157,7 +157,7 @@
Iterable<ConstantValue> _metadata;
Map<ir.LibraryDependency, ImportEntity> imports;
- LibraryData(this.library);
+ LibraryData(this.library, [this.imports]);
Iterable<ConstantValue> getMetadata(KernelToElementMapBase elementMap) {
return _metadata ??= elementMap.getMetadata(library.annotations);
@@ -184,7 +184,7 @@
}
LibraryData copy() {
- return new LibraryData(library);
+ return new LibraryData(library, imports);
}
}
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index e79d5da..24b957d 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -192,6 +192,7 @@
/// The locations of js patch-files relative to the sdk-descriptors.
static const _patchLocations = const <String, String>{
"async": "_internal/js_runtime/lib/async_patch.dart",
+ "cli": "_internal/js_runtime/lib/cli_patch.dart",
"collection": "_internal/js_runtime/lib/collection_patch.dart",
"convert": "_internal/js_runtime/lib/convert_patch.dart",
"core": "_internal/js_runtime/lib/core_patch.dart",
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 5c6a96f..ce0d531 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -1146,10 +1146,12 @@
@override
void visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded checkLoad) {
- HInstruction prefixConstant =
- graph.addConstantString(checkLoad.import.name, closedWorld);
- String uri = _elementMap.getDeferredUri(checkLoad.import);
- HInstruction uriConstant = graph.addConstantString(uri, closedWorld);
+ ImportEntity import = _elementMap.getImport(checkLoad.import);
+ String loadId = deferredLoadTask.getImportDeferName(
+ _elementMap.getSpannable(targetElement, checkLoad), import);
+ HInstruction prefixConstant = graph.addConstantString(loadId, closedWorld);
+ HInstruction uriConstant =
+ graph.addConstantString('${import.uri}', closedWorld);
_pushStaticInvocation(
_commonElements.checkDeferredIsLoaded,
[prefixConstant, uriConstant],
@@ -1159,11 +1161,12 @@
@override
void visitLoadLibrary(ir.LoadLibrary loadLibrary) {
+ String loadId = deferredLoadTask.getImportDeferName(
+ _elementMap.getSpannable(targetElement, loadLibrary),
+ _elementMap.getImport(loadLibrary.import));
// TODO(efortuna): Source information!
- push(new HInvokeStatic(
- commonElements.loadDeferredLibrary,
- [graph.addConstantString(loadLibrary.import.name, closedWorld)],
- commonMasks.nonNullType,
+ push(new HInvokeStatic(commonElements.loadDeferredLibrary,
+ [graph.addConstantString(loadId, closedWorld)], commonMasks.nonNullType,
targetCanThrow: false));
}
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 2b98deb..bac6584 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -959,8 +959,8 @@
}
/// An instruction is an 'allocation' is it is the sole alias for an object.
- /// This applies to to instructions that allocate new objects and can be
- /// extended to methods that return other allocations without escaping them.
+ /// This applies to instructions that allocate new objects and can be extended
+ /// to methods that return other allocations without escaping them.
bool get isAllocation => false;
/// Overridden by [HCheck] to return the actual non-[HCheck]
@@ -1658,11 +1658,7 @@
}
abstract class HInvoke extends HInstruction {
- /**
- * The first argument must be the target: either an [HStatic] node, or
- * the receiver of a method-call. The remaining inputs are the arguments
- * to the invocation.
- */
+ bool isAllocation = false;
HInvoke(List<HInstruction> inputs, type) : super(inputs, type) {
sideEffects.setAllSideEffects();
sideEffects.setDependsOnSomething();
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 9c972af..f27483a 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -421,10 +421,7 @@
}
} else if (input.isStringOrNull(_closedWorld)) {
if (applies(commonElements.jsStringSplit)) {
- HInstruction argument = node.inputs[2];
- if (argument.isString(_closedWorld)) {
- target = commonElements.jsStringSplit;
- }
+ return handleStringSplit(node);
} else if (applies(commonElements.jsStringOperatorAdd)) {
// `operator+` is turned into a JavaScript '+' so we need to
// make sure the receiver and the argument are not null.
@@ -466,6 +463,63 @@
return node;
}
+ HInstruction handleStringSplit(HInvokeDynamic node) {
+ HInstruction argument = node.inputs[2];
+ if (!argument.isString(_closedWorld)) return node;
+
+ // Replace `s.split$1(pattern)` with
+ //
+ // t1 = s.split(pattern);
+ // t2 = String;
+ // t3 = JSArray<t2>;
+ // t4 = setRuntimeTypeInfo(t1, t3);
+ //
+
+ TypeMask resultMask = _closedWorld.commonMasks.growableListType;
+
+ HInvokeDynamicMethod splitInstruction = new HInvokeDynamicMethod(
+ node.selector,
+ node.mask,
+ node.inputs.sublist(1),
+ resultMask,
+ node.sourceInformation)
+ ..element = commonElements.jsStringSplit
+ ..isAllocation = true;
+
+ if (!_closedWorld.rtiNeed
+ .classNeedsTypeArguments(commonElements.jsArrayClass)) {
+ return splitInstruction;
+ }
+
+ node.block.addBefore(node, splitInstruction);
+
+ HInstruction stringTypeInfo = new HTypeInfoExpression(
+ TypeInfoExpressionKind.COMPLETE,
+ _closedWorld.elementEnvironment.getThisType(commonElements.stringClass),
+ <HInstruction>[],
+ _closedWorld.commonMasks.dynamicType);
+ node.block.addBefore(node, stringTypeInfo);
+
+ HInstruction typeInfo = new HTypeInfoExpression(
+ TypeInfoExpressionKind.INSTANCE,
+ _closedWorld.elementEnvironment
+ .getThisType(commonElements.jsArrayClass),
+ <HInstruction>[stringTypeInfo],
+ _closedWorld.commonMasks.dynamicType);
+ node.block.addBefore(node, typeInfo);
+
+ HInvokeStatic tagInstruction = new HInvokeStatic(
+ commonElements.setRuntimeTypeInfo,
+ <HInstruction>[splitInstruction, typeInfo],
+ resultMask);
+ // 'Linear typing' trick: [tagInstruction] is the only use of the
+ // [splitInstruction], so it becomes the sole alias.
+ // TODO(sra): Build this knowledge into alias analysis.
+ tagInstruction.isAllocation = true;
+
+ return tagInstruction;
+ }
+
HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
propagateConstantValueToUses(node);
if (node.isInterceptedCall) {
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index d08f1e3..d8cf050 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -6070,15 +6070,16 @@
return type;
}
}
- if (type.isDynamic) {
- return type;
- } else if (type is InterfaceType && type.element == expectedType.element) {
+ if (type.isDynamic) return type;
+ if (type is InterfaceType &&
+ (type.element == expectedType.element ||
+ expectedType == types.futureType &&
+ type.element == types.futureOrType.element)) {
return type.typeArguments[0];
- } else {
- // TODO(leafp): The above only handles the case where the return type
- // is exactly Future/Stream/Iterable. Handle the subtype case.
- return DynamicTypeImpl.instance;
}
+ // TODO(leafp): The above only handles the case where the return type
+ // is exactly Future/Stream/Iterable. Handle the subtype case.
+ return DynamicTypeImpl.instance;
}
JS.Expression _callHelper(String code, [args]) {
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 2c07cf0..e35b71a 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -19,7 +19,6 @@
import '../compiler/module_builder.dart';
import '../js_ast/js_ast.dart' as JS;
import 'compiler.dart';
-import 'native_types.dart';
import 'source_map_printer.dart';
const _binaryName = 'dartdevk';
@@ -121,7 +120,12 @@
allowMultiple: true)
..addFlag('source-map', help: 'emit source mapping', defaultsTo: true)
..addOption('summary-input-dir', allowMultiple: true)
- ..addOption('custom-app-scheme', defaultsTo: 'org-dartlang-app');
+ ..addOption('custom-app-scheme', defaultsTo: 'org-dartlang-app')
+ // Ignore dart2js options that we don't support in DDC.
+ ..addFlag('enable-enum', hide: true)
+ ..addFlag('experimental-trust-js-interop-type-annotations', hide: true)
+ ..addFlag('trust-type-annotations', hide: true)
+ ..addFlag('supermixin', hide: true);
addModuleFormatOptions(argParser, singleOutFile: false);
@@ -216,8 +220,7 @@
JS.Program compileToJSModule(Program p, List<Program> summaries,
List<Uri> summaryUris, Map<String, String> declaredVariables) {
- var compiler = new ProgramCompiler(new NativeTypeSet(p),
- declaredVariables: declaredVariables);
+ var compiler = new ProgramCompiler(p, declaredVariables: declaredVariables);
return compiler.emitProgram(p, summaries, summaryUris);
}
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index f1f7661..6b7f851 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -115,7 +115,7 @@
/// unit.
final virtualFields = new VirtualFieldModel();
- JSTypeRep _typeRep;
+ final JSTypeRep _typeRep;
bool _superAllowed = true;
@@ -188,17 +188,28 @@
final ConstantVisitor _constants;
- NullableInference _nullableInference;
+ final NullableInference _nullableInference;
- ProgramCompiler(NativeTypeSet nativeTypes,
- {this.emitMetadata: true,
- this.replCompile: false,
- this.declaredVariables: const {}})
+ factory ProgramCompiler(Program program,
+ {bool emitMetadata: true,
+ bool replCompile: false,
+ Map<String, String> declaredVariables: const {}}) {
+ var nativeTypes = new NativeTypeSet(program);
+ var types = new TypeSchemaEnvironment(
+ nativeTypes.coreTypes, new ClassHierarchy(program), true);
+ return new ProgramCompiler._(
+ nativeTypes, new JSTypeRep(types, nativeTypes.sdk),
+ emitMetadata: emitMetadata,
+ replCompile: replCompile,
+ declaredVariables: declaredVariables);
+ }
+
+ ProgramCompiler._(NativeTypeSet nativeTypes, this._typeRep,
+ {this.emitMetadata, this.replCompile, this.declaredVariables})
: _extensionTypes = nativeTypes,
+ types = _typeRep.types,
coreTypes = nativeTypes.coreTypes,
_constants = new ConstantVisitor(nativeTypes.coreTypes),
- types = new TypeSchemaEnvironment(nativeTypes.coreTypes,
- new ClassHierarchy.deprecated_incremental(), true),
_jsArrayClass =
nativeTypes.sdk.getClass('dart:_interceptors', 'JSArray'),
_asyncStreamIteratorClass =
@@ -214,10 +225,8 @@
identityHashSetImplClass =
nativeTypes.sdk.getClass('dart:collection', '_IdentityHashSet'),
syncIterableClass =
- nativeTypes.sdk.getClass('dart:_js_helper', 'SyncIterable') {
- _typeRep = new JSTypeRep(types, nativeTypes.sdk);
- _nullableInference = new NullableInference(_typeRep);
- }
+ nativeTypes.sdk.getClass('dart:_js_helper', 'SyncIterable'),
+ _nullableInference = new NullableInference(_typeRep);
ClassHierarchy get hierarchy => types.hierarchy;
@@ -771,12 +780,6 @@
body.add(_addConstructorToClass(className, name, jsCtor));
}
- if (c.isEnum) {
- assert(!isCallable, 'enums should not be callable');
- addConstructor('', js.call('function(x) { this.index = x; }'));
- return body;
- }
-
var fields = c.fields;
for (var ctor in c.constructors) {
if (ctor.isExternal) continue;
@@ -1027,9 +1030,24 @@
/// Emits static fields for a class, and initialize them eagerly if possible,
/// otherwise define them as lazy properties.
void _emitStaticFields(Class c, List<JS.Statement> body) {
- var lazyStatics = c.fields.where((f) => f.isStatic).toList();
- if (lazyStatics.isNotEmpty) {
- body.add(_emitLazyFields(c, lazyStatics));
+ var fields = c.fields.where((f) => f.isStatic).toList();
+ if (c.isEnum) {
+ // We know enum fields can be safely emitted as const fields, as long
+ // as the `values` field is emitted last.
+ var classRef = _emitTopLevelName(c);
+ var valueField = fields.firstWhere((f) => f.name.name == 'values');
+ fields.remove(valueField);
+ fields.add(valueField);
+ for (var f in fields) {
+ assert(f.isConst);
+ body.add(_defineValueOnClass(
+ classRef,
+ _emitStaticMemberName(f.name.name),
+ _visitInitializer(f.initializer, f.annotations))
+ .toStatement());
+ }
+ } else if (fields.isNotEmpty) {
+ body.add(_emitLazyFields(c, fields));
}
}
@@ -1037,11 +1055,13 @@
List<JS.Statement> body) {
// Metadata
if (emitMetadata && metadata.isNotEmpty) {
- body.add(js.statement('#[#.metadata] = () => #;', [
+ body.add(js.statement('#[#.metadata] = #;', [
className,
_runtimeModule,
- new JS.ArrayInitializer(
- new List<JS.Expression>.from(metadata.map(_instantiateAnnotation)))
+ new JS.ArrowFun(
+ [],
+ _withLetScopeArrowFunction(() => new JS.ArrayInitializer(
+ new List.from(metadata.map(_instantiateAnnotation)))))
]));
}
}
@@ -1273,20 +1293,11 @@
() => _superDisallowed(
() => _emitConstructorBody(node, fields, className)));
- return _finishConstructorFunction(params, body, isCallable);
+ var block = new JS.Block(body)..sourceInformation = node;
+ return _finishConstructorFunction(params, block, isCallable);
}
- void addStatementToList(JS.Statement statement, List<JS.Statement> list) {
- // If the statement is a nested block, flatten it into the list when
- // possible. If the statement is empty, discard it.
- if (statement is JS.Block && (list.isEmpty || !statement.isScope)) {
- list.addAll(statement.statements);
- } else if (statement is! JS.EmptyStatement) {
- list.add(statement);
- }
- }
-
- JS.Block _emitConstructorBody(
+ List<JS.Statement> _emitConstructorBody(
Constructor node, List<Field> fields, JS.Expression className) {
var cls = node.enclosingClass;
@@ -1305,15 +1316,14 @@
if (redirectCall != null) {
body.add(_emitRedirectingConstructor(redirectCall, className));
- _initTempVars(body);
- return new JS.Block(body);
+ return body;
}
// Generate field initializers.
// These are expanded into each non-redirecting constructor.
// In the future we may want to create an initializer function if we have
// multiple constructors, but it needs to be balanced against readability.
- addStatementToList(_initializeFields(fields, node), body);
+ _addStatementToList(_initializeFields(fields, node), body);
var superCall = node.initializers.firstWhere((i) => i is SuperInitializer,
orElse: () => null) as SuperInitializer;
@@ -1323,13 +1333,12 @@
// enclosing class is class Object.
var jsSuper = _emitSuperConstructorCallIfNeeded(cls, className, superCall);
if (jsSuper != null) {
- addStatementToList(jsSuper..sourceInformation = superCall, body);
+ _addStatementToList(jsSuper..sourceInformation = superCall, body);
}
var jsBody = _visitStatement(node.function.body);
- if (jsBody != null) addStatementToList(jsBody, body);
- _initTempVars(body);
- return new JS.Block(body)..sourceInformation = node;
+ if (jsBody != null) _addStatementToList(jsBody, body);
+ return body;
}
JS.Expression _constructorName(String name) {
@@ -1390,7 +1399,7 @@
bool _hasUnnamedConstructor(Class c) {
if (c == null || c == coreTypes.objectClass) return false;
var ctor = unnamedConstructor(c);
- if (ctor != null && !ctor.isSyntheticDefault) return true;
+ if (ctor != null && !ctor.isSynthetic) return true;
if (c.fields.any((f) => !f.isStatic)) return true;
return _hasUnnamedSuperConstructor(c);
}
@@ -1501,16 +1510,20 @@
JS.Statement _addConstructorToClass(
JS.Expression className, String name, JS.Expression jsCtor) {
- var ctorName = _constructorName(name);
- if (JS.invalidStaticFieldName(name)) {
- jsCtor =
- _callHelper('defineValue(#, #, #)', [className, ctorName, jsCtor]);
- } else {
- jsCtor = js.call('#.# = #', [className, ctorName, jsCtor]);
- }
+ jsCtor = _defineValueOnClass(className, _constructorName(name), jsCtor);
return js.statement('#.prototype = #.prototype;', [jsCtor, className]);
}
+ JS.Expression _defineValueOnClass(
+ JS.Expression className, JS.Expression name, JS.Expression value) {
+ var args = [className, name, value];
+ if (name is JS.LiteralString &&
+ JS.invalidStaticFieldName(name.valueWithoutQuotes)) {
+ return _callHelper('defineValue(#, #, #)', args);
+ }
+ return js.call('#.# = #', args);
+ }
+
List<JS.Method> _emitClassMethods(Class c) {
var virtualFields = _classProperties.virtualFields;
@@ -2069,17 +2082,35 @@
}
JS.Fun _emitStaticFieldInitializer(Field field) {
+ return new JS.Fun(
+ [],
+ new JS.Block(_withLetScope(() => [
+ new JS.Return(
+ _visitInitializer(field.initializer, field.annotations))
+ ])));
+ }
+
+ List<JS.Statement> _withLetScope(List<JS.Statement> visitBody()) {
var savedLetVariables = _letVariables;
_letVariables = [];
- var body = [
- new JS.Return(_visitInitializer(field.initializer, field.annotations))
- ];
- _initTempVars(body);
+ var body = visitBody();
+ var letVars = _initLetVariables();
+ if (letVars != null) body.insert(0, letVars);
_letVariables = savedLetVariables;
+ return body;
+ }
- return new JS.Fun([], new JS.Block(body));
+ JS.Node _withLetScopeArrowFunction(JS.Expression visitBody()) {
+ var savedLetVariables = _letVariables;
+ _letVariables = [];
+
+ var expr = visitBody();
+ var letVars = _initLetVariables();
+
+ _letVariables = savedLetVariables;
+ return letVars == null ? expr : new JS.Block([letVars, expr.toReturn()]);
}
JS.PropertyAccess _emitTopLevelName(NamedNode n, {String suffix: ''}) {
@@ -2336,21 +2367,22 @@
}
void _emitLibraryProcedures(Library library) {
- var procedures =
- library.procedures.where((p) => !p.isExternal && !p.isAbstract);
+ var procedures = library.procedures
+ .where((p) => !p.isExternal && !p.isAbstract)
+ .toList();
_moduleItems.addAll(procedures
.where((p) => !p.isAccessor)
.map(_emitLibraryFunction)
.toList());
- _moduleItems
- .add(_emitLibraryAccessors(procedures.where((p) => p.isAccessor)));
+ _emitLibraryAccessors(procedures.where((p) => p.isAccessor).toList());
}
- JS.Statement _emitLibraryAccessors(Iterable<Procedure> accessors) {
- return _callHelperStatement('copyProperties(#, { # });', [
+ void _emitLibraryAccessors(Iterable<Procedure> accessors) {
+ if (accessors.isEmpty) return;
+ _moduleItems.add(_callHelperStatement('copyProperties(#, { # });', [
emitLibraryName(_currentLibrary),
accessors.map(_emitLibraryAccessor).toList()
- ]);
+ ]));
}
JS.Method _emitLibraryAccessor(Procedure node) {
@@ -2675,7 +2707,7 @@
List<JS.Parameter> _emitTypeFormals(List<TypeParameter> typeFormals) {
return typeFormals
.map((t) => new JS.Identifier(getTypeParameterName(t)))
- .toList(growable: false);
+ .toList();
}
JS.Expression _emitGeneratorFunction(FunctionNode function, String name) {
@@ -2768,30 +2800,30 @@
//
// In the body of an `async`, `await` is generated simply as `yield`.
var gen = emitGeneratorFn((_) => []);
- var returnType = _getExpectedReturnType(function, coreTypes.futureClass);
+ // Return type of an async body is `Future<flatten(T)>`, where T is the
+ // declared return type.
+ var returnType = types.unfutureType(function.functionType.returnType);
return js.call('#.async(#, #)',
[emitLibraryName(coreTypes.asyncLibrary), _emitType(returnType), gen])
..sourceInformation = function;
}
- // TODO(leafp): Various analyzer pieces computed similar things.
- // Share this logic somewhere?
+ /// Gets the expected return type of a `sync*` or `async*` body.
DartType _getExpectedReturnType(FunctionNode f, Class expected) {
var type = f.functionType.returnType;
if (type is InterfaceType) {
var match = hierarchy.getTypeAsInstanceOf(type, expected);
- return match.typeArguments[0];
+ if (match != null) return match.typeArguments[0];
}
return const DynamicType();
}
JS.Block _emitFunctionBody(FunctionNode f) {
- List<JS.Statement> block;
- _withCurrentFunction(f, () {
- block = _emitArgumentInitializers(f);
+ var block = _withCurrentFunction(f, () {
+ var block = _emitArgumentInitializers(f);
var jsBody = _visitStatement(f.body);
- if (jsBody != null) addStatementToList(jsBody, block);
- _initTempVars(block);
+ if (jsBody != null) _addStatementToList(jsBody, block);
+ return block;
});
if (f.asyncMarker == AsyncMarker.Sync) {
@@ -2812,18 +2844,16 @@
return new JS.Block(block);
}
- T _withCurrentFunction<T>(FunctionNode fn, T action()) {
+ List<JS.Statement> _withCurrentFunction(
+ FunctionNode fn, List<JS.Statement> action()) {
var savedFunction = _currentFunction;
_currentFunction = fn;
- var savedLetVariables = _letVariables;
- _letVariables = [];
_nullableInference.enterFunction(fn);
- var result = action();
+ var result = _withLetScope(action);
_nullableInference.exitFunction(fn);
_currentFunction = savedFunction;
- _letVariables = savedLetVariables;
return result;
}
@@ -3530,17 +3560,16 @@
return new JS.Identifier(name);
}
- void _initTempVars(List<JS.Statement> block) {
- if (_letVariables.isEmpty) return;
- block.insert(
- 0,
- new JS.VariableDeclarationList(
- 'let',
- _letVariables
- .map((v) => new JS.VariableInitialization(v, null))
- .toList())
- .toStatement());
+ JS.Statement _initLetVariables() {
+ if (_letVariables.isEmpty) return null;
+ var result = new JS.VariableDeclarationList(
+ 'let',
+ _letVariables
+ .map((v) => new JS.VariableInitialization(v, null))
+ .toList())
+ .toStatement();
_letVariables.clear();
+ return result;
}
// TODO(jmesserly): resugar operators for kernel, such as ++x, x++, x+=.
@@ -3629,7 +3658,7 @@
@override
visitSuperPropertySet(SuperPropertySet node) {
var target = node.interfaceTarget;
- var jsTarget = _emitSuperTarget(target);
+ var jsTarget = _emitSuperTarget(target, setter: true);
return _visitExpression(node.value).toAssignExpression(jsTarget);
}
@@ -4067,8 +4096,8 @@
var isAccessor = member is Procedure ? member.isAccessor : true;
if (isAccessor) {
assert(member is Procedure
- ? setter == member.isSetter
- : (member as Field).isFinal != setter);
+ ? member.isSetter == setter
+ : !setter || !(member as Field).isFinal);
var fn = js.call(
setter
? 'function(x) { super[#] = x; }'
@@ -4316,9 +4345,6 @@
visitConstructorInvocation(ConstructorInvocation node) {
var ctor = node.target;
var args = node.arguments;
- var ctorClass = ctor.enclosingClass;
- if (_isObjectLiteral(ctorClass)) return _emitObjectLiteral(args);
-
JS.Expression emitNew() {
return new JS.New(_emitConstructorName(node.constructedType, ctor),
_emitArgumentList(args, types: false));
@@ -4331,6 +4357,10 @@
var args = node.arguments;
var ctor = node.target;
var ctorClass = ctor.enclosingClass;
+ if (ctor.isExternal && _isJSNative(ctorClass)) {
+ return _emitJSInteropNew(ctor, args);
+ }
+
var type = ctorClass.typeParameters.isEmpty
? ctorClass.rawType
: new InterfaceType(ctorClass, args.types);
@@ -4395,7 +4425,6 @@
}
JS.Expression emitNew() {
- // Native factory constructors are JS constructors - use new here.
return new JS.Call(_emitConstructorName(type, ctor),
_emitArgumentList(args, types: false));
}
@@ -4403,6 +4432,13 @@
return node.isConst ? _emitConst(emitNew) : emitNew();
}
+ JS.Expression _emitJSInteropNew(Member ctor, Arguments args) {
+ var ctorClass = ctor.enclosingClass;
+ if (_isObjectLiteral(ctorClass)) return _emitObjectLiteral(args);
+ return new JS.New(_emitConstructorName(ctorClass.rawType, ctor),
+ _emitArgumentList(args, types: false));
+ }
+
JS.Expression _emitMapImplType(InterfaceType type, {bool identity}) {
var typeArgs = type.typeArguments;
if (typeArgs.isEmpty) return _emitType(type);
@@ -4420,11 +4456,10 @@
}
bool _isObjectLiteral(Class c) {
- return _isJSNative(c) && findAnnotation(c, isJSAnonymousAnnotation) != null;
+ return _isJSNative(c) && c.annotations.any(isJSAnonymousAnnotation);
}
- bool _isJSNative(NamedNode c) =>
- findAnnotation(c, isPublicJSAnnotation) != null;
+ bool _isJSNative(Class c) => c.annotations.any(isPublicJSAnnotation);
JS.Expression _emitObjectLiteral(Arguments node) {
var args = _emitArgumentList(node);
@@ -4737,8 +4772,17 @@
var body = _visitExpression(node.body);
var temp = _tempVariables.remove(v);
if (temp != null) {
- init = new JS.Assignment(temp, init);
- _letVariables.add(temp);
+ if (_letVariables != null) {
+ init = new JS.Assignment(temp, init);
+ _letVariables.add(temp);
+ } else {
+ // TODO(jmesserly): make sure this doesn't happen on any performance
+ // critical call path.
+ //
+ // Annotations on a top-level, non-lazy function type should be the only
+ // remaining use.
+ return new JS.Call(new JS.ArrowFun([temp], body), [init]);
+ }
}
return new JS.Binary(',', init, body);
}
@@ -4893,3 +4937,13 @@
bool _isObjectMethod(String name) =>
name == 'toString' || name == 'noSuchMethod';
+
+void _addStatementToList(JS.Statement statement, List<JS.Statement> list) {
+ // If the statement is a nested block, flatten it into the list when
+ // possible. If the statement is empty, discard it.
+ if (statement is JS.Block && (list.isEmpty || !statement.isScope)) {
+ list.addAll(statement.statements);
+ } else if (statement is! JS.EmptyStatement) {
+ list.add(statement);
+ }
+}
diff --git a/pkg/dev_compiler/lib/src/kernel/js_interop.dart b/pkg/dev_compiler/lib/src/kernel/js_interop.dart
index 7147be1..419823b 100644
--- a/pkg/dev_compiler/lib/src/kernel/js_interop.dart
+++ b/pkg/dev_compiler/lib/src/kernel/js_interop.dart
@@ -10,19 +10,23 @@
bool _isJSLibrary(Library library) {
if (library == null) return false;
var uri = library.importUri;
- if (uri.scheme == 'package' && uri.path.startsWith('js/')) return true;
- if (uri.scheme == 'dart') {
- return uri.path == '_js_helper' || uri.path == '_foreign_helper';
- }
- return false;
+ var scheme = uri.scheme;
+ return scheme == 'package' && uri.pathSegments[0] == 'js' ||
+ scheme == 'dart' &&
+ (uri.path == '_js_helper' || uri.path == '_foreign_helper');
}
bool _annotationIsFromJSLibrary(String expectedName, Expression value) {
+ Class c;
if (value is ConstructorInvocation) {
- var c = value.target.enclosingClass;
- return c.name == expectedName && _isJSLibrary(getLibrary(c));
+ c = value.target.enclosingClass;
+ } else if (value is StaticGet) {
+ var type = value.target.getterType;
+ if (type is InterfaceType) c = type.classNode;
}
- return false;
+ return c != null &&
+ c.name == expectedName &&
+ _isJSLibrary(c.enclosingLibrary);
}
/// Whether [value] is a `@rest` annotation (to be used on function parameters
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index 7fc8071..434170f 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -17,13 +17,12 @@
return n;
}
-final Pattern genericTypeEncodingCharacters = new RegExp('[&^#]');
+final Pattern _syntheticTypeCharacters = new RegExp('[&^#.]');
-// TODO(karlklose): add a namer for all identifiers?
String _escapeIdentifier(String identifier) {
// Remove the special characters used to encode mixin application class names
// which are legal in Kernel, but not in JavaScript.
- return identifier?.replaceAll(genericTypeEncodingCharacters, r'$');
+ return identifier?.replaceAll(_syntheticTypeCharacters, r'$');
}
/// Returns the escaped name for class [node].
@@ -109,7 +108,7 @@
String getAnnotationName(NamedNode node, bool test(Expression value)) {
var match = findAnnotation(node, test);
if (match is ConstructorInvocation && match.arguments.positional.isNotEmpty) {
- var first = match.arguments.positional[0];
+ var first = _followConstFields(match.arguments.positional[0]);
if (first is StringLiteral) {
return first.value;
}
@@ -117,6 +116,16 @@
return null;
}
+Expression _followConstFields(Expression expr) {
+ if (expr is StaticGet) {
+ var target = expr.target;
+ if (target is Field) {
+ return _followConstFields(target.initializer);
+ }
+ }
+ return expr;
+}
+
/// Finds constant expressions as defined in Dart language spec 4th ed,
/// 16.1 Constants
class ConstantVisitor extends ExpressionVisitor<bool> {
diff --git a/pkg/dev_compiler/lib/src/kernel/property_model.dart b/pkg/dev_compiler/lib/src/kernel/property_model.dart
index b589cc1..76e9761 100644
--- a/pkg/dev_compiler/lib/src/kernel/property_model.dart
+++ b/pkg/dev_compiler/lib/src/kernel/property_model.dart
@@ -141,6 +141,10 @@
if (field.isStatic) return false;
var class_ = field.enclosingClass;
+ if (class_.isEnum) {
+ // Enums are not extensible.
+ return false;
+ }
var libraryUri = class_.enclosingLibrary.importUri;
if (libraryUri.scheme == 'dart' && libraryUri.path.startsWith('_')) {
// There should be no extensible fields in private SDK libraries.
diff --git a/pkg/dev_compiler/tool/input_sdk/lib/libraries.json b/pkg/dev_compiler/tool/input_sdk/lib/libraries.json
index 1a51699..4c3c787 100644
--- a/pkg/dev_compiler/tool/input_sdk/lib/libraries.json
+++ b/pkg/dev_compiler/tool/input_sdk/lib/libraries.json
@@ -110,4 +110,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/libraries.dart b/pkg/dev_compiler/tool/input_sdk/libraries.dart
index aa4aede..cd7a447 100644
--- a/pkg/dev_compiler/tool/input_sdk/libraries.dart
+++ b/pkg/dev_compiler/tool/input_sdk/libraries.dart
@@ -115,6 +115,9 @@
implementation: true,
documented: false,
platforms: DART2JS_PLATFORM),
+ "cli": const LibraryInfo("cli/cli.dart",
+ categories: "Server",
+ dart2jsPatchPath: "_internal/js_runtime/lib/cli_patch.dart"),
"svg": const LibraryInfo("svg/dart2js/svg_dart2js.dart",
categories: "Client",
maturity: Maturity.WEB_STABLE,
diff --git a/pkg/dev_compiler/tool/input_sdk/libraries.json b/pkg/dev_compiler/tool/input_sdk/libraries.json
index a30411c..96f5163 100644
--- a/pkg/dev_compiler/tool/input_sdk/libraries.json
+++ b/pkg/dev_compiler/tool/input_sdk/libraries.json
@@ -99,4 +99,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/cli_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/cli_patch.dart
new file mode 100644
index 0000000..6921e60
--- /dev/null
+++ b/pkg/dev_compiler/tool/input_sdk/patch/cli_patch.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:_js_helper' show patch;
+
+@patch
+void _waitForEvent(int timeoutMillis) {
+ throw new UnsupportedError("waitForEvent");
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
index 9fe761c..4531ea6 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
@@ -691,3 +691,13 @@
@patch
_throw(error) => throw error;
}
+
+// TODO(jmesserly): this class is supposed to be obsolete in Strong Mode, but
+// the front-end crashes without it
+class _DuplicatedFieldInitializerError {
+ final String _name;
+
+ _DuplicatedFieldInitializerError(this._name);
+
+ toString() => "Error: field '$_name' is already initialized.";
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_string.dart b/pkg/dev_compiler/tool/input_sdk/private/js_string.dart
index b613734..65b77a8 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/js_string.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/js_string.dart
@@ -182,13 +182,12 @@
return JS('String', r'#.toUpperCase()', this);
}
- // Characters with Whitespace property (Unicode 6.2).
+ // Characters with Whitespace property (Unicode 6.3).
// 0009..000D ; White_Space # Cc <control-0009>..<control-000D>
// 0020 ; White_Space # Zs SPACE
// 0085 ; White_Space # Cc <control-0085>
// 00A0 ; White_Space # Zs NO-BREAK SPACE
// 1680 ; White_Space # Zs OGHAM SPACE MARK
- // 180E ; White_Space # Zs MONGOLIAN VOWEL SEPARATOR
// 2000..200A ; White_Space # Zs EN QUAD..HAIR SPACE
// 2028 ; White_Space # Zl LINE SEPARATOR
// 2029 ; White_Space # Zp PARAGRAPH SEPARATOR
@@ -218,7 +217,6 @@
}
switch (codeUnit) {
case 0x1680:
- case 0x180E:
case 0x2000:
case 0x2001:
case 0x2002:
diff --git a/pkg/front_end/lib/src/external_state_snapshot.dart b/pkg/front_end/lib/src/external_state_snapshot.dart
index c77c4486..cdb31e9 100644
--- a/pkg/front_end/lib/src/external_state_snapshot.dart
+++ b/pkg/front_end/lib/src/external_state_snapshot.dart
@@ -4,15 +4,15 @@
// TODO(ahe): Remove this file.
-import 'package:kernel/kernel.dart' show Library, LibraryDependency, Program;
+import 'package:kernel/kernel.dart' show Library, Program;
/// Helper class to work around modifications in [kernel_generator_impl.dart].
class ExternalStateSnapshot {
final List<ExternalState> snapshots;
ExternalStateSnapshot(Program program)
- : snapshots = new List<ExternalState>.from(program.libraries.map((l) =>
- new ExternalState(l, l.dependencies.toList(), l.isExternal)));
+ : snapshots = new List<ExternalState>.from(
+ program.libraries.map((l) => new ExternalState(l, l.isExternal)));
void restore() {
for (ExternalState state in snapshots) {
@@ -23,15 +23,11 @@
class ExternalState {
final Library library;
- final List<LibraryDependency> dependencies;
final bool isExternal;
- ExternalState(this.library, this.dependencies, this.isExternal);
+ ExternalState(this.library, this.isExternal);
void restore() {
library.isExternal = isExternal;
- library.dependencies
- ..clear()
- ..addAll(dependencies);
}
}
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 4eaf799..c90fb50 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -96,6 +96,38 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, DartType _type, DartType _type2)>
+ templateAmbiguousSupertypes = const Template<
+ Message Function(String name, DartType _type, DartType _type2)>(
+ messageTemplate:
+ r"""'#name' can't implement both '#type' and '#type2'""",
+ withArguments: _withArgumentsAmbiguousSupertypes);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, DartType _type, DartType _type2)>
+ codeAmbiguousSupertypes =
+ const Code<Message Function(String name, DartType _type, DartType _type2)>(
+ "AmbiguousSupertypes", templateAmbiguousSupertypes,
+ severity: Severity.error);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsAmbiguousSupertypes(
+ String name, DartType _type, DartType _type2) {
+ NameSystem nameSystem = new NameSystem();
+ StringBuffer buffer = new StringBuffer();
+ new Printer(buffer, syntheticNames: nameSystem).writeNode(_type);
+ String type = '$buffer';
+
+ buffer = new StringBuffer();
+ new Printer(buffer, syntheticNames: nameSystem).writeNode(_type2);
+ String type2 = '$buffer';
+
+ return new Message(codeAmbiguousSupertypes,
+ message: """'$name' can't implement both '$type' and '$type2'""",
+ arguments: {'name': name, 'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeAnnotationOnEnumConstant = messageAnnotationOnEnumConstant;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1935,6 +1967,19 @@
message: r"""Can't have a default value in a function type.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFunctionTypedParameterVar =
+ messageFunctionTypedParameterVar;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFunctionTypedParameterVar = const MessageCode(
+ "FunctionTypedParameterVar",
+ analyzerCode: "FUNCTION_TYPED_PARAMETER_VAR",
+ dart2jsCode: "*fatal*",
+ message:
+ r"""Function-typed parameters can't specify 'const', 'final' or 'var' in place of a return type.""",
+ tip: r"""Try replacing the keyword with a return type.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeGeneratorReturnsValue = messageGeneratorReturnsValue;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index b2c9042..f9556b0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -1292,8 +1292,12 @@
return new ThisPropertyAccessor(this, token, n, getter, setter);
} else if (builder.isRegularMethod) {
assert(builder.isStatic || builder.isTopLevel);
- return new StaticAccessor(this, token, builder.target, null,
+ StaticAccessor accessor = new StaticAccessor(
+ this, token, builder.target, null,
prefixName: prefix?.name);
+ return (prefix?.deferred == true)
+ ? new DeferredAccessor(this, token, prefix, accessor)
+ : accessor;
} else if (builder is PrefixBuilder) {
if (constantExpressionRequired && builder.deferred) {
deprecated_addCompileTimeError(
@@ -1329,7 +1333,9 @@
charOffset, "Not a constant expression.");
}
}
- return accessor;
+ return (prefix?.deferred == true)
+ ? new DeferredAccessor(this, token, prefix, accessor)
+ : accessor;
}
}
@@ -3632,6 +3638,14 @@
prefixName, targetOffset, targetClass, readTarget)
..fileOffset = offsetForToken(token);
}
+
+ @override
+ Expression makeDeferredCheck(Expression expression, PrefixBuilder prefix) {
+ return new Let(
+ new VariableDeclaration.forValue(
+ new CheckLibraryIsLoaded(prefix.dependency)),
+ expression);
+ }
}
class Identifier {
diff --git a/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart b/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart
index 5f39fe4..a5800d5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart
@@ -32,6 +32,7 @@
LoadLibraryAccessor,
PropertyAccessor,
ReadOnlyAccessor,
+ DeferredAccessor,
DelayedErrorAccessor,
StaticAccessor,
SuperIndexAccessor,
@@ -138,6 +139,8 @@
StaticGet makeStaticGet(Member readTarget, Token token,
{String prefixName, int targetOffset: -1, Class targetClass});
+ Expression makeDeferredCheck(Expression expression, PrefixBuilder prefix);
+
dynamic deprecated_addCompileTimeError(int charOffset, String message);
bool isIdentical(Member member);
@@ -825,6 +828,24 @@
}
}
+class DeferredAccessor extends kernel.DeferredAccessor with FastaAccessor {
+ DeferredAccessor(BuilderHelper helper, Token token, PrefixBuilder builder,
+ StaticAccessor expression)
+ : super(helper, token, builder, expression);
+
+ String get plainNameForRead {
+ return unsupported(
+ "deferredAccessor.plainNameForRead", offsetForToken(token), uri);
+ }
+
+ StaticAccessor get staticAccessor => super.staticAccessor;
+
+ Expression doInvocation(int offset, Arguments arguments) {
+ return helper.makeDeferredCheck(
+ staticAccessor.doInvocation(offset, arguments), builder);
+ }
+}
+
class SuperPropertyAccessor extends kernel.SuperPropertyAccessor
with FastaAccessor {
SuperPropertyAccessor(BuilderHelper helper, Token token, Name name,
diff --git a/pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart b/pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart
index d2920fa..c0afd0a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart
@@ -15,7 +15,7 @@
import 'fasta_accessors.dart' show BuilderHelper;
-import 'kernel_builder.dart' show LoadLibraryBuilder;
+import 'kernel_builder.dart' show LoadLibraryBuilder, PrefixBuilder;
import 'kernel_shadow_ast.dart'
show
@@ -736,6 +736,27 @@
}
}
+abstract class DeferredAccessor extends Accessor {
+ final PrefixBuilder builder;
+ final StaticAccessor staticAccessor;
+
+ DeferredAccessor(
+ BuilderHelper helper, Token token, this.builder, this.staticAccessor)
+ : super(helper, token);
+
+ Expression _makeRead(ShadowComplexAssignment complexAssignment) {
+ return helper.makeDeferredCheck(
+ staticAccessor._makeRead(complexAssignment), builder);
+ }
+
+ Expression _makeWrite(Expression value, bool voidContext,
+ ShadowComplexAssignment complexAssignment) {
+ return helper.makeDeferredCheck(
+ staticAccessor._makeWrite(value, voidContext, complexAssignment),
+ builder);
+ }
+}
+
class ReadOnlyAccessor extends Accessor {
Expression expression;
VariableDeclaration value;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
index 3c0a807..31fc317 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
@@ -114,8 +114,17 @@
}
actualBody = newBody;
if (function != null) {
- function.body = newBody;
- newBody?.parent = function;
+ // A forwarding semi-stub is a method that is abstract in the source code,
+ // but which needs to have a forwarding stub body in order to ensure that
+ // covariance checks occur. We don't want to replace the forwarding stub
+ // body with null.
+ var parent = function.parent;
+ if (!(newBody == null &&
+ parent is Procedure &&
+ parent.isForwardingSemiStub)) {
+ function.body = newBody;
+ newBody?.parent = function;
+ }
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 9ab59f7..d59f8de 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -374,17 +374,20 @@
loader.builders.forEach((Uri uri, LibraryBuilder library) {
if (library.loader == loader) {
library.forEach((String name, Builder builder) {
- if (builder is SourceClassBuilder) {
- Class cls = builder.target;
- if (cls != objectClass) {
- cls.supertype ??= objectClass.asRawSupertype;
- builder.supertype ??= new KernelNamedTypeBuilder("Object", null)
- ..bind(objectClassBuilder);
+ while (builder != null) {
+ if (builder is SourceClassBuilder) {
+ Class cls = builder.target;
+ if (cls != objectClass) {
+ cls.supertype ??= objectClass.asRawSupertype;
+ builder.supertype ??= new KernelNamedTypeBuilder("Object", null)
+ ..bind(objectClassBuilder);
+ }
+ if (builder.isMixinApplication) {
+ cls.mixedInType = builder.mixedInType.buildSupertype(
+ library, builder.charOffset, builder.fileUri);
+ }
}
- if (builder.isMixinApplication) {
- cls.mixedInType = builder.mixedInType
- .buildSupertype(library, builder.charOffset, builder.fileUri);
- }
+ builder = builder.next;
}
});
}
@@ -515,7 +518,7 @@
return new Constructor(
new FunctionNode(new EmptyStatement(), returnType: const VoidType()),
name: new Name(""),
- isSyntheticDefault: true);
+ isSynthetic: true);
}
void computeCoreTypes() {
diff --git a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
index 062b01d..cc9c060 100644
--- a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
@@ -74,6 +74,22 @@
return token;
}
+TypeContinuation typeContinuationAfterVar(TypeContinuation typeContinuation) {
+ switch (typeContinuation) {
+ case TypeContinuation.NormalFormalParameter:
+ return TypeContinuation.NormalFormalParameterAfterVar;
+
+ case TypeContinuation.OptionalPositionalFormalParameter:
+ return TypeContinuation.OptionalPositionalFormalParameterAfterVar;
+
+ case TypeContinuation.NamedFormalParameter:
+ return TypeContinuation.NamedFormalParameterAfterVar;
+
+ default:
+ return TypeContinuation.OptionalAfterVar;
+ }
+}
+
TypeContinuation typeContinuationFromMemberKind(
bool isVarAllowed, MemberKind memberKind) =>
(isVarAllowed || memberKind == MemberKind.GeneralizedFunctionType)
@@ -109,6 +125,7 @@
memberKind != MemberKind.NonStaticField;
Token parseOpt(Token token) {
+ assert(lastModifier != null);
if (token != lastModifier) {
if (optional('external', token.next)) {
token = parseExternalOpt(token);
@@ -173,6 +190,7 @@
return token;
}
switch (memberKind) {
+ case MemberKind.Local:
case MemberKind.StaticField:
case MemberKind.StaticMethod:
case MemberKind.TopLevelField:
@@ -268,24 +286,7 @@
next, fasta.templateExtraneousModifier);
return next;
}
- switch (typeContinuation ?? TypeContinuation.Required) {
- case TypeContinuation.NormalFormalParameter:
- typeContinuation = TypeContinuation.NormalFormalParameterAfterVar;
- break;
-
- case TypeContinuation.OptionalPositionalFormalParameter:
- typeContinuation =
- TypeContinuation.OptionalPositionalFormalParameterAfterVar;
- break;
-
- case TypeContinuation.NamedFormalParameter:
- typeContinuation = TypeContinuation.NamedFormalParameterAfterVar;
- break;
-
- default:
- typeContinuation = TypeContinuation.OptionalAfterVar;
- break;
- }
+ typeContinuation = typeContinuationAfterVar(typeContinuation);
varFinalOrConst ??= next;
modifierCount++;
return parser.parseModifier(token);
@@ -306,7 +307,7 @@
FormalParameterKind parameterKind,
bool isVarAllowed,
TypeContinuation typeContinuation,
- Token lastModifier)
+ [Token lastModifier])
: super(parser, memberKind, parameterKind, isVarAllowed, typeContinuation,
lastModifier);
@@ -344,6 +345,52 @@
return token;
}
+ Token parseRecovery(Token token,
+ {Token covariantToken, Token varFinalOrConst}) {
+ if (covariantToken != null) {
+ this.covariantToken = covariantToken;
+ ++modifierCount;
+ }
+ if (varFinalOrConst != null) {
+ ++modifierCount;
+ if (optional('var', varFinalOrConst)) {
+ varToken = varFinalOrConst;
+ } else if (optional('final', varFinalOrConst)) {
+ finalToken = varFinalOrConst;
+ } else if (optional('const', varFinalOrConst)) {
+ constToken = varFinalOrConst;
+ } else {
+ throw "Internal error: Unexpected varFinalOrConst '$varFinalOrConst'.";
+ }
+ }
+
+ // Process invalid and out-of-order modifiers
+ Token next = token.next;
+ while (isModifier(next)) {
+ final value = next.stringValue;
+ if (identical('abstract', value)) {
+ token = parseAbstract(token);
+ } else if (identical('const', value)) {
+ token = parseConst(token);
+ } else if (identical('covariant', value)) {
+ token = parseCovariantOpt(token);
+ } else if (identical('external', value)) {
+ token = parseExternalOpt(token);
+ } else if (identical('final', value)) {
+ token = parseFinal(token);
+ } else if (identical('static', value)) {
+ token = parseStaticOpt(token);
+ } else if (identical('var', value)) {
+ token = parseVar(token);
+ } else {
+ token = parseExtraneousModifier(token);
+ }
+ next = token.next;
+ }
+
+ return token;
+ }
+
Token parseAbstract(Token token) {
assert(optional('abstract', token.next));
if (memberKind == MemberKind.NonStaticField ||
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index fd654fe..8c558ac 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -79,11 +79,11 @@
ClassMethodModifierContext,
FactoryModifierContext,
ModifierContext,
+ ModifierRecoveryContext,
TopLevelMethodModifierContext,
isModifier,
parseModifiersOpt,
- skipToLastModifier,
- typeContinuationFromMemberKind;
+ typeContinuationAfterVar;
import 'recovery_listeners.dart'
show ClassHeaderRecoveryListener, ImportRecoveryListener;
@@ -1152,31 +1152,59 @@
/// ```
Token parseFormalParameter(
Token token, FormalParameterKind parameterKind, MemberKind memberKind) {
+ assert(parameterKind != null);
token = parseMetadataStar(token);
Token next = token.next;
listener.beginFormalParameter(next, memberKind);
TypeContinuation typeContinuation =
typeContinuationFromFormalParameterKind(parameterKind);
+ Token varFinalOrConst;
if (isModifier(next)) {
- ModifierContext modifierContext = parseModifiersOpt(
- this,
- token,
- skipToLastModifier(token),
- memberKind,
- parameterKind,
- false,
- typeContinuation);
- typeContinuation = modifierContext.typeContinuation;
- memberKind = modifierContext.memberKind;
- token = modifierContext.lastModifier;
- modifierContext = null;
+ int modifierCount = 0;
+ Token covariantToken;
+ if (optional('covariant', next)) {
+ if (memberKind != MemberKind.StaticMethod &&
+ memberKind != MemberKind.TopLevelMethod) {
+ covariantToken = token = parseModifier(token);
+ ++modifierCount;
+ next = token.next;
+ }
+ }
+
+ if (isModifier(next)) {
+ if (optional('var', next)) {
+ typeContinuation = typeContinuationAfterVar(typeContinuation);
+ varFinalOrConst = token = parseModifier(token);
+ ++modifierCount;
+ next = token.next;
+ } else if (optional('final', next)) {
+ varFinalOrConst = token = parseModifier(token);
+ ++modifierCount;
+ next = token.next;
+ }
+
+ if (isModifier(next)) {
+ // Recovery
+ ModifierRecoveryContext modifierContext = new ModifierRecoveryContext(
+ this, memberKind, parameterKind, false, typeContinuation);
+ token = modifierContext.parseRecovery(token,
+ covariantToken: covariantToken, varFinalOrConst: varFinalOrConst);
+
+ memberKind = modifierContext.memberKind;
+ typeContinuation = modifierContext.typeContinuation;
+ varFinalOrConst = modifierContext.varFinalOrConst;
+ modifierCount = modifierContext.modifierCount;
+ modifierContext = null;
+ }
+ }
+ listener.handleModifiers(modifierCount);
} else {
listener.handleModifiers(0);
- typeContinuation ??= typeContinuationFromMemberKind(false, memberKind);
}
- return parseType(token, typeContinuation, null, memberKind);
+ return parseType(
+ token, typeContinuation, null, memberKind, varFinalOrConst);
}
/// ```
@@ -2061,7 +2089,8 @@
Token parseType(Token token,
[TypeContinuation continuation = TypeContinuation.Required,
IdentifierContext continuationContext,
- MemberKind memberKind]) {
+ MemberKind memberKind,
+ Token varFinalOrConst]) {
/// True if we've seen the `var` keyword.
bool hasVar = false;
@@ -2580,12 +2609,20 @@
Token closer = closeBraceTokenFor(token);
if (closer != null) {
if (optional("(", closer.next)) {
+ if (varFinalOrConst != null) {
+ reportRecoverableError(
+ varFinalOrConst, fasta.messageFunctionTypedParameterVar);
+ }
inlineFunctionTypeStart = beforeToken;
beforeToken = token;
token = token.next;
}
}
} else if (optional("(", token)) {
+ if (varFinalOrConst != null) {
+ reportRecoverableError(
+ varFinalOrConst, fasta.messageFunctionTypedParameterVar);
+ }
inlineFunctionTypeStart = beforeToken;
beforeToken = closeBraceTokenFor(token);
token = beforeToken.next;
@@ -4186,6 +4223,8 @@
throw "Internal error: Unknown asyncState: '$asyncState'.";
} else if (identical(value, 'const')) {
return parseExpressionStatementOrConstDeclaration(token);
+ } else if (isModifier(token.next)) {
+ return parseVariablesDeclaration(token);
} else if (token.next.isIdentifier) {
return parseExpressionStatementOrDeclaration(token);
} else if (identical(value, '@')) {
@@ -5360,22 +5399,43 @@
Token parseVariablesDeclarationMaybeSemicolon(
Token token, bool endWithSemicolon) {
token = parseMetadataStar(token);
+ Token next = token.next;
MemberKind memberKind = MemberKind.Local;
TypeContinuation typeContinuation;
- if (isModifier(token.next)) {
- ModifierContext modifierContext = parseModifiersOpt(
- this, token, skipToLastModifier(token), memberKind, null, true, null);
- token = modifierContext.lastModifier;
- typeContinuation = modifierContext.typeContinuation;
- memberKind = modifierContext.memberKind;
- modifierContext = null;
+ Token varFinalOrConst;
+ if (isModifier(next)) {
+ if (optional('var', next)) {
+ typeContinuation = TypeContinuation.OptionalAfterVar;
+ varFinalOrConst = token = parseModifier(token);
+ next = token.next;
+ } else if (optional('final', next) || optional('const', next)) {
+ typeContinuation = TypeContinuation.Optional;
+ varFinalOrConst = token = parseModifier(token);
+ next = token.next;
+ }
+
+ if (isModifier(next)) {
+ // Recovery
+ ModifierRecoveryContext modifierContext = new ModifierRecoveryContext(
+ this, memberKind, null, true, typeContinuation);
+ token = modifierContext.parseRecovery(token,
+ varFinalOrConst: varFinalOrConst);
+
+ memberKind = modifierContext.memberKind;
+ typeContinuation = modifierContext.typeContinuation;
+ varFinalOrConst = modifierContext.varFinalOrConst;
+ listener.handleModifiers(modifierContext.modifierCount);
+ modifierContext = null;
+ } else {
+ listener.handleModifiers(1);
+ }
} else {
listener.handleModifiers(0);
- typeContinuation = typeContinuationFromMemberKind(true, memberKind);
}
- token = parseType(token, typeContinuation, null, memberKind);
+ token = parseType(
+ token, typeContinuation ?? TypeContinuation.Required, null, memberKind);
return parseVariablesDeclarationMaybeSemicolonRest(token, endWithSemicolon);
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 9f8bf37..9c361ef 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -11,12 +11,22 @@
import 'package:front_end/src/fasta/type_inference/interface_resolver.dart'
show InterfaceResolver;
-import 'package:kernel/ast.dart' show Arguments, Expression, Library, Program;
+import 'package:kernel/ast.dart'
+ show
+ Arguments,
+ Class,
+ Expression,
+ Library,
+ LibraryDependency,
+ Program,
+ Supertype;
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
+import 'package:kernel/type_environment.dart' show TypeEnvironment;
+
import '../../api_prototype/file_system.dart';
import '../../base/instrumentation.dart'
@@ -45,6 +55,7 @@
Message,
SummaryTemplate,
Template,
+ templateAmbiguousSupertypes,
templateCyclicClassHierarchy,
templateExtendingEnum,
templateExtendingRestricted,
@@ -541,20 +552,58 @@
}
Program computeFullProgram() {
- List<Library> libraries = <Library>[];
+ Set<Library> libraries = new Set<Library>();
+ List<Library> workList = <Library>[];
builders.forEach((Uri uri, LibraryBuilder library) {
if (!library.isPart && !library.isPatch) {
- libraries.add(library.target);
+ if (libraries.add(library.target)) {
+ workList.add(library.target);
+ }
}
});
+ while (workList.isNotEmpty) {
+ Library library = workList.removeLast();
+ for (LibraryDependency dependency in library.dependencies) {
+ if (libraries.add(dependency.targetLibrary)) {
+ workList.add(dependency.targetLibrary);
+ }
+ }
+ }
return new Program()..libraries.addAll(libraries);
}
void computeHierarchy() {
- hierarchy = new ClassHierarchy.deprecated_incremental(computeFullProgram());
+ List<List> ambiguousTypesRecords = [];
+ hierarchy = new ClassHierarchy(computeFullProgram(),
+ onAmbiguousSupertypes: (Class cls, Supertype a, Supertype b) {
+ if (ambiguousTypesRecords != null) {
+ ambiguousTypesRecords.add([cls, a, b]);
+ }
+ });
+ for (List record in ambiguousTypesRecords) {
+ handleAmbiguousSupertypes(record[0], record[1], record[2]);
+ }
+ ambiguousTypesRecords = null;
ticker.logMs("Computed class hierarchy");
}
+ void handleAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {
+ String name = cls.name;
+ TypeEnvironment env = new TypeEnvironment(coreTypes, hierarchy,
+ strongMode: target.strongMode);
+
+ if (cls.isSyntheticMixinImplementation) return;
+
+ if (env.isSubtypeOf(a.asInterfaceType, b.asInterfaceType)) return;
+ addProblem(
+ templateAmbiguousSupertypes.withArguments(
+ name, a.asInterfaceType, b.asInterfaceType),
+ cls.fileOffset,
+ cls.fileUri);
+ }
+
+ void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
+
void computeCoreTypes(Program program) {
coreTypes = new CoreTypes(program);
ticker.logMs("Computed core types");
@@ -634,8 +683,9 @@
// target those forwarding stubs.
// TODO(paulberry): could we make this unnecessary by not clearing class
// inference info?
- typeInferenceEngine.classHierarchy = hierarchy =
- new ClassHierarchy.deprecated_incremental(computeFullProgram());
+ typeInferenceEngine.classHierarchy = hierarchy = new ClassHierarchy(
+ computeFullProgram(),
+ onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
ticker.logMs("Performed top level inference");
}
diff --git a/pkg/front_end/lib/src/fasta/testing/kernel_chain.dart b/pkg/front_end/lib/src/fasta/testing/kernel_chain.dart
index 78cf4a8..07486e1 100644
--- a/pkg/front_end/lib/src/fasta/testing/kernel_chain.dart
+++ b/pkg/front_end/lib/src/fasta/testing/kernel_chain.dart
@@ -9,7 +9,7 @@
import 'dart:async' show Future;
-import 'dart:io' show Directory, File, IOSink, Platform;
+import 'dart:io' show Directory, File, IOSink;
import 'dart:typed_data' show Uint8List;
@@ -275,19 +275,9 @@
}
Future<String> runDiff(Uri expected, String actual) async {
- if (Platform.isWindows) {
- // TODO(ahe): Implement this for Windows.
- return """
-==> Expected ($expected) <==
-${new File.fromUri(expected).readAsStringSync()}
-
-==> Actual <==
-$actual
-
-""";
- }
- StdioProcess process = await StdioProcess
- .run("diff", <String>["-u", expected.toFilePath(), "-"], input: actual);
+ StdioProcess process = await StdioProcess.run(
+ "git", <String>["diff", "--no-index", "-u", expected.toFilePath(), "-"],
+ input: actual, runInShell: true);
return process.output;
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
index 1105396..54dd9e5 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
@@ -366,11 +366,16 @@
}
procedure.isAbstract = false;
if (!procedure.isForwardingStub) {
+ // This procedure exists abstractly in the source code; we need to make it
+ // concrete and give it a body that is a forwarding stub. This situation
+ // is called a "forwarding semi-stub".
+ procedure.isForwardingStub = true;
+ procedure.isForwardingSemiStub = true;
_interfaceResolver._instrumentation?.record(
procedure.fileUri,
procedure.fileOffset,
'forwardingStub',
- new InstrumentationValueLiteral('implementation'));
+ new InstrumentationValueLiteral('semi-stub'));
}
var positionalArguments = function.positionalParameters
.map<Expression>((parameter) => new VariableGet(parameter))
@@ -799,6 +804,7 @@
}
if (resolution is Procedure &&
resolution.isForwardingStub &&
+ !resolution.isForwardingSemiStub &&
identical(resolution.enclosingClass, class_)) {
if (strongMode) class_.addMember(resolution);
_instrumentation?.record(
@@ -971,7 +977,9 @@
for (var procedure in class_.procedures) {
if (procedure.isStatic) continue;
// Forwarding stubs are annotated separately
- if (procedure.isForwardingStub) continue;
+ if (procedure.isForwardingStub && !procedure.isForwardingSemiStub) {
+ continue;
+ }
void recordFormalAnnotations(VariableDeclaration formal) {
recordCovariance(formal.fileOffset, formal.isCovariant,
formal.isGenericCovariantInterface, formal.isGenericCovariantImpl);
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 2ff707a..a41e93a 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -80,7 +80,6 @@
dillTarget.loader.libraries.forEach((lib) {
// TODO(ahe): Don't do this, and remove [external_state_snapshot.dart].
lib.isExternal = true;
- lib.dependencies.clear();
});
// Linked dependencies are meant to be part of the program so they are not
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index ebab622..885b361 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -278,6 +278,16 @@
script:
- "class C { static f; }"
+FunctionTypedParameterVar:
+ template: "Function-typed parameters can't specify 'const', 'final' or 'var' in place of a return type."
+ tip: "Try replacing the keyword with a return type."
+ analyzerCode: FUNCTION_TYPED_PARAMETER_VAR
+ dart2jsCode: "*fatal*"
+ script:
+ - "void f(const x()) {}"
+ - "void f(final x()) {}"
+ - "void f(var x()) {}"
+
AbstractClassMember:
template: "Members of classes can't be declared to be 'abstract'."
tip: "Try removing the 'abstract' keyword. You can add the 'abstract' keyword before the class declaration."
@@ -1786,6 +1796,7 @@
C c;
c.foo();
}
+
SourceOutlineSummary:
template: |
Built outlines for #count compilation units (#count2 bytes) in #string, that is,
@@ -1812,3 +1823,7 @@
template: "Can't infer the type of '#string': circularity found during type inference."
tip: "Specify the type explicitly."
severity: ERROR
+
+AmbiguousSupertypes:
+ template: "'#name' can't implement both '#type' and '#type2'"
+ severity: ERROR
diff --git a/pkg/front_end/test/src/incremental/mock_sdk.dart b/pkg/front_end/test/src/incremental/mock_sdk.dart
index f2b817e..1cbbc83 100644
--- a/pkg/front_end/test/src/incremental/mock_sdk.dart
+++ b/pkg/front_end/test/src/incremental/mock_sdk.dart
@@ -302,6 +302,7 @@
addSdkLibrary('convert', 'library dart.convert;');
addSdkLibrary('developer', 'library dart.developer;');
addSdkLibrary('io', 'library dart.io;');
+ addSdkLibrary('cli', 'library dart.cli;');
addSdkLibrary('isolate', 'library dart.isolate;');
addSdkLibrary('math', '''
library dart.math;
diff --git a/pkg/front_end/testcases/ast_builder.status b/pkg/front_end/testcases/ast_builder.status
index b86de60..55d5d5f 100644
--- a/pkg/front_end/testcases/ast_builder.status
+++ b/pkg/front_end/testcases/ast_builder.status
@@ -10,6 +10,11 @@
argument_mismatch: Crash
bad_setter_abstract: Crash
cascade: Crash
+check_deferred_read: Crash
+check_deferred_before_write: Crash
+check_deferred_before_call: Crash
+check_deferred_before_args: Crash
+check_deferred_before_args2: Crash
classes: Crash
duplicated_named_args_3: Crash
dynamic_and_void: Fail
@@ -109,6 +114,7 @@
rasta/malformed_function: Crash
rasta/mandatory_parameter_initializer: Crash
rasta/parser_error: Crash
+rasta/previsit_deferred: Crash
rasta/static: Crash
rasta/super_initializer: Crash
rasta/supports_reflection: VerificationError
diff --git a/pkg/front_end/testcases/check_deferred_before_args.dart b/pkg/front_end/testcases/check_deferred_before_args.dart
new file mode 100644
index 0000000..cd12c6d
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_args.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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.md file.
+
+import 'deferred_lib.dart' deferred as lib;
+
+main() {}
+test() {
+ lib.x = m2();
+ lib.m(m2());
+}
+
+m2() => 1;
diff --git a/pkg/front_end/testcases/check_deferred_before_args.dart.direct.expect b/pkg/front_end/testcases/check_deferred_before_args.dart.direct.expect
new file mode 100644
index 0000000..0ff5bf9
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_args.dart.direct.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "./deferred_lib.dart" as def;
+
+static method main() → dynamic {}
+static method test() → dynamic {
+ let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::x = self::m2();
+ let final dynamic #t2 = CheckLibraryIsLoaded(lib) in def::m(self::m2());
+}
+static method m2() → dynamic
+ return 1;
diff --git a/pkg/front_end/testcases/check_deferred_before_args.dart.outline.expect b/pkg/front_end/testcases/check_deferred_before_args.dart.outline.expect
new file mode 100644
index 0000000..8140e58
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_args.dart.outline.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+
+static method main() → dynamic
+ ;
+static method test() → dynamic
+ ;
+static method m2() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/check_deferred_before_args.dart.strong.expect b/pkg/front_end/testcases/check_deferred_before_args.dart.strong.expect
new file mode 100644
index 0000000..0ff5bf9
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_args.dart.strong.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "./deferred_lib.dart" as def;
+
+static method main() → dynamic {}
+static method test() → dynamic {
+ let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::x = self::m2();
+ let final dynamic #t2 = CheckLibraryIsLoaded(lib) in def::m(self::m2());
+}
+static method m2() → dynamic
+ return 1;
diff --git a/pkg/front_end/testcases/check_deferred_before_args2.dart b/pkg/front_end/testcases/check_deferred_before_args2.dart
new file mode 100644
index 0000000..d885bb9
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_args2.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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.md file.
+
+import 'deferred_lib.dart' deferred as lib;
+
+main() {}
+
+test() async {
+ // The current evaluation order will triger the check of lib.m before the
+ // loadLibrary call.
+ lib.m(await lib.loadLibrary());
+}
diff --git a/pkg/front_end/testcases/check_deferred_before_args2.dart.direct.expect b/pkg/front_end/testcases/check_deferred_before_args2.dart.direct.expect
new file mode 100644
index 0000000..5b1c7ee
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_args2.dart.direct.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "./deferred_lib.dart" as def;
+
+static method main() → dynamic {}
+static method test() → dynamic async {
+ let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::m(await LoadLibrary(lib));
+}
diff --git a/pkg/front_end/testcases/check_deferred_before_args2.dart.outline.expect b/pkg/front_end/testcases/check_deferred_before_args2.dart.outline.expect
new file mode 100644
index 0000000..7a4d537
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_args2.dart.outline.expect
@@ -0,0 +1,7 @@
+library;
+import self as self;
+
+static method main() → dynamic
+ ;
+static method test() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/check_deferred_before_args2.dart.strong.expect b/pkg/front_end/testcases/check_deferred_before_args2.dart.strong.expect
new file mode 100644
index 0000000..5b1c7ee
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_args2.dart.strong.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "./deferred_lib.dart" as def;
+
+static method main() → dynamic {}
+static method test() → dynamic async {
+ let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::m(await LoadLibrary(lib));
+}
diff --git a/pkg/front_end/testcases/check_deferred_before_call.dart b/pkg/front_end/testcases/check_deferred_before_call.dart
new file mode 100644
index 0000000..aa6ad85
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_call.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2018, 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.md file.
+
+import 'deferred_lib.dart' deferred as lib;
+
+main() {}
+
+test() {
+ lib.m(3);
+}
diff --git a/pkg/front_end/testcases/check_deferred_before_call.dart.direct.expect b/pkg/front_end/testcases/check_deferred_before_call.dart.direct.expect
new file mode 100644
index 0000000..9aef4cf
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_call.dart.direct.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "./deferred_lib.dart" as def;
+
+static method main() → dynamic {}
+static method test() → dynamic {
+ let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::m(3);
+}
diff --git a/pkg/front_end/testcases/check_deferred_before_call.dart.outline.expect b/pkg/front_end/testcases/check_deferred_before_call.dart.outline.expect
new file mode 100644
index 0000000..7a4d537
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_call.dart.outline.expect
@@ -0,0 +1,7 @@
+library;
+import self as self;
+
+static method main() → dynamic
+ ;
+static method test() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/check_deferred_before_call.dart.strong.expect b/pkg/front_end/testcases/check_deferred_before_call.dart.strong.expect
new file mode 100644
index 0000000..9aef4cf
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_call.dart.strong.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "./deferred_lib.dart" as def;
+
+static method main() → dynamic {}
+static method test() → dynamic {
+ let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::m(3);
+}
diff --git a/pkg/front_end/testcases/check_deferred_before_write.dart b/pkg/front_end/testcases/check_deferred_before_write.dart
new file mode 100644
index 0000000..5a8f96c
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_write.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2018, 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.md file.
+
+import 'deferred_lib.dart' deferred as lib;
+
+main() {}
+test() {
+ lib.x = 2;
+}
diff --git a/pkg/front_end/testcases/check_deferred_before_write.dart.direct.expect b/pkg/front_end/testcases/check_deferred_before_write.dart.direct.expect
new file mode 100644
index 0000000..2b7ef3d
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_write.dart.direct.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "./deferred_lib.dart" as def;
+
+static method main() → dynamic {}
+static method test() → dynamic {
+ let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::x = 2;
+}
diff --git a/pkg/front_end/testcases/check_deferred_before_write.dart.outline.expect b/pkg/front_end/testcases/check_deferred_before_write.dart.outline.expect
new file mode 100644
index 0000000..7a4d537
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_write.dart.outline.expect
@@ -0,0 +1,7 @@
+library;
+import self as self;
+
+static method main() → dynamic
+ ;
+static method test() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/check_deferred_before_write.dart.strong.expect b/pkg/front_end/testcases/check_deferred_before_write.dart.strong.expect
new file mode 100644
index 0000000..2b7ef3d
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_before_write.dart.strong.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "./deferred_lib.dart" as def;
+
+static method main() → dynamic {}
+static method test() → dynamic {
+ let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::x = 2;
+}
diff --git a/pkg/front_end/testcases/check_deferred_read.dart b/pkg/front_end/testcases/check_deferred_read.dart
new file mode 100644
index 0000000..0cebef0
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_read.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2018, 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.md file.
+
+import 'deferred_lib.dart' deferred as lib;
+
+main() {}
+test() {
+ print(lib.x + 1);
+}
diff --git a/pkg/front_end/testcases/check_deferred_read.dart.direct.expect b/pkg/front_end/testcases/check_deferred_read.dart.direct.expect
new file mode 100644
index 0000000..5fd285b
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_read.dart.direct.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "./deferred_lib.dart" as def;
+
+static method main() → dynamic {}
+static method test() → dynamic {
+ core::print((let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::x).+(1));
+}
diff --git a/pkg/front_end/testcases/check_deferred_read.dart.outline.expect b/pkg/front_end/testcases/check_deferred_read.dart.outline.expect
new file mode 100644
index 0000000..7a4d537
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_read.dart.outline.expect
@@ -0,0 +1,7 @@
+library;
+import self as self;
+
+static method main() → dynamic
+ ;
+static method test() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/check_deferred_read.dart.strong.expect b/pkg/front_end/testcases/check_deferred_read.dart.strong.expect
new file mode 100644
index 0000000..5fd285b
--- /dev/null
+++ b/pkg/front_end/testcases/check_deferred_read.dart.strong.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "./deferred_lib.dart" as def;
+
+static method main() → dynamic {}
+static method test() → dynamic {
+ core::print((let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::x).+(1));
+}
diff --git a/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart b/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart
new file mode 100644
index 0000000..3385d23
--- /dev/null
+++ b/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+/**
+ * @assertion
+ * metadata:
+ * (‘@’ qualified (‘.’ identifier)? (arguments)?)*
+ * ;
+ * @description Check that it is a compile time error, if @ is missing
+ * @compile-error
+ * @author a.semenov@unipro.ru
+ */
+
+class A {
+ const A();
+}
+
+A()
+class B {}
+
+main() {
+}
diff --git a/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.direct.expect b/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.direct.expect
new file mode 100644
index 0000000..6262bfd
--- /dev/null
+++ b/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.direct.expect
@@ -0,0 +1,6 @@
+library;
+import self as self;
+
+static method #main() → dynamic {
+ throw "pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart:16:9: Error: Duplicated name: A\nclass A {\n ^";
+}
diff --git a/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.outline.expect b/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.outline.expect
new file mode 100644
index 0000000..869f502
--- /dev/null
+++ b/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.outline.expect
@@ -0,0 +1,16 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ const constructor •() → void
+ ;
+}
+class B extends core::Object {
+ default constructor •() → void
+ ;
+}
+static method A() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.strong.expect b/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.strong.expect
new file mode 100644
index 0000000..6262bfd
--- /dev/null
+++ b/pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart.strong.expect
@@ -0,0 +1,6 @@
+library;
+import self as self;
+
+static method #main() → dynamic {
+ throw "pkg/front_end/testcases/co19_language_metadata_syntax_t04.dart:16:9: Error: Duplicated name: A\nclass A {\n ^";
+}
diff --git a/pkg/front_end/testcases/compile.status b/pkg/front_end/testcases/compile.status
index 41e6f96..3945492 100644
--- a/pkg/front_end/testcases/compile.status
+++ b/pkg/front_end/testcases/compile.status
@@ -120,3 +120,5 @@
rasta/foo: RuntimeError # Expected, this file has no main method.
incomplete_field_formal_parameter: Fail # Fasta doesn't recover well
+
+co19_language_metadata_syntax_t04: RuntimeError # Fasta doesn't recover well
diff --git a/pkg/front_end/testcases/deferred_lib.dart b/pkg/front_end/testcases/deferred_lib.dart
new file mode 100644
index 0000000..b08a2df
--- /dev/null
+++ b/pkg/front_end/testcases/deferred_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2018, 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.md file.
+
+dynamic m(x) => null;
+
+var x = 0;
diff --git a/pkg/front_end/testcases/rasta/previsit_deferred.dart b/pkg/front_end/testcases/rasta/previsit_deferred.dart
index 6bdd3e9..ac2c00c 100644
--- a/pkg/front_end/testcases/rasta/previsit_deferred.dart
+++ b/pkg/front_end/testcases/rasta/previsit_deferred.dart
@@ -4,6 +4,7 @@
import 'deferred_lib.dart' deferred as lib;
-main() {
+main() {}
+test() {
lib.foo();
}
diff --git a/pkg/front_end/testcases/rasta/previsit_deferred.dart.direct.expect b/pkg/front_end/testcases/rasta/previsit_deferred.dart.direct.expect
index 93e2b71..f479708 100644
--- a/pkg/front_end/testcases/rasta/previsit_deferred.dart.direct.expect
+++ b/pkg/front_end/testcases/rasta/previsit_deferred.dart.direct.expect
@@ -2,6 +2,7 @@
import self as self;
import "./deferred_lib.dart" as def;
-static method main() → dynamic {
- def::foo();
+static method main() → dynamic {}
+static method test() → dynamic {
+ let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::foo();
}
diff --git a/pkg/front_end/testcases/rasta/previsit_deferred.dart.outline.expect b/pkg/front_end/testcases/rasta/previsit_deferred.dart.outline.expect
index 6a28c0d..7a4d537 100644
--- a/pkg/front_end/testcases/rasta/previsit_deferred.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/previsit_deferred.dart.outline.expect
@@ -3,3 +3,5 @@
static method main() → dynamic
;
+static method test() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/rasta/previsit_deferred.dart.strong.expect b/pkg/front_end/testcases/rasta/previsit_deferred.dart.strong.expect
new file mode 100644
index 0000000..f479708
--- /dev/null
+++ b/pkg/front_end/testcases/rasta/previsit_deferred.dart.strong.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "./deferred_lib.dart" as def;
+
+static method main() → dynamic {}
+static method test() → dynamic {
+ let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::foo();
+}
diff --git a/pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart b/pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart
index c38e6e0..111cb15 100644
--- a/pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart
+++ b/pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart
@@ -14,7 +14,7 @@
}
class C extends B implements I<num> {
- void /*@forwardingStub=implementation*/ f(num /*@covariance=genericImpl*/ x);
+ void /*@forwardingStub=semi-stub*/ f(num /*@covariance=genericImpl*/ x);
}
main() {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart.strong.expect
index 0a9b961..ac8f153 100644
--- a/pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/abstract_override_becomes_forwarding_stub.dart.strong.expect
@@ -18,6 +18,7 @@
default constructor •() → void
: super self::B::•()
;
- method f(generic-covariant-impl core::num x) → void;
+ forwarding-stub forwarding-semi-stub method f(generic-covariant-impl core::num x) → void
+ return super.{self::B::f}(x);
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 8f24726..ec8fc44 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -67,6 +67,7 @@
unused_methods: Fail
void_methods: Fail
warn_unresolved_sends: Fail # Test assumes Dart 1.0 semantics
+check_deferred_read: Fail
inference/abstract_class_instantiation: Fail # Issue #30040
inference/conflicts_can_happen: TypeCheckError
@@ -174,7 +175,6 @@
rasta/mixin_library: TypeCheckError
rasta/native_is_illegal: Fail
rasta/parser_error: Fail
-rasta/previsit_deferred: Fail
rasta/static: Fail
rasta/super: TypeCheckError
rasta/super_initializer: Fail
@@ -217,3 +217,5 @@
rasta/foo: RuntimeError # Expected, this file has no main method.
incomplete_field_formal_parameter: Fail # Fasta doesn't recover well
+
+co19_language_metadata_syntax_t04: RuntimeError # Fasta doesn't recover well
diff --git a/pkg/js_ast/pubspec.yaml b/pkg/js_ast/pubspec.yaml
index accf876..6994e78 100644
--- a/pkg/js_ast/pubspec.yaml
+++ b/pkg/js_ast/pubspec.yaml
@@ -3,6 +3,6 @@
description: Library creating and printing JavaScript ASTs.
homepage: http://www.dartlang.org
dev_dependencies:
- unittest: ">=0.9.0 <0.10.0"
+ test: '^0.12.29'
environment:
sdk: ">=0.8.10+6 <2.0.0"
diff --git a/pkg/js_ast/test/printer_callback_test.dart b/pkg/js_ast/test/printer_callback_test.dart
index 6483d28..7d8fb30 100644
--- a/pkg/js_ast/test/printer_callback_test.dart
+++ b/pkg/js_ast/test/printer_callback_test.dart
@@ -9,7 +9,7 @@
library js_ast.printer.callback_test;
import 'package:js_ast/js_ast.dart';
-import 'package:unittest/unittest.dart';
+import 'package:test/test.dart';
enum TestMode {
INPUT,
@@ -246,5 +246,7 @@
}
void main() {
- DATA.forEach(check);
+ test('printer callback test', () {
+ DATA.forEach(check);
+ });
}
diff --git a/pkg/js_ast/test/string_escape_test.dart b/pkg/js_ast/test/string_escape_test.dart
index 118225b..9277ed6 100644
--- a/pkg/js_ast/test/string_escape_test.dart
+++ b/pkg/js_ast/test/string_escape_test.dart
@@ -6,7 +6,7 @@
import 'package:js_ast/js_ast.dart';
import 'package:js_ast/src/characters.dart';
-import 'package:unittest/unittest.dart';
+import 'package:test/test.dart';
const int $LCURLY = $OPEN_CURLY_BRACKET;
const int $RCURLY = $CLOSE_CURLY_BRACKET;
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 519bd6d..85e2fbe 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -324,7 +324,7 @@
CanonicalNameReference canonicalName;
FileOffset fileOffset;
FileOffset fileEndOffset;
- Byte flags (isConst, isExternal);
+ Byte flags (isConst, isExternal, isSynthetic);
Name name;
UriReference fileUri;
List<Expression> annotations;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index eb61c33..c07f52a 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -1234,7 +1234,7 @@
{Name name,
bool isConst: false,
bool isExternal: false,
- bool isSyntheticDefault: false,
+ bool isSynthetic: false,
List<Initializer> initializers,
int transformerFlags: 0,
this.fileUri,
@@ -1245,20 +1245,20 @@
setParents(this.initializers, this);
this.isConst = isConst;
this.isExternal = isExternal;
- this.isSyntheticDefault = isSyntheticDefault;
+ this.isSynthetic = isSynthetic;
this.transformerFlags = transformerFlags;
}
static const int FlagConst = 1 << 0; // Must match serialized bit positions.
static const int FlagExternal = 1 << 1;
- static const int FlagSyntheticDefault = 1 << 2;
+ static const int FlagSynthetic = 1 << 2;
bool get isConst => flags & FlagConst != 0;
bool get isExternal => flags & FlagExternal != 0;
- /// True if this is a synthetic default constructor inserted in a class that
+ /// True if this is a synthetic constructor inserted in a class that
/// does not otherwise declare any constructors.
- bool get isSyntheticDefault => flags & FlagSyntheticDefault != 0;
+ bool get isSynthetic => flags & FlagSynthetic != 0;
void set isConst(bool value) {
flags = value ? (flags | FlagConst) : (flags & ~FlagConst);
@@ -1268,10 +1268,8 @@
flags = value ? (flags | FlagExternal) : (flags & ~FlagExternal);
}
- void set isSyntheticDefault(bool value) {
- flags = value
- ? (flags | FlagSyntheticDefault)
- : (flags & ~FlagSyntheticDefault);
+ void set isSynthetic(bool value) {
+ flags = value ? (flags | FlagSynthetic) : (flags & ~FlagSynthetic);
}
bool get isInstanceMember => false;
@@ -1363,7 +1361,6 @@
{Name name,
bool isConst: false,
bool isExternal: false,
- bool isSyntheticDefault: false,
int transformerFlags: 0,
List<DartType> typeArguments,
List<TypeParameter> typeParameters,
@@ -1390,7 +1387,6 @@
static const int FlagConst = 1 << 0; // Must match serialized bit positions.
static const int FlagExternal = 1 << 1;
- static const int FlagSyntheticDefault = 1 << 2;
bool get isConst => flags & FlagConst != 0;
bool get isExternal => flags & FlagExternal != 0;
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index d43b7ff..5f2954d 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -656,10 +656,6 @@
void _readLibraryDependencies(Library library) {
int length = readUInt();
- if (library.isExternal) {
- assert(length == 0);
- return;
- }
library.dependencies.length = length;
for (int i = 0; i < length; ++i) {
library.dependencies[i] = readLibraryDependency(library);
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 5eb3ab5..397e7f7 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -11,16 +11,25 @@
import 'src/incremental_class_hierarchy.dart' show IncrementalClassHierarchy;
+typedef HandleAmbiguousSupertypes = void Function(Class, Supertype, Supertype);
+
/// Interface for answering various subclassing queries.
/// TODO(scheglov) Several methods are not used, or used only in tests.
/// Check if these methods are not useful and should be removed .
abstract class ClassHierarchy {
- factory ClassHierarchy(Program program) {
+ factory ClassHierarchy(Program program,
+ {HandleAmbiguousSupertypes onAmbiguousSupertypes}) {
int numberOfClasses = 0;
for (var library in program.libraries) {
numberOfClasses += library.classes.length;
}
- return new ClosedWorldClassHierarchy._internal(program, numberOfClasses)
+ onAmbiguousSupertypes ??= (Class cls, Supertype a, Supertype b) {
+ if (!cls.isSyntheticMixinImplementation) {
+ throw "$cls can't implement both $a and $b";
+ }
+ };
+ return new ClosedWorldClassHierarchy._internal(
+ program, numberOfClasses, onAmbiguousSupertypes)
.._initialize();
}
@@ -94,6 +103,24 @@
/// is resolved if the class was not abstract.
Member getDispatchTarget(Class class_, Name name, {bool setter: false});
+ /// Returns the list of potential targets of dynamic dispatch to an instance
+ /// of [class_].
+ ///
+ /// If [setters] is `false`, only potential targets of a getter or call
+ /// dispatch are returned. If [setters] is `true`, only potential targets
+ /// of a setter dispatch are returned.
+ ///
+ /// See [getDispatchTarget] for more details.
+ ///
+ /// The returned list should not be modified.
+ List<Member> getDispatchTargets(Class class_, {bool setters: false});
+
+ /// Returns the single concrete target for invocation of the given interface
+ /// target, or `null` if it could not be resolved or there are multiple
+ /// possible targets.
+ Member getSingleTargetForInterfaceInvocation(Member interfaceTarget,
+ {bool setter: false});
+
/// Returns the possibly abstract interface member of [class_] with the given
/// [name].
///
@@ -122,6 +149,34 @@
/// classes.
List<Member> getDeclaredMembers(Class class_, {bool setters: false});
+ /// Returns the subclasses of [class_] as an interval list.
+ ClassSet getSubclassesOf(Class class_);
+
+ /// Returns the subtypes of [class_] as an interval list.
+ ClassSet getSubtypesOf(Class class_);
+
+ /// True if [subclass] inherits from [superclass] though zero or more
+ /// `extends` relationships.
+ bool isSubclassOf(Class subclass, Class superclass);
+
+ /// True if [submixture] inherits from [superclass] though zero or more
+ /// `extends` and `with` relationships.
+ bool isSubmixtureOf(Class submixture, Class superclass);
+
+ /// True if [subtype] inherits from [superclass] though zero or more
+ /// `extends`, `with`, and `implements` relationships.
+ bool isSubtypeOf(Class subtype, Class superclass);
+
+ /// True if the given class is used as the right-hand operand to a
+ /// mixin application (i.e. [Class.mixedInType]).
+ bool isUsedAsMixin(Class class_);
+
+ /// True if the given class is the direct super class of another class.
+ bool isUsedAsSuperClass(Class class_);
+
+ /// True if the given class is used in an `implements` clause.
+ bool isUsedAsSuperInterface(Class class_);
+
/// Invokes [callback] for every member declared in or inherited by [class_]
/// that overrides or implements a member in a supertype of [class_]
/// (or in rare cases, overrides a member declared in [class_]).
@@ -271,6 +326,8 @@
/// Implementation of [ClassHierarchy] for closed world.
class ClosedWorldClassHierarchy implements ClassHierarchy {
+ final HandleAmbiguousSupertypes _onAmbiguousSupertypes;
+
/// The [Program] that this class hierarchy represents.
final Program _program;
@@ -281,7 +338,8 @@
final Map<Class, _ClassInfo> _infoFor = <Class, _ClassInfo>{};
- ClosedWorldClassHierarchy._internal(this._program, int numberOfClasses)
+ ClosedWorldClassHierarchy._internal(
+ this._program, int numberOfClasses, this._onAmbiguousSupertypes)
: classes = new List<Class>(numberOfClasses);
@override
@@ -293,39 +351,35 @@
return classes.where(unorderedSet.contains);
}
- /// True if [subclass] inherits from [superclass] though zero or more
- /// `extends` relationships.
+ @override
bool isSubclassOf(Class subclass, Class superclass) {
if (identical(subclass, superclass)) return true;
return _infoFor[subclass].isSubclassOf(_infoFor[superclass]);
}
- /// True if [submixture] inherits from [superclass] though zero or more
- /// `extends` and `with` relationships.
+ @override
bool isSubmixtureOf(Class submixture, Class superclass) {
if (identical(submixture, superclass)) return true;
return _infoFor[submixture].isSubmixtureOf(_infoFor[superclass]);
}
- /// True if [subtype] inherits from [superclass] though zero or more
- /// `extends`, `with`, and `implements` relationships.
+ @override
bool isSubtypeOf(Class subtype, Class superclass) {
if (identical(subtype, superclass)) return true;
return _infoFor[subtype].isSubtypeOf(_infoFor[superclass]);
}
- /// True if the given class is the direct super class of another class.
+ @override
bool isUsedAsSuperClass(Class class_) {
return _infoFor[class_].directExtenders.isNotEmpty;
}
- /// True if the given class is used as the right-hand operand to a
- /// mixin application (i.e. [Class.mixedInType]).
+ @override
bool isUsedAsMixin(Class class_) {
return _infoFor[class_].directMixers.isNotEmpty;
}
- /// True if the given class is used in an `implements` clause.
+ @override
bool isUsedAsSuperInterface(Class class_) {
return _infoFor[class_].directImplementers.isNotEmpty;
}
@@ -446,11 +500,11 @@
var superType1 = identical(info1, next)
? type1
: Substitution.fromInterfaceType(type1).substituteType(
- info1.genericSuperTypes[next.classNode].asInterfaceType);
+ info1.genericSuperTypes[next.classNode].first.asInterfaceType);
var superType2 = identical(info2, next)
? type2
: Substitution.fromInterfaceType(type2).substituteType(
- info2.genericSuperTypes[next.classNode].asInterfaceType);
+ info2.genericSuperTypes[next.classNode].first.asInterfaceType);
if (superType1 == superType2) {
candidate = superType1;
++numCandidatesAtThisDepth;
@@ -463,10 +517,16 @@
Supertype getClassAsInstanceOf(Class class_, Class superclass) {
if (identical(class_, superclass)) return class_.asThisSupertype;
_ClassInfo info = _infoFor[class_];
+ if (info == null) {
+ throw "${class_.fileUri}: No class info for ${class_.name}";
+ }
_ClassInfo superInfo = _infoFor[superclass];
+ if (info == null) {
+ throw "${superclass.fileUri}: No class info for ${superclass.name}";
+ }
if (!info.isSubtypeOf(superInfo)) return null;
if (superclass.typeParameters.isEmpty) return superclass.asRawSupertype;
- return info.genericSuperTypes[superclass];
+ return info.genericSuperTypes[superclass]?.first;
}
@override
@@ -486,24 +546,13 @@
return ClassHierarchy.findMemberByName(list, name);
}
- /// Returns the list of potential targets of dynamic dispatch to an instance
- /// of [class_].
- ///
- /// If [setters] is `false`, only potential targets of a getter or call
- /// dispatch are returned. If [setters] is `true`, only potential targets
- /// of a setter dispatch are returned.
- ///
- /// See [getDispatchTarget] for more details.
- ///
- /// The returned list should not be modified.
+ @override
List<Member> getDispatchTargets(Class class_, {bool setters: false}) {
_ClassInfo info = _infoFor[class_];
return setters ? info.implementedSetters : info.implementedGettersAndCalls;
}
- /// Returns the single concrete target for invocation of the given interface
- /// target, or `null` if it could not be resolved or there are multiple
- /// possible targets.
+ @override
Member getSingleTargetForInterfaceInvocation(Member interfaceTarget,
{bool setter: false}) {
Name name = interfaceTarget.name;
@@ -611,12 +660,12 @@
return !getSubtypesOf(class_).isSingleton;
}
- /// Returns the subtypes of [class_] as an interval list.
+ @override
ClassSet getSubtypesOf(Class class_) {
return new ClassSet(this, _infoFor[class_].subtypeIntervalList);
}
- /// Returns the subclasses of [class_] as an interval list.
+ @override
ClassSet getSubclassesOf(Class class_) {
return new ClassSet(this, _infoFor[class_].subclassIntervalList);
}
@@ -624,7 +673,8 @@
@override
ClassHierarchy applyChanges(Iterable<Class> classes) {
if (classes.isEmpty) return this;
- return new ClassHierarchy(_program);
+ return new ClassHierarchy(_program,
+ onAmbiguousSupertypes: _onAmbiguousSupertypes);
}
void _initialize() {
@@ -671,7 +721,11 @@
throw "No info for ${cls.name} from ${cls.fileUri}.";
}
if (info.topologicalIndex != i) {
- throw "Unexpected topologicalIndex (${info.topologicalIndex} != $i) for ${cls.name} from ${cls.fileUri}.";
+ throw "Unexpected topologicalIndex (${info.topologicalIndex} != $i) "
+ "for ${cls.name} from ${cls.fileUri}.";
+ }
+ if (info.subtypeIntervalList == null) {
+ throw "No subtypeIntervalList for ${cls.name} from ${cls.fileUri}.";
}
}
}
@@ -900,8 +954,13 @@
superInfo.ownsGenericSuperTypeMap = false;
} else {
// Copy over the super type entries.
- subInfo.genericSuperTypes ??= <Class, Supertype>{};
- subInfo.genericSuperTypes.addAll(superInfo.genericSuperTypes);
+ subInfo.genericSuperTypes ??= <Class, List<Supertype>>{};
+ superInfo.genericSuperTypes
+ ?.forEach((Class key, List<Supertype> types) {
+ for (Supertype type in types) {
+ subInfo.recordGenericSuperType(key, type, _onAmbiguousSupertypes);
+ }
+ });
}
} else {
// Copy over all transitive generic super types, and substitute the
@@ -909,11 +968,16 @@
Class superclass = supertype.classNode;
var substitution = Substitution.fromPairs(
superclass.typeParameters, supertype.typeArguments);
- subInfo.genericSuperTypes ??= <Class, Supertype>{};
- superInfo.genericSuperTypes?.forEach((Class key, Supertype type) {
- subInfo.genericSuperTypes[key] = substitution.substituteSupertype(type);
+ subInfo.genericSuperTypes ??= <Class, List<Supertype>>{};
+ superInfo.genericSuperTypes?.forEach((Class key, List<Supertype> types) {
+ for (Supertype type in types) {
+ subInfo.recordGenericSuperType(key,
+ substitution.substituteSupertype(type), _onAmbiguousSupertypes);
+ }
});
- subInfo.genericSuperTypes[superclass] = supertype;
+
+ subInfo.recordGenericSuperType(
+ superclass, supertype, _onAmbiguousSupertypes);
}
}
@@ -1151,7 +1215,7 @@
///
/// In this case, a single map object `{A: A<String>, Q: Q<int>}` may be
/// shared by the classes `B` and `C`.
- Map<Class, Supertype> genericSuperTypes;
+ Map<Class, List<Supertype>> genericSuperTypes;
/// If true, this is the current "owner" of [genericSuperTypes], meaning
/// we may add additional entries to the map or transfer ownership to another
@@ -1178,6 +1242,17 @@
List<Member> interfaceSetters;
_ClassInfo(this.classNode);
+
+ void recordGenericSuperType(Class cls, Supertype type,
+ HandleAmbiguousSupertypes onAmbiguousSupertypes) {
+ List<Supertype> existing = genericSuperTypes[cls];
+ if (existing == null) {
+ genericSuperTypes[cls] = <Supertype>[type];
+ } else if (type != existing.first) {
+ existing.add(type);
+ onAmbiguousSupertypes(classNode, existing.first, type);
+ }
+ }
}
/// An immutable set of classes, internally represented as an interval list.
diff --git a/pkg/kernel/lib/src/incremental_class_hierarchy.dart b/pkg/kernel/lib/src/incremental_class_hierarchy.dart
index 21f219e..76c26da 100644
--- a/pkg/kernel/lib/src/incremental_class_hierarchy.dart
+++ b/pkg/kernel/lib/src/incremental_class_hierarchy.dart
@@ -585,6 +585,57 @@
}
}
}
+
+ @override
+ List<Member> getDispatchTargets(Class class_, {bool setters: false}) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ bool isUsedAsSuperInterface(Class class_) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ bool isUsedAsSuperClass(Class class_) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ bool isUsedAsMixin(Class class_) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ bool isSubtypeOf(Class subtype, Class superclass) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ bool isSubmixtureOf(Class submixture, Class superclass) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ bool isSubclassOf(Class subclass, Class superclass) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ ClassSet getSubtypesOf(Class class_) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ ClassSet getSubclassesOf(Class class_) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ Member getSingleTargetForInterfaceInvocation(Member interfaceTarget,
+ {bool setter: false}) {
+ throw new UnimplementedError();
+ }
}
/// Information about a [Class].
diff --git a/pkg/kernel/lib/target/vm.dart b/pkg/kernel/lib/target/vm.dart
index eefe395..a30abbb 100644
--- a/pkg/kernel/lib/target/vm.dart
+++ b/pkg/kernel/lib/target/vm.dart
@@ -52,6 +52,7 @@
'dart:_builtin',
'dart:nativewrappers',
'dart:io',
+ 'dart:cli',
];
@override
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 3578de3..5d84fa3 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -944,7 +944,7 @@
writeIndentation();
writeModifier(node.isExternal, 'external');
writeModifier(node.isConst, 'const');
- writeModifier(node.isSyntheticDefault, 'default');
+ writeModifier(node.isSynthetic, 'default');
writeWord('constructor');
writeFunction(node.function,
name: node.name, initializers: node.initializers);
diff --git a/pkg/kernel/test/type_subtype_test.dart b/pkg/kernel/test/type_subtype_test.dart
index 1517b25..29e7bae 100644
--- a/pkg/kernel/test/type_subtype_test.dart
+++ b/pkg/kernel/test/type_subtype_test.dart
@@ -18,6 +18,7 @@
'List<T>': ['Iterable<T>'],
'Future<T>': ['Object'],
'FutureOr<T>': ['Object'],
+ 'Null': ['Object'],
};
List<TestCase> testCases = <TestCase>[
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 21a7c83..a12448f 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -49,6 +49,7 @@
front_end/tool/incremental_perf_test: Slow, Pass
kernel/test/closures_test: Slow, Pass
kernel/testcases/*: Skip # These are not tests but input for tests.
+vm/testcases/*: SkipByDesign # These are not tests but input for tests.
[ $compiler == dart2analyzer ]
dev_compiler/test/options/*: SkipByDesign
@@ -112,9 +113,12 @@
[ $runtime != vm ]
dev_compiler/test/options/*: SkipByDesign
front_end/test/src/incremental/hot_reload_e2e_test: Skip
+vm/test/*: SkipByDesign # Only meant to run on vm
[ $system == windows ]
+front_end/test/fasta/bootstrap_test: Skip # Issue 31902
front_end/test/src/incremental/hot_reload_e2e_test: Skip # Issue 31901
+front_end/test/whole_program_test: Skip # Issue 31902
[ $browser ]
*/test/analyzer_test: SkipByDesign # No need to run analysis tests on browser bots
diff --git a/pkg/status_file/test/data/co19-dart2js.status b/pkg/status_file/test/data/co19-dart2js.status
index 6f8403f..438316b 100644
--- a/pkg/status_file/test/data/co19-dart2js.status
+++ b/pkg/status_file/test/data/co19-dart2js.status
@@ -205,7 +205,6 @@
LibTest/core/int/operator_remainder_A01_t01: RuntimeError, OK # Requires bigints.
LibTest/core/int/operator_right_shift_A01_t01: RuntimeError, OK # Expects negative result from bit-operation.
LibTest/core/int/toDouble_A01_t01: RuntimeError, OK # co19 issue 200
-LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: Pass,RuntimeError # https://github.com/dart-lang/sdk/issues/29814
LibTest/html/HttpRequest/responseType_A01_t03: CompileTimeError # co19-roll r706: Please triage this failure
LibTest/html/IFrameElement/enteredView_A01_t01: CompileTimeError # co19-roll r706: Please triage this failure
LibTest/isolate/Isolate/spawnUri_A01_t01: Fail # Dart issue 15974
@@ -626,7 +625,7 @@
LibTest/async/Zone/createTimer_A01_t01: RuntimeError # Issue 7728, timer not supported in jsshell
LibTest/core/List/sort_A01_t04: Skip # Must be a bug in jsshell, test sometimes times out.
LibTest/core/Map/Map_class_A01_t04: Pass, Slow # Issue 8096
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail # co19-roll r706: Please triage this failure.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail # JS engine has not moved to Unicode 6.3 yet.
LibTest/core/Stopwatch/elapsedInMs_A01_t01: RuntimeError # Issue 7728, timer not supported in jsshell
LibTest/core/Stopwatch/elapsedInUs_A01_t01: RuntimeError # Issue 7728, timer not supported in jsshell
LibTest/core/Stopwatch/elapsedTicks_A01_t01: RuntimeError # Please triage this failure
@@ -676,7 +675,7 @@
LibTest/core/Uri/encodeQueryComponent_A01_t02: Skip # Issue 18093, timeout.
[ $compiler == dart2js && $jscl ]
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail, Pass # issue 3333
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail, Pass # Does not work with old JS engines that are on Unicode 6.2
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError, OK # This is not rejected by V8. Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
@@ -1444,7 +1443,6 @@
LayoutTests/fast/xpath/py-dom-xpath/paths_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xpath/reverse-axes_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xsl/default-html_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Pass,RuntimeError # https://github.com/dart-lang/sdk/issues/29814
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
@@ -2253,7 +2251,7 @@
LayoutTests/fast/xpath/py-dom-xpath/paths_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xpath/reverse-axes_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xsl/default-html_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # DRT may not be on Unicode 6.2
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Please triage this failure
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Please triage this failure
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Please triage this failure
@@ -4902,7 +4900,7 @@
LayoutTests/fast/xpath/py-dom-xpath/paths_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xpath/reverse-axes_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xsl/default-html_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # Safari may not be on Unicode 6.3
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
@@ -6630,7 +6628,7 @@
LibTest/async/Stream/Stream.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
LibTest/async/Timer/Timer.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
LibTest/async/Timer/Timer_A01_t01: Pass, RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # IE11 may not be on Unicode 6.3
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
diff --git a/pkg/testing/lib/src/stdio_process.dart b/pkg/testing/lib/src/stdio_process.dart
index f6c5878..1004a59 100644
--- a/pkg/testing/lib/src/stdio_process.dart
+++ b/pkg/testing/lib/src/stdio_process.dart
@@ -43,8 +43,10 @@
static Future<StdioProcess> run(String executable, List<String> arguments,
{String input,
Duration timeout: const Duration(seconds: 60),
- bool suppressOutput: true}) async {
- Process process = await Process.start(executable, arguments);
+ bool suppressOutput: true,
+ bool runInShell: false}) async {
+ Process process =
+ await Process.start(executable, arguments, runInShell: runInShell);
Timer timer;
StringBuffer sb = new StringBuffer();
if (timeout != null) {
diff --git a/pkg/vm/bin/dump_kernel.dart b/pkg/vm/bin/dump_kernel.dart
index e2bbb61..28499bc 100644
--- a/pkg/vm/bin/dump_kernel.dart
+++ b/pkg/vm/bin/dump_kernel.dart
@@ -9,6 +9,8 @@
show BinaryBuilderWithMetadata;
import 'package:vm/metadata/direct_call.dart' show DirectCallMetadataRepository;
+import 'package:vm/metadata/inferred_type.dart'
+ show InferredTypeMetadataRepository;
final String _usage = '''
Usage: dump_kernel input.dill output.txt
@@ -28,6 +30,7 @@
// Register VM-specific metadata.
program.addMetadataRepository(new DirectCallMetadataRepository());
+ program.addMetadataRepository(new InferredTypeMetadataRepository());
final List<int> bytes = new File(input).readAsBytesSync();
new BinaryBuilderWithMetadata(bytes).readProgram(program);
diff --git a/pkg/vm/lib/metadata/inferred_type.dart b/pkg/vm/lib/metadata/inferred_type.dart
new file mode 100644
index 0000000..dafb370
--- /dev/null
+++ b/pkg/vm/lib/metadata/inferred_type.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2017, 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.
+
+library vm.metadata.inferred_type;
+
+import 'package:kernel/ast.dart';
+
+/// Metadata for annotating nodes with an inferred type information.
+class InferredType {
+ final Reference _concreteClassReference;
+ final bool nullable;
+
+ InferredType(Class concreteClass, bool nullable)
+ : this._byReference(getClassReference(concreteClass), nullable);
+
+ InferredType._byReference(this._concreteClassReference, this.nullable);
+
+ Class get concreteClass => _concreteClassReference?.asClass;
+
+ @override
+ String toString() =>
+ "${concreteClass != null ? concreteClass : '!'}${nullable ? '?' : ''}";
+}
+
+/// Repository for [InferredType].
+class InferredTypeMetadataRepository extends MetadataRepository<InferredType> {
+ @override
+ final String tag = 'vm.inferred-type.metadata';
+
+ @override
+ final Map<TreeNode, InferredType> mapping = <TreeNode, InferredType>{};
+
+ @override
+ void writeToBinary(InferredType metadata, BinarySink sink) {
+ sink.writeCanonicalNameReference(
+ getCanonicalNameOfClass(metadata.concreteClass));
+ sink.writeByte(metadata.nullable ? 1 : 0);
+ }
+
+ @override
+ InferredType readFromBinary(BinarySource source) {
+ final concreteClassReference =
+ source.readCanonicalNameReference()?.getReference();
+ final nullable = (source.readByte() != 0);
+ return new InferredType._byReference(concreteClassReference, nullable);
+ }
+}
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 871c63b..cd3cafb 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -24,7 +24,6 @@
// organized in several categories:
//
// === Correctness ===
-// * Add unit tests!!!
// * Support dynamic calls via getters & dynamic tear-offs.
// * Re-evaluate field initializer if its dependency changes (avoid
// re-using cached value).
@@ -350,6 +349,12 @@
final Set<Class> allocatedClasses = new Set<Class>();
final Map<Class, _ClassData> classes = <Class, _ClassData>{};
+ /// Class hierarchy is sealed after analysis is finished.
+ /// Once it is sealed, no new allocated classes may be added and no new
+ /// targets of invocations may appear.
+ /// It also means that there is no need to add dependencies on classes.
+ bool _sealed = false;
+
final Map<Member, _ProcedureInvocationHandler> _procedureHandlers =
<Member, _ProcedureInvocationHandler>{};
final Map<Field, _FieldGetterInvocationHandler> _fieldGetterHandlers =
@@ -375,6 +380,7 @@
void addAllocatedClass(Class cl) {
assertx(!cl.isAbstract);
+ assertx(!_sealed);
if (allocatedClasses.add(cl)) {
final _ClassData classData = getClassData(cl);
@@ -392,10 +398,16 @@
}
}
+ void seal() {
+ _sealed = true;
+ }
+
@override
bool isSubtype(DartType subType, DartType superType) {
- tracePrint(
- "isSubtype for sub = $subType (${subType.runtimeType}), sup = $superType (${superType.runtimeType})");
+ if (kPrintTrace) {
+ tracePrint("isSubtype for sub = $subType (${subType
+ .runtimeType}), sup = $superType (${superType.runtimeType})");
+ }
if (subType == superType) {
return true;
}
@@ -459,7 +471,9 @@
_ClassData classData = getClassData((base as InterfaceType).classNode);
final allocatedSubtypes = classData.allocatedSubtypes;
- classData.addDependentInvocation(_typeFlowAnalysis.currentInvocation);
+ if (!_sealed) {
+ classData.addDependentInvocation(_typeFlowAnalysis.currentInvocation);
+ }
final int numSubTypes = allocatedSubtypes.length;
@@ -515,6 +529,7 @@
}
void _addDynamicTarget(Class c, _DynamicInvocationHandler handler) {
+ assertx(!_sealed);
final selector = handler.selector;
final member = hierarchy.getDispatchTarget(c, selector.name,
setter: selector.isSetter);
@@ -815,6 +830,7 @@
void process() {
workList.process();
+ hierarchyCache.seal();
}
bool isMemberUsed(Member member) => hierarchyCache.isMemberUsed(member);
diff --git a/pkg/vm/lib/transformations/type_flow/entry_points.json b/pkg/vm/lib/transformations/type_flow/entry_points.json
index 17b472c..95d1f01 100644
--- a/pkg/vm/lib/transformations/type_flow/entry_points.json
+++ b/pkg/vm/lib/transformations/type_flow/entry_points.json
@@ -501,6 +501,11 @@
"action": "create-instance"
},
{
+ "library": "dart:async",
+ "name": "_ensureScheduleImmediate",
+ "action": "call"
+ },
+ {
"library": "dart:core",
"name": "_completeDeferredLoads",
"action": "call"
@@ -631,6 +636,11 @@
},
{
"library": "dart:isolate",
+ "name": "_runPendingImmediateCallback",
+ "action": "call"
+ },
+ {
+ "library": "dart:isolate",
"name": "_startIsolate",
"action": "call"
},
@@ -692,11 +702,6 @@
"action": "call"
},
{
- "library": "dart:isolate",
- "name": "_runPendingImmediateCallback",
- "action": "call"
- },
- {
"library": "dart:core",
"class": "Error",
"name": "_stackTrace",
@@ -766,6 +771,21 @@
"action": "call"
},
{
+ "library": "dart:cli",
+ "name": "_getWaitForEvent",
+ "action": "call"
+ },
+ {
+ "library": "dart:cli",
+ "name": "_waitForEventClosure",
+ "action": "get"
+ },
+ {
+ "library": "dart:cli",
+ "name": "_waitForEventClosure",
+ "action": "set"
+ },
+ {
"library": "dart:io",
"name": "_getUriBaseClosure",
"action": "call"
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index cb5aca1..1272b69 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -155,13 +155,14 @@
}
argTypes[i] = type;
}
+ setReachable();
if (selector is! DirectSelector) {
_observeReceiverType(argTypes[0]);
}
final Type result = callHandler.applyCall(this, selector,
new Args<Type>(argTypes, names: args.names), isResultUsed);
if (isResultUsed) {
- _observeResultType(result);
+ _observeResultType(result, typeHierarchy);
}
return result;
}
@@ -169,12 +170,13 @@
// --- Inferred call site information. ---
int _flags = 0;
+ Type _resultType = const EmptyType();
static const int kMonomorphic = (1 << 0);
static const int kPolymorphic = (1 << 1);
static const int kNullableReceiver = (1 << 2);
static const int kResultUsed = (1 << 3);
- static const int kNullableResult = (1 << 4);
+ static const int kReachable = (1 << 4);
Member _monomorphicTarget;
@@ -188,12 +190,18 @@
bool get isResultUsed => (_flags & kResultUsed) != 0;
- bool get isNullableResult => (_flags & kNullableResult) != 0;
+ bool get isReachable => (_flags & kReachable) != 0;
+
+ Type get resultType => _resultType;
void setResultUsed() {
_flags |= kResultUsed;
}
+ void setReachable() {
+ _flags |= kReachable;
+ }
+
void setPolymorphic() {
_flags = (_flags & ~kMonomorphic) | kPolymorphic;
_monomorphicTarget = null;
@@ -218,11 +226,8 @@
}
}
- void _observeResultType(Type result) {
- if (result is NullableType) {
- _flags |= kNullableResult;
- }
- // TODO(alexmarkov): Record result types.
+ void _observeResultType(Type result, TypeHierarchy typeHierarchy) {
+ _resultType = _resultType.union(result, typeHierarchy);
}
}
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 2947b68..1d19d63 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -16,16 +16,23 @@
import 'analysis.dart';
import 'calls.dart';
import 'summary_collector.dart';
+import 'types.dart';
import 'utils.dart';
import '../devirtualization.dart' show Devirtualization;
import '../../metadata/direct_call.dart';
+import '../../metadata/inferred_type.dart';
const bool kDumpAllSummaries =
const bool.fromEnvironment('global.type.flow.dump.all.summaries');
/// Whole-program type flow analysis and transformation.
/// Assumes strong mode and closed world.
-Program transformProgram(CoreTypes coreTypes, Program program) {
+Program transformProgram(CoreTypes coreTypes, Program program,
+ // TODO(alexmarkov): Pass entry points descriptors from command line.
+ {List<String> entryPointsJSONFiles: const [
+ 'pkg/vm/lib/transformations/type_flow/entry_points.json',
+ 'pkg/vm/lib/transformations/type_flow/entry_points_extra.json',
+ ]}) {
final hierarchy = new ClassHierarchy(program);
final types = new TypeEnvironment(coreTypes, hierarchy, strongMode: true);
final libraryIndex = new LibraryIndex.all(program);
@@ -40,11 +47,7 @@
final analysisStopWatch = new Stopwatch()..start();
final typeFlowAnalysis = new TypeFlowAnalysis(hierarchy, types, libraryIndex,
- // TODO(alexmarkov): Pass entry points descriptors from command line.
- entryPointsJSONFiles: [
- 'pkg/vm/lib/transformations/type_flow/entry_points.json',
- 'pkg/vm/lib/transformations/type_flow/entry_points_extra.json',
- ]);
+ entryPointsJSONFiles: entryPointsJSONFiles);
Procedure main = program.mainMethod;
final Selector mainSelector = new DirectSelector(main);
@@ -59,6 +62,9 @@
new TFADevirtualization(program, typeFlowAnalysis).visitProgram(program);
+ new AnnotateWithInferredTypes(program, typeFlowAnalysis)
+ .visitProgram(program);
+
transformsStopWatch.stop();
statPrint("TF analysis took ${analysisStopWatch.elapsedMilliseconds}ms");
@@ -117,3 +123,91 @@
}
}
}
+
+/// Annotates kernel AST with types inferred by type flow analysis.
+class AnnotateWithInferredTypes extends RecursiveVisitor<Null> {
+ final TypeFlowAnalysis _typeFlowAnalysis;
+ final InferredTypeMetadataRepository _metadata;
+
+ AnnotateWithInferredTypes(Program program, this._typeFlowAnalysis)
+ : _metadata = new InferredTypeMetadataRepository() {
+ program.addMetadataRepository(_metadata);
+ }
+
+ void _annotateNode(TreeNode node) {
+ final callSite = _typeFlowAnalysis.callSite(node);
+ if ((callSite != null) && callSite.isResultUsed && callSite.isReachable) {
+ final resultType = callSite.resultType;
+ assertx(resultType != null);
+
+ Class concreteClass;
+
+ final nullable = resultType is NullableType;
+ if (nullable) {
+ final baseType = (resultType as NullableType).baseType;
+
+ if (baseType == const EmptyType()) {
+ concreteClass = _typeFlowAnalysis.environment.coreTypes.nullClass;
+ } else {
+ concreteClass =
+ baseType.getConcreteClass(_typeFlowAnalysis.hierarchyCache);
+ }
+ } else {
+ concreteClass =
+ resultType.getConcreteClass(_typeFlowAnalysis.hierarchyCache);
+ }
+
+ if ((concreteClass != null) || !nullable) {
+ _metadata.mapping[node] = new InferredType(concreteClass, nullable);
+ }
+ }
+ }
+
+ @override
+ visitMethodInvocation(MethodInvocation node) {
+ _annotateNode(node);
+ super.visitMethodInvocation(node);
+ }
+
+ @override
+ visitPropertyGet(PropertyGet node) {
+ _annotateNode(node);
+ super.visitPropertyGet(node);
+ }
+
+ @override
+ visitDirectMethodInvocation(DirectMethodInvocation node) {
+ _annotateNode(node);
+ super.visitDirectMethodInvocation(node);
+ }
+
+ @override
+ visitDirectPropertyGet(DirectPropertyGet node) {
+ _annotateNode(node);
+ super.visitDirectPropertyGet(node);
+ }
+
+ @override
+ visitSuperMethodInvocation(SuperMethodInvocation node) {
+ _annotateNode(node);
+ super.visitSuperMethodInvocation(node);
+ }
+
+ @override
+ visitSuperPropertyGet(SuperPropertyGet node) {
+ _annotateNode(node);
+ super.visitSuperPropertyGet(node);
+ }
+
+ @override
+ visitStaticInvocation(StaticInvocation node) {
+ _annotateNode(node);
+ super.visitStaticInvocation(node);
+ }
+
+ @override
+ visitStaticGet(StaticGet node) {
+ _annotateNode(node);
+ super.visitStaticGet(node);
+ }
+}
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index a73bdd6..d9d9a68 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -65,7 +65,7 @@
/// instances of all Dart types which extend, mix-in or implement [dartType].
factory Type.cone(DartType dartType) {
dartType = _normalizeDartType(dartType);
- if (dartType == const DynamicType()) {
+ if ((dartType == const DynamicType()) || (dartType == const VoidType())) {
return const AnyType();
} else {
return new ConeType(dartType);
@@ -88,7 +88,7 @@
/// Dart type annotation [dartType].
factory Type.fromStatic(DartType dartType) {
dartType = _normalizeDartType(dartType);
- if (dartType == const DynamicType()) {
+ if ((dartType == const DynamicType()) || (dartType == const VoidType())) {
return new Type.nullable(const AnyType());
} else if (dartType == const BottomType()) {
return new Type.nullable(new Type.empty());
@@ -99,6 +99,8 @@
@override
DartType get staticType;
+ Class getConcreteClass(TypeHierarchy typeHierarchy) => null;
+
@override
Type getComputedType(List<Type> types) => this;
@@ -338,6 +340,11 @@
DartType get staticType => dartType;
@override
+ Class getConcreteClass(TypeHierarchy typeHierarchy) => typeHierarchy
+ .specializeTypeCone(dartType)
+ .getConcreteClass(typeHierarchy);
+
+ @override
int get hashCode => (dartType.hashCode + 37) & kHashMask;
@override
@@ -365,6 +372,10 @@
if (typeHierarchy.isSubtype(this.dartType, other.dartType)) {
return other;
}
+ } else if (other is ConcreteType) {
+ if (typeHierarchy.isSubtype(other.dartType, this.dartType)) {
+ return this;
+ }
}
return typeHierarchy
.specializeTypeCone(dartType)
@@ -414,6 +425,12 @@
DartType get staticType => dartType;
@override
+ Class getConcreteClass(TypeHierarchy typeHierarchy) =>
+ (dartType is InterfaceType)
+ ? (dartType as InterfaceType).classNode
+ : null;
+
+ @override
int get hashCode => (dartType.hashCode ^ 0x1234) & kHashMask;
@override
diff --git a/pkg/vm/test/transformations/type_flow/common_test_utils.dart b/pkg/vm/test/transformations/type_flow/common_test_utils.dart
new file mode 100644
index 0000000..01834d6
--- /dev/null
+++ b/pkg/vm/test/transformations/type_flow/common_test_utils.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2018, 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.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:front_end/src/api_prototype/front_end.dart';
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+ show computePlatformBinariesLocation;
+import 'package:kernel/ast.dart';
+import 'package:kernel/target/targets.dart';
+import 'package:kernel/target/vm.dart';
+import 'package:test/test.dart';
+
+const bool kDumpActualResult = const bool.fromEnvironment('dump.actual.result');
+
+Future<Program> compileTestCaseToKernelProgram(Uri sourceUri) async {
+ final platformKernel =
+ computePlatformBinariesLocation().resolve('vm_platform_strong.dill');
+ final options = new CompilerOptions()
+ ..strongMode = true
+ ..target = new VmTarget(new TargetFlags(strongMode: true))
+ ..linkedDependencies = <Uri>[platformKernel]
+ ..reportMessages = true
+ ..onError = (CompilationMessage error) {
+ fail("Compilation error: ${error}");
+ };
+ return kernelForProgram(sourceUri, options);
+}
+
+void compareResultWithExpectationsFile(Uri source, String actual) {
+ final expectFile = new File(source.toFilePath() + '.expect');
+ final expected = expectFile.existsSync() ? expectFile.readAsStringSync() : '';
+
+ if (actual != expected) {
+ if (kDumpActualResult) {
+ new File(source.toFilePath() + '.actual').writeAsStringSync(actual);
+ }
+ expect(actual, equals(expected), reason: "Test case: $source");
+ }
+}
diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
new file mode 100644
index 0000000..9e051d2
--- /dev/null
+++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2018, 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.
+
+import 'dart:io';
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/type_environment.dart';
+import 'package:test/test.dart';
+import 'package:vm/transformations/type_flow/native_code.dart';
+import 'package:vm/transformations/type_flow/summary_collector.dart';
+
+import 'common_test_utils.dart';
+
+final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
+
+class PrintSummaries extends RecursiveVisitor<Null> {
+ final SummaryCollector _summaryColector;
+ final StringBuffer _buf = new StringBuffer();
+
+ PrintSummaries(TypeEnvironment environment)
+ : _summaryColector = new SummaryCollector(
+ environment, new EntryPointsListener(), new NativeCodeOracle(null));
+
+ String print(TreeNode node) {
+ visitLibrary(node);
+ return _buf.toString();
+ }
+
+ @override
+ defaultMember(Member member) {
+ if (!member.isAbstract) {
+ _buf.writeln("------------ $member ------------");
+ _buf.writeln(_summaryColector.createSummary(member));
+ }
+ }
+}
+
+runTestCase(Uri source) async {
+ final Program program = await compileTestCaseToKernelProgram(source);
+ final Library library = program.mainMethod.enclosingLibrary;
+
+ // Make sure the library name is the same and does not depend on the order
+ // of test cases.
+ library.name = '#lib';
+
+ final typeEnvironment =
+ new TypeEnvironment(new CoreTypes(program), new ClassHierarchy(program));
+
+ final actual = new PrintSummaries(typeEnvironment).print(library);
+
+ compareResultWithExpectationsFile(source, actual);
+}
+
+main() {
+ group('collect-summary', () {
+ final testCasesDir = new Directory(
+ pkgVmDir + '/testcases/transformations/type_flow/summary_collector');
+
+ for (var entry
+ in testCasesDir.listSync(recursive: true, followLinks: false)) {
+ if (entry.path.endsWith(".dart")) {
+ test(entry.path, () => runTestCase(entry.uri));
+ }
+ }
+ });
+}
diff --git a/pkg/vm/test/transformations/type_flow/transformer_test.dart b/pkg/vm/test/transformations/type_flow/transformer_test.dart
new file mode 100644
index 0000000..61de1ec
--- /dev/null
+++ b/pkg/vm/test/transformations/type_flow/transformer_test.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2018, 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.
+
+import 'dart:io';
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/kernel.dart';
+import 'package:kernel/text/ast_to_text.dart';
+import 'package:test/test.dart';
+import 'package:vm/transformations/type_flow/transformer.dart'
+ show transformProgram;
+
+import 'common_test_utils.dart';
+
+final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
+
+runTestCase(Uri source) async {
+ Program program = await compileTestCaseToKernelProgram(source);
+
+ // Make sure the library name is the same and does not depend on the order
+ // of test cases.
+ program.mainMethod.enclosingLibrary.name = '#lib';
+
+ final coreTypes = new CoreTypes(program);
+
+ program = transformProgram(coreTypes, program, entryPointsJSONFiles: [
+ pkgVmDir + '/lib/transformations/type_flow/entry_points.json',
+ pkgVmDir + '/lib/transformations/type_flow/entry_points_extra.json',
+ ]);
+
+ final StringBuffer buffer = new StringBuffer();
+ new Printer(buffer, showExternal: false, showMetadata: true)
+ .writeLibraryFile(program.mainMethod.enclosingLibrary);
+ final actual = buffer.toString();
+
+ compareResultWithExpectationsFile(source, actual);
+}
+
+main() {
+ group('transform-program', () {
+ final testCasesDir = new Directory(
+ pkgVmDir + '/testcases/transformations/type_flow/transformer');
+
+ for (var entry
+ in testCasesDir.listSync(recursive: true, followLinks: false)) {
+ if (entry.path.endsWith(".dart")) {
+ test(entry.path, () => runTestCase(entry.uri));
+ }
+ }
+ });
+}
diff --git a/pkg/vm/test/transformations/type_flow/types_test.dart b/pkg/vm/test/transformations/type_flow/types_test.dart
new file mode 100644
index 0000000..7d60091
--- /dev/null
+++ b/pkg/vm/test/transformations/type_flow/types_test.dart
@@ -0,0 +1,383 @@
+// Copyright (c) 2018, 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.
+
+import 'dart:core' hide Type;
+
+import 'package:kernel/ast.dart';
+import 'package:test/test.dart';
+import 'package:vm/transformations/type_flow/types.dart';
+
+class TestTypeHierarchy implements TypeHierarchy {
+ final Map<DartType, List<DartType>> subtypes;
+ final Map<DartType, Type> specializations;
+
+ TestTypeHierarchy(this.subtypes, this.specializations);
+
+ @override
+ bool isSubtype(DartType subType, DartType superType) {
+ return subtypes[superType].contains(subType);
+ }
+
+ @override
+ Type specializeTypeCone(DartType base) {
+ Type result = specializations[base];
+ expect(result, isNotNull,
+ reason: "specializeTypeCone($base) is not defined");
+ return result;
+ }
+}
+
+main() {
+ test('factory-constructors', () {
+ Class c1 = new Class(name: 'C1');
+ Class c2 = new Class(name: 'C2', typeParameters: [new TypeParameter('E')]);
+ InterfaceType t1 = new InterfaceType(c1);
+ InterfaceType t2Raw = new InterfaceType(c2);
+ InterfaceType t2Generic = new InterfaceType(c2, [t1]);
+ FunctionType f1 = new FunctionType([t1], const VoidType());
+
+ expect(new Type.empty(), equals(const EmptyType()));
+
+ expect(new Type.cone(const DynamicType()), equals(const AnyType()));
+ expect(new Type.cone(t1), equals(new ConeType(t1)));
+ expect(new Type.cone(t2Raw), equals(new ConeType(t2Raw)));
+ expect(new Type.cone(t2Generic), equals(new ConeType(t2Raw)));
+ expect(new Type.cone(f1), equals(const AnyType()));
+
+ expect(new Type.concrete(t1), equals(new ConcreteType(t1)));
+ expect(new Type.concrete(t2Raw), equals(new ConcreteType(t2Raw)));
+ expect(new Type.concrete(t2Generic), equals(new ConcreteType(t2Raw)));
+
+ expect(new Type.nullable(new Type.empty()),
+ equals(new NullableType(new EmptyType())));
+ expect(new Type.nullable(new Type.cone(t1)),
+ equals(new NullableType(new ConeType(t1))));
+ expect(new Type.nullable(new Type.concrete(t1)),
+ equals(new NullableType(new ConcreteType(t1))));
+
+ expect(new Type.fromStatic(const DynamicType()),
+ equals(new NullableType(new AnyType())));
+ expect(new Type.fromStatic(const BottomType()),
+ equals(new NullableType(new EmptyType())));
+ expect(new Type.fromStatic(t1), equals(new NullableType(new ConeType(t1))));
+ expect(new Type.fromStatic(t2Raw),
+ equals(new NullableType(new ConeType(t2Raw))));
+ expect(new Type.fromStatic(t2Generic),
+ equals(new NullableType(new ConeType(t2Raw))));
+ });
+
+ test('static-type', () {
+ InterfaceType classType = new InterfaceType(new Class(name: 'C'));
+ FunctionType funcType = new FunctionType([], const VoidType());
+
+ // [T, T.staticType]
+ final testCases = [
+ [new Type.cone(classType), classType],
+ [new Type.cone(funcType), const DynamicType()],
+ [new Type.concrete(classType), classType],
+ [new AnyType(), const DynamicType()],
+ [new Type.nullable(new Type.empty()), const BottomType()],
+ [new Type.nullable(new Type.cone(classType)), classType],
+ [new Type.nullable(new Type.concrete(classType)), classType],
+ [new Type.nullable(new AnyType()), const DynamicType()],
+ [new Type.fromStatic(const DynamicType()), const DynamicType()],
+ [new Type.fromStatic(const BottomType()), const BottomType()],
+ [new Type.fromStatic(classType), classType],
+ [new Type.fromStatic(funcType), const DynamicType()],
+ ];
+
+ for (List testCase in testCases) {
+ Type type = testCase[0] as Type;
+ DartType staticType = testCase[1] as DartType;
+
+ expect(type.staticType, equals(staticType),
+ reason:
+ "Test case: ${type}.staticType is expected to be $staticType");
+ }
+ });
+
+ test('union-intersection', () {
+ // T1 <: T3, T2 <: T3
+
+ InterfaceType t1 = new InterfaceType(new Class(name: 'T1'));
+ InterfaceType t2 = new InterfaceType(new Class(name: 'T2'));
+ InterfaceType t3 = new InterfaceType(new Class(name: 'T3'));
+ InterfaceType t4 = new InterfaceType(new Class(name: 'T4'));
+
+ final empty = new EmptyType();
+ final any = new AnyType();
+ final concreteT1 = new ConcreteType(t1);
+ final concreteT2 = new ConcreteType(t2);
+ final concreteT3 = new ConcreteType(t3);
+ final concreteT4 = new ConcreteType(t4);
+ final coneT1 = new ConeType(t1);
+ final coneT2 = new ConeType(t2);
+ final coneT3 = new ConeType(t3);
+ final coneT4 = new ConeType(t4);
+ final setT12 = new SetType([concreteT1, concreteT2].toSet());
+ final setT14 = new SetType([concreteT1, concreteT4].toSet());
+ final setT23 = new SetType([concreteT2, concreteT3].toSet());
+ final setT34 = new SetType([concreteT3, concreteT4].toSet());
+ final setT123 = new SetType([concreteT1, concreteT2, concreteT3].toSet());
+ final setT124 = new SetType([concreteT1, concreteT2, concreteT4].toSet());
+ final setT1234 =
+ new SetType([concreteT1, concreteT2, concreteT3, concreteT4].toSet());
+ final nullableEmpty = new Type.nullable(empty);
+ final nullableAny = new Type.nullable(any);
+ final nullableConcreteT1 = new Type.nullable(concreteT1);
+ final nullableConcreteT2 = new Type.nullable(concreteT2);
+ final nullableConcreteT3 = new Type.nullable(concreteT3);
+ final nullableConeT1 = new Type.nullable(coneT1);
+ final nullableConeT3 = new Type.nullable(coneT3);
+ final nullableConeT4 = new Type.nullable(coneT4);
+ final nullableSetT12 = new Type.nullable(setT12);
+ final nullableSetT14 = new Type.nullable(setT14);
+ final nullableSetT23 = new Type.nullable(setT23);
+ final nullableSetT34 = new Type.nullable(setT34);
+ final nullableSetT123 = new Type.nullable(setT123);
+ final nullableSetT124 = new Type.nullable(setT124);
+ final nullableSetT1234 = new Type.nullable(setT1234);
+
+ // [A, B, union, intersection]
+ final testCases = [
+ // empty
+ [empty, empty, empty, empty],
+ [empty, any, any, empty],
+ [empty, concreteT1, concreteT1, empty],
+ [empty, coneT1, coneT1, empty],
+ [empty, setT12, setT12, empty],
+ [empty, nullableEmpty, nullableEmpty, empty],
+ [empty, nullableAny, nullableAny, empty],
+ [empty, nullableConcreteT1, nullableConcreteT1, empty],
+ [empty, nullableConeT1, nullableConeT1, empty],
+ [empty, nullableSetT12, nullableSetT12, empty],
+ // any
+ [any, any, any, any],
+ [any, concreteT1, any, concreteT1],
+ [any, coneT1, any, coneT1],
+ [any, setT12, any, setT12],
+ [any, nullableEmpty, nullableAny, empty],
+ [any, nullableAny, nullableAny, any],
+ [any, nullableConcreteT1, nullableAny, concreteT1],
+ [any, nullableConeT1, nullableAny, coneT1],
+ [any, nullableSetT12, nullableAny, setT12],
+ // nullableEmpty
+ [nullableEmpty, concreteT1, nullableConcreteT1, empty],
+ [nullableEmpty, coneT1, nullableConeT1, empty],
+ [nullableEmpty, setT12, nullableSetT12, empty],
+ [nullableEmpty, nullableEmpty, nullableEmpty, nullableEmpty],
+ [nullableEmpty, nullableAny, nullableAny, nullableEmpty],
+ [nullableEmpty, nullableConcreteT1, nullableConcreteT1, nullableEmpty],
+ [nullableEmpty, nullableConeT1, nullableConeT1, nullableEmpty],
+ [nullableEmpty, nullableSetT12, nullableSetT12, nullableEmpty],
+ // nullableAny
+ [nullableAny, concreteT1, nullableAny, concreteT1],
+ [nullableAny, coneT1, nullableAny, coneT1],
+ [nullableAny, setT12, nullableAny, setT12],
+ [nullableAny, nullableAny, nullableAny, nullableAny],
+ [nullableAny, nullableConcreteT1, nullableAny, nullableConcreteT1],
+ [nullableAny, nullableConeT1, nullableAny, nullableConeT1],
+ [nullableAny, nullableSetT12, nullableAny, nullableSetT12],
+ // concrete
+ [concreteT1, concreteT1, concreteT1, concreteT1],
+ [concreteT1, concreteT2, setT12, empty],
+ [concreteT1, coneT1, coneT1, concreteT1],
+ [concreteT1, coneT2, setT12, empty],
+ [concreteT1, coneT3, coneT3, concreteT1],
+ [concreteT1, coneT4, setT14, empty],
+ [concreteT1, setT12, setT12, concreteT1],
+ [concreteT1, setT23, setT123, empty],
+ [concreteT1, nullableConcreteT1, nullableConcreteT1, concreteT1],
+ [concreteT1, nullableConcreteT2, nullableSetT12, empty],
+ [concreteT1, nullableConeT1, nullableConeT1, concreteT1],
+ [concreteT1, nullableConeT3, nullableConeT3, concreteT1],
+ [concreteT1, nullableConeT4, nullableSetT14, empty],
+ [concreteT1, nullableSetT12, nullableSetT12, concreteT1],
+ [concreteT1, nullableSetT23, nullableSetT123, empty],
+ // cone
+ [coneT1, coneT1, coneT1, coneT1],
+ [coneT1, coneT2, setT12, empty],
+ [coneT1, coneT3, coneT3, coneT1],
+ [coneT3, coneT4, setT1234, empty],
+ [coneT1, setT12, setT12, concreteT1],
+ [coneT1, setT23, setT123, empty],
+ [coneT3, setT12, setT123, setT12],
+ [coneT3, setT1234, setT1234, setT123],
+ [coneT1, nullableConcreteT1, nullableConeT1, concreteT1],
+ [coneT1, nullableConcreteT2, nullableSetT12, empty],
+ [coneT3, nullableConcreteT2, nullableConeT3, concreteT2],
+ [coneT1, nullableConeT1, nullableConeT1, coneT1],
+ [coneT1, nullableConeT3, nullableConeT3, coneT1],
+ [coneT1, nullableConeT4, nullableSetT14, empty],
+ [coneT1, nullableSetT12, nullableSetT12, concreteT1],
+ [coneT3, nullableSetT23, nullableSetT123, setT23],
+ // set
+ [setT12, setT12, setT12, setT12],
+ [setT12, setT123, setT123, setT12],
+ [setT12, setT23, setT123, concreteT2],
+ [setT12, setT34, setT1234, empty],
+ [setT12, nullableConcreteT1, nullableSetT12, concreteT1],
+ [setT12, nullableConcreteT3, nullableSetT123, empty],
+ [setT12, nullableConeT1, nullableSetT12, concreteT1],
+ [setT12, nullableConeT3, nullableSetT123, setT12],
+ [setT12, nullableConeT4, nullableSetT124, empty],
+ [setT12, nullableSetT12, nullableSetT12, setT12],
+ [setT12, nullableSetT123, nullableSetT123, setT12],
+ [setT12, nullableSetT23, nullableSetT123, concreteT2],
+ [setT12, nullableSetT34, nullableSetT1234, empty],
+ // nullableConcrete
+ [
+ nullableConcreteT1,
+ nullableConcreteT1,
+ nullableConcreteT1,
+ nullableConcreteT1
+ ],
+ [nullableConcreteT1, nullableConcreteT2, nullableSetT12, nullableEmpty],
+ [nullableConcreteT1, nullableConeT1, nullableConeT1, nullableConcreteT1],
+ [nullableConcreteT1, nullableConeT3, nullableConeT3, nullableConcreteT1],
+ [nullableConcreteT1, nullableConeT4, nullableSetT14, nullableEmpty],
+ [nullableConcreteT1, nullableSetT12, nullableSetT12, nullableConcreteT1],
+ [nullableConcreteT1, nullableSetT23, nullableSetT123, nullableEmpty],
+ // nullableCone
+ [nullableConeT1, nullableConeT1, nullableConeT1, nullableConeT1],
+ [nullableConeT1, nullableConeT3, nullableConeT3, nullableConeT1],
+ [nullableConeT1, nullableConeT4, nullableSetT14, nullableEmpty],
+ [nullableConeT1, nullableSetT12, nullableSetT12, nullableConcreteT1],
+ [nullableConeT1, nullableSetT23, nullableSetT123, nullableEmpty],
+ [nullableConeT3, nullableSetT14, nullableSetT1234, nullableConcreteT1],
+ // nullableSet
+ [nullableSetT12, nullableSetT12, nullableSetT12, nullableSetT12],
+ [nullableSetT12, nullableSetT23, nullableSetT123, nullableConcreteT2],
+ [nullableSetT12, nullableSetT34, nullableSetT1234, nullableEmpty],
+ ];
+
+ final hierarchy = new TestTypeHierarchy(
+ // subtypes
+ {
+ t1: [t1],
+ t2: [t2],
+ t3: [t1, t2, t3],
+ t4: [t4],
+ },
+ // specializations
+ {
+ t1: concreteT1,
+ t2: concreteT2,
+ t3: setT123,
+ t4: concreteT4
+ });
+
+ for (List testCase in testCases) {
+ Type a = testCase[0] as Type;
+ Type b = testCase[1] as Type;
+ Type union = testCase[2] as Type;
+ Type intersection = testCase[3] as Type;
+
+ expect(a.union(b, hierarchy), equals(union),
+ reason: "Test case: UNION($a, $b) = $union");
+ expect(b.union(a, hierarchy), equals(union),
+ reason: "Test case: UNION($b, $a) = $union");
+ expect(a.intersection(b, hierarchy), equals(intersection),
+ reason: "Test case: INTERSECTION($a, $b) = $intersection");
+ expect(b.intersection(a, hierarchy), equals(intersection),
+ reason: "Test case: INTERSECTION($b, $a) = $intersection");
+ }
+ });
+
+ test('hashcode-equals', () {
+ final c1 = new Class(name: 'C1');
+ final c2 = new Class(name: 'C2');
+ final c3 = new Class(name: 'C3');
+
+ final t1a = new InterfaceType(c1);
+ final t1b = new InterfaceType(c1);
+ final t2 = new InterfaceType(c2);
+ final t3 = new InterfaceType(c3);
+ final f1a = new FunctionType([t1a], const VoidType());
+ final f1b = new FunctionType([t1b], const VoidType());
+ final f2 = new FunctionType([t1a, t1a], const VoidType());
+
+ void eq(dynamic a, dynamic b) {
+ expect(a == b, isTrue, reason: "Test case: $a == $b");
+ expect(a.hashCode == b.hashCode, isTrue,
+ reason: "Test case: ${a}.hashCode == ${b}.hashCode");
+ }
+
+ void ne(dynamic a, dynamic b) {
+ expect(a == b, isFalse, reason: "Test case: $a != $b");
+
+ // Hash codes can be the same, but it is unlikely.
+ expect(a.hashCode == b.hashCode, isFalse,
+ reason: "Test case: ${a}.hashCode != ${b}.hashCode");
+ }
+
+ eq(t1a, t1b);
+ ne(t1a, t2);
+ eq(f1a, f1b);
+ ne(f1a, f2);
+ ne(t1a, f1a);
+
+ eq(new EmptyType(), new EmptyType());
+ ne(new EmptyType(), new AnyType());
+ ne(new EmptyType(), new ConcreteType(t1a));
+ ne(new EmptyType(), new ConeType(t1a));
+ ne(new EmptyType(),
+ new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()));
+ ne(new EmptyType(), new NullableType(new EmptyType()));
+
+ eq(new AnyType(), new AnyType());
+ ne(new AnyType(), new ConcreteType(t1a));
+ ne(new AnyType(), new ConeType(t1a));
+ ne(new AnyType(),
+ new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()));
+ ne(new AnyType(), new NullableType(new EmptyType()));
+
+ eq(new ConcreteType(t1a), new ConcreteType(t1b));
+ eq(new ConcreteType(f1a), new ConcreteType(f1b));
+ ne(new ConcreteType(t1a), new ConcreteType(t2));
+ ne(new ConcreteType(f1a), new ConcreteType(f2));
+ ne(new ConcreteType(t1a), new ConcreteType(f1a));
+ ne(new ConcreteType(t1a), new ConeType(t1a));
+ ne(new ConcreteType(t1a), new ConeType(t2));
+ ne(new ConcreteType(t1a),
+ new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()));
+ ne(new ConcreteType(t1a), new NullableType(new ConcreteType(t1a)));
+
+ eq(new ConeType(t1a), new ConeType(t1b));
+ eq(new ConeType(f1a), new ConeType(f1b));
+ ne(new ConeType(t1a), new ConeType(t2));
+ ne(new ConeType(f1a), new ConeType(f2));
+ ne(new ConeType(t1a), new ConeType(f1a));
+ ne(new ConeType(t1a),
+ new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()));
+ ne(new ConeType(t1a), new NullableType(new ConeType(t1a)));
+
+ eq(new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()),
+ new SetType([new ConcreteType(t2), new ConcreteType(t1b)].toSet()));
+ eq(
+ new SetType([
+ new ConcreteType(t1a),
+ new ConcreteType(t2),
+ new ConcreteType(t3)
+ ].toSet()),
+ new SetType([
+ new ConcreteType(t2),
+ new ConcreteType(t1b),
+ new ConcreteType(t3)
+ ].toSet()));
+ ne(
+ new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()),
+ new SetType([
+ new ConcreteType(t1a),
+ new ConcreteType(t2),
+ new ConcreteType(t3)
+ ].toSet()));
+ ne(new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()),
+ new SetType([new ConcreteType(t1a), new ConcreteType(t3)].toSet()));
+ ne(
+ new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()),
+ new NullableType(new SetType(
+ [new ConcreteType(t1a), new ConcreteType(t2)].toSet())));
+ });
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart
new file mode 100644
index 0000000..06cf7ea
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2018, 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.
+
+abstract class A {
+ void foo1(Object x) {}
+ dynamic get foo2;
+ set foo3(int x);
+}
+
+class B {
+ void bar1(Object arg) {}
+ dynamic get bar2 => null;
+ set bar3(int y) {}
+ int bar4;
+}
+
+class C {
+ interfaceCalls(A aa, Object a2, Object a3, Object a4) {
+ aa.foo1(new B());
+ aa.foo3 = aa.foo2;
+ a4 = aa.foo2(a2, a3, aa.foo1);
+ return a4;
+ }
+
+ dynamicCalls(dynamic aa, Object a2, Object a3, Object a4) {
+ aa.foo1(new B());
+ aa.foo3 = aa.foo2;
+ a4 = aa.foo2(a2, a3, aa.foo1);
+ return a4;
+ }
+}
+
+class D extends B {
+ superCalls(Object a1, Object a2, Object a3, Object a4) {
+ super.bar1(a1);
+ super.bar3 = super.bar4;
+ a4 = super.bar2(a2, a3, super.bar1);
+ return a4;
+ }
+}
+
+main() {}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
new file mode 100644
index 0000000..1e61c59
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
@@ -0,0 +1,78 @@
+------------ #lib::A:: ------------
+%this = _Parameter #0 [#lib::A]
+t1 = _Call direct [dart.core::Object::] (%this)
+RESULT: _T {}?
+------------ #lib::A::foo1 ------------
+%this = _Parameter #0 [#lib::A]
+%x = _Parameter #1 [dart.core::Object]
+RESULT: _T {}?
+------------ #lib::B:: ------------
+%this = _Parameter #0 [#lib::B]
+t1 = _Call direct [dart.core::Object::] (%this)
+RESULT: _T {}?
+------------ #lib::B::bar1 ------------
+%this = _Parameter #0 [#lib::B]
+%arg = _Parameter #1 [dart.core::Object]
+RESULT: _T {}?
+------------ #lib::B::bar2 ------------
+%this = _Parameter #0 [#lib::B]
+RESULT: _T {}?
+------------ #lib::B::bar3 ------------
+%this = _Parameter #0 [#lib::B]
+%y = _Parameter #1 [dart.core::int]
+RESULT: _T {}?
+------------ #lib::B::bar4 ------------
+
+RESULT: _T {}?
+------------ #lib::C:: ------------
+%this = _Parameter #0 [#lib::C]
+t1 = _Call direct [dart.core::Object::] (%this)
+RESULT: _T {}?
+------------ #lib::C::interfaceCalls ------------
+%this = _Parameter #0 [#lib::C]
+%aa = _Parameter #1 [#lib::A]
+%a2 = _Parameter #2 [dart.core::Object]
+%a3 = _Parameter #3 [dart.core::Object]
+%a4 = _Parameter #4 [dart.core::Object]
+t5 = _Call direct [#lib::B::] (_T (#lib::B))
+t6 = _Call [#lib::A::foo1] (%aa, _T (#lib::B))
+t7* = _Call get [#lib::A::foo2] (%aa)
+t8 = _Narrow (t7 to _T (dart.core::int)+?)
+t9 = _Call set [#lib::A::foo3] (%aa, t8)
+t10 = _Call get [#lib::A::foo2] (%aa)
+a4 = _Join [dart.core::Object] (%a4, _T ANY?)
+RESULT: a4
+------------ #lib::C::dynamicCalls ------------
+%this = _Parameter #0 [#lib::C]
+%aa = _Parameter #1 [dynamic]
+%a2 = _Parameter #2 [dart.core::Object]
+%a3 = _Parameter #3 [dart.core::Object]
+%a4 = _Parameter #4 [dart.core::Object]
+t5 = _Call direct [#lib::B::] (_T (#lib::B))
+t6 = _Call dynamic [foo1] (%aa, _T (#lib::B))
+t7* = _Call dynamic get [foo2] (%aa)
+t8 = _Call dynamic set [foo3] (%aa, t7)
+t9* = _Call dynamic get [foo1] (%aa)
+t10* = _Call dynamic [foo2] (%aa, %a2, %a3, t9)
+a4 = _Join [dart.core::Object] (%a4, t10)
+RESULT: a4
+------------ #lib::D:: ------------
+%this = _Parameter #0 [#lib::D]
+t1 = _Call direct [#lib::B::] (%this)
+RESULT: _T {}?
+------------ #lib::D::superCalls ------------
+%this = _Parameter #0 [#lib::D]
+%a1 = _Parameter #1 [dart.core::Object]
+%a2 = _Parameter #2 [dart.core::Object]
+%a3 = _Parameter #3 [dart.core::Object]
+%a4 = _Parameter #4 [dart.core::Object]
+t5 = _Call direct [#lib::B::bar1] (%this, %a1)
+t6* = _Call direct get [#lib::B::bar4] (%this)
+t7 = _Call direct set [#lib::B::bar3] (%this, t6)
+t8* = _Call direct get [#lib::B::bar2] (%this)
+t9* = _Call dynamic [call] (t8, %a2, %a3, _T ANY?)
+a4 = _Join [dart.core::Object] (%a4, t9)
+RESULT: a4
+------------ #lib::main ------------
+
+RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart
new file mode 100644
index 0000000..820ca28
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2018, 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.
+
+main(List<String> args) {
+ print('Hello, world!');
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect
new file mode 100644
index 0000000..2f27227
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect
@@ -0,0 +1,4 @@
+------------ #lib::main ------------
+%args = _Parameter #0 [dart.core::List<dart.core::String>]
+t1 = _Call direct [dart.core::print] (_T (dart.core::String)+)
+RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart
new file mode 100644
index 0000000..753486f
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2018, 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.
+
+bool someStatic;
+
+class A {}
+
+class B {}
+
+Object foo(Object a1, [Object a2]) {
+ if (someStatic) {
+ a1 = new A();
+ }
+ bar(a1, 42);
+ a1 = new B();
+ return (a1 != a2) ? a1 : a2;
+}
+
+int bar(Object a1, int a2) {
+ Object v1 = a1;
+ if (v1 is int) {
+ int v2 = v1 + a2;
+ return v2 * 3;
+ }
+ return -1;
+}
+
+Object loop1(Object a1, Object a2) {
+ Object x = a1;
+ x = loop1(x, a1);
+ x = a2;
+ return x;
+}
+
+int loop2(int x) {
+ for (int i = 0; i < 5; i++) {
+ x = x + 10;
+ }
+ return x;
+}
+
+main() {}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
new file mode 100644
index 0000000..d334286
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
@@ -0,0 +1,50 @@
+------------ #lib::A:: ------------
+%this = _Parameter #0 [#lib::A]
+t1 = _Call direct [dart.core::Object::] (%this)
+RESULT: _T {}?
+------------ #lib::B:: ------------
+%this = _Parameter #0 [#lib::B]
+t1 = _Call direct [dart.core::Object::] (%this)
+RESULT: _T {}?
+------------ #lib::foo ------------
+%a1 = _Parameter #0 [dart.core::Object]
+%a2 = _Parameter #1 [dart.core::Object]
+t2 = _Call direct get [#lib::someStatic] ()
+t3 = _Call direct [#lib::A::] (_T (#lib::A))
+a1 = _Join [dart.core::Object] (%a1, _T (#lib::A), _T (#lib::B))
+t5 = _Call direct [#lib::bar] (a1, _T (dart.core::int)+)
+t6 = _Call direct [#lib::B::] (_T (#lib::B))
+a2 = _Join [dart.core::Object] (_T {}?, %a2)
+t8 = _Call [dart.core::Object::==] (a1, a2)
+t9 = _Join [dart.core::Object] (a1, a2)
+t10 = _Narrow (t9 to _T (dart.core::Object)+?)
+RESULT: t10
+------------ #lib::bar ------------
+%a1 = _Parameter #0 [dart.core::Object]
+%a2 = _Parameter #1 [dart.core::int]
+t2 = _Narrow (%a1 to _T (dart.core::int)+)
+t3* = _Call [dart.core::num::+] (t2, %a2)
+t4* = _Call [dart.core::num::*] (t3, _T (dart.core::int)+)
+t5* = _Call [dart.core::int::unary-] (_T (dart.core::int)+)
+%result = _Join [dart.core::int] (t4, t5)
+RESULT: %result
+------------ #lib::loop1 ------------
+%a1 = _Parameter #0 [dart.core::Object]
+%a2 = _Parameter #1 [dart.core::Object]
+t2* = _Call direct [#lib::loop1] (_T (dart.core::Object)+?, %a1)
+x = _Join [dart.core::Object] (%a1, t2, %a2)
+RESULT: x
+------------ #lib::loop2 ------------
+%x = _Parameter #0 [dart.core::int]
+t1* = _Call [dart.core::num::+] (_T (dart.core::int)+?, _T (dart.core::int)+)
+i = _Join [dart.core::int] (_T (dart.core::int)+, t1)
+t3 = _Call [dart.core::num::<] (i, _T (dart.core::int)+)
+t4* = _Call [dart.core::num::+] (_T (dart.core::int)+?, _T (dart.core::int)+)
+x = _Join [dart.core::int] (%x, t4)
+RESULT: x
+------------ #lib::main ------------
+
+RESULT: _T {}?
+------------ #lib::someStatic ------------
+
+RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart
new file mode 100644
index 0000000..e1fd3c5
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart
@@ -0,0 +1,44 @@
+import 'dart:typed_data';
+
+class _Vector {
+ _Vector(int size)
+ : _offset = 0,
+ _length = size,
+ _elements = new Float64List(size);
+
+ _Vector.fromVOL(List<double> values, int offset, int length)
+ : _offset = offset,
+ _length = length,
+ _elements = values;
+
+ final int _offset;
+
+ final int _length;
+
+ final List<double> _elements;
+
+ double operator [](int i) => _elements[i + _offset];
+ void operator []=(int i, double value) {
+ _elements[i + _offset] = value;
+ }
+
+ double operator *(_Vector a) {
+ double result = 0.0;
+ for (int i = 0; i < _length; i += 1) result += this[i] * a[i];
+ return result;
+ }
+}
+
+_Vector v = new _Vector(10);
+double x = 0.0;
+
+main(List<String> args) {
+ Stopwatch timer = new Stopwatch()..start();
+
+ for (int i = 0; i < 100000000; i++) {
+ x = x + v * v;
+ }
+
+ timer.stop();
+ print("Elapsed ${timer.elapsedMilliseconds}ms, result $x");
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
new file mode 100644
index 0000000..e409910
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
@@ -0,0 +1,37 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "dart:typed_data" as typ;
+
+class _Vector extends core::Object {
+ final field core::int _offset;
+ final field core::int _length;
+ final field core::List<core::double> _elements;
+ constructor •(core::int size) → void
+ : self::_Vector::_offset = 0, self::_Vector::_length = size, self::_Vector::_elements = [@vm.inferred-type.metadata=dart.typed_data::_Float64List] typ::Float64List::•(size), super core::Object::•()
+ ;
+ constructor fromVOL(core::List<core::double> values, core::int offset, core::int length) → void
+ : self::_Vector::_offset = offset, self::_Vector::_length = length, self::_Vector::_elements = values, super core::Object::•()
+ throw "TFA Error: #lib::_Vector::fromVOL";
+ operator [](core::int i) → core::double
+ return [@vm.direct-call.metadata=dart.typed_data::_Float64List::[]] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.direct-call.metadata=#lib::_Vector::_elements??] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}.{core::List::[]}(i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector::_offset??] [@vm.inferred-type.metadata=!] this.{self::_Vector::_offset}));
+ operator []=(core::int i, core::double value) → void {
+ [@vm.direct-call.metadata=#lib::_Vector::_elements??] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}.{core::List::[]=}([@vm.inferred-type.metadata=!] i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector::_offset??] [@vm.inferred-type.metadata=!] this.{self::_Vector::_offset}), value);
+ }
+ operator *(self::_Vector a) → core::double {
+ core::double result = 0.0;
+ for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=!] this.{self::_Vector::_length}); i = i.{core::num::+}(1))
+ result = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double] result.{core::double::+}([@vm.direct-call.metadata=dart.core::_Double::*] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.direct-call.metadata=#lib::_Vector::[]] [@vm.inferred-type.metadata=dart.core::_Double] this.{self::_Vector::[]}(i).{core::double::*}([@vm.direct-call.metadata=#lib::_Vector::[]] [@vm.inferred-type.metadata=dart.core::_Double] a.{self::_Vector::[]}(i)));
+ return result;
+ }
+}
+static field self::_Vector v = new self::_Vector::•(10);
+static field core::double x = 0.0;
+static method main(core::List<core::String> args) → dynamic {
+ core::Stopwatch timer = let final core::Stopwatch #t1 = new core::Stopwatch::•() in let final dynamic #t2 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] #t1.{core::Stopwatch::start}() in #t1;
+ for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] i.{core::num::<}(100000000); i = i.{core::num::+}(1)) {
+ self::x = [@vm.direct-call.metadata=dart.core::_Double::+] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=dart.core::_Double] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector::*] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=#lib::_Vector] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector] self::v));
+ }
+ [@vm.direct-call.metadata=dart.core::Stopwatch::stop] timer.{core::Stopwatch::stop}();
+ core::print("Elapsed ${[@vm.direct-call.metadata=dart.core::Stopwatch::elapsedMilliseconds] timer.{core::Stopwatch::elapsedMilliseconds}}ms, result ${self::x}");
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart
new file mode 100644
index 0000000..9fa7451
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2018, 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.
+
+abstract class A {
+ int foo();
+}
+
+class B extends A {
+ int foo() => 1;
+}
+
+class C implements A {
+ int foo() => 2;
+}
+
+class D extends C {}
+
+class E {
+ String toString() => 'D';
+}
+
+void callerA1(A aa) {
+ aa.foo();
+}
+
+void callerA2(A aa) {
+ aa.foo();
+}
+
+void callerA3(A aa) {
+ aa.foo();
+}
+
+void callerA4(A aa) {
+ aa.foo();
+}
+
+void callerE1(x) {
+ x.toString();
+}
+
+void callerE2(x) {
+ x.toString();
+}
+
+A dd;
+E ee = new E();
+
+main(List<String> args) {
+ callerA1(new B());
+ callerA1(new C());
+ callerA2(new B());
+ callerA3(new C());
+ callerA4(dd);
+ dd = new D();
+
+ callerE1('abc');
+ callerE2(ee);
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
new file mode 100644
index 0000000..8b353eb
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
@@ -0,0 +1,66 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → core::int;
+}
+class B extends self::A {
+ default constructor •() → void
+ : super self::A::•()
+ ;
+ method foo() → core::int
+ return 1;
+}
+class C extends core::Object implements self::A {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo() → core::int
+ return 2;
+}
+class D extends self::C {
+ default constructor •() → void
+ : super self::C::•()
+ ;
+}
+class E extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+ method toString() → core::String
+ return "D";
+}
+static field self::A dd;
+static field self::E ee = new self::E::•();
+static method callerA1(self::A aa) → void {
+ aa.{self::A::foo}();
+}
+static method callerA2(self::A aa) → void {
+ [@vm.direct-call.metadata=#lib::B::foo] aa.{self::A::foo}();
+}
+static method callerA3(self::A aa) → void {
+ [@vm.direct-call.metadata=#lib::C::foo] aa.{self::A::foo}();
+}
+static method callerA4(self::A aa) → void {
+ [@vm.direct-call.metadata=#lib::C::foo??] aa.{self::A::foo}();
+}
+static method callerE1(dynamic x) → void {
+ [@vm.direct-call.metadata=dart.core::_StringBase::toString] x.{core::Object::toString}();
+}
+static method callerE2(dynamic x) → void {
+ [@vm.direct-call.metadata=#lib::E::toString] x.{core::Object::toString}();
+}
+static method main(core::List<core::String> args) → dynamic {
+ self::callerA1(new self::B::•());
+ self::callerA1(new self::C::•());
+ self::callerA2(new self::B::•());
+ self::callerA3(new self::C::•());
+ self::callerA4([@vm.inferred-type.metadata=#lib::D?] self::dd);
+ self::dd = new self::D::•();
+ self::callerE1("abc");
+ self::callerE2([@vm.inferred-type.metadata=#lib::E] self::ee);
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart b/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart
new file mode 100644
index 0000000..11752a9
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2018, 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.
+
+class A {}
+
+Object foo() => new A();
+
+main(List<String> args) {
+ print(foo());
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart.expect
new file mode 100644
index 0000000..936910d
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart.expect
@@ -0,0 +1,14 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+}
+static method foo() → core::Object
+ return new self::A::•();
+static method main(core::List<core::String> args) → dynamic {
+ core::print([@vm.inferred-type.metadata=#lib::A] self::foo());
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart
new file mode 100644
index 0000000..b70a6cf
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2018, 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.
+
+class T1 {}
+
+class T2 {}
+
+abstract class A {
+ foo();
+}
+
+class B extends A {
+ foo() => new T1();
+}
+
+class C implements B {
+ foo() => new T2();
+}
+
+class Intermediate {
+ bar(A aa) => aa.foo();
+}
+
+use1(Intermediate i, A aa) => i.bar(aa);
+use2(Intermediate i, A aa) => i.bar(aa);
+
+Function unknown;
+
+getDynamic() => unknown.call();
+
+allocateB() {
+ new B();
+}
+
+main(List<String> args) {
+ use1(new Intermediate(), getDynamic()); // No subclasses of A allocated.
+
+ allocateB();
+
+ use2(new Intermediate(), getDynamic()); // Now B is allocated.
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
new file mode 100644
index 0000000..72ac45b
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
@@ -0,0 +1,56 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+class T1 extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class T2 extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ throw "TFA Error: #lib::T2::";
+}
+abstract class A extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → dynamic;
+}
+class B extends self::A {
+ default constructor •() → void
+ : super self::A::•()
+ ;
+ method foo() → dynamic
+ return new self::T1::•();
+}
+class C extends core::Object implements self::B {
+ default constructor •() → void
+ : super core::Object::•()
+ throw "TFA Error: #lib::C::";
+ method foo() → dynamic
+ throw "TFA Error: #lib::C::foo";
+}
+class Intermediate extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+ method bar(self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::B::foo??] [@vm.inferred-type.metadata=#lib::T1] aa.{self::A::foo}();
+}
+static field core::Function unknown;
+static method use1(self::Intermediate i, self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=#lib::T1] i.{self::Intermediate::bar}(aa);
+static method use2(self::Intermediate i, self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=#lib::T1] i.{self::Intermediate::bar}(aa);
+static method getDynamic() → dynamic
+ return self::unknown.call();
+static method allocateB() → dynamic {
+ new self::B::•();
+}
+static method main(core::List<core::String> args) → dynamic {
+ self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
+ self::allocateB();
+ self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart
new file mode 100644
index 0000000..5248ac9
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2018, 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.
+
+class T1 {}
+
+class T2 {}
+
+abstract class A {
+ foo();
+}
+
+class B extends A {
+ foo() => new T1();
+}
+
+abstract class C implements B {}
+
+class D {}
+
+class E extends D with C {
+ foo() => new T2();
+}
+
+class Intermediate {
+ bar(A aa) => aa.foo();
+}
+
+use1(Intermediate i, A aa) => i.bar(aa);
+use2(Intermediate i, A aa) => i.bar(aa);
+use3(Intermediate i, A aa) => i.bar(aa);
+
+Function unknown;
+
+getDynamic() => unknown.call();
+
+allocateB() {
+ new B();
+}
+
+allocateE() {
+ new E();
+}
+
+main(List<String> args) {
+ use1(new Intermediate(), getDynamic()); // No subclasses of A allocated.
+
+ allocateB();
+
+ use2(new Intermediate(), getDynamic()); // Now B is allocated.
+
+ allocateE();
+
+ use3(new Intermediate(), getDynamic()); // Now E is also allocated.
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
new file mode 100644
index 0000000..2559e906
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
@@ -0,0 +1,78 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+class T1 extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class T2 extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+}
+abstract class A extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → dynamic;
+}
+class B extends self::A {
+ default constructor •() → void
+ : super self::A::•()
+ ;
+ method foo() → dynamic
+ return new self::T1::•();
+}
+abstract class C extends core::Object implements self::B {
+ default constructor •() → void
+ : super core::Object::•()
+ throw "TFA Error: #lib::C::";
+}
+class D extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+}
+abstract class _D&C extends self::D implements self::C {
+ constructor •() → void
+ : super self::D::•()
+ ;
+}
+class E extends self::_D&C {
+ default constructor •() → void
+ : super self::D::•()
+ ;
+ method foo() → dynamic
+ return new self::T2::•();
+}
+class Intermediate extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+ method bar(self::A aa) → dynamic
+ return [@vm.inferred-type.metadata=!] aa.{self::A::foo}();
+}
+static field core::Function unknown;
+static method use1(self::Intermediate i, self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=!] i.{self::Intermediate::bar}(aa);
+static method use2(self::Intermediate i, self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=!] i.{self::Intermediate::bar}(aa);
+static method use3(self::Intermediate i, self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=!] i.{self::Intermediate::bar}(aa);
+static method getDynamic() → dynamic
+ return self::unknown.call();
+static method allocateB() → dynamic {
+ new self::B::•();
+}
+static method allocateE() → dynamic {
+ new self::E::•();
+}
+static method main(core::List<core::String> args) → dynamic {
+ self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
+ self::allocateB();
+ self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
+ self::allocateE();
+ self::use3(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart
new file mode 100644
index 0000000..7fb845e
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2018, 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.
+
+class T1 {}
+
+class T2 {}
+
+class A {
+ dynamic field1 = new T1();
+ dynamic field2 = new T1();
+}
+
+// Methods of this class should have inferred type = T1.
+class DeepCaller1 {
+ barL1(A aa) => barL2(aa);
+ barL2(A aa) => barL3(aa);
+ barL3(A aa) => barL4(aa);
+ barL4(A aa) => aa.field1;
+}
+
+// Methods of this class should have inferred type = T1 | T2.
+class DeepCaller2 {
+ barL1(A aa) => barL2(aa);
+ barL2(A aa) => barL3(aa);
+ barL3(A aa) => barL4(aa);
+ barL4(A aa) => aa.field2;
+}
+
+use1(DeepCaller1 x, A aa) => x.barL1(aa);
+use2(DeepCaller2 x, A aa) => x.barL1(aa);
+
+Function unknown;
+
+getDynamic() => unknown.call();
+
+void setField2(A aa, dynamic value) {
+ aa.field2 = value;
+}
+
+main(List<String> args) {
+ new A();
+ new T1();
+ new T2();
+
+ use1(new DeepCaller1(), getDynamic());
+ use2(new DeepCaller2(), getDynamic());
+
+ setField2(new A(), new T2());
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
new file mode 100644
index 0000000..d3ac445
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
@@ -0,0 +1,65 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+class T1 extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class T2 extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class A extends core::Object {
+ field dynamic field1 = new self::T1::•();
+ field dynamic field2 = new self::T1::•();
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class DeepCaller1 extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+ method barL1(self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller1::barL2] [@vm.inferred-type.metadata=#lib::T1] this.{self::DeepCaller1::barL2}(aa);
+ method barL2(self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller1::barL3] [@vm.inferred-type.metadata=#lib::T1] this.{self::DeepCaller1::barL3}(aa);
+ method barL3(self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller1::barL4] [@vm.inferred-type.metadata=#lib::T1] this.{self::DeepCaller1::barL4}(aa);
+ method barL4(self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::A::field1??] [@vm.inferred-type.metadata=#lib::T1] aa.{self::A::field1};
+}
+class DeepCaller2 extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+ method barL1(self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller2::barL2] [@vm.inferred-type.metadata=!] this.{self::DeepCaller2::barL2}(aa);
+ method barL2(self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller2::barL3] [@vm.inferred-type.metadata=!] this.{self::DeepCaller2::barL3}(aa);
+ method barL3(self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller2::barL4] [@vm.inferred-type.metadata=!] this.{self::DeepCaller2::barL4}(aa);
+ method barL4(self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::A::field2??] [@vm.inferred-type.metadata=!] aa.{self::A::field2};
+}
+static field core::Function unknown;
+static method use1(self::DeepCaller1 x, self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller1::barL1] [@vm.inferred-type.metadata=#lib::T1] x.{self::DeepCaller1::barL1}(aa);
+static method use2(self::DeepCaller2 x, self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller2::barL1] [@vm.inferred-type.metadata=!] x.{self::DeepCaller2::barL1}(aa);
+static method getDynamic() → dynamic
+ return self::unknown.call();
+static method setField2(self::A aa, dynamic value) → void {
+ [@vm.direct-call.metadata=#lib::A::field2] aa.{self::A::field2} = value;
+}
+static method main(core::List<core::String> args) → dynamic {
+ new self::A::•();
+ new self::T1::•();
+ new self::T2::•();
+ self::use1(new self::DeepCaller1::•(), self::getDynamic() as{TypeError} self::A);
+ self::use2(new self::DeepCaller2::•(), self::getDynamic() as{TypeError} self::A);
+ self::setField2(new self::A::•(), new self::T2::•());
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart
new file mode 100644
index 0000000..db52bf0
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2018, 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.
+
+A aa = new B();
+
+dynamic knownResult() => new B();
+
+abstract class A {
+ int foo();
+}
+
+class B extends A {
+ int foo() => 1 + knownResult().foo(); // Should have metadata.
+}
+
+class C implements A {
+ int foo() => 2 + knownResult().foo(); // Should be unreachable.
+}
+
+class TearOffInterfaceMethod {
+ dynamic bazz;
+ TearOffInterfaceMethod(A arg) : bazz = arg.foo;
+}
+
+main(List<String> args) {
+ new TearOffInterfaceMethod(new B()).bazz();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
new file mode 100644
index 0000000..65f9cd2
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
@@ -0,0 +1,36 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → core::int;
+}
+class B extends self::A {
+ default constructor •() → void
+ : super self::A::•()
+ ;
+ method foo() → core::int
+ return 1.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
+}
+class C extends core::Object implements self::A {
+ default constructor •() → void
+ : super core::Object::•()
+ throw "TFA Error: #lib::C::";
+ method foo() → core::int
+ throw "TFA Error: #lib::C::foo";
+}
+class TearOffInterfaceMethod extends core::Object {
+ field dynamic bazz;
+ constructor •(self::A arg) → void
+ : self::TearOffInterfaceMethod::bazz = arg.{self::A::foo}, super core::Object::•()
+ ;
+}
+static field self::A aa = throw "TFA Error: #lib::aa";
+static method knownResult() → dynamic
+ return new self::B::•();
+static method main(core::List<core::String> args) → dynamic {
+ new self::TearOffInterfaceMethod::•(new self::B::•()).{self::TearOffInterfaceMethod::bazz}();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart
new file mode 100644
index 0000000..ebe01db
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2018, 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.
+
+A aa = new B();
+
+dynamic knownResult() => new B();
+
+abstract class A {
+ int foo();
+}
+
+class B extends A {
+ int foo() => 1 + knownResult().foo(); // Should have metadata.
+}
+
+class C implements A {
+ int foo() => 2 + knownResult().foo(); // Should be unreachable.
+}
+
+class Base {
+ int foo() => 3 + knownResult().foo(); // Should have metadata.
+ int doCall(x) => x();
+}
+
+class TearOffSuperMethod extends Base {
+ int foo() {
+ // Should be unreachable.
+ aa = new C();
+ return 4 + knownResult().foo();
+ }
+
+ int bar() => doCall(super.foo);
+}
+
+main(List<String> args) {
+ new TearOffSuperMethod().bar();
+
+ aa.foo(); // Should be devirtualized.
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
new file mode 100644
index 0000000..4f68c9e
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
@@ -0,0 +1,49 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → core::int;
+}
+class B extends self::A {
+ default constructor •() → void
+ : super self::A::•()
+ ;
+ method foo() → core::int
+ return 1.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
+}
+class C extends core::Object implements self::A {
+ default constructor •() → void
+ : super core::Object::•()
+ throw "TFA Error: #lib::C::";
+ method foo() → core::int
+ throw "TFA Error: #lib::C::foo";
+}
+class Base extends core::Object {
+ default constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo() → core::int
+ return 3.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
+ method doCall(dynamic x) → core::int
+ return x.call() as{TypeError} core::int;
+}
+class TearOffSuperMethod extends self::Base {
+ default constructor •() → void
+ : super self::Base::•()
+ ;
+ method foo() → core::int
+ throw "TFA Error: #lib::TearOffSuperMethod::foo";
+ method bar() → core::int
+ return [@vm.direct-call.metadata=#lib::Base::doCall] this.{self::Base::doCall}(super.{self::Base::foo});
+}
+static field self::A aa = new self::B::•();
+static method knownResult() → dynamic
+ return new self::B::•();
+static method main(core::List<core::String> args) → dynamic {
+ [@vm.direct-call.metadata=#lib::TearOffSuperMethod::bar] new self::TearOffSuperMethod::•().{self::TearOffSuperMethod::bar}();
+ [@vm.direct-call.metadata=#lib::B::foo] [@vm.inferred-type.metadata=#lib::B] self::aa.{self::A::foo}();
+}
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 6afa317..9142737 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -5,6 +5,7 @@
import("../../build/compiled_action.gni")
import("../../sdk/lib/_http/http_sources.gni")
import("../../sdk/lib/io/io_sources.gni")
+import("../../sdk/lib/cli/cli_sources.gni")
import("../runtime_args.gni")
import("../vm/compiler/compiler_sources.gni")
import("../vm/vm_sources.gni")
@@ -12,6 +13,8 @@
import("builtin_sources.gni")
import("io_impl_sources.gni")
import("io_sources.gni")
+import("cli_impl_sources.gni")
+import("cli_sources.gni")
import("vmservice/vmservice_sources.gni")
# Generate a resources.cc file for the service isolate without Observatory.
@@ -109,6 +112,22 @@
output = "$target_gen_dir/http_gen.cc"
}
+rebased_cli_sdk_sources = rebase_path(cli_sdk_sources, ".", "../../sdk/lib/cli")
+
+gen_library_src_path("generate_cli_cc_file") {
+ name = "cli"
+ kind = "source"
+ sources = [ "../../sdk/lib/cli/cli.dart" ] + rebased_cli_sdk_sources
+ output = "$target_gen_dir/cli_gen.cc"
+}
+
+gen_library_src_path("generate_cli_patch_cc_file") {
+ name = "cli"
+ kind = "patch"
+ sources = cli_runtime_sources
+ output = "$target_gen_dir/cli_patch_gen.cc"
+}
+
gen_library_src_path("generate_html_cc_file") {
name = "html"
kind = "source"
@@ -235,6 +254,8 @@
public_configs = [ ":libdart_builtin_config" ]
deps = [
":generate_builtin_cc_file",
+ ":generate_cli_cc_file",
+ ":generate_cli_patch_cc_file",
":generate_html_cc_file",
":generate_html_common_cc_file",
":generate_http_cc_file",
@@ -297,11 +318,15 @@
":generate_http_cc_file",
":generate_io_cc_file",
":generate_io_patch_cc_file",
+ ":generate_cli_cc_file",
+ ":generate_cli_patch_cc_file",
] + extra_deps
sources = [
# Include generated source files.
"$target_gen_dir/builtin_gen.cc",
+ "$target_gen_dir/cli_gen.cc",
+ "$target_gen_dir/cli_patch_gen.cc",
"$target_gen_dir/http_gen.cc",
"$target_gen_dir/io_gen.cc",
"$target_gen_dir/io_patch_gen.cc",
@@ -417,7 +442,7 @@
defines = [ "DART_IO_SECURE_SOCKET_DISABLED" ]
- sources = io_impl_sources + builtin_impl_sources
+ sources = io_impl_sources + builtin_impl_sources + cli_impl_sources
sources += [
"io_natives.cc",
"io_natives.h",
@@ -494,7 +519,7 @@
libs = [ "launchpad" ]
}
- sources = io_impl_sources + builtin_impl_sources
+ sources = io_impl_sources + builtin_impl_sources + cli_impl_sources
sources += [
"builtin_natives.cc",
"io_natives.cc",
@@ -712,7 +737,7 @@
if (is_fuchsia) {
configs -= [ "//build/config:symbol_visibility_hidden" ]
}
- if (is_fuchsia_host) {
+ if (target_os != current_os && target_os == "fuchsia") {
# We already have these in the standalone build, but Fuchsia doesn't
# have them. They are needed for running Fuchsia binaries built for the
# host.
@@ -840,6 +865,8 @@
":generate_js_util_cc_file",
":generate_metadata_cc_file",
":generate_svg_cc_file",
+ ":generate_cli_cc_file",
+ ":generate_cli_patch_cc_file",
":generate_web_audio_cc_file",
":generate_web_gl_cc_file",
":generate_web_sql_cc_file",
@@ -871,6 +898,8 @@
"$target_gen_dir/metadata_gen.cc",
"$target_gen_dir/resources_gen.cc",
"$target_gen_dir/svg_gen.cc",
+ "$target_gen_dir/cli_gen.cc",
+ "$target_gen_dir/cli_patch_gen.cc",
"$target_gen_dir/web_audio_gen.cc",
"$target_gen_dir/web_gl_gen.cc",
"$target_gen_dir/web_sql_gen.cc",
@@ -1005,7 +1034,7 @@
}
executable("run_vm_tests") {
- if (is_fuchsia || is_fuchsia_host) {
+ if (target_os == "fuchsia") {
testonly = true
}
diff --git a/runtime/bin/builtin.cc b/runtime/bin/builtin.cc
index 049d2e9..3d205b9 100644
--- a/runtime/bin/builtin.cc
+++ b/runtime/bin/builtin.cc
@@ -23,6 +23,8 @@
{DartUtils::kIOLibURL, io_source_paths_, DartUtils::kIOLibPatchURL,
io_patch_paths_, true},
{DartUtils::kHttpLibURL, _http_source_paths_, NULL, NULL, false},
+ {DartUtils::kCLILibURL, cli_source_paths_, DartUtils::kCLILibPatchURL,
+ cli_patch_paths_, true},
#if defined(DART_NO_SNAPSHOT)
// Only include these libraries in the dart_bootstrap case for now.
diff --git a/runtime/bin/builtin.h b/runtime/bin/builtin.h
index 8182f3b..4823d91 100644
--- a/runtime/bin/builtin.h
+++ b/runtime/bin/builtin.h
@@ -30,6 +30,7 @@
kBuiltinLibrary = 0,
kIOLibrary,
kHttpLibrary,
+ kCLILibrary,
};
// Get source corresponding to built in library specified in 'id'.
@@ -79,6 +80,8 @@
static const char* web_gl_source_paths_[];
static const char* metadata_source_paths_[];
static const char* web_sql_source_paths_[];
+ static const char* cli_source_paths_[];
+ static const char* cli_patch_paths_[];
static const char* svg_source_paths_[];
static const char* web_audio_source_paths_[];
diff --git a/runtime/bin/builtin_nolib.cc b/runtime/bin/builtin_nolib.cc
index 4b11341..2bf2599 100644
--- a/runtime/bin/builtin_nolib.cc
+++ b/runtime/bin/builtin_nolib.cc
@@ -18,6 +18,7 @@
{DartUtils::kBuiltinLibURL, NULL, NULL, NULL, true},
{DartUtils::kIOLibURL, NULL, NULL, NULL, true},
{DartUtils::kHttpLibURL, NULL, NULL, NULL, false},
+ {DartUtils::kCLILibURL, NULL, NULL, NULL, true},
// End marker.
{NULL, NULL, NULL, NULL, false}};
diff --git a/runtime/bin/cli.cc b/runtime/bin/cli.cc
new file mode 100644
index 0000000..d56d522
--- /dev/null
+++ b/runtime/bin/cli.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2017, 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.
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+
+#include "include/dart_api.h"
+
+namespace dart {
+namespace bin {
+
+void FUNCTION_NAME(CLI_WaitForEvent)(Dart_NativeArguments args) {
+ int64_t timeout_millis;
+ Dart_Handle result = Dart_GetNativeIntegerArgument(args, 0, &timeout_millis);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ result = Dart_WaitForEvent(timeout_millis);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ Dart_SetReturnValue(args, result);
+}
+
+} // namespace bin
+} // namespace dart
diff --git a/runtime/bin/cli_impl_sources.gni b/runtime/bin/cli_impl_sources.gni
new file mode 100644
index 0000000..86f8fd7
--- /dev/null
+++ b/runtime/bin/cli_impl_sources.gni
@@ -0,0 +1,6 @@
+# Copyright (c) 2017, 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.
+
+# This file contains some C++ sources for the dart:cli library.
+cli_impl_sources = [ "cli.cc" ]
diff --git a/runtime/bin/cli_patch.dart b/runtime/bin/cli_patch.dart
new file mode 100644
index 0000000..504a0db
--- /dev/null
+++ b/runtime/bin/cli_patch.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2017, 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.
+
+import "dart:_internal" show patch;
+
+@patch
+void _waitForEvent(int timeoutMillis) native "CLI_WaitForEvent";
diff --git a/runtime/bin/cli_sources.gni b/runtime/bin/cli_sources.gni
new file mode 100644
index 0000000..532fbba
--- /dev/null
+++ b/runtime/bin/cli_sources.gni
@@ -0,0 +1,6 @@
+# Copyright (c) 2017, 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.
+
+# This file contains all sources for the dart:cli library.
+cli_runtime_sources = [ "cli_patch.dart" ]
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index e53d6db..f42ca27 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -46,6 +46,8 @@
const char* const DartUtils::kHttpLibURL = "dart:_http";
const char* const DartUtils::kIOLibURL = "dart:io";
const char* const DartUtils::kIOLibPatchURL = "dart:io-patch";
+const char* const DartUtils::kCLILibURL = "dart:cli";
+const char* const DartUtils::kCLILibPatchURL = "dart:cli-patch";
const char* const DartUtils::kUriLibURL = "dart:uri";
const char* const DartUtils::kHttpScheme = "http:";
const char* const DartUtils::kVMServiceLibURL = "dart:vmservice";
@@ -169,6 +171,10 @@
return (strcmp(url_name, kIOLibURL) == 0);
}
+bool DartUtils::IsDartCLILibURL(const char* url_name) {
+ return (strcmp(url_name, kCLILibURL) == 0);
+}
+
bool DartUtils::IsDartHttpLibURL(const char* url_name) {
return (strcmp(url_name, kHttpLibURL) == 0);
}
@@ -477,6 +483,14 @@
return Dart_Invoke(isolate_lib, NewString("_setupHooks"), 0, NULL);
}
+Dart_Handle DartUtils::PrepareCLILibrary(Dart_Handle cli_lib) {
+ Dart_Handle wait_for_event_handle =
+ Dart_Invoke(cli_lib, NewString("_getWaitForEvent"), 0, NULL);
+ RETURN_IF_ERROR(wait_for_event_handle);
+ return Dart_SetField(cli_lib, NewString("_waitForEventClosure"),
+ wait_for_event_handle);
+}
+
Dart_Handle DartUtils::SetupServiceLoadPort() {
// Wait for the service isolate to initialize the load port.
Dart_Port load_port = Dart_ServiceWaitForLoadPort();
@@ -539,6 +553,9 @@
Dart_Handle io_lib = Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
RETURN_IF_ERROR(io_lib);
Builtin::SetNativeResolver(Builtin::kIOLibrary);
+ Dart_Handle cli_lib = Builtin::LoadAndCheckLibrary(Builtin::kCLILibrary);
+ RETURN_IF_ERROR(cli_lib);
+ Builtin::SetNativeResolver(Builtin::kCLILibrary);
// Setup the builtin library in a persistent handle attached the isolate
// specific data as we seem to lookup and use builtin lib a lot.
@@ -560,6 +577,7 @@
RETURN_IF_ERROR(PrepareCoreLibrary(core_lib, io_lib, is_service_isolate));
RETURN_IF_ERROR(PrepareIsolateLibrary(isolate_lib));
RETURN_IF_ERROR(PrepareIOLibrary(io_lib));
+ RETURN_IF_ERROR(PrepareCLILibrary(cli_lib));
return result;
}
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 8c619c4..e2972cc 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -113,6 +113,7 @@
static bool IsDartSchemeURL(const char* url_name);
static bool IsDartExtensionSchemeURL(const char* url_name);
static bool IsDartIOLibURL(const char* url_name);
+ static bool IsDartCLILibURL(const char* url_name);
static bool IsDartHttpLibURL(const char* url_name);
static bool IsDartBuiltinLibURL(const char* url_name);
static bool IsHttpSchemeURL(const char* url_name);
@@ -235,6 +236,8 @@
static const char* const kHttpLibURL;
static const char* const kIOLibURL;
static const char* const kIOLibPatchURL;
+ static const char* const kCLILibURL;
+ static const char* const kCLILibPatchURL;
static const char* const kUriLibURL;
static const char* const kHttpScheme;
static const char* const kVMServiceLibURL;
@@ -254,6 +257,7 @@
Dart_Handle isolate_lib);
static Dart_Handle PrepareIOLibrary(Dart_Handle io_lib);
static Dart_Handle PrepareIsolateLibrary(Dart_Handle isolate_lib);
+ static Dart_Handle PrepareCLILibrary(Dart_Handle cli_lib);
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(DartUtils);
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index 3329221..c5a2e15 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -78,6 +78,9 @@
delete reinterpret_cast<kernel::Program*>(kernel_platform_);
kernel_platform_ = NULL;
+ delete reinterpret_cast<kernel::Program*>(kKernelServiceProgram);
+ kKernelServiceProgram = NULL;
+
delete reinterpret_cast<kernel::Program*>(application_kernel_binary_);
application_kernel_binary_ = NULL;
}
@@ -109,6 +112,10 @@
return frontend_filename_;
}
+bool DFE::KernelServiceDillAvailable() {
+ return kernel_service_dill != NULL;
+}
+
static void NoopRelease(uint8_t* buffer) {}
void* DFE::KernelServiceProgram() {
diff --git a/runtime/bin/dfe.h b/runtime/bin/dfe.h
index ead2c75..fb3258a 100644
--- a/runtime/bin/dfe.h
+++ b/runtime/bin/dfe.h
@@ -72,6 +72,7 @@
void* ReadScript(const char* script_uri) const;
static void* KernelServiceProgram();
+ static bool KernelServiceDillAvailable();
private:
// Tries to read [script_uri] as a Kernel IR file.
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 82ab90e..956cfe2 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -462,6 +462,9 @@
if (DartUtils::IsDartHttpLibURL(url)) {
return Builtin::kHttpLibrary;
}
+ if (DartUtils::IsDartCLILibURL(url)) {
+ return Builtin::kCLILibrary;
+ }
return Builtin::kInvalidLibrary;
}
@@ -1302,6 +1305,9 @@
Dart_Handle library = LoadGenericSnapshotCreationScript(Builtin::kIOLibrary);
CHECK_RESULT(library);
+ Dart_Handle standalone_library =
+ LoadGenericSnapshotCreationScript(Builtin::kCLILibrary);
+ CHECK_RESULT(standalone_library);
Dart_Handle result = Dart_FinalizeLoading(false);
if (Dart_IsError(result)) {
const char* err_msg = Dart_GetError(library);
@@ -1344,6 +1350,7 @@
// Setup the native resolver.
Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
+ Builtin::LoadAndCheckLibrary(Builtin::kCLILibrary);
ASSERT(Dart_IsServiceIsolate(isolate));
// Load embedder specific bits and return. Will not start http server.
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index 9ecb61d..c207088 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -19,6 +19,7 @@
// Some classes, like File and Directory, list their implementations in
// builtin_natives.cc instead.
#define IO_NATIVE_LIST(V) \
+ V(CLI_WaitForEvent, 1) \
V(Crypto_GetRandomBytes, 1) \
V(Directory_Create, 2) \
V(Directory_CreateTemp, 2) \
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 892417f..77004f5 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -221,6 +221,7 @@
// Setup the native resolver as the snapshot does not carry it.
Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
Builtin::SetNativeResolver(Builtin::kIOLibrary);
+ Builtin::SetNativeResolver(Builtin::kCLILibrary);
}
if (isolate_run_app_snapshot) {
Dart_Handle result = Loader::ReloadNativeExtensions();
@@ -686,6 +687,8 @@
{"dart:_builtin", "::", "_setPackagesMap"},
{"dart:_builtin", "::", "_setWorkingDirectory"},
{"dart:async", "::", "_setScheduleImmediateClosure"},
+ {"dart:cli", "::", "_getWaitForEvent"},
+ {"dart:cli", "::", "_waitForEventClosure"},
{"dart:io", "::", "_getUriBaseClosure"},
{"dart:io", "::", "_getWatchSignalInternal"},
{"dart:io", "::", "_makeDatagram"},
@@ -1091,7 +1094,16 @@
init_params.entropy_source = DartUtils::EntropySource;
init_params.get_service_assets = GetVMServiceAssetsArchiveCallback;
#if !defined(DART_PRECOMPILED_RUNTIME)
- init_params.start_kernel_isolate = dfe.UseDartFrontend();
+ // Start the kernel isolate only if
+ // 1. --dart_preview_2 and/or --dfe is used
+ //
+ // or
+ //
+ // 2. If we have kernel service dill file linked in and a dill file
+ // was specified as the main dart program.
+ init_params.start_kernel_isolate =
+ dfe.UseDartFrontend() ||
+ (dfe.kernel_file_specified() && DFE::KernelServiceDillAvailable());
#else
init_params.start_kernel_isolate = false;
#endif
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 03b348f..5b89ff9 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -68,6 +68,8 @@
DEFINE_BOOL_OPTION_CB(preview_dart_2, { Options::dfe()->set_use_dfe(); });
+// TODO(sivachandra): Make it an error to specify --dfe without
+// specifying --preview_dart_2.
DEFINE_STRING_OPTION_CB(dfe, { Options::dfe()->set_frontend_filename(value); });
DEFINE_STRING_OPTION_CB(kernel_binaries,
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index ce36ebc..de90aed 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1222,6 +1222,16 @@
DART_EXPORT Dart_Handle Dart_HandleMessages();
/**
+ * Drains the microtask queue, then blocks the calling thread until the current
+ * isolate recieves a message, then handles all messages.
+ *
+ * \param timeout_millis When non-zero, the call returns after the indicated
+ number of milliseconds even if no message was received.
+ * \return A valid handle if no error occurs, otherwise an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_WaitForEvent(int64_t timeout_millis);
+
+/**
* Handles any pending messages for the vm service for the current
* isolate.
*
@@ -2331,7 +2341,7 @@
* \return An error handle if the exception was not thrown.
* Otherwise the function does not return.
*/
-DART_EXPORT Dart_Handle Dart_RethrowException(Dart_Handle exception,
+DART_EXPORT Dart_Handle Dart_ReThrowException(Dart_Handle exception,
Dart_Handle stacktrace);
/*
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index 46562e6..7d13829 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -288,6 +288,12 @@
if (radix == 10) return this.toString();
final bool isNegative = this < 0;
int value = isNegative ? -this : this;
+ if (value < 0) {
+ // With integers limited to 64 bits, the value
+ // MIN_INT64 = -0x8000000000000000 overflows at negation:
+ // -MIN_INT64 == MIN_INT64, so it requires special handling.
+ return _minInt64ToRadixString(radix);
+ }
List temp = new List();
do {
int digit = value % radix;
@@ -313,6 +319,12 @@
if (negative) {
value = -value;
length = 1;
+ if (value < 0) {
+ // With integers limited to 64 bits, the value
+ // MIN_INT64 = -0x8000000000000000 overflows at negation:
+ // -MIN_INT64 == MIN_INT64, so it requires special handling.
+ return _minInt64ToRadixString(radix);
+ }
}
// Integer division, rounding up, to find number of _digits.
length += (value.bitLength + bitsPerDigit - 1) ~/ bitsPerDigit;
@@ -326,6 +338,27 @@
return string;
}
+ /// Converts negative value to radix string.
+ /// This method is only used to handle corner case of
+ /// MIN_INT64 = -0x8000000000000000.
+ String _minInt64ToRadixString(int radix) {
+ List temp = new List();
+ int value = this;
+ assert(value < 0);
+ do {
+ int digit = -value.remainder(radix);
+ value ~/= radix;
+ temp.add(_digits.codeUnitAt(digit));
+ } while (value != 0);
+ temp.add(0x2d); // '-'.
+
+ _OneByteString string = _OneByteString._allocate(temp.length);
+ for (int i = 0, j = temp.length; j > 0; i++) {
+ string._setAt(i, temp[--j]);
+ }
+ return string;
+ }
+
// Returns pow(this, e) % m.
int modPow(int e, int m) {
if (e is! int) {
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index 99cb61b..ad4f63b 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -100,7 +100,8 @@
/// The closure that should be used as scheduleImmediateClosure, when the VM
/// is responsible for the event loop.
void _isolateScheduleImmediate(void callback()) {
- assert(_pendingImmediateCallback == null);
+ assert((_pendingImmediateCallback == null) ||
+ (_pendingImmediateCallback == callback));
_pendingImmediateCallback = callback;
}
diff --git a/runtime/lib/schedule_microtask_patch.dart b/runtime/lib/schedule_microtask_patch.dart
index d450e8c..4dc837d 100644
--- a/runtime/lib/schedule_microtask_patch.dart
+++ b/runtime/lib/schedule_microtask_patch.dart
@@ -24,3 +24,7 @@
void _setScheduleImmediateClosure(_ScheduleImmediateClosure closure) {
_ScheduleImmediate._closure = closure;
}
+
+void _ensureScheduleImmediate() {
+ _AsyncRun._scheduleImmediate(_startMicrotaskLoop);
+}
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index 03cebd3..c111ac6 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -404,13 +404,12 @@
return (codeUnit == 0x85) || (codeUnit == 0xA0); // NEL, NBSP.
}
- // Characters with Whitespace property (Unicode 6.2).
+ // Characters with Whitespace property (Unicode 6.3).
// 0009..000D ; White_Space # Cc <control-0009>..<control-000D>
// 0020 ; White_Space # Zs SPACE
// 0085 ; White_Space # Cc <control-0085>
// 00A0 ; White_Space # Zs NO-BREAK SPACE
// 1680 ; White_Space # Zs OGHAM SPACE MARK
- // 180E ; White_Space # Zs MONGOLIAN VOWEL SEPARATOR
// 2000..200A ; White_Space # Zs EN QUAD..HAIR SPACE
// 2028 ; White_Space # Zl LINE SEPARATOR
// 2029 ; White_Space # Zp PARAGRAPH SEPARATOR
@@ -426,7 +425,7 @@
if (codeUnit < 0x85) return false;
if ((codeUnit == 0x85) || (codeUnit == 0xA0)) return true;
return (codeUnit <= 0x200A)
- ? ((codeUnit == 0x1680) || (codeUnit == 0x180E) || (0x2000 <= codeUnit))
+ ? ((codeUnit == 0x1680) || (0x2000 <= codeUnit))
: ((codeUnit == 0x2028) ||
(codeUnit == 0x2029) ||
(codeUnit == 0x202F) ||
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index 1f74a04..bc194bc 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -19,6 +19,7 @@
import("../../utils/compile_platform.gni")
import("../../utils/generate_patch_sdk.gni")
import("../bin/io_sources.gni")
+import("../bin/cli_sources.gni")
import("../lib/async_sources.gni")
import("../lib/collection_sources.gni")
import("../lib/convert_sources.gni")
@@ -72,13 +73,14 @@
if (is_fuchsia) {
configs -= [ "//build/config:symbol_visibility_hidden" ]
deps = [
+ # TODO(US-399): Remove time_service specific code when it is no longer
+ # necessary.
+ "//garnet/public/lib/app/cpp",
+ "//garnet/public/lib/time_service/fidl",
+
# TODO(zra): When the platform-specific timeline code is moved out to
# the embedder, this can go away.
"//zircon/system/ulib/fbl",
- # TODO(US-399): Remove time_service specific code when it is no longer
- # necessary.
- "//garnet/public/lib/time_service/fidl",
- "//garnet/public/lib/app/cpp",
]
}
public_configs = [ ":libdart_vm_config" ]
@@ -572,6 +574,11 @@
io_runtime_sources,
"../bin",
],
+ [
+ "cli",
+ cli_runtime_sources,
+ "../bin",
+ ],
]
}
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index 778ec14..e0764a2 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -111,6 +111,7 @@
BENCHMARK(CorelibCompileAll) {
bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
+ bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
TransitionNativeToVM transition(thread);
Timer timer(true, "Compile all of Core lib benchmark");
timer.Start();
@@ -129,6 +130,7 @@
BENCHMARK(CorelibCompilerStats) {
bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
+ bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
TransitionNativeToVM transition(thread);
CompilerStats* stats = thread->isolate()->aggregate_compiler_stats();
ASSERT(stats != NULL);
@@ -148,6 +150,7 @@
BENCHMARK(Dart2JSCompilerStats) {
bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
+ bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
SetupDart2JSPackagePath();
char* dart_root = ComputeDart2JSPath(Benchmark::Executable());
char* script = NULL;
@@ -349,6 +352,7 @@
BENCHMARK(Dart2JSCompileAll) {
bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
+ bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
SetupDart2JSPackagePath();
char* dart_root = ComputeDart2JSPath(Benchmark::Executable());
char* script = NULL;
@@ -530,6 +534,7 @@
"import 'dart:typed_data';\n"
"import 'dart:_builtin';\n"
"import 'dart:io';\n"
+ "import 'dart:cli';\n"
"\n";
// Start an Isolate, load a script and create a full snapshot.
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index e2b8ec5..68b4238 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -161,7 +161,7 @@
ASSERT(!function.IsNull());
const Function& target = Function::ZoneHandle(Z, function.raw());
StaticCallInstr* static_call = StaticCallInstr::FromCall(Z, call, target);
- static_call->set_result_cid(kTypeCid);
+ static_call->SetResultType(Z, CompileType::FromCid(kTypeCid));
call->ReplaceWith(static_call, current_iterator());
return true;
}
@@ -208,7 +208,7 @@
call->token_pos(), have_same_runtime_type, kTypeArgsLen,
Object::null_array(), // argument_names
args, call->deopt_id(), call->CallCount(), ICData::kOptimized);
- static_call->set_result_cid(kBoolCid);
+ static_call->SetResultType(Z, CompileType::FromCid(kBoolCid));
ReplaceCall(call, static_call);
return true;
}
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index bdb87e3..89aa1a8 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -580,6 +580,7 @@
static Dart_QualifiedFunctionName vm_entry_points[] = {
// Functions
+ {"dart:async", "::", "_ensureScheduleImmediate"},
{"dart:core", "::", "_completeDeferredLoads"},
{"dart:core", "::", "identityHashCode"},
{"dart:core", "AbstractClassInstantiationError",
@@ -603,6 +604,7 @@
{"dart:core", "_TypeError", "_TypeError._create"},
{"dart:collection", "::", "_rehashObjects"},
{"dart:isolate", "IsolateSpawnException", "IsolateSpawnException."},
+ {"dart:isolate", "::", "_runPendingImmediateCallback"},
{"dart:isolate", "::", "_startIsolate"},
{"dart:isolate", "_RawReceivePortImpl", "_handleMessage"},
{"dart:isolate", "_RawReceivePortImpl", "_lookupHandler"},
@@ -615,7 +617,6 @@
{"dart:_vmservice", "::", "_registerIsolate"},
{"dart:developer", "Metrics", "_printMetrics"},
{"dart:developer", "::", "_runExtension"},
- {"dart:isolate", "::", "_runPendingImmediateCallback"},
#endif // !PRODUCT
// Fields
{"dart:core", "Error", "_stackTrace"},
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 3f14be9..b5d4b7f 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -3102,6 +3102,7 @@
token_kind_(token_kind),
checked_argument_count_(checked_argument_count),
interface_target_(interface_target),
+ result_type_(NULL),
has_unique_selector_(false) {
ic_data_ = GetICData(ic_data_array);
ASSERT(function_name.IsNotTemporaryScopedHandle());
@@ -3141,6 +3142,7 @@
token_kind_(token_kind),
checked_argument_count_(checked_argument_count),
interface_target_(interface_target),
+ result_type_(NULL),
has_unique_selector_(false) {
ASSERT(function_name.IsNotTemporaryScopedHandle());
ASSERT(interface_target_.IsNotTemporaryScopedHandle());
@@ -3189,6 +3191,16 @@
virtual bool HasUnknownSideEffects() const { return true; }
+ void SetResultType(Zone* zone, CompileType new_type) {
+ result_type_ = new (zone) CompileType(new_type);
+ }
+
+ CompileType* result_type() const { return result_type_; }
+
+ intptr_t result_cid() const {
+ return (result_type_ != NULL) ? result_type_->ToCid() : kDynamicCid;
+ }
+
PRINT_OPERANDS_TO_SUPPORT
bool MatchesCoreName(const String& name);
@@ -3205,6 +3217,7 @@
const Token::Kind token_kind_; // Binary op, unary op, kGET or kILLEGAL.
const intptr_t checked_argument_count_;
const Function& interface_target_;
+ CompileType* result_type_; // Inferred result type.
bool has_unique_selector_;
DISALLOW_COPY_AND_ASSIGN(InstanceCallInstr);
@@ -3273,6 +3286,9 @@
static RawType* ComputeRuntimeType(const CallTargets& targets);
+ CompileType* result_type() const { return instance_call()->result_type(); }
+ intptr_t result_cid() const { return instance_call()->result_cid(); }
+
PRINT_OPERANDS_TO_SUPPORT
private:
@@ -3595,7 +3611,7 @@
call_count_(0),
function_(function),
rebind_rule_(rebind_rule),
- result_cid_(kDynamicCid),
+ result_type_(NULL),
is_known_list_constructor_(false),
identity_(AliasIdentity::Unknown()) {
ic_data_ = GetICData(ic_data_array);
@@ -3622,7 +3638,7 @@
call_count_(call_count),
function_(function),
rebind_rule_(rebind_rule),
- result_cid_(kDynamicCid),
+ result_type_(NULL),
is_known_list_constructor_(false),
identity_(AliasIdentity::Unknown()) {
ASSERT(function.IsZoneHandle());
@@ -3640,10 +3656,14 @@
for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
args->Add(call->PushArgumentAt(i));
}
- return new (zone)
+ StaticCallInstr* new_call = new (zone)
StaticCallInstr(call->token_pos(), target, call->type_args_len(),
call->argument_names(), args, call->deopt_id(),
call->CallCount(), ICData::kNoRebind);
+ if (call->result_type() != NULL) {
+ new_call->result_type_ = call->result_type();
+ }
+ return new_call;
}
// ICData for static calls carries call count.
@@ -3673,7 +3693,15 @@
virtual bool HasUnknownSideEffects() const { return true; }
- void set_result_cid(intptr_t value) { result_cid_ = value; }
+ void SetResultType(Zone* zone, CompileType new_type) {
+ result_type_ = new (zone) CompileType(new_type);
+ }
+
+ CompileType* result_type() const { return result_type_; }
+
+ intptr_t result_cid() const {
+ return (result_type_ != NULL) ? result_type_->ToCid() : kDynamicCid;
+ }
bool is_known_list_constructor() const { return is_known_list_constructor_; }
void set_is_known_list_constructor(bool value) {
@@ -3692,7 +3720,7 @@
const intptr_t call_count_;
const Function& function_;
const ICData::RebindRule rebind_rule_;
- intptr_t result_cid_; // For some library functions we know the result.
+ CompileType* result_type_; // Known or inferred result type.
// 'True' for recognized list constructors.
bool is_known_list_constructor_;
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index da721b8..52fbe2c 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -1819,7 +1819,8 @@
if (ShouldEmitStoreBarrier()) {
// Value input is a writable register and should be manually preserved
- // across allocation slow-path.
+ // across allocation slow-path. Add it to live_registers set which
+ // determines which registers to preserve.
locs()->live_registers()->Add(locs()->in(1), kTagged);
}
@@ -3448,54 +3449,70 @@
bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
- LocationSummary* summary = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps,
- ValueFitsSmi() ? LocationSummary::kNoCall
- : LocationSummary::kCallOnSlowPath);
- const bool needs_writable_input =
- ValueFitsSmi() || (from_representation() == kUnboxedUint32);
- summary->set_in(0, needs_writable_input ? Location::RequiresRegister()
- : Location::WritableRegister());
- if (!ValueFitsSmi()) {
+ if (ValueFitsSmi()) {
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ // Same regs, can overwrite input.
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_out(0, Location::SameAsFirstInput());
+ return summary;
+ } else {
+ LocationSummary* summary = new (zone) LocationSummary(
+ zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+ // Guaranteed different regs. In the signed case we are going to use the
+ // input for sign extension of any Mint.
+ const bool needs_writable_input = (from_representation() == kUnboxedInt32);
+ summary->set_in(0, needs_writable_input ? Location::WritableRegister()
+ : Location::RequiresRegister());
summary->set_temp(0, Location::RequiresRegister());
+ summary->set_out(0, Location::RequiresRegister());
+ return summary;
}
- summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
- : Location::RequiresRegister());
- return summary;
}
void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register value = locs()->in(0).reg();
const Register out = locs()->out(0).reg();
- __ MoveRegister(out, value);
- __ shll(out, Immediate(kSmiTagSize));
- if (!ValueFitsSmi()) {
- Label done;
- ASSERT(value != out);
- if (from_representation() == kUnboxedInt32) {
- __ j(NO_OVERFLOW, &done);
- } else {
- __ testl(value, Immediate(0xC0000000));
- __ j(ZERO, &done);
- }
-
- // Allocate a mint.
- // Value input is writable register and has to be manually preserved
- // on the slow path.
- locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32);
- BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
- locs()->temp(0).reg());
- __ movl(FieldAddress(out, Mint::value_offset()), value);
- if (from_representation() == kUnboxedInt32) {
- __ sarl(value, Immediate(31)); // Sign extend.
- __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value);
- } else {
- __ movl(FieldAddress(out, Mint::value_offset() + kWordSize),
- Immediate(0));
- }
- __ Bind(&done);
+ if (ValueFitsSmi()) {
+ ASSERT(value == out);
+ ASSERT(kSmiTag == 0);
+ __ shll(out, Immediate(kSmiTagSize));
+ return;
}
+
+ __ movl(out, value);
+ __ shll(out, Immediate(kSmiTagSize));
+ Label done;
+ if (from_representation() == kUnboxedInt32) {
+ __ j(NO_OVERFLOW, &done);
+ } else {
+ ASSERT(value != out); // Value was not overwritten.
+ __ testl(value, Immediate(0xC0000000));
+ __ j(ZERO, &done);
+ }
+
+ // Allocate a Mint.
+ if (from_representation() == kUnboxedInt32) {
+ // Value input is a writable register and should be manually preserved
+ // across allocation slow-path. Add it to live_registers set which
+ // determines which registers to preserve.
+ locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32);
+ }
+ ASSERT(value != out); // We need the value after the allocation.
+ BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
+ locs()->temp(0).reg());
+ __ movl(FieldAddress(out, Mint::value_offset()), value);
+ if (from_representation() == kUnboxedInt32) {
+ // In the signed may-overflow case we asked for the input (value) to be
+ // writable so we can use it as a temp to put the sign extension bits in.
+ __ sarl(value, Immediate(31)); // Sign extend the Mint.
+ __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value);
+ } else {
+ __ movl(FieldAddress(out, Mint::value_offset() + kWordSize),
+ Immediate(0)); // Zero extend the Mint.
+ }
+ __ Bind(&done);
}
LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
@@ -3755,6 +3772,8 @@
Register temp = locs()->temp(0).reg();
Register temp2 = locs()->temp(1).reg();
// Temp register needs to be manually preserved on allocation slow-path.
+ // Add it to live_registers set which determines which registers to
+ // preserve.
locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32);
ASSERT(temp != result);
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 3aa37d8..b8042bd 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1048,6 +1048,14 @@
}
CompileType InstanceCallInstr::ComputeType() const {
+ // TODO(alexmarkov): calculate type of InstanceCallInstr eagerly
+ // (in optimized mode) and avoid keeping separate result_type.
+ CompileType* inferred_type = result_type();
+ if ((inferred_type != NULL) &&
+ (inferred_type->ToNullableCid() != kDynamicCid)) {
+ return *inferred_type;
+ }
+
if (Isolate::Current()->strong() && FLAG_use_strong_mode_types) {
const Function& target = interface_target();
if (!target.IsNull()) {
@@ -1063,7 +1071,9 @@
// TODO(dartbug.com/30480): instantiate generic result_type
if (result_type.IsInstantiated()) {
TraceStrongModeType(this, result_type);
- return CompileType::FromAbstractType(result_type);
+ const bool is_nullable =
+ (inferred_type == NULL) || inferred_type->is_nullable();
+ return CompileType::FromAbstractType(result_type, is_nullable);
}
}
}
@@ -1089,8 +1099,12 @@
}
CompileType StaticCallInstr::ComputeType() const {
- if (result_cid_ != kDynamicCid) {
- return CompileType::FromCid(result_cid_);
+ // TODO(alexmarkov): calculate type of StaticCallInstr eagerly
+ // (in optimized mode) and avoid keeping separate result_type.
+ CompileType* inferred_type = result_type();
+ if ((inferred_type != NULL) &&
+ (inferred_type->ToNullableCid() != kDynamicCid)) {
+ return *inferred_type;
}
if (function_.recognized_kind() != MethodRecognizer::kUnknown) {
@@ -1107,7 +1121,9 @@
// non-instantiated types properly.
if (result_type.IsInstantiated()) {
TraceStrongModeType(this, result_type);
- return CompileType::FromAbstractType(result_type);
+ const bool is_nullable =
+ (inferred_type == NULL) || inferred_type->is_nullable();
+ return CompileType::FromAbstractType(result_type, is_nullable);
}
}
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc
index 1e12eda..628bd55 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc
@@ -2511,7 +2511,8 @@
node->arguments()->names(), arguments, owner()->ic_data_array(),
owner()->GetNextDeoptId(), ConvertRebindRule(node->rebind_rule()));
if (node->function().recognized_kind() != MethodRecognizer::kUnknown) {
- call->set_result_cid(MethodRecognizer::ResultCid(node->function()));
+ call->SetResultType(
+ Z, CompileType::FromCid(MethodRecognizer::ResultCid(node->function())));
}
ReturnDefinition(call);
}
@@ -2650,7 +2651,7 @@
owner()->GetNextDeoptId(), ICData::kStatic);
const intptr_t result_cid = GetResultCidOfListFactory(node);
if (result_cid != kDynamicCid) {
- call->set_result_cid(result_cid);
+ call->SetResultType(Z, CompileType::FromCid(result_cid));
call->set_is_known_list_constructor(true);
// Recognized fixed length array factory must have two arguments:
// (0) type-arguments, (1) length.
@@ -2658,7 +2659,8 @@
arguments->length() == 2);
} else if (node->constructor().recognized_kind() !=
MethodRecognizer::kUnknown) {
- call->set_result_cid(MethodRecognizer::ResultCid(node->constructor()));
+ call->SetResultType(Z, CompileType::FromCid(MethodRecognizer::ResultCid(
+ node->constructor())));
}
ReturnDefinition(call);
return;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 9cf6b55..52d5650 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -732,6 +732,32 @@
return DirectCallMetadata(target, check_receiver_for_null);
}
+InferredTypeMetadata InferredTypeMetadataHelper::GetInferredType(
+ intptr_t node_offset) {
+ const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
+ if (md_offset < 0) {
+ return InferredTypeMetadata(kDynamicCid, true);
+ }
+
+ AlternativeReadingScope alt(builder_->reader_, &H.metadata_payloads(),
+ md_offset - MetadataPayloadOffset);
+
+ const NameIndex kernel_name = builder_->ReadCanonicalNameReference();
+ const bool nullable = builder_->ReadBool();
+
+ if (H.IsRoot(kernel_name)) {
+ return InferredTypeMetadata(kDynamicCid, nullable);
+ }
+
+ const Class& klass =
+ Class::Handle(builder_->zone_, H.LookupClassByKernelClass(kernel_name));
+ ASSERT(!klass.IsNull());
+
+ const intptr_t cid = klass.id();
+
+ return InferredTypeMetadata(cid, nullable);
+}
+
StreamingScopeBuilder::StreamingScopeBuilder(ParsedFunction* parsed_function)
: result_(NULL),
parsed_function_(parsed_function),
@@ -4004,7 +4030,8 @@
intptr_t argument_count = positional_argument_count + named_argument_count;
if (!target.is_static()) ++argument_count;
body += StaticCall(TokenPosition::kNoSource, target, argument_count,
- argument_names, ICData::kNoRebind, type_args_len);
+ argument_names, ICData::kNoRebind,
+ /* result_type = */ NULL, type_args_len);
// Return the result.
body += Return(function_node_helper.end_position_);
@@ -5674,12 +5701,14 @@
intptr_t argument_count,
const Array& argument_names,
ICData::RebindRule rebind_rule,
+ const InferredTypeMetadata* result_type,
intptr_t type_args_count,
intptr_t argument_check_bits,
intptr_t type_argument_check_bits) {
return flow_graph_builder_->StaticCall(
position, target, argument_count, argument_names, rebind_rule,
- type_args_count, argument_check_bits, type_argument_check_bits);
+ result_type, type_args_count, argument_check_bits,
+ type_argument_check_bits);
}
Fragment StreamingFlowGraphBuilder::InstanceCall(
@@ -5703,12 +5732,13 @@
const Array& argument_names,
intptr_t checked_argument_count,
const Function& interface_target,
+ const InferredTypeMetadata* result_type,
intptr_t argument_check_bits,
intptr_t type_argument_check_bits) {
return flow_graph_builder_->InstanceCall(
position, name, kind, type_args_len, argument_count, argument_names,
- checked_argument_count, interface_target, argument_check_bits,
- type_argument_check_bits);
+ checked_argument_count, interface_target, result_type,
+ argument_check_bits, type_argument_check_bits);
}
Fragment StreamingFlowGraphBuilder::ThrowException(TokenPosition position) {
@@ -6072,6 +6102,8 @@
const DirectCallMetadata direct_call =
direct_call_metadata_helper_.GetDirectTargetForPropertyGet(offset);
+ const InferredTypeMetadata result_type =
+ inferred_type_metadata_helper_.GetInferredType(offset);
ReadFlags(); // read flags
@@ -6105,13 +6137,14 @@
if (!direct_call.target_.IsNull()) {
ASSERT(FLAG_precompiled_mode);
instructions +=
- StaticCall(position, direct_call.target_, 1, ICData::kNoRebind);
+ StaticCall(position, direct_call.target_, 1, Array::null_array(),
+ ICData::kNoRebind, &result_type);
} else {
const intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgsChecked = 1;
- instructions +=
- InstanceCall(position, getter_name, Token::kGET, kTypeArgsLen, 1,
- Array::null_array(), kNumArgsChecked, *interface_target);
+ instructions += InstanceCall(
+ position, getter_name, Token::kGET, kTypeArgsLen, 1,
+ Array::null_array(), kNumArgsChecked, *interface_target, &result_type);
}
if (direct_call.check_receiver_for_null_) {
@@ -6173,16 +6206,17 @@
if (!direct_call.target_.IsNull()) {
ASSERT(FLAG_precompiled_mode);
- instructions += StaticCall(position, direct_call.target_, 2,
- Array::null_array(), ICData::kNoRebind,
- /*type_args_len=*/0, argument_check_bits);
+ instructions +=
+ StaticCall(position, direct_call.target_, 2, Array::null_array(),
+ ICData::kNoRebind, /* result_type = */ NULL,
+ /*type_args_len=*/0, argument_check_bits);
} else {
const intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgsChecked = 1;
instructions +=
InstanceCall(position, setter_name, Token::kSET, kTypeArgsLen, 2,
Array::null_array(), kNumArgsChecked, *interface_target,
- argument_check_bits);
+ /* result_type = */ NULL, argument_check_bits);
}
instructions += Drop(); // Drop result of the setter invocation.
@@ -6267,9 +6301,13 @@
}
Fragment StreamingFlowGraphBuilder::BuildSuperPropertyGet(TokenPosition* p) {
+ const intptr_t offset = ReaderOffset() - 1; // Include the tag.
const TokenPosition position = ReadPosition(); // read position.
if (p != NULL) *p = position;
+ const InferredTypeMetadata result_type =
+ inferred_type_metadata_helper_.GetInferredType(offset);
+
Class& klass = GetSuperOrDie();
StringIndex name_index = ReadStringReference(); // read name index.
@@ -6332,7 +6370,8 @@
instructions +=
StaticCall(position, Function::ZoneHandle(Z, function.raw()),
- /* argument_count = */ 1, ICData::kSuper);
+ /* argument_count = */ 1, Array::null_array(),
+ ICData::kSuper, &result_type);
}
return instructions;
@@ -6402,9 +6441,13 @@
}
Fragment StreamingFlowGraphBuilder::BuildDirectPropertyGet(TokenPosition* p) {
+ const intptr_t offset = ReaderOffset() - 1; // Include the tag.
const TokenPosition position = ReadPosition(); // read position.
if (p != NULL) *p = position;
+ const InferredTypeMetadata result_type =
+ inferred_type_metadata_helper_.GetInferredType(offset);
+
ReadFlags(); // read flags.
const Tag receiver_tag = PeekTag(); // peek tag for receiver.
@@ -6448,7 +6491,8 @@
// can't change their structure during hot reload.
// If there are other sources of DirectPropertyGet in the future, this code
// have to be adjusted.
- return instructions + StaticCall(position, target, 1, ICData::kNoRebind);
+ return instructions + StaticCall(position, target, 1, Array::null_array(),
+ ICData::kNoRebind, &result_type);
}
Fragment StreamingFlowGraphBuilder::BuildDirectPropertySet(TokenPosition* p) {
@@ -6484,6 +6528,7 @@
// have to be adjusted.
instructions +=
StaticCall(position, target, 2, Array::null_array(), ICData::kNoRebind,
+ /* result_type = */ NULL,
/*type_args_len=*/0, argument_check_bits,
/*type_argument_check_bits=*/0);
@@ -6492,11 +6537,14 @@
Fragment StreamingFlowGraphBuilder::BuildStaticGet(TokenPosition* p) {
ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
- intptr_t offset = ReaderOffset() - 1; // Include the tag.
+ const intptr_t offset = ReaderOffset() - 1; // Include the tag.
TokenPosition position = ReadPosition(); // read position.
if (p != NULL) *p = position;
+ const InferredTypeMetadata result_type =
+ inferred_type_metadata_helper_.GetInferredType(offset);
+
NameIndex target = ReadCanonicalNameReference(); // read target_reference.
if (H.IsField(target)) {
@@ -6513,7 +6561,8 @@
Fragment instructions = Constant(field);
return instructions + LoadStaticField();
} else {
- return StaticCall(position, getter, 0, ICData::kStatic);
+ return StaticCall(position, getter, 0, Array::null_array(),
+ ICData::kStatic, &result_type);
}
}
} else {
@@ -6521,7 +6570,8 @@
Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
if (H.IsGetter(target)) {
- return StaticCall(position, function, 0, ICData::kStatic);
+ return StaticCall(position, function, 0, Array::null_array(),
+ ICData::kStatic, &result_type);
} else if (H.IsMethod(target)) {
return Constant(constant_evaluator_.EvaluateExpression(offset));
} else {
@@ -6755,6 +6805,8 @@
const DirectCallMetadata direct_call =
direct_call_metadata_helper_.GetDirectTargetForMethodInvocation(offset);
+ const InferredTypeMetadata result_type =
+ inferred_type_metadata_helper_.GetInferredType(offset);
uint8_t flags = ReadFlags(); // read flags.
@@ -6904,13 +6956,14 @@
if (!direct_call.target_.IsNull()) {
ASSERT(FLAG_precompiled_mode);
instructions += StaticCall(position, direct_call.target_, argument_count,
- argument_names, ICData::kNoRebind, type_args_len,
- argument_check_bits, type_argument_check_bits);
+ argument_names, ICData::kNoRebind, &result_type,
+ type_args_len, argument_check_bits,
+ type_argument_check_bits);
} else {
- instructions +=
- InstanceCall(position, name, token_kind, type_args_len, argument_count,
- argument_names, checked_argument_count, *interface_target,
- argument_check_bits, type_argument_check_bits);
+ instructions += InstanceCall(
+ position, name, token_kind, type_args_len, argument_count,
+ argument_names, checked_argument_count, *interface_target, &result_type,
+ argument_check_bits, type_argument_check_bits);
}
// Drop temporaries preserving result on the top of the stack.
@@ -6935,9 +6988,13 @@
Fragment StreamingFlowGraphBuilder::BuildDirectMethodInvocation(
TokenPosition* p) {
+ const intptr_t offset = ReaderOffset() - 1; // Include the tag.
TokenPosition position = ReadPosition(); // read offset.
if (p != NULL) *p = position;
+ const InferredTypeMetadata result_type =
+ inferred_type_metadata_helper_.GetInferredType(offset);
+
uint8_t flags = ReadFlags(); // read flags.
Tag receiver_tag = PeekTag(); // peek tag for receiver.
@@ -7001,17 +7058,21 @@
target, static_cast<DispatchCategory>(flags & 3), &argument_check_bits,
&type_argument_check_bits);
- return instructions + StaticCall(position, target, argument_count,
- argument_names, ICData::kNoRebind,
- type_args_len, argument_check_bits,
- type_argument_check_bits);
+ return instructions +
+ StaticCall(position, target, argument_count, argument_names,
+ ICData::kNoRebind, &result_type, type_args_len,
+ argument_check_bits, type_argument_check_bits);
}
Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation(
TokenPosition* p) {
+ const intptr_t offset = ReaderOffset() - 1; // Include the tag.
const TokenPosition position = ReadPosition(); // read position.
if (p != NULL) *p = position;
+ const InferredTypeMetadata result_type =
+ inferred_type_metadata_helper_.GetInferredType(offset);
+
intptr_t type_args_len = 0;
if (I->reify_generic_functions()) {
AlternativeReadingScope alt(reader_);
@@ -7140,18 +7201,22 @@
/* positional_argument_count = */ NULL); // read arguments.
++argument_count; // include receiver
SkipCanonicalNameReference(); // interfaceTargetReference
- return instructions + StaticCall(position,
- Function::ZoneHandle(Z, function.raw()),
- argument_count, argument_names,
- ICData::kSuper, type_args_len);
+ return instructions +
+ StaticCall(position, Function::ZoneHandle(Z, function.raw()),
+ argument_count, argument_names, ICData::kSuper,
+ &result_type, type_args_len);
}
}
Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
TokenPosition* p) {
+ const intptr_t offset = ReaderOffset() - 1; // Include the tag.
TokenPosition position = ReadPosition(); // read position.
if (p != NULL) *p = position;
+ const InferredTypeMetadata result_type =
+ inferred_type_metadata_helper_.GetInferredType(offset);
+
NameIndex procedure_reference =
ReadCanonicalNameReference(); // read procedure reference.
intptr_t argument_count = PeekArgumentsCount();
@@ -7233,7 +7298,7 @@
instructions += StrictCompare(Token::kEQ_STRICT, /*number_check=*/true);
} else {
instructions += StaticCall(position, target, argument_count, argument_names,
- ICData::kStatic, type_args_len);
+ ICData::kStatic, &result_type, type_args_len);
if (target.IsGenerativeConstructor()) {
// Drop the result of the constructor call and leave [instance_variable]
// on top-of-stack.
@@ -7332,7 +7397,7 @@
Z, H.LookupConstructorByKernelConstructor(klass, kernel_name));
++argument_count;
instructions += StaticCall(position, target, argument_count, argument_names,
- ICData::kStatic);
+ ICData::kStatic, /* result_type = */ NULL);
return instructions + Drop();
}
@@ -9556,6 +9621,16 @@
direct_call_metadata_helper_.SetMetadataMappings(offset + kUInt32Size,
mappings_num);
}
+ } else if (H.StringEquals(tag, InferredTypeMetadataHelper::tag())) {
+ ASSERT(node_references_num == 0);
+
+ if (mappings_num > 0) {
+ if (!FLAG_precompiled_mode) {
+ FATAL("InferredTypeMetadata is allowed in precompiled mode only");
+ }
+ inferred_type_metadata_helper_.SetMetadataMappings(offset + kUInt32Size,
+ mappings_num);
+ }
}
}
}
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 638f638..7a2ea01 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -329,7 +329,7 @@
enum Flag {
kConst = 1 << 0,
kExternal = 1 << 1,
- kSyntheticDefault = 1 << 2,
+ kSynthetic = 1 << 2,
};
explicit ConstructorHelper(StreamingFlowGraphBuilder* builder) {
@@ -348,7 +348,7 @@
bool IsExternal() { return (flags_ & kExternal) != 0; }
bool IsConst() { return (flags_ & kConst) != 0; }
- bool IsSyntheticDefault() { return (flags_ & kSyntheticDefault) != 0; }
+ bool IsSynthetic() { return (flags_ & kSynthetic) != 0; }
NameIndex canonical_name_;
TokenPosition position_;
@@ -571,6 +571,25 @@
bool* check_receiver_for_null);
};
+struct InferredTypeMetadata {
+ InferredTypeMetadata(intptr_t cid_, bool nullable_)
+ : cid(cid_), nullable(nullable_) {}
+
+ const intptr_t cid;
+ const bool nullable;
+};
+
+// Helper class which provides access to inferred type metadata.
+class InferredTypeMetadataHelper : public MetadataHelper {
+ public:
+ static const char* tag() { return "vm.inferred-type.metadata"; }
+
+ explicit InferredTypeMetadataHelper(StreamingFlowGraphBuilder* builder)
+ : MetadataHelper(builder) {}
+
+ InferredTypeMetadata GetInferredType(intptr_t node_offset);
+};
+
class StreamingDartTypeTranslator {
public:
StreamingDartTypeTranslator(StreamingFlowGraphBuilder* builder,
@@ -874,6 +893,7 @@
record_token_positions_into_(NULL),
record_yield_positions_into_(NULL),
direct_call_metadata_helper_(this),
+ inferred_type_metadata_helper_(this),
metadata_scanned_(false) {}
StreamingFlowGraphBuilder(TranslationHelper* translation_helper,
@@ -894,6 +914,7 @@
record_token_positions_into_(NULL),
record_yield_positions_into_(NULL),
direct_call_metadata_helper_(this),
+ inferred_type_metadata_helper_(this),
metadata_scanned_(false) {}
StreamingFlowGraphBuilder(TranslationHelper* translation_helper,
@@ -914,6 +935,7 @@
record_token_positions_into_(NULL),
record_yield_positions_into_(NULL),
direct_call_metadata_helper_(this),
+ inferred_type_metadata_helper_(this),
metadata_scanned_(false) {}
~StreamingFlowGraphBuilder() { delete reader_; }
@@ -1084,6 +1106,7 @@
intptr_t argument_count,
const Array& argument_names,
ICData::RebindRule rebind_rule,
+ const InferredTypeMetadata* result_type = NULL,
intptr_t type_args_len = 0,
intptr_t argument_check_bits = 0,
intptr_t type_argument_check_bits = 0);
@@ -1100,6 +1123,7 @@
const Array& argument_names,
intptr_t checked_argument_count,
const Function& interface_target,
+ const InferredTypeMetadata* result_type = NULL,
intptr_t argument_check_bits = 0,
intptr_t type_argument_check_bits = 0);
Fragment BuildArgumentTypeChecks();
@@ -1298,6 +1322,7 @@
GrowableArray<intptr_t>* record_token_positions_into_;
GrowableArray<intptr_t>* record_yield_positions_into_;
DirectCallMetadataHelper direct_call_metadata_helper_;
+ InferredTypeMetadataHelper inferred_type_metadata_helper_;
bool metadata_scanned_;
friend class ClassHelper;
@@ -1306,6 +1331,7 @@
friend class DirectCallMetadataHelper;
friend class FieldHelper;
friend class FunctionNodeHelper;
+ friend class InferredTypeMetadataHelper;
friend class KernelLoader;
friend class KernelReader;
friend class LibraryDependencyHelper;
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index cc5a679..f004628 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1235,6 +1235,7 @@
const Array& argument_names,
intptr_t checked_argument_count,
const Function& interface_target,
+ const InferredTypeMetadata* result_type,
intptr_t argument_bits,
intptr_t type_argument_bits) {
const intptr_t total_count = argument_count + (type_args_len > 0 ? 1 : 0);
@@ -1243,6 +1244,10 @@
position, name, kind, arguments, type_args_len, argument_names,
checked_argument_count, ic_data_array_, GetNextDeoptId(),
interface_target, argument_bits, type_argument_bits);
+ if (result_type != NULL) {
+ call->SetResultType(Z, CompileType::CreateNullable(result_type->nullable,
+ result_type->cid));
+ }
Push(call);
return Fragment(call);
}
@@ -1506,6 +1511,7 @@
intptr_t argument_count,
const Array& argument_names,
ICData::RebindRule rebind_rule,
+ const InferredTypeMetadata* result_type,
intptr_t type_args_count,
intptr_t argument_bits,
intptr_t type_argument_check_bits) {
@@ -1518,10 +1524,18 @@
const intptr_t list_cid =
GetResultCidOfListFactory(Z, target, argument_count);
if (list_cid != kDynamicCid) {
- call->set_result_cid(list_cid);
+ ASSERT((result_type == NULL) || (result_type->cid == kDynamicCid) ||
+ (result_type->cid == list_cid));
+ call->SetResultType(Z, CompileType::FromCid(list_cid));
call->set_is_known_list_constructor(true);
} else if (target.recognized_kind() != MethodRecognizer::kUnknown) {
- call->set_result_cid(MethodRecognizer::ResultCid(target));
+ intptr_t recognized_cid = MethodRecognizer::ResultCid(target);
+ ASSERT((result_type == NULL) || (result_type->cid == kDynamicCid) ||
+ (result_type->cid == recognized_cid));
+ call->SetResultType(Z, CompileType::FromCid(recognized_cid));
+ } else if (result_type != NULL) {
+ call->SetResultType(Z, CompileType::CreateNullable(result_type->nullable,
+ result_type->cid));
}
Push(call);
return Fragment(call);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 167e13b..6d9948d 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -18,6 +18,7 @@
namespace kernel {
class StreamingFlowGraphBuilder;
+struct InferredTypeMetadata;
class KernelConstMapKeyEqualsTraits {
public:
@@ -699,6 +700,7 @@
const Array& argument_names,
intptr_t checked_argument_count,
const Function& interface_target,
+ const InferredTypeMetadata* result_type = NULL,
intptr_t argument_bits = 0,
intptr_t type_argument_bits = 0);
Fragment ClosureCall(intptr_t type_args_len,
@@ -728,6 +730,7 @@
intptr_t argument_count,
const Array& argument_names,
ICData::RebindRule rebind_rule,
+ const InferredTypeMetadata* result_type = NULL,
intptr_t type_args_len = 0,
intptr_t argument_bits = 0,
intptr_t type_argument_check_bits = 0);
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 94f0dd9..990ce17 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -147,6 +147,7 @@
NOT_IN_PRODUCT(
TimelineDurationScope tds(Timeline::GetVMStream(), "Dart::InitOnce"));
Isolate::InitOnce();
+ IdleNotifier::InitOnce();
PortMap::InitOnce();
FreeListElement::InitOnce();
ForwardingCorpse::InitOnce();
@@ -415,6 +416,7 @@
}
WaitForIsolateShutdown();
+ IdleNotifier::Stop();
// Shutdown the thread pool. On return, all thread pool threads have exited.
if (FLAG_trace_shutdown) {
OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Deleting thread pool\n",
@@ -446,6 +448,7 @@
ShutdownIsolate();
vm_isolate_ = NULL;
ASSERT(Isolate::IsolateListLength() == 0);
+ IdleNotifier::Cleanup();
TargetCPUFeatures::Cleanup();
StoreBuffer::ShutDown();
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index acc162c..6219611 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1444,7 +1444,7 @@
CHECK_ISOLATE(T->isolate());
API_TIMELINE_BEGIN_END;
TransitionNativeToVM transition(T);
- T->isolate()->heap()->NotifyIdle(deadline);
+ T->isolate()->NotifyIdle(deadline);
}
DART_EXPORT void Dart_NotifyLowMemory() {
@@ -1672,6 +1672,57 @@
return Api::Success();
}
+DART_EXPORT Dart_Handle Dart_WaitForEvent(int64_t timeout_millis) {
+ Thread* T = Thread::Current();
+ Isolate* I = T->isolate();
+ CHECK_API_SCOPE(T);
+ CHECK_CALLBACK_STATE(T);
+ API_TIMELINE_BEGIN_END_BASIC;
+ TransitionNativeToVM transition(T);
+ if (I->message_notify_callback() != NULL) {
+ return Api::NewError("waitForEventSync is not supported by this embedder");
+ }
+ Object& result =
+ Object::Handle(Z, DartLibraryCalls::EnsureScheduleImmediate());
+ if (result.IsError()) {
+ return Api::NewHandle(T, result.raw());
+ }
+
+ // Drain the microtask queue. Propagate any errors to the entry frame.
+ result = DartLibraryCalls::DrainMicrotaskQueue();
+ if (result.IsError()) {
+ // Persist the error across unwiding scopes before propagating.
+ const Error* error;
+ {
+ NoSafepointScope no_safepoint;
+ RawError* raw_error = Error::Cast(result).raw();
+ T->UnwindScopes(T->top_exit_frame_info());
+ error = &Error::Handle(T->zone(), raw_error);
+ }
+ Exceptions::PropagateToEntry(*error);
+ UNREACHABLE();
+ return Api::NewError("Unreachable");
+ }
+
+ // Block to wait for messages and then handle them. Propagate any errors to
+ // the entry frame.
+ if (I->message_handler()->PauseAndHandleAllMessages(timeout_millis) !=
+ MessageHandler::kOK) {
+ // Persist the error across unwiding scopes before propagating.
+ const Error* error;
+ {
+ NoSafepointScope no_safepoint;
+ RawError* raw_error = T->get_and_clear_sticky_error();
+ T->UnwindScopes(T->top_exit_frame_info());
+ error = &Error::Handle(T->zone(), raw_error);
+ }
+ Exceptions::PropagateToEntry(*error);
+ UNREACHABLE();
+ return Api::NewError("Unreachable");
+ }
+ return Api::Success();
+}
+
DART_EXPORT bool Dart_HandleServiceMessages() {
#if defined(PRODUCT)
return true;
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 2fde805..7f22976 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -6528,6 +6528,7 @@
bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
+ bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
Dart_Handle result = Dart_SetLibraryTagHandler(library_handler);
EXPECT_VALID(result);
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 6129213..47c52c0 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -660,6 +660,20 @@
return result.raw();
}
+RawObject* DartLibraryCalls::EnsureScheduleImmediate() {
+ Zone* zone = Thread::Current()->zone();
+ const Library& async_lib = Library::Handle(zone, Library::AsyncLibrary());
+ ASSERT(!async_lib.IsNull());
+ const Function& function =
+ Function::Handle(zone, async_lib.LookupFunctionAllowPrivate(
+ Symbols::_ensureScheduleImmediate()));
+ ASSERT(!function.IsNull());
+ const Object& result = Object::Handle(
+ zone, DartEntry::InvokeFunction(function, Object::empty_array()));
+ ASSERT(result.IsNull() || result.IsError());
+ return result.raw();
+}
+
RawObject* DartLibraryCalls::MapSetAt(const Instance& map,
const Instance& key,
const Instance& value) {
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 79ba34b..d28a5cd 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -282,6 +282,11 @@
// Returns null on success, a RawError on failure.
static RawObject* DrainMicrotaskQueue();
+ // Ensures that the isolate's _pendingImmediateCallback is set to
+ // _startMicrotaskLoop from dart:async.
+ // Returns null on success, a RawError on failure.
+ static RawObject* EnsureScheduleImmediate();
+
// map[key] = value;
//
// Returns null on success, a RawError on failure.
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 01ff1c8..667e819 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -815,6 +815,26 @@
UNREACHABLE();
}
+void Exceptions::PropagateToEntry(const Error& error) {
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+ ASSERT(thread->top_exit_frame_info() != 0);
+ Instance& stacktrace = Instance::Handle(zone);
+ if (error.IsUnhandledException()) {
+ const UnhandledException& uhe = UnhandledException::Cast(error);
+ stacktrace = uhe.stacktrace();
+ } else {
+ stacktrace = Exceptions::CurrentStackTrace();
+ }
+ uword handler_pc = 0;
+ uword handler_sp = 0;
+ uword handler_fp = 0;
+ FindErrorHandler(&handler_pc, &handler_sp, &handler_fp);
+ JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, error,
+ stacktrace);
+ UNREACHABLE();
+}
+
void Exceptions::ThrowByType(ExceptionType type, const Array& arguments) {
Thread* thread = Thread::Current();
const Object& result =
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 114e085..fe58b37 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -33,6 +33,9 @@
const Instance& stacktrace);
static void PropagateError(const Error& error);
+ // Propagate an error to the entry frame, skipping over Dart frames.
+ static void PropagateToEntry(const Error& error);
+
// Helpers to create and throw errors.
static RawStackTrace* CurrentStackTrace();
static RawScript* GetCallerScript(DartFrameIterator* iterator);
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 4e0189c..67d23d6 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -97,6 +97,10 @@
"Artificially create type feedback for arithmetic etc. operations") \
P(huge_method_cutoff_in_tokens, int, 20000, \
"Huge method cutoff in tokens: Disables optimizations for huge methods.") \
+ P(idle_timeout_micros, int, 1000 * kMicrosecondsPerMillisecond, \
+ "Consider thread pool isolates for idle tasks after this long.") \
+ P(idle_duration_micros, int, 500 * kMicrosecondsPerMillisecond, \
+ "Allow idle tasks to run for this long.") \
P(interpret_irregexp, bool, USING_DBC, "Use irregexp bytecode interpreter") \
P(lazy_dispatchers, bool, true, "Generate dispatchers lazily") \
P(link_natives_lazily, bool, false, "Link native calls lazily") \
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index 7299746..da02f72 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -783,7 +783,7 @@
// clang-format off
const char* space_str = stats_.space_ == kNew ? "Scavenge" : "Mark-Sweep";
OS::PrintErr(
- "[ GC %9" Pd64 " : %10s(%9s), " // GC(isolate), space(reason)
+ "[ %-13.13s, %10s(%9s), " // GC(isolate), space(reason)
"%4" Pd ", " // count
"%6.2f, " // start time
"%5.1f, " // total time
@@ -796,7 +796,7 @@
"%6.2f, %6.2f, %6.2f, %6.2f, %6.2f, %6.2f, " // times
"%" Pd ", %" Pd ", %" Pd ", %" Pd ", " // data
"]\n", // End with a comma to make it easier to import in spreadsheets.
- isolate()->main_port(), space_str, GCReasonToString(stats_.reason_),
+ isolate()->name(), space_str, GCReasonToString(stats_.reason_),
stats_.num_,
MicrosecondsToSeconds(isolate()->UptimeMicros()),
MicrosecondsToMilliseconds(stats_.after_.micros_ -
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index b755770..17bbc19 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -1638,6 +1638,10 @@
reinterpret_cast<uword>(this));
}
+void Isolate::NotifyIdle(int64_t deadline) {
+ heap()->NotifyIdle(deadline);
+}
+
void Isolate::AddClosureFunction(const Function& function) const {
ASSERT(!Compiler::IsBackgroundCompilation());
GrowableObjectArray& closures =
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 6a569bc..85e8c46 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -317,6 +317,8 @@
#endif
}
+ void NotifyIdle(int64_t deadline);
+
bool compaction_in_progress() const {
return CompactionInProgressBit::decode(isolate_flags_);
}
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 10c8a24..f2e7227 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -985,7 +985,7 @@
true, // is_method
false, // is_closure
&function_node_helper);
- if (constructor_helper.IsSyntheticDefault()) {
+ if (constructor_helper.IsSynthetic()) {
function.set_is_debuggable(false);
}
diff --git a/runtime/vm/message_handler.cc b/runtime/vm/message_handler.cc
index e35d72a..f7f94ef 100644
--- a/runtime/vm/message_handler.cc
+++ b/runtime/vm/message_handler.cc
@@ -54,6 +54,7 @@
: queue_(new MessageQueue()),
oob_queue_(new MessageQueue()),
oob_message_handling_allowed_(true),
+ paused_for_messages_(false),
live_ports_(0),
paused_(0),
#if !defined(PRODUCT)
@@ -66,6 +67,7 @@
delete_me_(false),
pool_(NULL),
task_(NULL),
+ idle_start_time_(0),
start_callback_(NULL),
end_callback_(NULL),
callback_data_(0) {
@@ -74,6 +76,7 @@
}
MessageHandler::~MessageHandler() {
+ IdleNotifier::Remove(this);
delete queue_;
delete oob_queue_;
queue_ = NULL;
@@ -151,6 +154,9 @@
} else {
queue_->Enqueue(message, before_events);
}
+ if (paused_for_messages_) {
+ ml.Notify();
+ }
message = NULL; // Do not access message. May have been deleted.
if ((pool_ != NULL) && (task_ == NULL)) {
@@ -165,6 +171,19 @@
MessageNotify(saved_priority);
}
+void MessageHandler::EnsureTaskForIdleCheck() {
+ MonitorLocker ml(&monitor_);
+ if ((pool_ != NULL) && (task_ == NULL)) {
+ task_ = new MessageHandlerTask(this);
+ bool task_running = pool_->Run(task_);
+ if (!task_running) {
+ OS::PrintErr("Failed to start idle wakeup\n");
+ delete task_;
+ task_ = NULL;
+ }
+ }
+}
+
Message* MessageHandler::DequeueMessage(Message::Priority min_priority) {
// TODO(turnidge): Add assert that monitor_ is held here.
Message* message = oob_queue_->Dequeue();
@@ -230,6 +249,13 @@
break;
}
+ // Remember time since the last message. Don't consider OOB messages so
+ // using Observatory doesn't trigger additional idle tasks.
+ if ((FLAG_idle_timeout_micros != 0) &&
+ (saved_priority == Message::kNormalPriority)) {
+ idle_start_time_ = OS::GetCurrentMonotonicMicros();
+ }
+
// Some callers want to process only one normal message and then quit. At
// the same time it is OK to process multiple OOB messages.
if ((saved_priority == Message::kNormalPriority) &&
@@ -276,6 +302,36 @@
return HandleMessages(&ml, true, true);
}
+MessageHandler::MessageStatus MessageHandler::PauseAndHandleAllMessages(
+ int64_t timeout_millis) {
+ MonitorLocker ml(&monitor_);
+ ASSERT(task_ != NULL);
+ ASSERT(!delete_me_);
+#if defined(DEBUG)
+ CheckAccess();
+#endif
+ paused_for_messages_ = true;
+ while (queue_->IsEmpty() && oob_queue_->IsEmpty()) {
+ Monitor::WaitResult wr = ml.Wait(timeout_millis);
+ ASSERT(task_ != NULL);
+ ASSERT(!delete_me_);
+ if (wr == Monitor::kTimedOut) {
+ break;
+ }
+ if (queue_->IsEmpty()) {
+ // There are only OOB messages. Handle them and then continue waiting for
+ // normal messages unless there is an error.
+ MessageStatus status = HandleMessages(&ml, false, false);
+ if (status != kOK) {
+ paused_for_messages_ = false;
+ return status;
+ }
+ }
+ }
+ paused_for_messages_ = false;
+ return HandleMessages(&ml, true, true);
+}
+
MessageHandler::MessageStatus MessageHandler::HandleOOBMessages() {
if (!oob_message_handling_allowed_) {
return kOK;
@@ -373,9 +429,18 @@
ml.Enter();
}
- // Handle any pending messages for this message handler.
- if (status != kShutdown) {
- status = HandleMessages(&ml, (status == kOK), true);
+ bool handle_messages = true;
+ while (handle_messages) {
+ handle_messages = false;
+
+ // Handle any pending messages for this message handler.
+ if (status != kShutdown) {
+ status = HandleMessages(&ml, (status == kOK), true);
+ }
+
+ if (status == kOK) {
+ handle_messages = CheckAndRunIdleLocked(&ml);
+ }
}
}
@@ -448,6 +513,36 @@
}
}
+bool MessageHandler::CheckAndRunIdleLocked(MonitorLocker* ml) {
+ if ((isolate() == NULL) || (idle_start_time_ == 0) ||
+ (FLAG_idle_timeout_micros == 0)) {
+ return false;
+ }
+
+ const int64_t now = OS::GetCurrentMonotonicMicros();
+ const int64_t idle_expirary = idle_start_time_ + FLAG_idle_timeout_micros;
+ if (idle_expirary > now) {
+ IdleNotifier::Update(this, idle_expirary);
+ // No new messages.
+ return false;
+ }
+
+ // We've been without a message long enough to hope we can do some
+ // cleanup before the next message arrives.
+ const int64_t deadline = now + FLAG_idle_duration_micros;
+ // Idle tasks may take a while: don't block other isolates sending
+ // us messages.
+ ml->Exit();
+ {
+ StartIsolateScope start_isolate(isolate());
+ isolate()->NotifyIdle(deadline);
+ idle_start_time_ = 0;
+ }
+ ml->Enter();
+ // We may have received new messages while the monitor was released.
+ return true;
+}
+
void MessageHandler::ClosePort(Dart_Port port) {
MonitorLocker ml(&monitor_);
if (FLAG_trace_isolates) {
@@ -583,4 +678,122 @@
handler_->oob_message_handling_allowed_ = true;
}
+Monitor* IdleNotifier::monitor_ = NULL;
+bool IdleNotifier::task_running_ = false;
+IdleNotifier::Timer* IdleNotifier::queue_ = NULL;
+
+void IdleNotifier::InitOnce() {
+ monitor_ = new Monitor();
+}
+
+void IdleNotifier::Stop() {
+ Timer* timer;
+
+ {
+ MonitorLocker ml(monitor_);
+ timer = queue_;
+ queue_ = NULL;
+ ml.Notify();
+ while (task_running_) {
+ ml.Wait();
+ }
+ }
+
+ while (timer != NULL) {
+ Timer* next = timer->next;
+ delete timer;
+ timer = next;
+ }
+}
+
+void IdleNotifier::Cleanup() {
+ ASSERT(queue_ == NULL);
+ ASSERT(!task_running_);
+ delete monitor_;
+ monitor_ = NULL;
+}
+
+class IdleNotifier::Task : public ThreadPool::Task {
+ private:
+ void Run() {
+ MonitorLocker ml(monitor_);
+ while (queue_ != NULL) {
+ Timer* timer = queue_;
+ const int64_t now = OS::GetCurrentMonotonicMicros();
+ if (now >= timer->expirary) {
+ MessageHandler* handler = timer->handler;
+ queue_ = timer->next;
+ delete timer;
+ // A handler may try to update its expirary while we try to start its
+ // task for idle notification.
+ ml.Exit();
+ handler->EnsureTaskForIdleCheck();
+ ml.Enter();
+ } else {
+ ml.WaitMicros(timer->expirary - now);
+ }
+ }
+ task_running_ = false;
+ ml.Notify();
+ }
+};
+
+void IdleNotifier::Update(MessageHandler* handler, int64_t expirary) {
+ MonitorLocker ml(monitor_);
+
+ Timer* prev = NULL;
+ Timer* timer = queue_;
+ while (timer != NULL) {
+ if (timer->handler == handler) {
+ if (prev == NULL) {
+ queue_ = timer->next;
+ } else {
+ prev->next = timer->next;
+ }
+ if (expirary == 0) {
+ delete timer;
+ } else {
+ timer->expirary = expirary;
+ }
+ break;
+ } else {
+ prev = timer;
+ timer = timer->next;
+ }
+ }
+
+ if (expirary != 0) {
+ Timer* insert_timer = timer;
+ if (insert_timer == NULL) {
+ insert_timer = new Timer;
+ insert_timer->handler = handler;
+ insert_timer->expirary = expirary;
+ }
+
+ prev = NULL;
+ timer = queue_;
+ while ((timer != NULL) && (timer->expirary < insert_timer->expirary)) {
+ prev = timer;
+ timer = timer->next;
+ }
+ if (prev == NULL) {
+ queue_ = insert_timer;
+ } else {
+ prev->next = insert_timer;
+ }
+ insert_timer->next = timer;
+ }
+
+ if (task_running_) {
+ ml.Notify();
+ } else if (queue_ != NULL) {
+ Task* task = new Task();
+ task_running_ = Dart::thread_pool()->Run(task);
+ if (!task_running_) {
+ OS::PrintErr("Failed to start idle ticker\n");
+ delete task;
+ }
+ }
+}
+
} // namespace dart
diff --git a/runtime/vm/message_handler.h b/runtime/vm/message_handler.h
index d34b05b..a7d9f96 100644
--- a/runtime/vm/message_handler.h
+++ b/runtime/vm/message_handler.h
@@ -50,6 +50,10 @@
EndCallback end_callback,
CallbackData data);
+ // Starts a task for the message handler if it runs on the thread pool and a
+ // task is not already running.
+ void EnsureTaskForIdleCheck();
+
// Handles the next message for this message handler. Should only
// be used when not running the handler on the thread pool (via Run
// or RunBlocking).
@@ -70,6 +74,10 @@
// Returns true on success.
MessageStatus HandleOOBMessages();
+ // Blocks the thread on a condition variable until a message arrives, and then
+ // handles all messages.
+ MessageStatus PauseAndHandleAllMessages(int64_t timeout_millis);
+
// Returns true if there are pending OOB messages for this message
// handler.
bool HasOOBMessages();
@@ -210,6 +218,10 @@
// Called by MessageHandlerTask to process our task queue.
void TaskCallback();
+ // Returns true if the monitor was exited and there may be new OOB messages
+ // to process.
+ bool CheckAndRunIdleLocked(MonitorLocker* ml);
+
// NOTE: These two functions release and reacquire the monitor, you may
// need to call HandleMessages to ensure all pending messages are handled.
void PausedOnStartLocked(MonitorLocker* ml, bool paused);
@@ -232,6 +244,7 @@
// This flag is not thread safe and can only reliably be accessed on a single
// thread.
bool oob_message_handling_allowed_;
+ bool paused_for_messages_;
intptr_t live_ports_; // The number of open ports, including control ports.
intptr_t paused_; // The number of pause messages received.
#if !defined(PRODUCT)
@@ -244,6 +257,7 @@
bool delete_me_;
ThreadPool* pool_;
ThreadPool::Task* task_;
+ int64_t idle_start_time_;
StartCallback start_callback_;
EndCallback end_callback_;
CallbackData callback_data_;
@@ -251,6 +265,28 @@
DISALLOW_COPY_AND_ASSIGN(MessageHandler);
};
+class IdleNotifier : public AllStatic {
+ public:
+ static void InitOnce();
+ static void Stop();
+ static void Cleanup();
+ static void Update(MessageHandler* handler, int64_t expirary);
+ static void Remove(MessageHandler* handler) { Update(handler, 0); }
+
+ private:
+ class Task;
+
+ struct Timer {
+ MessageHandler* handler;
+ int64_t expirary;
+ Timer* next;
+ };
+
+ static Monitor* monitor_;
+ static bool task_running_;
+ static Timer* queue_;
+};
+
} // namespace dart
#endif // RUNTIME_VM_MESSAGE_HANDLER_H_
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index 62e072a..ff43451 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -1247,7 +1247,7 @@
heap_growth_max_(heap_growth_max),
garbage_collection_time_ratio_(garbage_collection_time_ratio),
last_code_collection_in_us_(OS::GetCurrentMonotonicMicros()),
- idle_gc_threshold_in_words_(grow_heap_ / 2 * kPageSizeInWords) {}
+ idle_gc_threshold_in_words_(0) {}
PageSpaceController::~PageSpaceController() {}
@@ -1267,22 +1267,11 @@
Utils::RoundUp(capacity_increase_in_words, kPageSizeInWords);
intptr_t capacity_increase_in_pages =
capacity_increase_in_words / kPageSizeInWords;
- double multiplier = 1.0;
- // To avoid waste, the first GC should be triggered before too long. After
- // kInitialTimeoutSeconds, gradually lower the capacity limit.
- static const double kInitialTimeoutSeconds = 1.00;
- if (history_.IsEmpty()) {
- double seconds_since_init =
- MicrosecondsToSeconds(heap_->isolate()->UptimeMicros());
- if (seconds_since_init > kInitialTimeoutSeconds) {
- multiplier *= (seconds_since_init / kInitialTimeoutSeconds);
- }
- }
- bool needs_gc = capacity_increase_in_pages * multiplier > grow_heap_;
+ bool needs_gc = capacity_increase_in_pages > grow_heap_;
if (FLAG_log_growth) {
- OS::PrintErr("%s: %" Pd " * %f %s %" Pd "\n",
- needs_gc ? "NEEDS GC" : "grow", capacity_increase_in_pages,
- multiplier, needs_gc ? ">" : "<=", grow_heap_);
+ OS::PrintErr("%s: allocate %s %" Pd " %s %" Pd "\n",
+ heap_->isolate()->name(), needs_gc ? "collect" : "grow",
+ capacity_increase_in_pages, needs_gc ? ">" : "<=", grow_heap_);
}
return needs_gc;
}
@@ -1294,19 +1283,12 @@
if (heap_growth_ratio_ == 100) {
return false;
}
- double multiplier = 1.0;
- // To avoid waste, the first GC should be triggered before too long. After
- // kInitialTimeoutSeconds, gradually lower the capacity limit.
- static const double kInitialTimeoutSeconds = 1.00;
- if (history_.IsEmpty()) {
- double seconds_since_init =
- MicrosecondsToSeconds(heap_->isolate()->UptimeMicros());
- if (seconds_since_init > kInitialTimeoutSeconds) {
- multiplier *= (seconds_since_init / kInitialTimeoutSeconds);
- }
+ bool needs_gc = current.used_in_words > idle_gc_threshold_in_words_;
+ if (FLAG_log_growth) {
+ OS::PrintErr("%s: idle %s %" Pd " %s %" Pd "\n", heap_->isolate()->name(),
+ needs_gc ? "collect" : "grow", current.used_in_words,
+ needs_gc ? ">" : "<=", idle_gc_threshold_in_words_);
}
- bool needs_gc =
- current.used_in_words * multiplier > idle_gc_threshold_in_words_;
return needs_gc;
}
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index fbbc1b7..4d99e0f 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -2678,9 +2678,11 @@
// The '2' variant is inclusive from and exclusive to.
// This covers \s as defined in ECMA-262 5.1, 15.10.2.12,
// which include WhiteSpace (7.2) or LineTerminator (7.3) values.
+// 0x180E has been removed from Unicode's Zs category and thus
+// from ECMAScript's WhiteSpace category as of Unicode 6.3.
static const intptr_t kSpaceRanges[] = {
- '\t', '\r' + 1, ' ', ' ' + 1, 0x00A0, 0x00A1, 0x1680, 0x1681,
- 0x180E, 0x180F, 0x2000, 0x200B, 0x2028, 0x202A, 0x202F, 0x2030,
+ '\t', '\r' + 1, ' ', ' ' + 1, 0x00A0, 0x00A1, 0x1680,
+ 0x1681, 0x2000, 0x200B, 0x2028, 0x202A, 0x202F, 0x2030,
0x205F, 0x2060, 0x3000, 0x3001, 0xFEFF, 0xFF00, 0x10000};
static const intptr_t kSpaceRangeCount = ARRAY_SIZE(kSpaceRanges);
static const intptr_t kWordRanges[] = {'0', '9' + 1, 'A', 'Z' + 1, '_',
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 5c7f208..0d2dfcd 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -430,6 +430,7 @@
V(ConstructorStacktracePrefix, "new ") \
V(_runExtension, "_runExtension") \
V(_runPendingImmediateCallback, "_runPendingImmediateCallback") \
+ V(_ensureScheduleImmediate, "_ensureScheduleImmediate") \
V(DartLibrary, "dart.library.") \
V(DartLibraryMirrors, "dart.library.mirrors") \
V(_name, "_name") \
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 74f34c4..caba5b0 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -285,6 +285,7 @@
bool is_dart_scheme_url = DartUtils::IsDartSchemeURL(url_chars);
bool is_io_library = DartUtils::IsDartIOLibURL(library_url_string);
+ bool is_standalone_library = DartUtils::IsDartCLILibURL(library_url_string);
if (is_dart_scheme_url) {
ASSERT(tag == Dart_kImportTag);
// Handle imports of other built-in libraries present in the SDK.
@@ -292,6 +293,8 @@
return Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
} else if (DartUtils::IsDartBuiltinLibURL(url_chars)) {
return Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
+ } else if (DartUtils::IsDartCLILibURL(url_chars)) {
+ return Builtin::LoadAndCheckLibrary(Builtin::kCLILibrary);
} else {
return DartUtils::NewError("Do not know how to load '%s'", url_chars);
}
@@ -316,6 +319,12 @@
Builtin::PartSource(Builtin::kIOLibrary, url_chars),
0, 0);
}
+ if (is_standalone_library) {
+ ASSERT(tag == Dart_kSourceTag);
+ return Dart_LoadSource(library, url, Dart_Null(),
+ Builtin::PartSource(Builtin::kCLILibrary, url_chars),
+ 0, 0);
+ }
Dart_Handle resolved_url = url;
const char* resolved_url_chars = url_chars;
if (IsPackageSchemeURL(url_chars)) {
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 41adf01..1bff383 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -179,6 +179,7 @@
_platform_sdk_libraries = [
"_internal",
"async",
+ "cli",
"collection",
"convert",
"core",
@@ -198,6 +199,7 @@
"_chrome",
"_internal",
"async",
+ "cli",
"collection",
"convert",
"core",
@@ -314,7 +316,7 @@
}
# Copies the Dart VM binary into bin/
-if (is_fuchsia_host) {
+if (target_os != current_os && target_os == "fuchsia") {
# In the Fuchsia build, this has to use a symlink for two reasons.
# First, it makes the lookup of shared libraries relative to $ORIGIN
# (Linux) or @loader_path (macOS) find the libraries where they are,
diff --git a/sdk/lib/_internal/js_runtime/lib/cli_patch.dart b/sdk/lib/_internal/js_runtime/lib/cli_patch.dart
new file mode 100644
index 0000000..6921e60
--- /dev/null
+++ b/sdk/lib/_internal/js_runtime/lib/cli_patch.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:_js_helper' show patch;
+
+@patch
+void _waitForEvent(int timeoutMillis) {
+ throw new UnsupportedError("waitForEvent");
+}
diff --git a/sdk/lib/_internal/js_runtime/lib/interceptors.dart b/sdk/lib/_internal/js_runtime/lib/interceptors.dart
index 9bc4bf1..7221968 100644
--- a/sdk/lib/_internal/js_runtime/lib/interceptors.dart
+++ b/sdk/lib/_internal/js_runtime/lib/interceptors.dart
@@ -36,6 +36,7 @@
stringReplaceFirstUnchecked,
stringReplaceFirstMappedUnchecked,
stringReplaceRangeUnchecked,
+ stringSplitUnchecked,
throwConcurrentModificationError,
lookupAndCacheInterceptor,
StringMatch,
diff --git a/sdk/lib/_internal/js_runtime/lib/js_string.dart b/sdk/lib/_internal/js_runtime/lib/js_string.dart
index b149c23..91e9734 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_string.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_string.dart
@@ -92,10 +92,10 @@
List<String> split(Pattern pattern) {
checkNull(pattern);
if (pattern is String) {
- return JS('JSExtendableArray', r'#.split(#)', this, pattern);
+ return stringSplitUnchecked(this, pattern);
} else if (pattern is JSSyntaxRegExp && regExpCaptureCount(pattern) == 0) {
var re = regExpGetNative(pattern);
- return JS('JSExtendableArray', r'#.split(#)', this, re);
+ return stringSplitUnchecked(this, re);
} else {
return _defaultSplit(pattern);
}
diff --git a/sdk/lib/_internal/js_runtime/lib/string_helper.dart b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
index cf8b17a..0180369 100644
--- a/sdk/lib/_internal/js_runtime/lib/string_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
@@ -20,6 +20,11 @@
return stringIndexOfStringUnchecked(receiver, other, startIndex) >= 0;
}
+List<String> stringSplitUnchecked(String receiver, pattern) {
+ return new JSArray<String>.markGrowable(JS(
+ 'returns:JSExtendableArray;new:true', '#.split(#)', receiver, pattern));
+}
+
class StringMatch implements Match {
const StringMatch(int this.start, String this.input, String this.pattern);
diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
index 6b016f4..5f3a40c 100644
--- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -117,6 +117,9 @@
implementation: true,
documented: false,
platforms: DART2JS_PLATFORM),
+ "cli": const LibraryInfo("cli/cli.dart",
+ categories: "Server",
+ dart2jsPatchPath: "_internal/js_runtime/lib/cli_patch.dart"),
"svg": const LibraryInfo("svg/dart2js/svg_dart2js.dart",
categories: "Client",
maturity: Maturity.WEB_STABLE,
diff --git a/sdk/lib/cli/cli.dart b/sdk/lib/cli/cli.dart
new file mode 100644
index 0000000..1dc4ca7
--- /dev/null
+++ b/sdk/lib/cli/cli.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2017, 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.
+
+library dart.cli;
+
+import 'dart:async';
+import 'dart:math';
+
+part 'wait_for.dart';
diff --git a/sdk/lib/cli/cli_sources.gni b/sdk/lib/cli/cli_sources.gni
new file mode 100644
index 0000000..e90e1de
--- /dev/null
+++ b/sdk/lib/cli/cli_sources.gni
@@ -0,0 +1,10 @@
+# Copyright (c) 2017, 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.
+
+cli_sdk_sources = [
+ "cli.dart",
+
+ # The above file needs to be first if additional parts are added to the lib.
+ "wait_for.dart",
+]
diff --git a/sdk/lib/cli/wait_for.dart b/sdk/lib/cli/wait_for.dart
new file mode 100644
index 0000000..03089bd
--- /dev/null
+++ b/sdk/lib/cli/wait_for.dart
@@ -0,0 +1,149 @@
+// Copyright (c) 2017, 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.
+
+part of dart.cli;
+
+/**
+ * Synchronously blocks the calling isolate to wait for asynchronous events to
+ * complete.
+ *
+ * If the [timeout] parameter is supplied, [waitForEvent] will return after
+ * the specified timeout even if no events have occurred.
+ *
+ * This call does the following:
+ * - suspends the current execution stack,
+ * - runs the microtask queue until it is empty,
+ * - waits until the message queue is not empty,
+ * - handles messages on the message queue, plus their associated microtasks,
+ * until the message queue is empty,
+ * - resumes the original stack.
+ *
+ * This function breaks the usual promise offered by Dart semantics that
+ * message handlers and microtasks run to completion before the next message
+ * handler or microtask begins to run. Of particular note is that use of this
+ * function in a finally block will allow microtasks and message handlers to
+ * run before all finally blocks for an exception have completed, possibly
+ * breaking invariants in your program.
+ *
+ * This function will synchronously throw the first unhandled exception it
+ * encounters in running the microtasks and message handlers as though the
+ * throwing microtask or message handler was the only Dart invocation on the
+ * stack. That is, unhandled exceptions in a microtask or message handler will
+ * skip over stacks suspended in a call to [waitForEvent].
+ *
+ * Calls to this function may be nested. Earlier invocations will not
+ * be able to complete until subsequent ones do. Messages that arrive after
+ * a subsequent invocation are "consumed" by that invocation, and do not
+ * unblock an earlier invocation. Please be aware that nesting calls to
+ * [waitForEvent] can lead to deadlock when subsequent calls block to wait for
+ * a condition that is only satisfied after an earlier call returns.
+ *
+ * Please note that this call is only available in the standalone command-line
+ * Dart VM. Further, because it suspends the current execution stack until the
+ * message queue is empty, even when running in the standalone command-line VM
+ * there exists a risk that the current execution stack will be starved.
+ */
+external void _waitForEvent(int timeoutMillis);
+
+void Function(int) _getWaitForEvent() => _waitForEvent;
+
+// This should be set from C++ code by the embedder to wire up waitFor() to the
+// native implementation. In the standalone VM this is set to _waitForEvent()
+// above. If it is null, calling waitFor() will throw an UnsupportedError.
+void Function(int) _waitForEventClosure;
+
+class _WaitForUtils {
+ static void waitForEvent({Duration timeout}) {
+ if (_waitForEventClosure == null) {
+ throw new UnsupportedError("waitFor is not supported by this embedder");
+ }
+ _waitForEventClosure(timeout == null ? 0 : max(1, timeout.inMilliseconds));
+ }
+}
+
+/**
+ * Suspends the stack, runs microtasks, and handles incoming events until
+ * [future] completes.
+ *
+ * WARNING: EXPERIMENTAL. USE AT YOUR OWN RISK.
+ *
+ * This call does the following:
+ * - While [future] is not completed:
+ * - suspends the current execution stack,
+ * - runs the microtask queue until it is empty,
+ * - waits until the message queue is not empty,
+ * - handles messages on the message queue, plus their associated microtasks,
+ * until the message queue is empty,
+ * - resumes the original stack.
+ *
+ * This function breaks the usual promise offered by Dart semantics that
+ * message handlers and microtasks run to completion before the next message
+ * handler or microtask begins to run. Of particular note is that use of this
+ * function in a finally block will allow microtasks and message handlers to
+ * run before all finally blocks for an exception have completed, possibly
+ * breaking invariants in your program.
+ *
+ * Use of this function should be considered a last resort when it is not
+ * possible to convert a Dart program entirely to an asynchronous style using
+ * `async` and `await`.
+ *
+ * If the [Future] completes normally, its result is returned. If the [Future]
+ * completes with an error, the error and stack trace are wrapped in an
+ * [AsyncError] and thrown. If a microtask or message handler run during this
+ * call results in an unhandled exception, that exception will be propagated
+ * as though the microtask or message handler was the only Dart invocation on
+ * the stack. That is, unhandled exceptions in a microtask or message handler
+ * will skip over stacks suspended in a call to [waitFor].
+ *
+ * If the optional `timeout` parameter is passed, [waitFor] throws a
+ * [TimeoutException] if the [Future] is not completed within the specified
+ * period.
+ *
+ * Calls to [waitFor] may be nested. Earlier invocations will not complete
+ * until subsequent ones do, but the completion of a subsequent invocation will
+ * cause the previous invocation to wake up and check its [Future] for
+ * completion.
+ *
+ * Please be aware that nesting calls to [waitFor] can lead to deadlock if
+ * subsequent calls block waiting for a condition that is only satisfied when
+ * an earlier call returns.
+ */
+@provisional
+T waitFor<T>(Future<T> future, {Duration timeout}) {
+ T result;
+ Object error;
+ StackTrace stacktrace;
+ future.then((r) {
+ result = r;
+ }, onError: (e, st) {
+ error = e;
+ stacktrace = st;
+ });
+
+ Stopwatch s;
+ if (timeout != null) {
+ s = new Stopwatch()..start();
+ }
+ Timer.run(() {}); // Enusre there is at least one message.
+ while ((result == null) && (error == null)) {
+ Duration remaining;
+ if (timeout != null) {
+ if (s.elapsed >= timeout) {
+ throw new TimeoutException("waitFor() timed out", timeout);
+ }
+ remaining = timeout - s.elapsed;
+ }
+ _WaitForUtils.waitForEvent(timeout: remaining);
+ }
+ if (timeout != null) {
+ s.stop();
+ }
+ Timer.run(() {}); // Ensure that previous calls to waitFor are woken up.
+
+ if (error != null) {
+ throw new AsyncError(error, stacktrace);
+ }
+
+ return result;
+}
diff --git a/sdk/lib/convert/utf.dart b/sdk/lib/convert/utf.dart
index 1dadd36..b5850a6 100644
--- a/sdk/lib/convert/utf.dart
+++ b/sdk/lib/convert/utf.dart
@@ -27,7 +27,7 @@
* 0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
*/
const Utf8Codec utf8 = const Utf8Codec();
-/** Deprecated, use [tf8Codec] instead. */
+/** Deprecated, use [Utf8Codec] instead. */
const Utf8Codec UTF8 = utf8;
/**
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index bf18121..ce66b2d 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -321,14 +321,13 @@
* Whitespace is defined by the Unicode White_Space property (as defined in
* version 6.2 or later) and the BOM character, 0xFEFF.
*
- * Here is the list of trimmed characters (following version 6.2):
+ * Here is the list of trimmed characters (following version 6.3):
*
* 0009..000D ; White_Space # Cc <control-0009>..<control-000D>
* 0020 ; White_Space # Zs SPACE
* 0085 ; White_Space # Cc <control-0085>
* 00A0 ; White_Space # Zs NO-BREAK SPACE
* 1680 ; White_Space # Zs OGHAM SPACE MARK
- * 180E ; White_Space # Zs MONGOLIAN VOWEL SEPARATOR
* 2000..200A ; White_Space # Zs EN QUAD..HAIR SPACE
* 2028 ; White_Space # Zl LINE SEPARATOR
* 2029 ; White_Space # Zp PARAGRAPH SEPARATOR
diff --git a/sdk/lib/dart_client.platform b/sdk/lib/dart_client.platform
index a42f16b..3813dc0 100644
--- a/sdk/lib/dart_client.platform
+++ b/sdk/lib/dart_client.platform
@@ -29,6 +29,7 @@
_http: unsupported:_http/http.dart
indexed_db: indexed_db/dart2js/indexed_db_dart2js.dart
io: unsupported:io/io.dart
+cli: unsupported:cli/cli.dart
isolate: isolate/isolate.dart
js: js/dart2js/js_dart2js.dart
js_util: js_util/dart2js/js_util_dart2js.dart
diff --git a/sdk/lib/dart_server.platform b/sdk/lib/dart_server.platform
index 6aadf8a..de57d4c 100644
--- a/sdk/lib/dart_server.platform
+++ b/sdk/lib/dart_server.platform
@@ -20,6 +20,7 @@
core: core/core.dart
developer: developer/developer.dart
io: io/io.dart
+cli: cli/cli.dart
isolate: isolate/isolate.dart
math: math/math.dart
mirrors: mirrors/mirrors.dart
diff --git a/sdk/lib/dart_shared.platform b/sdk/lib/dart_shared.platform
index 3d98e94..be8ed61 100644
--- a/sdk/lib/dart_shared.platform
+++ b/sdk/lib/dart_shared.platform
@@ -23,6 +23,7 @@
_http: _http/http.dart
indexed_db: indexed_db/dart2js/indexed_db_dart2js.dart
io: io/io.dart
+cli: cli/cli.dart
isolate: isolate/isolate.dart
js: js/dart2js/js_dart2js.dart
js_util: js_util/dart2js/js_util_dart2js.dart
diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart
index e374096d..5f57649 100644
--- a/sdk/lib/developer/timeline.dart
+++ b/sdk/lib/developer/timeline.dart
@@ -78,7 +78,7 @@
///
/// [Timeline]'s methods add synchronous events to the timeline. When
/// generating a timeline in Chrome's tracing format, using [Timeline] generates
-/// "Complete" events. [Timeline]'s [startSync] and [endSync] can be used
+/// "Complete" events. [Timeline]'s [startSync] and [finishSync] can be used
/// explicitly, or implicitly by wrapping a closure in [timeSync]. For exmaple:
///
/// ```dart
diff --git a/sdk/lib/internal/iterable.dart b/sdk/lib/internal/iterable.dart
index 01ac05e..7123c47 100644
--- a/sdk/lib/internal/iterable.dart
+++ b/sdk/lib/internal/iterable.dart
@@ -730,7 +730,7 @@
Iterable<E> where(bool test(E element)) => this;
- Iterable<T> map<T>(T f(E element)) => const EmptyIterable();
+ Iterable<T> map<T>(T f(E element)) => new EmptyIterable<T>();
E reduce(E combine(E value, E element)) {
throw IterableElementError.noElement();
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index 82c4ff4..be981c7 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -6,6 +6,12 @@
"_builtin": {
"uri": "../../runtime/bin/builtin.dart"
},
+ "cli": {
+ "patches": [
+ "../../runtime/bin/cli_patch.dart"
+ ],
+ "uri": "cli/cli.dart"
+ },
"core": {
"patches": [
"../../runtime/lib/core_patch.dart",
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index 6c88c97..deff85f 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -128,10 +128,15 @@
profiler:
uri: "profiler/profiler.dart"
+ cli:
+ uri: "cli/cli.dart"
+ patches:
+ - "../../runtime/bin/cli_patch.dart"
+
typed_data:
uri: "typed_data/typed_data.dart"
patches: "../../runtime/lib/typed_data_patch.dart"
-
+
_vmservice:
uri: "vmservice/vmservice.dart"
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 794ab91..5f6aca9 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -820,7 +820,7 @@
*
* If this class is the result of a mixin application of the form S with M,
* returns a class mirror on M. Otherwise returns a class mirror on
- * [reflectee].
+ * the reflectee.
*/
ClassMirror get mixin;
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index d81a4d4..574c8c1 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -180,7 +180,6 @@
LibTest/core/List/getRange_A03_t01: RuntimeError, OK # Tests that fail because they use the legacy try-catch syntax. co19 issue 184.
LibTest/core/List/removeAt_A02_t01: RuntimeError # Issue 1533
LibTest/core/List/sort_A01_t06: Slow, Pass # Slow tests that needs extra time to finish.
-LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: Pass, RuntimeError # https://github.com/dart-lang/sdk/issues/29814
LibTest/core/double/INFINITY_A01_t04: RuntimeError # Expected to fail because double.INFINITY is int.
LibTest/core/double/NEGATIVE_INFINITY_A01_t04: RuntimeError # Expected to fail because double.NEGATIVE_INFINITY is int.
LibTest/core/int/hashCode_A01_t01: RuntimeError, OK # co19 issue 308
@@ -981,7 +980,6 @@
LayoutTests/fast/xpath/py-dom-xpath/paths_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xpath/reverse-axes_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xsl/default-html_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Pass, RuntimeError # https://github.com/dart-lang/sdk/issues/29814
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
@@ -2031,10 +2029,11 @@
LayoutTests/fast/xpath/py-dom-xpath/paths_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xpath/reverse-axes_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xsl/default-html_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # DRT is not on Unicode 6.3 yet.
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Please triage this failure
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Please triage this failure
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: Fail # DRT is not on Unicode 6.3 yet.
LibTest/core/int/compareTo_A01_t01: RuntimeError # Please triage this failure
LibTest/core/int/operator_left_shift_A01_t01: RuntimeError # Please triage this failure
LibTest/core/int/operator_remainder_A01_t03: RuntimeError # Please triage this failure
@@ -3386,7 +3385,6 @@
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
-LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: Fail # co19 issue #90
LibTest/core/double/roundToDouble_A01_t01: Pass, RuntimeError # Passes on ff 35. Please triage this failure
LibTest/core/double/round_A01_t01: Pass, RuntimeError # Passes on ff 35. Please triage this failure
LibTest/core/int/compareTo_A01_t01: RuntimeError # Please triage this failure
@@ -5149,10 +5147,11 @@
LibTest/async/Stream/Stream.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
LibTest/async/Timer/Timer.periodic_A01_t01: Pass, RuntimeError # Please triage this failure
LibTest/async/Timer/Timer_A01_t01: Pass, RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # IE11 is not on Unicode 6.3 yet.
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: Fail # IE11 is not on Unicode 6.3 yet.
LibTest/core/Runes/takeWhile_A01_t01: Skip # Times out. Please triage this failure
LibTest/core/String/split_A01_t02: Skip # Times out. Please triage this failure
LibTest/core/String/toLowerCase_A01_t02: Skip # Times out. Please triage this failure
@@ -5648,7 +5647,6 @@
LibTest/async/Zone/createTimer_A01_t01: RuntimeError # Issue 7728, timer not supported in jsshell
LibTest/core/List/sort_A01_t04: Skip # Must be a bug in jsshell, test sometimes times out.
LibTest/core/Map/Map_class_A01_t04: Pass, Slow # Issue 8096
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail # co19-roll r706: Please triage this failure.
LibTest/core/Stopwatch/elapsedInMs_A01_t01: RuntimeError # Issue 7728, timer not supported in jsshell
LibTest/core/Stopwatch/elapsedInUs_A01_t01: RuntimeError # Issue 7728, timer not supported in jsshell
LibTest/core/Stopwatch/elapsedTicks_A01_t01: RuntimeError # Please triage this failure
@@ -6494,10 +6492,11 @@
LayoutTests/fast/xpath/py-dom-xpath/paths_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xpath/reverse-axes_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xsl/default-html_t01: RuntimeError # Please triage this failure
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # Please triage this failure
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # Safari is not on Unicode 6.3 yet.
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
+LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: Fail # Safari is not on Unicode 6.3 yet.
LibTest/core/double/roundToDouble_A01_t01: RuntimeError # Please triage this failure
LibTest/core/double/round_A01_t01: RuntimeError # Please triage this failure
LibTest/core/int/compareTo_A01_t01: RuntimeError # Please triage this failure
@@ -7068,7 +7067,6 @@
Language/Types/Function_Types/call_t01: Crash # Issue 28894
[ $compiler == dart2js && $jscl ]
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail, Pass # issue 3333
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError, OK # This is not rejected by V8. Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError # Issue 22200
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index fdc9c63..907d7df 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -7,6 +7,7 @@
Language/Expressions/Instance_Creation/Const/canonicalized_t05: RuntimeError
Language/Expressions/Object_Identity/string_t01: RuntimeError
Language/Expressions/Strings/adjacent_strings_t02: RuntimeError
+Language/Libraries_and_Scripts/Imports/invalid_uri_deferred_t03: CompileTimeError
Language/Metadata/before_type_param_t01: RuntimeError
LibTest/isolate/Isolate/spawnUri_A01_t03: Pass, Timeout
@@ -24,12 +25,17 @@
Language/Expressions/Null/extend_or_implement_t03: MissingCompileTimeError # New entries after going from kernel-service to batch-mode compilation. Please investigate.
Language/Expressions/Null/extend_or_implement_t04: MissingCompileTimeError # New entries after going from kernel-service to batch-mode compilation. Please investigate.
Language/Expressions/Null/extend_or_implement_t05: MissingCompileTimeError # New entries after going from kernel-service to batch-mode compilation. Please investigate.
+Language/Libraries_and_Scripts/Imports/invalid_uri_deferred_t03: CompileTimeError
Language/Mixins/Mixin_Application/syntax_t16: RuntimeError # New entries after going from kernel-service to batch-mode compilation. Please investigate.
Language/Overview/Scoping/hiding_declaration_t11: Crash
Language/Overview/Scoping/hiding_declaration_t11: Pass
Language/Overview/Scoping/hiding_declaration_t12: Crash
Language/Overview/Scoping/hiding_declaration_t12: Pass
+[ $fasta ]
+Language/Mixins/Mixin_Application/syntax_t20: CompileTimeError
+Language/Types/Interface_Types/subtype_t30: CompileTimeError
+
# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
# are to be triaged. Isolate tests are skipped on purpose due to the usage of
# batch mode.
@@ -153,8 +159,6 @@
Language/Functions/External_Functions/not_connected_to_a_body_t01: RuntimeError # Dartk Issue 28565
Language/Functions/Formal_Parameters/Optional_Formals/default_value_t01: MissingCompileTimeError
Language/Functions/Formal_Parameters/Optional_Formals/default_value_t02: MissingCompileTimeError
-Language/Functions/Formal_Parameters/Required_Formals/syntax_t06: MissingCompileTimeError
-Language/Functions/Formal_Parameters/Required_Formals/syntax_t07: MissingCompileTimeError
Language/Libraries_and_Scripts/Exports/reexport_t01: MissingCompileTimeError
Language/Libraries_and_Scripts/Imports/deferred_import_t01: CompileTimeError # Deferred loading kernel issue 28335.
Language/Libraries_and_Scripts/Imports/deferred_import_t02: CompileTimeError # Deferred loading kernel issue 28335.
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 0f5f5bf..b350ad7 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -302,11 +302,9 @@
LibTest/core/Duration/inMinutes_A01_t01: RuntimeError # Large integers
LibTest/core/Duration/inSeconds_A01_t01: RuntimeError # Large integers
LibTest/core/List/List_class_A01_t01: RuntimeError # Large integers
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: RuntimeError # Issue 1296
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError, Fail # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: RuntimeError, Fail # Issue 22200
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: RuntimeError, Fail # Issue 22200
-LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: RuntimeError # Issue 1296
LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # Issue 13596
LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # Issue 13596
LibTest/core/double/ceil_A01_t04: RuntimeError # Large integers
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 933e5f3..dfa1d84 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -78,7 +78,6 @@
deferred/deferred_mirrors2_test: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
deferred/reflect_multiple_annotations_test: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
deferred/reflect_multiple_default_arg_test: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
-deferred_custom_loader_test: RuntimeError
deferred_fail_and_retry_test: RuntimeError
deferred_fail_and_retry_worker_test: Fail
dummy_compiler_test: CompileTimeError
@@ -135,7 +134,6 @@
deferred/deferred_mirrors2_test: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
deferred/reflect_multiple_annotations_test: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
deferred/reflect_multiple_default_arg_test: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
-deferred_custom_loader_test: RuntimeError
deferred_fail_and_retry_test: RuntimeError
deferred_fail_and_retry_worker_test: Fail
dummy_compiler_test: CompileTimeError
@@ -163,7 +161,6 @@
deferred/deferred_mirrors2_test: CompileTimeError
deferred/reflect_multiple_annotations_test: CompileTimeError
deferred/reflect_multiple_default_arg_test: CompileTimeError
-deferred_custom_loader_test: RuntimeError
deferred_fail_and_retry_test: RuntimeError
deferred_fail_and_retry_worker_test: Fail
inference_nsm_mirrors_test: CompileTimeError
@@ -211,7 +208,6 @@
deferred/deferred_mirrors2_test: CompileTimeError
deferred/reflect_multiple_annotations_test: Crash # NoSuchMethodError: The getter 'closureClassEntity' was called on null.
deferred/reflect_multiple_default_arg_test: Crash # NoSuchMethodError: The getter 'closureClassEntity' was called on null.
-deferred_custom_loader_test: RuntimeError
deferred_fail_and_retry_test: RuntimeError
deferred_fail_and_retry_worker_test: Fail
dummy_compiler_test: CompileTimeError
diff --git a/tests/compiler/dart2js_extra/deferred_custom_loader_test.dart b/tests/compiler/dart2js_extra/deferred_custom_loader_test.dart
index 819635d..d1f358e 100644
--- a/tests/compiler/dart2js_extra/deferred_custom_loader_test.dart
+++ b/tests/compiler/dart2js_extra/deferred_custom_loader_test.dart
@@ -4,24 +4,29 @@
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
+import 'dart:_foreign_helper' show JS;
import 'deferred_custom_loader_lib.dart' deferred as def;
-void setup() native """
-// In d8 we don't have any way to load the content of the file, so just use
-// the preamble's loader.
-if (!self.dartDeferredLibraryLoader) {
- self.dartDeferredLibraryLoader = function(uri, success, error) {
- var req = new XMLHttpRequest();
- req.addEventListener("load", function() {
- eval(this.responseText);
- success();
- });
- req.open("GET", uri);
- req.send();
- };
+void setup() {
+ JS('', r"""
+(function(){
+ // In d8 we don't have any way to load the content of the file, so just use
+ // the preamble's loader.
+ if (!self.dartDeferredLibraryLoader) {
+ self.dartDeferredLibraryLoader = function(uri, success, error) {
+ var req = new XMLHttpRequest();
+ req.addEventListener("load", function() {
+ eval(this.responseText);
+ success();
+ });
+ req.open("GET", uri);
+ req.send();
+ };
+ }
+})()
+""");
}
-""";
runTest() async {
setup();
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 8a40903..b4055c8 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -57,7 +57,6 @@
main_test: RuntimeError # Flutter Issue 9111
string_from_environment2_test: Fail # Flutter Issue 9111
string_from_environment_test: Fail # Flutter Issue 9111
-string_trimlr_test/02: RuntimeError # Flutter Issue 9111
[ $runtime == jsshell ]
string_case_test/01: RuntimeError # jsshell does not recognize character 223 aka \xdf
@@ -66,7 +65,7 @@
[ $runtime == safari ]
double_round3_test: RuntimeError
double_round_to_double2_test: Pass, Fail, OK
-string_trimlr_test/02: RuntimeError # Uses Unicode 6.2.0 or earlier.
+string_trimlr_test/unicode63: RuntimeError # Uses Unicode 6.2.0 or earlier.
[ $strong ]
*: SkipByDesign # tests/corelib_2 has the strong mode versions of these tests.
@@ -101,10 +100,10 @@
[ $compiler == dart2js && $runtime == chromeOnAndroid ]
list_as_map_test: Pass, Slow # TODO(kasperl): Please triage.
-string_trimlr_test/02: RuntimeError # Uses Unicode 6.2.0 or earlier.
+string_trimlr_test/unicode63: RuntimeError # Uses Unicode 6.2.0 or earlier.
[ $compiler == dart2js && $runtime == drt ]
-string_trimlr_test/02: RuntimeError # Uses Unicode 6.2.0 or earlier.
+string_trimlr_test/unicode63: RuntimeError # Uses Unicode 6.2.0 or earlier.
[ $compiler == dart2js && $runtime == drt && $csp && $minified ]
core_runtime_types_test: Pass, Fail # Issue 27913
@@ -335,9 +334,6 @@
[ $compiler == dart2js && $fast_startup ]
apply3_test: Fail # mirrors not supported
-[ $compiler == none && ($runtime == flutter || $runtime == vm) ]
-string_trimlr_test/02: RuntimeError # Issue 29060
-
[ $runtime != d8 && $runtime != dart_precompiled && $runtime != vm ]
regexp/*: Skip # The regexp tests are not verified to work on non d8/vm platforms yet.
@@ -369,7 +365,6 @@
file_resource_test: Skip # Resolve URI not supported yet in product mode.
http_resource_test: Skip # Resolve URI not supported yet in product mode.
package_resource_test: Skip # Resolve URI not supported yet in product mode.
-string_trimlr_test/02: RuntimeError # Issue 29060
# We skip all the Dart 1.0 tests in dartk and dartkp mode as these
# modes are intended only for Dart 2.0 with strong mode enabled.
diff --git a/tests/corelib/string_trimlr_test.dart b/tests/corelib/string_trimlr_test.dart
index 90eb02d..360b9e0 100644
--- a/tests/corelib/string_trimlr_test.dart
+++ b/tests/corelib/string_trimlr_test.dart
@@ -104,8 +104,9 @@
Expect.identical(s200B, s200B.trimRight()); // //# 01: ok
// U+180E ceased to be whitespace in Unicode version 6.3.0
- // string_trimlr_test/02 fails on implementations using earlier versions.
+ // string_trimlr_test/unicode63 fails on implementations using earlier
+ // versions.
var s180E = new String.fromCharCode(0x180E);
- Expect.identical(s180E, s180E.trimLeft()); // //# 02: ok
- Expect.identical(s180E, s180E.trimRight()); // //# 02: ok
+ Expect.identical(s180E, s180E.trimLeft()); // //# unicode63: ok
+ Expect.identical(s180E, s180E.trimRight()); // //# unicode63: ok
}
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index fefc9fc..2021a13 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -66,7 +66,6 @@
main_test: RuntimeError # Flutter Issue 9111
string_from_environment2_test: Fail # Flutter Issue 9111
string_from_environment_test: Fail # Flutter Issue 9111
-string_trimlr_test/02: RuntimeError # Flutter Issue 9111
[ $runtime == jsshell ]
string_case_test/01: Fail, OK # German double S.
@@ -75,7 +74,7 @@
[ $runtime == safari ]
double_round3_test: Fail, OK # Runtime rounds 0.49999999999999994 to 1.
double_round_to_double2_test: Fail, OK # Runtime rounds 0.49999999999999994 to 1.
-string_trimlr_test/02: RuntimeError # Uses Unicode 6.2.0 or earlier.
+string_trimlr_test/unicode63: RuntimeError # Uses Unicode 6.2.0 or earlier.
[ !$strong ]
cast_test: SkipByDesign # Uses generic method parameters.
@@ -130,10 +129,9 @@
[ $compiler == dart2js && $runtime == chromeOnAndroid ]
list_as_map_test: Pass, Slow # TODO(kasperl): Please triage.
-string_trimlr_test/02: RuntimeError # Uses Unicode 6.2.0 or earlier.
+string_trimlr_test/unicode63: RuntimeError # Uses Unicode 6.2.0 or earlier.
[ $compiler == dart2js && $runtime == d8 ]
-string_trimlr_test/02: RuntimeError, Pass # Uses Unicode 6.2.0 or earlier, issue 30279.
uri_base_test: RuntimeError # D8 uses a custom uri scheme for Uri.base
[ $compiler == dart2js && $runtime == drt && $csp && $minified ]
@@ -148,11 +146,11 @@
list_test/*: RuntimeError # dart2js doesn't implement strong mode covariance checks
nan_infinity_test/01: RuntimeError
regexp/pcre_test: Pass, Slow # Issue 21593
-string_split_test: RuntimeError # Issue 30548: does not return List<String>
[ $compiler == dart2js && $runtime != none && !$checked ]
growable_list_test: RuntimeError # Concurrent modifications test always runs
splay_tree_from_iterable_test: RuntimeError
+string_split_test/checkedstore: RuntimeError # Issue 30548: does not check stores into List<String>
[ $compiler == dart2js && $runtime != none && $dart2js_with_kernel ]
list_concurrent_modify_test: Crash # Issue 30559
@@ -333,7 +331,6 @@
apply3_test: CompileTimeError # Issue 31402 (Invocation arguments)
bool_from_environment2_test/03: MissingCompileTimeError
compare_to2_test: RuntimeError
-iterable_empty_test: RuntimeError
iterable_fold_test/02: RuntimeError
iterable_reduce_test/01: CompileTimeError # Issue 31533
iterable_reduce_test/none: RuntimeError
@@ -344,25 +341,23 @@
list_set_all_test: RuntimeError
null_nosuchmethod_test/01: CompileTimeError # Issue 31402 (Invocation arguments)
null_nosuchmethod_test/none: CompileTimeError # Issue 31402 (Invocation arguments)
-string_from_environment3_test/03: MissingCompileTimeError
-string_trimlr_test/02: RuntimeError
-symbol_operator_test/03: RuntimeError
-symbol_reserved_word_test/04: MissingCompileTimeError
-symbol_reserved_word_test/06: RuntimeError
-symbol_reserved_word_test/07: MissingCompileTimeError
-symbol_reserved_word_test/09: RuntimeError
-symbol_reserved_word_test/10: MissingCompileTimeError
-symbol_reserved_word_test/12: RuntimeError
-symbol_test/02: MissingCompileTimeError
-symbol_test/03: MissingCompileTimeError
-symbol_test/none: RuntimeError
-unicode_test: RuntimeError
+string_from_environment3_test/03: MissingCompileTimeError # Issue 31936 - throwing const constructors.
+symbol_operator_test/03: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
+symbol_reserved_word_test/04: MissingCompileTimeError # Issue 31936 - throwing const constructors.
+symbol_reserved_word_test/06: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
+symbol_reserved_word_test/07: MissingCompileTimeError # Issue 31936 - throwing const constructors.
+symbol_reserved_word_test/09: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
+symbol_reserved_word_test/10: MissingCompileTimeError # Issue 31936 - throwing const constructors.
+symbol_reserved_word_test/12: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
+symbol_test/02: MissingCompileTimeError # Issue 31936 - throwing const constructors.
+symbol_test/03: MissingCompileTimeError # Issue 31936 - throwing const constructors.
+symbol_test/none: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
+unicode_test: RuntimeError # Issue 18061: German double S.
# ===== dartkp + dart_precompiled status lines =====
[ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
bool_from_environment2_test/03: MissingCompileTimeError
compare_to2_test: RuntimeError
-iterable_empty_test: RuntimeError
iterable_fold_test/02: RuntimeError
iterable_reduce_test/01: CompileTimeError # Issue 31533
iterable_reduce_test/none: RuntimeError
@@ -374,19 +369,18 @@
null_nosuchmethod_test/01: CompileTimeError # Issue 31402 (Invocation arguments)
null_nosuchmethod_test/none: CompileTimeError # Issue 31402 (Invocation arguments)
regexp/stack-overflow_test: RuntimeError
-string_from_environment3_test/03: MissingCompileTimeError
-string_trimlr_test/02: RuntimeError
-symbol_operator_test/03: RuntimeError
-symbol_reserved_word_test/04: MissingCompileTimeError
-symbol_reserved_word_test/06: RuntimeError
-symbol_reserved_word_test/07: MissingCompileTimeError
-symbol_reserved_word_test/09: RuntimeError
-symbol_reserved_word_test/10: MissingCompileTimeError
-symbol_reserved_word_test/12: RuntimeError
-symbol_test/02: MissingCompileTimeError
-symbol_test/03: MissingCompileTimeError
-symbol_test/none: RuntimeError
-unicode_test: RuntimeError
+string_from_environment3_test/03: MissingCompileTimeError # Issue 31936 - throwing const constructors.
+symbol_operator_test/03: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
+symbol_reserved_word_test/04: MissingCompileTimeError # Issue 31936 - throwing const constructors.
+symbol_reserved_word_test/06: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
+symbol_reserved_word_test/07: MissingCompileTimeError # Issue 31936 - throwing const constructors.
+symbol_reserved_word_test/09: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
+symbol_reserved_word_test/10: MissingCompileTimeError # Issue 31936 - throwing const constructors.
+symbol_reserved_word_test/12: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
+symbol_test/02: MissingCompileTimeError # Issue 31936 - throwing const constructors.
+symbol_test/03: MissingCompileTimeError # Issue 31936 - throwing const constructors.
+symbol_test/none: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
+unicode_test: RuntimeError # Issue 18061: German double S.
[ $compiler == none && $runtime == drt ]
string_from_environment2_test: Skip
@@ -395,7 +389,6 @@
[ $compiler == none && ($runtime == flutter || $runtime == vm) ]
iterable_to_set_test: RuntimeError # is-checks do not implement strong mode type system
-string_trimlr_test/02: RuntimeError # Issue 29060
[ $compiler == precompiler && $runtime == dart_precompiled && !$checked ]
iterable_generate_test/01: RuntimeError
@@ -406,7 +399,7 @@
error_stack_trace1_test: Skip # Expects unobfuscated stack trace
[ $runtime == drt && ($compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk) ]
-string_trimlr_test/02: RuntimeError # Uses Unicode 6.2.0 or earlier.
+string_trimlr_test/unicode63: RuntimeError # Uses Unicode 6.2.0 or earlier.
[ $runtime != drt && ($compiler == app_jit || $compiler == none || $compiler == precompiler) ]
symbol_test/02: MissingCompileTimeError # Issue 11669
@@ -507,12 +500,6 @@
symbol_test/none: RuntimeError # Issue 29921
typed_data_with_limited_ints_test: Skip # dartdevc doesn't know about --limit-ints-to-64-bits
-# We no longer expect Dart2 tests to run with the standalone VM without the new
-# common front end, but for now we get better coverage by still running them in
-# checked mode, which is mostly Dart2-compatible.
-[ $runtime == vm && !$checked && ($compiler == app_jit || $compiler == none) ]
-*: Skip
-
[ !$checked && !$strong ]
core_runtime_types_static_test: MissingCompileTimeError
splay_tree_test/01: MissingCompileTimeError
@@ -521,6 +508,12 @@
string_replace_static_test: MissingCompileTimeError
string_static_test: MissingCompileTimeError
+# We no longer expect Dart2 tests to run with the standalone VM without the new
+# common front end, but for now we get better coverage by still running them in
+# checked mode, which is mostly Dart2-compatible.
+[ !$checked && ($compiler == app_jit || $compiler == none || $compiler == precompiler) && ($runtime == dart_precompiled || $runtime == vm) ]
+*: Skip
+
[ !$checked && ($compiler == dart2js || $compiler == none && $runtime == vm) ]
from_environment_const_type_test/02: MissingCompileTimeError
from_environment_const_type_test/03: MissingCompileTimeError
@@ -605,7 +598,6 @@
from_environment_const_type_undefined_test/14: MissingCompileTimeError
from_environment_const_type_undefined_test/16: MissingCompileTimeError
iterable_to_set_test: RuntimeError # is-checks do not implement strong mode type system
-string_trimlr_test/02: RuntimeError # Issue 29060
[ $compiler == dart2js || $compiler == none && $runtime == vm ]
from_environment_const_type_undefined_test/09: MissingCompileTimeError
@@ -636,10 +628,6 @@
regexp/pcre_test: Pass, Slow, Timeout
[ $runtime == dart_precompiled || $runtime == vm ]
-integer_parsed_arith_vm_test/01: RuntimeError # Issue 31346
-integer_parsed_arith_vm_test/02: RuntimeError # Issue 31346
-integer_parsed_div_rem_vm_test/01: RuntimeError # Issue 31346
-integer_to_radix_string_test/01: RuntimeError # Issue 31346
string_case_test/01: RuntimeError # Issue 18061: German double S.
[ $runtime == ff || $runtime == jsshell ]
diff --git a/tests/corelib_2/integer_parsed_arith_vm_test.dart b/tests/corelib_2/integer_parsed_arith_vm_test.dart
index d3e273d..0ccc6bd 100644
--- a/tests/corelib_2/integer_parsed_arith_vm_test.dart
+++ b/tests/corelib_2/integer_parsed_arith_vm_test.dart
@@ -10,27 +10,25 @@
import "package:expect/expect.dart";
+String toHexString(int value) => value >= 0
+ ? "0x${value.toRadixString(16)}"
+ : "-0x${value.toRadixString(16).substring(1)}";
+
addSubParsed(String a, String b, String sum) {
int int_a = int.parse(a);
int int_b = int.parse(b);
int int_sum = int.parse(sum);
int computed_sum = int_a + int_b;
Expect.equals(int_sum, computed_sum);
- String str_sum = computed_sum >= 0
- ? "0x${computed_sum.toRadixString(16)}"
- : "-0x${(-computed_sum).toRadixString(16)}";
+ String str_sum = toHexString(computed_sum);
Expect.equals(sum.toLowerCase(), str_sum);
int computed_difference1 = int_sum - int_a;
Expect.equals(int_b, computed_difference1);
- String str_difference1 = computed_difference1 >= 0
- ? "0x${computed_difference1.toRadixString(16)}"
- : "-0x${(-computed_difference1).toRadixString(16)}";
+ String str_difference1 = toHexString(computed_difference1);
Expect.equals(b.toLowerCase(), str_difference1);
int computed_difference2 = int_sum - int_b;
Expect.equals(int_a, computed_difference2);
- String str_difference2 = computed_difference2 >= 0
- ? "0x${computed_difference2.toRadixString(16)}"
- : "-0x${(-computed_difference2).toRadixString(16)}";
+ String str_difference2 = toHexString(computed_difference2);
Expect.equals(a.toLowerCase(), str_difference2);
}
@@ -60,14 +58,14 @@
"0xFFFFFFFFFFFFFF",
one, // 56 bit overflow.
"0x100000000000000");
- addSubParsed( // //# 01: ok
- "0x7FFFFFFFFFFFFFFF", // //# 01: continued
- one, // 64 bit overflow. //# 01: continued
- "-0x8000000000000000"); // //# 01: continued
- addSubParsed( // //# 02: ok
- minus_one, // //# 02: continued
- one, // 64 bit overflow. //# 02: continued
- zero); // //# 02: continued
+ addSubParsed(
+ "0x7FFFFFFFFFFFFFFF",
+ one, // 64 bit overflow.
+ "-0x8000000000000000");
+ addSubParsed(
+ minus_one,
+ one, // 64 bit overflow.
+ zero);
addSubParsed(
"0x8000000", // 28 bit overflow.
"0x8000000",
@@ -80,10 +78,10 @@
"0x80000000000000", // 56 bit overflow.
"0x80000000000000",
"0x100000000000000");
- addSubParsed( // //# 02: continued
- "-0x8000000000000000", // 64 bit overflow. //# 02: continued
- "-0x8000000000000000", // //# 02: continued
- zero); // //# 02: continued
+ addSubParsed(
+ "-0x8000000000000000", // 64 bit overflow.
+ "-0x8000000000000000",
+ zero);
addSubParsed("-0x123", minus_one, "-0x124");
addSubParsed(minus_one, "-0x123", "-0x124");
@@ -99,10 +97,10 @@
"-0xFFFFFFFFFFFFFF",
minus_one, // 56 bit overflow.
"-0x100000000000000");
- addSubParsed( // //# 01: continued
- "-0x8000000000000000", // //# 01: continued
- minus_one, // 64 bit overflow. //# 01: continued
- "0x7FFFFFFFFFFFFFFF"); // //# 01: continued
+ addSubParsed(
+ "-0x8000000000000000",
+ minus_one, // 64 bit overflow.
+ "0x7FFFFFFFFFFFFFFF");
addSubParsed(
"-0x8000000", // 28 bit overflow.
"-0x8000000",
@@ -115,10 +113,10 @@
"-0x80000000000000", // 56 bit overflow.
"-0x80000000000000",
"-0x100000000000000");
- addSubParsed( // //# 01: continued
- "-0x8000000000000000", // 64 bit overflow. //# 01: continued
- "-0x8000000000000000", // //# 01: continued
- "0x0"); // //# 01: continued
+ addSubParsed(
+ "-0x8000000000000000", // 64 bit overflow.
+ "-0x8000000000000000",
+ "0x0");
addSubParsed("0xB", "-0x7", "0x4");
addSubParsed("-0xB", "-0x7", "-0x12");
@@ -138,15 +136,11 @@
int int_result_back_shifted = int.parse(result_back_shifted);
int shifted = int_a << amount;
Expect.equals(int_result, shifted);
- String str_shifted = shifted >= 0
- ? "0x${shifted.toRadixString(16)}"
- : "-0x${(-shifted).toRadixString(16)}";
+ String str_shifted = toHexString(shifted);
Expect.equals(result.toLowerCase(), str_shifted);
int back_shifted = shifted >> amount;
Expect.equals(int_result_back_shifted, back_shifted);
- String str_back_shifted = back_shifted >= 0
- ? "0x${back_shifted.toRadixString(16)}"
- : "-0x${(-back_shifted).toRadixString(16)}";
+ String str_back_shifted = toHexString(back_shifted);
Expect.equals(result_back_shifted.toLowerCase(), str_back_shifted);
}
@@ -171,17 +165,15 @@
shiftLeftParsed("0x5", 27, "0x28000000");
shiftLeftParsed("0x5", 31, "0x280000000");
shiftLeftParsed("0x5", 55, "0x280000000000000");
- shiftLeftParsed("0x5", 63, "-0x8000000000000000", // //# 01: continued
- result_back_shifted: "-0x1"); // //# 01: continued
+ shiftLeftParsed("0x5", 63, "-0x8000000000000000",
+ result_back_shifted: "-0x1");
shiftLeftParsed("0x5", 127, zero, result_back_shifted: zero);
shiftLeftParsed("0x8000001", 1, "0x10000002");
shiftLeftParsed("0x80000001", 1, "0x100000002");
- shiftLeftParsed("0x8000000000000001", 1, "0x2", // //# 02: continued
- result_back_shifted: "0x1"); // //# 02: continued
+ shiftLeftParsed("0x8000000000000001", 1, "0x2", result_back_shifted: "0x1");
shiftLeftParsed("0x8000001", 29, "0x100000020000000");
shiftLeftParsed("0x80000001", 33, "0x200000000", result_back_shifted: "0x1");
- shiftLeftParsed("0x8000000000000001", 65, zero, // //# 02: continued
- result_back_shifted: zero); // //# 02: continued
+ shiftLeftParsed("0x8000000000000001", 65, zero, result_back_shifted: zero);
shiftLeftParsed("0x7fffffffffffffff", 1, "-0x2", result_back_shifted: "-0x1");
shiftLeftParsed("0x7fffffffffffffff", 29, "-0x20000000",
result_back_shifted: "-0x1");
@@ -196,7 +188,8 @@
shiftLeftParsed("-0x5", 64, zero, result_back_shifted: zero);
shiftLeftParsed("-0x5", 27, "-0x28000000");
shiftLeftParsed("-0x5", 31, "-0x280000000");
- shiftLeftParsed("-0x5", 63, "-0x8000000000000000"); // //# 01: continued
+ shiftLeftParsed("-0x5", 63, "-0x8000000000000000",
+ result_back_shifted: minus_one);
shiftLeftParsed("-0x8000001", 1, "-0x10000002");
shiftLeftParsed("-0x80000001", 1, "-0x100000002");
shiftLeftParsed("-0x8000001", 29, "-0x100000020000000");
@@ -213,9 +206,7 @@
int int_result = int.parse(result);
int shifted = int_a >> amount;
Expect.equals(int_result, shifted);
- String str_shifted = shifted >= 0
- ? "0x${shifted.toRadixString(16)}"
- : "-0x${(-shifted).toRadixString(16)}";
+ String str_shifted = toHexString(shifted);
Expect.equals(result.toLowerCase(), str_shifted);
}
@@ -257,15 +248,11 @@
int int_result = int.parse(result);
int anded = int_a & int_b;
Expect.equals(int_result, anded);
- String str_anded = anded >= 0
- ? "0x${anded.toRadixString(16)}"
- : "-0x${(-anded).toRadixString(16)}";
+ String str_anded = toHexString(anded);
Expect.equals(result.toLowerCase(), str_anded);
int anded2 = int_b & int_a;
Expect.equals(int_result, anded2);
- String str_anded2 = anded2 >= 0
- ? "0x${anded2.toRadixString(16)}"
- : "-0x${(-anded2).toRadixString(16)}";
+ String str_anded2 = toHexString(anded2);
Expect.equals(result.toLowerCase(), str_anded2);
}
@@ -298,11 +285,11 @@
bitAndParsed("-0x10000001", "0x3FFFFFFF", "0x2FFFFFFF");
bitAndParsed("-0x100000001", "0x3FFFFFFFF", "0x2FFFFFFFF");
bitAndParsed("-0x100000000000000", "0xFFFFFFFFFFFFFF", "0x0");
- bitAndParsed("-0x1000000000000000", "0xFFFFFFFFFFFFFFFF", // //# 02: continued
- "-0x1000000000000000"); // //# 02: continued
+ bitAndParsed(
+ "-0x1000000000000000", "0xFFFFFFFFFFFFFFFF", "-0x1000000000000000");
bitAndParsed("-0x300000000000000", "0xFFFFFFFFFFFFFFF", "0xD00000000000000");
- bitAndParsed("-0x3000000000000000", "0xFFFFFFFFFFFFFFFF", // //# 02: continued
- "-0x3000000000000000"); // //# 02: continued
+ bitAndParsed(
+ "-0x3000000000000000", "0xFFFFFFFFFFFFFFFF", "-0x3000000000000000");
bitAndParsed("-0x10000000", "-0x10000000", "-0x10000000");
bitAndParsed("-0x100000000", "-0x100000000", "-0x100000000");
bitAndParsed(
@@ -324,15 +311,11 @@
int int_result = int.parse(result);
int ored = int_a | int_b;
Expect.equals(int_result, ored);
- String str_ored = ored >= 0
- ? "0x${ored.toRadixString(16)}"
- : "-0x${(-ored).toRadixString(16)}";
+ String str_ored = toHexString(ored);
Expect.equals(result.toLowerCase(), str_ored);
int ored2 = int_b | int_a;
Expect.equals(int_result, ored2);
- String str_ored2 = ored2 >= 0
- ? "0x${ored2.toRadixString(16)}"
- : "-0x${(-ored2).toRadixString(16)}";
+ String str_ored2 = toHexString(ored2);
Expect.equals(result.toLowerCase(), str_ored2);
}
@@ -370,7 +353,7 @@
bitOrParsed("-0x100000000000000", "0xFFFFFFFFFFFFFF", "-0x1");
bitOrParsed("-0x1000000000000000", "0xFFFFFFFFFFFFFFF", "-0x1");
bitOrParsed("-0x300000000000000", "0xFFFFFFFFFFFFFFF", "-0x1");
- bitOrParsed("-0x3000000000000000", "0xFFFFFFFFFFFFFFFF", "-0x1"); // //# 02: continued
+ bitOrParsed("-0x3000000000000000", "0xFFFFFFFFFFFFFFFF", "-0x1");
bitOrParsed("-0x10000000", "-0x10000000", "-0x10000000");
bitOrParsed("-0x100000000", "-0x100000000", "-0x100000000");
bitOrParsed("-0x100000000000000", "-0x100000000000000", "-0x100000000000000");
@@ -389,21 +372,15 @@
int int_result = int.parse(result);
int xored = int_a ^ int_b;
Expect.equals(int_result, xored);
- String str_xored = xored >= 0
- ? "0x${xored.toRadixString(16)}"
- : "-0x${(-xored).toRadixString(16)}";
+ String str_xored = toHexString(xored);
Expect.equals(result.toLowerCase(), str_xored);
int xored2 = int_b ^ int_a;
Expect.equals(int_result, xored2);
- String str_xored2 = xored2 >= 0
- ? "0x${xored2.toRadixString(16)}"
- : "-0x${(-xored2).toRadixString(16)}";
+ String str_xored2 = toHexString(xored2);
Expect.equals(result.toLowerCase(), str_xored2);
int xored3 = int_a ^ xored2;
Expect.equals(int_b, xored3);
- String str_xored3 = xored3 >= 0
- ? "0x${xored3.toRadixString(16)}"
- : "-0x${(-xored3).toRadixString(16)}";
+ String str_xored3 = toHexString(xored3);
Expect.equals(b.toLowerCase(), str_xored3);
}
@@ -459,15 +436,11 @@
int int_result = int.parse(result);
int inverted = ~int_a;
Expect.equals(int_result, inverted);
- String str_inverted = inverted >= 0
- ? "0x${inverted.toRadixString(16)}"
- : "-0x${(-inverted).toRadixString(16)}";
+ String str_inverted = toHexString(inverted);
Expect.equals(result.toLowerCase(), str_inverted);
int back = ~inverted;
Expect.equals(int_a, back);
- String str_back = back >= 0
- ? "0x${back.toRadixString(16)}"
- : "-0x${(-back).toRadixString(16)}";
+ String str_back = toHexString(back);
Expect.equals(a.toLowerCase(), str_back);
}
@@ -483,8 +456,7 @@
bitNotParsed("0xFFFFFFF", "-0x10000000");
bitNotParsed("0xFFFFFFFF", "-0x100000000");
bitNotParsed("0xFFFFFFFFFFFFFF", "-0x100000000000000");
- bitNotParsed( // //# 01: continued
- "0x7FFFFFFFFFFFFFFF", "-0x8000000000000000"); // //# 01: continued
+ bitNotParsed("0x7FFFFFFFFFFFFFFF", "-0x8000000000000000");
bitNotParsed("-0x1", "0x0");
}
diff --git a/tests/corelib_2/string_split_test.dart b/tests/corelib_2/string_split_test.dart
index f15ac1f..a05bced 100644
--- a/tests/corelib_2/string_split_test.dart
+++ b/tests/corelib_2/string_split_test.dart
@@ -23,8 +23,11 @@
// Ensure that the correct type is reified.
actual = actual as List<String>;
- Expect.throwsTypeError(() => actual.add(42),
- 'List<String>.add should not accept an int');
+
+ // Check that store of the wrong type throws. Some platforms don't do this,
+ // so it's protected by multitest syntax.
+ Expect.throwsTypeError(() => actual.add(42), // //# checkedstore: ok
+ 'List<String>.add should not accept an int'); // //# checkedstore: ok
Expect.listEquals(expect, actual, '"$string".split($patternString)');
}
diff --git a/tests/corelib_2/string_trimlr_test.dart b/tests/corelib_2/string_trimlr_test.dart
index 90eb02d..95f6af6 100644
--- a/tests/corelib_2/string_trimlr_test.dart
+++ b/tests/corelib_2/string_trimlr_test.dart
@@ -96,16 +96,15 @@
Expect.identical(s, s.trimRight());
}
- // U+200b is currently being treated as whitespace by some JS engines.
- // string_trimlr_test/01 fails on these engines.
- // Should be fixed in tip-of-tree V8 per 2014-02-10.
+ // U+200b is not treated as whitespace, though historically, some JS engines
+ // did.
var s200B = new String.fromCharCode(0x200B);
- Expect.identical(s200B, s200B.trimLeft()); // //# 01: ok
- Expect.identical(s200B, s200B.trimRight()); // //# 01: ok
+ Expect.identical(s200B, s200B.trimLeft());
+ Expect.identical(s200B, s200B.trimRight());
// U+180E ceased to be whitespace in Unicode version 6.3.0
- // string_trimlr_test/02 fails on implementations using earlier versions.
+ // string_trimlr_test/unicode63 fails on implementations using earlier versions.
var s180E = new String.fromCharCode(0x180E);
- Expect.identical(s180E, s180E.trimLeft()); // //# 02: ok
- Expect.identical(s180E, s180E.trimRight()); // //# 02: ok
+ Expect.identical(s180E, s180E.trimLeft()); // //# unicode63: ok
+ Expect.identical(s180E, s180E.trimRight()); // //# unicode63: ok
}
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index b61f8d0..632499c 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -143,7 +143,6 @@
constructor_redirect2_test/01: MissingCompileTimeError
constructor_redirect_test/01: Crash # Assertion failure: Cannot find value Instance of 'ThisLocal' in (local(A.named2#x), local(A.named2#y), local(A.named2#z)) for j:constructor(A.named2).
cyclic_constructor_test/01: Crash # Issue 30856
-deferred_call_empty_before_load_test: RuntimeError
deferred_constraints_constants_test/default_argument2: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
deferred_constraints_constants_test/none: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
deferred_constraints_constants_test/reference_after_load: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
@@ -384,9 +383,6 @@
regress_17382_test: RuntimeError
regress_20394_test/01: MissingCompileTimeError
regress_22936_test/01: RuntimeError
-regress_22976_test/01: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/02: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/none: Pass # Incorrectly pass, we are ignoring an error due to #31118
regress_24283_test: RuntimeError
regress_26133_test: RuntimeError # Issue 26429
regress_27572_test: RuntimeError
@@ -761,9 +757,6 @@
regress_17382_test: RuntimeError
regress_20394_test/01: MissingCompileTimeError
regress_22936_test/01: RuntimeError
-regress_22976_test/01: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/02: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/none: Pass # Incorrectly pass, we are ignoring an error due to #31118
regress_24283_test: RuntimeError
regress_27572_test: RuntimeError
regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
@@ -840,7 +833,6 @@
constructor_redirect2_test/01: MissingCompileTimeError
constructor_redirect_test/01: Crash # Assertion failure: Cannot find value Instance of 'ThisLocal' in (local(A.named2#x), local(A.named2#y), local(A.named2#z)) for j:constructor(A.named2).
cyclic_constructor_test/01: Crash # Issue 30856
-deferred_call_empty_before_load_test: RuntimeError
deferred_constraints_constants_test/none: CompileTimeError
deferred_constraints_constants_test/reference_after_load: CompileTimeError
deferred_constraints_type_annotation_test/as_operation: RuntimeError
@@ -1078,9 +1070,6 @@
regress_18535_test: CompileTimeError
regress_20394_test/01: MissingCompileTimeError
regress_22936_test/01: RuntimeError
-regress_22976_test/01: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/02: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/none: Pass # Incorrectly pass, we are ignoring an error due to #31118
regress_24283_test: RuntimeError
regress_27572_test: RuntimeError
regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
@@ -1167,7 +1156,6 @@
cyclic_type_test/02: RuntimeError
cyclic_type_test/03: RuntimeError
cyclic_type_test/04: RuntimeError
-deferred_call_empty_before_load_test: RuntimeError
deferred_constraints_constants_test/none: CompileTimeError
deferred_constraints_constants_test/reference_after_load: CompileTimeError
deferred_constraints_type_annotation_test/as_operation: Crash # NoSuchMethodError: The getter 'closureClassEntity' was called on null.
@@ -1413,9 +1401,6 @@
regress_20394_test/01: MissingCompileTimeError
regress_21795_test: RuntimeError
regress_22936_test/01: RuntimeError
-regress_22976_test/01: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/02: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/none: Pass # Incorrectly pass, we are ignoring an error due to #31118
regress_24283_test: RuntimeError
regress_27572_test: RuntimeError
regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
diff --git a/tests/language_2/bug31436_test.dart b/tests/language_2/bug31436_test.dart
index 30fec3e..eace48f 100644
--- a/tests/language_2/bug31436_test.dart
+++ b/tests/language_2/bug31436_test.dart
@@ -27,7 +27,7 @@
}; // No implicit downcast on the assignment, implicit downcast on the return
assert(g is List<Object> Function());
assert(g is! List<int> Function());
- assert(g is! Object Function());
+ assert(g is Object Function());
g(); // No runtime error;
o = 3;
Expect.throwsTypeError(() {
@@ -53,7 +53,7 @@
o; // No implicit downcast on the assignment, implicit downcast on the return
assert(g is List<Object> Function());
assert(g is! List<int> Function());
- assert(g is! Object Function());
+ assert(g is Object Function());
g(); // No runtime error;
o = 3;
Expect.throwsTypeError(() {
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index 146c5dd..1b8fbc9 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -43,12 +43,6 @@
[ $compiler == none && $runtime == drt && !$checked ]
assertion_initializer_const_error_test/01: Fail
-# We no longer expect Dart2 tests to run with the standalone VM without the new
-# common front end, but for now we get better coverage by still running them in
-# checked mode, which is mostly Dart2-compatible.
-[ $compiler == none && $runtime == vm && !$checked ]
-*: Skip
-
[ $compiler != spec_parser && !$checked && !$strong ]
closure_type_test: RuntimeError
map_literal1_test/01: MissingCompileTimeError
@@ -176,6 +170,12 @@
[ $checked && !$strong ]
type_parameter_test/05: Pass
+# We no longer expect Dart2 tests to run with the standalone VM without the new
+# common front end, but for now we get better coverage by still running them in
+# checked mode, which is mostly Dart2-compatible.
+[ !$checked && ($compiler == app_jit || $compiler == none || $compiler == precompiler) && ($runtime == dart_precompiled || $runtime == vm) ]
+*: Skip
+
[ !$dart2js_with_kernel && $minified ]
regress_21795_test: RuntimeError # Issue 12605
stack_trace_test: Fail, OK # Stack trace not preserved in minified code.
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index 803fd57..09d1afc 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -1120,6 +1120,7 @@
super_bound_closure_test/none: CompileTimeError
super_setter_test: StaticWarning # Issue 28823
switch_case_test/none: CompileTimeError
+type_inference_accessor_ref_test/06: MissingCompileTimeError
type_inference_circularity_test: MissingCompileTimeError
type_promotion_functions_test/01: Pass
type_promotion_functions_test/05: Pass
@@ -1570,6 +1571,8 @@
try_catch_on_syntax_test/07: MissingCompileTimeError
try_catch_syntax_test/08: MissingCompileTimeError
type_checks_in_factory_method_test/01: MissingCompileTimeError
+type_inference_accessor_ref_test/03: MissingCompileTimeError
+type_inference_accessor_ref_test/06: MissingCompileTimeError
type_inference_circularity_test: MissingCompileTimeError
type_promotion_functions_test/01: MissingCompileTimeError
type_promotion_functions_test/05: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 64b68c3..a753676 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -1197,7 +1197,6 @@
covariant_override/runtime_check_test: RuntimeError
covariant_subtyping_test: CompileTimeError
cyclic_constructor_test/01: Crash # Stack Overflow
-deferred_call_empty_before_load_test: RuntimeError
deferred_constraints_constants_test/default_argument2: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
deferred_constraints_constants_test/none: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
deferred_constraints_constants_test/reference_after_load: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
@@ -1419,9 +1418,6 @@
redirecting_factory_long_test: RuntimeError
redirecting_factory_reflection_test: RuntimeError
regress_20394_test/01: MissingCompileTimeError
-regress_22976_test/01: RuntimeError
-regress_22976_test/02: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/none: Pass # Incorrectly pass, we are ignoring an error due to #31118
regress_24283_test: RuntimeError
regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
regress_28217_test/01: MissingCompileTimeError
@@ -1627,6 +1623,8 @@
object_has_no_call_method_test/02: MissingCompileTimeError
object_has_no_call_method_test/05: MissingCompileTimeError
object_has_no_call_method_test/08: MissingCompileTimeError
+type_inference_accessor_ref_test/03: MissingCompileTimeError
+type_inference_accessor_ref_test/06: MissingCompileTimeError
type_inference_circularity_test: MissingCompileTimeError
type_inference_inconsistent_inheritance_test: MissingCompileTimeError
@@ -1750,7 +1748,6 @@
covariant_subtyping_unsafe_call2_test: RuntimeError
covariant_subtyping_unsafe_call3_test: RuntimeError
cyclic_constructor_test/01: Crash # Stack Overflow
-deferred_call_empty_before_load_test: RuntimeError
deferred_constraints_constants_test/default_argument2: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
deferred_constraints_constants_test/none: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
deferred_constraints_constants_test/reference_after_load: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
@@ -2010,9 +2007,6 @@
redirecting_factory_long_test: RuntimeError
redirecting_factory_reflection_test: RuntimeError
regress_20394_test/01: MissingCompileTimeError
-regress_22976_test/01: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/02: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/none: Pass # Incorrectly pass, we are ignoring an error due to #31118
regress_24283_test: RuntimeError
regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
regress_28217_test/01: MissingCompileTimeError
@@ -2244,7 +2238,6 @@
covariant_subtyping_unsafe_call3_test: RuntimeError
crash_6725_test/01: MissingCompileTimeError
cyclic_constructor_test/01: Crash # Issue 30856
-deferred_call_empty_before_load_test: RuntimeError
deferred_constraints_constants_test/none: CompileTimeError
deferred_constraints_constants_test/reference_after_load: CompileTimeError
deferred_constraints_type_annotation_test/as_operation: MissingCompileTimeError
@@ -2588,9 +2581,6 @@
regress_13462_1_test: CompileTimeError
regress_18535_test: CompileTimeError
regress_20394_test/01: MissingCompileTimeError
-regress_22976_test/01: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/02: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/none: Pass # Incorrectly pass, we are ignoring an error due to #31118
regress_23408_test: Crash # Assertion failure: Missing scope info for j:method(_loadLibraryWrapper).
regress_24283_test: RuntimeError
regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
@@ -3010,7 +3000,6 @@
covariant_subtyping_unsafe_call3_test: RuntimeError
crash_6725_test/01: MissingCompileTimeError
cyclic_constructor_test/01: Crash # Issue 30856
-deferred_call_empty_before_load_test: RuntimeError
deferred_constraints_constants_test/none: CompileTimeError
deferred_constraints_constants_test/reference_after_load: CompileTimeError
deferred_constraints_type_annotation_test/as_operation: MissingCompileTimeError
@@ -3344,9 +3333,6 @@
regress_18535_test: CompileTimeError
regress_20394_test/01: MissingCompileTimeError
regress_21795_test: RuntimeError
-regress_22976_test/01: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/02: Pass # Incorrectly pass, we are ignoring an error due to #31118
-regress_22976_test/none: Pass # Incorrectly pass, we are ignoring an error due to #31118
regress_23408_test: Crash # NoSuchMethodError: The getter 'closureClassEntity' was called on null.
regress_24283_test: RuntimeError, OK # Requires 64 bit numbers.
regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
@@ -3732,6 +3718,8 @@
truncdiv_test: RuntimeError # Issue 15246
try_catch_on_syntax_test/10: Fail # Issue 19823
try_catch_on_syntax_test/11: Fail # Issue 19823
+type_inference_accessor_ref_test/03: MissingCompileTimeError
+type_inference_accessor_ref_test/06: MissingCompileTimeError
type_inference_circularity_test: MissingCompileTimeError
type_inference_inconsistent_inheritance_test: MissingCompileTimeError
type_variable_conflict_test/01: Fail # Issue 13702
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index 2e88f06..40dd00d 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -18,7 +18,6 @@
assertion_initializer_const_function_test/01: Crash
assertion_initializer_test: CompileTimeError
black_listed_test/none: Fail # Issue 14228
-bug31436_test: RuntimeError
built_in_identifier_prefix_test: CompileTimeError
built_in_identifier_type_annotation_test/22: MissingCompileTimeError # Issue 28816
cascaded_forwarding_stubs_generic_test: RuntimeError
@@ -125,16 +124,6 @@
additional_interface_adds_optional_args_concrete_subclass_test: MissingCompileTimeError
additional_interface_adds_optional_args_concrete_test: MissingCompileTimeError
additional_interface_adds_optional_args_supercall_test: MissingCompileTimeError
-assertion_initializer_const_error2_test/cc01: MissingCompileTimeError
-assertion_initializer_const_error2_test/cc02: MissingCompileTimeError
-assertion_initializer_const_error2_test/cc03: MissingCompileTimeError
-assertion_initializer_const_error2_test/cc05: MissingCompileTimeError
-assertion_initializer_const_error2_test/cc06: MissingCompileTimeError
-assertion_initializer_const_error2_test/cc07: MissingCompileTimeError
-assertion_initializer_const_error2_test/cc08: MissingCompileTimeError
-assertion_initializer_const_error2_test/cc09: MissingCompileTimeError
-assertion_initializer_const_error2_test/cc10: MissingCompileTimeError
-assertion_initializer_const_error2_test/cc11: MissingCompileTimeError
assertion_initializer_test: CompileTimeError
async_await_syntax_test/c10a: MissingCompileTimeError
async_await_syntax_test/d08b: MissingCompileTimeError
@@ -143,8 +132,7 @@
async_or_generator_return_type_stacktrace_test/02: MissingCompileTimeError
async_or_generator_return_type_stacktrace_test/03: MissingCompileTimeError
async_return_types_test/tooManyTypeParameters: MissingCompileTimeError
-async_return_types_test/wrongReturnType: Crash # Maltyped input from Fasta, issue 31414
-await_test: Crash # Issue 31541
+async_return_types_test/wrongReturnType: MissingCompileTimeError
bad_named_parameters2_test/01: MissingCompileTimeError
bad_named_parameters_test/01: MissingCompileTimeError
bad_named_parameters_test/02: MissingCompileTimeError
@@ -156,7 +144,6 @@
bad_override_test/03: MissingCompileTimeError
bad_override_test/04: MissingCompileTimeError
bad_override_test/05: MissingCompileTimeError
-bug31436_test: RuntimeError
built_in_identifier_type_annotation_test/22: Crash # Crashes in Fasta, issue 31416
built_in_identifier_type_annotation_test/52: MissingCompileTimeError
built_in_identifier_type_annotation_test/53: MissingCompileTimeError
@@ -193,7 +180,6 @@
compile_time_constant_k_test/03: MissingCompileTimeError
compile_time_constant_o_test/01: MissingCompileTimeError
compile_time_constant_o_test/02: MissingCompileTimeError
-compile_time_constant_p_test/01: Crash
compile_time_constant_static2_test/04: MissingCompileTimeError
compile_time_constant_static3_test/04: MissingCompileTimeError
compile_time_constant_static4_test/02: MissingCompileTimeError
@@ -208,29 +194,19 @@
const_constructor2_test/24: MissingCompileTimeError
const_constructor3_test/04: MissingCompileTimeError
const_constructor_nonconst_field_test/01: MissingCompileTimeError
-const_constructor_syntax_test/05: Crash
const_dynamic_type_literal_test/02: MissingCompileTimeError
-const_error_multiply_initialized_test/01: Crash
-const_error_multiply_initialized_test/02: Crash
-const_error_multiply_initialized_test/03: Crash
-const_error_multiply_initialized_test/04: Crash
const_factory_with_body_test/01: MissingCompileTimeError
const_instance_field_test/01: MissingCompileTimeError
const_map2_test/00: MissingCompileTimeError
const_map3_test/00: MissingCompileTimeError
const_optional_args_test/01: MissingCompileTimeError
-const_qq_test: Crash
const_switch2_test/01: MissingCompileTimeError
const_syntax_test/05: MissingCompileTimeError
-const_syntax_test/09: Crash
const_types_test/34: MissingCompileTimeError
const_types_test/35: MissingCompileTimeError
const_types_test/39: MissingCompileTimeError
const_types_test/40: MissingCompileTimeError
constants_test/05: MissingCompileTimeError
-constructor_duplicate_final_test/01: Crash
-constructor_duplicate_final_test/02: Crash
-constructor_duplicate_final_test/03: Crash
constructor_redirect1_negative_test/01: MissingCompileTimeError
constructor_redirect2_negative_test: MissingCompileTimeError
constructor_redirect2_test/01: MissingCompileTimeError
@@ -289,9 +265,6 @@
field_override4_test/02: MissingCompileTimeError
field_override_test/00: MissingCompileTimeError
field_override_test/01: MissingCompileTimeError
-final_attempt_reinitialization_test/01: Crash
-final_attempt_reinitialization_test/02: Crash
-final_syntax_test/09: Crash
function_propagation_test: CompileTimeError
function_type/function_type10_test: RuntimeError # Issue 31766
function_type/function_type11_test: RuntimeError # Issue 31766
@@ -478,57 +451,28 @@
mixin_invalid_bound_test/08: MissingCompileTimeError
mixin_invalid_bound_test/09: MissingCompileTimeError
mixin_invalid_bound_test/10: MissingCompileTimeError
-mixin_lib_extends_field_test: Crash
-mixin_lib_extends_method_test: Crash
-mixin_of_mixin_test/01: Crash
-mixin_of_mixin_test/02: Crash
-mixin_of_mixin_test/03: Crash
-mixin_of_mixin_test/04: Crash
-mixin_of_mixin_test/05: Crash
-mixin_of_mixin_test/06: Crash
-mixin_of_mixin_test/none: Crash
-mixin_super_2_test/01: Crash
-mixin_super_2_test/02: Crash
-mixin_super_2_test/03: Crash
-mixin_super_2_test/04: Crash
-mixin_super_2_test/none: Crash
+mixin_lib_extends_field_test: RuntimeError
+mixin_of_mixin_test/01: MissingCompileTimeError
+mixin_of_mixin_test/02: MissingCompileTimeError
+mixin_of_mixin_test/03: MissingCompileTimeError
+mixin_of_mixin_test/04: MissingCompileTimeError
+mixin_of_mixin_test/05: MissingCompileTimeError
+mixin_of_mixin_test/06: MissingCompileTimeError
+mixin_super_2_test/01: MissingCompileTimeError
+mixin_super_2_test/03: MissingCompileTimeError
mixin_super_bound_test/01: MissingCompileTimeError
mixin_super_bound_test/02: MissingCompileTimeError
mixin_super_constructor_named_test/01: MissingCompileTimeError
mixin_super_constructor_positionals_test/01: MissingCompileTimeError
-mixin_super_test: Crash
-mixin_super_use_test: Crash
-mixin_superclass_test: Crash
-mixin_supertype_subclass2_test/01: Crash
-mixin_supertype_subclass2_test/02: Crash
-mixin_supertype_subclass2_test/03: Crash
-mixin_supertype_subclass2_test/04: Crash
-mixin_supertype_subclass2_test/05: Crash
-mixin_supertype_subclass2_test/none: Crash
-mixin_supertype_subclass3_test/01: Crash
-mixin_supertype_subclass3_test/02: Crash
-mixin_supertype_subclass3_test/03: Crash
-mixin_supertype_subclass3_test/04: Crash
-mixin_supertype_subclass3_test/05: Crash
-mixin_supertype_subclass3_test/none: Crash
-mixin_supertype_subclass4_test/01: Crash
-mixin_supertype_subclass4_test/02: Crash
-mixin_supertype_subclass4_test/03: Crash
-mixin_supertype_subclass4_test/04: Crash
-mixin_supertype_subclass4_test/05: Crash
-mixin_supertype_subclass4_test/none: Crash
-mixin_supertype_subclass_test/01: Crash
-mixin_supertype_subclass_test/02: Crash
-mixin_supertype_subclass_test/03: Crash
-mixin_supertype_subclass_test/04: Crash
-mixin_supertype_subclass_test/05: Crash
-mixin_supertype_subclass_test/none: Crash
+mixin_super_test: RuntimeError
+mixin_super_use_test: RuntimeError
+mixin_supertype_subclass_test/02: MissingCompileTimeError
+mixin_supertype_subclass_test/05: MissingCompileTimeError
mixin_type_parameters_errors_test/01: MissingCompileTimeError
mixin_type_parameters_errors_test/02: MissingCompileTimeError
mixin_type_parameters_errors_test/03: MissingCompileTimeError
mixin_type_parameters_errors_test/04: MissingCompileTimeError
mixin_type_parameters_errors_test/05: MissingCompileTimeError
-mixin_with_named_import_test: Crash
multiline_newline_test/06: MissingCompileTimeError
multiline_newline_test/06r: MissingCompileTimeError
named_constructor_test/01: MissingCompileTimeError
@@ -586,8 +530,7 @@
redirecting_factory_default_values_test/03: MissingCompileTimeError
redirecting_factory_infinite_steps_test/01: MissingCompileTimeError
redirecting_factory_malbounded_test/01: MissingCompileTimeError
-regress_22976_test/01: CompileTimeError
-regress_23089_test: Crash
+regress_23089_test: Crash # Crashes in KernelClassBuilder.buildTypeArguments
regress_23408_test: CompileTimeError # Issue 31533
regress_25550_test: CompileTimeError
regress_29025_test: CompileTimeError
@@ -607,13 +550,7 @@
string_supertype_checked_test: CompileTimeError # Issue 31616
super_bound_closure_test/none: CompileTimeError # Issue 31533
super_call4_test: CompileTimeError
-super_from_constructor_test: Crash
super_getter_setter_test: CompileTimeError
-super_in_async3_test: Crash
-super_in_async4_test: Crash
-super_in_async6_test: Crash
-super_in_constructor_test: RuntimeError
-super_in_finally_test: Crash
super_no_such_method1_test: CompileTimeError
super_no_such_method2_test: CompileTimeError
super_no_such_method3_test: CompileTimeError
@@ -718,13 +655,6 @@
conditional_import_test: CompileTimeError # Test is broken
cyclic_type_test/00: RuntimeError # Expect.equals(expected: <Derived>, actual: <dynamic>) fails.
cyclic_type_test/01: RuntimeError # Expect.equals(at index 0: Expected <Derived<Derived<int>>...>, Found: <dynamic>) fails.
-enum_duplicate_test/01: RuntimeError # NoSuchMethodError: method not found: '<Unexpected Null Value>'
-enum_duplicate_test/02: RuntimeError # NoSuchMethodError: method not found: '<Unexpected Null Value>'
-enum_duplicate_test/none: RuntimeError # NoSuchMethodError: method not found: '<Unexpected Null Value>'
-enum_mirror_test: RuntimeError # Expect.equals(expected: <Foo.BAR>, actual: <null>) fails.
-enum_private_test/01: RuntimeError # NoSuchMethodError: method not found: '<Unexpected Null Value>'
-enum_private_test/none: RuntimeError # NoSuchMethodError: method not found: '<Unexpected Null Value>'
-enum_test: RuntimeError # NoSuchMethodError: method not found: '<Unexpected Null Value>'
f_bounded_equality_test: RuntimeError # Expect.equals(expected: <dynamic>, actual: <Real>) fails.
first_class_types_test: RuntimeError # Expect.equals(expected: <List>, actual: <List<int>>) fails.
forwarding_stub_tearoff_test: RuntimeError
@@ -786,6 +716,13 @@
type_literal_test: RuntimeError # Expect.equals(expected: <Func>, actual: <(bool) => int>) fails.
instantiate_tearoff_test: RuntimeError
+[ $compiler == dartdevk && $checked ]
+assertion_initializer_const_error2_test/*: MissingCompileTimeError
+assertion_initializer_const_error2_test/none: Pass
+
+[ $compiler == dartdevk && !$checked ]
+assertion_initializer_const_error2_test/*: SkipByDesign # DDC does not support non-checked mode.
+
# Compiler tests for dartdevc and dartdevk. These contain common expectations
# for all runtimes including $runtime == none. They are organized by: shared
# expectations for dartdevc and dartdevk, then expectations for dartdevc, and
@@ -999,3 +936,4 @@
[ $compiler == dartdevk || $compiler == dartdevc && $runtime == none ]
instantiate_type_variable_test/01: CompileTimeError
setter_no_getter_call_test/01: CompileTimeError
+
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 5d9d5ee..dfefc92 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -15,6 +15,9 @@
mock_writable_final_field_test: RuntimeError # Issue 31424
no_such_method_subtype_test: RuntimeError # Issue 31424
+[ $fasta ]
+regress_22976_test/*: CompileTimeError # Issue 31935
+
[ $compiler == dartk && $mode == debug && $runtime == vm && $strong ]
bad_named_parameters_test/01: Crash # Issue(http://dartbug.com/31630)
bad_named_parameters_test/02: Crash # Issue(http://dartbug.com/31630)
@@ -38,7 +41,7 @@
deferred_load_constants_test/02: Fail
deferred_load_constants_test/03: Fail
deferred_load_constants_test/05: Fail
-deferred_not_loaded_check_test: RuntimeError
+deferred_not_loaded_check_test: CompileTimeError
vm/causal_async_exception_stack2_test: SkipByDesign
vm/causal_async_exception_stack_test: SkipByDesign
vm/regress_27201_test: Fail
@@ -83,7 +86,6 @@
async_star_take_reyield_test: RuntimeError
asyncstar_yield_test: RuntimeError
asyncstar_yieldstar_test: RuntimeError
-bug31436_test: RuntimeError
compile_time_constant_checked_test/02: MissingCompileTimeError
const_constructor2_test/20: MissingCompileTimeError
const_constructor2_test/22: MissingCompileTimeError
@@ -327,11 +329,9 @@
cyclic_typedef_test/11: Crash
default_factory2_test/01: MissingCompileTimeError
default_factory_test/01: MissingCompileTimeError
-deferred_call_empty_before_load_test: RuntimeError # Fasta/KernelVM bug: Deferred loading kernel issue 28335.
+deferred_call_empty_before_load_test: CompileTimeError # VM doen't support deserializing load-library checks (issue XXX)
deferred_closurize_load_library_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-deferred_closurize_load_library_test: DartkCrash
deferred_constant_list_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-deferred_constant_list_test: RuntimeError
deferred_constraints_constants_test/default_argument2: Pass # Passes by mistake. KernelVM bug: Deferred loading kernel issue 28335.
deferred_constraints_constants_test/none: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_constraints_constants_test/reference_after_load: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
@@ -341,35 +341,27 @@
deferred_constraints_type_annotation_test/static_method: CompileTimeError # Deferred loading kernel issue 28335.
deferred_constraints_type_annotation_test/type_annotation_non_deferred: CompileTimeError # Deferred loading kernel issue 28335.
deferred_function_type_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-deferred_function_type_test: RuntimeError
deferred_global_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_import_core_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_inheritance_constraints_test/extends: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 28335.
deferred_inheritance_constraints_test/implements: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 28335.
deferred_inheritance_constraints_test/mixin: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 28335.
-deferred_inheritance_constraints_test/redirecting_constructor: MissingCompileTimeError
-deferred_inheritance_constraints_test/redirecting_constructor: RuntimeError # Fasta/KernelVM bug: Deferred loading kernel issue 28335.
+deferred_inheritance_constraints_test/redirecting_constructor: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 28335.
deferred_inlined_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-deferred_inlined_test: RuntimeError
deferred_load_constants_test/none: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_load_inval_code_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_load_library_wrong_args_test/01: Pass # Passes by mistake. KernelVM bug: Deferred loading kernel issue 28335.
deferred_load_library_wrong_args_test/none: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_mixin_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-deferred_mixin_test: RuntimeError
deferred_no_such_method_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-deferred_not_loaded_check_test: RuntimeError # Fasta/KernelVM bug: Deferred loading kernel issue 28335.
+deferred_not_loaded_check_test: CompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 28335.
deferred_only_constant_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-deferred_only_constant_test: RuntimeError
deferred_optimized_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-deferred_redirecting_factory_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-deferred_redirecting_factory_test: RuntimeError
+deferred_redirecting_factory_test: RuntimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_regression_22995_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_regression_28678_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_shadow_load_library_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-deferred_shadow_load_library_test: RuntimeError
deferred_shared_and_unshared_classes_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-deferred_shared_and_unshared_classes_test: RuntimeError
deferred_static_seperate_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_super_dependency_test/01: Pass # Passes by mistake. KernelVM bug: Deferred loading kernel issue 28335.
deferred_type_dependency_test/as: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
@@ -629,7 +621,6 @@
redirecting_factory_long_test: RuntimeError # Fasta bug: Bad compilation of type arguments for redirecting factory.
redirecting_factory_malbounded_test/01: MissingCompileTimeError
regress_22443_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-regress_22976_test/01: CompileTimeError # Issue 31402 (Variable declaration)
regress_23089_test: Crash
regress_23408_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
regress_23408_test: RuntimeError
@@ -863,7 +854,6 @@
async_star_take_reyield_test: RuntimeError
asyncstar_yield_test: RuntimeError
asyncstar_yieldstar_test: RuntimeError
-bug31436_test: RuntimeError
compile_time_constant_checked_test/02: MissingCompileTimeError
const_constructor2_test/20: MissingCompileTimeError
const_constructor2_test/22: MissingCompileTimeError
@@ -1149,7 +1139,7 @@
deep_nesting2_negative_test: Skip # Issue 31158
default_factory2_test/01: MissingCompileTimeError
default_factory_test/01: MissingCompileTimeError
-deferred_call_empty_before_load_test: RuntimeError # Fasta/KernelVM bug: Deferred loading kernel issue 28335.
+deferred_call_empty_before_load_test: CompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 28335.
deferred_closurize_load_library_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_constant_list_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_constraints_constants_test: SkipByDesign
@@ -1176,7 +1166,7 @@
deferred_load_library_wrong_args_test/none: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_mixin_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_no_such_method_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-deferred_not_loaded_check_test: RuntimeError # Fasta/KernelVM bug: Deferred loading kernel issue 28335.
+deferred_not_loaded_check_test: CompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 28335.
deferred_only_constant_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_optimized_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
deferred_redirecting_factory_test: CompileTimeError, Fail, Crash # Issue 23408, KernelVM bug: Deferred loading kernel issue 28335.
@@ -1498,7 +1488,6 @@
regress_13462_1_test: SkipByDesign
regress_18535_test: SkipByDesign
regress_22443_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
-regress_22976_test/01: CompileTimeError # Issue 31402 (Variable declaration)
regress_23089_test: Crash
regress_23408_test: CompileTimeError # KernelVM bug: Deferred loading kernel issue 28335.
regress_23408_test: RuntimeError
diff --git a/tests/language_2/language_2_precompiled.status b/tests/language_2/language_2_precompiled.status
index 6bedfa3..e6ce2c6 100644
--- a/tests/language_2/language_2_precompiled.status
+++ b/tests/language_2/language_2_precompiled.status
@@ -393,9 +393,7 @@
generic_methods_bounds_test/01: MissingCompileTimeError
generic_methods_bounds_test/02: MissingRuntimeError
generic_methods_dynamic_test/01: MissingCompileTimeError
-generic_methods_dynamic_test/02: MissingRuntimeError
generic_methods_dynamic_test/03: MissingCompileTimeError
-generic_methods_dynamic_test/04: MissingRuntimeError
generic_methods_generic_class_tearoff_test: RuntimeError
generic_methods_named_parameters_test: RuntimeError
generic_methods_optional_parameters_test: RuntimeError
@@ -886,6 +884,8 @@
try_catch_on_syntax_test/11: MissingCompileTimeError
try_catch_syntax_test/08: MissingCompileTimeError
type_checks_in_factory_method_test/01: MissingCompileTimeError
+type_inference_accessor_ref_test/03: MissingCompileTimeError
+type_inference_accessor_ref_test/06: MissingCompileTimeError
type_inference_circularity_test: MissingCompileTimeError
type_inference_inconsistent_inheritance_test: MissingCompileTimeError
type_parameter_test/05: MissingCompileTimeError
@@ -1058,6 +1058,8 @@
function_type_call_getter2_test/none: RuntimeError
function_type_test: RuntimeError
generic_field_mixin6_test/none: RuntimeError
+generic_methods_dynamic_test/02: MissingRuntimeError
+generic_methods_dynamic_test/04: MissingRuntimeError
implicit_downcast_during_assignment_test: RuntimeError
implicit_downcast_during_combiner_test: RuntimeError
implicit_downcast_during_compound_assignment_test: RuntimeError
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index 54520a6..291d6f6 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -842,6 +842,8 @@
try_catch_on_syntax_test/11: MissingCompileTimeError
try_catch_syntax_test/08: MissingCompileTimeError
type_checks_in_factory_method_test/01: MissingCompileTimeError
+type_inference_accessor_ref_test/03: MissingCompileTimeError
+type_inference_accessor_ref_test/06: MissingCompileTimeError
type_inference_circularity_test: MissingCompileTimeError
type_inference_inconsistent_inheritance_test: MissingCompileTimeError
type_promotion_functions_test/01: MissingCompileTimeError
diff --git a/tests/language_2/type_inference_accessor_ref_test.dart b/tests/language_2/type_inference_accessor_ref_test.dart
new file mode 100644
index 0000000..cb72da6
--- /dev/null
+++ b/tests/language_2/type_inference_accessor_ref_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2018, 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+class A {
+ B b;
+}
+
+class B {
+ C get c => null;
+ void set c(C value) {}
+}
+
+class C {}
+
+class D extends C {}
+
+class E extends C {}
+
+// Inferred type: A
+var a = new A();
+
+// Inferred type: C
+var x = a.b.c;
+
+// Inferred type: C
+var y = a.b.c ??= new D();
+
+test() {
+ // Verify the types of x and y by trying to assign to them.
+ x = new C(); //# 01: ok
+ x = new E(); //# 02: ok
+ x = new B(); //# 03: compile-time error
+ y = new C(); //# 04: ok
+ y = new E(); //# 05: ok
+ y = new B(); //# 06: compile-time error
+}
+
+main() {}
diff --git a/tests/language_2/void_type_usage_test.dart b/tests/language_2/void_type_usage_test.dart
index 64a040b..135e8bd 100644
--- a/tests/language_2/void_type_usage_test.dart
+++ b/tests/language_2/void_type_usage_test.dart
@@ -224,6 +224,8 @@
void get x => null;
set x(void y) {}
+ void foo() {}
+
void forInTest() {
for (x in <void>[]) {} //# instance3_for_in2: compile-time error
for (x in [1, 2]) {} //# instance3_for_in3: ok
@@ -344,7 +346,7 @@
void testReturnToVoid(void x, void f()) {
void y;
- final void z;
+ final void z = null;
A<void> a = new A<void>();
B b = new B();
C c = new C();
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index bf9e495..f7b811d 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -422,7 +422,7 @@
mirrors/library_imports_prefixed_test: RuntimeError
mirrors/library_imports_shown_test: RuntimeError
mirrors/library_metadata_test: RuntimeError
-mirrors/load_library_test: RuntimeError
+mirrors/load_library_test: CompileTimeError
mirrors/metadata_allowed_values_test/13: MissingCompileTimeError
mirrors/metadata_allowed_values_test/14: MissingCompileTimeError
mirrors/metadata_allowed_values_test/16: Skip # Flaky, crashes.
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index 8d082b1..17f16aa 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -19,20 +19,6 @@
convert/codec1_test: RuntimeError
convert/utf82_test: RuntimeError
html/debugger_test: CompileTimeError
-html/js_typed_interop_anonymous2_exp_test: Crash
-html/js_typed_interop_anonymous2_test: RuntimeError
-html/js_typed_interop_anonymous_exp_test: Crash
-html/js_typed_interop_anonymous_test: RuntimeError
-html/js_typed_interop_anonymous_unreachable_exp_test: Crash
-html/js_typed_interop_dynamic_test: RuntimeError
-html/js_typed_interop_lazy_test/01: RuntimeError
-html/js_typed_interop_lazy_test/none: RuntimeError
-html/js_typed_interop_side_cast_exp_test/01: Crash
-html/js_typed_interop_side_cast_exp_test/none: Crash
-html/js_typed_interop_side_cast_test: RuntimeError
-html/js_typed_interop_test: RuntimeError
-html/js_typed_interop_type2_test/01: RuntimeError
-html/js_typed_interop_type2_test/none: RuntimeError
js/prototype_access_test: RuntimeError
[ $runtime == chrome && ($compiler == dartdevc || $compiler == dartdevk) ]
diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index cebcb02..5373ab3 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -135,7 +135,7 @@
mirrors/library_metadata_test: RuntimeError
mirrors/list_constructor_test/01: Crash, RuntimeError
mirrors/list_constructor_test/none: Crash, RuntimeError
-mirrors/load_library_test: Crash, RuntimeError
+mirrors/load_library_test: CompileTimeError
mirrors/metadata_allowed_values_test/13: MissingCompileTimeError
mirrors/metadata_allowed_values_test/14: MissingCompileTimeError
mirrors/metadata_allowed_values_test/16: Skip # Flaky, crashes.
diff --git a/tests/standalone_2/io/wait_for_error_test.dart b/tests/standalone_2/io/wait_for_error_test.dart
new file mode 100644
index 0000000..a3b71c5
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_error_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+main() {
+ asyncStart();
+ Completer<bool> c = new Completer<bool>();
+ Timer.run(() {
+ c.completeError("Error", StackTrace.current);
+ asyncEnd();
+ });
+ Expect.throws(() => waitFor<bool>(c.future), (e) => e is AsyncError);
+}
diff --git a/tests/standalone_2/io/wait_for_event_helper.dart b/tests/standalone_2/io/wait_for_event_helper.dart
new file mode 100644
index 0000000..e79ff13
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_event_helper.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:mirrors';
+import 'dart:cli';
+
+void Function({Duration timeout}) waitForEvent;
+
+void initWaitForEvent() {
+ LibraryMirror lib = currentMirrorSystem().findLibrary(#dart.cli);
+ for (Symbol s in lib.declarations.keys) {
+ if (s.toString().contains("_WaitForUtils")) {
+ DeclarationMirror d = lib.declarations[s];
+ ClassMirror utils = (d as ClassMirror);
+ for (Symbol m in utils.staticMembers.keys) {
+ if (m.toString().contains("waitForEvent")) {
+ waitForEvent = utils.getField(m).reflectee;
+ }
+ }
+ }
+ }
+}
diff --git a/tests/standalone_2/io/wait_for_event_isolate_test.dart b/tests/standalone_2/io/wait_for_event_isolate_test.dart
new file mode 100644
index 0000000..e051adc
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_event_isolate_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:isolate';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that waitForEvent() returns on an Isolate message.
+
+messageSender(SendPort s) {
+ new Timer(const Duration(seconds: 1), () {
+ s.send(true);
+ });
+}
+
+main() {
+ initWaitForEvent();
+ asyncStart();
+ bool flag1 = false;
+ bool flag2 = false;
+ ReceivePort r = new ReceivePort();
+ Isolate.spawn(messageSender, r.sendPort).then((Isolate i) {
+ r.listen((message) {
+ flag1 = true;
+ });
+ Expect.isFalse(flag1);
+ waitForEvent();
+ Expect.isTrue(flag1);
+ r.close();
+ flag2 = true;
+ });
+ Expect.isFalse(flag1);
+ Expect.isFalse(flag2);
+ waitForEvent();
+ Expect.isTrue(flag1);
+ Expect.isTrue(flag2);
+ asyncEnd();
+}
diff --git a/tests/standalone_2/io/wait_for_event_microtask_test.dart b/tests/standalone_2/io/wait_for_event_microtask_test.dart
new file mode 100644
index 0000000..b707265
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_event_microtask_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that microtasks are run before waitForEvent() blocks.
+
+main() {
+ initWaitForEvent();
+ asyncStart();
+ bool flag = false;
+ scheduleMicrotask(() {
+ flag = true;
+ asyncEnd();
+ });
+ Expect.isFalse(flag);
+ waitForEvent(timeout: const Duration(milliseconds: 10));
+ Expect.isTrue(flag);
+}
diff --git a/tests/standalone_2/io/wait_for_event_nested_microtask_test.dart b/tests/standalone_2/io/wait_for_event_nested_microtask_test.dart
new file mode 100644
index 0000000..cb11bf9
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_event_nested_microtask_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that waitForEvent() drains microtasks before blocking even when
+// called from a microtask.
+
+main() {
+ initWaitForEvent();
+ asyncStart();
+ bool flag1 = false;
+ bool flag2 = false;
+ scheduleMicrotask(() {
+ scheduleMicrotask(() {
+ flag1 = true;
+ asyncEnd();
+ });
+ Expect.isFalse(flag1);
+ waitForEvent(timeout: const Duration(milliseconds: 10));
+ Expect.isTrue(flag1);
+ flag2 = true;
+ });
+ Expect.isFalse(flag1);
+ Expect.isFalse(flag2);
+ waitForEvent(timeout: const Duration(milliseconds: 10));
+ Expect.isTrue(flag1);
+ Expect.isTrue(flag2);
+}
diff --git a/tests/standalone_2/io/wait_for_event_nested_timer_microtask_test.dart b/tests/standalone_2/io/wait_for_event_nested_timer_microtask_test.dart
new file mode 100644
index 0000000..7fbac17
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_event_nested_timer_microtask_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that the microtasks for a message handler are run before
+// waitForEvent() returns.
+
+main() {
+ initWaitForEvent();
+ asyncStart();
+ bool flag = false;
+ Timer.run(() {
+ scheduleMicrotask(() {
+ flag = true;
+ asyncEnd();
+ });
+ });
+ Expect.isFalse(flag);
+ waitForEvent();
+ Expect.isTrue(flag);
+}
diff --git a/tests/standalone_2/io/wait_for_event_nested_timer_test.dart b/tests/standalone_2/io/wait_for_event_nested_timer_test.dart
new file mode 100644
index 0000000..6971952
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_event_nested_timer_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that all messages are processed before waitForEvent() returns.
+
+main() {
+ initWaitForEvent();
+ asyncStart();
+ bool flag = false;
+ Timer.run(() {
+ Timer.run(() {
+ Timer.run(() {
+ Timer.run(() {
+ flag = true;
+ asyncEnd();
+ });
+ });
+ });
+ });
+ Expect.isFalse(flag);
+ waitForEvent();
+ Expect.isTrue(flag);
+}
diff --git a/tests/standalone_2/io/wait_for_event_nested_waits_test.dart b/tests/standalone_2/io/wait_for_event_nested_waits_test.dart
new file mode 100644
index 0000000..0701996
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_event_nested_waits_test.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that waitForEvent() works when called from a message handler.
+
+main() {
+ initWaitForEvent();
+ asyncStart();
+ bool flag1 = false;
+ bool flag2 = false;
+ bool flag3 = false;
+ bool flag4 = false;
+ Timer.run(() {
+ Timer.run(() {
+ Timer.run(() {
+ Timer.run(() {
+ flag1 = true;
+ asyncEnd();
+ });
+ Expect.isFalse(flag1);
+ Expect.isFalse(flag2);
+ Expect.isFalse(flag3);
+ Expect.isFalse(flag4);
+ waitForEvent();
+ Expect.isTrue(flag1);
+ Expect.isFalse(flag2);
+ Expect.isFalse(flag3);
+ Expect.isFalse(flag4);
+ flag2 = true;
+ });
+ Expect.isFalse(flag1);
+ Expect.isFalse(flag2);
+ Expect.isFalse(flag3);
+ Expect.isFalse(flag4);
+ waitForEvent();
+ Expect.isTrue(flag1);
+ Expect.isTrue(flag2);
+ Expect.isFalse(flag3);
+ Expect.isFalse(flag4);
+ flag3 = true;
+ });
+ Expect.isFalse(flag1);
+ Expect.isFalse(flag2);
+ Expect.isFalse(flag3);
+ Expect.isFalse(flag4);
+ waitForEvent();
+ Expect.isTrue(flag1);
+ Expect.isTrue(flag2);
+ Expect.isTrue(flag3);
+ Expect.isFalse(flag4);
+ flag4 = true;
+ });
+ Expect.isFalse(flag1);
+ Expect.isFalse(flag2);
+ Expect.isFalse(flag3);
+ Expect.isFalse(flag4);
+ waitForEvent();
+ Expect.isTrue(flag1);
+ Expect.isTrue(flag2);
+ Expect.isTrue(flag3);
+ Expect.isTrue(flag4);
+}
diff --git a/tests/standalone_2/io/wait_for_event_timer_test.dart b/tests/standalone_2/io/wait_for_event_timer_test.dart
new file mode 100644
index 0000000..5ce0a64
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_event_timer_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that waitForEvent() works in a simple case.
+
+main() {
+ initWaitForEvent();
+ asyncStart();
+ bool flag = false;
+ Timer.run(() {
+ flag = true;
+ asyncEnd();
+ });
+ Expect.isFalse(flag);
+ waitForEvent();
+ Expect.isTrue(flag);
+}
diff --git a/tests/standalone_2/io/wait_for_event_zone_caught_error_test.dart b/tests/standalone_2/io/wait_for_event_zone_caught_error_test.dart
new file mode 100644
index 0000000..09e60c4
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_event_zone_caught_error_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that waitForEvent() doesn't cause an error to escape a Zone that
+// has an error handler.
+
+main() {
+ initWaitForEvent();
+ asyncStart();
+ bool flag = false;
+ runZoned(() {
+ Timer.run(() {
+ asyncEnd();
+ throw "Exception";
+ });
+ }, onError: (e) {
+ flag = true;
+ });
+ Expect.isFalse(flag);
+ waitForEvent();
+ Expect.isTrue(flag);
+}
diff --git a/tests/standalone_2/io/wait_for_event_zone_test.dart b/tests/standalone_2/io/wait_for_event_zone_test.dart
new file mode 100644
index 0000000..b6a7825
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_event_zone_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import 'wait_for_event_helper.dart';
+
+// Tests that waitForEvent() works even when the message handler is run in
+// a different Zone.
+
+main() {
+ initWaitForEvent();
+ asyncStart();
+ bool flag = false;
+ runZoned(() {
+ Timer.run(() {
+ flag = true;
+ asyncEnd();
+ });
+ });
+ Expect.isFalse(flag);
+ waitForEvent();
+ Expect.isTrue(flag);
+}
diff --git a/tests/standalone_2/io/wait_for_exception_test.dart b/tests/standalone_2/io/wait_for_exception_test.dart
new file mode 100644
index 0000000..f5c207d
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_exception_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+main() {
+ asyncStart();
+ Completer<bool> c = new Completer<bool>();
+ runZoned(() {
+ Timer.run(() {
+ asyncEnd();
+ throw "Error";
+ });
+ }, onError: (e) {
+ Expect.isTrue(e is String);
+ c.complete(true);
+ });
+ Expect.isTrue(waitFor<bool>(c.future));
+}
diff --git a/tests/standalone_2/io/wait_for_test.dart b/tests/standalone_2/io/wait_for_test.dart
new file mode 100644
index 0000000..a8ac543
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:mirrors';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+main() {
+ asyncStart();
+ Completer<bool> c = new Completer<bool>();
+ Timer.run(() {
+ c.complete(true);
+ asyncEnd();
+ });
+ bool result = waitFor<bool>(c.future);
+ Expect.isTrue(result);
+}
diff --git a/tests/standalone_2/io/wait_for_timeout_test.dart b/tests/standalone_2/io/wait_for_timeout_test.dart
new file mode 100644
index 0000000..2b239fa
--- /dev/null
+++ b/tests/standalone_2/io/wait_for_timeout_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+import 'dart:cli';
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+main() {
+ asyncStart();
+ Completer<bool> c = new Completer<bool>();
+ Expect.throws(() {
+ waitFor<bool>(c.future, timeout: const Duration(seconds: 1));
+ }, (e) => e is TimeoutException);
+ asyncEnd();
+}
diff --git a/tests/standalone_2/standalone_2.status b/tests/standalone_2/standalone_2.status
index 924b2f6..8bde01d 100644
--- a/tests/standalone_2/standalone_2.status
+++ b/tests/standalone_2/standalone_2.status
@@ -51,6 +51,16 @@
[ $runtime == dart_precompiled ]
http_launch_test: Skip
io/addlatexhash_test: Skip
+io/wait_for_event_isolate_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_microtask_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_nested_microtask_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_nested_timer_microtask_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_nested_timer_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_nested_waits_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_timer_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_zone_caught_error_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_zone_test: SkipByDesign # Uses mirrors.
+io/wait_for_test: SkipByDesign # Uses mirrors.
[ !$strong ]
float_array_static_test: MissingCompileTimeError
diff --git a/tools/VERSION b/tools/VERSION
index f7edf31..82c9caf 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 0
PATCH 0
-PRERELEASE 18
+PRERELEASE 19
PRERELEASE_PATCH 0