From ae33e9c12c4ec4eb546230f4ebeaf72b825c2dce Mon Sep 17 00:00:00 2001 From: Martin Kustermann Date: Wed, 29 Apr 2026 02:26:33 -0700 Subject: [PATCH] [dart2wasm] Filter out user-provided program constraints When users provide program constraints, some of the library import prefixes will be unreachable. Though the core partitioning algorithm in dart2wasm will only work on imports sets of alive / reachable prefixes. => Make us filter out unreachable library prefixes before processing user-provided program constraints. => Add a check that those we filter out are still valid library prefixes from the Kernel AST. Change-Id: Id55064ee03e682a04d5e9117e466ac9573e66a39 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/498901 Reviewed-by: Nate Biggs Commit-Queue: Martin Kustermann --- pkg/dart2wasm/analysis_options.yaml | 1 + .../lib/deferred_load/partition.dart | 99 ++++++++++++++++- .../test/deferred_loading/partition_test.dart | 29 ++++- .../dead_constraint.constraints.json | 90 ++++++++++++++++ .../dead_constraint.constraints.txt | 75 +++++++++++++ .../partition_tests/dead_constraint.dart | 102 ++++++++++++++++++ .../dead_constraint.default.txt | 74 +++++++++++++ 7 files changed, 463 insertions(+), 7 deletions(-) create mode 100644 pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.constraints.json create mode 100644 pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.constraints.txt create mode 100644 pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart create mode 100644 pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.default.txt diff --git a/pkg/dart2wasm/analysis_options.yaml b/pkg/dart2wasm/analysis_options.yaml index c54ed7392f1..bb01371e023 100644 --- a/pkg/dart2wasm/analysis_options.yaml +++ b/pkg/dart2wasm/analysis_options.yaml @@ -10,6 +10,7 @@ analyzer: exclude: - test/ir_tests/*.dart + - test/deferred_loading/partition_tests/*.dart linter: rules: diff --git a/pkg/dart2wasm/lib/deferred_load/partition.dart b/pkg/dart2wasm/lib/deferred_load/partition.dart index ee79fa53231..181d17accd5 100644 --- a/pkg/dart2wasm/lib/deferred_load/partition.dart +++ b/pkg/dart2wasm/lib/deferred_load/partition.dart @@ -255,17 +255,22 @@ class _Algorithm { final namedNodes = ProgramSplitBuilder(); final orderNodes = []; + final filteredUserConstraints = _filterUserConstraints( + userConstraints, + allDeferredImportsIncludingRoot, + ); + // If user provided constraints, initialize from them. final existingNames = {}; - if (userConstraints != null) { - for (final named in userConstraints!.named) { + if (filteredUserConstraints != null) { + for (final named in filteredUserConstraints.named) { if (named is ReferenceNode) { final import = UriAndPrefix(named.uri, named.prefix).toString(); existingNames[import] = named; } namedNodes.namedNodes[named.name] = named; } - for (final ordered in userConstraints!.ordered) { + for (final ordered in filteredUserConstraints.ordered) { orderNodes.add(ordered); } } @@ -298,6 +303,94 @@ class _Algorithm { ).build(allDeferredImportsIncludingRoot); } + ConstraintData? _filterUserConstraints( + ConstraintData? userConstraints, + Set allDeferredImportsIncludingRoot, + ) { + if (userConstraints == null) return null; + + /// The set of all prefixes (even unreachable ones). + final allPrefixNames = { + for (final library in component.libraries) + for (final import in library.dependencies) + if (import.isDeferred) import.uriPrefix, + }; + + /// The set of reachable prefixes. + final validImportPrefixes = allDeferredImportsIncludingRoot + .map((d) => d.uriPrefix) + .toSet(); + + final newNamedNodes = {}; + + // Find [ReferenceNode]s that exist. + for (final NamedNode node in userConstraints.named) { + if (node is ReferenceNode) { + final importPrefix = UriAndPrefix(node.uri, node.prefix).toString(); + if (validImportPrefixes.contains(importPrefix)) { + newNamedNodes[node] = node; + continue; + } + if (!allPrefixNames.contains(importPrefix)) { + throw StateError('The library $importPrefix is not known.'); + } + // The [importPrefix] is in the Kernel AST but unreachable. This can + // happen due to RTA+TFA leaving unreachable code behind. We therefore + // prune this node and simplify or remove depending constraint nodes + // below. + } + } + + // Prune or remove [CombinerNode]s. + for (final NamedNode node in userConstraints.named) { + if (node is CombinerNode) { + final Set remaining = node.nodes + .where(newNamedNodes.containsKey) + .toSet(); + if (remaining.isEmpty) continue; + if (node.type == CombinerType.and && + remaining.length < node.nodes.length) { + continue; + } + if (remaining.length == 1) { + newNamedNodes[node] = remaining.first; + } else { + newNamedNodes[node] = CombinerNode(node.name, node.type, remaining); + } + } + } + + // Filter/prune [OrderNode]s. + final newOrderNodes = []; + for (final node in userConstraints.ordered) { + if (node is RelativeOrderNode) { + final predecessor = newNamedNodes[node.predecessor]; + final successor = newNamedNodes[node.successor]; + if (predecessor != null && successor != null) { + newOrderNodes.add( + RelativeOrderNode(predecessor: predecessor, successor: successor), + ); + } + continue; + } + if (node is FuseNode) { + final newNodes = {}; + for (final node in node.nodes) { + final newNode = newNamedNodes[node]; + if (newNode == null) continue; + newNodes.add(newNode); + } + if (newNodes.length >= 2) { + newOrderNodes.add(FuseNode(newNodes)); + } + continue; + } + throw StateError('Unknown order node $node.'); + } + + return ConstraintData(newNamedNodes.values.toList(), newOrderNodes); + } + void collectDependencies(Set roots) { for (final reference in roots) { ensureReferenceDependencies(reference); diff --git a/pkg/dart2wasm/test/deferred_loading/partition_test.dart b/pkg/dart2wasm/test/deferred_loading/partition_test.dart index 7080f8f879f..89fa1bc202c 100644 --- a/pkg/dart2wasm/test/deferred_loading/partition_test.dart +++ b/pkg/dart2wasm/test/deferred_loading/partition_test.dart @@ -38,15 +38,36 @@ Future runDart2wasmTests() async { .toList(); for (final mainFile in tests) { final mainFilePath = mainFile.path; - final defaultSplitExpectationFile = - '${mainFilePath.substring(0, mainFilePath.length - '.dart'.length)}.default.txt'; + final mainFileBasePath = mainFilePath.substring( + 0, + mainFilePath.length - '.dart'.length, + ); - // Test without constraints. + // Generate a partitioning without constraints under + // `.default.txt`. await testPartitionExpectation( mainFilePath, null, - defaultSplitExpectationFile, + '$mainFileBasePath.default.txt', ); + + // If the `.constraints.json` exists generate a partitioining with + // constraints under `.constraints.txt`. + final jsonConstraintsFile = File('$mainFileBasePath.constraints.json'); + if (jsonConstraintsFile.existsSync()) { + final constraintsJsonString = jsonConstraintsFile + .readAsStringSync() + .replaceAll( + '\${SDK_ROOT}', + Directory.current.absolute.uri.toString(), + ); + final constraints = Parser().read(constraintsJsonString); + await testPartitionExpectation( + mainFilePath, + constraints, + '$mainFileBasePath.constraints.txt', + ); + } } } diff --git a/pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.constraints.json b/pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.constraints.json new file mode 100644 index 00000000000..826d81067eb --- /dev/null +++ b/pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.constraints.json @@ -0,0 +1,90 @@ +[ + { + "type": "reference", + "name": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#OrAlive", + "import": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#OrAlive" + }, + { + "type": "reference", + "name": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#OrAlive_1", + "import": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#OrAlive_1" + }, + { + "type": "reference", + "name": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#OrAlive_2", + "import": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#OrAlive_2" + }, + { + "type": "reference", + "name": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#OrDead", + "import": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#OrDead" + }, + { + "type": "reference", + "name": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#AndAlive", + "import": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#AndAlive" + }, + { + "type": "reference", + "name": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#AndAlive_1", + "import": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#AndAlive_1" + }, + { + "type": "reference", + "name": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#AndAlive_2", + "import": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#AndAlive_2" + }, + { + "type": "reference", + "name": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#AndDead", + "import": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#AndDead" + }, + { + "type": "reference", + "name": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#FuseAlive", + "import": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#FuseAlive" + }, + { + "type": "reference", + "name": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#FuseAlive_1", + "import": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#FuseAlive_1" + }, + { + "type": "reference", + "name": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#FuseAlive_2", + "import": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#FuseAlive_2" + }, + { + "type": "reference", + "name": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#FuseDead", + "import": "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#FuseDead" + }, + { + "type": "or", + "name": "or_with_dead", + "nodes": [ + "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#OrAlive_1", + "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#OrAlive_2", + "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#OrDead" + ] + }, + { + "type": "and", + "name": "and_with_dead", + "nodes": [ + "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#AndAlive_1", + "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#AndAlive_2", + "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#AndDead" + ] + }, + { + "type": "fuse", + "nodes": [ + "or_with_dead", + "and_with_dead", + "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#FuseAlive_1", + "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#FuseAlive_2", + "${SDK_ROOT}pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart#FuseDead" + ] + } +] diff --git a/pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.constraints.txt b/pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.constraints.txt new file mode 100644 index 00000000000..805d7277b5e --- /dev/null +++ b/pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.constraints.txt @@ -0,0 +1,75 @@ +Part 0 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: FuseAlive_1 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: FuseAlive_2 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive_1 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive_2 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::testOr + Constants + +Part 1 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: AndAlive + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: AndAlive_1 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: AndAlive_2 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::testAnd + Constants + +Part 2 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: FuseAlive + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: FuseAlive_1 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: FuseAlive_2 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive_1 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive_2 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::testFuse + Constants + +Part 3 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive_1 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::orTest_alive_1 + Constants + - StringConstant("orTest_alive_1") + +Part 4 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive_2 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::orTest_alive_2 + Constants + - StringConstant("orTest_alive_2") + +Part 5 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: AndAlive_1 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::andTest_alive_1 + Constants + - StringConstant("andTest_alive_1") + +Part 6 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: AndAlive_2 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::andTest_alive_2 + Constants + - StringConstant("andTest_alive_2") + +Part 7 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: FuseAlive_1 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: FuseAlive_2 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive_1 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive_2 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::fuseTest_alive_1 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::fuseTest_alive_2 + Constants + - StringConstant("fuseTest_alive_1") + - StringConstant("fuseTest_alive_2") diff --git a/pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart b/pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart new file mode 100644 index 00000000000..5948d9f68c4 --- /dev/null +++ b/pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart @@ -0,0 +1,102 @@ +// Copyright (c) 2026, 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. + +// Or node +import '' deferred as OrAlive; +import '' deferred as OrAlive_1; +import '' deferred as OrAlive_2; +import '' deferred as OrDead; + +// And node +import '' deferred as AndAlive; +import '' deferred as AndAlive_1; +import '' deferred as AndAlive_2; +import '' deferred as AndDead; + +// Fuse node +import '' deferred as FuseAlive; +import '' deferred as FuseAlive_1; +import '' deferred as FuseAlive_2; +import '' deferred as FuseDead; + +void main() async { + print('main'); + switch (opaqueInt) { + case 1: + await OrAlive.loadLibrary(); + await OrAlive.testOr(); + break; + case 2: + await AndAlive.loadLibrary(); + await AndAlive.testAnd(); + break; + case 3: + await FuseAlive.loadLibrary(); + await FuseAlive.testFuse(); + break; + } +} + +Future testOr() async { + switch (opaqueInt) { + case 1: + await OrAlive_1.loadLibrary(); + OrAlive_1.orTest_alive_1(); + break; + case 2: + await OrAlive_2.loadLibrary(); + OrAlive_2.orTest_alive_2(); + break; + default: + if (alwaysFalse) { + await OrDead.loadLibrary(); + OrDead.orTest_dead(); + } + break; + } +} + +Future testAnd() async { + for (int i = 0; i < 3; ++i) { + if (i == 0) { + await AndAlive_1.loadLibrary(); + AndAlive_1.andTest_alive_1(); + } else if (i == 1) { + await AndAlive_2.loadLibrary(); + AndAlive_2.andTest_alive_2(); + } else { + if (!alwaysTrue) { + await AndDead.loadLibrary(); + AndDead.andTest_dead(); + } + } + } +} + +Future testFuse() async { + await FuseAlive_1.loadLibrary(); + FuseAlive_1.fuseTest_alive_1(); + await FuseAlive_2.loadLibrary(); + FuseAlive_2.fuseTest_alive_2(); + if (alwaysFalse) { + await FuseDead.loadLibrary(); + FuseDead.fuseTest_dead(); + } +} + +void orTest_alive_1() => print('orTest_alive_1'); +void orTest_alive_2() => print('orTest_alive_2'); +void orTest_dead() => print('orTest_dead'); + +void andTest_alive_1() => print('andTest_alive_1'); +void andTest_alive_2() => print('andTest_alive_2'); +void andTest_dead() => print('andTest_dead'); + +void fuseTest_alive_1() => print('fuseTest_alive_1'); +void fuseTest_alive_2() => print('fuseTest_alive_2'); +void fuseTest_dead() => print('fuseTest_dead'); + +int get opaqueInt => int.parse('1'); +bool get alwaysTrue => true; +bool get alwaysFalse => false; diff --git a/pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.default.txt b/pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.default.txt new file mode 100644 index 00000000000..0fc04876eaa --- /dev/null +++ b/pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.default.txt @@ -0,0 +1,74 @@ +Part 0 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive_1 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive_2 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::testOr + Constants + +Part 1 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: AndAlive + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: AndAlive_1 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: AndAlive_2 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::testAnd + Constants + +Part 2 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: FuseAlive + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: FuseAlive_1 + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: FuseAlive_2 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::testFuse + Constants + +Part 3 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive_1 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::orTest_alive_1 + Constants + - StringConstant("orTest_alive_1") + +Part 4 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: OrAlive_2 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::orTest_alive_2 + Constants + - StringConstant("orTest_alive_2") + +Part 5 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: AndAlive_1 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::andTest_alive_1 + Constants + - StringConstant("andTest_alive_1") + +Part 6 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: AndAlive_2 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::andTest_alive_2 + Constants + - StringConstant("andTest_alive_2") + +Part 7 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: FuseAlive_1 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::fuseTest_alive_1 + Constants + - StringConstant("fuseTest_alive_1") + +Part 8 + ImportSet + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart prefix: FuseAlive_2 + References + - pkg/dart2wasm/test/deferred_loading/partition_tests/dead_constraint.dart::@methods::fuseTest_alive_2 + Constants + - StringConstant("fuseTest_alive_2")