From aacf9939822d98a9c31e9b368c7bf027a240906f Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Thu, 10 Jul 2025 17:45:41 -0700 Subject: [PATCH 1/2] test: wpt for Wasm jsapi including new ESM Integration tests --- test/common/wpt.js | 2 +- test/common/wpt/worker.js | 16 ++- .../esm-integration/exports.tentative.any.js | 36 ++++++ ...bal-exports-live-bindings.tentative.any.js | 46 ++++++++ .../global-exports.tentative.any.js | 111 ++++++++++++++++++ .../js-wasm-cycle.tentative.any.js | 7 ++ .../mutable-global-sharing.tentative.any.js | 78 ++++++++++++ .../namespace-instance.tentative.any.js | 52 ++++++++ .../reserved-import-names.tentative.any.js | 41 +++++++ .../resolve-export.tentative.any.js | 9 ++ .../jsapi/esm-integration/resources/dep.wasm | Bin 0 -> 529 bytes .../esm-integration/resources/exports.wasm | Bin 0 -> 226 bytes .../esm-integration/resources/globals.js | 29 +++++ .../esm-integration/resources/globals.wasm | Bin 0 -> 2973 bytes .../invalid-export-name-wasm-js.wasm | Bin 0 -> 64 bytes .../resources/invalid-export-name.wasm | Bin 0 -> 61 bytes .../resources/invalid-import-module.wasm | Bin 0 -> 94 bytes .../invalid-import-name-wasm-js.wasm | Bin 0 -> 94 bytes .../resources/invalid-import-name.wasm | Bin 0 -> 91 bytes .../resources/js-string-builtins.wasm | Bin 0 -> 401 bytes .../resources/js-wasm-cycle.js | 17 +++ .../resources/js-wasm-cycle.wasm | Bin 0 -> 101 bytes .../jsapi/esm-integration/resources/log.js | 1 + .../resources/mutable-global-export.wasm | Bin 0 -> 378 bytes .../resources/mutable-global-reexport.wasm | Bin 0 -> 428 bytes .../resources/resolve-export.js | 1 + .../resources/resolve-export.wasm | Bin 0 -> 8 bytes .../resources/wasm-export-to-wasm.wasm | Bin 0 -> 45 bytes .../resources/wasm-import-from-wasm.wasm | Bin 0 -> 75 bytes ...rce-phase-string-builtins.tentative.any.js | 39 ++++++ .../source-phase.tentative.any.js | 42 +++++++ .../string-builtins.tentative.any.js | 12 ++ .../esm-integration/v128-tdz.tentative.any.js | 11 ++ .../wasm-import-wasm-export.tentative.any.js | 14 +++ test/fixtures/wpt/wasm/resources/load_wasm.js | 12 ++ test/wpt/status/wasm/jsapi.json | 56 +++++++++ test/wpt/test-wasm-jsapi.mjs | 21 ++++ 37 files changed, 649 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/exports.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/global-exports-live-bindings.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/global-exports.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/js-wasm-cycle.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/mutable-global-sharing.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/namespace-instance.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/reserved-import-names.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resolve-export.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/dep.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/exports.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/globals.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/globals.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/invalid-export-name-wasm-js.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/invalid-export-name.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/invalid-import-module.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/invalid-import-name-wasm-js.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/invalid-import-name.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/js-string-builtins.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/js-wasm-cycle.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/js-wasm-cycle.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/log.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/mutable-global-export.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/mutable-global-reexport.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/resolve-export.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/resolve-export.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/wasm-export-to-wasm.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/wasm-import-from-wasm.wasm create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/source-phase-string-builtins.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/source-phase.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/string-builtins.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/v128-tdz.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/wasm-import-wasm-export.tentative.any.js create mode 100644 test/fixtures/wpt/wasm/resources/load_wasm.js create mode 100644 test/wpt/status/wasm/jsapi.json create mode 100644 test/wpt/test-wasm-jsapi.mjs diff --git a/test/common/wpt.js b/test/common/wpt.js index 74b182e5b84296..bfdf6fa9054028 100644 --- a/test/common/wpt.js +++ b/test/common/wpt.js @@ -885,7 +885,7 @@ class WPTRunner { console.log(test.stack); } const command = `${process.execPath} ${process.execArgv}` + - ` ${require.main.filename} '${spec.filename}${spec.variant}'`; + ` ${require.main?.filename} '${spec.filename}${spec.variant}'`; console.log(`Command: ${command}\n`); reportResult?.addSubtest(test.name, 'FAIL', test.message); diff --git a/test/common/wpt/worker.js b/test/common/wpt/worker.js index 855ec7e91c394b..30585ecbe57f73 100644 --- a/test/common/wpt/worker.js +++ b/test/common/wpt/worker.js @@ -1,6 +1,10 @@ 'use strict'; -const { runInNewContext, runInThisContext } = require('vm'); +const { + runInNewContext, + runInThisContext, + constants: { USE_MAIN_CONTEXT_DEFAULT_LOADER }, +} = require('vm'); const { setFlagsFromString } = require('v8'); const { parentPort, workerData } = require('worker_threads'); @@ -28,11 +32,14 @@ globalThis.fetch = function fetch(file) { }; if (workerData.initScript) { - runInThisContext(workerData.initScript); + runInThisContext(workerData.initScript, { + importModuleDynamically: USE_MAIN_CONTEXT_DEFAULT_LOADER, + }); } runInThisContext(workerData.harness.code, { filename: workerData.harness.filename, + importModuleDynamically: USE_MAIN_CONTEXT_DEFAULT_LOADER, }); // eslint-disable-next-line no-undef @@ -66,5 +73,8 @@ add_completion_callback((_, status) => { }); for (const scriptToRun of workerData.scriptsToRun) { - runInThisContext(scriptToRun.code, { filename: scriptToRun.filename }); + runInThisContext(scriptToRun.code, { + filename: scriptToRun.filename, + importModuleDynamically: USE_MAIN_CONTEXT_DEFAULT_LOADER, + }); } diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/exports.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/exports.tentative.any.js new file mode 100644 index 00000000000000..9feaa283aaed26 --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/exports.tentative.any.js @@ -0,0 +1,36 @@ +// META: global=window,dedicatedworker,jsshell,shadowrealm + +"use strict"; + +promise_test(async () => { + const mod = await import("./resources/exports.wasm"); + + assert_array_equals(Object.getOwnPropertyNames(mod).sort(), [ + "a\u200Bb\u0300c", + "func", + "glob", + "mem", + "tab", + "value with spaces", + "🎯test-func!", + ]); + assert_true(mod.func instanceof Function); + assert_true(mod.mem instanceof WebAssembly.Memory); + assert_true(mod.tab instanceof WebAssembly.Table); + + assert_false(mod.glob instanceof WebAssembly.Global); + assert_equals(typeof mod.glob, "number"); + + assert_throws_js(TypeError, () => { + mod.func = 2; + }); + + assert_equals(typeof mod["value with spaces"], "number"); + assert_equals(mod["value with spaces"], 123); + + assert_true(mod["🎯test-func!"] instanceof Function); + assert_equals(mod["🎯test-func!"](), 456); + + assert_equals(typeof mod["a\u200Bb\u0300c"], "number"); + assert_equals(mod["a\u200Bb\u0300c"], 789); +}, "Exported names from a WebAssembly module"); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/global-exports-live-bindings.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/global-exports-live-bindings.tentative.any.js new file mode 100644 index 00000000000000..d80c30943c04c7 --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/global-exports-live-bindings.tentative.any.js @@ -0,0 +1,46 @@ +// META: global=window,dedicatedworker,jsshell,shadowrealm + +promise_test(async () => { + const wasmExports = await import("./resources/globals.wasm"); + + wasmExports.setLocalMutI32(555); + assert_equals(wasmExports.getLocalMutI32(), 555); + assert_equals(wasmExports.localMutI32, 555); + + wasmExports.setLocalMutI64(444n); + assert_equals(wasmExports.getLocalMutI64(), 444n); + assert_equals(wasmExports.localMutI64, 444n); + + wasmExports.setLocalMutF32(3.33); + assert_equals(Math.round(wasmExports.getLocalMutF32() * 100) / 100, 3.33); + assert_equals(Math.round(wasmExports.localMutF32 * 100) / 100, 3.33); + + wasmExports.setLocalMutF64(2.22); + assert_equals(wasmExports.getLocalMutF64(), 2.22); + assert_equals(wasmExports.localMutF64, 2.22); + + const anotherTestObj = { another: "test object" }; + wasmExports.setLocalMutExternref(anotherTestObj); + assert_equals(wasmExports.getLocalMutExternref(), anotherTestObj); + assert_equals(wasmExports.localMutExternref, anotherTestObj); +}, "Local mutable global exports should be live bindings"); + +promise_test(async () => { + const wasmExports = await import("./resources/globals.wasm"); + + wasmExports.setDepMutI32(3001); + assert_equals(wasmExports.getDepMutI32(), 3001); + assert_equals(wasmExports.depMutI32, 3001); + + wasmExports.setDepMutI64(30000000001n); + assert_equals(wasmExports.getDepMutI64(), 30000000001n); + assert_equals(wasmExports.depMutI64, 30000000001n); + + wasmExports.setDepMutF32(30.01); + assert_equals(Math.round(wasmExports.getDepMutF32() * 100) / 100, 30.01); + assert_equals(Math.round(wasmExports.depMutF32 * 100) / 100, 30.01); + + wasmExports.setDepMutF64(300.0001); + assert_equals(wasmExports.getDepMutF64(), 300.0001); + assert_equals(wasmExports.depMutF64, 300.0001); +}, "Dep module mutable global exports should be live bindings"); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/global-exports.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/global-exports.tentative.any.js new file mode 100644 index 00000000000000..51ebcaf95a2ad9 --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/global-exports.tentative.any.js @@ -0,0 +1,111 @@ +// META: global=window,dedicatedworker,jsshell,shadowrealm + +promise_test(async () => { + const wasmModule = await import("./resources/globals.wasm"); + + assert_equals(wasmModule.importedI32, 42); + assert_equals(wasmModule.importedI64, 9223372036854775807n); + assert_equals(Math.round(wasmModule.importedF32 * 100000) / 100000, 3.14159); + assert_equals(wasmModule.importedF64, 3.141592653589793); + assert_not_equals(wasmModule.importedExternref, null); + assert_equals(wasmModule.importedNullExternref, null); +}, "WebAssembly module global values should be unwrapped when importing in ESM integration"); + +promise_test(async () => { + const wasmModule = await import("./resources/globals.wasm"); + + assert_equals(wasmModule.importedMutI32, 100); + assert_equals(wasmModule.importedMutI64, 200n); + assert_equals( + Math.round(wasmModule.importedMutF32 * 100000) / 100000, + 2.71828 + ); + assert_equals(wasmModule.importedMutF64, 2.718281828459045); + assert_not_equals(wasmModule.importedMutExternref, null); + assert_equals(wasmModule.importedMutExternref.mutable, "global"); +}, "WebAssembly mutable global values should be unwrapped when importing in ESM integration"); + +promise_test(async () => { + const wasmModule = await import("./resources/globals.wasm"); + + assert_equals(wasmModule["🚀localI32"], 42); + assert_equals(wasmModule.localMutI32, 100); + assert_equals(wasmModule.localI64, 9223372036854775807n); + assert_equals(wasmModule.localMutI64, 200n); + assert_equals(Math.round(wasmModule.localF32 * 100000) / 100000, 3.14159); + assert_equals(Math.round(wasmModule.localMutF32 * 100000) / 100000, 2.71828); + assert_equals(wasmModule.localF64, 2.718281828459045); + assert_equals(wasmModule.localMutF64, 3.141592653589793); +}, "WebAssembly local global values should be unwrapped when exporting in ESM integration"); + +promise_test(async () => { + const wasmModule = await import("./resources/globals.wasm"); + + assert_equals(wasmModule.depI32, 1001); + assert_equals(wasmModule.depMutI32, 2001); + assert_equals(wasmModule.depI64, 10000000001n); + assert_equals(wasmModule.depMutI64, 20000000001n); + assert_equals(Math.round(wasmModule.depF32 * 100) / 100, 10.01); + assert_equals(Math.round(wasmModule.depMutF32 * 100) / 100, 20.01); + assert_equals(wasmModule.depF64, 100.0001); + assert_equals(wasmModule.depMutF64, 200.0001); +}, "WebAssembly module globals from imported WebAssembly modules should be unwrapped"); + +promise_test(async () => { + const wasmModule = await import("./resources/globals.wasm"); + + assert_equals(wasmModule.importedI32, 42); + assert_equals(wasmModule.importedMutI32, 100); + assert_equals(wasmModule.importedI64, 9223372036854775807n); + assert_equals(wasmModule.importedMutI64, 200n); + assert_equals(Math.round(wasmModule.importedF32 * 100000) / 100000, 3.14159); + assert_equals( + Math.round(wasmModule.importedMutF32 * 100000) / 100000, + 2.71828 + ); + assert_equals(wasmModule.importedF64, 3.141592653589793); + assert_equals(wasmModule.importedMutF64, 2.718281828459045); + assert_equals(wasmModule.importedExternref !== null, true); + assert_equals(wasmModule.importedMutExternref !== null, true); + assert_equals(wasmModule.importedNullExternref, null); + + assert_equals(wasmModule["🚀localI32"], 42); + assert_equals(wasmModule.localMutI32, 100); + assert_equals(wasmModule.localI64, 9223372036854775807n); + assert_equals(wasmModule.localMutI64, 200n); + assert_equals(Math.round(wasmModule.localF32 * 100000) / 100000, 3.14159); + assert_equals(Math.round(wasmModule.localMutF32 * 100000) / 100000, 2.71828); + assert_equals(wasmModule.localF64, 2.718281828459045); + assert_equals(wasmModule.localMutF64, 3.141592653589793); + + assert_equals(wasmModule.getImportedMutI32(), 100); + assert_equals(wasmModule.getImportedMutI64(), 200n); + assert_equals( + Math.round(wasmModule.getImportedMutF32() * 100000) / 100000, + 2.71828 + ); + assert_equals(wasmModule.getImportedMutF64(), 2.718281828459045); + assert_equals(wasmModule.getImportedMutExternref() !== null, true); + + assert_equals(wasmModule.getLocalMutI32(), 100); + assert_equals(wasmModule.getLocalMutI64(), 200n); + assert_equals( + Math.round(wasmModule.getLocalMutF32() * 100000) / 100000, + 2.71828 + ); + assert_equals(wasmModule.getLocalMutF64(), 3.141592653589793); + assert_equals(wasmModule.getLocalMutExternref(), null); + + assert_equals(wasmModule.depI32, 1001); + assert_equals(wasmModule.depMutI32, 2001); + assert_equals(wasmModule.getDepMutI32(), 2001); + assert_equals(wasmModule.depI64, 10000000001n); + assert_equals(wasmModule.depMutI64, 20000000001n); + assert_equals(wasmModule.getDepMutI64(), 20000000001n); + assert_equals(Math.round(wasmModule.depF32 * 100) / 100, 10.01); + assert_equals(Math.round(wasmModule.depMutF32 * 100) / 100, 20.01); + assert_equals(Math.round(wasmModule.getDepMutF32() * 100) / 100, 20.01); + assert_equals(wasmModule.depF64, 100.0001); + assert_equals(wasmModule.depMutF64, 200.0001); + assert_equals(wasmModule.getDepMutF64(), 200.0001); +}, "WebAssembly should properly handle all global types"); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/js-wasm-cycle.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/js-wasm-cycle.tentative.any.js new file mode 100644 index 00000000000000..ce71a33a24b043 --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/js-wasm-cycle.tentative.any.js @@ -0,0 +1,7 @@ +// META: global=window,dedicatedworker,jsshell,shadowrealm + +promise_test(async () => { + const { f } = await import("./resources/js-wasm-cycle.js"); + + assert_equals(f(), 24); +}, "Check bindings in JavaScript and WebAssembly cycle (JS higher)"); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/mutable-global-sharing.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/mutable-global-sharing.tentative.any.js new file mode 100644 index 00000000000000..c636da929b3b2f --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/mutable-global-sharing.tentative.any.js @@ -0,0 +1,78 @@ +promise_test(async () => { + const exporterModule = await import("./resources/mutable-global-export.wasm"); + const reexporterModule = await import( + "./resources/mutable-global-reexport.wasm" + ); + + assert_equals(exporterModule.mutableValue, 100); + assert_equals(reexporterModule.reexportedMutableValue, 100); +}, "WebAssembly modules should export shared mutable globals with correct initial values"); + +promise_test(async () => { + const exporterModule = await import("./resources/mutable-global-export.wasm"); + const reexporterModule = await import( + "./resources/mutable-global-reexport.wasm" + ); + + exporterModule.setGlobal(500); + + assert_equals(exporterModule.getGlobal(), 500, "exporter should see 500"); + assert_equals(reexporterModule.getImportedGlobal(), 500); + + reexporterModule.setImportedGlobal(600); + + assert_equals(exporterModule.getGlobal(), 600); + assert_equals(reexporterModule.getImportedGlobal(), 600); + + exporterModule.setGlobal(700); + + assert_equals(exporterModule.getGlobal(), 700); + assert_equals(reexporterModule.getImportedGlobal(), 700); +}, "Wasm-to-Wasm mutable global sharing is live"); + +promise_test(async () => { + const module1 = await import("./resources/mutable-global-export.wasm"); + const module2 = await import("./resources/mutable-global-export.wasm"); + + assert_equals(module1, module2); + + module1.setGlobal(800); + assert_equals(module1.getGlobal(), 800, "module1 should see its own change"); + assert_equals(module2.getGlobal(), 800); +}, "Multiple JavaScript imports return the same WebAssembly module instance"); + +promise_test(async () => { + const exporterModule = await import("./resources/mutable-global-export.wasm"); + const reexporterModule = await import( + "./resources/mutable-global-reexport.wasm" + ); + + assert_equals(exporterModule.getV128Lane(0), 1); + assert_equals(exporterModule.getV128Lane(1), 2); + assert_equals(exporterModule.getV128Lane(2), 3); + assert_equals(exporterModule.getV128Lane(3), 4); + + assert_equals(reexporterModule.getImportedV128Lane(0), 1); + assert_equals(reexporterModule.getImportedV128Lane(1), 2); + assert_equals(reexporterModule.getImportedV128Lane(2), 3); + assert_equals(reexporterModule.getImportedV128Lane(3), 4); +}, "v128 globals should work correctly in WebAssembly-to-WebAssembly imports"); + +promise_test(async () => { + const exporterModule = await import("./resources/mutable-global-export.wasm"); + const reexporterModule = await import( + "./resources/mutable-global-reexport.wasm" + ); + + exporterModule.setV128Global(10, 20, 30, 40); + + assert_equals(exporterModule.getV128Lane(0), 10); + assert_equals(exporterModule.getV128Lane(1), 20); + assert_equals(exporterModule.getV128Lane(2), 30); + assert_equals(exporterModule.getV128Lane(3), 40); + + assert_equals(reexporterModule.getImportedV128Lane(0), 10); + assert_equals(reexporterModule.getImportedV128Lane(1), 20); + assert_equals(reexporterModule.getImportedV128Lane(2), 30); + assert_equals(reexporterModule.getImportedV128Lane(3), 40); +}, "v128 global mutations should work correctly between WebAssembly modules"); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/namespace-instance.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/namespace-instance.tentative.any.js new file mode 100644 index 00000000000000..e5e4e0721034d8 --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/namespace-instance.tentative.any.js @@ -0,0 +1,52 @@ +// META: global=window,dedicatedworker,jsshell,shadowrealm + +promise_test(async () => { + const wasmNamespace = await import("./resources/mutable-global-export.wasm"); + const instance = WebAssembly.namespaceInstance(wasmNamespace); + + assert_true(instance instanceof WebAssembly.Instance); + + wasmNamespace.setGlobal(999); + assert_equals(instance.exports.getGlobal(), 999); + + instance.exports.setGlobal(888); + assert_equals(wasmNamespace.getGlobal(), 888); +}, "WebAssembly.namespaceInstance() should return the underlying instance with shared state"); + +promise_test(async () => { + assert_throws_js(TypeError, () => WebAssembly.namespaceInstance({})); + assert_throws_js(TypeError, () => WebAssembly.namespaceInstance(null)); + assert_throws_js(TypeError, () => WebAssembly.namespaceInstance(undefined)); + assert_throws_js(TypeError, () => WebAssembly.namespaceInstance(42)); + assert_throws_js(TypeError, () => + WebAssembly.namespaceInstance("not a namespace") + ); + assert_throws_js(TypeError, () => WebAssembly.namespaceInstance([])); + assert_throws_js(TypeError, () => + WebAssembly.namespaceInstance(function () {}) + ); + + const jsModule = await import("./resources/globals.js"); + assert_throws_js(TypeError, () => WebAssembly.namespaceInstance(jsModule)); +}, "WebAssembly.namespaceInstance() should throw TypeError for non-WebAssembly namespaces"); + +promise_test(async () => { + const exportsModule = await import("./resources/exports.wasm"); + const globalsModule = await import("./resources/globals.wasm"); + + const exportsInstance = WebAssembly.namespaceInstance(exportsModule); + const globalsInstance = WebAssembly.namespaceInstance(globalsModule); + + assert_not_equals(exportsInstance, globalsInstance); + assert_true(exportsInstance.exports.func instanceof Function); + assert_true(globalsInstance.exports.getLocalMutI32 instanceof Function); + + globalsModule.setLocalMutI32(12345); + assert_equals(globalsInstance.exports.getLocalMutI32(), 12345); + + globalsInstance.exports.setLocalMutI32(54321); + assert_equals(globalsModule.getLocalMutI32(), 54321); + + const exportsInstance2 = WebAssembly.namespaceInstance(exportsModule); + assert_equals(exportsInstance, exportsInstance2); +}, "WebAssembly.namespaceInstance() should work correctly with multiple modules"); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/reserved-import-names.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/reserved-import-names.tentative.any.js new file mode 100644 index 00000000000000..aa17735b0206ff --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/reserved-import-names.tentative.any.js @@ -0,0 +1,41 @@ +// Test that wasm: and wasm-js: reserved cases should cause WebAssembly.LinkError + +promise_test(async (t) => { + await promise_rejects_js( + t, + WebAssembly.LinkError, + import("./resources/invalid-import-name.wasm") + ); +}, "wasm: reserved import names should cause WebAssembly.LinkError"); + +promise_test(async (t) => { + await promise_rejects_js( + t, + WebAssembly.LinkError, + import("./resources/invalid-import-name-wasm-js.wasm") + ); +}, "wasm-js: reserved import names should cause WebAssembly.LinkError"); + +promise_test(async (t) => { + await promise_rejects_js( + t, + WebAssembly.LinkError, + import("./resources/invalid-export-name.wasm") + ); +}, "wasm: reserved export names should cause WebAssembly.LinkError"); + +promise_test(async (t) => { + await promise_rejects_js( + t, + WebAssembly.LinkError, + import("./resources/invalid-export-name-wasm-js.wasm") + ); +}, "wasm-js: reserved export names should cause WebAssembly.LinkError"); + +promise_test(async (t) => { + await promise_rejects_js( + t, + WebAssembly.LinkError, + import("./resources/invalid-import-module.wasm") + ); +}, "wasm-js: reserved module names should cause WebAssembly.LinkError"); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resolve-export.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/resolve-export.tentative.any.js new file mode 100644 index 00000000000000..86325d11b0bad5 --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/resolve-export.tentative.any.js @@ -0,0 +1,9 @@ +// META: global=window,dedicatedworker,jsshell,shadowrealm + +promise_test(async (t) => { + await promise_rejects_js( + t, + SyntaxError, + import("./resources/resolve-export.js") + ); +}, "ResolveExport on invalid re-export from WebAssembly"); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/dep.wasm b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/dep.wasm new file mode 100644 index 0000000000000000000000000000000000000000..ad9abfaa66af53b33aca06422ad2850020731a9c GIT binary patch literal 529 zcmZQbEY4+QU|?XBWJ_RRtOw#cAg%@C8X(RG;%c@Uo_Yqym+aj2jE)!ix$7958c(cW zpvqmx=+rpj{((~r+_enO-!v2)xoa7nt3?(#a@R1pY|_hH%*YVwz+J=W5-Gm@A_GIF z19v{dg?#ROMj%nm@Rx@RXsrkk%K@lkBt|^M#!=Ar&g4t z7UdPCra?{S5Jrd~)Nyi^85&tYm2mNaIS5&9hRuvDd5O8H?5i1h7!Y1yMD+m^k_S-T g&w_A1E2`_+5RPX@bvp;T(>bxZoD0d}+-U9w0Ac`}+5i9m literal 0 HcmV?d00001 diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/exports.wasm b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/exports.wasm new file mode 100644 index 0000000000000000000000000000000000000000..7382eff0356128f58ee446e15be51f662e406590 GIT binary patch literal 226 zcmXAjF>b;@5Jms&tZjmoNQMiTf(9u)Ep@7#z^u*MfV_a@H7TKwlrA+#;2J471>ykd zY1lQ*`_gFUzkzBD0ib~9paZi2q@-}vC&3=t;z|qs<$~q zmhGkhlD(>1oqnzCGHrIM&<)eu|LNy!bz|TC&Ir^~*W-77ITkGXuOh(ghS>3sV|>bu uGMa|sSx9|tw(C{q4}*|8W$4pA5RIMH%PH|xb>^*EXB984EvK1YRQdt#qBtG^ literal 0 HcmV?d00001 diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/globals.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/globals.js new file mode 100644 index 00000000000000..fabf23faf38ae3 --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/globals.js @@ -0,0 +1,29 @@ +const i32_value = 42; +export { i32_value as "🚀i32_value" }; +export const i64_value = 9223372036854775807n; +export const f32_value = 3.14159; +export const f64_value = 3.141592653589793; + +export const i32_mut_value = new WebAssembly.Global( + { value: "i32", mutable: true }, + 100 +); +export const i64_mut_value = new WebAssembly.Global( + { value: "i64", mutable: true }, + 200n +); +export const f32_mut_value = new WebAssembly.Global( + { value: "f32", mutable: true }, + 2.71828 +); +export const f64_mut_value = new WebAssembly.Global( + { value: "f64", mutable: true }, + 2.718281828459045 +); + +export const externref_value = { hello: "world" }; +export const externref_mut_value = new WebAssembly.Global( + { value: "externref", mutable: true }, + { mutable: "global" } +); +export const null_externref_value = null; diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/globals.wasm b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/globals.wasm new file mode 100644 index 0000000000000000000000000000000000000000..c5e6dd9f1ded20ddec7f1a5fa84b27bd063d0827 GIT binary patch literal 2973 zcmZ`*JCEB&5Z)CjQ4}ANDC%)Kotz+P62NDGB-jNw+m`?b#4d~gDeq*PXDE=4#+@!n zp-1`@>C@y_q)wYE@GnS}!j<9DK#F8WOYTcL0Xw_%eLM55hO?r`+NIi; zWuqDOu*Bd50=By){1p00;Eft|5gydBVNo2~-GU(Cl_0Er1o2SK0>pJ|3j*6NL0AVa z>=Y86Cd(|4(8bF?%U?`pDBX3o%R;K0`?pV0=$vGO(len z+NF}f#_d))3IIETP|6`vcU*u)RSqN?q)|BH>ZvcRDu7C)5FB zpsAv<(AZ9md_+E_Y%g|amPrFV2-pi!+UmPjz2U*qbi=#m6#?Ibml&@qQNjDNQ z$`>+@`pWej?75wCBgc`{$B;{I<2V{AO?|Ydr>(z?d&DhY4(C&7h8Fkc@DB`-ip0au zs>Y{@Dfr7cs;WF7HHn9ZuJLJ754d7hzR2tz$M6&!Z}d5?{xfncc+KExT?ZG%(LIKy zi7(JJX>L(CS&O6Kv>BQvfk4xw<6%0kAGXWv9O~NJw+d?aJhm*<`z4bm1DQ#agMtCs ap~QfDSTbocl9@C)YO>^9c-#?c9Q+^eI*}y+ literal 0 HcmV?d00001 diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/invalid-export-name-wasm-js.wasm b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/invalid-export-name-wasm-js.wasm new file mode 100644 index 0000000000000000000000000000000000000000..a6b9a7f7c5ad57d8347003d77940f6ec99dadf26 GIT binary patch literal 64 zcmZQbEY4+QU|?WmWlUgTtY>CoWMCI&t+>OW#*M7=47TYFmSOkvM@MmaWn9- SCoWMCIy{zCFW$NFfeejF|sf?YH>60vE(J@ PrZTcKGO(1S7MB13J$4H? literal 0 HcmV?d00001 diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/invalid-import-module.wasm b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/invalid-import-module.wasm new file mode 100644 index 0000000000000000000000000000000000000000..ead151ac0c84ad5a2504c1f7752a08e14b989a0e GIT binary patch literal 94 zcmZQbEY4+QU|?WmWlUgTtY?y71GvMW#*M7=47U@l%y7yFfcGPF*2}oFhY2Y iTx^Ui3<3{zCFW$NFfcGPF*2}oKx7#h ix!4$47z7x&8Dv@V5_3}-#h4g)p-Me-3-XIfAPNDJ%oP;? literal 0 HcmV?d00001 diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/invalid-import-name.wasm b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/invalid-import-name.wasm new file mode 100644 index 0000000000000000000000000000000000000000..3c631418294584fecbe13fc122c28dbab5670525 GIT binary patch literal 91 zcmZQbEY4+QU|?WmWlUgTtY;EsWGP84F5xK$id$vol_ln6rZ6xtGchu-b3mjR7`fOO fSr`NuxEW+w@)C1X8O4|wc%e!?a|`l|N+1dWJZlsM literal 0 HcmV?d00001 diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/js-string-builtins.wasm b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/js-string-builtins.wasm new file mode 100644 index 0000000000000000000000000000000000000000..4c4ff4df7f62b145aaf258e6cfb4775a19a9b437 GIT binary patch literal 401 zcmZ8cK~BRk5S+C)PKni0i4U}A!~u@*1#UbbwSpC>niy(V9Qz)Ai5RFujaT6oXwiGGd+vdJkw{yfo)H+#aB<`6BGHNRU Pj^&Zk`=tJ%I!pcliXL*D literal 0 HcmV?d00001 diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/js-wasm-cycle.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/js-wasm-cycle.js new file mode 100644 index 00000000000000..9f14dc04bde41f --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/js-wasm-cycle.js @@ -0,0 +1,17 @@ +function f() { + return 42; +} +export { f }; + +import { mem, tab, glob, func } from "./js-wasm-cycle.wasm"; +assert_false(glob instanceof WebAssembly.Global, "imported global should be unwrapped in ESM integration"); +assert_equals(glob, 1, "unwrapped global should have direct value"); +assert_true(mem instanceof WebAssembly.Memory); +assert_true(tab instanceof WebAssembly.Table); +assert_true(func instanceof Function); + +f = () => { + return 24; +}; + +assert_equals(func(), 42); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/js-wasm-cycle.wasm b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/js-wasm-cycle.wasm new file mode 100644 index 0000000000000000000000000000000000000000..77a3b86ab67528e404eef4aae4a7c76511b1f863 GIT binary patch literal 101 zcmWN{K@LSQ6a~r77$x)=z630v?nfBvd^j^*`v u>2JRb)f_njVhC04aETDkT0Ur)rG-iuf`J@e|BY$cdV!AT>Op6z$dSE}6%fk+ literal 0 HcmV?d00001 diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/log.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/log.js new file mode 100644 index 00000000000000..0c4f5ed519b0fd --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/log.js @@ -0,0 +1 @@ +export function logExec() { log.push("executed"); } diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/mutable-global-export.wasm b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/mutable-global-export.wasm new file mode 100644 index 0000000000000000000000000000000000000000..89c478b19151d0abdc0c6fdb24935df8a2d7d1e7 GIT binary patch literal 378 zcmY+Ay-veG5QJxTFNvH>3JNMLWGQ)pKtt;SXy}kqA;pel(bx$h&JR$ShvhX+Vl7Mp zD~)vD?G&?vd{Yqs&t1j_8Q5g5v4J5Q?Kx1iA4|jZ3;u&))Y`?QCTH@4$Ns3=*7>q5 z=6Sg-6vN%@>gM+FvVN_V(Wa>H%k?rZf#~`8=Ggw{=IeIiZP)TczAB)@C)Y=UDZIl3 zK1PagmLSAP7-A+8Vo5Z_I;EePF~yy0CJYzo8L$JkARS1r-K)33C*3Nq3SK*$^6?Z; t{-@Kw;bf{HqE)e9?Am+9Iy#VV!gu9f30K+)gG<4OpwR^I>s literal 0 HcmV?d00001 diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/mutable-global-reexport.wasm b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/mutable-global-reexport.wasm new file mode 100644 index 0000000000000000000000000000000000000000..b06f94a75d3c48e753a3f5860643af3e8820a660 GIT binary patch literal 428 zcmaJ-!Ab)$6rA^xwb)g$D81-Gtk+iR$%7ysY!UQY@YJUCQH1QSwA)tjkS`ZZy1@!7 z=90`z=4CQ4%Zvcfk(!Xh1myfqj$iq_cb%tU0|2zZ2$TQ- literal 0 HcmV?d00001 diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/wasm-import-from-wasm.wasm b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/wasm-import-from-wasm.wasm new file mode 100644 index 0000000000000000000000000000000000000000..652ff143100f832bf3e4e16c4427e17e2a651148 GIT binary patch literal 75 zcmZQbEY4+QU|?WmVN76PU{Yd~($g;ois`0S6yz6`=$7Q`g1CAhf;lHYoq>UwiIIVw Xn~@#Jaji&AW? { + const wasmModuleSource = await import.source("./resources/js-string-builtins.wasm"); + + assert_true(wasmModuleSource instanceof WebAssembly.Module); + + const instance = new WebAssembly.Instance(wasmModuleSource, {}); + + assert_equals(instance.exports.getLength("hello"), 5); + assert_equals( + instance.exports.concatStrings("hello", " world"), + "hello world" + ); + assert_equals(instance.exports.compareStrings("test", "test"), 1); + assert_equals(instance.exports.compareStrings("test", "different"), 0); + assert_equals(instance.exports.testString("hello"), 1); + assert_equals(instance.exports.testString(42), 0); +}, "String builtins should be supported in source phase imports"); + +promise_test(async () => { + const wasmModuleSource = await import.source("./resources/js-string-builtins.wasm"); + + const exports = WebAssembly.Module.exports(wasmModuleSource); + const exportNames = exports.map((exp) => exp.name); + + assert_true(exportNames.includes("getLength")); + assert_true(exportNames.includes("concatStrings")); + assert_true(exportNames.includes("compareStrings")); + assert_true(exportNames.includes("testString")); +}, "Source phase import should properly expose string builtin exports"); + +promise_test(async () => { + const wasmModuleSource = await import.source("./resources/js-string-builtins.wasm"); + + const imports = WebAssembly.Module.imports(wasmModuleSource); + + assert_equals(imports.length, 0); +}, "Source phase import should handle string builtin import reflection correctly"); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/source-phase.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/source-phase.tentative.any.js new file mode 100644 index 00000000000000..59a71226530ac1 --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/source-phase.tentative.any.js @@ -0,0 +1,42 @@ +// META: global=window,dedicatedworker,jsshell,shadowrealm + +promise_test(async () => { + const exportedNamesSource = await import.source("./resources/exports.wasm"); + + assert_true(exportedNamesSource instanceof WebAssembly.Module); + const AbstractModuleSource = Object.getPrototypeOf(WebAssembly.Module); + assert_equals(AbstractModuleSource.name, "AbstractModuleSource"); + assert_true(exportedNamesSource instanceof AbstractModuleSource); + + assert_array_equals( + WebAssembly.Module.exports(exportedNamesSource) + .map(({ name }) => name) + .sort(), + [ + "a\u200Bb\u0300c", + "func", + "glob", + "mem", + "tab", + "value with spaces", + "🎯test-func!", + ] + ); + + const wasmImportFromWasmSource = await import.source( + "./resources/wasm-import-from-wasm.wasm" + ); + + assert_true(wasmImportFromWasmSource instanceof WebAssembly.Module); + + let logged = false; + const instance = await WebAssembly.instantiate(wasmImportFromWasmSource, { + "./wasm-export-to-wasm.wasm": { + log() { + logged = true; + }, + }, + }); + instance.exports.logExec(); + assert_true(logged, "WebAssembly instance should execute imported function"); +}, "Source phase imports"); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/string-builtins.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/string-builtins.tentative.any.js new file mode 100644 index 00000000000000..bac8fd92727437 --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/string-builtins.tentative.any.js @@ -0,0 +1,12 @@ +// META: global=window,dedicatedworker,jsshell,shadowrealm + +promise_test(async () => { + const wasmModule = await import("./resources/js-string-builtins.wasm"); + + assert_equals(wasmModule.getLength("hello"), 5); + assert_equals(wasmModule.concatStrings("hello", " world"), "hello world"); + assert_equals(wasmModule.compareStrings("test", "test"), 1); + assert_equals(wasmModule.compareStrings("test", "different"), 0); + assert_equals(wasmModule.testString("hello"), 1); + assert_equals(wasmModule.testString(42), 0); +}, "String builtins should be supported in imports in ESM integration"); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/v128-tdz.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/v128-tdz.tentative.any.js new file mode 100644 index 00000000000000..5d11e590148851 --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/v128-tdz.tentative.any.js @@ -0,0 +1,11 @@ +// META: global=window,dedicatedworker,jsshell,shadowrealm + +promise_test(async () => { + const exporterModule = await import("./resources/mutable-global-export.wasm"); + const reexporterModule = await import( + "./resources/mutable-global-reexport.wasm" + ); + + assert_throws_js(ReferenceError, () => exporterModule.v128Export); + assert_throws_js(ReferenceError, () => reexporterModule.reexportedV128Export); +}, "v128 global exports should cause TDZ errors"); diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/wasm-import-wasm-export.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/wasm-import-wasm-export.tentative.any.js new file mode 100644 index 00000000000000..2c1a1446ee4987 --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/wasm-import-wasm-export.tentative.any.js @@ -0,0 +1,14 @@ +// META: global=window,dedicatedworker,jsshell,shadowrealm + +promise_test(async () => { + globalThis.log = []; + + const { logExec } = await import("./resources/wasm-import-from-wasm.wasm"); + logExec(); + + assert_equals(globalThis.log.length, 1, "log should have one entry"); + assert_equals(globalThis.log[0], "executed"); + + // Clean up + delete globalThis.log; +}, "Check import and export between WebAssembly modules"); diff --git a/test/fixtures/wpt/wasm/resources/load_wasm.js b/test/fixtures/wpt/wasm/resources/load_wasm.js new file mode 100644 index 00000000000000..7f280ac032f40a --- /dev/null +++ b/test/fixtures/wpt/wasm/resources/load_wasm.js @@ -0,0 +1,12 @@ +// Copyright 2016 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function createWasmModule() { + return fetch('/wasm/incrementer.wasm') + .then(response => { + if (!response.ok) throw new Error(response.statusText); + return response.arrayBuffer(); + }) + .then(WebAssembly.compile); +} diff --git a/test/wpt/status/wasm/jsapi.json b/test/wpt/status/wasm/jsapi.json new file mode 100644 index 00000000000000..4d7f5c266dde5b --- /dev/null +++ b/test/wpt/status/wasm/jsapi.json @@ -0,0 +1,56 @@ +{ + "esm-integration/global-exports-live-bindings.tentative.any.js": { + "skip": "Live bindings unsupported pending V8 WebAssemblyModuleRecord" + }, + "esm-integration/v128-tdz.tentative.any.js": { + "skip": "v128 undefined Wasm bindings not yet supported in V8" + }, + "esm-integration/namespace-instance.tentative.any.js": { + "skip": "pending https://github.com/nodejs/node/pull/59024" + }, + "esm-integration/reserved-import-names.tentative.any.js": { + "skip": "pending https://github.com/nodejs/node/pull/59020" + }, + "esm-integration/source-phase-string-builtins.tentative.any.js": { + "skip": "pending https://github.com/nodejs/node/pull/59020" + }, + "esm-integration/string-builtins.tentative.any.js": { + "skip": "pending https://github.com/nodejs/node/pull/59020" + }, + "exception/getArg.tentative.any.js": { + "skip": "track - still tentative / unsupported" + }, + "function/call.tentative.any.js": { + "skip": "track - still tentative / unsupported" + }, + "function/constructor.tentative.any.js": { + "skip": "track - still tentative / unsupported" + }, + "function/table.tentative.any.js": { + "skip": "track - still tentative / unsupported" + }, + "function/type.tentative.any.js": { + "skip": "track - still tentative / unsupported" + }, + "global/type.tentative.any.js": { + "skip": "track - still tentative / unsupported" + }, + "idlharness.any.js": { + "skip": "track - still tentative / unsupported" + }, + "memory/constructor-types.tentative.any.js": { + "skip": "track - still tentative / unsupported" + }, + "memory/type.tentative.any.js": { + "skip": "track - still tentative / unsupported" + }, + "table/constructor-types.tentative.any.js": { + "skip": "track - still tentative / unsupported" + }, + "table/type.tentative.any.js": { + "skip": "track - still tentative / unsupported" + }, + "tag/type.tentative.any.js": { + "skip": "track - still tentative / unsupported" + } +} diff --git a/test/wpt/test-wasm-jsapi.mjs b/test/wpt/test-wasm-jsapi.mjs new file mode 100644 index 00000000000000..e4ebb9c53e7373 --- /dev/null +++ b/test/wpt/test-wasm-jsapi.mjs @@ -0,0 +1,21 @@ +// Flags: --experimental-wasm-modules +import * as fixtures from '../common/fixtures.mjs'; +import { ok } from 'node:assert'; +import { WPTRunner } from '../common/wpt.js'; + +// Verify we have Wasm SIMD support by importing a Wasm with SIMD +// since Wasm SIMD is not supported on older architectures such as IBM Power8. +let supportsSimd = false; +try { + await import(fixtures.fileURL('es-modules/globals.wasm')); + supportsSimd = true; +} catch (e) { + ok(e instanceof WebAssembly.CompileError); + ok(e.message.includes('SIMD unsupported')); +} + +if (supportsSimd) { + const runner = new WPTRunner('wasm/jsapi'); + runner.setFlags(['--experimental-wasm-modules']); + runner.runJsTests(); +} From 7cb343711d3e8762e0bf6e85fbd9f12d8bcf905d Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Mon, 14 Jul 2025 11:08:56 -0700 Subject: [PATCH 2/2] include WebAssembly/esm-integraiton#113 --- .../mutable-global-sharing.tentative.any.js | 2 ++ .../esm-integration/resources/source-phase-identity.js | 6 ++++++ .../jsapi/esm-integration/source-phase.tentative.any.js | 7 +++++++ 3 files changed, 15 insertions(+) create mode 100644 test/fixtures/wpt/wasm/jsapi/esm-integration/resources/source-phase-identity.js diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/mutable-global-sharing.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/mutable-global-sharing.tentative.any.js index c636da929b3b2f..d76c69ad5d2333 100644 --- a/test/fixtures/wpt/wasm/jsapi/esm-integration/mutable-global-sharing.tentative.any.js +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/mutable-global-sharing.tentative.any.js @@ -1,3 +1,5 @@ +// META: global=window,dedicatedworker,jsshell,shadowrealm + promise_test(async () => { const exporterModule = await import("./resources/mutable-global-export.wasm"); const reexporterModule = await import( diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/source-phase-identity.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/source-phase-identity.js new file mode 100644 index 00000000000000..643d15b2f8912e --- /dev/null +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/resources/source-phase-identity.js @@ -0,0 +1,6 @@ +import * as mod1 from './exports.wasm'; +import * as mod2 from './exports.wasm'; +import source mod3 from './exports.wasm'; +import source mod4 from './exports.wasm'; + +export { mod1, mod2, mod3, mod4 } diff --git a/test/fixtures/wpt/wasm/jsapi/esm-integration/source-phase.tentative.any.js b/test/fixtures/wpt/wasm/jsapi/esm-integration/source-phase.tentative.any.js index 59a71226530ac1..ad45391f7f9c9f 100644 --- a/test/fixtures/wpt/wasm/jsapi/esm-integration/source-phase.tentative.any.js +++ b/test/fixtures/wpt/wasm/jsapi/esm-integration/source-phase.tentative.any.js @@ -40,3 +40,10 @@ promise_test(async () => { instance.exports.logExec(); assert_true(logged, "WebAssembly instance should execute imported function"); }, "Source phase imports"); + +promise_test(async () => { + const { mod1, mod2, mod3, mod4 } = await import('./resources/source-phase-identity.js'); + + assert_equals(mod1, mod2); + assert_equals(mod3, mod4); +}, "Source phase identities");