[dynamic_modules] Add support for deduplicating library prefixes to dart2wasm

Change-Id: I325e4e1e3aff25c4e894bc2f3f23fcf02f15da16
Fixes: https://github.com/dart-lang/sdk/issues/62828
Tested: Dynamic module tests.
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/485980
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Auto-Submit: Nate Biggs <natebiggs@google.com>
This commit is contained in:
Nate Biggs
2026-03-06 05:39:21 -08:00
committed by Commit Queue
parent 64797f76c9
commit 44a049c082
7 changed files with 106 additions and 72 deletions
+5 -57
View File
@@ -15,7 +15,7 @@ import 'package:front_end/src/api_unstable/vm.dart'
parseExperimentalArguments,
parseExperimentalFlags,
resolveInputUri;
import 'package:kernel/ast.dart' show Component, Library, Source;
import 'package:kernel/ast.dart' show Component;
import 'package:vm/kernel_front_end.dart'
show
badUsageExitCode,
@@ -30,6 +30,8 @@ import 'package:vm/kernel_front_end.dart'
parseCommandLineDefines,
successExitCode,
writeDepfile;
import 'package:vm/transformations/prefix_library_uris.dart'
as prefix_library_uris;
import 'bytecode_serialization.dart' show BytecodeSizeStatistics;
import 'bytecode_generator.dart' show generateBytecode;
@@ -260,8 +262,8 @@ Future<int> runCompilerWithOptions({
if (errorDetector.hasCompilationErrors || component == null) {
return compileTimeErrorExitCode;
}
component =
prefixLibraryUris(component, results.loadedLibraries, libraryUrisPrefix);
component = prefix_library_uris.prefixLibraryUris(
component, results.loadedLibraries, libraryUrisPrefix);
if (bytecodeOptions.showBytecodeSizeStatistics) {
BytecodeSizeStatistics.reset();
}
@@ -291,57 +293,3 @@ Future<int> runCompilerWithOptions({
return successExitCode;
}
Component prefixLibraryUris(Component component, Set<Library> loadedLibraries,
String libraryUrisPrefix) {
if (libraryUrisPrefix.isEmpty) {
return component;
}
final prefixSegments = libraryUrisPrefix.split('/');
final importUriReplacements = <Uri, Uri>{};
for (final lib in component.libraries) {
// Skip libraries that come from the host app or the SDK.
if (loadedLibraries.contains(lib)) {
continue;
}
final newImportUri = prefixUri(lib.importUri, prefixSegments);
importUriReplacements[lib.importUri] = newImportUri;
lib.importUri = newImportUri;
}
// Update import uris in sources.
final allSourceFileUris = component.uriToSource.keys.toSet();
for (final fileUri in allSourceFileUris) {
final source = component.uriToSource[fileUri]!;
final importUriReplacement = importUriReplacements[source.importUri];
if (importUriReplacement == null) {
continue;
}
// Rewrite the source with the new import URI.
component.uriToSource[fileUri] = Source(
source.lineStarts,
source.source,
importUriReplacement,
source.fileUri,
)
..cachedText = source.cachedText
..constantCoverageConstructors = source.constantCoverageConstructors;
}
return component;
}
Uri prefixUri(Uri uri, List<String> prefixSegments) {
if (uri.scheme == 'package') {
// For package URIs, the first segment is dot-separated package path, so
// we prepend the prefix to the first segment.
final pathSegments = uri.pathSegments.toList();
pathSegments[0] = [...prefixSegments, pathSegments.first].join('.');
return uri.replace(pathSegments: pathSegments);
}
// For other schemes, we just prepend the prefix to the path segments.
return uri.replace(pathSegments: prefixSegments.followedBy(uri.pathSegments));
}
@@ -1,18 +0,0 @@
// 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.
import 'package:dart2bytecode/dart2bytecode.dart' show prefixUri;
import 'package:test/test.dart';
void main() {
group('prefixUri', () {
test('prefixes file URIs', () {
expect(prefixUri(Uri.parse('file:///foo/bar.dart'), ['pre', 'fix']),
Uri.parse('file:///pre/fix/foo/bar.dart'));
});
test('prefixes package URIs', () {
expect(prefixUri(Uri.parse('package:foo/bar.dart'), ['pre', 'fix']),
Uri.parse('package:pre.fix.foo/bar.dart'));
});
});
}