Skip to content

Commit 9ece92e

Browse files
fishythefishCommit Queue
authored andcommitted
[dart2wasm] Enable dynamic module validation.
This change requires some modifications to the dart2wasm flags for dynamic module support. Previously, we determined that dynamic module support was needed if `--dynamic-main-module` was passed. We determined that the main module was being compiled if `--dynamic-interface-uri` was also passed, and a submodule (AKA "dynamic module") otherwise. This design prevented us from passing the interface specification to the dynamic module validator when submodules were being compiled. Instead, we now build with dynamic support when the `--dynamic-module-type` flag is passed. Allowable values are `main` and `submodule`. Both the main module URI and interface URI are currently required for both dynamic module types. (The main module URI could be made optional if we generated a default filename like we do for dynamic module metadata.) Dynamic interface validation is enabled by default and is controlled by the `--validate-dynamic-modules` flag. This flag can be negated via `--validate-dynamic-modules=false` or `--no-validate-dynamic-modules`. Change-Id: I3165c3a8255205a61c3ccfe546f5d436472ed0d9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425154 Reviewed-by: Nate Biggs <[email protected]> Reviewed-by: Ömer Ağacan <[email protected]>
1 parent a0a6fc1 commit 9ece92e

File tree

5 files changed

+73
-29
lines changed

5 files changed

+73
-29
lines changed

