Page MenuHomePhorge

test_wasm_webassembly_api.mjs
No OneTemporary

Size
5 KB
Referenced Files
None
Subscribers
None

test_wasm_webassembly_api.mjs

import { readFileSync } from 'ant:fs';
function assert(condition, message) {
if (!condition) throw new Error(message);
}
function fixture(path) {
return readFileSync(import.meta.dirname + '/../' + path);
}
const api = globalThis.WebAssembly;
assert(api && typeof api === 'object', 'globalThis.WebAssembly should exist');
for (const name of ['Global', 'Instance', 'Memory', 'Module', 'Table', 'Tag', 'Exception', 'CompileError', 'LinkError', 'RuntimeError']) {
assert(typeof api[name] === 'function', `WebAssembly.${name} should exist`);
}
const incrementer = fixture('wpt/wasm/webapi/resources/incrementer.wasm');
const tableExportFixture = new Uint8Array([
0, 97, 115, 109, 1, 0, 0, 0, 1, 9, 2, 96, 0, 1, 127, 96, 0, 1, 127, 3, 3, 2, 0, 1, 4, 4, 1, 112, 0, 2, 7, 24, 3, 5, 115, 101, 118, 101, 110, 0, 0,
4, 110, 105, 110, 101, 0, 1, 5, 116, 97, 98, 108, 101, 1, 0, 9, 8, 1, 0, 65, 0, 11, 2, 0, 1, 10, 11, 2, 4, 0, 65, 7, 11, 4, 0, 65, 9, 11, 0, 21, 4,
110, 97, 109, 101, 1, 14, 2, 0, 5, 115, 101, 118, 101, 110, 1, 4, 110, 105, 110, 101
]);
const throwingImportFixture = new Uint8Array([
0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 2, 12, 1, 3, 101, 110, 118, 4, 102, 97, 105, 108, 0, 0, 3, 2, 1, 0, 7, 7, 1, 3, 114, 117, 110, 0, 1,
10, 6, 1, 4, 0, 16, 0, 11
]);
assert(WebAssembly.validate(incrementer) === true, 'incrementer.wasm should validate');
const module = new WebAssembly.Module(incrementer);
const descriptors = WebAssembly.Module.exports(module);
assert(Array.isArray(descriptors), 'WebAssembly.Module.exports() should return an array');
assert(
descriptors.some(entry => entry && entry.name === 'increment' && entry.kind === 'function'),
'incrementer.wasm should export increment()'
);
const instance = new WebAssembly.Instance(module);
assert(typeof instance.exports.increment === 'function', 'instance.exports.increment should exist');
assert(instance.exports.increment(41) === 42, 'increment(41) should return 42');
const tableModule = new WebAssembly.Module(tableExportFixture);
const tableInstance = new WebAssembly.Instance(tableModule);
assert(tableInstance.exports.table.length === 2, 'exported table should expose its length');
const firstTableEntry = tableInstance.exports.table.get(0);
const secondTableEntry = tableInstance.exports.table.get(1);
assert(typeof firstTableEntry === 'function', 'table.get(0) should return a callable function');
assert(typeof secondTableEntry === 'function', 'table.get(1) should return a callable function');
assert(firstTableEntry() === 7, 'table.get(0) should invoke the first table function');
assert(secondTableEntry() === 9, 'table.get(1) should invoke the second table function');
tableInstance.exports.table.set(0, tableInstance.exports.nine);
assert(tableInstance.exports.table.get(0)() === 9, 'table.set() should accept wasm-exported functions');
const throwingModule = new WebAssembly.Module(throwingImportFixture);
let sawPrimitiveThrow = false;
try {
new WebAssembly.Instance(throwingModule, {
env: {
fail() {
throw Infinity;
}
}
}).exports.run();
} catch (error) {
sawPrimitiveThrow = true;
assert(error === Infinity, 'import throws should preserve primitive thrown values');
}
assert(sawPrimitiveThrow, 'primitive import throws should escape the wasm call');
const thrownError = new Error('import boom');
let sawErrorThrow = false;
try {
new WebAssembly.Instance(throwingModule, {
env: {
fail() {
throw thrownError;
}
}
}).exports.run();
} catch (error) {
sawErrorThrow = true;
assert(error === thrownError, 'import throws should preserve original Error objects');
}
assert(sawErrorThrow, 'Error import throws should escape the wasm call');
const thrownStatus = {
name: 'ExitStatus',
message: 'Program terminated with exit(1)',
status: 1
};
let sawErrorlikeThrow = false;
try {
new WebAssembly.Instance(throwingModule, {
env: {
fail() {
throw thrownStatus;
}
}
}).exports.run();
} catch (error) {
sawErrorlikeThrow = true;
assert(error === thrownStatus, 'import throws should preserve original error-like objects');
assert(error.stack === undefined, 'error-like import throws should not grow a synthetic stack');
}
assert(sawErrorlikeThrow, 'error-like import throws should escape the wasm call');
const compiled = await WebAssembly.compile(incrementer);
assert(compiled instanceof WebAssembly.Module, 'WebAssembly.compile() should resolve a module');
const instantiated = await WebAssembly.instantiate(incrementer);
assert(instantiated.module instanceof WebAssembly.Module, 'instantiate(bytes) should return a module');
assert(instantiated.instance instanceof WebAssembly.Instance, 'instantiate(bytes) should return an instance');
assert(instantiated.instance.exports.increment(9) === 10, 'instantiate(bytes) should wire exports');
const global = new WebAssembly.Global({ value: 'i32', mutable: true }, 7);
assert(global.value === 7, 'WebAssembly.Global should expose its initial value');
global.value = 11;
assert(global.value === 11, 'WebAssembly.Global should accept writes');
assert(global.valueOf() === 11, 'WebAssembly.Global.prototype.valueOf() should read the value');
const invalid = new Uint8Array([0x00, 0x61, 0x62, 0x63]);
assert(WebAssembly.validate(invalid) === false, 'invalid wasm bytes should fail validation');
let sawCompileError = false;
try {
new WebAssembly.Module(invalid);
} catch (error) {
sawCompileError = true;
assert(error instanceof WebAssembly.CompileError || error?.name === 'CompileError', 'invalid module should throw CompileError');
}
assert(sawCompileError, 'invalid module construction should fail');
console.log('wasm:webassembly-api:ok');

File Metadata

Mime Type
application/javascript
Expires
Sat, May 2, 4:19 PM (1 d, 22 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
544489
Default Alt Text
test_wasm_webassembly_api.mjs (5 KB)

Event Timeline