From 2a5dc0b3a136bc45d27fb7f0c962939730aa469e Mon Sep 17 00:00:00 2001 From: Clemens Hammacher Date: Fri, 6 Oct 2017 16:09:29 +0200 Subject: [PATCH] [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 Reviewed-by: Michael Starzinger Commit-Queue: Clemens Hammacher Cr-Commit-Position: refs/heads/master@{#48373} --- src/wasm/wasm-js.cc | 4 +-- test/mjsunit/wasm/js-api.js | 70 ++++++++++++++++++++++++++++++++----- 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/wasm/wasm-js.cc b/src/wasm/wasm-js.cc index 40c6ee100c..fd078ec477 100644 --- a/src/wasm/wasm-js.cc +++ b/src/wasm/wasm-js.cc @@ -771,10 +771,10 @@ void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo& args) { EXTRACT_THIS(receiver, WasmMemoryObject); int64_t delta_size = 0; - if (args.Length() < 1 || !args[0]->IntegerValue(context).To(&delta_size)) { - thrower.TypeError("Argument 0 required, must be numeric value of pages"); + if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&delta_size)) { return; } + int64_t max_size64 = receiver->maximum_pages(); if (max_size64 < 0 || max_size64 > static_cast(i::FLAG_wasm_max_mem_pages)) { diff --git a/test/mjsunit/wasm/js-api.js b/test/mjsunit/wasm/js-api.js index 352f7caefa..2015f46ec1 100644 --- a/test/mjsunit/wasm/js-api.js +++ b/test/mjsunit/wasm/js-api.js @@ -16,7 +16,7 @@ function unexpectedFail(error) { } function assertEq(val, expected) { - assertEquals(expected, val); + assertSame(expected, val); } function assertArrayBuffer(val, expected) { assertTrue(val instanceof ArrayBuffer); @@ -512,13 +512,40 @@ assertTrue(buf !== mem.buffer); assertEq(buf.byteLength, 0); buf = mem.buffer; 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); assertEq(buf.byteLength, 0); buf = mem.buffer; assertEq(buf.byteLength, 2 * kPageSize); 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); +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_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, maximum: 1.5, element: 'anyfunc'}) instanceof Table); -// TODO:maximum assertTrue(new Table({initial:1, maximum:Math.pow(2,32)-1, -// element:"anyfunc"}) instanceof Table); +assertTrue( + new Table({initial: 1, maximum: Math.pow(2, 32) - 1, element: 'anyfunc'}) + instanceof Table); // 'WebAssembly.Table.prototype' data property let tableProtoDesc = Object.getOwnPropertyDescriptor(Table, 'prototype'); @@ -623,15 +651,17 @@ assertErrorMessage( () => get.call(), TypeError, /called on incompatible undefined/); assertErrorMessage( () => get.call({}), TypeError, /called on incompatible Object/); +assertEq(get.call(tbl1), 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.5), null); assertErrorMessage(() => get.call(tbl1, 2), RangeError, /bad Table get index/); assertErrorMessage( () => get.call(tbl1, 2.5), 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, -// /bad Table get index/); +assertErrorMessage( + () => get.call(tbl1, Math.pow(2, 33)), RangeError, /bad Table get index/); assertErrorMessage( () => get.call(tbl1, {valueOf() { throw new Error('hi') }}), Error, 'hi'); @@ -650,15 +680,26 @@ assertErrorMessage( () => set.call({}), TypeError, /called on incompatible Object/); assertErrorMessage( () => set.call(tbl1, 0), TypeError, /requires more than 1 argument/); +assertErrorMessage( + () => set.call(tbl1, undefined), TypeError, + /requires more than 1 argument/); assertErrorMessage( () => set.call(tbl1, 2, null), RangeError, /bad Table set index/); assertErrorMessage( () => set.call(tbl1, -1, null), RangeError, /bad Table set index/); -// TODO assertErrorMessage(() => set.call(tbl1, Math.pow(2,33), null), -// RangeError, /bad Table set index/); +assertErrorMessage( + () => 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( () => set.call(tbl1, 0, undefined), TypeError, /can only assign WebAssembly exported functions to Table/); +assertErrorMessage( + () => set.call(tbl1, undefined, undefined), TypeError, + /can only assign WebAssembly exported functions to Table/); assertErrorMessage( () => set.call(tbl1, 0, {}), TypeError, /can only assign WebAssembly exported functions to Table/); @@ -672,6 +713,7 @@ assertErrorMessage( 'hai'); assertEq(set.call(tbl1, 0, null), undefined); assertEq(set.call(tbl1, 1, null), undefined); +assertEq(set.call(tbl1, undefined, null), undefined); // 'WebAssembly.Table.prototype.grow' data property let tblGrowDesc = Object.getOwnPropertyDescriptor(tableProto, 'grow'); @@ -693,11 +735,21 @@ assertErrorMessage( /bad Table grow delta/); var tbl = new Table({element: 'anyfunc', initial: 1, maximum: 2}); 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.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); 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 assertErrorMessage(() => WebAssembly.validate(), TypeError);