| // Copyright 2016 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Flags: --expose-wasm |
| |
| 'use strict'; |
| |
| load("test/mjsunit/wasm/wasm-module-builder.js"); |
| |
| // Basic tests. |
| |
| const outOfUint32RangeValue = 1e12; |
| const kV8MaxWasmTableSize = 10000000; |
| |
| function assertTableIsValid(table, length) { |
| assertSame(WebAssembly.Table.prototype, table.__proto__); |
| assertSame(WebAssembly.Table, table.constructor); |
| assertTrue(table instanceof Object); |
| assertTrue(table instanceof WebAssembly.Table); |
| assertEquals(length, table.length); |
| } |
| |
| (function TestConstructor() { |
| assertTrue(WebAssembly.Table instanceof Function); |
| assertSame(WebAssembly.Table, WebAssembly.Table.prototype.constructor); |
| assertTrue(WebAssembly.Table.prototype.grow instanceof Function); |
| assertTrue(WebAssembly.Table.prototype.get instanceof Function); |
| assertTrue(WebAssembly.Table.prototype.set instanceof Function); |
| let desc = Object.getOwnPropertyDescriptor(WebAssembly.Table.prototype, 'length'); |
| assertTrue(desc.get instanceof Function); |
| assertSame(undefined, desc.set); |
| |
| assertThrows(() => new WebAssembly.Table(), TypeError); |
| assertThrows(() => new WebAssembly.Table(1), TypeError); |
| assertThrows(() => new WebAssembly.Table(""), TypeError); |
| |
| assertThrows(() => new WebAssembly.Table({}), TypeError); |
| assertThrows(() => new WebAssembly.Table({initial: 10}), TypeError); |
| |
| assertThrows(() => new WebAssembly.Table({element: 0, initial: 10}), TypeError); |
| assertThrows(() => new WebAssembly.Table({element: "any", initial: 10}), TypeError); |
| |
| assertThrows(() => new WebAssembly.Table( |
| {element: "anyfunc", initial: -1}), TypeError); |
| assertThrows(() => new WebAssembly.Table( |
| {element: "anyfunc", initial: outOfUint32RangeValue}), TypeError); |
| |
| assertThrows(() => new WebAssembly.Table( |
| {element: "anyfunc", initial: 10, maximum: -1}), TypeError); |
| assertThrows(() => new WebAssembly.Table( |
| {element: "anyfunc", initial: 10, maximum: outOfUint32RangeValue}), TypeError); |
| assertThrows(() => new WebAssembly.Table( |
| {element: "anyfunc", initial: 10, maximum: 9}), RangeError); |
| |
| let table; |
| table = new WebAssembly.Table({element: "anyfunc", initial: 1}); |
| assertTableIsValid(table, 1); |
| assertEquals(null, table.get(0)); |
| assertEquals(undefined, table[0]); |
| |
| table = new WebAssembly.Table({element: "anyfunc", initial: "2"}); |
| assertTableIsValid(table, 2); |
| assertEquals(null, table.get(0)); |
| assertEquals(null, table.get(1)); |
| assertEquals(undefined, table[0]); |
| assertEquals(undefined, table[1]); |
| |
| table = new WebAssembly.Table({element: "anyfunc", initial: {valueOf() { return "1" }}}); |
| assertTableIsValid(table, 1); |
| assertEquals(null, table.get(0)); |
| assertEquals(undefined, table[0]); |
| |
| table = new WebAssembly.Table({element: "anyfunc", initial: 0, maximum: 10}); |
| assertTableIsValid(table, 0); |
| |
| table = new WebAssembly.Table({element: "anyfunc", initial: 0, maximum: "10"}); |
| assertTableIsValid(table, 0); |
| |
| table = new WebAssembly.Table({element: "anyfunc", initial: 0, maximum: {valueOf() { return "10" }}}); |
| assertTableIsValid(table, 0); |
| |
| table = new WebAssembly.Table({element: "anyfunc", initial: 0, maximum: undefined}); |
| assertTableIsValid(table, 0); |
| |
| table = new WebAssembly.Table({element: "anyfunc", initial: 0, maximum: 1000000}); |
| assertTableIsValid(table, 0); |
| |
| table = new WebAssembly.Table({element: "anyfunc", initial: 0, maximum: kV8MaxWasmTableSize}); |
| assertTableIsValid(table, 0); |
| |
| assertThrows( |
| () => new WebAssembly.Table( |
| {element: "anyfunc", initial: 0, maximum: kV8MaxWasmTableSize + 1}), |
| RangeError, /above the upper bound/); |
| })(); |
| |
| (function TestMaximumIsReadOnce() { |
| var a = true; |
| var desc = {element: "anyfunc", initial: 10}; |
| Object.defineProperty(desc, 'maximum', {get: function() { |
| if (a) { |
| a = false; |
| return 16; |
| } |
| else { |
| // Change the return value on the second call so it throws. |
| return -1; |
| } |
| }}); |
| let table = new WebAssembly.Table(desc); |
| assertTableIsValid(table, 10); |
| })(); |
| |
| (function TestMaximumDoesHasProperty() { |
| var hasPropertyWasCalled = false; |
| var desc = {element: "anyfunc", initial: 10}; |
| var proxy = new Proxy({maximum: 16}, { |
| has: function(target, name) { hasPropertyWasCalled = true; } |
| }); |
| Object.setPrototypeOf(desc, proxy); |
| let table = new WebAssembly.Table(desc); |
| assertTableIsValid(table, 10); |
| })(); |
| |
| (function TestLength() { |
| for (let i = 0; i < 10; ++i) { |
| let table = new WebAssembly.Table({element: "anyfunc", initial: i}); |
| assertEquals(i, table.length); |
| } |
| |
| assertThrows(() => WebAssembly.Table.prototype.length.call([]), TypeError); |
| })(); |
| |
| (function TestGet() { |
| let table = new WebAssembly.Table({element: "anyfunc", initial: 10}); |
| |
| for (let i = 0; i < table.length; ++i) { |
| assertEquals(null, table.get(i)); |
| assertEquals(null, table.get(String(i))); |
| } |
| for (let key of [0.4, "", []]) { |
| assertEquals(null, table.get(key)); |
| } |
| for (let key of [-1, NaN, {}, () => {}]) { |
| assertThrows(() => table.get(key), TypeError); |
| } |
| for (let key of [table.length, table.length * 10]) { |
| assertThrows(() => table.get(key), RangeError); |
| } |
| assertThrows(() => table.get(Symbol()), TypeError); |
| assertThrows(() => WebAssembly.Table.prototype.get.call([], 0), TypeError); |
| })(); |
| |
| (function TestSet() { |
| let builder = new WasmModuleBuilder; |
| builder.addExport("host", builder.addImport("test", "f", kSig_v_v)); |
| builder.addExport("wasm", builder.addFunction("", kSig_v_v).addBody([])); |
| let {wasm, host} = builder.instantiate({test: {f() {}}}).exports; |
| |
| let table = new WebAssembly.Table({element: "anyfunc", initial: 10}); |
| |
| for (let f of [wasm, host]) { |
| for (let i = 0; i < table.length; ++i) table.set(i, null); |
| for (let i = 0; i < table.length; ++i) { |
| assertSame(null, table.get(i)); |
| assertSame(undefined, table.set(i, f)); |
| assertSame(f, table.get(i)); |
| assertSame(undefined, table[i]); |
| } |
| |
| for (let i = 0; i < table.length; ++i) table.set(i, null); |
| for (let i = 0; i < table.length; ++i) { |
| assertSame(null, table.get(i)); |
| assertSame(undefined, table.set(String(i), f)); |
| assertSame(f, table.get(i)); |
| assertSame(undefined, table[i]); |
| } |
| |
| for (let key of [0.4, "", []]) { |
| assertSame(undefined, table.set(0, null)); |
| assertSame(undefined, table.set(key, f)); |
| assertSame(f, table.get(0)); |
| assertSame(undefined, table[key]); |
| } |
| for (let key of [NaN, {}, () => {}]) { |
| assertSame(undefined, table[key]); |
| assertThrows(() => table.set(key, f), TypeError); |
| } |
| |
| assertThrows(() => table.set(-1, f), TypeError); |
| for (let key of [table.length, table.length * 10]) { |
| assertThrows(() => table.set(key, f), RangeError); |
| } |
| |
| assertThrows(() => table.set(0), TypeError); |
| for (let val of [undefined, 0, "", {}, [], () => {}]) { |
| assertThrows(() => table.set(0, val), TypeError); |
| } |
| |
| assertThrows(() => table.set(Symbol(), f), TypeError); |
| assertThrows(() => WebAssembly.Table.prototype.set.call([], 0, f), |
| TypeError); |
| } |
| })(); |
| |
| |
| (function TestIndexing() { |
| let builder = new WasmModuleBuilder; |
| builder.addExport("host", builder.addImport("test", "f", kSig_v_v)); |
| builder.addExport("wasm", builder.addFunction("", kSig_v_v).addBody([])); |
| let {wasm, host} = builder.instantiate({test: {f() {}}}).exports; |
| |
| let table = new WebAssembly.Table({element: "anyfunc", initial: 10}); |
| |
| for (let f of [wasm, host, () => {}, 5, {}, ""]) { |
| for (let i = 0; i < table.length; ++i) table[i] = f; |
| for (let i = 0; i < table.length; ++i) { |
| assertSame(null, table.get(i)); |
| assertSame(f, table[i]); |
| } |
| |
| for (let key of [NaN, {}, () => {}]) { |
| assertSame(f, table[key] = f); |
| assertSame(f, table[key]); |
| assertThrows(() => table.get(key), TypeError); |
| } |
| for (let key of [0.4, "", []]) { |
| assertSame(f, table[key] = f); |
| assertSame(f, table[key]); |
| assertSame(null, table.get(key)); |
| } |
| } |
| })(); |
| |
| (function TestGrow() { |
| let builder = new WasmModuleBuilder; |
| builder.addExport("host", builder.addImport("test", "f", kSig_v_v)); |
| builder.addExport("wasm", builder.addFunction("", kSig_v_v).addBody([])); |
| let {wasm, host} = builder.instantiate({test: {f() {}}}).exports; |
| |
| function init(table) { |
| for (let i = 0; i < 5; ++i) table.set(i, wasm); |
| for (let i = 15; i < 20; ++i) table.set(i, host); |
| } |
| function check(table) { |
| for (let i = 0; i < 5; ++i) assertSame(wasm, table.get(i)); |
| for (let i = 6; i < 15; ++i) assertSame(null, table.get(i)); |
| for (let i = 15; i < 20; ++i) assertSame(host, table.get(i)); |
| for (let i = 21; i < table.length; ++i) assertSame(null, table.get(i)); |
| } |
| |
| let table = new WebAssembly.Table({element: "anyfunc", initial: 20}); |
| init(table); |
| check(table); |
| table.grow(0); |
| check(table); |
| table.grow(10); |
| check(table); |
| assertThrows(() => table.grow(-10), TypeError); |
| |
| table = new WebAssembly.Table({element: "anyfunc", initial: 20, maximum: 25}); |
| init(table); |
| check(table); |
| table.grow(0); |
| check(table); |
| table.grow(5); |
| check(table); |
| table.grow(0); |
| check(table); |
| assertThrows(() => table.grow(1), RangeError); |
| assertThrows(() => table.grow(-10), TypeError); |
| |
| assertThrows(() => WebAssembly.Table.prototype.grow.call([], 0), TypeError); |
| |
| table = new WebAssembly.Table( |
| {element: "anyfunc", initial: 0, maximum: kV8MaxWasmTableSize}); |
| table.grow(kV8MaxWasmTableSize); |
| assertThrows(() => table.grow(1), RangeError); |
| |
| table = new WebAssembly.Table({element: "anyfunc", initial: 0}); |
| table.grow({valueOf: () => {table.grow(2); return 1;}}); |
| assertEquals(3, table.length); |
| })(); |