v8/test/mjsunit/wasm/js-api.js
gdeepti e6d13999fd [wasm] Memory buffer should be detached after Memory.Grow
Memory.Grow should detach the ArrayBuffer associated with the Mem object after Grow. Currently, when guard pages are enabled protection is changed to make more of the buffer accessible. This does not work for when the buffer should be detached after grow, because the memory object has a reference to the same buffer befor/after grow.

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

Review-Url: https://codereview.chromium.org/2653183003
Cr-Commit-Position: refs/heads/master@{#42717}
2017-01-26 22:15:59 +00:00

706 lines
32 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 --allow-natives-syntax
if ((typeof drainJobQueue) != "function") {
drainJobQueue = () => { %RunMicrotasks() };
}
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
function assertEq(val, expected) {
assertEquals(expected, val);
}
function assertArrayBuffer(val, expected) {
assertTrue(val instanceof ArrayBuffer);
assertEq(expected.length, val.byteLength);
var input = new Int8Array(val);
for (var i = 0; i < expected.length; i++) {
assertEq(expected[i], input[i]);
}
}
function wasmIsSupported() {
return (typeof WebAssembly.Module) == "function";
}
function assertErrorMessage(func, type, msg) {
//TODO assertThrows(func, type, msg);
assertThrows(func, type);
}
let emptyModuleBinary = (() => {
var builder = new WasmModuleBuilder();
return new Int8Array(builder.toBuffer());
})();
let exportingModuleBinary = (() => {
var builder = new WasmModuleBuilder();
builder.addFunction("f", kSig_i_v)
.addBody([kExprI32Const, 42])
.exportAs("f");
return new Int8Array(builder.toBuffer());
})();
let importingModuleBinary = (() => {
var builder = new WasmModuleBuilder();
builder.addImport("", "f", kSig_i_v);
return new Int8Array(builder.toBuffer());
})();
let memoryImportingModuleBinary = (() => {
var builder = new WasmModuleBuilder();
builder.addImportedMemory("", "my_memory");
return new Int8Array(builder.toBuffer());
})();
let moduleBinaryImporting2Memories = (() => {
var builder = new WasmModuleBuilder();
builder.addImportedMemory("", "memory1");
builder.addImportedMemory("", "memory2");
return new Int8Array(builder.toBuffer());
})();
let moduleBinaryWithMemSectionAndMemImport = (() => {
var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, false);
builder.addImportedMemory("", "memory1");
return new Int8Array(builder.toBuffer());
})();
// 'WebAssembly' data property on global object
let wasmDesc = Object.getOwnPropertyDescriptor(this, 'WebAssembly');
assertEq(typeof wasmDesc.value, "object");
assertTrue(wasmDesc.writable);
assertFalse(wasmDesc.enumerable);
assertTrue(wasmDesc.configurable);
// 'WebAssembly' object
assertEq(WebAssembly, wasmDesc.value);
assertEq(String(WebAssembly), "[object WebAssembly]");
// 'WebAssembly.CompileError'
let compileErrorDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'CompileError');
assertEq(typeof compileErrorDesc.value, "function");
assertTrue(compileErrorDesc.writable);
assertFalse(compileErrorDesc.enumerable);
assertTrue(compileErrorDesc.configurable);
let CompileError = WebAssembly.CompileError;
assertEq(CompileError, compileErrorDesc.value);
assertEq(CompileError.length, 1);
assertEq(CompileError.name, "CompileError");
let compileError = new CompileError;
assertTrue(compileError instanceof CompileError);
assertTrue(compileError instanceof Error);
assertFalse(compileError instanceof TypeError);
assertEq(compileError.message, "");
assertEq(new CompileError("hi").message, "hi");
// 'WebAssembly.RuntimeError'
let runtimeErrorDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'RuntimeError');
assertEq(typeof runtimeErrorDesc.value, "function");
assertTrue(runtimeErrorDesc.writable);
assertFalse(runtimeErrorDesc.enumerable);
assertTrue(runtimeErrorDesc.configurable);
let RuntimeError = WebAssembly.RuntimeError;
assertEq(RuntimeError, runtimeErrorDesc.value);
assertEq(RuntimeError.length, 1);
assertEq(RuntimeError.name, "RuntimeError");
let runtimeError = new RuntimeError;
assertTrue(runtimeError instanceof RuntimeError);
assertTrue(runtimeError instanceof Error);
assertFalse(runtimeError instanceof TypeError);
assertEq(runtimeError.message, "");
assertEq(new RuntimeError("hi").message, "hi");
// 'WebAssembly.LinkError'
let linkErrorDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'LinkError');
assertEq(typeof linkErrorDesc.value, "function");
assertTrue(linkErrorDesc.writable);
assertFalse(linkErrorDesc.enumerable);
assertTrue(linkErrorDesc.configurable);
let LinkError = WebAssembly.LinkError;
assertEq(LinkError, linkErrorDesc.value);
assertEq(LinkError.length, 1);
assertEq(LinkError.name, "LinkError");
let linkError = new LinkError;
assertTrue(linkError instanceof LinkError);
assertTrue(linkError instanceof Error);
assertFalse(linkError instanceof TypeError);
assertEq(linkError.message, "");
assertEq(new LinkError("hi").message, "hi");
// 'WebAssembly.Module' data property
let moduleDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'Module');
assertEq(typeof moduleDesc.value, "function");
assertTrue(moduleDesc.writable);
assertFalse(moduleDesc.enumerable);
assertTrue(moduleDesc.configurable);
// 'WebAssembly.Module' constructor function
let Module = WebAssembly.Module;
assertEq(Module, moduleDesc.value);
assertEq(Module.length, 1);
assertEq(Module.name, "Module");
assertErrorMessage(() => Module(), TypeError, /constructor without new is forbidden/);
assertErrorMessage(() => new Module(), TypeError, /requires more than 0 arguments/);
assertErrorMessage(() => new Module(undefined), TypeError, "first argument must be an ArrayBuffer or typed array object");
assertErrorMessage(() => new Module(1), TypeError, "first argument must be an ArrayBuffer or typed array object");
assertErrorMessage(() => new Module({}), TypeError, "first argument must be an ArrayBuffer or typed array object");
assertErrorMessage(() => new Module(new Uint8Array()), CompileError, /failed to match magic number/);
assertErrorMessage(() => new Module(new ArrayBuffer()), CompileError, /failed to match magic number/);
assertTrue(new Module(emptyModuleBinary) instanceof Module);
assertTrue(new Module(emptyModuleBinary.buffer) instanceof Module);
// 'WebAssembly.Module.prototype' data property
let moduleProtoDesc = Object.getOwnPropertyDescriptor(Module, 'prototype');
assertEq(typeof moduleProtoDesc.value, "object");
assertFalse(moduleProtoDesc.writable);
assertFalse(moduleProtoDesc.enumerable);
assertFalse(moduleProtoDesc.configurable);
// 'WebAssembly.Module.prototype' object
let moduleProto = Module.prototype;
assertEq(moduleProto, moduleProtoDesc.value);
assertEq(String(moduleProto), "[object WebAssembly.Module]");
assertEq(Object.getPrototypeOf(moduleProto), Object.prototype);
// 'WebAssembly.Module' instance objects
let emptyModule = new Module(emptyModuleBinary);
let importingModule = new Module(importingModuleBinary);
let exportingModule = new Module(exportingModuleBinary);
assertEq(typeof emptyModule, "object");
assertEq(String(emptyModule), "[object WebAssembly.Module]");
assertEq(Object.getPrototypeOf(emptyModule), moduleProto);
// 'WebAssembly.Module.imports' data property
let moduleImportsDesc = Object.getOwnPropertyDescriptor(Module, 'imports');
assertEq(typeof moduleImportsDesc.value, "function");
assertTrue(moduleImportsDesc.writable);
assertFalse(moduleImportsDesc.enumerable);
assertTrue(moduleImportsDesc.configurable);
// 'WebAssembly.Module.imports' method
let moduleImports = moduleImportsDesc.value;
assertEq(moduleImports.length, 1);
assertErrorMessage(() => moduleImports(), TypeError, /requires more than 0 arguments/);
assertErrorMessage(() => moduleImports(undefined), TypeError, /first argument must be a WebAssembly.Module/);
assertErrorMessage(() => moduleImports({}), TypeError, /first argument must be a WebAssembly.Module/);
var arr = moduleImports(new Module(emptyModuleBinary));
assertTrue(arr instanceof Array);
assertEq(arr.length, 0);
let importingModuleBinary2 = (() => {
var text = '(module (func (import "a" "b")) (memory (import "c" "d") 1) (table (import "e" "f") 1 anyfunc) (global (import "g" "⚡") i32))'
let builder = new WasmModuleBuilder();
builder.addImport("a", "b", kSig_i_i);
builder.addImportedMemory("c", "d");
builder.addImportedTable("e", "f");
builder.addImportedGlobal("g", "x", kWasmI32);
return new Int8Array(builder.toBuffer());
})();
var arr = moduleImports(new Module(importingModuleBinary2));
assertTrue(arr instanceof Array);
assertEq(arr.length, 4);
assertEq(arr[0].kind, "function");
assertEq(arr[0].module, "a");
assertEq(arr[0].name, "b");
assertEq(arr[1].kind, "memory");
assertEq(arr[1].module, "c");
assertEq(arr[1].name, "d");
assertEq(arr[2].kind, "table");
assertEq(arr[2].module, "e");
assertEq(arr[2].name, "f");
assertEq(arr[3].kind, "global");
assertEq(arr[3].module, "g");
assertEq(arr[3].name, "x");
// 'WebAssembly.Module.exports' data property
let moduleExportsDesc = Object.getOwnPropertyDescriptor(Module, 'exports');
assertEq(typeof moduleExportsDesc.value, "function");
assertTrue(moduleExportsDesc.writable);
assertFalse(moduleExportsDesc.enumerable);
assertTrue(moduleExportsDesc.configurable);
// 'WebAssembly.Module.exports' method
let moduleExports = moduleExportsDesc.value;
assertEq(moduleExports.length, 1);
assertErrorMessage(() => moduleExports(), TypeError, /requires more than 0 arguments/);
assertErrorMessage(() => moduleExports(undefined), TypeError, /first argument must be a WebAssembly.Module/);
assertErrorMessage(() => moduleExports({}), TypeError, /first argument must be a WebAssembly.Module/);
var arr = moduleExports(emptyModule);
assertTrue(arr instanceof Array);
assertEq(arr.length, 0);
let exportingModuleBinary2 = (() => {
var text =
'(module (func (export "a")) (memory (export "b") 1) (table (export "c") 1 anyfunc) (global (export "⚡") i32 (i32.const 0)))';
let builder = new WasmModuleBuilder();
builder.addFunction("foo", kSig_v_v)
.addBody([])
.exportAs("a");
builder.addMemory(1, 1, false);
builder.exportMemoryAs("b");
builder.setFunctionTableLength(1);
builder.addExportOfKind("c", kExternalTable, 0);
var o = builder.addGlobal(kWasmI32, false)
.exportAs("x");
return new Int8Array(builder.toBuffer());
})();
var arr = moduleExports(new Module(exportingModuleBinary2));
assertTrue(arr instanceof Array);
assertEq(arr.length, 4);
assertEq(arr[0].kind, "function");
assertEq(arr[0].name, "a");
assertEq(arr[1].kind, "memory");
assertEq(arr[1].name, "b");
assertEq(arr[2].kind, "table");
assertEq(arr[2].name, "c");
assertEq(arr[3].kind, "global");
assertEq(arr[3].name, "x");
// 'WebAssembly.Module.customSections' data property
let moduleCustomSectionsDesc =
Object.getOwnPropertyDescriptor(Module, 'customSections');
assertEq(typeof moduleCustomSectionsDesc.value, 'function');
assertEq(moduleCustomSectionsDesc.writable, true);
assertEq(moduleCustomSectionsDesc.enumerable, false);
assertEq(moduleCustomSectionsDesc.configurable, true);
let moduleCustomSections = moduleCustomSectionsDesc.value;
assertEq(moduleCustomSections.length, 2);
assertErrorMessage(
() => moduleCustomSections(), TypeError, /requires more than 0 arguments/);
assertErrorMessage(
() => moduleCustomSections(undefined), TypeError,
/first argument must be a WebAssembly.Module/);
assertErrorMessage(
() => moduleCustomSections({}), TypeError,
/first argument must be a WebAssembly.Module/);
var arr = moduleCustomSections(emptyModule, 'x');
assertEq(arr instanceof Array, true);
assertEq(arr.length, 0);
assertErrorMessage(
() => moduleCustomSections(1), TypeError,
'first argument must be a WebAssembly.Module');
assertErrorMessage(
() => moduleCustomSections(emptyModule), TypeError,
'second argument must be a String');
assertErrorMessage(
() => moduleCustomSections(emptyModule, 3), TypeError,
'second argument must be a String');
let customSectionModuleBinary2 = (() => {
let builder = new WasmModuleBuilder();
builder.addCustomSection('x', [2]);
builder.addCustomSection('foo', [66, 77]);
builder.addCustomSection('foo', [91, 92, 93]);
builder.addCustomSection('fox', [99, 99, 99]);
return new Int8Array(builder.toBuffer());
})();
var arr = moduleCustomSections(new Module(customSectionModuleBinary2), 'x');
assertEq(arr instanceof Array, true);
assertEq(arr.length, 1);
assertArrayBuffer(arr[0], [2]);
var arr = moduleCustomSections(new Module(customSectionModuleBinary2), 'foo');
assertEq(arr instanceof Array, true);
assertEq(arr.length, 2);
assertArrayBuffer(arr[0], [66, 77]);
assertArrayBuffer(arr[1], [91, 92, 93]);
var arr = moduleCustomSections(new Module(customSectionModuleBinary2), 'bar');
assertEq(arr instanceof Array, true);
assertEq(arr.length, 0);
// 'WebAssembly.Instance' data property
let instanceDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'Instance');
assertEq(typeof instanceDesc.value, "function");
assertTrue(instanceDesc.writable);
assertFalse(instanceDesc.enumerable);
assertTrue(instanceDesc.configurable);
// 'WebAssembly.Instance' constructor function
let Instance = WebAssembly.Instance;
assertEq(Instance, instanceDesc.value);
assertEq(Instance.length, 1);
assertEq(Instance.name, "Instance");
assertErrorMessage(() => Instance(), TypeError, /constructor without new is forbidden/);
assertErrorMessage(() => new Instance(1), TypeError, "first argument must be a WebAssembly.Module");
assertErrorMessage(() => new Instance({}), TypeError, "first argument must be a WebAssembly.Module");
assertErrorMessage(() => new Instance(emptyModule, null), TypeError, "second argument must be an object");
assertErrorMessage(() => new Instance(importingModule, null), TypeError, "");
assertErrorMessage(() => new Instance(importingModule, undefined), TypeError, "");
assertErrorMessage(() => new Instance(importingModule, {"":{g:()=>{}}}), LinkError, "");
assertErrorMessage(() => new Instance(importingModule, {t:{f:()=>{}}}), LinkError, "");
assertTrue(new Instance(emptyModule) instanceof Instance);
assertTrue(new Instance(emptyModule, {}) instanceof Instance);
// 'WebAssembly.Instance.prototype' data property
let instanceProtoDesc = Object.getOwnPropertyDescriptor(Instance, 'prototype');
assertEq(typeof instanceProtoDesc.value, "object");
assertFalse(instanceProtoDesc.writable);
assertFalse(instanceProtoDesc.enumerable);
assertFalse(instanceProtoDesc.configurable);
// 'WebAssembly.Instance.prototype' object
let instanceProto = Instance.prototype;
assertEq(instanceProto, instanceProtoDesc.value);
assertEq(String(instanceProto), "[object WebAssembly.Instance]");
assertEq(Object.getPrototypeOf(instanceProto), Object.prototype);
// 'WebAssembly.Instance' instance objects
let exportingInstance = new Instance(exportingModule);
assertEq(typeof exportingInstance, "object");
assertEq(String(exportingInstance), "[object WebAssembly.Instance]");
assertEq(Object.getPrototypeOf(exportingInstance), instanceProto);
// 'WebAssembly.Instance' 'exports' data property
let instanceExportsDesc = Object.getOwnPropertyDescriptor(exportingInstance, 'exports');
assertEq(typeof instanceExportsDesc.value, "object");
assertTrue(instanceExportsDesc.writable);
assertTrue(instanceExportsDesc.enumerable);
assertTrue(instanceExportsDesc.configurable);
exportsObj = exportingInstance.exports;
assertEq(typeof exportsObj, 'object');
assertFalse(Object.isExtensible(exportsObj));
assertEq(Object.getPrototypeOf(exportsObj), null);
assertEq(Object.keys(exportsObj).join(), 'f');
// Exported WebAssembly functions
let f = exportingInstance.exports.f;
assertTrue(f instanceof Function);
assertEq(f.length, 0);
assertTrue('name' in f);
assertEq(Function.prototype.call.call(f), 42);
assertErrorMessage(() => new f(), TypeError, /is not a constructor/);
// 'WebAssembly.Memory' data property
let memoryDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'Memory');
assertEq(typeof memoryDesc.value, "function");
assertTrue(memoryDesc.writable);
assertFalse(memoryDesc.enumerable);
assertTrue(memoryDesc.configurable);
// 'WebAssembly.Memory' constructor function
let Memory = WebAssembly.Memory;
assertEq(Memory, memoryDesc.value);
assertEq(Memory.length, 1);
assertEq(Memory.name, "Memory");
assertErrorMessage(() => Memory(), TypeError, /constructor without new is forbidden/);
assertErrorMessage(() => new Memory(1), TypeError, "first argument must be a memory descriptor");
assertErrorMessage(() => new Memory({initial:{valueOf() { throw new Error("here")}}}), Error, "here");
assertErrorMessage(() => new Memory({initial:-1}), RangeError, /bad Memory initial size/);
assertErrorMessage(() => new Memory({initial:Math.pow(2,32)}), RangeError, /bad Memory initial size/);
assertErrorMessage(() => new Memory({initial:1, maximum: Math.pow(2,32)/Math.pow(2,14) }), RangeError, /bad Memory maximum size/);
assertErrorMessage(() => new Memory({initial:2, maximum:1 }), RangeError, /bad Memory maximum size/);
assertErrorMessage(() => new Memory({maximum: -1 }), RangeError, /bad Memory maximum size/);
assertTrue(new Memory({initial: 1}) instanceof Memory);
assertEq(new Memory({initial:1.5}).buffer.byteLength, kPageSize);
// 'WebAssembly.Memory.prototype' data property
let memoryProtoDesc = Object.getOwnPropertyDescriptor(Memory, 'prototype');
assertEq(typeof memoryProtoDesc.value, "object");
assertFalse(memoryProtoDesc.writable);
assertFalse(memoryProtoDesc.enumerable);
assertFalse(memoryProtoDesc.configurable);
// 'WebAssembly.Memory.prototype' object
let memoryProto = Memory.prototype;
assertEq(memoryProto, memoryProtoDesc.value);
assertEq(String(memoryProto), "[object WebAssembly.Memory]");
assertEq(Object.getPrototypeOf(memoryProto), Object.prototype);
// 'WebAssembly.Memory' instance objects
let mem1 = new Memory({initial:1});
assertEq(typeof mem1, "object");
assertEq(String(mem1), "[object WebAssembly.Memory]");
assertEq(Object.getPrototypeOf(mem1), memoryProto);
// 'WebAssembly.Memory.prototype.buffer' accessor property
let bufferDesc = Object.getOwnPropertyDescriptor(memoryProto, 'buffer');
assertEq(typeof bufferDesc.get, "function");
assertEq(bufferDesc.set, undefined);
assertFalse(bufferDesc.enumerable);
assertTrue(bufferDesc.configurable);
// 'WebAssembly.Memory.prototype.buffer' getter
let bufferGetter = bufferDesc.get;
assertErrorMessage(() => bufferGetter.call(), TypeError, /called on incompatible undefined/);
assertErrorMessage(() => bufferGetter.call({}), TypeError, /called on incompatible Object/);
assertTrue(bufferGetter.call(mem1) instanceof ArrayBuffer);
assertEq(bufferGetter.call(mem1).byteLength, kPageSize);
// 'WebAssembly.Memory.prototype.grow' data property
let memGrowDesc = Object.getOwnPropertyDescriptor(memoryProto, 'grow');
assertEq(typeof memGrowDesc.value, "function");
assertFalse(memGrowDesc.enumerable);
assertTrue(memGrowDesc.configurable);
// 'WebAssembly.Memory.prototype.grow' method
let memGrow = memGrowDesc.value;
assertEq(memGrow.length, 1);
assertErrorMessage(() => memGrow.call(), TypeError,
/called on incompatible undefined/);
assertErrorMessage(() => memGrow.call({}), TypeError,
/called on incompatible Object/);
assertErrorMessage(() => memGrow.call(mem1, -1), RangeError,
/bad Memory grow delta/);
assertErrorMessage(() => memGrow.call(mem1, Math.pow(2,32)), RangeError,
/bad Memory grow delta/);
var mem = new Memory({initial:1, maximum:2});
var buf = mem.buffer;
assertEq(buf.byteLength, kPageSize);
assertEq(mem.grow(0), 1);
assertTrue(buf !== mem.buffer);
assertEq(buf.byteLength, 0);
buf = mem.buffer;
assertEq(buf.byteLength, kPageSize);
assertEq(mem.grow(1), 1);
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/);
assertEq(buf, mem.buffer);
// 'WebAssembly.Table' data property
let tableDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'Table');
assertEq(typeof tableDesc.value, "function");
assertTrue(tableDesc.writable);
assertFalse(tableDesc.enumerable);
assertTrue(tableDesc.configurable);
// 'WebAssembly.Table' constructor function
let Table = WebAssembly.Table;
assertEq(Table, tableDesc.value);
assertEq(Table.length, 1);
assertEq(Table.name, "Table");
assertErrorMessage(() => Table(), TypeError, /constructor without new is forbidden/);
assertErrorMessage(() => new Table(1), TypeError, "first argument must be a table descriptor");
assertErrorMessage(() => new Table({initial:1, element:1}), TypeError, /must be "anyfunc"/);
assertErrorMessage(() => new Table({initial:1, element:"any"}), TypeError, /must be "anyfunc"/);
assertErrorMessage(() => new Table({initial:1, element:{valueOf() { return "anyfunc" }}}), TypeError, /must be "anyfunc"/);
assertErrorMessage(() => new Table({initial:{valueOf() { throw new Error("here")}}, element:"anyfunc"}), Error, "here");
assertErrorMessage(() => new Table({initial:-1, element:"anyfunc"}), RangeError, /bad Table initial size/);
assertErrorMessage(() => new Table({initial:Math.pow(2,32), element:"anyfunc"}), RangeError, /bad Table initial size/);
assertErrorMessage(() => new Table({initial:2, maximum:1, element:"anyfunc"}), RangeError, /bad Table maximum size/);
assertErrorMessage(() => new Table({initial:2, maximum:Math.pow(2,32), element:"anyfunc"}), RangeError, /bad Table maximum size/);
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);
// 'WebAssembly.Table.prototype' data property
let tableProtoDesc = Object.getOwnPropertyDescriptor(Table, 'prototype');
assertEq(typeof tableProtoDesc.value, "object");
assertFalse(tableProtoDesc.writable);
assertFalse(tableProtoDesc.enumerable);
assertFalse(tableProtoDesc.configurable);
// 'WebAssembly.Table.prototype' object
let tableProto = Table.prototype;
assertEq(tableProto, tableProtoDesc.value);
assertEq(String(tableProto), "[object WebAssembly.Table]");
assertEq(Object.getPrototypeOf(tableProto), Object.prototype);
// 'WebAssembly.Table' instance objects
let tbl1 = new Table({initial:2, element:"anyfunc"});
assertEq(typeof tbl1, "object");
assertEq(String(tbl1), "[object WebAssembly.Table]");
assertEq(Object.getPrototypeOf(tbl1), tableProto);
// 'WebAssembly.Table.prototype.length' accessor data property
let lengthDesc = Object.getOwnPropertyDescriptor(tableProto, 'length');
assertEq(typeof lengthDesc.get, "function");
assertEq(lengthDesc.set, undefined);
assertFalse(lengthDesc.enumerable);
assertTrue(lengthDesc.configurable);
// 'WebAssembly.Table.prototype.length' getter
let lengthGetter = lengthDesc.get;
assertEq(lengthGetter.length, 0);
assertErrorMessage(() => lengthGetter.call(), TypeError, /called on incompatible undefined/);
assertErrorMessage(() => lengthGetter.call({}), TypeError, /called on incompatible Object/);
assertEq(typeof lengthGetter.call(tbl1), "number");
assertEq(lengthGetter.call(tbl1), 2);
// 'WebAssembly.Table.prototype.get' data property
let getDesc = Object.getOwnPropertyDescriptor(tableProto, 'get');
assertEq(typeof getDesc.value, "function");
assertFalse(getDesc.enumerable);
assertTrue(getDesc.configurable);
// 'WebAssembly.Table.prototype.get' method
let get = getDesc.value;
assertEq(get.length, 1);
assertErrorMessage(() => get.call(), TypeError, /called on incompatible undefined/);
assertErrorMessage(() => get.call({}), TypeError, /called on incompatible Object/);
assertEq(get.call(tbl1, 0), 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, {valueOf() { throw new Error("hi") }}), Error, "hi");
// 'WebAssembly.Table.prototype.set' data property
let setDesc = Object.getOwnPropertyDescriptor(tableProto, 'set');
assertEq(typeof setDesc.value, "function");
assertFalse(setDesc.enumerable);
assertTrue(setDesc.configurable);
// 'WebAssembly.Table.prototype.set' method
let set = setDesc.value;
assertEq(set.length, 2);
assertErrorMessage(() => set.call(), TypeError, /called on incompatible undefined/);
assertErrorMessage(() => set.call({}), TypeError, /called on incompatible Object/);
assertErrorMessage(() => set.call(tbl1, 0), 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, 0, undefined), TypeError, /can only assign WebAssembly exported functions to Table/);
assertErrorMessage(() => set.call(tbl1, 0, {}), TypeError, /can only assign WebAssembly exported functions to Table/);
assertErrorMessage(() => set.call(tbl1, 0, function() {}), TypeError, /can only assign WebAssembly exported functions to Table/);
assertErrorMessage(() => set.call(tbl1, 0, Math.sin), TypeError, /can only assign WebAssembly exported functions to Table/);
assertErrorMessage(() => set.call(tbl1, {valueOf() { throw Error("hai") }}, null), Error, "hai");
assertEq(set.call(tbl1, 0, null), undefined);
assertEq(set.call(tbl1, 1, null), undefined);
// 'WebAssembly.Table.prototype.grow' data property
let tblGrowDesc = Object.getOwnPropertyDescriptor(tableProto, 'grow');
assertEq(typeof tblGrowDesc.value, "function");
assertFalse(tblGrowDesc.enumerable);
assertTrue(tblGrowDesc.configurable);
// 'WebAssembly.Table.prototype.grow' method
let tblGrow = tblGrowDesc.value;
assertEq(tblGrow.length, 1);
assertErrorMessage(() => tblGrow.call(), TypeError, /called on incompatible undefined/);
assertErrorMessage(() => tblGrow.call({}), TypeError, /called on incompatible Object/);
assertErrorMessage(() => tblGrow.call(tbl1, -1), RangeError, /bad Table grow delta/);
assertErrorMessage(() => tblGrow.call(tbl1, Math.pow(2,32)), RangeError, /bad Table grow delta/);
var tbl = new Table({element:"anyfunc", initial:1, maximum:2});
assertEq(tbl.length, 1);
assertEq(tbl.grow(0), 1);
assertEq(tbl.length, 1);
assertEq(tbl.grow(1), 1);
assertEq(tbl.length, 2);
assertErrorMessage(() => tbl.grow(1), Error, /failed to grow table/);
// 'WebAssembly.validate' function
assertErrorMessage(() => WebAssembly.validate(), TypeError);
assertErrorMessage(() => WebAssembly.validate("hi"), TypeError);
assertTrue(WebAssembly.validate(emptyModuleBinary));
// TODO: other ways for validate to return false.
assertFalse(WebAssembly.validate(moduleBinaryImporting2Memories));
assertFalse(WebAssembly.validate(moduleBinaryWithMemSectionAndMemImport));
// 'WebAssembly.compile' data property
let compileDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'compile');
assertEq(typeof compileDesc.value, "function");
assertTrue(compileDesc.writable);
assertFalse(compileDesc.enumerable);
assertTrue(compileDesc.configurable);
// 'WebAssembly.compile' function
let compile = WebAssembly.compile;
assertEq(compile, compileDesc.value);
assertEq(compile.length, 1);
assertEq(compile.name, "compile");
function assertCompileError(args, err, msg) {
var error = null;
compile(...args).catch(e => error = e);
drainJobQueue();
assertTrue(error instanceof err);
assertTrue(Boolean(error.stack.match('js-api.js')));
// TODO assertTrue(Boolean(error.message.match(msg)));
}
assertCompileError([], TypeError, /requires more than 0 arguments/);
assertCompileError([undefined], TypeError, /first argument must be an ArrayBuffer or typed array object/);
assertCompileError([1], TypeError, /first argument must be an ArrayBuffer or typed array object/);
assertCompileError([{}], TypeError, /first argument must be an ArrayBuffer or typed array object/);
assertCompileError([new Uint8Array()], CompileError, /BufferSource argument is empty/);
assertCompileError([new ArrayBuffer()], CompileError, /BufferSource argument is empty/);
assertCompileError([new Uint8Array("hi!")], CompileError, /failed to match magic number/);
assertCompileError([new ArrayBuffer("hi!")], CompileError, /failed to match magic number/);
function assertCompileSuccess(bytes) {
var module = null;
compile(bytes).then(m => module = m);
drainJobQueue();
assertTrue(module instanceof Module);
}
assertCompileSuccess(emptyModuleBinary);
assertCompileSuccess(emptyModuleBinary.buffer);
// 'WebAssembly.instantiate' data property
let instantiateDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'instantiate');
assertEq(typeof instantiateDesc.value, "function");
assertTrue(instantiateDesc.writable);
assertFalse(instantiateDesc.enumerable);
assertTrue(instantiateDesc.configurable);
// 'WebAssembly.instantiate' function
let instantiate = WebAssembly.instantiate;
assertEq(instantiate, instantiateDesc.value);
assertEq(instantiate.length, 1);
assertEq(instantiate.name, "instantiate");
function assertInstantiateError(args, err, msg) {
var error = null;
instantiate(...args).catch(e => error = e);
drainJobQueue();
assertTrue(error instanceof err);
assertTrue(Boolean(error.stack.match('js-api.js')));
// TODO assertTrue(Boolean(error.message.match(msg)));
}
var scratch_memory = new WebAssembly.Memory(new ArrayBuffer(10));
assertInstantiateError([], TypeError, /requires more than 0 arguments/);
assertInstantiateError([undefined], TypeError, /first argument must be a BufferSource/);
assertInstantiateError([1], TypeError, /first argument must be a BufferSource/);
assertInstantiateError([{}], TypeError, /first argument must be a BufferSource/);
assertInstantiateError([new Uint8Array()], CompileError, /failed to match magic number/);
assertInstantiateError([new ArrayBuffer()], CompileError, /failed to match magic number/);
assertInstantiateError([new Uint8Array("hi!")], CompileError, /failed to match magic number/);
assertInstantiateError([new ArrayBuffer("hi!")], CompileError, /failed to match magic number/);
assertInstantiateError([importingModule], TypeError, /second argument must be an object/);
assertInstantiateError([importingModule, null], TypeError, /second argument must be an object/);
assertInstantiateError([importingModuleBinary, null], TypeError, /second argument must be an object/);
assertInstantiateError([emptyModule, null], TypeError, /first argument must be a BufferSource/);
assertInstantiateError([importingModuleBinary, null], TypeError, /TODO: error messages?/);
assertInstantiateError([importingModuleBinary, undefined], TypeError, /TODO: error messages?/);
assertInstantiateError([importingModuleBinary, {}], LinkError, /TODO: error messages?/);
assertInstantiateError([importingModuleBinary, {"":{g:()=>{}}}], LinkError, /TODO: error messages?/);
assertInstantiateError([importingModuleBinary, {t:{f:()=>{}}}], LinkError, /TODO: error messages?/);
assertInstantiateError([memoryImportingModuleBinary, null], TypeError, /TODO: error messages?/);
assertInstantiateError([memoryImportingModuleBinary, undefined], TypeError, /TODO: error messages?/);
assertInstantiateError([memoryImportingModuleBinary, {}], LinkError, /TODO: error messages?/);
assertInstantiateError([memoryImportingModuleBinary, {"mod": {"my_memory": scratch_memory}}], LinkError, /TODO: error messages?/);
assertInstantiateError([memoryImportingModuleBinary, {"": {"memory": scratch_memory}}], LinkError, /TODO: error messages?/);
function assertInstantiateSuccess(module_or_bytes, imports) {
var result = null;
instantiate(module_or_bytes, imports)
.then(r => result = r)
.catch(e => print(e));
drainJobQueue();
if (module_or_bytes instanceof Module) {
assertTrue(result instanceof Instance);
} else {
assertTrue(result.module instanceof Module);
assertTrue(result.instance instanceof Instance);
}
}
assertInstantiateSuccess(emptyModule);
assertInstantiateSuccess(emptyModuleBinary);
assertInstantiateSuccess(emptyModuleBinary.buffer);
assertInstantiateSuccess(importingModule, {'': {f: () => {}}});
assertInstantiateSuccess(importingModuleBinary, {"":{f:()=>{}}});
assertInstantiateSuccess(importingModuleBinary.buffer, {"":{f:()=>{}}});
assertInstantiateSuccess(memoryImportingModuleBinary, {"": {"my_memory": scratch_memory}});