// META: global=window,dedicatedworker,jsshell // META: script=/wasm/jsapi/wasm-module-builder.js // META: script=/wasm/jsapi/assertions.js // META: script=/wasm/jsapi/table/assertions.js test(() => { assert_function_name(WebAssembly.Table, "Table", "WebAssembly.Table"); }, "name"); test(() => { assert_function_length(WebAssembly.Table, 1, "WebAssembly.Table"); }, "length"); test(() => { assert_throws_js(TypeError, () => new WebAssembly.Table()); }, "No arguments"); test(() => { const argument = { "element": "anyfunc", "initial": 0 }; assert_throws_js(TypeError, () => WebAssembly.Table(argument)); }, "Calling"); test(() => { assert_throws_js(TypeError, () => new WebAssembly.Table({})); }, "Empty descriptor"); test(() => { const invalidArguments = [ undefined, null, false, true, "", "test", Symbol(), 1, NaN, {}, ]; for (const invalidArgument of invalidArguments) { assert_throws_js(TypeError, () => new WebAssembly.Table(invalidArgument), `new Table(${format_value(invalidArgument)})`); } }, "Invalid descriptor argument"); test(() => { assert_throws_js(TypeError, () => new WebAssembly.Table({ "element": "anyfunc", "initial": undefined })); }, "Undefined initial value in descriptor"); test(() => { assert_throws_js(TypeError, () => new WebAssembly.Table({ "element": undefined, "initial": 0 })); }, "Undefined element value in descriptor"); const outOfRangeValues = [ NaN, Infinity, -Infinity, -1, 0x100000000, 0x1000000000, ]; for (const value of outOfRangeValues) { test(() => { assert_throws_js(TypeError, () => new WebAssembly.Table({ "element": "anyfunc", "initial": value })); }, `Out-of-range initial value in descriptor: ${format_value(value)}`); test(() => { assert_throws_js(TypeError, () => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })); }, `Out-of-range maximum value in descriptor: ${format_value(value)}`); } test(() => { assert_throws_js(RangeError, () => new WebAssembly.Table({ "element": "anyfunc", "initial": 10, "maximum": 9 })); }, "Initial value exceeds maximum"); test(() => { const argument = { "element": "anyfunc", "initial": 0 }; const table = new WebAssembly.Table(argument); assert_Table(table, { "length": 0 }); }, "Basic (zero)"); test(() => { const argument = { "element": "anyfunc", "initial": 5 }; const table = new WebAssembly.Table(argument); assert_Table(table, { "length": 5 }); }, "Basic (non-zero)"); test(() => { const argument = { "element": "anyfunc", "initial": 0 }; const table = new WebAssembly.Table(argument, null, {}); assert_Table(table, { "length": 0 }); }, "Stray argument"); test(() => { const proxy = new Proxy({}, { has(o, x) { assert_unreached(`Should not call [[HasProperty]] with ${x}`); }, get(o, x) { switch (x) { case "element": return "anyfunc"; case "initial": case "maximum": return 0; default: return undefined; } }, }); const table = new WebAssembly.Table(proxy); assert_Table(table, { "length": 0 }); }, "Proxy descriptor"); test(() => { const table = new WebAssembly.Table({ "element": { toString() { return "anyfunc"; }, }, "initial": 1, }); assert_Table(table, { "length": 1 }); }, "Type conversion for descriptor.element"); test(() => { const order = []; new WebAssembly.Table({ get maximum() { order.push("maximum"); return { valueOf() { order.push("maximum valueOf"); return 1; }, }; }, get initial() { order.push("initial"); return { valueOf() { order.push("initial valueOf"); return 1; }, }; }, get element() { order.push("element"); return { toString() { order.push("element toString"); return "anyfunc"; }, }; }, }); assert_array_equals(order, [ "element", "element toString", "initial", "initial valueOf", "maximum", "maximum valueOf", ]); }, "Order of evaluation for descriptor"); test(() => { const testObject = {}; const argument = { "element": "externref", "initial": 3 }; const table = new WebAssembly.Table(argument, testObject); assert_equals(table.length, 3); assert_equals(table.get(0), testObject); assert_equals(table.get(1), testObject); assert_equals(table.get(2), testObject); }, "initialize externref table with default value"); test(() => { const argument = { "element": "i32", "initial": 3 }; assert_throws_js(TypeError, () => new WebAssembly.Table(argument)); }, "initialize table with a wrong element value"); test(() => { const builder = new WasmModuleBuilder(); builder .addFunction("fn", kSig_v_v) .addBody([]) .exportFunc(); const bin = builder.toBuffer(); const fn = new WebAssembly.Instance(new WebAssembly.Module(bin)).exports.fn; const argument = { "element": "anyfunc", "initial": 3 }; const table = new WebAssembly.Table(argument, fn); assert_equals(table.length, 3); assert_equals(table.get(0), fn); assert_equals(table.get(1), fn); assert_equals(table.get(2), fn); }, "initialize anyfunc table with default value"); test(() => { const argument = { "element": "anyfunc", "initial": 3 }; assert_throws_js(TypeError, () => new WebAssembly.Table(argument, {})); assert_throws_js(TypeError, () => new WebAssembly.Table(argument, "cannot be used as a wasm function")); assert_throws_js(TypeError, () => new WebAssembly.Table(argument, 37)); }, "initialize anyfunc table with a bad default value");