Add deferred test for local functions
Change-Id: I9f4b67de9435e74378af72d2a0c0fc711c0b0252
Reviewed-on: https://dart-review.googlesource.com/55891
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/tests/compiler/dart2js/deferred_loading/data/basic_deferred.dart b/tests/compiler/dart2js/deferred_loading/data/basic_deferred.dart
index b7d44ab..2c0951c 100644
--- a/tests/compiler/dart2js/deferred_loading/data/basic_deferred.dart
+++ b/tests/compiler/dart2js/deferred_loading/data/basic_deferred.dart
@@ -4,6 +4,6 @@
import '../libs/basic_deferred_lib.dart' deferred as lib;
/*element: main:OutputUnit(main, {})*/
-main() => lib.loadLibrary().then((_) {
+main() => lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
(lib.funky)();
});
diff --git a/tests/compiler/dart2js/deferred_loading/data/deferred_class.dart b/tests/compiler/dart2js/deferred_loading/data/deferred_class.dart
index 0ded6cf..b688215 100644
--- a/tests/compiler/dart2js/deferred_loading/data/deferred_class.dart
+++ b/tests/compiler/dart2js/deferred_loading/data/deferred_class.dart
@@ -6,7 +6,7 @@
/*element: main:OutputUnit(main, {})*/
main() {
- lib.loadLibrary().then((_) {
+ lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
return new lib.MyClass().foo(87);
});
}
diff --git a/tests/compiler/dart2js/deferred_loading/data/deferred_constant1.dart b/tests/compiler/dart2js/deferred_loading/data/deferred_constant1.dart
index b3d820a..99f8444 100644
--- a/tests/compiler/dart2js/deferred_loading/data/deferred_constant1.dart
+++ b/tests/compiler/dart2js/deferred_loading/data/deferred_constant1.dart
@@ -9,7 +9,7 @@
main() async {
C1.value;
print(const C(4));
- () => print(const C(5));
+ /*OutputUnit(main, {})*/ () => print(const C(5));
await lib2.loadLibrary();
lib2.C2.value;
lib2.C3.value;
diff --git a/tests/compiler/dart2js/deferred_loading/data/deferred_constant2.dart b/tests/compiler/dart2js/deferred_loading/data/deferred_constant2.dart
index 9f82270..f8821ae 100644
--- a/tests/compiler/dart2js/deferred_loading/data/deferred_constant2.dart
+++ b/tests/compiler/dart2js/deferred_loading/data/deferred_constant2.dart
@@ -8,7 +8,7 @@
/*element: main:OutputUnit(main, {})*/
main() {
- lib.loadLibrary().then((_) {
+ lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
Expect.equals(499, lib.C1.value);
});
}
diff --git a/tests/compiler/dart2js/deferred_loading/data/deferred_fail_and_retry.dart b/tests/compiler/dart2js/deferred_loading/data/deferred_fail_and_retry.dart
index 819032b..80b59bf 100644
--- a/tests/compiler/dart2js/deferred_loading/data/deferred_fail_and_retry.dart
+++ b/tests/compiler/dart2js/deferred_loading/data/deferred_fail_and_retry.dart
@@ -34,14 +34,14 @@
]);
asyncStart();
- lib.loadLibrary().then((_) {
+ lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
Expect.fail("Library should not have loaded");
- }, onError: (error) {
- lib.loadLibrary().then((_) {
+ }, onError: /*OutputUnit(main, {})*/ (error) {
+ lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
Expect.equals("loaded", lib.foo());
- }, onError: (error) {
+ }, onError: /*OutputUnit(main, {})*/ (error) {
Expect.fail("Library should have loaded this time");
- }).whenComplete(() {
+ }).whenComplete(/*OutputUnit(main, {})*/ () {
asyncEnd();
});
});
diff --git a/tests/compiler/dart2js/deferred_loading/data/deferred_function.dart b/tests/compiler/dart2js/deferred_loading/data/deferred_function.dart
index d8895f7..6f809df 100644
--- a/tests/compiler/dart2js/deferred_loading/data/deferred_function.dart
+++ b/tests/compiler/dart2js/deferred_loading/data/deferred_function.dart
@@ -14,7 +14,7 @@
/*element: main:OutputUnit(main, {})*/
main() {
- lib.loadLibrary().then((_) {
+ lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
lib.foo('b');
readFoo();
});
diff --git a/tests/compiler/dart2js/deferred_loading/data/deferred_overlapping.dart b/tests/compiler/dart2js/deferred_loading/data/deferred_overlapping.dart
index ea2354b..754ee48 100644
--- a/tests/compiler/dart2js/deferred_loading/data/deferred_overlapping.dart
+++ b/tests/compiler/dart2js/deferred_loading/data/deferred_overlapping.dart
@@ -8,9 +8,9 @@
// lib1.C1 and lib2.C2 has a shared base class. It will go in its own hunk.
/*element: main:OutputUnit(main, {})*/
void main() {
- lib1.loadLibrary().then((_) {
+ lib1.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
new lib1.C1();
- lib2.loadLibrary().then((_) {
+ lib2.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
new lib2.C2();
});
});
diff --git a/tests/compiler/dart2js/deferred_loading/data/dont_inline_deferred_global.dart b/tests/compiler/dart2js/deferred_loading/data/dont_inline_deferred_global.dart
index 58669a5..3e42dd2 100644
--- a/tests/compiler/dart2js/deferred_loading/data/dont_inline_deferred_global.dart
+++ b/tests/compiler/dart2js/deferred_loading/data/dont_inline_deferred_global.dart
@@ -6,7 +6,7 @@
/*element: main:OutputUnit(main, {})*/
void main() {
- lib.loadLibrary().then((_) {
+ lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
print(lib.finalVar);
print(lib.globalVar);
lib.globalVar = "foobar";
diff --git a/tests/compiler/dart2js/deferred_loading/data/static_separate.dart b/tests/compiler/dart2js/deferred_loading/data/static_separate.dart
new file mode 100644
index 0000000..ac5b27d
--- /dev/null
+++ b/tests/compiler/dart2js/deferred_loading/data/static_separate.dart
@@ -0,0 +1,36 @@
+// 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.
+
+// The class lib1.C is referenced via lib1
+// The static function lib1.C.foo is referenced via lib2
+// Dart2js will put them in separate hunks.
+// Similarly for C2, ..., C5.
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+import "../libs/static_separate_lib1.dart" deferred as lib1;
+import "../libs/static_separate_lib2.dart" deferred as lib2;
+
+/*element: main:OutputUnit(main, {})*/
+void main() {
+ asyncStart();
+ Expect.throws(/*OutputUnit(main, {})*/ () => new lib1.C());
+ lib1.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+ lib2.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+ print("HERE");
+ Expect.equals(1, new lib1.C().bar());
+ var x = new lib1.C2();
+ Expect.mapEquals({1: 2}, x.bar);
+ x.bar = {2: 3};
+ Expect.mapEquals({2: 3}, x.bar);
+
+ Expect.equals(lib1.x, new lib1.C3().bar);
+ Expect.mapEquals({lib1.x: lib1.x}, new lib1.C4().bar);
+ Expect.equals(1, new lib1.C5().bar());
+
+ lib2.foo();
+ asyncEnd();
+ });
+ });
+}
diff --git a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
index 8abed7c..cef5d1b 100644
--- a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
+++ b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
@@ -4,6 +4,7 @@
import 'dart:io' hide Link;
import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/closure.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/deferred_load.dart';
@@ -87,44 +88,73 @@
void computeKernelOutputUnitData(
Compiler compiler, MemberEntity member, Map<Id, ActualData> actualMap,
{bool verbose: false}) {
- OutputUnitData data = compiler.backend.outputUnitData;
- String value = outputUnitString(data.outputUnitForEntity(member));
-
KernelBackendStrategy backendStrategy = compiler.backendStrategy;
KernelToElementMapForBuilding elementMap = backendStrategy.elementMap;
MemberDefinition definition = elementMap.getMemberDefinition(member);
+ new TypeMaskIrComputer(
+ compiler.reporter,
+ actualMap,
+ elementMap,
+ member,
+ compiler.backend.outputUnitData,
+ backendStrategy.closureDataLookup as ClosureDataLookup<ir.Node>)
+ .run(definition.node);
+}
- _registerValue(
- computeEntityId(definition.node),
- value,
- member,
- computeSourceSpanFromTreeNode(definition.node),
- actualMap,
- compiler.reporter);
+/// IR visitor for computing inference data for a member.
+class TypeMaskIrComputer extends IrDataExtractor {
+ final KernelToElementMapForBuilding _elementMap;
+ final OutputUnitData _data;
+ final ClosureDataLookup<ir.Node> _closureDataLookup;
- ir.Member memberNode = definition.node;
- if (memberNode is ir.Field && memberNode.isConst) {
- ir.Expression node = memberNode.initializer;
- ConstantValue constant = elementMap.getConstantValue(node);
- if (constant.isPrimitive) return;
- SourceSpan span = computeSourceSpanFromTreeNode(node);
- if (node is ir.ConstructorInvocation ||
- node is ir.ListLiteral ||
- (node is ir.MapLiteral && node.keyType == null)) {
- // Adjust the source-span to match the AST-based location. The kernel FE
- // skips the "const" keyword for the expression offset and any prefix in
- // front of the constructor. The "-6" is an approximation assuming that
- // there is just a single space after "const" and no prefix.
- // TODO(sigmund): offsets should be fixed in the FE instead.
- span = new SourceSpan(span.uri, span.begin - 6, span.end - 6);
+ TypeMaskIrComputer(
+ DiagnosticReporter reporter,
+ Map<Id, ActualData> actualMap,
+ this._elementMap,
+ MemberEntity member,
+ this._data,
+ this._closureDataLookup)
+ : super(reporter, actualMap);
+
+ String getMemberValue(MemberEntity member) {
+ return outputUnitString(_data.outputUnitForEntity(member));
+ }
+
+ @override
+ String computeMemberValue(Id id, ir.Member node) {
+ if (node is ir.Field && node.isConst) {
+ ir.Expression initializer = node.initializer;
+ ConstantValue constant = _elementMap.getConstantValue(initializer);
+ if (!constant.isPrimitive) {
+ SourceSpan span = computeSourceSpanFromTreeNode(initializer);
+ if (initializer is ir.ConstructorInvocation) {
+ // Adjust the source-span to match the AST-based location. The kernel FE
+ // skips the "const" keyword for the expression offset and any prefix in
+ // front of the constructor. The "-6" is an approximation assuming that
+ // there is just a single space after "const" and no prefix.
+ // TODO(sigmund): offsets should be fixed in the FE instead.
+ span = new SourceSpan(span.uri, span.begin - 6, span.end - 6);
+ }
+ _registerValue(
+ new NodeId(span.begin, IdKind.node),
+ outputUnitString(_data.outputUnitForConstant(constant)),
+ node,
+ span,
+ actualMap,
+ reporter);
+ }
}
- _registerValue(
- new NodeId(span.begin, IdKind.node),
- outputUnitString(data.outputUnitForConstant(constant)),
- member,
- span,
- actualMap,
- compiler.reporter);
+
+ return getMemberValue(_elementMap.getMember(node));
+ }
+
+ @override
+ String computeNodeValue(Id id, ir.TreeNode node) {
+ if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
+ ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
+ return getMemberValue(info.callMethod);
+ }
+ return null;
}
}
diff --git a/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_main.dart b/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_main.dart
index 494a35d..a8f56bd 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_main.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_main.dart
@@ -22,8 +22,8 @@
/*element: main:OutputUnit(main, {})*/
void main() {
- lib1.loadLibrary().then((_) {
- lib2.loadLibrary().then((_) {
+ lib1.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+ lib2.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
lib1.foo();
lib2.foo();
print(lib1.C1);
diff --git a/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart
new file mode 100644
index 0000000..d95536e
--- /dev/null
+++ b/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart
@@ -0,0 +1,95 @@
+// 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.
+
+library lib1;
+
+/*class: ConstClass:OutputUnit(2, {lib1, lib2})*/
+class ConstClass {
+ /*element: ConstClass.x:OutputUnit(2, {lib1, lib2})*/
+ final x;
+
+ /*element: ConstClass.:OutputUnit(2, {lib1, lib2})*/
+ const ConstClass(this.x);
+}
+
+/*element: x:OutputUnit(2, {lib1, lib2})*/
+var x = const ConstClass(const ConstClass(1));
+
+/*class: C:OutputUnit(1, {lib1})*/
+class C {
+ /*element: C.foo:OutputUnit(3, {lib2})*/
+ static foo() {
+ /*OutputUnit(3, {lib2})*/ () {}(); // Hack to avoid inlining.
+ return 1;
+ }
+
+ /*element: C.:OutputUnit(1, {lib1})*/
+ C();
+
+ /*element: C.bar:OutputUnit(1, {lib1})*/
+ bar() {
+ /*OutputUnit(1, {lib1})*/ () {}(); // Hack to avoid inlining.
+ return 1;
+ }
+}
+
+/*class: C1:OutputUnit(main, {})*/
+class C1 {
+ /*element: C1.foo:OutputUnit(3, {lib2})*/
+ static var foo = const {};
+ var bar = const {};
+}
+
+/*class: C2:OutputUnit(1, {lib1})*/
+class C2 {
+ /*element: C2.foo:OutputUnit(3, {lib2})*/
+ static var foo = new Map<int, int>.from({1: 2});
+
+ /*element: C2.bar:OutputUnit(1, {lib1})*/
+ var bar = new Map<int, int>.from({1: 2});
+
+ /*element: C2.:OutputUnit(1, {lib1})*/
+ C2();
+}
+
+/*class: C3:OutputUnit(1, {lib1})*/
+class C3 {
+ /*element: C3.foo:OutputUnit(3, {lib2})*/
+ static final foo = const ConstClass(const ConstClass(1));
+
+ /*element: C3.bar:OutputUnit(1, {lib1})*/
+ final bar = const ConstClass(const ConstClass(1));
+
+ /*element: C3.:OutputUnit(1, {lib1})*/
+ C3();
+}
+
+/*class: C4:OutputUnit(1, {lib1})*/
+class C4 {
+ /*element: C4.foo:OutputUnit(3, {lib2})*/
+ static final foo = new Map<ConstClass, ConstClass>.from({x: x});
+
+ /*element: C4.bar:OutputUnit(1, {lib1})*/
+ final bar = new Map<ConstClass, ConstClass>.from({x: x});
+
+ /*element: C4.:OutputUnit(1, {lib1})*/
+ C4();
+}
+
+/*class: C5:OutputUnit(1, {lib1})*/
+class C5 {
+ /*element: C5.foo:OutputUnit(3, {lib2})*/
+ static const foo = /*OutputUnit(3, {lib2})*/ const [
+ const {1: 3}
+ ];
+
+ /*element: C5.:OutputUnit(1, {lib1})*/
+ C5();
+
+ /*element: C5.bar:OutputUnit(1, {lib1})*/
+ bar() {
+ /*OutputUnit(1, {lib1})*/ () {}(); // Hack to avoid inlining.
+ return 1;
+ }
+}
diff --git a/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib2.dart b/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib2.dart
new file mode 100644
index 0000000..4358474
--- /dev/null
+++ b/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib2.dart
@@ -0,0 +1,24 @@
+// 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.
+
+library lib2;
+
+import "package:expect/expect.dart";
+import "static_separate_lib1.dart";
+
+/*element: foo:OutputUnit(3, {lib2})*/
+foo() {
+ Expect.equals(1, C.foo());
+ Expect.mapEquals({}, C1.foo);
+
+ Expect.mapEquals({1: 2}, C2.foo);
+ C2.foo = {1: 2};
+ Expect.mapEquals({1: 2}, C2.foo);
+
+ Expect.equals(x, C3.foo);
+ Expect.mapEquals({x: x}, C4.foo);
+ Expect.listEquals([
+ const {1: 3}
+ ], C5.foo);
+}
diff --git a/tests/compiler/dart2js/deferred_loading/libs/type_argument_dependency_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/type_argument_dependency_lib1.dart
index 37095d3..d785ac6 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/type_argument_dependency_lib1.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/type_argument_dependency_lib1.dart
@@ -5,4 +5,4 @@
import 'type_argument_dependency_lib2.dart';
/*element: doCast:OutputUnit(main, {})*/
-doCast(List<dynamic> l) => l.cast<B>().map((x) => 1);
+doCast(List<dynamic> l) => l.cast<B>().map(/*OutputUnit(main, {})*/ (x) => 1);
diff --git a/tests/compiler/dart2js/inference/inference_test_helper.dart b/tests/compiler/dart2js/inference/inference_test_helper.dart
index a116e44..4094778 100644
--- a/tests/compiler/dart2js/inference/inference_test_helper.dart
+++ b/tests/compiler/dart2js/inference/inference_test_helper.dart
@@ -106,7 +106,7 @@
.run(definition.node);
}
-/// AST visitor for computing inference data for a member.
+/// IR visitor for computing inference data for a member.
class TypeMaskIrComputer extends IrDataExtractor
with ComputeValueMixin<ir.Node> {
final GlobalTypeInferenceResults<ir.Node> results;