4743426571
We used to check the size of tables at compile time, and threw a CompilationError if a given size exceeded the implementation-defined limit. However, the spec defines that an error should only be thrown when the implementation-defined limit is reached, which is either at instantiation time of during runtime at a table.grow. With this CL the V8 implementation becomes spec compliant in this regard. R=jkummerow@chromium.org Bug: v8:10556 Change-Id: I7d0e688b385a65e4060a569e5ab1dec68947ceea Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2326331 Commit-Queue: Andreas Haas <ahaas@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#69267}
288 lines
9.7 KiB
JavaScript
288 lines
9.7 KiB
JavaScript
// 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);
|
|
|
|
table = new WebAssembly.Table({element: "anyfunc", initial: 0, maximum: kV8MaxWasmTableSize + 1});
|
|
assertTableIsValid(table, 0);
|
|
|
|
assertThrows(
|
|
() => new WebAssembly.Table(
|
|
{element: "anyfunc", initial: 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);
|
|
})();
|