[wasm] Fix JS api for more/less arguments than expected

Missing arguments are identical to undefined, and are converted to the
integer 0 by ECMAScript {ToInteger()}.
Add more tests, and enable previously disabled tests.

There is a follow-up refactoring here: https://crrev.com/c/704586

R=titzer@chromium.org, mstarzinger@chromium.org

Change-Id: I89cc259aaf5975ec2f6f51ff002e7d1b32adba5e
Reviewed-on: https://chromium-review.googlesource.com/704658
Reviewed-by: Ben Titzer <titzer@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48373}
This commit is contained in:
Clemens Hammacher 2017-10-06 16:09:29 +02:00 committed by Commit Bot
parent ddc5855478
commit 2a5dc0b3a1
2 changed files with 63 additions and 11 deletions

View File

@ -771,10 +771,10 @@ void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
EXTRACT_THIS(receiver, WasmMemoryObject); EXTRACT_THIS(receiver, WasmMemoryObject);
int64_t delta_size = 0; int64_t delta_size = 0;
if (args.Length() < 1 || !args[0]->IntegerValue(context).To(&delta_size)) { if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&delta_size)) {
thrower.TypeError("Argument 0 required, must be numeric value of pages");
return; return;
} }
int64_t max_size64 = receiver->maximum_pages(); int64_t max_size64 = receiver->maximum_pages();
if (max_size64 < 0 || if (max_size64 < 0 ||
max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_mem_pages)) { max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_mem_pages)) {

View File

@ -16,7 +16,7 @@ function unexpectedFail(error) {
} }
function assertEq(val, expected) { function assertEq(val, expected) {
assertEquals(expected, val); assertSame(expected, val);
} }
function assertArrayBuffer(val, expected) { function assertArrayBuffer(val, expected) {
assertTrue(val instanceof ArrayBuffer); assertTrue(val instanceof ArrayBuffer);
@ -512,13 +512,40 @@ assertTrue(buf !== mem.buffer);
assertEq(buf.byteLength, 0); assertEq(buf.byteLength, 0);
buf = mem.buffer; buf = mem.buffer;
assertEq(buf.byteLength, kPageSize); assertEq(buf.byteLength, kPageSize);
assertEq(mem.grow(1), 1); assertEq(mem.grow(1, 23), 1);
assertTrue(buf !== mem.buffer);
assertEq(buf.byteLength, 0);
buf = mem.buffer;
assertEq(buf.byteLength, 2 * kPageSize);
assertEq(mem.grow(), 2);
assertTrue(buf !== mem.buffer); assertTrue(buf !== mem.buffer);
assertEq(buf.byteLength, 0); assertEq(buf.byteLength, 0);
buf = mem.buffer; buf = mem.buffer;
assertEq(buf.byteLength, 2 * kPageSize); assertEq(buf.byteLength, 2 * kPageSize);
assertErrorMessage(() => mem.grow(1), Error, /failed to grow memory/); assertErrorMessage(() => mem.grow(1), Error, /failed to grow memory/);
assertErrorMessage(() => mem.grow(Infinity), Error, /failed to grow memory/);
assertErrorMessage(() => mem.grow(-Infinity), Error, /failed to grow memory/);
assertEq(buf, mem.buffer); assertEq(buf, mem.buffer);
let throwOnValueOf = {
valueOf: function() {
throw Error('throwOnValueOf')
}
};
assertErrorMessage(() => mem.grow(throwOnValueOf), Error, /throwOnValueOf/);
assertEq(buf, mem.buffer);
let zero_wrapper = {
valueOf: function() {
++this.call_counter;
return 0;
},
call_counter: 0
};
assertEq(mem.grow(zero_wrapper), 2);
assertEq(zero_wrapper.call_counter, 1);
assertTrue(buf !== mem.buffer);
assertEq(buf.byteLength, 0);
buf = mem.buffer;
assertEq(buf.byteLength, 2 * kPageSize);
let empty_mem = new Memory({initial: 0, maximum: 5}); let empty_mem = new Memory({initial: 0, maximum: 5});
let empty_buf = empty_mem.buffer; let empty_buf = empty_mem.buffer;
@ -571,8 +598,9 @@ assertTrue(new Table({initial: 1, element: 'anyfunc'}) instanceof Table);
assertTrue(new Table({initial: 1.5, element: 'anyfunc'}) instanceof Table); assertTrue(new Table({initial: 1.5, element: 'anyfunc'}) instanceof Table);
assertTrue( assertTrue(
new Table({initial: 1, maximum: 1.5, element: 'anyfunc'}) instanceof Table); new Table({initial: 1, maximum: 1.5, element: 'anyfunc'}) instanceof Table);
// TODO:maximum assertTrue(new Table({initial:1, maximum:Math.pow(2,32)-1, assertTrue(
// element:"anyfunc"}) instanceof Table); new Table({initial: 1, maximum: Math.pow(2, 32) - 1, element: 'anyfunc'})
instanceof Table);
// 'WebAssembly.Table.prototype' data property // 'WebAssembly.Table.prototype' data property
let tableProtoDesc = Object.getOwnPropertyDescriptor(Table, 'prototype'); let tableProtoDesc = Object.getOwnPropertyDescriptor(Table, 'prototype');
@ -623,15 +651,17 @@ assertErrorMessage(
() => get.call(), TypeError, /called on incompatible undefined/); () => get.call(), TypeError, /called on incompatible undefined/);
assertErrorMessage( assertErrorMessage(
() => get.call({}), TypeError, /called on incompatible Object/); () => get.call({}), TypeError, /called on incompatible Object/);
assertEq(get.call(tbl1), null);
assertEq(get.call(tbl1, 0), null); assertEq(get.call(tbl1, 0), null);
assertEq(get.call(tbl1, 0, Infinity), null);
assertEq(get.call(tbl1, 1), null); assertEq(get.call(tbl1, 1), null);
assertEq(get.call(tbl1, 1.5), null); assertEq(get.call(tbl1, 1.5), null);
assertErrorMessage(() => get.call(tbl1, 2), RangeError, /bad Table get index/); assertErrorMessage(() => get.call(tbl1, 2), RangeError, /bad Table get index/);
assertErrorMessage( assertErrorMessage(
() => get.call(tbl1, 2.5), RangeError, /bad Table get index/); () => get.call(tbl1, 2.5), RangeError, /bad Table get index/);
assertErrorMessage(() => get.call(tbl1, -1), RangeError, /bad Table get index/); assertErrorMessage(() => get.call(tbl1, -1), RangeError, /bad Table get index/);
// TODO assertErrorMessage(() => get.call(tbl1, Math.pow(2,33)), RangeError, assertErrorMessage(
// /bad Table get index/); () => get.call(tbl1, Math.pow(2, 33)), RangeError, /bad Table get index/);
assertErrorMessage( assertErrorMessage(
() => get.call(tbl1, {valueOf() { throw new Error('hi') }}), Error, 'hi'); () => get.call(tbl1, {valueOf() { throw new Error('hi') }}), Error, 'hi');
@ -650,15 +680,26 @@ assertErrorMessage(
() => set.call({}), TypeError, /called on incompatible Object/); () => set.call({}), TypeError, /called on incompatible Object/);
assertErrorMessage( assertErrorMessage(
() => set.call(tbl1, 0), TypeError, /requires more than 1 argument/); () => set.call(tbl1, 0), TypeError, /requires more than 1 argument/);
assertErrorMessage(
() => set.call(tbl1, undefined), TypeError,
/requires more than 1 argument/);
assertErrorMessage( assertErrorMessage(
() => set.call(tbl1, 2, null), RangeError, /bad Table set index/); () => set.call(tbl1, 2, null), RangeError, /bad Table set index/);
assertErrorMessage( assertErrorMessage(
() => set.call(tbl1, -1, null), RangeError, /bad Table set index/); () => set.call(tbl1, -1, null), RangeError, /bad Table set index/);
// TODO assertErrorMessage(() => set.call(tbl1, Math.pow(2,33), null), assertErrorMessage(
// RangeError, /bad Table set index/); () => set.call(tbl1, Math.pow(2, 33), null), RangeError,
/bad Table set index/);
assertErrorMessage(
() => set.call(tbl1, Infinity, null), RangeError, /bad Table set index/);
assertErrorMessage(
() => set.call(tbl1, -Infinity, null), RangeError, /bad Table set index/);
assertErrorMessage( assertErrorMessage(
() => set.call(tbl1, 0, undefined), TypeError, () => set.call(tbl1, 0, undefined), TypeError,
/can only assign WebAssembly exported functions to Table/); /can only assign WebAssembly exported functions to Table/);
assertErrorMessage(
() => set.call(tbl1, undefined, undefined), TypeError,
/can only assign WebAssembly exported functions to Table/);
assertErrorMessage( assertErrorMessage(
() => set.call(tbl1, 0, {}), TypeError, () => set.call(tbl1, 0, {}), TypeError,
/can only assign WebAssembly exported functions to Table/); /can only assign WebAssembly exported functions to Table/);
@ -672,6 +713,7 @@ assertErrorMessage(
'hai'); 'hai');
assertEq(set.call(tbl1, 0, null), undefined); assertEq(set.call(tbl1, 0, null), undefined);
assertEq(set.call(tbl1, 1, null), undefined); assertEq(set.call(tbl1, 1, null), undefined);
assertEq(set.call(tbl1, undefined, null), undefined);
// 'WebAssembly.Table.prototype.grow' data property // 'WebAssembly.Table.prototype.grow' data property
let tblGrowDesc = Object.getOwnPropertyDescriptor(tableProto, 'grow'); let tblGrowDesc = Object.getOwnPropertyDescriptor(tableProto, 'grow');
@ -693,11 +735,21 @@ assertErrorMessage(
/bad Table grow delta/); /bad Table grow delta/);
var tbl = new Table({element: 'anyfunc', initial: 1, maximum: 2}); var tbl = new Table({element: 'anyfunc', initial: 1, maximum: 2});
assertEq(tbl.length, 1); assertEq(tbl.length, 1);
assertErrorMessage(
() => tbl.grow(Infinity), RangeError, /failed to grow table/);
assertErrorMessage(
() => tbl.grow(-Infinity), RangeError, /failed to grow table/);
assertEq(tbl.grow(0), 1); assertEq(tbl.grow(0), 1);
assertEq(tbl.length, 1); assertEq(tbl.length, 1);
assertEq(tbl.grow(1), 1); assertEq(tbl.grow(1, 4), 1);
assertEq(tbl.length, 2);
assertEq(tbl.grow(), 2);
assertEq(tbl.length, 2); assertEq(tbl.length, 2);
assertErrorMessage(() => tbl.grow(1), Error, /failed to grow table/); assertErrorMessage(() => tbl.grow(1), Error, /failed to grow table/);
assertErrorMessage(
() => tbl.grow(Infinity), RangeError, /failed to grow table/);
assertErrorMessage(
() => tbl.grow(-Infinity), RangeError, /failed to grow table/);
// 'WebAssembly.validate' function // 'WebAssembly.validate' function
assertErrorMessage(() => WebAssembly.validate(), TypeError); assertErrorMessage(() => WebAssembly.validate(), TypeError);