Skip to content

test: WPT for Wasm jsapi including new ESM Integration tests #59034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion test/common/wpt.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
16 changes: 13 additions & 3 deletions test/common/wpt/worker.js
Original file line number Diff line number Diff line change
@@ -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');

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
});
}
Original file line number Diff line number Diff line change
@@ -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");
Original file line number Diff line number Diff line change
@@ -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");
Original file line number Diff line number Diff line change
@@ -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");
Original file line number Diff line number Diff line change
@@ -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)");
Original file line number Diff line number Diff line change
@@ -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");
Original file line number Diff line number Diff line change
@@ -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");
Loading
Loading