MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 136 lines 5.7 kB view raw
1import { readFileSync } from 'ant:fs'; 2 3function assert(condition, message) { 4 if (!condition) throw new Error(message); 5} 6 7function fixture(path) { 8 return readFileSync(import.meta.dirname + '/../' + path); 9} 10 11const api = globalThis.WebAssembly; 12 13assert(api && typeof api === 'object', 'globalThis.WebAssembly should exist'); 14 15for (const name of ['Global', 'Instance', 'Memory', 'Module', 'Table', 'Tag', 'Exception', 'CompileError', 'LinkError', 'RuntimeError']) { 16 assert(typeof api[name] === 'function', `WebAssembly.${name} should exist`); 17} 18 19const incrementer = fixture('wpt/wasm/webapi/resources/incrementer.wasm'); 20const tableExportFixture = new Uint8Array([ 21 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, 22 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, 23 110, 97, 109, 101, 1, 14, 2, 0, 5, 115, 101, 118, 101, 110, 1, 4, 110, 105, 110, 101 24]); 25const throwingImportFixture = new Uint8Array([ 26 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, 27 10, 6, 1, 4, 0, 16, 0, 11 28]); 29 30assert(WebAssembly.validate(incrementer) === true, 'incrementer.wasm should validate'); 31 32const module = new WebAssembly.Module(incrementer); 33const descriptors = WebAssembly.Module.exports(module); 34assert(Array.isArray(descriptors), 'WebAssembly.Module.exports() should return an array'); 35assert( 36 descriptors.some(entry => entry && entry.name === 'increment' && entry.kind === 'function'), 37 'incrementer.wasm should export increment()' 38); 39 40const instance = new WebAssembly.Instance(module); 41assert(typeof instance.exports.increment === 'function', 'instance.exports.increment should exist'); 42assert(instance.exports.increment(41) === 42, 'increment(41) should return 42'); 43 44const tableModule = new WebAssembly.Module(tableExportFixture); 45const tableInstance = new WebAssembly.Instance(tableModule); 46assert(tableInstance.exports.table.length === 2, 'exported table should expose its length'); 47const firstTableEntry = tableInstance.exports.table.get(0); 48const secondTableEntry = tableInstance.exports.table.get(1); 49assert(typeof firstTableEntry === 'function', 'table.get(0) should return a callable function'); 50assert(typeof secondTableEntry === 'function', 'table.get(1) should return a callable function'); 51assert(firstTableEntry() === 7, 'table.get(0) should invoke the first table function'); 52assert(secondTableEntry() === 9, 'table.get(1) should invoke the second table function'); 53tableInstance.exports.table.set(0, tableInstance.exports.nine); 54assert(tableInstance.exports.table.get(0)() === 9, 'table.set() should accept wasm-exported functions'); 55 56const throwingModule = new WebAssembly.Module(throwingImportFixture); 57 58let sawPrimitiveThrow = false; 59try { 60 new WebAssembly.Instance(throwingModule, { 61 env: { 62 fail() { 63 throw Infinity; 64 } 65 } 66 }).exports.run(); 67} catch (error) { 68 sawPrimitiveThrow = true; 69 assert(error === Infinity, 'import throws should preserve primitive thrown values'); 70} 71assert(sawPrimitiveThrow, 'primitive import throws should escape the wasm call'); 72 73const thrownError = new Error('import boom'); 74let sawErrorThrow = false; 75try { 76 new WebAssembly.Instance(throwingModule, { 77 env: { 78 fail() { 79 throw thrownError; 80 } 81 } 82 }).exports.run(); 83} catch (error) { 84 sawErrorThrow = true; 85 assert(error === thrownError, 'import throws should preserve original Error objects'); 86} 87assert(sawErrorThrow, 'Error import throws should escape the wasm call'); 88 89const thrownStatus = { 90 name: 'ExitStatus', 91 message: 'Program terminated with exit(1)', 92 status: 1 93}; 94let sawErrorlikeThrow = false; 95try { 96 new WebAssembly.Instance(throwingModule, { 97 env: { 98 fail() { 99 throw thrownStatus; 100 } 101 } 102 }).exports.run(); 103} catch (error) { 104 sawErrorlikeThrow = true; 105 assert(error === thrownStatus, 'import throws should preserve original error-like objects'); 106 assert(error.stack === undefined, 'error-like import throws should not grow a synthetic stack'); 107} 108assert(sawErrorlikeThrow, 'error-like import throws should escape the wasm call'); 109 110const compiled = await WebAssembly.compile(incrementer); 111assert(compiled instanceof WebAssembly.Module, 'WebAssembly.compile() should resolve a module'); 112 113const instantiated = await WebAssembly.instantiate(incrementer); 114assert(instantiated.module instanceof WebAssembly.Module, 'instantiate(bytes) should return a module'); 115assert(instantiated.instance instanceof WebAssembly.Instance, 'instantiate(bytes) should return an instance'); 116assert(instantiated.instance.exports.increment(9) === 10, 'instantiate(bytes) should wire exports'); 117 118const global = new WebAssembly.Global({ value: 'i32', mutable: true }, 7); 119assert(global.value === 7, 'WebAssembly.Global should expose its initial value'); 120global.value = 11; 121assert(global.value === 11, 'WebAssembly.Global should accept writes'); 122assert(global.valueOf() === 11, 'WebAssembly.Global.prototype.valueOf() should read the value'); 123 124const invalid = new Uint8Array([0x00, 0x61, 0x62, 0x63]); 125assert(WebAssembly.validate(invalid) === false, 'invalid wasm bytes should fail validation'); 126 127let sawCompileError = false; 128try { 129 new WebAssembly.Module(invalid); 130} catch (error) { 131 sawCompileError = true; 132 assert(error instanceof WebAssembly.CompileError || error?.name === 'CompileError', 'invalid module should throw CompileError'); 133} 134assert(sawCompileError, 'invalid module construction should fail'); 135 136console.log('wasm:webassembly-api:ok');