diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /js/src/jit-test/tests/wasm/function-references | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/wasm/function-references')
11 files changed, 799 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/function-references/as-non-null.js b/js/src/jit-test/tests/wasm/function-references/as-non-null.js new file mode 100644 index 0000000000..1280c8ee06 --- /dev/null +++ b/js/src/jit-test/tests/wasm/function-references/as-non-null.js @@ -0,0 +1,13 @@ +// |jit-test| skip-if: !wasmFunctionReferencesEnabled() + +let {checkNonNull} = wasmEvalText(`(module + (func (export "checkNonNull") (param externref) (result (ref extern)) + local.get 0 + ref.as_non_null + ) +)`).exports; + +assertErrorMessage(() => checkNonNull(null), WebAssembly.RuntimeError, /dereferencing null pointer/); +for (let val of WasmNonNullExternrefValues) { + assertEq(checkNonNull(val), val, `is non-null`); +} diff --git a/js/src/jit-test/tests/wasm/function-references/binary.js b/js/src/jit-test/tests/wasm/function-references/binary.js new file mode 100644 index 0000000000..91cf807dc4 --- /dev/null +++ b/js/src/jit-test/tests/wasm/function-references/binary.js @@ -0,0 +1,52 @@ +// |jit-test| skip-if: !wasmFunctionReferencesEnabled() + +load(libdir + "wasm-binary.js"); + +const v2vSig = {args:[], ret:VoidCode}; +const v2vSigSection = sigSection([v2vSig]); + +function checkInvalid(binary, errorMessage) { + assertErrorMessage(() => new WebAssembly.Module(binary), + WebAssembly.CompileError, + errorMessage); +} + +// The immediate of ref.null is a heap type, not a general reference type + +const invalidRefNullHeapBody = moduleWithSections([ + v2vSigSection, + declSection([0]), + bodySection([ + funcBody({locals:[], body:[ + RefNullCode, + OptRefCode, + AnyFuncCode, + DropCode, + ]}) + ]) +]); +checkInvalid(invalidRefNullHeapBody, /invalid heap type/); + +const invalidRefNullHeapElem = moduleWithSections([ + generalElemSection([ + { + flag: PassiveElemExpr, + typeCode: AnyFuncCode, + elems: [ + [RefNullCode, OptRefCode, AnyFuncCode, EndCode] + ] + } + ]) +]); +checkInvalid(invalidRefNullHeapElem, /invalid heap type/); + +const invalidRefNullHeapGlobal = moduleWithSections([ + globalSection([ + { + valType: AnyFuncCode, + flag: 0, + initExpr: [RefNullCode, OptRefCode, AnyFuncCode, EndCode] + } + ]) +]); +checkInvalid(invalidRefNullHeapGlobal, /invalid heap type/); diff --git a/js/src/jit-test/tests/wasm/function-references/br-non-null.js b/js/src/jit-test/tests/wasm/function-references/br-non-null.js new file mode 100644 index 0000000000..371cdaa40a --- /dev/null +++ b/js/src/jit-test/tests/wasm/function-references/br-non-null.js @@ -0,0 +1,76 @@ +// |jit-test| skip-if: !wasmFunctionReferencesEnabled() + +// br_on_non_null from constant +wasmValidateText(`(module + (func + block (result (ref extern)) + ref.null extern + br_on_non_null 0 + return + end + drop + ) +)`); + +// br_on_non_null from parameter +wasmValidateText(`(module + (func (param externref) (result (ref extern)) + local.get 0 + br_on_non_null 0 + unreachable + ) +)`); + +// br_on_null with multiple results +wasmValidateText(`(module + (func (param (ref null extern) (ref extern)) (result i32 i32 i32 (ref extern)) + i32.const 0 + i32.const 1 + i32.const 2 + local.get 0 + br_on_non_null 0 + local.get 1 + ) +)`); + +// no block type +wasmFailValidateText(`(module + (func + block + ref.null extern + br_on_non_null 0 + end + ) +)`, /type mismatch: target block type expected to be \[_, ref\]/); + +// in dead code +wasmValidateText(`(module + (type $t (func)) + (func (result funcref) + ref.null $t + return + br_on_non_null 0 + ) +)`); + +wasmFailValidateText(`(module + (func + return + br_on_non_null 0 + ) +)`, /type mismatch: target block type expected to be \[_, ref\]/); + +// Test the branch takes the correct path and results are passed correctly +let {ifNull} = wasmEvalText(`(module + (func (export "ifNull") (param externref externref) (result externref) + local.get 0 + br_on_non_null 0 + local.get 1 + ) +)`).exports; + +const DefaultTestVal = "default!test"; +assertEq(ifNull(null, DefaultTestVal), DefaultTestVal); +for (let val of WasmNonNullExternrefValues) { + assertEq(ifNull(val, DefaultTestVal), val); +} diff --git a/js/src/jit-test/tests/wasm/function-references/br-null.js b/js/src/jit-test/tests/wasm/function-references/br-null.js new file mode 100644 index 0000000000..26d1013de2 --- /dev/null +++ b/js/src/jit-test/tests/wasm/function-references/br-null.js @@ -0,0 +1,58 @@ +// |jit-test| skip-if: !wasmFunctionReferencesEnabled() + +// br_on_null from constant +wasmValidateText(`(module + (func + ref.null extern + br_on_null 0 + drop + ) +)`); + +// br_on_null from parameter +wasmValidateText(`(module + (func (param externref) + local.get 0 + br_on_null 0 + drop + ) +)`); + +// br_on_null with single result +wasmValidateText(`(module + (func (result i32) + i32.const 0 + ref.null extern + br_on_null 0 + drop + ) +)`); + +// br_on_null with multiple results +wasmValidateText(`(module + (func (result i32 i32 i32) + i32.const 0 + i32.const 1 + i32.const 2 + ref.null extern + br_on_null 0 + drop + ) +)`); + +// Test the branch takes the correct path and results are passed correctly +let {isNull} = wasmEvalText(`(module + (func (export "isNull") (param externref) (result i32) + i32.const 1 + local.get 0 + br_on_null 0 + drop + drop + i32.const 0 + ) +)`).exports; + +assertEq(isNull(null), 1, `null is null`); +for (let val of WasmNonNullExternrefValues) { + assertEq(isNull(val), 0, `${typeof(val)} is not null`); +} diff --git a/js/src/jit-test/tests/wasm/function-references/call_ref.js b/js/src/jit-test/tests/wasm/function-references/call_ref.js new file mode 100644 index 0000000000..514c3145d6 --- /dev/null +++ b/js/src/jit-test/tests/wasm/function-references/call_ref.js @@ -0,0 +1,100 @@ +// |jit-test| skip-if: !wasmFunctionReferencesEnabled() + +let { plusOne } = wasmEvalText(`(module + (; forward declaration so that ref.func works ;) + (elem declare func $plusOneRef) + (type $t (func (param i32) (result i32))) + + (func $plusOneRef (param i32) (result i32) + (i32.add + local.get 0 + i32.const 1) + ) + + (func (export "plusOne") (param i32) (result i32) + local.get 0 + ref.func $plusOneRef + call_ref $t + ) +)`).exports; + +assertEq(plusOne(3), 4); + +// pass non-funcref type +wasmFailValidateText(`(module + (type $t (func (param i32))) + (func (param $a i32) + local.get $a + call_ref $t + ) +)`, /type mismatch: expression has type i32 but expected \(ref null \d+\)/); + +wasmFailValidateText(`(module + (type $t (func (param externref))) + (func (param $a (ref extern)) + local.get $a + call_ref $t + ) +)`, /type mismatch: expression has type \(ref extern\) but expected \(ref null \d+\)/); + +// pass (non-subtype of) funcref +wasmFailValidateText(`(module + (type $t (func (param i32) (result i32))) + (func (param funcref) + local.get 0 + call_ref $t + ) +)`, /type mismatch: expression has type funcref but expected \(ref null \d+\)/); + +// signature mismatch +wasmFailValidateText(`(module + (type $t (func (param i32) (result i32))) + (elem declare func $plusOneRef) + (func $plusOneRef (param f32) (result f32) + (f32.add + local.get 0 + f32.const 1.0) + ) + + (func (export "plusOne") (param i32) (result i32) + local.get 0 + ref.func $plusOneRef + call_ref $t + ) +)`, /type mismatch: expression has type \(ref \d+\) but expected \(ref null \d+\)/); + +// Cross-instance calls +let { loadInt } = wasmEvalText(`(module + (memory 1 1) + (data (i32.const 0) "\\04\\00\\00\\00") + (func (export "loadInt") (result i32) + i32.const 0 + i32.load offset=0 + ) +)`).exports; + +let { callLoadInt } = wasmEvalText(`(module + (type $t (func (result i32))) + (elem declare func 0) + (import "" "loadInt" (func (result i32))) + (func (export "callLoadInt") (result i32) + ref.func 0 + call_ref $t + ) +)`, {"": { loadInt, }}).exports; + +assertEq(loadInt(), 4); +assertEq(callLoadInt(), 4); + +// Null call. +assertErrorMessage(function() { + let { nullCall } = wasmEvalText(`(module + (type $t (func (param i32) (result i32))) + (func (export "nullCall") (param i32) (result i32) + local.get 0 + ref.null $t + call_ref $t + ) + )`).exports; + nullCall(3); +}, WebAssembly.RuntimeError, /dereferencing null pointer/); diff --git a/js/src/jit-test/tests/wasm/function-references/directives.txt b/js/src/jit-test/tests/wasm/function-references/directives.txt new file mode 100644 index 0000000000..f7d2135421 --- /dev/null +++ b/js/src/jit-test/tests/wasm/function-references/directives.txt @@ -0,0 +1 @@ +|jit-test| test-also=--wasm-compiler=optimizing --wasm-function-references; test-also=--wasm-compiler=baseline --wasm-function-references; include:wasm.js diff --git a/js/src/jit-test/tests/wasm/function-references/disabled.js b/js/src/jit-test/tests/wasm/function-references/disabled.js new file mode 100644 index 0000000000..70a66a937d --- /dev/null +++ b/js/src/jit-test/tests/wasm/function-references/disabled.js @@ -0,0 +1,17 @@ +// |jit-test| skip-if: wasmFunctionReferencesEnabled() + +const { CompileError, validate } = WebAssembly; + +const UNRECOGNIZED_OPCODE_OR_BAD_TYPE = /unrecognized opcode|bad type|\(ref T\) types not enabled/; + +let simpleTests = [ + `(module (func (param (ref 0)) (unreachable)))`, +]; + +// Test that use of function-references fails when function-references is disabled. + +for (let src of simpleTests) { + let bin = wasmTextToBinary(src); + assertEq(validate(bin), false); + wasmCompilationShouldFail(bin, UNRECOGNIZED_OPCODE_OR_BAD_TYPE); +} diff --git a/js/src/jit-test/tests/wasm/function-references/nnl-test.js b/js/src/jit-test/tests/wasm/function-references/nnl-test.js new file mode 100644 index 0000000000..9436b970d5 --- /dev/null +++ b/js/src/jit-test/tests/wasm/function-references/nnl-test.js @@ -0,0 +1,176 @@ +// |jit-test| skip-if: !wasmFunctionReferencesEnabled() + +// Generates combinations of different block types and operations for +// non-defaultable locals (local.set / .tee / .get). +// See the function references specification on the updated algorithm +// for validating non-null references in locals. + +const KINDS = [ + "block", + "loop", + "try", + "catch", + "delegate", + "if", + "else", +] +const INITIALIZED = [ + "nowhere", + "outer", + "inner", + "outer-tee", + "inner-tee", +]; +const USED = [ + "outer", + "inner", + "after-inner", + "after-outer", +]; + +function generateBlock(kind, contents) { + switch (kind) { + case "block": { + return `block\n${contents}end\n` + } + case "loop": { + return `loop\n${contents}end\n` + } + case "try": { + return `try\n${contents}end\n` + } + case "catch": { + return `try\ncatch_all\n${contents}end\n` + } + case "delegate": { + return `try\n${contents}\ndelegate 0\n` + } + case "if": { + return `i32.const 0\nif\n${contents}end\n` + } + case "else": { + return `i32.const 0\nif\nelse\n${contents}end\n` + } + } +} + +// Generate a variation of the module below: +// +// (func +// (block +// $outer +// (block +// $inner +// ) +// $after-inner +// ) +// $after-outer +// ) +// +// Where a local is used and initialized at different points depending on the +// parameters. The block kinds of the inner and outer block may also be +// customized. +function generateModule(outerBlockKind, innerBlockKind, initializedWhere, usedWhere) { + const INITIALIZE_STMT = '(local.set 0 ref.func 0)\n'; + const INITIALIZE_STMT2 = '(drop (local.tee 0 ref.func 0))\n'; + const USE_STMT = '(drop local.get 0)\n'; + + // inner block + let innerBlockContents = ''; + if (initializedWhere === 'inner') { + innerBlockContents += INITIALIZE_STMT; + } else if (initializedWhere === 'inner-tee') { + innerBlockContents += INITIALIZE_STMT2; + } + if (usedWhere === 'inner') { + innerBlockContents += USE_STMT; + } + let innerBlock = generateBlock(innerBlockKind, innerBlockContents); + + // outer block + let outerBlockContents = ''; + if (initializedWhere === 'outer') { + outerBlockContents += INITIALIZE_STMT; + } else if (initializedWhere === 'outer-tee') { + outerBlockContents += INITIALIZE_STMT2; + } + if (usedWhere === 'outer') { + outerBlockContents += USE_STMT; + } + outerBlockContents += innerBlock; + if (usedWhere === 'after-inner') { + outerBlockContents += USE_STMT; + } + let outerBlock = generateBlock(outerBlockKind, outerBlockContents); + + // after outer block + let afterOuterBlock = ''; + if (usedWhere === 'after-outer') { + afterOuterBlock += USE_STMT; + } + + return `(module + (type $t (func)) + (func (export "test") + (local (ref $t)) +${outerBlock}${afterOuterBlock} ) +)`; +} + +const LOGGING = false; + +for (let outer of KINDS) { + for (let inner of KINDS) { + for (let initialized of INITIALIZED) { + for (let used of USED) { + let text = generateModule(outer, inner, initialized, used); + + let expectPass; + switch (initialized) { + case "outer": + case "outer-tee": { + // Defining the local in the outer block makes it valid + // in the outer block, the inner block, and after the + // inner block + expectPass = used !== "after-outer"; + break; + } + case "inner": + case "inner-tee": { + // Defining the local in the inner block makes it valid + // in the inner block + // + // NOTE: an extension to typing could make this valid + // after the inner block in some cases + expectPass = used === "inner"; + break; + } + case "nowhere": { + // Not defining the local makes it always invalid to + // use + expectPass = false; + break; + } + } + + if (LOGGING) { + console.log(); + console.log(`TEST: outer=${outer}, inner=${inner}, initialized=${initialized}, used=${used}`); + console.log(expectPass ? "EXPECT PASS" : "EXPECT FAIL"); + console.log(text); + } + + let binary = wasmTextToBinary(text); + assertEq(WebAssembly.validate(binary), expectPass); + if (!expectPass) { + // Check if the error message is right. + try { + new WebAssembly.Module(binary); + } catch (ex) { + assertEq(true, /local\.get read from unset local/.test(ex.message)); + } + } + } + } + } +} diff --git a/js/src/jit-test/tests/wasm/function-references/non-nullable-table.js b/js/src/jit-test/tests/wasm/function-references/non-nullable-table.js new file mode 100644 index 0000000000..97ab04713c --- /dev/null +++ b/js/src/jit-test/tests/wasm/function-references/non-nullable-table.js @@ -0,0 +1,79 @@ +// |jit-test| skip-if: !wasmFunctionReferencesEnabled() + +// non-null table initialization +var { get1, get2, get3, get4 } = wasmEvalText(`(module + (type $dummy (func)) + (func $dummy) + + (table $t1 10 funcref) + (table $t2 10 funcref (ref.func $dummy)) + (table $t3 10 (ref $dummy) (ref.func $dummy)) + (table $t4 10 (ref func) (ref.func $dummy)) + + (func (export "get1") (result funcref) (table.get $t1 (i32.const 1))) + (func (export "get2") (result funcref) (table.get $t2 (i32.const 4))) + (func (export "get3") (result funcref) (table.get $t3 (i32.const 7))) + (func (export "get4") (result funcref) (table.get $t4 (i32.const 5))) +)`).exports; +assertEq(get1(), null); +assertEq(get2() != null, true); +assertEq(get3() != null, true); +assertEq(get4() != null, true); + +const sampleWasmFunction = get2(); +sampleWasmFunction(); + +// Invalid initializers +for (let i of [ + `(table $t1 10 (ref $dummy) (ref.func $dummy1))`, + `(table $t2 5 10 (ref func))`, + `(table $t3 10 10 (ref func) (ref.null $dummy1))`, + `(table $t4 10 (ref $dummy))`, + '(table $t5 1 (ref $dummy) (ref.null $dummy))', +]) { + wasmFailValidateText(`(module + (type $dummy (func)) + (type $dummy1 (func (param i32))) + (func $dummy1 (param i32)) + + ${i} + )`, /(type mismatch|table with non-nullable references requires initializer)/); +} + +var t1 = new WebAssembly.Table({initial: 10, element: {ref: 'func', nullable: false }}, sampleWasmFunction); +assertEq(t1.get(2) != null, true); +assertThrows(() => { + new WebAssembly.Table({initial: 10, element: {ref: 'func', nullable: false }}); +}); +assertThrows(() => { + new WebAssembly.Table({initial: 10, element: {ref: 'func', nullable: false }}, null); +}); + +var t2 = new WebAssembly.Table({initial: 6, maximum: 20, element: {ref: 'extern', nullable: false }}, {foo: "bar"}); +assertEq(t2.get(1).foo, "bar"); +assertThrows(() => { t2.get(7) }); +assertThrows(() => { t2.grow(9, null) }); +t2.grow(8, {t: "test"}); +assertEq(t2.get(3).foo, "bar"); +assertEq(t2.get(7).t, "test"); +assertThrows(() => { + new WebAssembly.Table({initial: 10, element: {ref: 'extern', nullable: false }}, null); +}); + +// Fail because tables come before globals in the binary format, so tables +// cannot refer to globals. +wasmFailValidateText(`(module + (global $g1 externref) + (table 10 externref (global.get $g1)) +)`, /global.get index out of range/); + +function assertThrows(f) { + var ok = false; + try { + f(); + } catch (exc) { + ok = true; + } + if (!ok) + throw new TypeError("Assertion failed: " + f + " did not throw as expected"); +} diff --git a/js/src/jit-test/tests/wasm/function-references/non-nullable.js b/js/src/jit-test/tests/wasm/function-references/non-nullable.js new file mode 100644 index 0000000000..afe1d3cb43 --- /dev/null +++ b/js/src/jit-test/tests/wasm/function-references/non-nullable.js @@ -0,0 +1,176 @@ +// |jit-test| skip-if: !wasmFunctionReferencesEnabled() + +// non-null values are subtype of null values +wasmValidateText(`(module + (func (param $a (ref extern)) + local.get $a + (block (param (ref null extern)) + drop + ) + ) +)`); + +// null values are not subtype of non-null values +wasmFailValidateText(`(module + (func (param $a (ref null extern)) + local.get $a + (block (param (ref extern)) + drop + ) + ) +)`, /expression has type externref but expected \(ref extern\)/); + +// can have non-defaultable local, but not use/get if unset. +wasmValidateText(`(module + (func (local (ref extern))) +)`); +wasmFailValidateText(`(module + (func (local (ref extern)) + local.get 0 + drop + ) +)`, /local\.get read from unset local/); +wasmFailValidateText(`(module + (func + (local (ref extern)) + unreachable + block + local.get 0 + drop + end + ) +)`, /local\.get read from unset local/); +wasmFailValidateText(`(module + (func (param funcref) (result funcref) (local (ref func)) + block + local.get 0 + ref.as_non_null + local.set 1 + end + local.get 1 + ) +)`, /local\.get read from unset local/); +wasmValidateText(`(module + (func (param $r (ref extern)) + (local $var (ref extern)) + local.get $r + ref.as_non_null + local.set $var + block block block + local.get $var + drop + end end end + ) + (func + (param (ref null func) (ref null func) (ref func)) + (result funcref) + (local (ref func) i32 (ref func) (ref null func)) + local.get 0 + ref.as_non_null + local.tee 3 + block + local.get 6 + ref.as_non_null + local.set 5 + end + local.get 2 + drop + local.tee 5 + ) +)`); +wasmFailValidateText(`(module + (elem declare func 0) + (func + (local (ref func)) + i32.const 0 + if + ref.func 0 + local.set 0 + else + local.get 0 + drop + end + ) +)`, /local\.get read from unset local/); +wasmValidateText(`(module + (elem declare func 0) + (func (result funcref) + (local (ref func) (ref func)) + i32.const 0 + if (result funcref) + ref.func 0 + local.set 0 + local.get 0 + else + ref.func 0 + local.tee 1 + local.get 1 + drop + end + ) +)`); + +// exported funcs can't take null in non-nullable params +let {a} = wasmEvalText(`(module + (func (export "a") (param (ref extern))) +)`).exports; +assertErrorMessage(() => a(null), TypeError, /cannot pass null to non-nullable/); +for (let val of WasmNonNullExternrefValues) { + a(val); +} + +// imported funcs can't return null in non-nullable results +function returnNull() { + return null; +} +function returnMultiNullReg() { + return [null, null]; +} +function returnMultiNullStack() { + return [1, 2, 3, 4, 5, 6, 7, 8, null]; +} +let {runNull, runMultiNullReg, runMultiNullStack} = wasmEvalText(`(module + (func $returnNull (import "" "returnNull") (result (ref extern))) + (func $returnMultiNullReg (import "" "returnMultiNullReg") (result (ref extern) (ref extern))) + (func $returnMultiNullStack (import "" "returnMultiNullStack") (result (ref extern) (ref extern) (ref extern) (ref extern) (ref extern) (ref extern) (ref extern) (ref extern) (ref extern))) + (func (export "runNull") + call $returnNull + unreachable + ) + (func (export "runMultiNullReg") + call $returnMultiNullReg + unreachable + ) + (func (export "runMultiNullStack") + call $returnMultiNullStack + unreachable + ) +)`, { "": { returnNull, returnMultiNullReg, returnMultiNullStack } }).exports; +assertErrorMessage(() => runNull(), TypeError, /cannot pass null to non-nullable/); +assertErrorMessage(() => runMultiNullReg(), TypeError, /cannot pass null to non-nullable/); +assertErrorMessage(() => runMultiNullStack(), TypeError, /cannot pass null to non-nullable/); + +{ + // can have non-nullable globals + wasmEvalText(`(module + (func $f) + (elem declare func $f) + (global (ref func) ref.func $f) + )`); +} + +// cannot have non-nullable tables without initializer +wasmFailValidateText(`(module + (table (ref extern) (elem)) +)`, /table with non-nullable references requires initializer/); + +// Testing internal wasmLosslessInvoke to pass non-nullable as params and arguments. +let {t} = wasmEvalText(`(module + (func (export "t") (param (ref extern)) (result (ref extern)) + (local (ref extern)) + (local.set 1 (local.get 0)) + (local.get 1) + ) +)`).exports; +const ret = wasmLosslessInvoke(t, {test: 1}); +assertEq(ret.value.test, 1); diff --git a/js/src/jit-test/tests/wasm/function-references/reftype-parse.js b/js/src/jit-test/tests/wasm/function-references/reftype-parse.js new file mode 100644 index 0000000000..643f753ec8 --- /dev/null +++ b/js/src/jit-test/tests/wasm/function-references/reftype-parse.js @@ -0,0 +1,51 @@ +// |jit-test| skip-if: !wasmFunctionReferencesEnabled() + +// RefType/ValueType as a simple string +const t01 = new WebAssembly.Table({element: 'funcref', initial: 3}); +const t02 = new WebAssembly.Table({element: 'externref', initial: 8}); +const g01 = new WebAssembly.Global({value: 'funcref', mutable: true}, null); +const g02 = new WebAssembly.Global({value: 'externref', mutable: true}, null); + +// Specify ToString() equivalents +const t05 = new WebAssembly.Table({element: {toString() { return 'funcref' },}, initial: 11}); +const t06 = new WebAssembly.Table({element: ['externref'], initial: 7}); + +assertErrorMessage( + () => new WebAssembly.Table({element: 'foo', initial: 1}), + TypeError, /bad value type/); +assertErrorMessage( + () => new WebAssembly.Table({element: true, initial: 1}), + TypeError, /bad value type/); + +// RefType/ValueType can be specified as an {ref: 'func', ...} object +const t11 = new WebAssembly.Table({element: {ref: 'func', nullable: true}, initial: 3}); +const t12 = new WebAssembly.Table({element: {ref: 'extern', nullable: true}, initial: 3}); +const t13 = new WebAssembly.Table({element: {ref: 'extern', nullable: false}, initial: 3}, {}); + +assertErrorMessage( + () => new WebAssembly.Table({element: {ref: 'func', nullable: false}, initial: 1}, null), + TypeError, /cannot pass null to non-nullable WebAssembly reference/); +assertErrorMessage( + () => new WebAssembly.Table({element: {ref: 'extern', nullable: false}, initial: 1}, null), + TypeError, /cannot pass null to non-nullable WebAssembly reference/); + +assertErrorMessage( + () => new WebAssembly.Table({element: {ref: 'bar', nullable: true}, initial: 1}), + TypeError, /bad value type/); + +const g11 = new WebAssembly.Global({value: {ref: 'func', nullable: true}, mutable: true}); +const g12 = new WebAssembly.Global({value: {ref: 'extern', nullable: true}, mutable: true}); +const g13 = new WebAssembly.Global({value: {ref: 'extern', nullable: false}, mutable: true}, {}); +const g14 = new WebAssembly.Global({value: {ref: 'extern', nullable: false}, mutable: true}); +const g15 = new WebAssembly.Global({value: {ref: 'extern', nullable: false}, mutable: true}, void 0); + +assertErrorMessage( + () => new WebAssembly.Global({value: {ref: 'func', nullable: false}, mutable: true}), + TypeError, /cannot pass null to non-nullable WebAssembly reference/); +assertErrorMessage( + () => new WebAssembly.Global({value: {ref: 'extern', nullable: false}, mutable: true}, null), + TypeError, /cannot pass null to non-nullable WebAssembly reference/); + +assertErrorMessage( + () => new WebAssembly.Global({value: {ref: 'bar', nullable: true}, mutable: true}), + TypeError, /bad value type/); |