11cb0ef41Sopenharmony_ci// META: global=window,dedicatedworker,jsshell
21cb0ef41Sopenharmony_ci// META: script=/wasm/jsapi/wasm-module-builder.js
31cb0ef41Sopenharmony_ci// META: script=assertions.js
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_cilet functions = {};
61cb0ef41Sopenharmony_cisetup(() => {
71cb0ef41Sopenharmony_ci  const builder = new WasmModuleBuilder();
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci  builder
101cb0ef41Sopenharmony_ci    .addFunction("fn", kSig_v_d)
111cb0ef41Sopenharmony_ci    .addBody([])
121cb0ef41Sopenharmony_ci    .exportFunc();
131cb0ef41Sopenharmony_ci  builder
141cb0ef41Sopenharmony_ci    .addFunction("fn2", kSig_v_v)
151cb0ef41Sopenharmony_ci    .addBody([])
161cb0ef41Sopenharmony_ci    .exportFunc();
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci  const buffer = builder.toBuffer()
191cb0ef41Sopenharmony_ci  const module = new WebAssembly.Module(buffer);
201cb0ef41Sopenharmony_ci  const instance = new WebAssembly.Instance(module, {});
211cb0ef41Sopenharmony_ci  functions = instance.exports;
221cb0ef41Sopenharmony_ci});
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_citest(() => {
251cb0ef41Sopenharmony_ci  const argument = { "element": "anyfunc", "initial": 5 };
261cb0ef41Sopenharmony_ci  const table = new WebAssembly.Table(argument);
271cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => table.get());
281cb0ef41Sopenharmony_ci}, "Missing arguments: get");
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_citest(t => {
311cb0ef41Sopenharmony_ci  const thisValues = [
321cb0ef41Sopenharmony_ci    undefined,
331cb0ef41Sopenharmony_ci    null,
341cb0ef41Sopenharmony_ci    true,
351cb0ef41Sopenharmony_ci    "",
361cb0ef41Sopenharmony_ci    Symbol(),
371cb0ef41Sopenharmony_ci    1,
381cb0ef41Sopenharmony_ci    {},
391cb0ef41Sopenharmony_ci    WebAssembly.Table,
401cb0ef41Sopenharmony_ci    WebAssembly.Table.prototype,
411cb0ef41Sopenharmony_ci  ];
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci  const argument = {
441cb0ef41Sopenharmony_ci    valueOf: t.unreached_func("Should not touch the argument (valueOf)"),
451cb0ef41Sopenharmony_ci    toString: t.unreached_func("Should not touch the argument (toString)"),
461cb0ef41Sopenharmony_ci  };
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  const fn = WebAssembly.Table.prototype.get;
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  for (const thisValue of thisValues) {
511cb0ef41Sopenharmony_ci    assert_throws_js(TypeError, () => fn.call(thisValue, argument), `this=${format_value(thisValue)}`);
521cb0ef41Sopenharmony_ci  }
531cb0ef41Sopenharmony_ci}, "Branding: get");
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_citest(() => {
561cb0ef41Sopenharmony_ci  const argument = { "element": "anyfunc", "initial": 5 };
571cb0ef41Sopenharmony_ci  const table = new WebAssembly.Table(argument);
581cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => table.set());
591cb0ef41Sopenharmony_ci}, "Missing arguments: set");
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_citest(t => {
621cb0ef41Sopenharmony_ci  const thisValues = [
631cb0ef41Sopenharmony_ci    undefined,
641cb0ef41Sopenharmony_ci    null,
651cb0ef41Sopenharmony_ci    true,
661cb0ef41Sopenharmony_ci    "",
671cb0ef41Sopenharmony_ci    Symbol(),
681cb0ef41Sopenharmony_ci    1,
691cb0ef41Sopenharmony_ci    {},
701cb0ef41Sopenharmony_ci    WebAssembly.Table,
711cb0ef41Sopenharmony_ci    WebAssembly.Table.prototype,
721cb0ef41Sopenharmony_ci  ];
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  const argument = {
751cb0ef41Sopenharmony_ci    valueOf: t.unreached_func("Should not touch the argument (valueOf)"),
761cb0ef41Sopenharmony_ci    toString: t.unreached_func("Should not touch the argument (toString)"),
771cb0ef41Sopenharmony_ci  };
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  const fn = WebAssembly.Table.prototype.set;
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  for (const thisValue of thisValues) {
821cb0ef41Sopenharmony_ci    assert_throws_js(TypeError, () => fn.call(thisValue, argument, null), `this=${format_value(thisValue)}`);
831cb0ef41Sopenharmony_ci  }
841cb0ef41Sopenharmony_ci}, "Branding: set");
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_citest(() => {
871cb0ef41Sopenharmony_ci  const argument = { "element": "anyfunc", "initial": 5 };
881cb0ef41Sopenharmony_ci  const table = new WebAssembly.Table(argument);
891cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [null, null, null, null, null]);
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  const {fn, fn2} = functions;
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  assert_equals(table.set(0, fn), undefined, "set() returns undefined.");
941cb0ef41Sopenharmony_ci  table.set(2, fn2);
951cb0ef41Sopenharmony_ci  table.set(4, fn);
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [fn, null, fn2, null, fn]);
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  table.set(0, null);
1001cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [null, null, fn2, null, fn]);
1011cb0ef41Sopenharmony_ci}, "Basic");
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_citest(() => {
1041cb0ef41Sopenharmony_ci  const argument = { "element": "anyfunc", "initial": 5 };
1051cb0ef41Sopenharmony_ci  const table = new WebAssembly.Table(argument);
1061cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [null, null, null, null, null]);
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  const {fn, fn2} = functions;
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  table.set(0, fn);
1111cb0ef41Sopenharmony_ci  table.set(2, fn2);
1121cb0ef41Sopenharmony_ci  table.set(4, fn);
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [fn, null, fn2, null, fn]);
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci  table.grow(4);
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [fn, null, fn2, null, fn, null, null, null, null]);
1191cb0ef41Sopenharmony_ci}, "Growing");
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_citest(() => {
1221cb0ef41Sopenharmony_ci  const argument = { "element": "anyfunc", "initial": 5 };
1231cb0ef41Sopenharmony_ci  const table = new WebAssembly.Table(argument);
1241cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [null, null, null, null, null]);
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ci  const {fn} = functions;
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci  // -1 is the wrong type hence the type check on entry gets this
1291cb0ef41Sopenharmony_ci  // before the range check does.
1301cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => table.set(-1, fn));
1311cb0ef41Sopenharmony_ci  assert_throws_js(RangeError, () => table.set(5, fn));
1321cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [null, null, null, null, null]);
1331cb0ef41Sopenharmony_ci}, "Setting out-of-bounds");
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_citest(() => {
1361cb0ef41Sopenharmony_ci  const argument = { "element": "anyfunc", "initial": 1 };
1371cb0ef41Sopenharmony_ci  const table = new WebAssembly.Table(argument);
1381cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [null]);
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci  const invalidArguments = [
1411cb0ef41Sopenharmony_ci    undefined,
1421cb0ef41Sopenharmony_ci    true,
1431cb0ef41Sopenharmony_ci    false,
1441cb0ef41Sopenharmony_ci    "test",
1451cb0ef41Sopenharmony_ci    Symbol(),
1461cb0ef41Sopenharmony_ci    7,
1471cb0ef41Sopenharmony_ci    NaN,
1481cb0ef41Sopenharmony_ci    {},
1491cb0ef41Sopenharmony_ci  ];
1501cb0ef41Sopenharmony_ci  for (const argument of invalidArguments) {
1511cb0ef41Sopenharmony_ci    assert_throws_js(TypeError, () => table.set(0, argument),
1521cb0ef41Sopenharmony_ci                     `set(${format_value(argument)})`);
1531cb0ef41Sopenharmony_ci  }
1541cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [null]);
1551cb0ef41Sopenharmony_ci}, "Setting non-function");
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_citest(() => {
1581cb0ef41Sopenharmony_ci  const argument = { "element": "anyfunc", "initial": 1 };
1591cb0ef41Sopenharmony_ci  const table = new WebAssembly.Table(argument);
1601cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [null]);
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  const fn = function() {};
1631cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => table.set(0, fn));
1641cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [null]);
1651cb0ef41Sopenharmony_ci}, "Setting non-wasm function");
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_citest(() => {
1681cb0ef41Sopenharmony_ci  const argument = { "element": "anyfunc", "initial": 1 };
1691cb0ef41Sopenharmony_ci  const table = new WebAssembly.Table(argument);
1701cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [null]);
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  const fn = () => {};
1731cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => table.set(0, fn));
1741cb0ef41Sopenharmony_ci  assert_equal_to_array(table, [null]);
1751cb0ef41Sopenharmony_ci}, "Setting non-wasm arrow function");
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ciconst outOfRangeValues = [
1781cb0ef41Sopenharmony_ci  undefined,
1791cb0ef41Sopenharmony_ci  NaN,
1801cb0ef41Sopenharmony_ci  Infinity,
1811cb0ef41Sopenharmony_ci  -Infinity,
1821cb0ef41Sopenharmony_ci  -1,
1831cb0ef41Sopenharmony_ci  0x100000000,
1841cb0ef41Sopenharmony_ci  0x1000000000,
1851cb0ef41Sopenharmony_ci  "0x100000000",
1861cb0ef41Sopenharmony_ci  { valueOf() { return 0x100000000; } },
1871cb0ef41Sopenharmony_ci];
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_cifor (const value of outOfRangeValues) {
1901cb0ef41Sopenharmony_ci  test(() => {
1911cb0ef41Sopenharmony_ci    const argument = { "element": "anyfunc", "initial": 1 };
1921cb0ef41Sopenharmony_ci    const table = new WebAssembly.Table(argument);
1931cb0ef41Sopenharmony_ci    assert_throws_js(TypeError, () => table.get(value));
1941cb0ef41Sopenharmony_ci  }, `Getting out-of-range argument: ${format_value(value)}`);
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci  test(() => {
1971cb0ef41Sopenharmony_ci    const argument = { "element": "anyfunc", "initial": 1 };
1981cb0ef41Sopenharmony_ci    const table = new WebAssembly.Table(argument);
1991cb0ef41Sopenharmony_ci    assert_throws_js(TypeError, () => table.set(value, null));
2001cb0ef41Sopenharmony_ci  }, `Setting out-of-range argument: ${format_value(value)}`);
2011cb0ef41Sopenharmony_ci}
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_citest(() => {
2041cb0ef41Sopenharmony_ci  const argument = { "element": "anyfunc", "initial": 1 };
2051cb0ef41Sopenharmony_ci  const table = new WebAssembly.Table(argument);
2061cb0ef41Sopenharmony_ci  let called = 0;
2071cb0ef41Sopenharmony_ci  const value = {
2081cb0ef41Sopenharmony_ci    valueOf() {
2091cb0ef41Sopenharmony_ci      called++;
2101cb0ef41Sopenharmony_ci      return 0;
2111cb0ef41Sopenharmony_ci    },
2121cb0ef41Sopenharmony_ci  };
2131cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => table.set(value, {}));
2141cb0ef41Sopenharmony_ci  assert_equals(called, 1);
2151cb0ef41Sopenharmony_ci}, "Order of argument conversion");
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_citest(() => {
2181cb0ef41Sopenharmony_ci  const {fn} = functions;
2191cb0ef41Sopenharmony_ci  const argument = { "element": "anyfunc", "initial": 1 };
2201cb0ef41Sopenharmony_ci  const table = new WebAssembly.Table(argument);
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  assert_equals(table.get(0, {}), null);
2231cb0ef41Sopenharmony_ci  assert_equals(table.set(0, fn, {}), undefined);
2241cb0ef41Sopenharmony_ci}, "Stray argument");
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_citest(() => {
2271cb0ef41Sopenharmony_ci  const builder = new WasmModuleBuilder();
2281cb0ef41Sopenharmony_ci  builder
2291cb0ef41Sopenharmony_ci    .addFunction("fn", kSig_v_v)
2301cb0ef41Sopenharmony_ci    .addBody([])
2311cb0ef41Sopenharmony_ci    .exportFunc();
2321cb0ef41Sopenharmony_ci  const bin = builder.toBuffer();
2331cb0ef41Sopenharmony_ci  const fn = new WebAssembly.Instance(new WebAssembly.Module(bin)).exports.fn;
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci  const argument = { "element": "anyfunc", "initial": 1 };
2361cb0ef41Sopenharmony_ci  const table = new WebAssembly.Table(argument, fn);
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci  assert_equals(table.get(0), fn);
2391cb0ef41Sopenharmony_ci  table.set(0);
2401cb0ef41Sopenharmony_ci  assert_equals(table.get(0), null);
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci  table.set(0, fn);
2431cb0ef41Sopenharmony_ci  assert_equals(table.get(0), fn);
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => table.set(0, {}));
2461cb0ef41Sopenharmony_ci  assert_throws_js(TypeError, () => table.set(0, 37));
2471cb0ef41Sopenharmony_ci}, "Arguments for anyfunc table set");
2481cb0ef41Sopenharmony_ci
2491cb0ef41Sopenharmony_citest(() => {
2501cb0ef41Sopenharmony_ci  const testObject = {};
2511cb0ef41Sopenharmony_ci  const argument = { "element": "externref", "initial": 1 };
2521cb0ef41Sopenharmony_ci  const table = new WebAssembly.Table(argument, testObject);
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  assert_equals(table.get(0), testObject);
2551cb0ef41Sopenharmony_ci  table.set(0);
2561cb0ef41Sopenharmony_ci  assert_equals(table.get(0), undefined);
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci  table.set(0, testObject);
2591cb0ef41Sopenharmony_ci  assert_equals(table.get(0), testObject);
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ci  table.set(0, 37);
2621cb0ef41Sopenharmony_ci  assert_equals(table.get(0), 37);
2631cb0ef41Sopenharmony_ci}, "Arguments for externref table set");
264