[dart2wasm] Separate deferred map json creation from use of load ids.
Currently the 'load-ids' controls both how deferred modules are loaded and whether or not the compiler emits a deferred map JSON file. This change separates these 2 actions into 2 separate flags. 'deferred-map' now provides the URI for the JSON file. And 'use-load-ids' controls how deferred modules are loaded. This is needed for some tools that might not want to use load ids but still need to process the deferred map file. Change-Id: I6909307f058d8f97dd8987e421f693ee97d6572f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/499520 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Nate Biggs <natebiggs@google.com>
This commit is contained in:
committed by
dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
c783ae42a4
commit
9f33810b01
@@ -651,9 +651,9 @@ Future<CompilationResult> _runCodegenPhase(
|
||||
|
||||
final supportJs = _generateSupportJs(options.translatorOptions);
|
||||
|
||||
final loadIdsFile = options.loadsIdsUri;
|
||||
if (loadIdsFile != null) {
|
||||
await writeLoadIdsFile(component, coreTypes, options, loadingMap);
|
||||
final deferredMapFile = options.deferredMapUri;
|
||||
if (deferredMapFile != null) {
|
||||
await writeDeferredMapFile(component, coreTypes, options, loadingMap);
|
||||
}
|
||||
|
||||
final wasmOutputFilename = path.basename(options.outputFile);
|
||||
|
||||
@@ -42,7 +42,8 @@ class WasmCompilerOptions {
|
||||
Uri mainUri;
|
||||
String outputFile;
|
||||
String? depFile;
|
||||
Uri? loadsIdsUri;
|
||||
Uri? deferredMapUri;
|
||||
bool useLoadIds = false;
|
||||
Uri? programSplitConstraintsUri;
|
||||
Map<String, String> environment = {};
|
||||
Map<fe.ExperimentalFlag, bool> feExperimentalFlags = const {};
|
||||
@@ -125,12 +126,20 @@ class WasmCompilerOptions {
|
||||
}
|
||||
|
||||
if (!translatorOptions.enableDeferredLoading) {
|
||||
if (loadsIdsUri != null) {
|
||||
if (deferredMapUri != null) {
|
||||
throw ArgumentError(
|
||||
"--load-ids can only be used with "
|
||||
"--deferred-map can only be used with "
|
||||
"--enable-deferred-loading",
|
||||
);
|
||||
}
|
||||
if (useLoadIds) {
|
||||
throw ArgumentError(
|
||||
"--use-load-ids can only be used with "
|
||||
"--enable-deferred-loading",
|
||||
);
|
||||
}
|
||||
} else if (useLoadIds && deferredMapUri == null) {
|
||||
throw ArgumentError("--use-load-ids requires --deferred-map");
|
||||
}
|
||||
|
||||
if (translatorOptions.standalone) {
|
||||
|
||||
@@ -37,7 +37,7 @@ class ConstantEvaluator extends kernel.ConstantEvaluator
|
||||
_deferredLoadingEnabled =
|
||||
options.translatorOptions.enableDeferredLoading ||
|
||||
options.translatorOptions.enableMultiModuleStressTestMode,
|
||||
_deferredLoadingViaEmbedderLoadId = options.loadsIdsUri != null,
|
||||
_deferredLoadingViaEmbedderLoadId = options.useLoadIds,
|
||||
_dartInternalCheckBoundsGetter = libraryIndex.tryGetProcedure(
|
||||
"dart:_internal",
|
||||
LibraryIndex.topLevel,
|
||||
|
||||
@@ -179,7 +179,8 @@ final List<Option> options = [
|
||||
(o, value) => o.translatorOptions.enableDeferredLoading = value,
|
||||
defaultsTo: _d.translatorOptions.enableDeferredLoading,
|
||||
),
|
||||
UriOption("load-ids", (o, value) => o.loadsIdsUri = value),
|
||||
UriOption("deferred-map", (o, value) => o.deferredMapUri = value),
|
||||
Flag("use-load-ids", (o, value) => o.useLoadIds = value),
|
||||
UriOption(
|
||||
"read-program-split",
|
||||
(o, value) => o.programSplitConstraintsUri = value,
|
||||
|
||||
@@ -235,13 +235,13 @@ class StressTestModuleStrategy extends ModuleStrategy {
|
||||
ModuleOutputData buildModuleOutputData() => moduleOutputData;
|
||||
}
|
||||
|
||||
Future<void> writeLoadIdsFile(
|
||||
Future<void> writeDeferredMapFile(
|
||||
Component component,
|
||||
CoreTypes coreTypes,
|
||||
WasmCompilerOptions options,
|
||||
DeferredModuleLoadingMap loadingMap,
|
||||
) async {
|
||||
final file = File.fromUri(options.loadsIdsUri!);
|
||||
final file = File.fromUri(options.deferredMapUri!);
|
||||
await file.create(recursive: true);
|
||||
await file.writeAsString(
|
||||
_generateDeferredMapJson(
|
||||
|
||||
@@ -56,12 +56,13 @@ class CompiledApp {
|
||||
// loadDeferredModules should return a Promise that resolves when all the
|
||||
// modules have been loaded and the callback promises have resolved.
|
||||
// `loadDeferredId` is a JS function that takes load ID produced by the
|
||||
// compiler when the `load-ids` option is passed. Each load ID maps to one
|
||||
// or more wasm files as specified in the emitted JSON file. It also takes a
|
||||
// callback that should be invoked for each loaded module with 2 arugments:
|
||||
// (1) the module name, (2) the loaded module in a format supported by
|
||||
// `WebAssembly.compile` or `WebAssembly.compileStreaming`. The callback
|
||||
// returns a Promise that resolves when the module is instantiated.
|
||||
// compiler when the `use-load-ids` option is passed. Each load ID maps to
|
||||
// one or more wasm files as specified in the emitted JSON file. It also
|
||||
// takes a callback that should be invoked for each loaded module with 2
|
||||
// arugments: (1) the module name, (2) the loaded module in a format
|
||||
// supported by `WebAssembly.compile` or `WebAssembly.compileStreaming`.
|
||||
// The callback returns a Promise that resolves when the module is
|
||||
// instantiated.
|
||||
// loadDeferredModules should return a Promise that resolves when all the
|
||||
// modules have been loaded and the callback promises have resolved.
|
||||
async instantiate(additionalImports, {loadDeferredModules, loadDeferredId} = {}) {
|
||||
|
||||
@@ -599,12 +599,12 @@ class Translator with KernelNodes {
|
||||
getThisModuleGlobal(moduleBuilder);
|
||||
}
|
||||
|
||||
// This getter will be null if we pass e.g. `--load-ids=<uri>` as the
|
||||
// This getter will be null if we pass e.g. `--use-load-ids` as the
|
||||
// runtime code will then be pruned to call out to embedder instead of
|
||||
// consulting the load mapping bundled in the app.
|
||||
final loadingMapGetter = dartInternalLoadingMapGetter;
|
||||
if (loadingMapGetter != null && !options.standalone) {
|
||||
// This function will be null if we didn't pass `--load-ids=<uri>` but we
|
||||
// This function will be null if we didn't pass `--use-load-ids` but we
|
||||
// ended up not having any actual deferred code (e.g. `await
|
||||
// foo.loadLibrary()` is never called anywhere).
|
||||
final function =
|
||||
|
||||
+12
-10
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
|
||||
// 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.
|
||||
|
||||
@@ -15,7 +15,7 @@ const String helperJsLoadIdLookupToken = 'LOAD_ID_LOOKUP';
|
||||
const String helperJsModuleDirToken = 'MODULE_DIR';
|
||||
|
||||
final String goldenPath =
|
||||
'${path.dirname(Platform.script.path)}/data/deferred_load_ids.golden.json';
|
||||
'${path.dirname(Platform.script.path)}/data/deferred_map.golden.json';
|
||||
final String mainDart = '${path.dirname(Platform.script.path)}/data/main.dart';
|
||||
final String helperJs = '${path.dirname(Platform.script.path)}/helper.js';
|
||||
|
||||
@@ -27,7 +27,7 @@ Future<void> main(List<String> args) async {
|
||||
|
||||
await withTempDir((tmpDirPath) async {
|
||||
final tmpDir = File(tmpDirPath);
|
||||
final loadIdsUri = tmpDir.uri.resolve('deferred_load_ids.json');
|
||||
final deferredMapUri = tmpDir.uri.resolve('deferred_map.json');
|
||||
final outFilename = '${tmpDir.path}/out.wasm';
|
||||
// Compile the test
|
||||
await run([
|
||||
@@ -36,25 +36,27 @@ Future<void> main(List<String> args) async {
|
||||
mainDart,
|
||||
'--platform=$platformDill',
|
||||
'--enable-deferred-loading',
|
||||
'--load-ids=$loadIdsUri',
|
||||
'--deferred-map=$deferredMapUri',
|
||||
outFilename,
|
||||
]);
|
||||
|
||||
final loadIdsContent = await File.fromUri(loadIdsUri).readAsString();
|
||||
final deferredMapContent = await File.fromUri(
|
||||
deferredMapUri,
|
||||
).readAsString();
|
||||
final goldenFile = File(goldenPath);
|
||||
|
||||
if (argsResult.flag('update-golden')) {
|
||||
print('Updating golden:\n$loadIdsContent');
|
||||
await goldenFile.writeAsString(loadIdsContent);
|
||||
print('Updating golden:\n$deferredMapContent');
|
||||
await goldenFile.writeAsString(deferredMapContent);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure the load IDs JSON matches the golden.
|
||||
Expect.equals(await goldenFile.readAsString(), loadIdsContent);
|
||||
// Ensure the deferred map JSON matches the golden.
|
||||
Expect.equals(await goldenFile.readAsString(), deferredMapContent);
|
||||
|
||||
// Extract a map from each load ID to its corresponding module.
|
||||
final loadIdToModules = <String, List<String>>{};
|
||||
final json = const JsonDecoder().convert(loadIdsContent);
|
||||
final json = const JsonDecoder().convert(deferredMapContent);
|
||||
(json as Map).forEach((_, info) {
|
||||
((info as Map)['imports'] as Map).forEach((loadId, modules) {
|
||||
loadIdToModules[loadId] = (modules as List).cast<String>();
|
||||
Reference in New Issue
Block a user