Version 2.15.0-80.0.dev
Merge commit '21cbe332fddc90b337045c7cbec66d64dbb84f55' into 'dev'
diff --git a/pkg/analysis_server/benchmark/perf/memory_tests.dart b/pkg/analysis_server/benchmark/perf/memory_tests.dart
index a7b3682..b67b63c 100644
--- a/pkg/analysis_server/benchmark/perf/memory_tests.dart
+++ b/pkg/analysis_server/benchmark/perf/memory_tests.dart
@@ -254,14 +254,11 @@
var total = 0;
- List isolateRefs = vm['isolates'];
- for (Map isolateRef in isolateRefs) {
- var isolate =
- await service.call('getIsolate', {'isolateId': isolateRef['id']});
-
- Map _heaps = isolate['_heaps'];
- total += _heaps['new']['used'] + _heaps['new']['external'] as int;
- total += _heaps['old']['used'] + _heaps['old']['external'] as int;
+ List isolateGroupsRefs = vm['isolateGroups'];
+ for (Map isolateGroupRef in isolateGroupsRefs) {
+ final heapUsage = await service.call('getIsolateGroupMemoryUsage',
+ {'isolateGroupId': isolateGroupRef['id']});
+ total += heapUsage['heapUsage'] + heapUsage['externalUsage'] as int;
}
service.dispose();
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index cccab31..be4cdbe 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -75,9 +75,10 @@
/// Validates that there is an identifier region at [regionSearch] with target
/// at [targetSearch].
- void assertHasRegionTarget(String regionSearch, String targetSearch) {
+ void assertHasRegionTarget(String regionSearch, String targetSearch,
+ {int targetLength = -1}) {
assertHasRegion(regionSearch);
- assertHasTarget(targetSearch);
+ assertHasTarget(targetSearch, targetLength);
}
/// Validates that there is a target in [testTargets] with [testFile], at the
@@ -391,6 +392,62 @@
assertHasRegionTarget('BBB p', 'BBB {}');
}
+ Future<void> test_constructorReference_named() async {
+ addTestFile('''
+class A {}
+class B<T> {
+ B.named();
+}
+void f() {
+ B<A>.named;
+}
+''');
+ await prepareNavigation();
+ assertHasRegionTarget('B<A>.named;', 'named();');
+ assertHasRegionTarget('named;', 'named();');
+ assertHasRegionTarget('A>', 'A {}');
+ }
+
+ Future<void> test_constructorReference_unnamed_declared() async {
+ addTestFile('''
+class A {
+ A();
+}
+void f() {
+ A.new;
+}
+''');
+ await prepareNavigation();
+ assertHasRegionTarget('A.new;', 'A();', targetLength: 0);
+ assertHasRegionTarget('new;', 'A();', targetLength: 0);
+ }
+
+ Future<void> test_constructorReference_unnamed_declared_new() async {
+ addTestFile('''
+class A {
+ A.new();
+}
+void f() {
+ A.new;
+}
+''');
+ await prepareNavigation();
+ assertHasRegionTarget('A.new;', 'new();');
+ assertHasRegionTarget('new;', 'new();');
+ }
+
+ Future<void> test_constructorReference_unnamed_default() async {
+ addTestFile('''
+class A {}
+void f() {
+ A.new;
+}
+''');
+ await prepareNavigation();
+ assertHasRegionTarget('A.new;', 'A {}');
+ assertHasRegionTarget('new;', 'A {}');
+ }
+
Future<void> test_enum_constant() async {
addTestFile('''
enum E { a, b }
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
index 7927eca..38d0316 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
@@ -334,8 +334,12 @@
}
// Stop infinite recursion via links.
- var canonicalFolderPath = folder.resolveSymbolicLinksSync().path;
- if (!visited.add(canonicalFolderPath)) {
+ try {
+ var canonicalFolderPath = folder.resolveSymbolicLinksSync().path;
+ if (!visited.add(canonicalFolderPath)) {
+ return;
+ }
+ } on FileSystemException {
return;
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_root.dart b/pkg/analyzer/lib/src/dart/analysis/context_root.dart
index 068948f..58a4b93 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_root.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_root.dart
@@ -96,13 +96,25 @@
Folder folder,
String includedPath,
) sync* {
- for (Resource resource in folder.getChildren()) {
+ List<Resource> children;
+ try {
+ children = folder.getChildren();
+ } on FileSystemException {
+ return;
+ }
+
+ for (Resource resource in children) {
String path = resource.path;
if (!_isExcluded(path, includedPath)) {
if (resource is File) {
yield path;
} else if (resource is Folder) {
- var canonicalPath = resource.resolveSymbolicLinksSync().path;
+ String canonicalPath;
+ try {
+ canonicalPath = resource.resolveSymbolicLinksSync().path;
+ } on FileSystemException {
+ return;
+ }
if (visited.add(canonicalPath)) {
yield* _includedFilesInFolder(visited, resource, includedPath);
visited.remove(canonicalPath);
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 87fd68d..edcf6c3 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1526,6 +1526,16 @@
ElementKind get kind => ElementKind.CONSTRUCTOR;
@override
+ int get nameLength {
+ final nameEnd = this.nameEnd;
+ if (nameEnd == null || periodOffset == null) {
+ return 0;
+ } else {
+ return nameEnd - nameOffset;
+ }
+ }
+
+ @override
Element get nonSynthetic {
return isSynthetic ? enclosingElement : this;
}
diff --git a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
index 63b08a5..31462c1 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
@@ -95,6 +95,36 @@
]);
}
+ void test_locateRoots_link_folder_notExistingTarget() {
+ var rootFolder = newFolder('/test');
+ newFile('/test/lib/a.dart');
+ newFolder('/test/lib/foo');
+ resourceProvider.newLink(
+ convertPath('/test/lib/foo'),
+ convertPath('/test/lib/bar'),
+ );
+
+ var roots = contextLocator.locateRoots(
+ includedPaths: [rootFolder.path],
+ );
+ expect(roots, hasLength(1));
+
+ var root = findRoot(roots, rootFolder);
+ expect(root.includedPaths, unorderedEquals([rootFolder.path]));
+ expect(root.excludedPaths, isEmpty);
+ expect(root.optionsFile, isNull);
+ expect(root.packagesFile, isNull);
+
+ _assertAnalyzedFiles(root, [
+ '/test/lib/a.dart',
+ ]);
+
+ _assertAnalyzed(root, [
+ '/test/lib/a.dart',
+ '/test/lib/foo/b.dart',
+ ]);
+ }
+
void test_locateRoots_link_folder_toParentInRoot() {
Folder rootFolder = newFolder('/test');
newFile('/test/lib/a.dart');
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index 557e7c1..ec74ce8 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -310,13 +310,27 @@
@override
void visitConstructorName(ConstructorName node) {
- var parent = node.parent;
- if (parent is InstanceCreationExpression &&
- parent.constructorName == node) {
- _addConstructorName(parent, node);
- } else if (parent is ConstructorDeclaration &&
- parent.redirectedConstructor == node) {
- _addConstructorName(node, node);
+ Element? element = node.staticElement;
+ if (element == null) {
+ return;
+ }
+ // add regions
+ var typeName = node.type;
+ // [prefix].ClassName
+ {
+ var name = typeName.name;
+ var className = name;
+ if (name is PrefixedIdentifier) {
+ name.prefix.accept(this);
+ className = name.identifier;
+ }
+ computer._addRegionForNode(className, element);
+ }
+ // <TypeA, TypeB>
+ typeName.typeArguments?.accept(this);
+ // optional "name"
+ if (node.name != null) {
+ computer._addRegionForNode(node.name, element);
}
}
@@ -459,34 +473,6 @@
super.visitVariableDeclarationList(node);
}
- void _addConstructorName(AstNode parent, ConstructorName node) {
- Element? element = node.staticElement;
- if (element == null) {
- return;
- }
- // add regions
- var typeName = node.type;
- // [prefix].ClassName
- {
- var name = typeName.name;
- var className = name;
- if (name is PrefixedIdentifier) {
- name.prefix.accept(this);
- className = name.identifier;
- }
- computer._addRegionForNode(className, element);
- }
- // <TypeA, TypeB>
- var typeArguments = typeName.typeArguments;
- if (typeArguments != null) {
- typeArguments.accept(this);
- }
- // optional "name"
- if (node.name != null) {
- computer._addRegionForNode(node.name, element);
- }
- }
-
/// If the source of the given [element] (referenced by the [node]) exists,
/// then add the navigation region from the [node] to the [element].
void _addUriDirectiveRegion(UriBasedDirective node, Element? element) {
diff --git a/pkg/compiler/lib/src/deferred_load/algorithm_state.dart b/pkg/compiler/lib/src/deferred_load/algorithm_state.dart
index fca24eb..ad11986 100644
--- a/pkg/compiler/lib/src/deferred_load/algorithm_state.dart
+++ b/pkg/compiler/lib/src/deferred_load/algorithm_state.dart
@@ -145,4 +145,14 @@
queue.processNextItem(this);
}
}
+
+ /// Processes each [ImportSet], applying [SetTransition]s if their
+ /// prerequisites are met.
+ void applySetTransitions() {
+ var imports = entityToSet.values.toSet();
+ var finalTransitions = importSets.computeFinalTransitions(imports);
+ for (var key in entityToSet.keys) {
+ entityToSet[key] = finalTransitions[entityToSet[key]];
+ }
+ }
}
diff --git a/pkg/compiler/lib/src/deferred_load/deferred_load.dart b/pkg/compiler/lib/src/deferred_load/deferred_load.dart
index 38da9db..d741a38 100644
--- a/pkg/compiler/lib/src/deferred_load/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load/deferred_load.dart
@@ -366,11 +366,16 @@
/// Computes a unique string for the name field for each outputUnit.
void _createOutputUnits() {
+ // Before finalizing [OutputUnit]s, we apply [ImportSetTransition]s.
+ measureSubtask('apply set transitions', () {
+ algorithmState?.applySetTransitions();
+ });
+
+ // Add an [OutputUnit] for each [ImportSet].
int counter = 1;
void addUnit(ImportSet importSet) {
if (importSet.unit != null) return;
- var unit = OutputUnit(false, '$counter',
- importSet.collectImports().map((i) => i.declaration).toSet());
+ var unit = OutputUnit(false, '$counter', importSet.toSet());
counter++;
importSet.unit = unit;
_allOutputUnits.add(unit);
@@ -535,8 +540,9 @@
// them now.
if (compiler.programSplitConstraintsData != null) {
var builder = psc.Builder(compiler.programSplitConstraintsData);
- var transitions = builder.buildTransitionsMap(_allDeferredImports);
- importSets.buildInitialSets(transitions);
+ var transitions = builder.build(_allDeferredImports);
+ importSets.buildInitialSets(transitions.singletonTransitions);
+ importSets.buildSetTransitions(transitions.setTransitions);
}
// Build the [ImportSet] representing the [_mainOutputUnit].
diff --git a/pkg/compiler/lib/src/deferred_load/import_set.dart b/pkg/compiler/lib/src/deferred_load/import_set.dart
index 984f7cb..9bf3816 100644
--- a/pkg/compiler/lib/src/deferred_load/import_set.dart
+++ b/pkg/compiler/lib/src/deferred_load/import_set.dart
@@ -4,9 +4,25 @@
import 'output_unit.dart';
+import 'program_split_constraints/builder.dart' as psc show SetTransition;
+
import '../elements/entities.dart';
import '../util/maplet.dart';
+/// An [ImportSetTransition] is similar to a [SetTransition]
+/// except its source and transitions are represented as a single [ImportSet].
+class ImportSetTransition {
+ /// The [ImportSet] which, if contained in another [ImportSet] means
+ /// [transitions] should be applied.
+ final ImportSet source;
+
+ /// The [ImportSet] which should be applied if [source] is present in an
+ /// [ImportSet].
+ final ImportSet transitions;
+
+ ImportSetTransition(this.source, this.transitions);
+}
+
/// Indirectly represents a deferred import in an [ImportSet].
///
/// We could directly store the [declaration] in [ImportSet], but adding this
@@ -34,6 +50,10 @@
/// A map of [ImportEntity] to its initial [ImportSet].
final Map<ImportEntity, ImportSet> initialSets = {};
+ /// A list of [ImportSetTransition]s which should be applied to
+ /// [ImportSet]s either during [union] or just before finalization.
+ final List<ImportSetTransition> importSetTransitions = [];
+
/// Index of deferred imports that defines the canonical order used by the
/// operations below.
Map<ImportEntity, _DeferredImport> _importIndex = {};
@@ -90,6 +110,16 @@
});
}
+ /// Builds a list of [ImportSetTransition]s which should be applied
+ /// before finalizing [ImportSet]s.
+ void buildSetTransitions(List<psc.SetTransition> setTransitions) {
+ setTransitions.forEach((setTransition) {
+ importSetTransitions.add(ImportSetTransition(
+ setOfImportsToImportSet(setTransition.source),
+ setOfImportsToImportSet(setTransition.transitions)));
+ });
+ }
+
/// Get the import set that includes the union of [a] and [b].
ImportSet union(ImportSet a, ImportSet b) {
if (a == null || a.isEmpty) return b;
@@ -135,6 +165,52 @@
return result;
}
+ /// Computes a map of transitions, such that the key of every entry in the map
+ /// should be replaced with the value.
+ Map<ImportSet, ImportSet> computeFinalTransitions(Set<ImportSet> imports) {
+ var finalTransitions = <ImportSet, ImportSet>{};
+ var allCandidateTransitions = <ImportSet, Set<ImportSetTransition>>{};
+ bool process(ImportSet originalImportSet) {
+ // If we've already got [finalTransitions] for this [originalImportSet],
+ // i.e. if we've processed it before, we use the processed [ImportSet] for
+ // the next iteration.
+ var importSet = finalTransitions[originalImportSet] ?? originalImportSet;
+ var appliedTransitions = <ImportSetTransition>[];
+
+ // Try and apply any [ImportSetTransition]s that have not yet been
+ // applied to this [ImportSet].
+ var candidateTransitions = allCandidateTransitions[originalImportSet];
+ for (var transition in candidateTransitions) {
+ if (originalImportSet.containsAll(transition.source)) {
+ importSet = union(importSet, transition.transitions);
+ appliedTransitions.add(transition);
+ }
+ }
+
+ // Update [finalTransitions] and remove any applied transitions from
+ // [transitionsToApply] so that they will not be applied again.
+ finalTransitions[originalImportSet] = importSet;
+ candidateTransitions.removeAll(appliedTransitions);
+ return appliedTransitions.isNotEmpty;
+ }
+
+ for (var import in imports) {
+ allCandidateTransitions[import] = importSetTransitions.toSet();
+ }
+
+ // Determine any final transitions.
+ // Note: We have to keep running this algorithm until we reach a fixed
+ // point.
+ var hasChanges = true;
+ do {
+ hasChanges = false;
+ for (var import in imports) {
+ hasChanges |= process(import);
+ }
+ } while (hasChanges);
+ return finalTransitions;
+ }
+
/// Get the index for an [import] according to the canonical order.
_DeferredImport _wrap(ImportEntity import) {
return _importIndex[import] ??=
@@ -182,6 +258,25 @@
/// The output unit corresponding to this set of imports, if any.
OutputUnit unit;
+ /// Returns true if this [ImportSet] contains all of [other].
+ bool containsAll(ImportSet other) {
+ var current = this;
+ while (true) {
+ if (other.isEmpty) return true;
+ if (current.isEmpty) return false;
+
+ if (current._import.index > other._import.index) {
+ current = current._previous;
+ } else if (other._import.index > current._import.index) {
+ return false;
+ } else {
+ assert(current._import.index == other._import.index);
+ current = current._previous;
+ other = other._previous;
+ }
+ }
+ }
+
/// Create an import set that adds [import] to all the imports on this set.
/// This assumes that import's canonical order comes after all imports in
/// this current set. This should only be called from [ImportSetLattice],
@@ -201,4 +296,9 @@
sb.write(')');
return '$sb';
}
+
+ /// Converts an [ImportSet] to a [Set<ImportEntity].
+ /// Note: Not for performance sensitive code.
+ Set<ImportEntity> toSet() =>
+ collectImports().map((i) => i.declaration).toSet();
}
diff --git a/pkg/compiler/lib/src/deferred_load/program_split_constraints/builder.dart b/pkg/compiler/lib/src/deferred_load/program_split_constraints/builder.dart
index c270a19..2520547 100644
--- a/pkg/compiler/lib/src/deferred_load/program_split_constraints/builder.dart
+++ b/pkg/compiler/lib/src/deferred_load/program_split_constraints/builder.dart
@@ -28,6 +28,14 @@
/// Imports which load before [import].
final Set<Constraint> predecessors = {};
+ /// Whether or not this [ConstraintNode] should always apply transitions as
+ /// opposed to conditionally applying transitions.
+ bool get alwaysApplyTransitions {
+ return combinerType == null ||
+ combinerType == CombinerType.and ||
+ combinerType == CombinerType.fuse;
+ }
+
Constraint(this.name, this.imports, this.combinerType) {
assert((this.imports.length == 1 && combinerType == null) ||
(this.imports.length > 1 && combinerType != null));
@@ -65,10 +73,9 @@
Builder(this.nodes);
- /// Builds a map of transitions which can be applied by an [ImportSetLattice]
- /// when generating [ImportSet]s.
- Map<ImportEntity, Set<ImportEntity>> buildTransitionsMap(
- Iterable<ImportEntity> imports) {
+ /// Builds [ProgramSplitConstraints] which can be applied by an
+ /// [ImportSetLattice] when generating [ImportSet]s.
+ ProgramSplitConstraints build(Iterable<ImportEntity> imports) {
// 1) Create a map of uri#prefix to [ImportEntity].
Map<Uri, Map<String, ImportEntity>> importsByUriAndPrefix = {};
for (var import in imports) {
@@ -126,7 +133,8 @@
// transitiveTransitions, where each key is a parent [ImportEntity] and each
// value represents the transitive set of child [ImportEntity]s which are
// always loaded after the parent.
- Map<ImportEntity, Set<ImportEntity>> transitiveTransitions = {};
+ Map<ImportEntity, Set<ImportEntity>> singletonTransitions = {};
+ Map<Constraint, SetTransition> setTransitions = {};
Queue<_WorkItem> queue = Queue.from(nodeToConstraintMap.values
.where((node) => node.successors.isEmpty)
.map((node) => _WorkItem(node)));
@@ -138,18 +146,29 @@
// Update [transitiveTransitions] with reachable transitions for this
// [_WorkItem]
var transitiveChildren = item.transitiveChildren;
- for (var import in imports) {
- // We insert an implicit 'self' transition for every import.
- var transitions = transitiveTransitions[import] ??= {import};
- // In the case of [CombinerType.fuse], the nodes in the
- // [Constraint] form a strongly connected component,
- // i.e. [ImportEntity]s that are always part of a
- // single [ImportSet].
- if (constraint.combinerType == CombinerType.fuse) {
- transitions.addAll(imports);
+ // We only add singletonTransitions for a given [ImportEntity] when it is
+ // guaranteed to dominate another [ImportEntity]. Some nodes such as 'or'
+ // nodes do not have this property.
+ if (constraint.alwaysApplyTransitions) {
+ for (var import in imports) {
+ // We insert an implicit 'self' transition for every import.
+ var transitions = singletonTransitions[import] ??= {import};
+
+ // In the case of [CombinerType.fuse], the nodes in the
+ // [Constraint] form a strongly connected component,
+ // i.e. [ImportEntity]s that are always part of a
+ // single [ImportSet].
+ if (constraint.combinerType == CombinerType.fuse) {
+ transitions.addAll(imports);
+ }
+ transitions.addAll(transitiveChildren);
}
- transitions.addAll(transitiveChildren);
+ } else {
+ assert(constraint.combinerType == CombinerType.or);
+ var setTransition =
+ setTransitions[constraint] ??= SetTransition(constraint.imports);
+ setTransition.transitions.addAll(transitiveChildren);
}
// Propagate constraints transitively to the parent.
@@ -162,6 +181,34 @@
transitiveChildren: predecessorTransitiveChildren));
}
}
- return transitiveTransitions;
+ return ProgramSplitConstraints(
+ singletonTransitions, setTransitions.values.toList());
}
}
+
+/// A [SetTransition] is a set of [ImportEntity] transitions which can only be
+/// applied when all of the [ImportEntity]s in a given [source] are present in a
+/// given [ImportSet].
+class SetTransition {
+ /// The [Set<ImportEntity>] which, if present in a given [ImportSet] means
+ /// [transitions] should be applied.
+ final Set<ImportEntity> source;
+
+ /// The [Set<ImportEntity>] which is applied if [source] is present in a
+ /// given [ImportSet].
+ final Set<ImportEntity> transitions = {};
+
+ SetTransition(this.source);
+}
+
+/// [ProgramSplitConstraints] is a holder for transitions which should be
+/// applied while splitting a program.
+class ProgramSplitConstraints {
+ /// Transitions which apply when a singleton [ImportEntity] is present.
+ final Map<ImportEntity, Set<ImportEntity>> singletonTransitions;
+
+ /// Transitions which apply only when a set of [ImportEntity]s is present.
+ final List<SetTransition> setTransitions;
+
+ ProgramSplitConstraints(this.singletonTransitions, this.setTransitions);
+}
diff --git a/pkg/compiler/lib/src/deferred_load/program_split_constraints/nodes.dart b/pkg/compiler/lib/src/deferred_load/program_split_constraints/nodes.dart
index ea8a9d6..33f7b58 100644
--- a/pkg/compiler/lib/src/deferred_load/program_split_constraints/nodes.dart
+++ b/pkg/compiler/lib/src/deferred_load/program_split_constraints/nodes.dart
@@ -28,7 +28,7 @@
/// A [CombinerType] defines how to combine multiple [ReferenceNode]s in a
/// single step.
-enum CombinerType { fuse, and }
+enum CombinerType { fuse, and, or }
/// A [CombinerNode] is a [NamedNode] with a list of [ReferenceNode] children
/// and a [CombinerType] for combining them.
diff --git a/pkg/compiler/lib/src/deferred_load/program_split_constraints/parser.dart b/pkg/compiler/lib/src/deferred_load/program_split_constraints/parser.dart
index 3333d8a..a758569 100644
--- a/pkg/compiler/lib/src/deferred_load/program_split_constraints/parser.dart
+++ b/pkg/compiler/lib/src/deferred_load/program_split_constraints/parser.dart
@@ -43,6 +43,8 @@
return CombinerType.fuse;
case 'and':
return CombinerType.and;
+ case 'or':
+ return CombinerType.or;
default:
throw 'Unrecognized Combiner $nodeJson';
}
@@ -92,6 +94,7 @@
break;
case 'and':
case 'fuse':
+ case 'or':
combinerConstraints.add(constraint);
break;
case 'order':
diff --git a/pkg/compiler/test/custom_split/custom_split_test.dart b/pkg/compiler/test/custom_split/custom_split_test.dart
index 3411e25..5203eb3 100644
--- a/pkg/compiler/test/custom_split/custom_split_test.dart
+++ b/pkg/compiler/test/custom_split/custom_split_test.dart
@@ -17,6 +17,7 @@
'diamond',
'diamond_and',
'diamond_fuse',
+ 'diamond_or',
'two_step',
'two_branch',
];
diff --git a/pkg/compiler/test/custom_split/data/diamond_or/constraints.json b/pkg/compiler/test/custom_split/data/diamond_or/constraints.json
new file mode 100644
index 0000000..310309a
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/diamond_or/constraints.json
@@ -0,0 +1,40 @@
+[
+ {
+ "type": "reference",
+ "name": "s1",
+ "import": "memory:sdk/tests/web/native/main.dart#step1"
+ },
+ {
+ "type": "reference",
+ "name": "s2a",
+ "import": "memory:sdk/tests/web/native/main.dart#step2a"
+ },
+ {
+ "type": "reference",
+ "name": "s2b",
+ "import": "memory:sdk/tests/web/native/main.dart#step2b"
+ },
+ {
+ "type": "reference",
+ "name": "s3",
+ "import": "memory:sdk/tests/web/native/main.dart#step3"
+ },
+ {
+ "type": "or",
+ "name": "s2",
+ "nodes": [
+ "s2a",
+ "s2b"
+ ]
+ },
+ {
+ "type": "order",
+ "predecessor": "s1",
+ "successor": "s2"
+ },
+ {
+ "type": "order",
+ "predecessor": "s2",
+ "successor": "s3"
+ }
+]
diff --git a/pkg/compiler/test/custom_split/data/diamond_or/main.dart b/pkg/compiler/test/custom_split/data/diamond_or/main.dart
new file mode 100644
index 0000000..eeac09b
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/diamond_or/main.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2021, 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:
+ a_pre_fragments=[
+ p1: {units: [2{step2a}], usedBy: [], needs: []},
+ p2: {units: [5{step2b}], usedBy: [], needs: []},
+ p3: {units: [7{step3}], usedBy: [], needs: []},
+ p4: {units: [3{step2a, step3}], usedBy: [], needs: []},
+ p5: {units: [6{step2b, step3}], usedBy: [], needs: []},
+ p6: {units: [4{step2a, step2b, step3}], usedBy: [], needs: []},
+ p7: {units: [1{step1, step2a, step2b, step3}], usedBy: [], needs: []}],
+ b_finalized_fragments=[
+ f1: [2{step2a}],
+ f2: [5{step2b}],
+ f3: [7{step3}],
+ f4: [3{step2a, step3}],
+ f5: [6{step2b, step3}],
+ f6: [4{step2a, step2b, step3}],
+ f7: [1{step1, step2a, step2b, step3}]],
+ c_steps=[
+ step1=(f7),
+ step2a=(f7, f6, f4, f1),
+ step2b=(f7, f6, f5, f2),
+ step3=(f7, f6, f5, f4, f3)]
+*/
+import 'step1.dart' deferred as step1;
+import 'step2a.dart' deferred as step2a;
+import 'step2b.dart' deferred as step2b;
+import 'step3.dart' deferred as step3;
+
+/*member: main:member_unit=main{}*/
+main() {
+ step1.loadLibrary().then(/*closure_unit=main{}*/ (_) {
+ print(step1.step());
+ step2a.loadLibrary().then(/*closure_unit=main{}*/ (_) {
+ print(step2a.step());
+ });
+ step2b.loadLibrary().then(/*closure_unit=main{}*/ (_) {
+ print(step2b.step());
+ step3.loadLibrary().then(/*closure_unit=main{}*/ (_) {
+ print(step3.step());
+ });
+ });
+ });
+}
diff --git a/pkg/compiler/test/custom_split/data/diamond_or/shared.dart b/pkg/compiler/test/custom_split/data/diamond_or/shared.dart
new file mode 100644
index 0000000..60cec94
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/diamond_or/shared.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2021, 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.
+
+@pragma('dart2js:noInline')
+/*member: step12a:member_unit=1{step1, step2a, step2b, step3}*/
+step12a() => '12a';
+
+@pragma('dart2js:noInline')
+/*member: step12a3:member_unit=1{step1, step2a, step2b, step3}*/
+step12a3() => '12a3';
+
+@pragma('dart2js:noInline')
+/*member: step2a3:member_unit=3{step2a, step3}*/
+step2a3() => '2a3';
+
+@pragma('dart2js:noInline')
+/*member: step12b:member_unit=1{step1, step2a, step2b, step3}*/
+step12b() => '12b';
+
+@pragma('dart2js:noInline')
+/*member: step12b3:member_unit=1{step1, step2a, step2b, step3}*/
+step12b3() => '12b3';
+
+@pragma('dart2js:noInline')
+/*member: step2b3:member_unit=6{step2b, step3}*/
+step2b3() => '2b3';
+
+@pragma('dart2js:noInline')
+/*member: step2ab:member_unit=4{step2a, step2b, step3}*/
+step2ab() => '2ab';
+
+@pragma('dart2js:noInline')
+/*member: step2ab3:member_unit=4{step2a, step2b, step3}*/
+step2ab3() => '2ab3';
+
+@pragma('dart2js:noInline')
+/*member: step13:member_unit=1{step1, step2a, step2b, step3}*/
+step13() => '13';
+
+@pragma('dart2js:noInline')
+/*member: step12ab:member_unit=1{step1, step2a, step2b, step3}*/
+step12ab() => '12ab';
+
+@pragma('dart2js:noInline')
+/*member: step12ab3:member_unit=1{step1, step2a, step2b, step3}*/
+step12ab3() => '12ab3';
diff --git a/pkg/compiler/test/custom_split/data/diamond_or/step1.dart b/pkg/compiler/test/custom_split/data/diamond_or/step1.dart
new file mode 100644
index 0000000..d87a15b
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/diamond_or/step1.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2021, 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 'shared.dart';
+
+/*member: step:member_unit=1{step1, step2a, step2b, step3}*/
+step() => [
+ step12a(),
+ step12b(),
+ step13(),
+ step12ab(),
+ step12a3(),
+ step12b3(),
+ step12ab3(),
+ ];
diff --git a/pkg/compiler/test/custom_split/data/diamond_or/step2a.dart b/pkg/compiler/test/custom_split/data/diamond_or/step2a.dart
new file mode 100644
index 0000000..6c52220
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/diamond_or/step2a.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2021, 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 'shared.dart';
+
+/*member: step:member_unit=2{step2a}*/
+step() => [
+ step12a(),
+ step12a3(),
+ step12ab(),
+ step12ab3(),
+ step2a3(),
+ step2ab(),
+ step2ab3(),
+ ];
diff --git a/pkg/compiler/test/custom_split/data/diamond_or/step2b.dart b/pkg/compiler/test/custom_split/data/diamond_or/step2b.dart
new file mode 100644
index 0000000..46e7aca
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/diamond_or/step2b.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2021, 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 'shared.dart';
+
+/*member: step:member_unit=5{step2b}*/
+step() => [
+ step12b(),
+ step12b3(),
+ step12ab(),
+ step12ab3(),
+ step2b3(),
+ step2ab(),
+ step2ab3(),
+ ];
diff --git a/pkg/compiler/test/custom_split/data/diamond_or/step3.dart b/pkg/compiler/test/custom_split/data/diamond_or/step3.dart
new file mode 100644
index 0000000..c4d45a9
--- /dev/null
+++ b/pkg/compiler/test/custom_split/data/diamond_or/step3.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2021, 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 'shared.dart';
+
+/*member: step:member_unit=7{step3}*/
+step() => [
+ step2a3(),
+ step2b3(),
+ step13(),
+ step2ab3(),
+ step12a3(),
+ step12b3(),
+ step12ab3(),
+ ];
diff --git a/pkg/dartdev/lib/src/analysis_server.dart b/pkg/dartdev/lib/src/analysis_server.dart
index 0d0ce90..0954378 100644
--- a/pkg/dartdev/lib/src/analysis_server.dart
+++ b/pkg/dartdev/lib/src/analysis_server.dart
@@ -27,10 +27,12 @@
this.packagesFile,
this.sdkPath,
this.analysisRoots, {
+ this.cacheDirectoryPath,
@required this.commandName,
@required this.argResults,
});
+ final String cacheDirectoryPath;
final File packagesFile;
final Directory sdkPath;
final List<FileSystemEntity> analysisRoots;
@@ -87,6 +89,7 @@
'--disable-server-feature-search',
'--sdk',
sdkPath.path,
+ if (cacheDirectoryPath != null) '--cache=$cacheDirectoryPath',
if (packagesFile != null) '--packages=${packagesFile.path}',
];
diff --git a/pkg/dartdev/lib/src/commands/analyze.dart b/pkg/dartdev/lib/src/commands/analyze.dart
index 8664577..96f0fbe 100644
--- a/pkg/dartdev/lib/src/commands/analyze.dart
+++ b/pkg/dartdev/lib/src/commands/analyze.dart
@@ -45,6 +45,12 @@
// Options hidden by default.
..addOption(
+ 'cache',
+ valueHelp: 'path',
+ help: 'Override the location of the analysis cache.',
+ hide: !verbose,
+ )
+ ..addOption(
'format',
valueHelp: 'value',
help: 'Specifies the format to display errors.',
@@ -107,6 +113,7 @@
_packagesFile(),
io.Directory(sdk.sdkPath),
targets,
+ cacheDirectoryPath: argResults['cache'],
commandName: 'analyze',
argResults: argResults,
);
diff --git a/pkg/dartdev/test/commands/analyze_test.dart b/pkg/dartdev/test/commands/analyze_test.dart
index ed11a45..af8984c 100644
--- a/pkg/dartdev/test/commands/analyze_test.dart
+++ b/pkg/dartdev/test/commands/analyze_test.dart
@@ -424,6 +424,22 @@
});
});
+ test('--cache', () {
+ var cache = project(name: 'cache');
+
+ p = project(mainSrc: 'var v = 0;');
+ var result = p.runSync([
+ 'analyze',
+ '--cache=${cache.dirPath}',
+ p.mainPath,
+ ]);
+
+ expect(result.exitCode, 0);
+ expect(result.stderr, isEmpty);
+ expect(result.stdout, contains('No issues found!'));
+ expect(cache.findDirectory('.analysis-driver'), isNotNull);
+ });
+
group('display mode', () {
final sampleInfoJson = {
'severity': 'INFO',
diff --git a/pkg/dartdev/test/utils.dart b/pkg/dartdev/test/utils.dart
index 5a64ced..ae6be55 100644
--- a/pkg/dartdev/test/utils.dart
+++ b/pkg/dartdev/test/utils.dart
@@ -141,6 +141,11 @@
String get absolutePathToDartdevFile =>
path.join(sdkRootPath, 'pkg', 'dartdev', 'bin', 'dartdev.dart');
+ Directory findDirectory(String name) {
+ var directory = Directory(path.join(dir.path, name));
+ return directory.existsSync() ? directory : null;
+ }
+
File findFile(String name) {
var file = File(path.join(dir.path, name));
return file.existsSync() ? file : null;
diff --git a/pkg/dev_compiler/lib/src/compiler/js_utils.dart b/pkg/dev_compiler/lib/src/compiler/js_utils.dart
index f6feb7d..73aeddc 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_utils.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_utils.dart
@@ -44,3 +44,12 @@
super.visitAssignment(node);
}
}
+
+/// Recursively clears all source information from all visited nodes.
+class SourceInformationClearer extends BaseVisitor<void> {
+ @override
+ void visitNode(Node node) {
+ node.visitChildren(this);
+ node.sourceInformation = null;
+ }
+}
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 4f3d3c5..102b0e8 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -8,6 +8,8 @@
import 'dart:convert';
import 'dart:math' show max, min;
+import 'package:front_end/src/fasta/kernel/constructor_tearoff_lowering.dart'
+ show isTearOffLowering;
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
@@ -1934,11 +1936,20 @@
fn = _emitFunction(member.function, member.name.text);
}
- return js_ast.Method(_declareMemberName(member), fn,
+ var method = js_ast.Method(_declareMemberName(member), fn,
isGetter: member.isGetter,
isSetter: member.isSetter,
- isStatic: member.isStatic)
- ..sourceInformation = _nodeEnd(member.fileEndOffset);
+ isStatic: member.isStatic);
+
+ if (isTearOffLowering(member)) {
+ // Remove all source information from static methods introduced by the
+ // constructor tearoff CFE lowering.
+ method.accept(js_ast.SourceInformationClearer());
+ } else {
+ method.sourceInformation = _nodeEnd(member.fileEndOffset);
+ }
+
+ return method;
}
js_ast.Fun _emitNativeFunctionBody(Procedure node) {
@@ -2398,7 +2409,11 @@
// Static members skip the rename steps and may require JS interop renames.
if (isStatic) {
var memberName = _emitStaticMemberName(name, member);
- memberNames[member] = memberName.valueWithoutQuotes;
+ if (!isTearOffLowering(member)) {
+ // No need to track the names of methods that were created by the CFE
+ // lowering and don't exist in the original source code.
+ memberNames[member] = memberName.valueWithoutQuotes;
+ }
return memberName;
}
diff --git a/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart b/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
index acb2bcd..7c77325e 100644
--- a/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
+++ b/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
@@ -4,6 +4,8 @@
// @dart = 2.9
+import 'package:front_end/src/fasta/kernel/constructor_tearoff_lowering.dart'
+ show isTearOffLowering;
import 'package:kernel/kernel.dart';
import 'module_symbols.dart';
@@ -143,7 +145,10 @@
void visitProcedure(Procedure node) {
// Legacy libraries contain procedures with no bodies for all Object methods
// in every class. We can ignore these unless they actually contain a body.
- if (node.function.body == null) return;
+ //
+ // Also avoid adding information for the static methods introduced by the
+ // CFE lowering for constructor tearoffs.
+ if (node.function.body == null || isTearOffLowering(node)) return;
var functionSymbol = FunctionSymbol(
name: node.name.text,
// TODO(nshahan) typeId - probably should canonicalize but keep original
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 1beb7d8..8468f28 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -48,7 +48,7 @@
bool get supportsExplicitGetterCalls => false;
@override
- int get enabledConstructorTearOffLowerings => ConstructorTearOffLowering.none;
+ int get enabledConstructorTearOffLowerings => ConstructorTearOffLowering.all;
@override
String get name => 'dartdevc';
diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart
index e63b928..47f9e8d 100644
--- a/pkg/dev_compiler/test/nullable_inference_test.dart
+++ b/pkg/dev_compiler/test/nullable_inference_test.dart
@@ -65,7 +65,8 @@
});
test('this', () async {
- await expectNotNull('class C { m() { return this; } }', 'this');
+ await expectNotNull(
+ 'library a; class C { m() { return this; } }', 'this, new a::C()');
});
test('is', () async {
@@ -80,7 +81,7 @@
test('constructor', () async {
await expectNotNull(
- 'library a; class C {} main() { new C(); }', 'new a::C()');
+ 'library a; class C {} main() { new C(); }', 'new a::C(), new a::C()');
});
group('operator', () {
@@ -490,7 +491,7 @@
await expectNotNull(
'library b; $imports class C { @notNull m() {} } '
'main() { var c = new C(); c.m(); }',
- 'new b::C(), c.{b::C.m}(), c');
+ 'new b::C(), new b::C(), c.{b::C.m}(), c');
});
});
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 2b0b76f..3f1b27e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -6345,6 +6345,13 @@
TypeLiteral node, DartType typeContext) {
DartType inferredType =
inferrer.coreTypes.typeRawType(inferrer.library.nonNullable);
+ if (inferrer.library.enableConstructorTearOffsInLibrary) {
+ inferrer.library.checkBoundsInType(
+ node.type,
+ inferrer.typeSchemaEnvironment,
+ inferrer.library.fileUri,
+ node.fileOffset);
+ }
return new ExpressionInferenceResult(inferredType, node);
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart
new file mode 100644
index 0000000..a5c95ac
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2021, 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 C<T extends num> {}
+
+test() => C<Object>;
+
+test2([Type t = C<Object>]) {}
+
+var test3 = (() => C<Object>)();
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.strong.expect
new file mode 100644
index 0000000..28d6f05
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.strong.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:11:20: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// var test3 = (() => C<Object>)();
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:7:11: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// test() => C<Object>;
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:9:17: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// test2([Type t = C<Object>]) {}
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static field core::Type test3 = (() → core::Type => #C1)(){() → core::Type};
+static method test() → dynamic
+ return #C1;
+static method test2([core::Type t = #C1]) → dynamic {}
+static method main() → dynamic {}
+
+constants {
+ #C1 = TypeLiteralConstant(self::C<core::Object>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.strong.transformed.expect
new file mode 100644
index 0000000..28d6f05
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.strong.transformed.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:11:20: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// var test3 = (() => C<Object>)();
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:7:11: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// test() => C<Object>;
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:9:17: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// test2([Type t = C<Object>]) {}
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static field core::Type test3 = (() → core::Type => #C1)(){() → core::Type};
+static method test() → dynamic
+ return #C1;
+static method test2([core::Type t = #C1]) → dynamic {}
+static method main() → dynamic {}
+
+constants {
+ #C1 = TypeLiteralConstant(self::C<core::Object>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.textual_outline.expect
new file mode 100644
index 0000000..c95931c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+class C<T extends num> {}
+
+test() => C<Object>;
+test2([Type t = C<Object>]) {}
+var test3 = (() => C<Object>)();
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3256518
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+class C<T extends num> {}
+
+main() {}
+test() => C<Object>;
+test2([Type t = C<Object>]) {}
+var test3 = (() => C<Object>)();
diff --git a/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.weak.expect
new file mode 100644
index 0000000..0494323
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.weak.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:11:20: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// var test3 = (() => C<Object>)();
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:7:11: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// test() => C<Object>;
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:9:17: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// test2([Type t = C<Object>]) {}
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static field core::Type test3 = (() → core::Type => #C1)(){() → core::Type};
+static method test() → dynamic
+ return #C1;
+static method test2([core::Type t = #C1]) → dynamic {}
+static method main() → dynamic {}
+
+constants {
+ #C1 = TypeLiteralConstant(self::C<core::Object*>*)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.weak.outline.expect
new file mode 100644
index 0000000..337fe9c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.weak.outline.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:11:20: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// var test3 = (() => C<Object>)();
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ ;
+}
+static field core::Type test3;
+static method test() → dynamic
+ ;
+static method test2([core::Type t]) → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.weak.transformed.expect
new file mode 100644
index 0000000..0494323
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart.weak.transformed.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:11:20: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// var test3 = (() => C<Object>)();
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:7:11: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// test() => C<Object>;
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:9:17: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+// - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+// test2([Type t = C<Object>]) {}
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/bound_checks_in_type_literals.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class C<T extends num> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static field core::Type test3 = (() → core::Type => #C1)(){() → core::Type};
+static method test() → dynamic
+ return #C1;
+static method test2([core::Type t = #C1]) → dynamic {}
+static method main() → dynamic {}
+
+constants {
+ #C1 = TypeLiteralConstant(self::C<core::Object*>*)
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect
index 203b0cf..3eaf932 100644
--- a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect
@@ -24,9 +24,15 @@
@#C1
static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
return new test::Class::_internal(defaultValue: defaultValue);
+ static method _#fact#tearOff({core::bool defaultValue = #C3}) → test::Class
+ return test::Class::fact(defaultValue: defaultValue);
@#C1
static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
return throw "unsupported";
+ static method _#constFact#tearOff({core::bool defaultValue = #C3}) → test::Class
+ return test::Class::constFact(defaultValue: defaultValue);
+ static method /* from org-dartlang-testcase:///patch_lib.dart */ _#_internal#tearOff({core::bool defaultValue = #C2}) → test::Class
+ return new test::Class::_internal(defaultValue: defaultValue);
}
constants {
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect
index 203b0cf..3eaf932 100644
--- a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect
@@ -24,9 +24,15 @@
@#C1
static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
return new test::Class::_internal(defaultValue: defaultValue);
+ static method _#fact#tearOff({core::bool defaultValue = #C3}) → test::Class
+ return test::Class::fact(defaultValue: defaultValue);
@#C1
static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
return throw "unsupported";
+ static method _#constFact#tearOff({core::bool defaultValue = #C3}) → test::Class
+ return test::Class::constFact(defaultValue: defaultValue);
+ static method /* from org-dartlang-testcase:///patch_lib.dart */ _#_internal#tearOff({core::bool defaultValue = #C2}) → test::Class
+ return new test::Class::_internal(defaultValue: defaultValue);
}
constants {
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect
index 203b0cf..3eaf932 100644
--- a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect
@@ -24,9 +24,15 @@
@#C1
static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
return new test::Class::_internal(defaultValue: defaultValue);
+ static method _#fact#tearOff({core::bool defaultValue = #C3}) → test::Class
+ return test::Class::fact(defaultValue: defaultValue);
@#C1
static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
return throw "unsupported";
+ static method _#constFact#tearOff({core::bool defaultValue = #C3}) → test::Class
+ return test::Class::constFact(defaultValue: defaultValue);
+ static method /* from org-dartlang-testcase:///patch_lib.dart */ _#_internal#tearOff({core::bool defaultValue = #C2}) → test::Class
+ return new test::Class::_internal(defaultValue: defaultValue);
}
constants {
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect
index fe1495b..5ab22e6 100644
--- a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect
@@ -21,8 +21,14 @@
;
@_js::patch
external static factory fact({core::bool defaultValue}) → self2::Class;
+ static method _#fact#tearOff({core::bool defaultValue}) → self2::Class
+ return self2::Class::fact(defaultValue: defaultValue);
@_js::patch
external static factory constFact({core::bool defaultValue = true}) → self2::Class;
+ static method _#constFact#tearOff({core::bool defaultValue}) → self2::Class
+ return self2::Class::constFact(defaultValue: defaultValue);
+ static method /* from org-dartlang-testcase:///patch_lib.dart */ _#_internal#tearOff({core::bool defaultValue}) → self2::Class
+ return new self2::Class::_internal(defaultValue: defaultValue);
}
@@ -30,4 +36,4 @@
Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:6:50 -> InstanceConstant(const _Patch{})
Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:8:28 -> InstanceConstant(const _Patch{})
Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
-Extra constant evaluation: evaluated: 4, effectively constant: 3
+Extra constant evaluation: evaluated: 10, effectively constant: 3
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect
index 203b0cf..3eaf932 100644
--- a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect
@@ -24,9 +24,15 @@
@#C1
static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
return new test::Class::_internal(defaultValue: defaultValue);
+ static method _#fact#tearOff({core::bool defaultValue = #C3}) → test::Class
+ return test::Class::fact(defaultValue: defaultValue);
@#C1
static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
return throw "unsupported";
+ static method _#constFact#tearOff({core::bool defaultValue = #C3}) → test::Class
+ return test::Class::constFact(defaultValue: defaultValue);
+ static method /* from org-dartlang-testcase:///patch_lib.dart */ _#_internal#tearOff({core::bool defaultValue = #C2}) → test::Class
+ return new test::Class::_internal(defaultValue: defaultValue);
}
constants {
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.expect
index d463dc9..d249938 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.expect
@@ -10,6 +10,8 @@
return #C1;
get dynFunction() → dynamic
return #C1;
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
}
static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
return t;
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.transformed.expect
index 977003e..e06ef9e 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.transformed.expect
@@ -10,6 +10,8 @@
return #C1;
get dynFunction() → dynamic
return #C1;
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
}
static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
return t;
@@ -28,4 +30,4 @@
Evaluated: VariableGet @ org-dartlang-testcase:///instance_getter_invocation.dart:14:16 -> DoubleConstant(0.0)
Evaluated: VariableGet @ org-dartlang-testcase:///instance_getter_invocation.dart:15:21 -> DoubleConstant(0.0)
Evaluated: VariableGet @ org-dartlang-testcase:///instance_getter_invocation.dart:16:17 -> DoubleConstant(0.0)
-Extra constant evaluation: evaluated: 20, effectively constant: 3
+Extra constant evaluation: evaluated: 21, effectively constant: 3
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.expect
index d463dc9..d249938 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.expect
@@ -10,6 +10,8 @@
return #C1;
get dynFunction() → dynamic
return #C1;
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
}
static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
return t;
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.outline.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.outline.expect
index 85f75fa..41de7ee 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.outline.expect
@@ -9,6 +9,8 @@
;
get dynFunction() → dynamic
;
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
}
static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
;
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.transformed.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.transformed.expect
index 977003e..e06ef9e 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.transformed.expect
@@ -10,6 +10,8 @@
return #C1;
get dynFunction() → dynamic
return #C1;
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
}
static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
return t;
@@ -28,4 +30,4 @@
Evaluated: VariableGet @ org-dartlang-testcase:///instance_getter_invocation.dart:14:16 -> DoubleConstant(0.0)
Evaluated: VariableGet @ org-dartlang-testcase:///instance_getter_invocation.dart:15:21 -> DoubleConstant(0.0)
Evaluated: VariableGet @ org-dartlang-testcase:///instance_getter_invocation.dart:16:17 -> DoubleConstant(0.0)
-Extra constant evaluation: evaluated: 20, effectively constant: 3
+Extra constant evaluation: evaluated: 21, effectively constant: 3
diff --git a/pkg/front_end/testcases/dartdevc/private_covariant.dart.strong.expect b/pkg/front_end/testcases/dartdevc/private_covariant.dart.strong.expect
index 3fed750..d99381b 100644
--- a/pkg/front_end/testcases/dartdevc/private_covariant.dart.strong.expect
+++ b/pkg/front_end/testcases/dartdevc/private_covariant.dart.strong.expect
@@ -7,6 +7,8 @@
: super core::Object::•()
;
method _privateMethod(covariant core::int i) → dynamic {}
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
}
static method main() → dynamic {
new self::Class::•().{self::Class::_privateMethod}(0){(core::int) → dynamic};
diff --git a/pkg/front_end/testcases/dartdevc/private_covariant.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/private_covariant.dart.strong.transformed.expect
index 965d2e1..0941b67 100644
--- a/pkg/front_end/testcases/dartdevc/private_covariant.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/private_covariant.dart.strong.transformed.expect
@@ -7,6 +7,8 @@
: super core::Object::•()
;
method _privateMethod(core::int i) → dynamic {}
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
}
static method main() → dynamic {
new self::Class::•().{self::Class::_privateMethod}(0){(core::int) → dynamic};
diff --git a/pkg/front_end/testcases/dartdevc/private_covariant.dart.weak.expect b/pkg/front_end/testcases/dartdevc/private_covariant.dart.weak.expect
index 3fed750..d99381b 100644
--- a/pkg/front_end/testcases/dartdevc/private_covariant.dart.weak.expect
+++ b/pkg/front_end/testcases/dartdevc/private_covariant.dart.weak.expect
@@ -7,6 +7,8 @@
: super core::Object::•()
;
method _privateMethod(covariant core::int i) → dynamic {}
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
}
static method main() → dynamic {
new self::Class::•().{self::Class::_privateMethod}(0){(core::int) → dynamic};
diff --git a/pkg/front_end/testcases/dartdevc/private_covariant.dart.weak.outline.expect b/pkg/front_end/testcases/dartdevc/private_covariant.dart.weak.outline.expect
index 3a09c94..7c99f9e 100644
--- a/pkg/front_end/testcases/dartdevc/private_covariant.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/dartdevc/private_covariant.dart.weak.outline.expect
@@ -7,6 +7,8 @@
;
method _privateMethod(covariant core::int i) → dynamic
;
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
}
static method main() → dynamic
;
diff --git a/pkg/front_end/testcases/dartdevc/private_covariant.dart.weak.transformed.expect b/pkg/front_end/testcases/dartdevc/private_covariant.dart.weak.transformed.expect
index 965d2e1..0941b67 100644
--- a/pkg/front_end/testcases/dartdevc/private_covariant.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/private_covariant.dart.weak.transformed.expect
@@ -7,6 +7,8 @@
: super core::Object::•()
;
method _privateMethod(core::int i) → dynamic {}
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
}
static method main() → dynamic {
new self::Class::•().{self::Class::_privateMethod}(0){(core::int) → dynamic};
diff --git a/pkg/front_end/testcases/incremental/crash_01.yaml.world.1.expect b/pkg/front_end/testcases/incremental/crash_01.yaml.world.1.expect
index 137fbff..6951e96 100644
--- a/pkg/front_end/testcases/incremental/crash_01.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/crash_01.yaml.world.1.expect
@@ -12,6 +12,8 @@
synthetic constructor •() → int::CupertinoUserInterfaceLevel
: super fra::InheritedWidget::•()
;
+ static method _#new#tearOff() → int::CupertinoUserInterfaceLevel
+ return new int::CupertinoUserInterfaceLevel::•();
}
}
library from "package:flutter/src/widgets/framework.dart" as fra {
diff --git a/pkg/front_end/testcases/incremental/flutter_issue_66122.yaml.world.1.expect b/pkg/front_end/testcases/incremental/flutter_issue_66122.yaml.world.1.expect
index 596001e..15ee75b 100644
--- a/pkg/front_end/testcases/incremental/flutter_issue_66122.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/flutter_issue_66122.yaml.world.1.expect
@@ -37,21 +37,29 @@
synthetic constructor •() → fra::State2
: super fra::State::•()
;
+ static method _#new#tearOff() → fra::State2
+ return new fra::State2::•();
}
class StatefulWidget extends dart.core::Object {
synthetic constructor •() → fra::StatefulWidget
: super dart.core::Object::•()
;
+ static method _#new#tearOff() → fra::StatefulWidget
+ return new fra::StatefulWidget::•();
}
class Widget extends dart.core::Object {
synthetic constructor •() → fra::Widget
: super dart.core::Object::•()
;
+ static method _#new#tearOff() → fra::Widget
+ return new fra::Widget::•();
}
class BuildContext extends dart.core::Object {
synthetic constructor •() → fra::BuildContext
: super dart.core::Object::•()
;
+ static method _#new#tearOff() → fra::BuildContext
+ return new fra::BuildContext::•();
}
static final field fra::State<fra::StatefulWidget> state = new fra::State2::•();
static method foo() → void {
@@ -81,11 +89,15 @@
;
method build(fra::BuildContext* context) → fra::Widget* {}
method afterFirstLayout(fra::BuildContext* context) → void {}
+ static method _#new#tearOff() → main::_HotReloadIssueState*
+ return new main::_HotReloadIssueState::•();
}
class HotReloadIssue extends fra::StatefulWidget {
synthetic constructor •() → main::HotReloadIssue*
: super fra::StatefulWidget::•()
;
+ static method _#new#tearOff() → main::HotReloadIssue*
+ return new main::HotReloadIssue::•();
abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
diff --git a/pkg/front_end/testcases/incremental/flutter_issue_66122.yaml.world.2.expect b/pkg/front_end/testcases/incremental/flutter_issue_66122.yaml.world.2.expect
index f1cc6fa..4ba21fd 100644
--- a/pkg/front_end/testcases/incremental/flutter_issue_66122.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/flutter_issue_66122.yaml.world.2.expect
@@ -37,21 +37,29 @@
synthetic constructor •() → fra::State2
: super fra::State::•()
;
+ static method _#new#tearOff() → fra::State2
+ return new fra::State2::•();
}
class StatefulWidget extends dart.core::Object {
synthetic constructor •() → fra::StatefulWidget
: super dart.core::Object::•()
;
+ static method _#new#tearOff() → fra::StatefulWidget
+ return new fra::StatefulWidget::•();
}
class Widget extends dart.core::Object {
synthetic constructor •() → fra::Widget
: super dart.core::Object::•()
;
+ static method _#new#tearOff() → fra::Widget
+ return new fra::Widget::•();
}
class BuildContext extends dart.core::Object {
synthetic constructor •() → fra::BuildContext
: super dart.core::Object::•()
;
+ static method _#new#tearOff() → fra::BuildContext
+ return new fra::BuildContext::•();
}
static final field fra::State<fra::StatefulWidget> state = new fra::State2::•();
static method foo() → void {
@@ -81,11 +89,15 @@
;
method build(fra::BuildContext* context) → fra::Widget* {}
method afterFirstLayout(fra::BuildContext* context) → void {}
+ static method _#new#tearOff() → main::_HotReloadIssueState*
+ return new main::_HotReloadIssueState::•();
}
class HotReloadIssue extends fra::StatefulWidget {
synthetic constructor •() → main::HotReloadIssue*
: super fra::StatefulWidget::•()
;
+ static method _#new#tearOff() → main::HotReloadIssue*
+ return new main::HotReloadIssue::•();
abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
diff --git a/pkg/front_end/testcases/incremental/flutter_widget_transform.yaml.world.1.expect b/pkg/front_end/testcases/incremental/flutter_widget_transform.yaml.world.1.expect
index aaba95f..4000948 100644
--- a/pkg/front_end/testcases/incremental/flutter_widget_transform.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/flutter_widget_transform.yaml.world.1.expect
@@ -40,6 +40,8 @@
const constructor •({dart.core::String* file = #C1, dart.core::int* line = #C1, dart.core::int* column = #C1, dart.core::String* name = #C1, dart.core::List<wid::_Location*>* parameterLocations = #C1}) → wid::_Location*
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
;
+ static method _#new#tearOff({dart.core::String* file = #C1, dart.core::int* line = #C1, dart.core::int* column = #C1, dart.core::String* name = #C1, dart.core::List<wid::_Location*>* parameterLocations = #C1}) → wid::_Location*
+ return new wid::_Location::•(file: file, line: line, column: column, name: name, parameterLocations: parameterLocations);
abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
@@ -56,8 +58,15 @@
synthetic constructor •({wid::_Location* $creationLocationd_0dea112b090073317d4 = #C1}) → main::Foo*
: super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
;
+ static method _#new#tearOff() → main::Foo*
+ return new main::Foo::•($creationLocationd_0dea112b090073317d4: #C6);
}
}
constants {
#C1 = null
+ #C2 = "org-dartlang-test:///main.dart"
+ #C3 = 5.0
+ #C4 = 7.0
+ #C5 = "Foo"
+ #C6 = wid::_Location {file:#C2, line:#C3, column:#C4, name:#C5, parameterLocations:#C1}
}
diff --git a/pkg/front_end/testcases/incremental/flutter_widget_transform.yaml.world.2.expect b/pkg/front_end/testcases/incremental/flutter_widget_transform.yaml.world.2.expect
index aaba95f..4000948 100644
--- a/pkg/front_end/testcases/incremental/flutter_widget_transform.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/flutter_widget_transform.yaml.world.2.expect
@@ -40,6 +40,8 @@
const constructor •({dart.core::String* file = #C1, dart.core::int* line = #C1, dart.core::int* column = #C1, dart.core::String* name = #C1, dart.core::List<wid::_Location*>* parameterLocations = #C1}) → wid::_Location*
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
;
+ static method _#new#tearOff({dart.core::String* file = #C1, dart.core::int* line = #C1, dart.core::int* column = #C1, dart.core::String* name = #C1, dart.core::List<wid::_Location*>* parameterLocations = #C1}) → wid::_Location*
+ return new wid::_Location::•(file: file, line: line, column: column, name: name, parameterLocations: parameterLocations);
abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
@@ -56,8 +58,15 @@
synthetic constructor •({wid::_Location* $creationLocationd_0dea112b090073317d4 = #C1}) → main::Foo*
: super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
;
+ static method _#new#tearOff() → main::Foo*
+ return new main::Foo::•($creationLocationd_0dea112b090073317d4: #C6);
}
}
constants {
#C1 = null
+ #C2 = "org-dartlang-test:///main.dart"
+ #C3 = 5.0
+ #C4 = 7.0
+ #C5 = "Foo"
+ #C6 = wid::_Location {file:#C2, line:#C3, column:#C4, name:#C5, parameterLocations:#C1}
}
diff --git a/pkg/front_end/testcases/incremental/flutter_widget_transform_const.yaml.world.1.expect b/pkg/front_end/testcases/incremental/flutter_widget_transform_const.yaml.world.1.expect
index e334a8f..41475f6 100644
--- a/pkg/front_end/testcases/incremental/flutter_widget_transform_const.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/flutter_widget_transform_const.yaml.world.1.expect
@@ -30,6 +30,8 @@
const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
;
+ static method _#new#tearOff({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
+ return new wid::_Location::•(file: file, line: line, column: column, name: name, parameterLocations: parameterLocations);
}
}
library from "org-dartlang-test:///foo.dart" as foo {
@@ -43,6 +45,10 @@
;
static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
return #C7;
+ static method _#new#tearOff() → foo::Foo
+ return foo::Foo::•($creationLocationd_0dea112b090073317d4: #C9);
+ static method _#_#tearOff() → foo::Foo
+ return new foo::Foo::_($creationLocationd_0dea112b090073317d4: #C12);
}
class Bar extends fra::Widget /*hasConstConstructor*/ {
static final field dynamic _redirecting# = <dynamic>[foo::Bar::•]/*isLegacy*/;
@@ -51,6 +57,10 @@
;
static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Bar
return new foo::Bar::_($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4);
+ static method _#new#tearOff() → foo::Bar
+ return new foo::Bar::_($creationLocationd_0dea112b090073317d4: #C16);
+ static method _#_#tearOff() → foo::Bar
+ return new foo::Bar::_($creationLocationd_0dea112b090073317d4: #C18);
}
class Baz extends fra::Widget /*hasConstConstructor*/ {
static final field dynamic _redirecting# = <dynamic>[foo::Baz::_]/*isLegacy*/;
@@ -58,9 +68,15 @@
: super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
;
static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
- return #C11;
+ return #C22;
+ static method _#new#tearOff() → foo::Baz
+ return foo::Baz::•($creationLocationd_0dea112b090073317d4: #C23);
static factory _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
return new foo::Baz::__($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4);
+ static method _#_#tearOff() → foo::Baz
+ return new foo::Baz::__($creationLocationd_0dea112b090073317d4: #C25);
+ static method _#__#tearOff() → foo::Baz
+ return new foo::Baz::__($creationLocationd_0dea112b090073317d4: #C27);
}
class Boz extends fra::Widget /*hasConstConstructor*/ {
const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Boz
@@ -71,21 +87,25 @@
return new foo::Boz::_($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4);
}
else {
- return #C16;
+ return #C32;
}
}
+ static method _#new#tearOff({required dart.core::bool createNew = #C1}) → foo::Boz
+ return foo::Boz::•(createNew: createNew, $creationLocationd_0dea112b090073317d4: #C33);
+ static method _#_#tearOff() → foo::Boz
+ return new foo::Boz::_($creationLocationd_0dea112b090073317d4: #C35);
}
}
library from "org-dartlang-test:///main.dart" as main {
import "org-dartlang-test:///foo.dart";
- static field foo::Foo newFoo = foo::Foo::•($creationLocationd_0dea112b090073317d4: #C19);
- static field foo::Bar newBar = new foo::Bar::_($creationLocationd_0dea112b090073317d4: #C22);
- static field foo::Bar constBar = #C26;
- static field foo::Baz newBaz = foo::Baz::•($creationLocationd_0dea112b090073317d4: #C28);
- static field foo::Boz newBoz = foo::Boz::•(createNew: true, $creationLocationd_0dea112b090073317d4: #C29);
- static field foo::Boz constBoz = foo::Boz::•(createNew: false, $creationLocationd_0dea112b090073317d4: #C32);
+ static field foo::Foo newFoo = foo::Foo::•($creationLocationd_0dea112b090073317d4: #C38);
+ static field foo::Bar newBar = new foo::Bar::_($creationLocationd_0dea112b090073317d4: #C39);
+ static field foo::Bar constBar = #C42;
+ static field foo::Baz newBaz = foo::Baz::•($creationLocationd_0dea112b090073317d4: #C43);
+ static field foo::Boz newBoz = foo::Boz::•(createNew: true, $creationLocationd_0dea112b090073317d4: #C44);
+ static field foo::Boz constBoz = foo::Boz::•(createNew: false, $creationLocationd_0dea112b090073317d4: #C46);
}
constants {
#C1 = null
@@ -95,29 +115,43 @@
#C5 = "Foo"
#C6 = wid::_Location {file:#C2, line:#C3, column:#C4, name:#C5, parameterLocations:#C1}
#C7 = foo::Foo {_location:#C6}
- #C8 = 6.0
- #C9 = "Baz"
- #C10 = wid::_Location {file:#C2, line:#C8, column:#C4, name:#C9, parameterLocations:#C1}
- #C11 = foo::Baz {_location:#C10}
- #C12 = 9.0
- #C13 = 128.0
- #C14 = "Boz"
- #C15 = wid::_Location {file:#C2, line:#C12, column:#C13, name:#C14, parameterLocations:#C1}
- #C16 = foo::Boz {_location:#C15}
- #C17 = "org-dartlang-test:///main.dart"
- #C18 = 18.0
- #C19 = wid::_Location {file:#C17, line:#C3, column:#C18, name:#C5, parameterLocations:#C1}
- #C20 = 3.0
- #C21 = "Bar"
- #C22 = wid::_Location {file:#C17, line:#C20, column:#C18, name:#C21, parameterLocations:#C1}
- #C23 = 4.0
- #C24 = 22.0
- #C25 = wid::_Location {file:#C17, line:#C23, column:#C24, name:#C21, parameterLocations:#C1}
- #C26 = foo::Bar {_location:#C25}
- #C27 = 5.0
- #C28 = wid::_Location {file:#C17, line:#C27, column:#C18, name:#C9, parameterLocations:#C1}
- #C29 = wid::_Location {file:#C17, line:#C8, column:#C18, name:#C14, parameterLocations:#C1}
- #C30 = 7.0
- #C31 = 20.0
- #C32 = wid::_Location {file:#C17, line:#C30, column:#C31, name:#C14, parameterLocations:#C1}
+ #C8 = 36.0
+ #C9 = wid::_Location {file:#C2, line:#C3, column:#C8, name:#C5, parameterLocations:#C1}
+ #C10 = 3.0
+ #C11 = 7.0
+ #C12 = wid::_Location {file:#C2, line:#C10, column:#C11, name:#C5, parameterLocations:#C1}
+ #C13 = 4.0
+ #C14 = 42.0
+ #C15 = "Bar"
+ #C16 = wid::_Location {file:#C2, line:#C13, column:#C14, name:#C15, parameterLocations:#C1}
+ #C17 = 5.0
+ #C18 = wid::_Location {file:#C2, line:#C17, column:#C11, name:#C15, parameterLocations:#C1}
+ #C19 = 6.0
+ #C20 = "Baz"
+ #C21 = wid::_Location {file:#C2, line:#C19, column:#C4, name:#C20, parameterLocations:#C1}
+ #C22 = foo::Baz {_location:#C21}
+ #C23 = wid::_Location {file:#C2, line:#C19, column:#C8, name:#C20, parameterLocations:#C1}
+ #C24 = 15.0
+ #C25 = wid::_Location {file:#C2, line:#C11, column:#C24, name:#C20, parameterLocations:#C1}
+ #C26 = 8.0
+ #C27 = wid::_Location {file:#C2, line:#C26, column:#C11, name:#C20, parameterLocations:#C1}
+ #C28 = 9.0
+ #C29 = 128.0
+ #C30 = "Boz"
+ #C31 = wid::_Location {file:#C2, line:#C28, column:#C29, name:#C30, parameterLocations:#C1}
+ #C32 = foo::Boz {_location:#C31}
+ #C33 = wid::_Location {file:#C2, line:#C28, column:#C8, name:#C30, parameterLocations:#C1}
+ #C34 = 10.0
+ #C35 = wid::_Location {file:#C2, line:#C34, column:#C11, name:#C30, parameterLocations:#C1}
+ #C36 = "org-dartlang-test:///main.dart"
+ #C37 = 18.0
+ #C38 = wid::_Location {file:#C36, line:#C3, column:#C37, name:#C5, parameterLocations:#C1}
+ #C39 = wid::_Location {file:#C36, line:#C10, column:#C37, name:#C15, parameterLocations:#C1}
+ #C40 = 22.0
+ #C41 = wid::_Location {file:#C36, line:#C13, column:#C40, name:#C15, parameterLocations:#C1}
+ #C42 = foo::Bar {_location:#C41}
+ #C43 = wid::_Location {file:#C36, line:#C17, column:#C37, name:#C20, parameterLocations:#C1}
+ #C44 = wid::_Location {file:#C36, line:#C19, column:#C37, name:#C30, parameterLocations:#C1}
+ #C45 = 20.0
+ #C46 = wid::_Location {file:#C36, line:#C11, column:#C45, name:#C30, parameterLocations:#C1}
}
diff --git a/pkg/front_end/testcases/incremental/flutter_widget_transform_const.yaml.world.2.expect b/pkg/front_end/testcases/incremental/flutter_widget_transform_const.yaml.world.2.expect
index c1f530e..6f610b2 100644
--- a/pkg/front_end/testcases/incremental/flutter_widget_transform_const.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/flutter_widget_transform_const.yaml.world.2.expect
@@ -30,6 +30,8 @@
const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
;
+ static method _#new#tearOff({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
+ return new wid::_Location::•(file: file, line: line, column: column, name: name, parameterLocations: parameterLocations);
}
}
library from "org-dartlang-test:///foo.dart" as foo {
@@ -43,6 +45,10 @@
;
static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
return #C7;
+ static method _#new#tearOff() → foo::Foo
+ return foo::Foo::•($creationLocationd_0dea112b090073317d4: #C9);
+ static method _#_#tearOff() → foo::Foo
+ return new foo::Foo::_($creationLocationd_0dea112b090073317d4: #C12);
}
class Bar extends fra::Widget /*hasConstConstructor*/ {
static final field dynamic _redirecting# = <dynamic>[foo::Bar::•]/*isLegacy*/;
@@ -51,6 +57,10 @@
;
static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Bar
return new foo::Bar::_($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4);
+ static method _#new#tearOff() → foo::Bar
+ return new foo::Bar::_($creationLocationd_0dea112b090073317d4: #C16);
+ static method _#_#tearOff() → foo::Bar
+ return new foo::Bar::_($creationLocationd_0dea112b090073317d4: #C18);
}
class Baz extends fra::Widget /*hasConstConstructor*/ {
static final field dynamic _redirecting# = <dynamic>[foo::Baz::_]/*isLegacy*/;
@@ -58,9 +68,15 @@
: super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
;
static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
- return #C11;
+ return #C22;
+ static method _#new#tearOff() → foo::Baz
+ return foo::Baz::•($creationLocationd_0dea112b090073317d4: #C23);
static factory _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
return new foo::Baz::__($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4);
+ static method _#_#tearOff() → foo::Baz
+ return new foo::Baz::__($creationLocationd_0dea112b090073317d4: #C25);
+ static method _#__#tearOff() → foo::Baz
+ return new foo::Baz::__($creationLocationd_0dea112b090073317d4: #C27);
}
class Boz extends fra::Widget /*hasConstConstructor*/ {
const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Boz
@@ -71,9 +87,13 @@
return new foo::Boz::_($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4);
}
else {
- return #C16;
+ return #C32;
}
}
+ static method _#new#tearOff({required dart.core::bool createNew = #C1}) → foo::Boz
+ return foo::Boz::•(createNew: createNew, $creationLocationd_0dea112b090073317d4: #C33);
+ static method _#_#tearOff() → foo::Boz
+ return new foo::Boz::_($creationLocationd_0dea112b090073317d4: #C35);
}
}
library from "org-dartlang-test:///main.dart" as main {
@@ -89,13 +109,32 @@
#C5 = "Foo"
#C6 = wid::_Location {file:#C2, line:#C3, column:#C4, name:#C5, parameterLocations:#C1}
#C7 = foo::Foo {_location:#C6}
- #C8 = 6.0
- #C9 = "Baz"
- #C10 = wid::_Location {file:#C2, line:#C8, column:#C4, name:#C9, parameterLocations:#C1}
- #C11 = foo::Baz {_location:#C10}
- #C12 = 9.0
- #C13 = 128.0
- #C14 = "Boz"
- #C15 = wid::_Location {file:#C2, line:#C12, column:#C13, name:#C14, parameterLocations:#C1}
- #C16 = foo::Boz {_location:#C15}
+ #C8 = 36.0
+ #C9 = wid::_Location {file:#C2, line:#C3, column:#C8, name:#C5, parameterLocations:#C1}
+ #C10 = 3.0
+ #C11 = 7.0
+ #C12 = wid::_Location {file:#C2, line:#C10, column:#C11, name:#C5, parameterLocations:#C1}
+ #C13 = 4.0
+ #C14 = 42.0
+ #C15 = "Bar"
+ #C16 = wid::_Location {file:#C2, line:#C13, column:#C14, name:#C15, parameterLocations:#C1}
+ #C17 = 5.0
+ #C18 = wid::_Location {file:#C2, line:#C17, column:#C11, name:#C15, parameterLocations:#C1}
+ #C19 = 6.0
+ #C20 = "Baz"
+ #C21 = wid::_Location {file:#C2, line:#C19, column:#C4, name:#C20, parameterLocations:#C1}
+ #C22 = foo::Baz {_location:#C21}
+ #C23 = wid::_Location {file:#C2, line:#C19, column:#C8, name:#C20, parameterLocations:#C1}
+ #C24 = 15.0
+ #C25 = wid::_Location {file:#C2, line:#C11, column:#C24, name:#C20, parameterLocations:#C1}
+ #C26 = 8.0
+ #C27 = wid::_Location {file:#C2, line:#C26, column:#C11, name:#C20, parameterLocations:#C1}
+ #C28 = 9.0
+ #C29 = 128.0
+ #C30 = "Boz"
+ #C31 = wid::_Location {file:#C2, line:#C28, column:#C29, name:#C30, parameterLocations:#C1}
+ #C32 = foo::Boz {_location:#C31}
+ #C33 = wid::_Location {file:#C2, line:#C28, column:#C8, name:#C30, parameterLocations:#C1}
+ #C34 = 10.0
+ #C35 = wid::_Location {file:#C2, line:#C34, column:#C11, name:#C30, parameterLocations:#C1}
}
diff --git a/pkg/front_end/testcases/incremental/flutter_widget_transform_const.yaml.world.3.expect b/pkg/front_end/testcases/incremental/flutter_widget_transform_const.yaml.world.3.expect
index e334a8f..41475f6 100644
--- a/pkg/front_end/testcases/incremental/flutter_widget_transform_const.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental/flutter_widget_transform_const.yaml.world.3.expect
@@ -30,6 +30,8 @@
const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
;
+ static method _#new#tearOff({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
+ return new wid::_Location::•(file: file, line: line, column: column, name: name, parameterLocations: parameterLocations);
}
}
library from "org-dartlang-test:///foo.dart" as foo {
@@ -43,6 +45,10 @@
;
static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
return #C7;
+ static method _#new#tearOff() → foo::Foo
+ return foo::Foo::•($creationLocationd_0dea112b090073317d4: #C9);
+ static method _#_#tearOff() → foo::Foo
+ return new foo::Foo::_($creationLocationd_0dea112b090073317d4: #C12);
}
class Bar extends fra::Widget /*hasConstConstructor*/ {
static final field dynamic _redirecting# = <dynamic>[foo::Bar::•]/*isLegacy*/;
@@ -51,6 +57,10 @@
;
static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Bar
return new foo::Bar::_($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4);
+ static method _#new#tearOff() → foo::Bar
+ return new foo::Bar::_($creationLocationd_0dea112b090073317d4: #C16);
+ static method _#_#tearOff() → foo::Bar
+ return new foo::Bar::_($creationLocationd_0dea112b090073317d4: #C18);
}
class Baz extends fra::Widget /*hasConstConstructor*/ {
static final field dynamic _redirecting# = <dynamic>[foo::Baz::_]/*isLegacy*/;
@@ -58,9 +68,15 @@
: super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
;
static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
- return #C11;
+ return #C22;
+ static method _#new#tearOff() → foo::Baz
+ return foo::Baz::•($creationLocationd_0dea112b090073317d4: #C23);
static factory _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
return new foo::Baz::__($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4);
+ static method _#_#tearOff() → foo::Baz
+ return new foo::Baz::__($creationLocationd_0dea112b090073317d4: #C25);
+ static method _#__#tearOff() → foo::Baz
+ return new foo::Baz::__($creationLocationd_0dea112b090073317d4: #C27);
}
class Boz extends fra::Widget /*hasConstConstructor*/ {
const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Boz
@@ -71,21 +87,25 @@
return new foo::Boz::_($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4);
}
else {
- return #C16;
+ return #C32;
}
}
+ static method _#new#tearOff({required dart.core::bool createNew = #C1}) → foo::Boz
+ return foo::Boz::•(createNew: createNew, $creationLocationd_0dea112b090073317d4: #C33);
+ static method _#_#tearOff() → foo::Boz
+ return new foo::Boz::_($creationLocationd_0dea112b090073317d4: #C35);
}
}
library from "org-dartlang-test:///main.dart" as main {
import "org-dartlang-test:///foo.dart";
- static field foo::Foo newFoo = foo::Foo::•($creationLocationd_0dea112b090073317d4: #C19);
- static field foo::Bar newBar = new foo::Bar::_($creationLocationd_0dea112b090073317d4: #C22);
- static field foo::Bar constBar = #C26;
- static field foo::Baz newBaz = foo::Baz::•($creationLocationd_0dea112b090073317d4: #C28);
- static field foo::Boz newBoz = foo::Boz::•(createNew: true, $creationLocationd_0dea112b090073317d4: #C29);
- static field foo::Boz constBoz = foo::Boz::•(createNew: false, $creationLocationd_0dea112b090073317d4: #C32);
+ static field foo::Foo newFoo = foo::Foo::•($creationLocationd_0dea112b090073317d4: #C38);
+ static field foo::Bar newBar = new foo::Bar::_($creationLocationd_0dea112b090073317d4: #C39);
+ static field foo::Bar constBar = #C42;
+ static field foo::Baz newBaz = foo::Baz::•($creationLocationd_0dea112b090073317d4: #C43);
+ static field foo::Boz newBoz = foo::Boz::•(createNew: true, $creationLocationd_0dea112b090073317d4: #C44);
+ static field foo::Boz constBoz = foo::Boz::•(createNew: false, $creationLocationd_0dea112b090073317d4: #C46);
}
constants {
#C1 = null
@@ -95,29 +115,43 @@
#C5 = "Foo"
#C6 = wid::_Location {file:#C2, line:#C3, column:#C4, name:#C5, parameterLocations:#C1}
#C7 = foo::Foo {_location:#C6}
- #C8 = 6.0
- #C9 = "Baz"
- #C10 = wid::_Location {file:#C2, line:#C8, column:#C4, name:#C9, parameterLocations:#C1}
- #C11 = foo::Baz {_location:#C10}
- #C12 = 9.0
- #C13 = 128.0
- #C14 = "Boz"
- #C15 = wid::_Location {file:#C2, line:#C12, column:#C13, name:#C14, parameterLocations:#C1}
- #C16 = foo::Boz {_location:#C15}
- #C17 = "org-dartlang-test:///main.dart"
- #C18 = 18.0
- #C19 = wid::_Location {file:#C17, line:#C3, column:#C18, name:#C5, parameterLocations:#C1}
- #C20 = 3.0
- #C21 = "Bar"
- #C22 = wid::_Location {file:#C17, line:#C20, column:#C18, name:#C21, parameterLocations:#C1}
- #C23 = 4.0
- #C24 = 22.0
- #C25 = wid::_Location {file:#C17, line:#C23, column:#C24, name:#C21, parameterLocations:#C1}
- #C26 = foo::Bar {_location:#C25}
- #C27 = 5.0
- #C28 = wid::_Location {file:#C17, line:#C27, column:#C18, name:#C9, parameterLocations:#C1}
- #C29 = wid::_Location {file:#C17, line:#C8, column:#C18, name:#C14, parameterLocations:#C1}
- #C30 = 7.0
- #C31 = 20.0
- #C32 = wid::_Location {file:#C17, line:#C30, column:#C31, name:#C14, parameterLocations:#C1}
+ #C8 = 36.0
+ #C9 = wid::_Location {file:#C2, line:#C3, column:#C8, name:#C5, parameterLocations:#C1}
+ #C10 = 3.0
+ #C11 = 7.0
+ #C12 = wid::_Location {file:#C2, line:#C10, column:#C11, name:#C5, parameterLocations:#C1}
+ #C13 = 4.0
+ #C14 = 42.0
+ #C15 = "Bar"
+ #C16 = wid::_Location {file:#C2, line:#C13, column:#C14, name:#C15, parameterLocations:#C1}
+ #C17 = 5.0
+ #C18 = wid::_Location {file:#C2, line:#C17, column:#C11, name:#C15, parameterLocations:#C1}
+ #C19 = 6.0
+ #C20 = "Baz"
+ #C21 = wid::_Location {file:#C2, line:#C19, column:#C4, name:#C20, parameterLocations:#C1}
+ #C22 = foo::Baz {_location:#C21}
+ #C23 = wid::_Location {file:#C2, line:#C19, column:#C8, name:#C20, parameterLocations:#C1}
+ #C24 = 15.0
+ #C25 = wid::_Location {file:#C2, line:#C11, column:#C24, name:#C20, parameterLocations:#C1}
+ #C26 = 8.0
+ #C27 = wid::_Location {file:#C2, line:#C26, column:#C11, name:#C20, parameterLocations:#C1}
+ #C28 = 9.0
+ #C29 = 128.0
+ #C30 = "Boz"
+ #C31 = wid::_Location {file:#C2, line:#C28, column:#C29, name:#C30, parameterLocations:#C1}
+ #C32 = foo::Boz {_location:#C31}
+ #C33 = wid::_Location {file:#C2, line:#C28, column:#C8, name:#C30, parameterLocations:#C1}
+ #C34 = 10.0
+ #C35 = wid::_Location {file:#C2, line:#C34, column:#C11, name:#C30, parameterLocations:#C1}
+ #C36 = "org-dartlang-test:///main.dart"
+ #C37 = 18.0
+ #C38 = wid::_Location {file:#C36, line:#C3, column:#C37, name:#C5, parameterLocations:#C1}
+ #C39 = wid::_Location {file:#C36, line:#C10, column:#C37, name:#C15, parameterLocations:#C1}
+ #C40 = 22.0
+ #C41 = wid::_Location {file:#C36, line:#C13, column:#C40, name:#C15, parameterLocations:#C1}
+ #C42 = foo::Bar {_location:#C41}
+ #C43 = wid::_Location {file:#C36, line:#C17, column:#C37, name:#C20, parameterLocations:#C1}
+ #C44 = wid::_Location {file:#C36, line:#C19, column:#C37, name:#C30, parameterLocations:#C1}
+ #C45 = 20.0
+ #C46 = wid::_Location {file:#C36, line:#C11, column:#C45, name:#C30, parameterLocations:#C1}
}
diff --git a/pkg/front_end/testcases/incremental/flutter_widget_transform_nnbd.yaml.world.1.expect b/pkg/front_end/testcases/incremental/flutter_widget_transform_nnbd.yaml.world.1.expect
index bf659ac..f4d0275 100644
--- a/pkg/front_end/testcases/incremental/flutter_widget_transform_nnbd.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/flutter_widget_transform_nnbd.yaml.world.1.expect
@@ -30,6 +30,8 @@
const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
;
+ static method _#new#tearOff({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
+ return new wid::_Location::•(file: file, line: line, column: column, name: name, parameterLocations: parameterLocations);
}
}
library from "org-dartlang-test:///foo.dart" as foo {
@@ -41,6 +43,8 @@
const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
: super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
;
+ static method _#new#tearOff() → foo::Foo
+ return new foo::Foo::•($creationLocationd_0dea112b090073317d4: #C6);
}
}
library from "org-dartlang-test:///main.dart" as main {
@@ -50,4 +54,9 @@
}
constants {
#C1 = null
+ #C2 = "org-dartlang-test:///foo.dart"
+ #C3 = 2.0
+ #C4 = 34.0
+ #C5 = "Foo"
+ #C6 = wid::_Location {file:#C2, line:#C3, column:#C4, name:#C5, parameterLocations:#C1}
}
diff --git a/pkg/front_end/testcases/incremental/flutter_widget_transform_nnbd.yaml.world.2.expect b/pkg/front_end/testcases/incremental/flutter_widget_transform_nnbd.yaml.world.2.expect
index 178186e..3fdfb87 100644
--- a/pkg/front_end/testcases/incremental/flutter_widget_transform_nnbd.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/flutter_widget_transform_nnbd.yaml.world.2.expect
@@ -30,6 +30,8 @@
const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
;
+ static method _#new#tearOff({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
+ return new wid::_Location::•(file: file, line: line, column: column, name: name, parameterLocations: parameterLocations);
}
}
library from "org-dartlang-test:///foo.dart" as foo {
@@ -41,20 +43,26 @@
const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
: super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
;
+ static method _#new#tearOff() → foo::Foo
+ return new foo::Foo::•($creationLocationd_0dea112b090073317d4: #C6);
}
}
library from "org-dartlang-test:///main.dart" as main {
import "org-dartlang-test:///foo.dart";
- static field foo::Foo foo = #C7;
+ static field foo::Foo foo = #C11;
}
constants {
#C1 = null
- #C2 = "org-dartlang-test:///main.dart"
- #C3 = 3.0
- #C4 = 17.0
+ #C2 = "org-dartlang-test:///foo.dart"
+ #C3 = 2.0
+ #C4 = 34.0
#C5 = "Foo"
#C6 = wid::_Location {file:#C2, line:#C3, column:#C4, name:#C5, parameterLocations:#C1}
- #C7 = foo::Foo {_location:#C6}
+ #C7 = "org-dartlang-test:///main.dart"
+ #C8 = 3.0
+ #C9 = 17.0
+ #C10 = wid::_Location {file:#C7, line:#C8, column:#C9, name:#C5, parameterLocations:#C1}
+ #C11 = foo::Foo {_location:#C10}
}
diff --git a/pkg/front_end/testcases/incremental/flutter_widget_transformer_43371.yaml.world.1.expect b/pkg/front_end/testcases/incremental/flutter_widget_transformer_43371.yaml.world.1.expect
index 2c443b6..6704d7b 100644
--- a/pkg/front_end/testcases/incremental/flutter_widget_transformer_43371.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/flutter_widget_transformer_43371.yaml.world.1.expect
@@ -36,6 +36,8 @@
const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
;
+ static method _#new#tearOff({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
+ return new wid::_Location::•(file: file, line: line, column: column, name: name, parameterLocations: parameterLocations);
}
}
library from "org-dartlang-test:///foo.dart" as foo {
@@ -47,6 +49,8 @@
const constructor •([dart.core::Object* key = #C1]) → foo::Foo*
: super fra::StatelessWidget::•(key: key)
;
+ static method _#new#tearOff([dart.core::Object* key = #C1]) → foo::Foo*
+ return new foo::Foo::•(key);
abstract member-signature get key() → dart.core::Object*; -> fra::Widget::key
abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
diff --git a/pkg/front_end/testcases/incremental/flutter_widget_transformer_43371.yaml.world.2.expect b/pkg/front_end/testcases/incremental/flutter_widget_transformer_43371.yaml.world.2.expect
index a13a232..64a1fbd 100644
--- a/pkg/front_end/testcases/incremental/flutter_widget_transformer_43371.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/flutter_widget_transformer_43371.yaml.world.2.expect
@@ -36,6 +36,8 @@
const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
;
+ static method _#new#tearOff({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
+ return new wid::_Location::•(file: file, line: line, column: column, name: name, parameterLocations: parameterLocations);
}
}
library from "org-dartlang-test:///foo.dart" as foo {
@@ -47,6 +49,8 @@
const constructor •([dart.core::Object* key = #C1]) → foo::Foo*
: super fra::StatelessWidget::•(key: key)
;
+ static method _#new#tearOff([dart.core::Object* key = #C1]) → foo::Foo*
+ return new foo::Foo::•(key);
abstract member-signature get key() → dart.core::Object*; -> fra::Widget::key
abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
diff --git a/pkg/front_end/testcases/incremental/flutter_widget_transformer_non_const.yaml.world.1.expect b/pkg/front_end/testcases/incremental/flutter_widget_transformer_non_const.yaml.world.1.expect
index 67d2066..a6fb1d9 100644
--- a/pkg/front_end/testcases/incremental/flutter_widget_transformer_non_const.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/flutter_widget_transformer_non_const.yaml.world.1.expect
@@ -30,6 +30,8 @@
const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
;
+ static method _#new#tearOff({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
+ return new wid::_Location::•(file: file, line: line, column: column, name: name, parameterLocations: parameterLocations);
}
}
library from "org-dartlang-test:///foo.dart" as foo {
@@ -42,6 +44,8 @@
constructor •({required dart.core::String name = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
: foo::Foo::name = name, super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
;
+ static method _#new#tearOff({required dart.core::String name = #C1}) → foo::Foo
+ return new foo::Foo::•(name: name, $creationLocationd_0dea112b090073317d4: #C6);
}
}
library from "org-dartlang-test:///main.dart" as main {
@@ -51,4 +55,9 @@
}
constants {
#C1 = null
+ #C2 = "org-dartlang-test:///foo.dart"
+ #C3 = 3.0
+ #C4 = 1.0
+ #C5 = "Foo"
+ #C6 = wid::_Location {file:#C2, line:#C3, column:#C4, name:#C5, parameterLocations:#C1}
}
diff --git a/pkg/front_end/testcases/incremental/flutter_widget_transformer_non_const.yaml.world.2.expect b/pkg/front_end/testcases/incremental/flutter_widget_transformer_non_const.yaml.world.2.expect
index 8d1b8cf..e6b030d 100644
--- a/pkg/front_end/testcases/incremental/flutter_widget_transformer_non_const.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/flutter_widget_transformer_non_const.yaml.world.2.expect
@@ -30,6 +30,8 @@
const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
;
+ static method _#new#tearOff({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
+ return new wid::_Location::•(file: file, line: line, column: column, name: name, parameterLocations: parameterLocations);
}
}
library from "org-dartlang-test:///foo.dart" as foo {
@@ -42,19 +44,25 @@
constructor •({required dart.core::String name = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
: foo::Foo::name = name, super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
;
+ static method _#new#tearOff({required dart.core::String name = #C1}) → foo::Foo
+ return new foo::Foo::•(name: name, $creationLocationd_0dea112b090073317d4: #C6);
}
}
library from "org-dartlang-test:///main.dart" as main {
import "org-dartlang-test:///foo.dart";
- static field foo::Foo foo = new foo::Foo::•(name: "foo", $creationLocationd_0dea112b090073317d4: #C6);
+ static field foo::Foo foo = new foo::Foo::•(name: "foo", $creationLocationd_0dea112b090073317d4: #C10);
}
constants {
#C1 = null
- #C2 = "org-dartlang-test:///main.dart"
- #C3 = 2.0
- #C4 = 15.0
+ #C2 = "org-dartlang-test:///foo.dart"
+ #C3 = 3.0
+ #C4 = 1.0
#C5 = "Foo"
#C6 = wid::_Location {file:#C2, line:#C3, column:#C4, name:#C5, parameterLocations:#C1}
+ #C7 = "org-dartlang-test:///main.dart"
+ #C8 = 2.0
+ #C9 = 15.0
+ #C10 = wid::_Location {file:#C7, line:#C8, column:#C9, name:#C5, parameterLocations:#C1}
}
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_44_flutter.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_44_flutter.yaml.world.1.expect
index 394b66f..b92e29e 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_44_flutter.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_44_flutter.yaml.world.1.expect
@@ -21,6 +21,8 @@
synthetic constructor •() → wid::_Location
: super dart.core::Object::•()
;
+ static method _#new#tearOff() → wid::_Location
+ return new wid::_Location::•();
}
}
library from "org-dartlang-test:///flutter_gallery/lib/main.dart" as main {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_44_flutter.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_44_flutter.yaml.world.2.expect
index 394b66f..b92e29e 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_44_flutter.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_44_flutter.yaml.world.2.expect
@@ -21,6 +21,8 @@
synthetic constructor •() → wid::_Location
: super dart.core::Object::•()
;
+ static method _#new#tearOff() → wid::_Location
+ return new wid::_Location::•();
}
}
library from "org-dartlang-test:///flutter_gallery/lib/main.dart" as main {
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index f900fc0..5dfb8b8 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -21,6 +21,7 @@
#include "vm/message_handler.h"
#include "vm/message_snapshot.h"
#include "vm/object.h"
+#include "vm/object_graph_copy.h"
#include "vm/object_store.h"
#include "vm/port.h"
#include "vm/resolver.h"
@@ -319,6 +320,7 @@
Dart_Port origin_id,
const char* script_url,
const Function& func,
+ PersistentHandle* closure_tuple_handle,
SerializedObjectBuffer* message_buffer,
const char* package_config,
bool paused,
@@ -353,10 +355,16 @@
const char* class_name() const { return class_name_; }
const char* function_name() const { return function_name_; }
const char* debug_name() const { return debug_name_; }
- bool is_spawn_uri() const { return library_url_ == nullptr; }
+ bool is_spawn_uri() const {
+ return library_url_ == nullptr && // No top-level entrypoint.
+ closure_tuple_handle_ == nullptr; // No closure entrypoint.
+ }
bool paused() const { return paused_; }
bool errors_are_fatal() const { return errors_are_fatal_; }
Dart_IsolateFlags* isolate_flags() { return &isolate_flags_; }
+ PersistentHandle* closure_tuple_handle() const {
+ return closure_tuple_handle_;
+ }
ObjectPtr ResolveFunction();
ObjectPtr BuildArgs(Thread* thread);
@@ -376,6 +384,7 @@
const char* class_name_ = nullptr;
const char* function_name_ = nullptr;
const char* debug_name_;
+ PersistentHandle* closure_tuple_handle_ = nullptr;
IsolateGroup* isolate_group_;
std::unique_ptr<Message> serialized_args_;
std::unique_ptr<Message> serialized_message_;
@@ -396,6 +405,7 @@
Dart_Port origin_id,
const char* script_url,
const Function& func,
+ PersistentHandle* closure_tuple_handle,
SerializedObjectBuffer* message_buffer,
const char* package_config,
bool paused,
@@ -411,25 +421,34 @@
script_url_(script_url),
package_config_(package_config),
debug_name_(debug_name),
+ closure_tuple_handle_(closure_tuple_handle),
isolate_group_(isolate_group),
serialized_args_(nullptr),
serialized_message_(message_buffer->StealMessage()),
paused_(paused),
errors_are_fatal_(errors_are_fatal) {
+ // Either we have a top-level function or we have a closure.
+ ASSERT((closure_tuple_handle_ != nullptr) == func.IsNull());
+
auto thread = Thread::Current();
auto isolate = thread->isolate();
- auto zone = thread->zone();
- const auto& cls = Class::Handle(zone, func.Owner());
- const auto& lib = Library::Handle(zone, cls.library());
- const auto& lib_url = String::Handle(zone, lib.url());
- library_url_ = NewConstChar(lib_url.ToCString());
- String& func_name = String::Handle(zone);
- func_name = func.name();
- function_name_ = NewConstChar(String::ScrubName(func_name));
- if (!cls.IsTopLevel()) {
- const auto& class_name = String::Handle(zone, cls.Name());
- class_name_ = NewConstChar(class_name.ToCString());
+ if (!func.IsNull()) {
+ auto zone = thread->zone();
+ const auto& cls = Class::Handle(zone, func.Owner());
+ const auto& lib = Library::Handle(zone, cls.library());
+ const auto& lib_url = String::Handle(zone, lib.url());
+ library_url_ = NewConstChar(lib_url.ToCString());
+
+ String& func_name = String::Handle(zone);
+ func_name = func.name();
+ function_name_ = NewConstChar(String::ScrubName(func_name));
+ if (!cls.IsTopLevel()) {
+ const auto& class_name = String::Handle(zone, cls.Name());
+ class_name_ = NewConstChar(class_name.ToCString());
+ }
+ } else {
+ ASSERT(closure_tuple_handle != nullptr);
}
// Inherit flags from spawning isolate.
@@ -446,14 +465,14 @@
Dart_Port on_exit_port,
Dart_Port on_error_port,
const char* debug_name,
- IsolateGroup* group)
+ IsolateGroup* isolate_group)
: parent_port_(parent_port),
on_exit_port_(on_exit_port),
on_error_port_(on_error_port),
script_url_(script_url),
package_config_(package_config),
debug_name_(debug_name),
- isolate_group_(group),
+ isolate_group_(isolate_group),
serialized_args_(args_buffer->StealMessage()),
serialized_message_(message_buffer->StealMessage()),
isolate_flags_(),
@@ -734,20 +753,32 @@
bool EnqueueEntrypointInvocationAndNotifySpawner(Thread* thread) {
auto isolate = thread->isolate();
auto zone = thread->zone();
+ const bool is_spawn_uri = state_->is_spawn_uri();
// Step 1) Resolve the entrypoint function.
- auto& result = Object::Handle(zone, state_->ResolveFunction());
- const bool is_spawn_uri = state_->is_spawn_uri();
- if (result.IsError()) {
- ASSERT(is_spawn_uri);
- ReportError("Failed to resolve entrypoint function.");
- return false;
+ auto& entrypoint_closure = Closure::Handle(zone);
+ if (state_->closure_tuple_handle() != nullptr) {
+ const auto& result = Object::Handle(
+ zone,
+ ReadObjectGraphCopyMessage(thread, state_->closure_tuple_handle()));
+ if (result.IsError()) {
+ ReportError(
+ "Failed to deserialize the passed entrypoint to the new isolate.");
+ return false;
+ }
+ entrypoint_closure = Closure::RawCast(result.ptr());
+ } else {
+ const auto& result = Object::Handle(zone, state_->ResolveFunction());
+ if (result.IsError()) {
+ ASSERT(is_spawn_uri);
+ ReportError("Failed to resolve entrypoint function.");
+ return false;
+ }
+ ASSERT(result.IsFunction());
+ auto& func = Function::Handle(zone, Function::Cast(result).ptr());
+ func = func.ImplicitClosureFunction();
+ entrypoint_closure = func.ImplicitStaticClosure();
}
- ASSERT(result.IsFunction());
- auto& func = Function::Handle(zone, Function::Cast(result).ptr());
- func = func.ImplicitClosureFunction();
- const auto& entrypoint_closure =
- Object::Handle(zone, func.ImplicitStaticClosure());
// Step 2) Enqueue delayed invocation of entrypoint callback.
const auto& args_obj = Object::Handle(zone, state_->BuildArgs(thread));
@@ -776,7 +807,8 @@
const auto& entry_point =
Function::Handle(zone, lib.LookupLocalFunction(entry_name));
ASSERT(entry_point.IsFunction() && !entry_point.IsNull());
- result = DartEntry::InvokeFunction(entry_point, args);
+ const auto& result =
+ Object::Handle(zone, DartEntry::InvokeFunction(entry_point, args));
if (result.IsError()) {
ReportError("Failed to enqueue delayed entrypoint invocation.");
return false;
@@ -858,10 +890,23 @@
return result;
}
+static FunctionPtr GetTopLevelFunction(Zone* zone, const Instance& closure) {
+ if (closure.IsClosure()) {
+ auto& func = Function::Handle(zone);
+ func = Closure::Cast(closure).function();
+ if (func.IsImplicitClosureFunction() && func.is_static()) {
+ ASSERT(Closure::Cast(closure).context() == Context::null());
+ // Get the parent function so that we get the right function name.
+ return func.parent_function();
+ }
+ }
+ return Function::null();
+}
+
DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 10) {
GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(String, script_uri, arguments->NativeArgAt(1));
- GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(2));
+ GET_NON_NULL_NATIVE_ARGUMENT(Closure, closure, arguments->NativeArgAt(2));
GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(3));
GET_NON_NULL_NATIVE_ARGUMENT(Bool, paused, arguments->NativeArgAt(4));
GET_NATIVE_ARGUMENT(Bool, fatalErrors, arguments->NativeArgAt(5));
@@ -870,51 +915,62 @@
GET_NATIVE_ARGUMENT(String, packageConfig, arguments->NativeArgAt(8));
GET_NATIVE_ARGUMENT(String, debugName, arguments->NativeArgAt(9));
- if (closure.IsClosure()) {
- Function& func = Function::Handle();
- func = Closure::Cast(closure).function();
- if (func.IsImplicitClosureFunction() && func.is_static()) {
-#if defined(DEBUG)
- Context& ctx = Context::Handle();
- ctx = Closure::Cast(closure).context();
- ASSERT(ctx.IsNull());
-#endif
- // Get the parent function so that we get the right function name.
- func = func.parent_function();
-
- bool fatal_errors = fatalErrors.IsNull() ? true : fatalErrors.value();
- Dart_Port on_exit_port = onExit.IsNull() ? ILLEGAL_PORT : onExit.Id();
- Dart_Port on_error_port = onError.IsNull() ? ILLEGAL_PORT : onError.Id();
-
- // We first try to serialize the message. In case the message is not
- // serializable this will throw an exception.
- SerializedObjectBuffer message_buffer;
- message_buffer.set_message(WriteMessage(
- /* can_send_any_object */ true,
- /* same_group */ FLAG_enable_isolate_groups, message, ILLEGAL_PORT,
- Message::kNormalPriority));
-
- const char* utf8_package_config =
- packageConfig.IsNull() ? NULL : String2UTF8(packageConfig);
- const char* utf8_debug_name =
- debugName.IsNull() ? NULL : String2UTF8(debugName);
-
- std::unique_ptr<IsolateSpawnState> state(new IsolateSpawnState(
- port.Id(), isolate->origin_id(), String2UTF8(script_uri), func,
- &message_buffer, utf8_package_config, paused.value(), fatal_errors,
- on_exit_port, on_error_port, utf8_debug_name, isolate->group()));
-
- // Since this is a call to Isolate.spawn, copy the parent isolate's code.
- state->isolate_flags()->copy_parent_code = true;
-
- isolate->group()->thread_pool()->Run<SpawnIsolateTask>(isolate,
- std::move(state));
- return Object::null();
+ const auto& func = Function::Handle(zone, GetTopLevelFunction(zone, closure));
+ PersistentHandle* closure_tuple_handle = nullptr;
+ if (func.IsNull()) {
+ if (!FLAG_enable_isolate_groups) {
+ const String& msg = String::Handle(String::New(
+ "Isolate.spawn expects to be passed a static or top-level function"));
+ Exceptions::ThrowArgumentError(msg);
+ } else {
+ // We have a non-toplevel closure that we might need to copy.
+ // Result will be [<closure-copy>, <objects-in-msg-to-rehash>]
+ const auto& closure_copy_tuple = Object::Handle(
+ zone, CopyMutableObjectGraph(closure)); // Throws if it fails.
+ ASSERT(closure_copy_tuple.IsArray());
+ ASSERT(Object::Handle(zone, Array::Cast(closure_copy_tuple).At(0))
+ .IsClosure());
+ closure_tuple_handle =
+ isolate->group()->api_state()->AllocatePersistentHandle();
+ closure_tuple_handle->set_ptr(closure_copy_tuple.ptr());
}
}
- const String& msg = String::Handle(String::New(
- "Isolate.spawn expects to be passed a static or top-level function"));
- Exceptions::ThrowArgumentError(msg);
+
+ bool fatal_errors = fatalErrors.IsNull() ? true : fatalErrors.value();
+ Dart_Port on_exit_port = onExit.IsNull() ? ILLEGAL_PORT : onExit.Id();
+ Dart_Port on_error_port = onError.IsNull() ? ILLEGAL_PORT : onError.Id();
+
+ // We first try to serialize the message. In case the message is not
+ // serializable this will throw an exception.
+ SerializedObjectBuffer message_buffer;
+ message_buffer.set_message(WriteMessage(
+ /* can_send_any_object */ true,
+ /* same_group */ FLAG_enable_isolate_groups, message, ILLEGAL_PORT,
+ Message::kNormalPriority));
+
+ const char* utf8_package_config =
+ packageConfig.IsNull() ? NULL : String2UTF8(packageConfig);
+ const char* utf8_debug_name =
+ debugName.IsNull() ? NULL : String2UTF8(debugName);
+ if (closure_tuple_handle != nullptr && utf8_debug_name == nullptr) {
+ ASSERT(func.IsNull());
+
+ const auto& closure_function = Function::Handle(zone, closure.function());
+ utf8_debug_name =
+ NewConstChar(closure_function.QualifiedUserVisibleNameCString());
+ }
+
+ std::unique_ptr<IsolateSpawnState> state(new IsolateSpawnState(
+ port.Id(), isolate->origin_id(), String2UTF8(script_uri), func,
+ closure_tuple_handle, &message_buffer, utf8_package_config,
+ paused.value(), fatal_errors, on_exit_port, on_error_port,
+ utf8_debug_name, isolate->group()));
+
+ // Since this is a call to Isolate.spawn, copy the parent isolate's code.
+ state->isolate_flags()->copy_parent_code = true;
+
+ isolate->group()->thread_pool()->Run<SpawnIsolateTask>(isolate,
+ std::move(state));
return Object::null();
}
diff --git a/runtime/tests/vm/dart/isolates/closure_entrypoint_test.dart b/runtime/tests/vm/dart/isolates/closure_entrypoint_test.dart
new file mode 100644
index 0000000..b855c4f
--- /dev/null
+++ b/runtime/tests/vm/dart/isolates/closure_entrypoint_test.dart
@@ -0,0 +1,111 @@
+// Copyright (c) 2021, 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.
+
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
+
+// The tests in this file will only succeed when isolate groups are enabled
+// (hence the VMOptions above).
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:expect/expect.dart';
+
+import 'fast_object_copy_test.dart' show ClassWithNativeFields;
+
+class HashThrower {
+ static bool throwOnHashCode = true;
+
+ const HashThrower();
+
+ int get hashCode => throwOnHashCode ? throw 'failing' : 2;
+ bool operator ==(other) => identical(this, other);
+}
+
+Future testWithClosure<T>(
+ void Function(SendPort) entrypoint, T expectedResult) async {
+ final rp = ReceivePort();
+ try {
+ await Isolate.spawn(entrypoint, rp.sendPort);
+ Expect.equals(expectedResult, await rp.first);
+ } finally {
+ rp.close();
+ }
+}
+
+class ClosureEntrypointTester {
+ int instanceValue = 42;
+
+ void send42(SendPort sendPort) => sendPort.send(42);
+
+ Future run() async {
+ await noCapturedVariablesTest();
+ await capturedInt();
+ await capturedInstanceInt();
+ await captureThisViaMethodTearOff();
+ await captureInvalidObject();
+ await captureRehashThrower();
+ }
+
+ Future noCapturedVariablesTest() async {
+ print('noCapturedVariablesTest');
+ await testWithClosure((SendPort s) => s.send(42), 42);
+ }
+
+ Future capturedInt() async {
+ print('capturedInt');
+ int value = 42;
+ await testWithClosure((SendPort s) => s.send(value), 42);
+ }
+
+ Future capturedInstanceInt() async {
+ print('capturedInstanceValue');
+ await testWithClosure((SendPort s) => s.send(this.instanceValue), 42);
+ }
+
+ Future captureThisViaMethodTearOff() async {
+ print('captureThisViaMethodTearOff');
+ await testWithClosure(send42, 42);
+ }
+
+ Future captureInvalidObject() async {
+ print('captureInvalidObject');
+ final invalidObject = ClassWithNativeFields();
+ send42(SendPort sendPort) {
+ '$invalidObject'; // Use an object that cannot be copied.
+ sendPort.send(42);
+ }
+
+ throwsAsync<ArgumentError>(() => testWithClosure(send42, 42));
+ }
+
+ Future captureRehashThrower() async {
+ print('captureRehashThrower');
+ HashThrower.throwOnHashCode = false;
+ final hashThrower = {HashThrower()};
+ send42(SendPort sendPort) {
+ '$hashThrower'; // Use an object that cannot be deserialized.
+ sendPort.send(42);
+ }
+
+ throwsAsync<IsolateSpawnException>(() => testWithClosure(send42, 42));
+ }
+
+ Future throwsAsync<T>(Future Function() fun) async {
+ try {
+ await fun();
+ } catch (e) {
+ if (e is T) return;
+ rethrow;
+ }
+ throw 'Function failed to throw ArgumentError';
+ }
+}
+
+main() async {
+ await ClosureEntrypointTester().run();
+}
diff --git a/runtime/tests/vm/dart_2/isolates/closure_entrypoint_test.dart b/runtime/tests/vm/dart_2/isolates/closure_entrypoint_test.dart
new file mode 100644
index 0000000..4fa05c9
--- /dev/null
+++ b/runtime/tests/vm/dart_2/isolates/closure_entrypoint_test.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2021, 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.
+
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
+
+// The tests in this file will only succeed when isolate groups are enabled
+// (hence the VMOptions above).
+
+// @dart = 2.9
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:expect/expect.dart';
+
+import 'fast_object_copy_test.dart' show ClassWithNativeFields;
+
+class HashThrower {
+ static bool throwOnHashCode = true;
+
+ const HashThrower();
+
+ int get hashCode => throwOnHashCode ? throw 'failing' : 2;
+ bool operator ==(other) => identical(this, other);
+}
+
+Future testWithClosure<T>(
+ void Function(SendPort) entrypoint, T expectedResult) async {
+ final rp = ReceivePort();
+ try {
+ await Isolate.spawn(entrypoint, rp.sendPort);
+ Expect.equals(expectedResult, await rp.first);
+ } finally {
+ rp.close();
+ }
+}
+
+class ClosureEntrypointTester {
+ int instanceValue = 42;
+
+ void send42(SendPort sendPort) => sendPort.send(42);
+
+ Future run() async {
+ await noCapturedVariablesTest();
+ await capturedInt();
+ await capturedInstanceInt();
+ await captureThisViaMethodTearOff();
+ await captureInvalidObject();
+ await captureRehashThrower();
+ }
+
+ Future noCapturedVariablesTest() async {
+ print('noCapturedVariablesTest');
+ await testWithClosure((SendPort s) => s.send(42), 42);
+ }
+
+ Future capturedInt() async {
+ print('capturedInt');
+ int value = 42;
+ await testWithClosure((SendPort s) => s.send(value), 42);
+ }
+
+ Future capturedInstanceInt() async {
+ print('capturedInstanceValue');
+ await testWithClosure((SendPort s) => s.send(this.instanceValue), 42);
+ }
+
+ Future captureThisViaMethodTearOff() async {
+ print('captureThisViaMethodTearOff');
+ await testWithClosure(send42, 42);
+ }
+
+ Future captureInvalidObject() async {
+ print('captureInvalidObject');
+ final invalidObject = ClassWithNativeFields();
+ send42(SendPort sendPort) {
+ '$invalidObject'; // Use an object that cannot be copied.
+ sendPort.send(42);
+ }
+
+ throwsAsync<ArgumentError>(() => testWithClosure(send42, 42));
+ }
+
+ Future captureRehashThrower() async {
+ print('captureRehashThrower');
+ HashThrower.throwOnHashCode = false;
+ final hashThrower = {HashThrower()};
+ send42(SendPort sendPort) {
+ '$hashThrower'; // Use an object that cannot be deserialized.
+ sendPort.send(42);
+ }
+
+ throwsAsync<IsolateSpawnException>(() => testWithClosure(send42, 42));
+ }
+
+ Future throwsAsync<T>(Future Function() fun) async {
+ try {
+ await fun();
+ } catch (e) {
+ if (e is T) return;
+ rethrow;
+ }
+ throw 'Function failed to throw ArgumentError';
+ }
+}
+
+main() async {
+ await ClosureEntrypointTester().run();
+}
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index aadc7a4..46cf7f1 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -2681,12 +2681,6 @@
visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&ic_miss_code_));
visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&tag_table_));
visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&sticky_error_));
- if (isolate_group_ != nullptr) {
- if (isolate_group_->source()->loaded_blobs_ != nullptr) {
- visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(
- &(isolate_group_->source()->loaded_blobs_)));
- }
- }
#if !defined(PRODUCT)
visitor->VisitPointer(
reinterpret_cast<ObjectPtr*>(&pending_service_extension_calls_));
@@ -2889,6 +2883,11 @@
visitor);
}
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+
+ if (source()->loaded_blobs_ != nullptr) {
+ visitor->VisitPointer(
+ reinterpret_cast<ObjectPtr*>(&(source()->loaded_blobs_)));
+ }
}
void IsolateGroup::VisitStackPointers(ObjectPointerVisitor* visitor,
diff --git a/runtime/vm/message_snapshot.cc b/runtime/vm/message_snapshot.cc
index 076f612..b2ff598 100644
--- a/runtime/vm/message_snapshot.cc
+++ b/runtime/vm/message_snapshot.cc
@@ -3722,40 +3722,43 @@
return serializer.Finish(dest_port, priority);
}
+ObjectPtr ReadObjectGraphCopyMessage(Thread* thread, PersistentHandle* handle) {
+ // msg_array = [
+ // <message>,
+ // <collection-lib-objects-to-rehash>,
+ // <core-lib-objects-to-rehash>,
+ // ]
+ Zone* zone = thread->zone();
+ Object& msg_obj = Object::Handle(zone);
+ const auto& msg_array = Array::Handle(zone, Array::RawCast(handle->ptr()));
+ ASSERT(msg_array.Length() == 3);
+ msg_obj = msg_array.At(0);
+ if (msg_array.At(1) != Object::null()) {
+ const auto& objects_to_rehash = Object::Handle(zone, msg_array.At(1));
+ auto& result = Object::Handle(zone);
+ result = DartLibraryCalls::RehashObjectsInDartCollection(thread,
+ objects_to_rehash);
+ if (result.ptr() != Object::null()) {
+ msg_obj = result.ptr();
+ }
+ }
+ if (msg_array.At(2) != Object::null()) {
+ const auto& objects_to_rehash = Object::Handle(zone, msg_array.At(2));
+ auto& result = Object::Handle(zone);
+ result =
+ DartLibraryCalls::RehashObjectsInDartCore(thread, objects_to_rehash);
+ if (result.ptr() != Object::null()) {
+ msg_obj = result.ptr();
+ }
+ }
+ return msg_obj.ptr();
+}
+
ObjectPtr ReadMessage(Thread* thread, Message* message) {
if (message->IsRaw()) {
return message->raw_obj();
} else if (message->IsPersistentHandle()) {
- // msg_array = [
- // <message>,
- // <collection-lib-objects-to-rehash>,
- // <core-lib-objects-to-rehash>,
- // ]
- Zone* zone = thread->zone();
- Object& msg_obj = Object::Handle(zone);
- const auto& msg_array = Array::Handle(
- zone, Array::RawCast(message->persistent_handle()->ptr()));
- ASSERT(msg_array.Length() == 3);
- msg_obj = msg_array.At(0);
- if (msg_array.At(1) != Object::null()) {
- const auto& objects_to_rehash = Object::Handle(zone, msg_array.At(1));
- auto& result = Object::Handle(zone);
- result = DartLibraryCalls::RehashObjectsInDartCollection(
- thread, objects_to_rehash);
- if (result.ptr() != Object::null()) {
- msg_obj = result.ptr();
- }
- }
- if (msg_array.At(2) != Object::null()) {
- const auto& objects_to_rehash = Object::Handle(zone, msg_array.At(2));
- auto& result = Object::Handle(zone);
- result =
- DartLibraryCalls::RehashObjectsInDartCore(thread, objects_to_rehash);
- if (result.ptr() != Object::null()) {
- msg_obj = result.ptr();
- }
- }
- return msg_obj.ptr();
+ return ReadObjectGraphCopyMessage(thread, message->persistent_handle());
} else {
RELEASE_ASSERT(message->IsSnapshot());
MessageDeserializer deserializer(thread, message);
diff --git a/runtime/vm/message_snapshot.h b/runtime/vm/message_snapshot.h
index be7eb8a..a584748 100644
--- a/runtime/vm/message_snapshot.h
+++ b/runtime/vm/message_snapshot.h
@@ -24,6 +24,8 @@
Dart_Port dest_port,
Message::Priority priority);
+ObjectPtr ReadObjectGraphCopyMessage(Thread* thread, PersistentHandle* handle);
+
ObjectPtr ReadMessage(Thread* thread, Message* message);
Dart_CObject* ReadApiMessage(Zone* zone, Message* message);
diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc
index 52c680f..f5d8bc5 100644
--- a/runtime/vm/object_graph_copy.cc
+++ b/runtime/vm/object_graph_copy.cc
@@ -1710,7 +1710,12 @@
thread_->isolate()->set_forward_table_old(nullptr);
}
- // Result will be [<msg>, <objects-in-msg-to-rehash>]
+ // Result will be
+ // [
+ // <message>,
+ // <collection-lib-objects-to-rehash>,
+ // <core-lib-objects-to-rehash>,
+ // ]
ObjectPtr CopyObjectGraph(const Object& root) {
const char* volatile exception_msg = nullptr;
auto& result = Object::Handle(zone_);
diff --git a/runtime/vm/object_graph_copy.h b/runtime/vm/object_graph_copy.h
index b33c3e4..e7efa5a 100644
--- a/runtime/vm/object_graph_copy.h
+++ b/runtime/vm/object_graph_copy.h
@@ -13,9 +13,13 @@
// Makes a transitive copy of the object graph referenced by [object]. Will not
// copy objects that can be safely shared - due to being immutable.
//
-// The result will be an array of length 2 of the format
+// The result will be an array of length 3 of the format
//
-// [<copy-of-root>, <array-of-objects-to-rehash / null>]
+// [
+// <message>,
+// <collection-lib-objects-to-rehash>,
+// <core-lib-objects-to-rehash>,
+// ]
//
// If the array of objects to rehash is not `null` the receiver should re-hash
// those objects.
diff --git a/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart b/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
index fdc771d..01921c0 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
@@ -178,18 +178,68 @@
dart.typeName(dart.getReifiedType(this)), this);
}
- // TODO(jmesserly): remove these once we canonicalize tearoffs.
+ // TODO(nshahan): We can remove these if we canonicalize all tearoffs and no
+ // longer support weak null safety "same type" equality.
operator ==(other) {
- if (other == null) return false;
- var boundObj = JS<Object?>('', '#._boundObject', this);
- if (boundObj == null) return JS<bool>('!', '# === #', this, other);
- return JS(
- 'bool',
+ // Basic function values (no generics, no bound instances) are represented
+ // as the original functions so reference equality is sufficient.
+ if (JS<bool>('!', '# === #', this, other)) return true;
+
+ dynamic boundObj;
+ dynamic otherFn;
+ var originalFn = JS('', '#._originalFn', this);
+
+ if (originalFn == null) {
+ // No generic instantiation present.
+ boundObj = JS('', '#._boundObject', this);
+ if (boundObj == null) return false;
+ originalFn = this;
+ otherFn = other;
+ } else {
+ // Generic instantiation was present.
+ var typeArgs = JS('!', '#._typeArgs', this);
+ var otherTypeArgs = JS('', '#._typeArgs', other);
+ // Test if all instantiated type arguments are equal.
+ if (dart.compileTimeFlag('soundNullSafety')) {
+ // The list has been canonicalized on creation so reference equality
+ // is sufficient.
+ if (JS<bool>('!', '# !== #', typeArgs, otherTypeArgs)) return false;
+ } else {
+ // In weak null safety all types arguments must be compared in a way
+ // that is agnostic to legacy.
+ var typeArgCount = JS<int>('!', '#.length', typeArgs);
+ if (JS<bool>('!', '!#', otherTypeArgs) ||
+ typeArgCount != JS('', '#.length', otherTypeArgs)) {
+ return false;
+ }
+ for (var i = 0; i < typeArgCount; i++) {
+ var typeArg = JS('!', '#[#]', typeArgs, i);
+ var otherTypeArg = JS('!', '#[#]', otherTypeArgs, i);
+ // TODO(nshahan) Replace wrapType() with a lighter weight legacy
+ // erasure.
+ if (JS<bool>('!', '# !== #', dart.wrapType(typeArg),
+ dart.wrapType(otherTypeArg))) {
+ return false;
+ }
+ }
+ }
+ boundObj = JS('', '#._boundObject', originalFn);
+ otherFn = JS('', '#._originalFn', other);
+ if (boundObj == null) {
+ // This isn't an instance tearoff, test if the original uninstantiated
+ // methods are equal.
+ return JS<bool>('!', '# === #', originalFn, otherFn);
+ }
+ }
+ // This is an instance tearoff, test if the bound instances and methods
+ // are equal.
+ return JS<bool>(
+ '!',
'# === #._boundObject && #._boundMethod === #._boundMethod',
boundObj,
- other,
- this,
- other);
+ otherFn,
+ originalFn,
+ otherFn);
}
get hashCode {
diff --git a/tools/VERSION b/tools/VERSION
index b52e166..4a2ce87 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 79
+PRERELEASE 80
PRERELEASE_PATCH 0
\ No newline at end of file