| //@ runWebAssemblySuite("--useWebAssemblyReferences=true") |
| 'use strict'; |
| |
| let console = { log: print } |
| |
| let hostrefs = {}; |
| let hostsym = Symbol("hostref"); |
| function hostref(s) { |
| if (! (s in hostrefs)) hostrefs[s] = {[hostsym]: s}; |
| return hostrefs[s]; |
| } |
| function is_hostref(x) { |
| return (x !== null && hostsym in x) ? 1 : 0; |
| } |
| function is_funcref(x) { |
| return typeof x === "function" ? 1 : 0; |
| } |
| function eq_ref(x, y) { |
| return x === y ? 1 : 0; |
| } |
| |
| let spectest = { |
| hostref: hostref, |
| is_hostref: is_hostref, |
| is_funcref: is_funcref, |
| eq_ref: eq_ref, |
| print: console.log.bind(console), |
| print_i32: console.log.bind(console), |
| print_i32_f32: console.log.bind(console), |
| print_f64_f64: console.log.bind(console), |
| print_f32: console.log.bind(console), |
| print_f64: console.log.bind(console), |
| global_i32: 666, |
| global_f32: 666, |
| global_f64: 666, |
| table: new WebAssembly.Table({initial: 10, maximum: 20, element: 'anyfunc'}), |
| memory: new WebAssembly.Memory({initial: 1, maximum: 2}) |
| }; |
| |
| let handler = { |
| get(target, prop) { |
| return (prop in target) ? target[prop] : {}; |
| } |
| }; |
| let registry = new Proxy({spectest}, handler); |
| |
| function register(name, instance) { |
| registry[name] = instance.exports; |
| } |
| |
| function module(bytes, valid = true) { |
| let buffer = new ArrayBuffer(bytes.length); |
| let view = new Uint8Array(buffer); |
| for (let i = 0; i < bytes.length; ++i) { |
| view[i] = bytes.charCodeAt(i); |
| } |
| let validated; |
| try { |
| validated = WebAssembly.validate(buffer); |
| } catch (e) { |
| console.log(e) |
| throw new Error("Wasm validate throws"); |
| } |
| if (validated !== valid) { |
| //throw new Error("Wasm validate failure" + (valid ? "" : " expected")); |
| } |
| return new WebAssembly.Module(buffer); |
| } |
| |
| function instance(bytes, imports = registry) { |
| return new WebAssembly.Instance(module(bytes), imports); |
| } |
| |
| function call(instance, name, args) { |
| return instance.exports[name](...args); |
| } |
| |
| function get(instance, name) { |
| let v = instance.exports[name]; |
| return (v instanceof WebAssembly.Global) ? v.value : v; |
| } |
| |
| function exports(instance) { |
| return {module: instance.exports, spectest: spectest}; |
| } |
| |
| function run(action) { |
| action(); |
| } |
| |
| function assert_malformed(bytes) { |
| try { module(bytes, false) } catch (e) { |
| if (e instanceof WebAssembly.CompileError) return; |
| } |
| throw new Error("Wasm decoding failure expected"); |
| } |
| |
| function assert_invalid(bytes) { |
| try { module(bytes, false) } catch (e) { |
| if (e instanceof WebAssembly.CompileError) return; |
| } |
| throw new Error("Wasm validation failure expected"); |
| } |
| |
| function assert_unlinkable(bytes) { |
| let mod = module(bytes); |
| try { new WebAssembly.Instance(mod, registry) } catch (e) { |
| if (e instanceof WebAssembly.LinkError) return; |
| } |
| throw new Error("Wasm linking failure expected"); |
| } |
| |
| function assert_uninstantiable(bytes) { |
| let mod = module(bytes); |
| try { new WebAssembly.Instance(mod, registry) } catch (e) { |
| if (e instanceof WebAssembly.RuntimeError) return; |
| } |
| throw new Error("Wasm trap expected"); |
| } |
| |
| function assert_trap(action) { |
| try { action() } catch (e) { |
| if (e instanceof WebAssembly.RuntimeError) return; |
| } |
| throw new Error("Wasm trap expected"); |
| } |
| |
| let StackOverflow; |
| try { (function f() { 1 + f() })() } catch (e) { StackOverflow = e.constructor } |
| |
| function assert_exhaustion(action) { |
| try { action() } catch (e) { |
| if (e instanceof StackOverflow) return; |
| } |
| throw new Error("Wasm resource exhaustion expected"); |
| } |
| |
| function assert_return(action, expected) { |
| let actual = action(); |
| if (!Object.is(actual, expected)) { |
| throw new Error("Wasm return value " + expected + " expected, got " + actual); |
| }; |
| } |
| |
| function assert_return_canonical_nan(action) { |
| let actual = action(); |
| // Note that JS can't reliably distinguish different NaN values, |
| // so there's no good way to test that it's a canonical NaN. |
| if (!Number.isNaN(actual)) { |
| throw new Error("Wasm return value NaN expected, got " + actual); |
| }; |
| } |
| |
| function assert_return_arithmetic_nan(action) { |
| // Note that JS can't reliably distinguish different NaN values, |
| // so there's no good way to test for specific bitpatterns here. |
| let actual = action(); |
| if (!Number.isNaN(actual)) { |
| throw new Error("Wasm return value NaN expected, got " + actual); |
| }; |
| } |
| |
| function assert_return_ref(action) { |
| let actual = action(); |
| if (actual === null || typeof actual !== "object" && typeof actual !== "function") { |
| throw new Error("Wasm reference return value expected, got " + actual); |
| }; |
| } |
| |
| function assert_return_func(action) { |
| let actual = action(); |
| if (typeof actual !== "function") { |
| throw new Error("Wasm function return value expected, got " + actual); |
| }; |
| } |
| |
| // ref_null.wast:1 |
| let $1 = instance("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x89\x80\x80\x80\x00\x02\x60\x00\x01\x6f\x60\x00\x01\x70\x03\x83\x80\x80\x80\x00\x02\x00\x01\x06\x89\x80\x80\x80\x00\x02\x6f\x00\xd0\x0b\x70\x00\xd0\x0b\x07\x94\x80\x80\x80\x00\x02\x06\x61\x6e\x79\x72\x65\x66\x00\x00\x07\x66\x75\x6e\x63\x72\x65\x66\x00\x01\x0a\x91\x80\x80\x80\x00\x02\x83\x80\x80\x80\x00\x00\xd0\x0b\x83\x80\x80\x80\x00\x00\xd0\x0b"); |
| |
| // ref_null.wast:9 |
| assert_return(() => call($1, "anyref", []), null); |
| |
| // ref_null.wast:10 |
| assert_return(() => call($1, "funcref", []), null); |