pkg/dart2wasm/lib/compile.dart

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -177,17 +177,24 @@ Future<CompilationResult> compileToModule(
177177
final dynamicModuleMainUri = await resolveUri(options.dynamicModuleMainUri);
178178
final dynamicInterfaceUri = await resolveUri(options.dynamicInterfaceUri);
179179
final isDynamicMainModule =
180-
dynamicModuleMainUri != null && dynamicInterfaceUri != null;
181-
final isDynamicModule =
182-
dynamicModuleMainUri != null && dynamicInterfaceUri == null;
183-
if (isDynamicModule) {
184-
compilerOptions.additionalDills.add(dynamicModuleMainUri);
180+
options.dynamicModuleType == DynamicModuleType.main;
181+
final isDynamicSubmodule =
182+
options.dynamicModuleType == DynamicModuleType.submodule;
183+
if (isDynamicSubmodule) {
184+
compilerOptions.additionalDills.add(dynamicModuleMainUri!);
185+
186+
if (options.validateDynamicModules) {
187+
// We must pass the unresolved URI here to be compatible with the CFE
188+
// dynamic interface validator.
189+
compilerOptions.dynamicInterfaceSpecificationUri =
190+
options.dynamicInterfaceUri;
191+
}
185192
}
186193

187194
CompilerResult? compilerResult;
188195
try {
189196
compilerResult = await kernelForProgram(options.mainUri, compilerOptions,
190-
requireMain: !isDynamicModule);
197+
requireMain: !isDynamicSubmodule);
191198
} catch (e, s) {
192199
return CFECrashError(e, s);
193200
}
@@ -215,19 +222,19 @@ Future<CompilationResult> compileToModule(
215222
coreTypes,
216223
classHierarchy);
217224

218-
if (isDynamicModule) {
225+
if (isDynamicSubmodule) {
219226
// Join the dynamic module libraries with the TFAed component from the main
220227
// module compilation. JS interop transformer must be run before this since
221228
// some methods it uses may have been tree-shaken from the TFAed component.
222229
(component, jsInteropMethods) = await generateDynamicModuleComponent(
223-
component, coreTypes, dynamicModuleMainUri, jsInteropMethods);
230+
component, coreTypes, dynamicModuleMainUri!, jsInteropMethods);
224231
coreTypes = CoreTypes(component);
225232
classHierarchy =
226233
ClassHierarchy(component, coreTypes) as ClosedWorldClassHierarchy;
227234
libraryIndex = LibraryIndex(component, _librariesToIndex);
228235
}
229236

230-
final librariesToTransform = isDynamicModule
237+
final librariesToTransform = isDynamicSubmodule
231238
? component.getDynamicModuleLibraries(coreTypes)
232239
: component.libraries;
233240
final constantEvaluator = ConstantEvaluator(
@@ -238,7 +245,7 @@ Future<CompilationResult> compileToModule(
238245
final Map<RecordShape, Class> recordClasses = generateRecordClasses(
239246
component, coreTypes,
240247
isDynamicMainModule: isDynamicMainModule,
241-
isDynamicModule: isDynamicModule);
248+
isDynamicModule: isDynamicSubmodule);
242249
target.recordClasses = recordClasses;
243250

244251
if (options.dumpKernelBeforeTfa != null) {
@@ -258,11 +265,11 @@ Future<CompilationResult> compileToModule(
258265
moduleStrategy = DynamicMainModuleStrategy(
259266
component,
260267
coreTypes,
261-
File.fromUri(dynamicInterfaceUri).readAsStringSync(),
268+
File.fromUri(dynamicInterfaceUri!).readAsStringSync(),
262269
options.dynamicInterfaceUri!);
263-
} else if (isDynamicModule) {
270+
} else if (isDynamicSubmodule) {
264271
moduleStrategy = DynamicModuleStrategy(
265-
component, options, target, coreTypes, dynamicModuleMainUri);
272+
component, options, target, coreTypes, dynamicModuleMainUri!);
266273
} else {
267274
moduleStrategy = DefaultModuleStrategy(component);
268275
}
@@ -272,17 +279,17 @@ Future<CompilationResult> compileToModule(
272279
MainModuleMetadata mainModuleMetadata =
273280
MainModuleMetadata.empty(options.translatorOptions, options.environment);
274281

275-
if (isDynamicModule) {
282+
if (isDynamicSubmodule) {
276283
mainModuleMetadata =
277284
await deserializeMainModuleMetadata(component, options);
278285
mainModuleMetadata.verifyDynamicModuleOptions(options);
279286
} else if (isDynamicMainModule) {
280287
MainModuleMetadata.verifyMainModuleOptions(options);
281-
await serializeMainModuleComponent(component, dynamicModuleMainUri,
288+
await serializeMainModuleComponent(component, dynamicModuleMainUri!,
282289
optimized: false);
283290
}
284291

285-
if (!isDynamicModule) {
292+
if (!isDynamicSubmodule) {
286293
_patchMainTearOffs(coreTypes, component);
287294

288295
// Keep the flags in-sync with
@@ -307,7 +314,7 @@ Future<CompilationResult> compileToModule(
307314
var translator = Translator(component, coreTypes, libraryIndex, recordClasses,
308315
moduleOutputData, options.translatorOptions,
309316
mainModuleMetadata: mainModuleMetadata,
310-
enableDynamicModules: dynamicModuleMainUri != null);
317+
enableDynamicModules: options.enableDynamicModules);
311318

312319
String? depFile = options.depFile;
313320
if (depFile != null) {
@@ -332,7 +339,7 @@ Future<CompilationResult> compileToModule(
332339

333340
final jsRuntimeFinalizer = js.RuntimeFinalizer(jsInteropMethods);
334341

335-
final jsRuntime = isDynamicModule
342+
final jsRuntime = isDynamicSubmodule
336343
? jsRuntimeFinalizer.generateDynamicModule(
337344
translator.functions.translatedProcedures,
338345
translator.internalizedStringsForJSRuntime)
@@ -347,7 +354,7 @@ Future<CompilationResult> compileToModule(
347354
final supportJs = _generateSupportJs(options.translatorOptions);
348355
if (isDynamicMainModule) {
349356
await serializeMainModuleMetadata(component, translator, options);
350-
await serializeMainModuleComponent(component, dynamicModuleMainUri,
357+
await serializeMainModuleComponent(component, dynamicModuleMainUri!,
351358
optimized: true);
352359
}
353360

pkg/dart2wasm/lib/compiler_options.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'package:front_end/src/api_unstable/vm.dart' as fe;
66

7+
import 'dynamic_modules.dart' show DynamicModuleType;
78
import 'translator.dart';
89

910
class WasmCompilerOptions {
@@ -15,9 +16,11 @@ class WasmCompilerOptions {
1516
Uri mainUri;
1617
String outputFile;
1718
String? depFile;
19+
DynamicModuleType? dynamicModuleType;
1820
Uri? dynamicModuleMainUri;
1921
Uri? dynamicInterfaceUri;
2022
Uri? dynamicModuleMetadataFile;
23+
bool validateDynamicModules = true;
2124
Map<String, String> environment = {};
2225
Map<fe.ExperimentalFlag, bool> feExperimentalFlags = const {};
2326
String? multiRootScheme;
@@ -32,11 +35,25 @@ class WasmCompilerOptions {
3235

3336
WasmCompilerOptions({required this.mainUri, required this.outputFile});
3437

38+
bool get enableDynamicModules => dynamicModuleType != null;
39+
3540
void validate() {
3641
if (translatorOptions.importSharedMemory &&
3742
translatorOptions.sharedMemoryMaxPages == null) {
3843
throw ArgumentError("--shared-memory-max-pages must be specified if "
3944
"--import-shared-memory is used.");
4045
}
46+
47+
if (enableDynamicModules) {
48+
if (dynamicModuleMainUri == null) {
49+
throw ArgumentError("--dynamic-module-main must be specified if "
50+
"compiling dynamic modules.");
51+
}
52+
53+
if (dynamicInterfaceUri == null) {
54+
throw ArgumentError("--dynamic-module-interface must be specified if "
55+
"compiling dynamic modules.");
56+
}
57+
}
4158
}
4259
}

pkg/dart2wasm/lib/dart2wasm.dart

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:args/args.dart' as args;
88
import 'package:front_end/src/api_unstable/vm.dart' show resolveInputUri;
99
import 'package:front_end/src/api_unstable/vm.dart' as fe;
1010

11+
import 'dynamic_modules.dart' show DynamicModuleType;
1112
import 'generate_wasm.dart';
1213
import 'option.dart';
1314

@@ -103,23 +104,31 @@ final List<Option> options = [
103104
Flag("enable-multi-module-stress-test-mode",
104105
(o, value) => o.translatorOptions.enableMultiModuleStressTestMode = value,
105106
defaultsTo: _d.translatorOptions.enableMultiModuleStressTestMode),
107+
106108
// Flags for dynamic modules
107-
// The modified dill file produced by the main module compilation for dynamic
108-
// modules. Providing this and not "dynamic-module-interface" indicates that
109-
// this is a compilation of a dynamic module. The dill will contain the AST
110-
// for the main module as well as some annotations to help identify entities
111-
// when compiling dynamic modules.
109+
StringOption("dynamic-module-type",
110+
(o, value) => o.dynamicModuleType = DynamicModuleType.parse(value)),
111+
112+
// The modified dill file to be output by the main module compilation for
113+
// dynamic modules. The dill will contain the AST for the main module as well
114+
// as some annotations to help identify entities when compiling dynamic
115+
// modules.
112116
UriOption(
113117
"dynamic-module-main", (o, value) => o.dynamicModuleMainUri = value),
118+
114119
// A yaml file describing the interface of the main module accessible from
115-
// dynamic modules. Providing this indicates to the dart2wasm that the module
116-
// produced should support dynamic modules.
120+
// dynamic modules.
117121
UriOption(
118122
"dynamic-module-interface", (o, value) => o.dynamicInterfaceUri = value),
123+
119124
// A binary metadata file produced by the main module compilation for dynamic
120125
// modules.
121126
UriOption("dynamic-module-metadata",
122127
(o, value) => o.dynamicModuleMetadataFile = value),
128+
129+
Flag("validate-dynamic-modules",
130+
(o, value) => o.validateDynamicModules = value,
131+
defaultsTo: true, negatable: true),
123132
];
124133

125134
Map<fe.ExperimentalFlag, bool> processFeExperimentalFlags(

pkg/dart2wasm/lib/dynamic_modules.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,17 @@ import 'util.dart';
3636
const String _mainModLibPragma = 'wasm:mainMod';
3737
const String _dynamicModuleEntryPointName = '\$invokeEntryPoint';
3838

39+
enum DynamicModuleType {
40+
main,
41+
submodule;
42+
43+
static DynamicModuleType parse(String s) => switch (s) {
44+
"main" => main,
45+
"submodule" => submodule,
46+
_ => throw ArgumentError("Unrecognized dynamic module type $s."),
47+
};
48+
}
49+
3950
extension DynamicModuleComponent on Component {
4051
static final Expando<Procedure> _dynamicModuleEntryPoint =
4152
Expando<Procedure>();

pkg/dynamic_modules/test/runner/dart2wasm.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ class Dart2wasmExecutor implements TargetExecutor {
6565
// This is required while binaryen lacks support for partially closed
6666
// world optimizations.
6767
'-O0',
68+
'--extra-compiler-option=--dynamic-module-type=${isMain ? "main" : "submodule"}',
6869
'--extra-compiler-option=--dynamic-module-main=main.dart.dill',
69-
if (isMain)
70-
'--extra-compiler-option=--dynamic-module-interface='
71-
'$rootScheme:/data/$testName/dynamic_interface.yaml',
70+
'--extra-compiler-option=--dynamic-module-interface='
71+
'$rootScheme:/data/$testName/dynamic_interface.yaml',
7272
'$rootScheme:/data/$testName/$source',
7373
'$source.wasm',
7474
];

0 commit comments

Comments
 (0)