diff --git a/build/rbe/rewrapper_dart.py b/build/rbe/rewrapper_dart.py index 76b753dd7cb..40e4f4952cb 100644 --- a/build/rbe/rewrapper_dart.py +++ b/build/rbe/rewrapper_dart.py @@ -82,7 +82,7 @@ def list_imports(uri, exec_root, package_config): ]: continue # Imports must happen before definitions. - if tokens[0] in ['const', 'class', 'enum']: + if tokens[0] in ['const', 'class', 'enum', 'final']: break if 2 <= len(tokens ) and tokens[0] == 'if' and tokens[1] == '(dart.library.io)': diff --git a/pkg/dart2wasm/lib/compile.dart b/pkg/dart2wasm/lib/compile.dart index 61dd17addc6..b3dfa7f9a0f 100644 --- a/pkg/dart2wasm/lib/compile.dart +++ b/pkg/dart2wasm/lib/compile.dart @@ -48,8 +48,9 @@ sealed class CompilationResult {} class CompilationSuccess extends CompilationResult { final Map wasmModules; final String jsRuntime; + final String supportJs; - CompilationSuccess(this.wasmModules, this.jsRuntime); + CompilationSuccess(this.wasmModules, this.jsRuntime, this.supportJs); } class CompilationError extends CompilationResult {} @@ -238,11 +239,8 @@ Future compileToModule( String? depFile = options.depFile; if (depFile != null) { - writeDepfile( - compilerOptions.fileSystem, - component.uriToSource.keys, - options.outputFile, - depFile); + writeDepfile(compilerOptions.fileSystem, component.uriToSource.keys, + options.outputFile, depFile); } final generateSourceMaps = options.translatorOptions.generateSourceMaps; @@ -262,7 +260,50 @@ Future compileToModule( String jsRuntime = jsRuntimeFinalizer.generate( translator.functions.translatedProcedures, translator.internalizedStringsForJSRuntime, + translator.options.requireJsStringBuiltin, mode); - return CompilationSuccess(wasmModules, jsRuntime); + final supportJs = _generateSupportJs(options.translatorOptions); + return CompilationSuccess(wasmModules, jsRuntime, supportJs); +} + +String _generateSupportJs(TranslatorOptions options) { + // Copied from + // https://github.com/GoogleChromeLabs/wasm-feature-detect/blob/main/src/detectors/gc/index.js + // + // Uses WasmGC types and will only validate correctly if the engine supports + // WasmGC: + // ``` + // (module + // (type $type0 (struct (field $field0 i8))) + // ) + // ``` + // + // NOTE: Once we support more feature detections we may use + // `package:wasm_builder` to create the module instead of having a fixed one + // here. + const String supportsWasmGC = + 'WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,95,1,120,0]))'; + + // Imports a `js-string` builtin spec function *with wrong signature*. An engine + // + // * *without* knowledge about `js-string` builtin would accept such an import at + // validation time. + // + // * *with* knowledge about `js-string` would refuse it as the signature + // used to import the `cast` function is not according to `js-string` spec + // + // ``` + // (module + // (func $wasm:js-string.cast (;0;) (import "wasm:js-string" "cast")) + // ) + // ``` + const String supportsJsStringBuiltins = + '!WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,2,23,1,14,119,97,115,109,58,106,115,45,115,116,114,105,110,103,4,99,97,115,116,0,0]),{"builtins":["js-string"]})'; + + final requiredFeatures = [ + supportsWasmGC, + if (options.requireJsStringBuiltin) supportsJsStringBuiltins + ]; + return '(${requiredFeatures.join('&&')})'; } diff --git a/pkg/dart2wasm/lib/compiler_options.dart b/pkg/dart2wasm/lib/compiler_options.dart index fa526289737..da74fdc84d8 100644 --- a/pkg/dart2wasm/lib/compiler_options.dart +++ b/pkg/dart2wasm/lib/compiler_options.dart @@ -15,7 +15,6 @@ class WasmCompilerOptions { Uri mainUri; String outputFile; String? depFile; - String? outputJSRuntimeFile; Uri? dynamicModuleMainUri; Uri? dynamicInterfaceUri; Uri? dynamicModuleMetadataFile; diff --git a/pkg/dart2wasm/lib/dart2wasm.dart b/pkg/dart2wasm/lib/dart2wasm.dart index 352b3a9d3fe..9cb8c5a3f61 100644 --- a/pkg/dart2wasm/lib/dart2wasm.dart +++ b/pkg/dart2wasm/lib/dart2wasm.dart @@ -78,8 +78,6 @@ final List