Fix WASM Error classes and re-sync wpt/wasm/jsapi from upstream
authorshvaikalesh@gmail.com <shvaikalesh@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 25 Apr 2020 04:58:37 +0000 (04:58 +0000)
committershvaikalesh@gmail.com <shvaikalesh@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 25 Apr 2020 04:58:37 +0000 (04:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=210980

Reviewed by Keith Miller.

JSTests:

* wasm/modules/js-wasm-cycle.js:
* wasm/modules/wasm-wasm-cycle.js:
* wasm/stress/too-many-locals.js:

LayoutTests/imported/w3c:

web-platform-tests revision: 028bd8650758

* web-platform-tests/wasm/jsapi/*: Updated.

Source/JavaScriptCore:

assert_throws_js() harness, which is extensively used by wpt/wasm/jsapi tests,
was recently updated to assert that passed constructors subclass Error in
spec-perfect way.

With this patch, WebAssembly errors have Error as [[Prototype]] of their constructors
and define correct "name" and "message" properties on their prototypes, aligning JSC
with the spec [1], V8 and SpiderMonkey.

[1]: https://webassembly.github.io/spec/js-api/#error-objects

* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* wasm/js/WebAssemblyCompileErrorPrototype.cpp:
(JSC::WebAssemblyCompileErrorPrototype::finishCreation):
* wasm/js/WebAssemblyLinkErrorPrototype.cpp:
(JSC::WebAssemblyLinkErrorPrototype::finishCreation):
* wasm/js/WebAssemblyRuntimeErrorPrototype.cpp:
(JSC::WebAssemblyRuntimeErrorPrototype::finishCreation):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@260690 268f45cc-cd09-0410-ab3c-d52691b4dbfc

135 files changed:
JSTests/ChangeLog
JSTests/wasm/modules/js-wasm-cycle.js
JSTests/wasm/modules/wasm-wasm-cycle.js
JSTests/wasm/stress/too-many-locals.js
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/assertions.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/bad-imports.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.worker-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.worker.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate-bad-imports.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate-bad-imports.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate-bad-imports.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.worker-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.worker.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.worker-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.worker.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.worker-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.worker.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/w3c-import.log
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/error-interfaces-no-symbol-tostringtag.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/constructor.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/constructor.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/constructor.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/toString.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/toString.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/toString.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any.js [moved from LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-set.any.js with 54% similarity]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any.worker-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any.worker.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-set.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-set.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/valueOf.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/valueOf.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/valueOf.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/w3c-import.log
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.worker-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.worker.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-bad-imports.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-bad-imports.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-bad-imports.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.worker-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.worker.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/exports.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/exports.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/exports.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/toString.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/toString.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/toString.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/w3c-import.log
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instanceTestFactory.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/interface.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/interface.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/interface.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/memory/buffer.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/memory/buffer.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/memory/buffer.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/memory/constructor.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/memory/constructor.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/memory/constructor.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/memory/grow.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/memory/grow.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/memory/grow.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/memory/toString.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/memory/toString.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/memory/toString.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/constructor.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/constructor.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/constructor.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/customSections.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/customSections.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/customSections.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/exports.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/exports.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/exports.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/imports.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/imports.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/imports.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/toString.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/toString.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/module/toString.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/proto-from-ctor-realm-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/proto-from-ctor-realm.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/assertions.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/constructor.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/constructor.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/constructor.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/get-set.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/get-set.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/get-set.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.worker-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.worker.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/length.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/length.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/length.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/toString.any-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/toString.any.js
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/toString.any.worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/w3c-import.log
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/w3c-import.log
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/wasm-constants.js [deleted file]
LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/wasm-module-builder.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyCompileErrorPrototype.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyLinkErrorPrototype.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyRuntimeErrorPrototype.cpp

index 41e3b0d..24acb74 100644 (file)
@@ -1,3 +1,14 @@
+2020-04-24  Alexey Shvayka  <shvaikalesh@gmail.com>
+
+        Fix WASM Error classes and re-sync wpt/wasm/jsapi from upstream
+        https://bugs.webkit.org/show_bug.cgi?id=210980
+
+        Reviewed by Keith Miller.
+
+        * wasm/modules/js-wasm-cycle.js:
+        * wasm/modules/wasm-wasm-cycle.js:
+        * wasm/stress/too-many-locals.js:
+
 2020-04-24  Saam Barati  <sbarati@apple.com>
 
         Return BigInt32 whenever we can
index 94f0f86..fefd0b5 100644 (file)
@@ -1,4 +1,4 @@
 import * as assert from '../assert.js';
 import("./js-wasm-cycle/entry.js").then($vm.abort, function (error) {
-    assert.eq(String(error), `Error: import function ./entry.js:return42 must be callable`);
+    assert.eq(String(error), `LinkError: import function ./entry.js:return42 must be callable`);
 }).then(function () { }, $vm.abort);
index b1a504e..6becaeb 100644 (file)
@@ -1,4 +1,4 @@
 import * as assert from '../assert.js';
 import("./wasm-wasm-cycle/entry.wasm").then($vm.abort, function (error) {
-    assert.eq(String(error), `Error: import function ./entry.wasm:return42 must be callable`);
+    assert.eq(String(error), `LinkError: import function ./entry.wasm:return42 must be callable`);
 }).then(function () { }, $vm.abort);
index c046d32..bea5583 100644 (file)
@@ -29,5 +29,5 @@ import * as assert from '../assert.js'
         exception = "" + e;
     }
 
-    assert.eq(exception, "Error: WebAssembly.Module doesn't parse at byte 100002: Function's number of locals is too big 50001 maximum 50000, in function at index 0 (evaluating 'new WebAssembly.Module(bin)')");
+    assert.eq(exception, "CompileError: WebAssembly.Module doesn't parse at byte 100002: Function's number of locals is too big 50001 maximum 50000, in function at index 0 (evaluating 'new WebAssembly.Module(bin)')");
 }
index aaa8bb9..11774f2 100644 (file)
@@ -1,3 +1,14 @@
+2020-04-24  Alexey Shvayka  <shvaikalesh@gmail.com>
+
+        Fix WASM Error classes and re-sync wpt/wasm/jsapi from upstream
+        https://bugs.webkit.org/show_bug.cgi?id=210980
+
+        Reviewed by Keith Miller.
+
+        web-platform-tests revision: 028bd8650758
+
+        * web-platform-tests/wasm/jsapi/*: Updated.
+
 2020-04-24  David Kilzer  <ddkilzer@apple.com>
 
         REGRESSION (r223327): Remove merge conflict file
index 151a406..f00303f 100644 (file)
@@ -15,3 +15,81 @@ function assert_function_length(fn, length, description) {
   assert_true(propdesc.configurable, "configurable", `${description} length should be configurable`);
   assert_equals(propdesc.value, length, `${description} length should be ${length}`);
 }
+
+function assert_exported_function(fn, { name, length }, description) {
+  assert_equals(Object.getPrototypeOf(fn), Function.prototype,
+                `${description}: prototype`);
+
+  assert_function_name(fn, name, description);
+  assert_function_length(fn, length, description);
+}
+
+function assert_Instance(instance, expected_exports) {
+  assert_equals(Object.getPrototypeOf(instance), WebAssembly.Instance.prototype,
+                "prototype");
+  assert_true(Object.isExtensible(instance), "extensible");
+
+  assert_equals(instance.exports, instance.exports, "exports should be idempotent");
+  const exports = instance.exports;
+
+  assert_equals(Object.getPrototypeOf(exports), null, "exports prototype");
+  assert_false(Object.isExtensible(exports), "extensible exports");
+  assert_array_equals(Object.keys(exports), Object.keys(expected_exports), "matching export keys");
+  for (const [key, expected] of Object.entries(expected_exports)) {
+    const property = Object.getOwnPropertyDescriptor(exports, key);
+    assert_equals(typeof property, "object", `${key} should be present`);
+    assert_false(property.writable, `${key}: writable`);
+    assert_true(property.enumerable, `${key}: enumerable`);
+    assert_false(property.configurable, `${key}: configurable`);
+    const actual = property.value;
+    assert_true(Object.isExtensible(actual), `${key}: extensible`);
+
+    switch (expected.kind) {
+    case "function":
+      assert_exported_function(actual, expected, `value of ${key}`);
+      break;
+    case "global":
+      assert_equals(Object.getPrototypeOf(actual), WebAssembly.Global.prototype,
+                    `value of ${key}: prototype`);
+      assert_equals(actual.value, expected.value, `value of ${key}: value`);
+      assert_equals(actual.valueOf(), expected.value, `value of ${key}: valueOf()`);
+      break;
+    case "memory":
+      assert_equals(Object.getPrototypeOf(actual), WebAssembly.Memory.prototype,
+                    `value of ${key}: prototype`);
+      assert_equals(Object.getPrototypeOf(actual.buffer), ArrayBuffer.prototype,
+                    `value of ${key}: prototype of buffer`);
+      assert_equals(actual.buffer.byteLength, 0x10000 * expected.size, `value of ${key}: size of buffer`);
+      const array = new Uint8Array(actual.buffer);
+      assert_equals(array[0], 0, `value of ${key}: first element of buffer`);
+      assert_equals(array[array.byteLength - 1], 0, `value of ${key}: last element of buffer`);
+      break;
+    case "table":
+      assert_equals(Object.getPrototypeOf(actual), WebAssembly.Table.prototype,
+                    `value of ${key}: prototype`);
+      assert_equals(actual.length, expected.length, `value of ${key}: length of table`);
+      break;
+    }
+  }
+}
+
+function assert_WebAssemblyInstantiatedSource(actual, expected_exports={}) {
+  assert_equals(Object.getPrototypeOf(actual), Object.prototype,
+                "Prototype");
+  assert_true(Object.isExtensible(actual), "Extensibility");
+
+  const module = Object.getOwnPropertyDescriptor(actual, "module");
+  assert_equals(typeof module, "object", "module: type of descriptor");
+  assert_true(module.writable, "module: writable");
+  assert_true(module.enumerable, "module: enumerable");
+  assert_true(module.configurable, "module: configurable");
+  assert_equals(Object.getPrototypeOf(module.value), WebAssembly.Module.prototype,
+                "module: prototype");
+
+  const instance = Object.getOwnPropertyDescriptor(actual, "instance");
+  assert_equals(typeof instance, "object", "instance: type of descriptor");
+  assert_true(instance.writable, "instance: writable");
+  assert_true(instance.enumerable, "instance: enumerable");
+  assert_true(instance.configurable, "instance: configurable");
+  assert_Instance(instance.value, expected_exports);
+}
index f076baa..afd4193 100644 (file)
@@ -1,7 +1,19 @@
+/**
+ * `t` should be a function that takes at least three arguments:
+ *
+ * - the name of the test;
+ * - the expected error (to be passed to `assert_throws_js`);
+ * - a function that takes a `WasmModuleBuilder` and initializes it;
+ * - (optionally) an options object.
+ *
+ * The function is expected to create a test that checks if instantiating a
+ * module with the result of the `WasmModuleBuilder` and the options object
+ * (if any) yields the correct error.
+ */
 function test_bad_imports(t) {
   for (const value of [null, true, "", Symbol(), 1, 0.1, NaN]) {
     t(`Non-object imports argument: ${format_value(value)}`,
-      new TypeError(),
+      TypeError,
       builder => {},
       value);
   }
@@ -11,22 +23,22 @@ function test_bad_imports(t) {
       "module": value,
     };
     t(`Non-object module: ${format_value(value)}`,
-      new TypeError(),
+      TypeError,
       builder => {
         builder.addImport("module", "fn", kSig_v_v);
       },
-      value);
+      imports);
   }
 
   t(`Missing imports argument`,
-    new TypeError(),
+    TypeError,
     builder => {
       builder.addImport("module", "fn", kSig_v_v);
     });
 
   for (const [value, name] of [[undefined, "undefined"], [{}, "empty object"], [{ "module\0": null }, "wrong property"]]) {
     t(`Imports argument with missing property: ${name}`,
-      new TypeError(),
+      TypeError,
       builder => {
         builder.addImport("module", "fn", kSig_v_v);
       },
@@ -34,7 +46,7 @@ function test_bad_imports(t) {
   }
 
   t(`Importing an i64 global`,
-    new WebAssembly.LinkError(),
+    WebAssembly.LinkError,
     builder => {
       builder.addImportedGlobal("module", "global", kWasmI64);
     },
@@ -46,7 +58,7 @@ function test_bad_imports(t) {
 
   for (const value of [undefined, null, true, "", Symbol(), 1, 0.1, NaN, {}]) {
     t(`Importing a function with an incorrectly-typed value: ${format_value(value)}`,
-      new WebAssembly.LinkError(),
+      WebAssembly.LinkError,
       builder => {
         builder.addImport("module", "fn", kSig_v_v);
       },
@@ -67,11 +79,12 @@ function test_bad_imports(t) {
     [WebAssembly.Global, "WebAssembly.Global"],
     [WebAssembly.Global.prototype, "WebAssembly.Global.prototype"],
     [Object.create(WebAssembly.Global.prototype), "Object.create(WebAssembly.Global.prototype)"],
+    [new WebAssembly.Global({value: "f32"}), "WebAssembly.Global object (wrong value type)"],
   ];
 
   for (const [value, name = format_value(value)] of nonGlobals) {
     t(`Importing a global with an incorrectly-typed value: ${name}`,
-      new WebAssembly.LinkError(),
+      WebAssembly.LinkError,
       builder => {
         builder.addImportedGlobal("module", "global", kWasmI32);
       },
@@ -95,11 +108,12 @@ function test_bad_imports(t) {
     [WebAssembly.Memory, "WebAssembly.Memory"],
     [WebAssembly.Memory.prototype, "WebAssembly.Memory.prototype"],
     [Object.create(WebAssembly.Memory.prototype), "Object.create(WebAssembly.Memory.prototype)"],
+    [new WebAssembly.Memory({"initial": 256}), "WebAssembly.Memory object (too large)"],
   ];
 
   for (const [value, name = format_value(value)] of nonMemories) {
     t(`Importing memory with an incorrectly-typed value: ${name}`,
-      new WebAssembly.LinkError(),
+      WebAssembly.LinkError,
       builder => {
         builder.addImportedMemory("module", "memory", 0, 128);
       },
@@ -123,11 +137,12 @@ function test_bad_imports(t) {
     [WebAssembly.Table, "WebAssembly.Table"],
     [WebAssembly.Table.prototype, "WebAssembly.Table.prototype"],
     [Object.create(WebAssembly.Table.prototype), "Object.create(WebAssembly.Table.prototype)"],
+    [new WebAssembly.Table({"element": "anyfunc", "initial": 256}), "WebAssembly.Table object (too large)"],
   ];
 
   for (const [value, name = format_value(value)] of nonTables) {
     t(`Importing table with an incorrectly-typed value: ${name}`,
-      new WebAssembly.LinkError(),
+      WebAssembly.LinkError,
       builder => {
         builder.addImportedTable("module", "table", 0, 128);
       },
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any-expected.txt
new file mode 100644 (file)
index 0000000..86b0f85
--- /dev/null
@@ -0,0 +1,11 @@
+
+PASS Missing argument 
+PASS Invalid arguments 
+PASS Branding 
+PASS Promise type 
+PASS Empty buffer 
+PASS Invalid code 
+PASS Result type 
+PASS Stray argument 
+PASS Changing the buffer 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.js b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.js
new file mode 100644 (file)
index 0000000..6c41239
--- /dev/null
@@ -0,0 +1,85 @@
+// META: global=jsshell
+// META: script=/wasm/jsapi/wasm-module-builder.js
+
+function assert_Module(module) {
+  assert_equals(Object.getPrototypeOf(module), WebAssembly.Module.prototype,
+                "Prototype");
+  assert_true(Object.isExtensible(module), "Extensibility");
+}
+
+let emptyModuleBinary;
+setup(() => {
+  emptyModuleBinary = new WasmModuleBuilder().toBuffer();
+});
+
+promise_test(t => {
+  return promise_rejects_js(t, TypeError, WebAssembly.compile());
+}, "Missing argument");
+
+promise_test(t => {
+  const invalidArguments = [
+    undefined,
+    null,
+    true,
+    "",
+    Symbol(),
+    1,
+    {},
+    ArrayBuffer,
+    ArrayBuffer.prototype,
+    Array.from(emptyModuleBinary),
+  ];
+  return Promise.all(invalidArguments.map(argument => {
+    return promise_rejects_js(t, TypeError, WebAssembly.compile(argument),
+                           `compile(${format_value(argument)})`);
+  }));
+}, "Invalid arguments");
+
+promise_test(() => {
+  const fn = WebAssembly.compile;
+  const thisValues = [
+    undefined,
+    null,
+    true,
+    "",
+    Symbol(),
+    1,
+    {},
+    WebAssembly,
+  ];
+  return Promise.all(thisValues.map(thisValue => {
+    return fn.call(thisValue, emptyModuleBinary).then(assert_Module);
+  }));
+}, "Branding");
+
+test(() => {
+  const promise = WebAssembly.compile(emptyModuleBinary);
+  assert_equals(Object.getPrototypeOf(promise), Promise.prototype, "prototype");
+  assert_true(Object.isExtensible(promise), "extensibility");
+}, "Promise type");
+
+promise_test(t => {
+  const buffer = new Uint8Array();
+  return promise_rejects_js(t, WebAssembly.CompileError, WebAssembly.compile(buffer));
+}, "Empty buffer");
+
+promise_test(t => {
+  const buffer = new Uint8Array(Array.from(emptyModuleBinary).concat([0, 0]));
+  return promise_rejects_js(t, WebAssembly.CompileError, WebAssembly.compile(buffer));
+}, "Invalid code");
+
+promise_test(() => {
+  return WebAssembly.compile(emptyModuleBinary).then(assert_Module);
+}, "Result type");
+
+promise_test(() => {
+  return WebAssembly.compile(emptyModuleBinary, {}).then(assert_Module);
+}, "Stray argument");
+
+promise_test(() => {
+  const buffer = new WasmModuleBuilder().toBuffer();
+  assert_equals(buffer[0], 0);
+  const promise = WebAssembly.compile(buffer);
+  buffer[0] = 1;
+  return promise.then(assert_Module);
+}, "Changing the buffer");
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.worker-expected.txt
new file mode 100644 (file)
index 0000000..86b0f85
--- /dev/null
@@ -0,0 +1,11 @@
+
+PASS Missing argument 
+PASS Invalid arguments 
+PASS Branding 
+PASS Promise type 
+PASS Empty buffer 
+PASS Invalid code 
+PASS Result type 
+PASS Stray argument 
+PASS Changing the buffer 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.worker.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.worker.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
index fb7d759..c0f42b3 100644 (file)
@@ -37,6 +37,7 @@ PASS WebAssembly.instantiate(module): Importing a global with an incorrectly-typ
 PASS WebAssembly.instantiate(module): Importing a global with an incorrectly-typed value: WebAssembly.Global 
 PASS WebAssembly.instantiate(module): Importing a global with an incorrectly-typed value: WebAssembly.Global.prototype 
 PASS WebAssembly.instantiate(module): Importing a global with an incorrectly-typed value: Object.create(WebAssembly.Global.prototype) 
+PASS WebAssembly.instantiate(module): Importing a global with an incorrectly-typed value: WebAssembly.Global object (wrong value type) 
 PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: undefined 
 PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: null 
 PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: true 
@@ -49,6 +50,7 @@ PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed
 PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: WebAssembly.Memory 
 PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: WebAssembly.Memory.prototype 
 PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: Object.create(WebAssembly.Memory.prototype) 
+PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: WebAssembly.Memory object (too large) 
 PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: undefined 
 PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: null 
 PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: true 
@@ -61,6 +63,7 @@ PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed
 PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: WebAssembly.Table 
 PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: WebAssembly.Table.prototype 
 PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: Object.create(WebAssembly.Table.prototype) 
+PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: WebAssembly.Table object (too large) 
 PASS WebAssembly.instantiate(buffer): Non-object imports argument: null 
 PASS WebAssembly.instantiate(buffer): Non-object imports argument: true 
 PASS WebAssembly.instantiate(buffer): Non-object imports argument: "" 
@@ -99,6 +102,7 @@ PASS WebAssembly.instantiate(buffer): Importing a global with an incorrectly-typ
 PASS WebAssembly.instantiate(buffer): Importing a global with an incorrectly-typed value: WebAssembly.Global 
 PASS WebAssembly.instantiate(buffer): Importing a global with an incorrectly-typed value: WebAssembly.Global.prototype 
 PASS WebAssembly.instantiate(buffer): Importing a global with an incorrectly-typed value: Object.create(WebAssembly.Global.prototype) 
+PASS WebAssembly.instantiate(buffer): Importing a global with an incorrectly-typed value: WebAssembly.Global object (wrong value type) 
 PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: undefined 
 PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: null 
 PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: true 
@@ -111,6 +115,7 @@ PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed
 PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: WebAssembly.Memory 
 PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: WebAssembly.Memory.prototype 
 PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: Object.create(WebAssembly.Memory.prototype) 
+PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: WebAssembly.Memory object (too large) 
 PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: undefined 
 PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: null 
 PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: true 
@@ -123,4 +128,5 @@ PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed
 PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: WebAssembly.Table 
 PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: WebAssembly.Table.prototype 
 PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: Object.create(WebAssembly.Table.prototype) 
+PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: WebAssembly.Table object (too large) 
 
index 8670029..3707243 100644 (file)
@@ -1,5 +1,4 @@
 // META: global=jsshell
-// META: script=/wasm/jsapi/wasm-constants.js
 // META: script=/wasm/jsapi/wasm-module-builder.js
 // META: script=/wasm/jsapi/bad-imports.js
 
@@ -9,7 +8,7 @@ test_bad_imports((name, error, build, ...arguments) => {
     build(builder);
     const buffer = builder.toBuffer();
     const module = new WebAssembly.Module(buffer);
-    return promise_rejects(t, error, WebAssembly.instantiate(module, ...arguments));
+    return promise_rejects_js(t, error, WebAssembly.instantiate(module, ...arguments));
   }, `WebAssembly.instantiate(module): ${name}`);
 });
 
@@ -18,6 +17,6 @@ test_bad_imports((name, error, build, ...arguments) => {
     const builder = new WasmModuleBuilder();
     build(builder);
     const buffer = builder.toBuffer();
-    return promise_rejects(t, error, WebAssembly.instantiate(buffer, ...arguments));
+    return promise_rejects_js(t, error, WebAssembly.instantiate(buffer, ...arguments));
   }, `WebAssembly.instantiate(buffer): ${name}`);
 });
index fb7d759..c0f42b3 100644 (file)
@@ -37,6 +37,7 @@ PASS WebAssembly.instantiate(module): Importing a global with an incorrectly-typ
 PASS WebAssembly.instantiate(module): Importing a global with an incorrectly-typed value: WebAssembly.Global 
 PASS WebAssembly.instantiate(module): Importing a global with an incorrectly-typed value: WebAssembly.Global.prototype 
 PASS WebAssembly.instantiate(module): Importing a global with an incorrectly-typed value: Object.create(WebAssembly.Global.prototype) 
+PASS WebAssembly.instantiate(module): Importing a global with an incorrectly-typed value: WebAssembly.Global object (wrong value type) 
 PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: undefined 
 PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: null 
 PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: true 
@@ -49,6 +50,7 @@ PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed
 PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: WebAssembly.Memory 
 PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: WebAssembly.Memory.prototype 
 PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: Object.create(WebAssembly.Memory.prototype) 
+PASS WebAssembly.instantiate(module): Importing memory with an incorrectly-typed value: WebAssembly.Memory object (too large) 
 PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: undefined 
 PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: null 
 PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: true 
@@ -61,6 +63,7 @@ PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed
 PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: WebAssembly.Table 
 PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: WebAssembly.Table.prototype 
 PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: Object.create(WebAssembly.Table.prototype) 
+PASS WebAssembly.instantiate(module): Importing table with an incorrectly-typed value: WebAssembly.Table object (too large) 
 PASS WebAssembly.instantiate(buffer): Non-object imports argument: null 
 PASS WebAssembly.instantiate(buffer): Non-object imports argument: true 
 PASS WebAssembly.instantiate(buffer): Non-object imports argument: "" 
@@ -99,6 +102,7 @@ PASS WebAssembly.instantiate(buffer): Importing a global with an incorrectly-typ
 PASS WebAssembly.instantiate(buffer): Importing a global with an incorrectly-typed value: WebAssembly.Global 
 PASS WebAssembly.instantiate(buffer): Importing a global with an incorrectly-typed value: WebAssembly.Global.prototype 
 PASS WebAssembly.instantiate(buffer): Importing a global with an incorrectly-typed value: Object.create(WebAssembly.Global.prototype) 
+PASS WebAssembly.instantiate(buffer): Importing a global with an incorrectly-typed value: WebAssembly.Global object (wrong value type) 
 PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: undefined 
 PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: null 
 PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: true 
@@ -111,6 +115,7 @@ PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed
 PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: WebAssembly.Memory 
 PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: WebAssembly.Memory.prototype 
 PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: Object.create(WebAssembly.Memory.prototype) 
+PASS WebAssembly.instantiate(buffer): Importing memory with an incorrectly-typed value: WebAssembly.Memory object (too large) 
 PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: undefined 
 PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: null 
 PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: true 
@@ -123,4 +128,5 @@ PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed
 PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: WebAssembly.Table 
 PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: WebAssembly.Table.prototype 
 PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: Object.create(WebAssembly.Table.prototype) 
+PASS WebAssembly.instantiate(buffer): Importing table with an incorrectly-typed value: WebAssembly.Table object (too large) 
 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any-expected.txt
new file mode 100644 (file)
index 0000000..64ef0bf
--- /dev/null
@@ -0,0 +1,27 @@
+
+PASS Missing arguments 
+PASS Branding 
+PASS Invalid arguments 
+PASS Promise type 
+PASS Empty module without imports argument: BufferSource argument 
+PASS Empty module without imports argument: Module argument 
+PASS Empty module with undefined imports argument: BufferSource argument 
+PASS Empty module with undefined imports argument: Module argument 
+PASS Empty module with empty imports argument: BufferSource argument 
+PASS Empty module with empty imports argument: Module argument 
+FAIL getter order for imports object: BufferSource argument assert_array_equals: property 1, expected "global1 getter" but got "memory getter"
+FAIL getter order for imports object: Module argument assert_array_equals: property 1, expected "global1 getter" but got "memory getter"
+PASS imports: BufferSource argument 
+PASS imports: Module argument 
+FAIL No imports: BufferSource argument assert_array_equals: matching export keys property 2, expected "table" but got "global"
+FAIL No imports: Module argument assert_array_equals: matching export keys property 2, expected "table" but got "global"
+FAIL exports and imports: BufferSource argument assert_false: fn: writable expected false got true
+FAIL exports and imports: Module argument assert_false: fn: writable expected false got true
+PASS stray argument: BufferSource argument 
+PASS stray argument: Module argument 
+PASS Synchronous options handling: Buffer argument 
+FAIL Synchronous options handling: Module argument assert_array_equals: lengths differ, expected 2 got 0
+PASS Empty buffer 
+PASS Invalid code 
+PASS Changing the buffer 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.js b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.js
new file mode 100644 (file)
index 0000000..0218de2
--- /dev/null
@@ -0,0 +1,152 @@
+// META: global=jsshell
+// META: script=/wasm/jsapi/wasm-module-builder.js
+// META: script=/wasm/jsapi/assertions.js
+// META: script=/wasm/jsapi/instanceTestFactory.js
+
+let emptyModuleBinary;
+setup(() => {
+  emptyModuleBinary = new WasmModuleBuilder().toBuffer();
+});
+
+promise_test(t => {
+  return promise_rejects_js(t, TypeError, WebAssembly.instantiate());
+}, "Missing arguments");
+
+promise_test(() => {
+  const fn = WebAssembly.instantiate;
+  const thisValues = [
+    undefined,
+    null,
+    true,
+    "",
+    Symbol(),
+    1,
+    {},
+    WebAssembly,
+  ];
+  return Promise.all(thisValues.map(thisValue => {
+    return fn.call(thisValue, emptyModuleBinary).then(assert_WebAssemblyInstantiatedSource);
+  }));
+}, "Branding");
+
+promise_test(t => {
+  const invalidArguments = [
+    undefined,
+    null,
+    true,
+    "",
+    Symbol(),
+    1,
+    {},
+    WebAssembly.Module,
+    WebAssembly.Module.prototype,
+    ArrayBuffer,
+    ArrayBuffer.prototype,
+    Array.from(emptyModuleBinary),
+  ];
+  return Promise.all(invalidArguments.map(argument => {
+    return promise_rejects_js(t, TypeError, WebAssembly.instantiate(argument),
+                           `instantiate(${format_value(argument)})`);
+  }));
+}, "Invalid arguments");
+
+test(() => {
+  const promise = WebAssembly.instantiate(emptyModuleBinary);
+  assert_equals(Object.getPrototypeOf(promise), Promise.prototype, "prototype");
+  assert_true(Object.isExtensible(promise), "extensibility");
+}, "Promise type");
+
+for (const [name, fn] of instanceTestFactory) {
+  promise_test(() => {
+    const { buffer, args, exports, verify } = fn();
+    return WebAssembly.instantiate(buffer, ...args).then(result => {
+      assert_WebAssemblyInstantiatedSource(result, exports);
+      verify(result.instance);
+    });
+  }, `${name}: BufferSource argument`);
+
+  promise_test(() => {
+    const { buffer, args, exports, verify } = fn();
+    const module = new WebAssembly.Module(buffer);
+    return WebAssembly.instantiate(module, ...args).then(instance => {
+      assert_Instance(instance, exports);
+      verify(instance);
+    });
+  }, `${name}: Module argument`);
+}
+
+promise_test(() => {
+  const builder = new WasmModuleBuilder();
+  builder.addImportedGlobal("module", "global", kWasmI32);
+  const buffer = builder.toBuffer();
+  const order = [];
+
+  const imports = {
+    get module() {
+      order.push("module getter");
+      return {
+        get global() {
+          order.push("global getter");
+          return 0;
+        },
+      }
+    },
+  };
+
+  const expected = [
+    "module getter",
+    "global getter",
+  ];
+  const p = WebAssembly.instantiate(buffer, imports);
+  assert_array_equals(order, []);
+  return p.then(result => {
+    assert_WebAssemblyInstantiatedSource(result);
+    assert_array_equals(order, expected);
+  });
+}, "Synchronous options handling: Buffer argument");
+
+promise_test(() => {
+  const builder = new WasmModuleBuilder();
+  builder.addImportedGlobal("module", "global", kWasmI32);
+  const buffer = builder.toBuffer();
+  const module = new WebAssembly.Module(buffer);
+  const order = [];
+
+  const imports = {
+    get module() {
+      order.push("module getter");
+      return {
+        get global() {
+          order.push("global getter");
+          return 0;
+        },
+      }
+    },
+  };
+
+  const expected = [
+    "module getter",
+    "global getter",
+  ];
+  const p = WebAssembly.instantiate(module, imports);
+  assert_array_equals(order, expected);
+  return p.then(instance => assert_Instance(instance, {}));
+}, "Synchronous options handling: Module argument");
+
+promise_test(t => {
+  const buffer = new Uint8Array();
+  return promise_rejects_js(t, WebAssembly.CompileError, WebAssembly.instantiate(buffer));
+}, "Empty buffer");
+
+promise_test(t => {
+  const buffer = new Uint8Array(Array.from(emptyModuleBinary).concat([0, 0]));
+  return promise_rejects_js(t, WebAssembly.CompileError, WebAssembly.instantiate(buffer));
+}, "Invalid code");
+
+promise_test(() => {
+  const buffer = new WasmModuleBuilder().toBuffer();
+  assert_equals(buffer[0], 0);
+  const promise = WebAssembly.instantiate(buffer);
+  buffer[0] = 1;
+  return promise.then(assert_WebAssemblyInstantiatedSource);
+}, "Changing the buffer");
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.worker-expected.txt
new file mode 100644 (file)
index 0000000..64ef0bf
--- /dev/null
@@ -0,0 +1,27 @@
+
+PASS Missing arguments 
+PASS Branding 
+PASS Invalid arguments 
+PASS Promise type 
+PASS Empty module without imports argument: BufferSource argument 
+PASS Empty module without imports argument: Module argument 
+PASS Empty module with undefined imports argument: BufferSource argument 
+PASS Empty module with undefined imports argument: Module argument 
+PASS Empty module with empty imports argument: BufferSource argument 
+PASS Empty module with empty imports argument: Module argument 
+FAIL getter order for imports object: BufferSource argument assert_array_equals: property 1, expected "global1 getter" but got "memory getter"
+FAIL getter order for imports object: Module argument assert_array_equals: property 1, expected "global1 getter" but got "memory getter"
+PASS imports: BufferSource argument 
+PASS imports: Module argument 
+FAIL No imports: BufferSource argument assert_array_equals: matching export keys property 2, expected "table" but got "global"
+FAIL No imports: Module argument assert_array_equals: matching export keys property 2, expected "table" but got "global"
+FAIL exports and imports: BufferSource argument assert_false: fn: writable expected false got true
+FAIL exports and imports: Module argument assert_false: fn: writable expected false got true
+PASS stray argument: BufferSource argument 
+PASS stray argument: Module argument 
+PASS Synchronous options handling: Buffer argument 
+FAIL Synchronous options handling: Module argument assert_array_equals: lengths differ, expected 2 got 0
+PASS Empty buffer 
+PASS Invalid code 
+PASS Changing the buffer 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.worker.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.worker.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any-expected.txt
new file mode 100644 (file)
index 0000000..7f7017e
--- /dev/null
@@ -0,0 +1,5 @@
+
+PASS multiple return values from wasm to js 
+PASS multiple return values inside wasm 
+FAIL multiple return values from js to wasm assert_array_equals: property 6, expected "next call 2" but got "valueOf get 1"
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.js b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.js
new file mode 100644 (file)
index 0000000..2c53e36
--- /dev/null
@@ -0,0 +1,149 @@
+// META: global=jsshell
+// META: script=/wasm/jsapi/wasm-module-builder.js
+// META: script=/wasm/jsapi/assertions.js
+
+const type_if_fi = makeSig([kWasmF64, kWasmI32], [kWasmI32, kWasmF64]);
+
+promise_test(async () => {
+  const builder = new WasmModuleBuilder();
+
+  builder
+    .addFunction("swap", type_if_fi)
+    .addBody([
+        kExprLocalGet, 1,
+        kExprLocalGet, 0,
+        kExprReturn,
+    ])
+    .exportFunc();
+
+  const buffer = builder.toBuffer();
+
+  const result = await WebAssembly.instantiate(buffer);
+  const swapped = result.instance.exports.swap(4.2, 7);
+  assert_true(Array.isArray(swapped));
+  assert_equals(Object.getPrototypeOf(swapped), Array.prototype);
+  assert_array_equals(swapped, [7, 4.2]);
+}, "multiple return values from wasm to js");
+
+promise_test(async () => {
+  const builder = new WasmModuleBuilder();
+
+  const swap = builder
+    .addFunction("swap", type_if_fi)
+    .addBody([
+        kExprLocalGet, 1,
+        kExprLocalGet, 0,
+        kExprReturn,
+    ]);
+  builder
+    .addFunction("callswap", kSig_i_v)
+    .addBody([
+        ...wasmF64Const(4.2),
+        ...wasmI32Const(7),
+        kExprCallFunction, swap.index,
+        kExprDrop,
+        kExprReturn,
+    ])
+    .exportFunc();
+
+  const buffer = builder.toBuffer();
+
+  const result = await WebAssembly.instantiate(buffer);
+  const swapped = result.instance.exports.callswap();
+  assert_equals(swapped, 7);
+}, "multiple return values inside wasm");
+
+promise_test(async () => {
+  const builder = new WasmModuleBuilder();
+
+  const fnIndex = builder.addImport("module", "fn", type_if_fi);
+  builder
+    .addFunction("callfn", kSig_i_v)
+    .addBody([
+        ...wasmF64Const(4.2),
+        ...wasmI32Const(7),
+        kExprCallFunction, fnIndex,
+        kExprDrop,
+        kExprReturn,
+    ])
+    .exportFunc();
+
+  const buffer = builder.toBuffer();
+
+  const actual = [];
+  const imports = {
+    "module": {
+      fn(f32, i32) {
+        assert_equals(f32, 4.2);
+        assert_equals(i32, 7);
+        const result = [2, 7.3];
+        let i = 0;
+        return {
+          get [Symbol.iterator]() {
+            actual.push("@@iterator getter");
+            return function iterator() {
+              actual.push("@@iterator call");
+              return {
+                get next() {
+                  actual.push("next getter");
+                  return function next(...args) {
+                    assert_array_equals(args, []);
+                    let j = ++i;
+                    actual.push(`next call ${j}`);
+                    if (j > result.length) {
+                      return {
+                        get done() {
+                          actual.push(`done call ${j}`);
+                          return true;
+                        }
+                      };
+                    }
+                    return {
+                      get done() {
+                        actual.push(`done call ${j}`);
+                        return false;
+                      },
+                      get value() {
+                        actual.push(`value call ${j}`);
+                        return {
+                          get valueOf() {
+                            actual.push(`valueOf get ${j}`);
+                            return function() {
+                              actual.push(`valueOf call ${j}`);
+                              return result[j - 1];
+                            };
+                          }
+                        };
+                      }
+                    };
+                  };
+                }
+              };
+            }
+          },
+        };
+      },
+    }
+  };
+
+  const { instance } = await WebAssembly.instantiate(buffer, imports);
+  const result = instance.exports.callfn();
+  assert_equals(result, 2);
+  assert_array_equals(actual, [
+    "@@iterator getter",
+    "@@iterator call",
+    "next getter",
+    "next call 1",
+    "done call 1",
+    "value call 1",
+    "next call 2",
+    "done call 2",
+    "value call 2",
+    "next call 3",
+    "done call 3",
+    "valueOf get 1",
+    "valueOf call 1",
+    "valueOf get 2",
+    "valueOf call 2",
+  ]);
+}, "multiple return values from js to wasm");
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.worker-expected.txt
new file mode 100644 (file)
index 0000000..7f7017e
--- /dev/null
@@ -0,0 +1,5 @@
+
+PASS multiple return values from wasm to js 
+PASS multiple return values inside wasm 
+FAIL multiple return values from js to wasm assert_array_equals: property 6, expected "next call 2" but got "valueOf get 1"
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.worker.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.worker.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any-expected.txt
new file mode 100644 (file)
index 0000000..9fa99c7
--- /dev/null
@@ -0,0 +1,64 @@
+
+PASS Missing argument 
+PASS Invalid arguments 
+PASS Branding 
+PASS Validating module [] in Uint8Array 
+PASS Validating module [] in Int8Array 
+PASS Validating module [] in Uint16Array 
+PASS Validating module [] in Int16Array 
+PASS Validating module [] in Uint32Array 
+PASS Validating module [] in Int32Array 
+PASS Validating module [0] in Uint8Array 
+PASS Validating module [0] in Int8Array 
+PASS Validating module [0 61] in Uint8Array 
+PASS Validating module [0 61] in Int8Array 
+PASS Validating module [0 61] in Uint16Array 
+PASS Validating module [0 61] in Int16Array 
+PASS Validating module [0 61 73] in Uint8Array 
+PASS Validating module [0 61 73] in Int8Array 
+PASS Validating module [0 61 73 6d] in Uint8Array 
+PASS Validating module [0 61 73 6d] in Int8Array 
+PASS Validating module [0 61 73 6d] in Uint16Array 
+PASS Validating module [0 61 73 6d] in Int16Array 
+PASS Validating module [0 61 73 6d] in Uint32Array 
+PASS Validating module [0 61 73 6d] in Int32Array 
+PASS Validating module [0 61 73 6d 1] in Uint8Array 
+PASS Validating module [0 61 73 6d 1] in Int8Array 
+PASS Validating module [0 61 73 6d 1 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 1 0] in Int8Array 
+PASS Validating module [0 61 73 6d 1 0] in Uint16Array 
+PASS Validating module [0 61 73 6d 1 0] in Int16Array 
+PASS Validating module [0 61 73 6d 1 0 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 1 0 0] in Int8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0] in Int8Array 
+FAIL Validating module [0 61 73 6d 1 0 0 0] in Uint16Array assert_equals: expected true but got false
+FAIL Validating module [0 61 73 6d 1 0 0 0] in Int16Array assert_equals: expected true but got false
+FAIL Validating module [0 61 73 6d 1 0 0 0] in Uint32Array assert_equals: expected true but got false
+FAIL Validating module [0 61 73 6d 1 0 0 0] in Int32Array assert_equals: expected true but got false
+PASS Validating module [0 61 73 6d 0 0 0 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 0 0 0 0] in Int8Array 
+PASS Validating module [0 61 73 6d 0 0 0 0] in Uint16Array 
+PASS Validating module [0 61 73 6d 0 0 0 0] in Int16Array 
+PASS Validating module [0 61 73 6d 0 0 0 0] in Uint32Array 
+PASS Validating module [0 61 73 6d 0 0 0 0] in Int32Array 
+PASS Validating module [0 61 73 6d 2 0 0 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 2 0 0 0] in Int8Array 
+PASS Validating module [0 61 73 6d 2 0 0 0] in Uint16Array 
+PASS Validating module [0 61 73 6d 2 0 0 0] in Int16Array 
+PASS Validating module [0 61 73 6d 2 0 0 0] in Uint32Array 
+PASS Validating module [0 61 73 6d 2 0 0 0] in Int32Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 0] in Int8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 0] in Uint16Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 0] in Int16Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 1 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 1 0] in Int8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 2 1 61] in Uint8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 2 1 61] in Int8Array 
+FAIL Validating module [0 61 73 6d 1 0 0 0 0 2 1 61] in Uint16Array assert_equals: expected true but got false
+FAIL Validating module [0 61 73 6d 1 0 0 0 0 2 1 61] in Int16Array assert_equals: expected true but got false
+FAIL Validating module [0 61 73 6d 1 0 0 0 0 2 1 61] in Uint32Array assert_equals: expected true but got false
+FAIL Validating module [0 61 73 6d 1 0 0 0 0 2 1 61] in Int32Array assert_equals: expected true but got false
+PASS Stray argument 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.js b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.js
new file mode 100644 (file)
index 0000000..a523acc
--- /dev/null
@@ -0,0 +1,99 @@
+// META: global=jsshell
+// META: script=/wasm/jsapi/wasm-module-builder.js
+
+let emptyModuleBinary;
+setup(() => {
+  emptyModuleBinary = new WasmModuleBuilder().toBuffer();
+});
+
+test(() => {
+  assert_throws_js(TypeError, () => WebAssembly.validate());
+}, "Missing argument");
+
+test(() => {
+  const invalidArguments = [
+    undefined,
+    null,
+    true,
+    "",
+    Symbol(),
+    1,
+    {},
+    ArrayBuffer,
+    ArrayBuffer.prototype,
+    Array.from(emptyModuleBinary),
+  ];
+  for (const argument of invalidArguments) {
+    assert_throws_js(TypeError, () => WebAssembly.validate(argument),
+                     `validate(${format_value(argument)})`);
+  }
+}, "Invalid arguments");
+
+test(() => {
+  const fn = WebAssembly.validate;
+  const thisValues = [
+    undefined,
+    null,
+    true,
+    "",
+    Symbol(),
+    1,
+    {},
+    WebAssembly,
+  ];
+  for (const thisValue of thisValues) {
+    assert_true(fn.call(thisValue, emptyModuleBinary), `this=${format_value(thisValue)}`);
+  }
+}, "Branding");
+
+const modules = [
+  // Incomplete header.
+  [[], false],
+  [[0x00], false],
+  [[0x00, 0x61], false],
+  [[0x00, 0x61, 0x73], false],
+  [[0x00, 0x61, 0x73, 0x6d], false],
+  [[0x00, 0x61, 0x73, 0x6d, 0x01], false],
+  [[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00], false],
+  [[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00], false],
+
+  // Complete header.
+  [[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00], true],
+
+  // Invalid version.
+  [[0x00, 0x61, 0x73, 0x6d, 0x00, 0x00, 0x00, 0x00], false],
+  [[0x00, 0x61, 0x73, 0x6d, 0x02, 0x00, 0x00, 0x00], false],
+
+  // Nameless custom section.
+  [[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00], false],
+
+  // Custom section with empty name.
+  [[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00], true],
+
+  // Custom section with name "a".
+  [[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x61], true],
+];
+const bufferTypes = [
+  Uint8Array,
+  Int8Array,
+  Uint16Array,
+  Int16Array,
+  Uint32Array,
+  Int32Array,
+];
+for (const [module, expected] of modules) {
+  const name = module.map(n => n.toString(16)).join(" ");
+  for (const bufferType of bufferTypes) {
+    if (module.length % bufferType.BYTES_PER_ELEMENT === 0) {
+      test(() => {
+        const bytes = new Uint8Array(module);
+        const moduleBuffer = new bufferType(bytes.buffer);
+        assert_equals(WebAssembly.validate(moduleBuffer), expected);
+      }, `Validating module [${name}] in ${bufferType.name}`);
+    }
+  }
+}
+
+test(() => {
+  assert_true(WebAssembly.validate(emptyModuleBinary, {}));
+}, "Stray argument");
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.worker-expected.txt
new file mode 100644 (file)
index 0000000..9fa99c7
--- /dev/null
@@ -0,0 +1,64 @@
+
+PASS Missing argument 
+PASS Invalid arguments 
+PASS Branding 
+PASS Validating module [] in Uint8Array 
+PASS Validating module [] in Int8Array 
+PASS Validating module [] in Uint16Array 
+PASS Validating module [] in Int16Array 
+PASS Validating module [] in Uint32Array 
+PASS Validating module [] in Int32Array 
+PASS Validating module [0] in Uint8Array 
+PASS Validating module [0] in Int8Array 
+PASS Validating module [0 61] in Uint8Array 
+PASS Validating module [0 61] in Int8Array 
+PASS Validating module [0 61] in Uint16Array 
+PASS Validating module [0 61] in Int16Array 
+PASS Validating module [0 61 73] in Uint8Array 
+PASS Validating module [0 61 73] in Int8Array 
+PASS Validating module [0 61 73 6d] in Uint8Array 
+PASS Validating module [0 61 73 6d] in Int8Array 
+PASS Validating module [0 61 73 6d] in Uint16Array 
+PASS Validating module [0 61 73 6d] in Int16Array 
+PASS Validating module [0 61 73 6d] in Uint32Array 
+PASS Validating module [0 61 73 6d] in Int32Array 
+PASS Validating module [0 61 73 6d 1] in Uint8Array 
+PASS Validating module [0 61 73 6d 1] in Int8Array 
+PASS Validating module [0 61 73 6d 1 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 1 0] in Int8Array 
+PASS Validating module [0 61 73 6d 1 0] in Uint16Array 
+PASS Validating module [0 61 73 6d 1 0] in Int16Array 
+PASS Validating module [0 61 73 6d 1 0 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 1 0 0] in Int8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0] in Int8Array 
+FAIL Validating module [0 61 73 6d 1 0 0 0] in Uint16Array assert_equals: expected true but got false
+FAIL Validating module [0 61 73 6d 1 0 0 0] in Int16Array assert_equals: expected true but got false
+FAIL Validating module [0 61 73 6d 1 0 0 0] in Uint32Array assert_equals: expected true but got false
+FAIL Validating module [0 61 73 6d 1 0 0 0] in Int32Array assert_equals: expected true but got false
+PASS Validating module [0 61 73 6d 0 0 0 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 0 0 0 0] in Int8Array 
+PASS Validating module [0 61 73 6d 0 0 0 0] in Uint16Array 
+PASS Validating module [0 61 73 6d 0 0 0 0] in Int16Array 
+PASS Validating module [0 61 73 6d 0 0 0 0] in Uint32Array 
+PASS Validating module [0 61 73 6d 0 0 0 0] in Int32Array 
+PASS Validating module [0 61 73 6d 2 0 0 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 2 0 0 0] in Int8Array 
+PASS Validating module [0 61 73 6d 2 0 0 0] in Uint16Array 
+PASS Validating module [0 61 73 6d 2 0 0 0] in Int16Array 
+PASS Validating module [0 61 73 6d 2 0 0 0] in Uint32Array 
+PASS Validating module [0 61 73 6d 2 0 0 0] in Int32Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 0] in Int8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 0] in Uint16Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 0] in Int16Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 1 0] in Uint8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 1 0] in Int8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 2 1 61] in Uint8Array 
+PASS Validating module [0 61 73 6d 1 0 0 0 0 2 1 61] in Int8Array 
+FAIL Validating module [0 61 73 6d 1 0 0 0 0 2 1 61] in Uint16Array assert_equals: expected true but got false
+FAIL Validating module [0 61 73 6d 1 0 0 0 0 2 1 61] in Int16Array assert_equals: expected true but got false
+FAIL Validating module [0 61 73 6d 1 0 0 0 0 2 1 61] in Uint32Array assert_equals: expected true but got false
+FAIL Validating module [0 61 73 6d 1 0 0 0 0 2 1 61] in Int32Array assert_equals: expected true but got false
+PASS Stray argument 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.worker.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.worker.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
index 7197fd2..f89b799 100644 (file)
@@ -14,4 +14,8 @@ Property values requiring vendor prefixes:
 None
 ------------------------------------------------------------------------
 List of files:
+/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/compile.any.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate-bad-imports.any.js
+/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/instantiate.any.js
+/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/multi-value.any.js
+/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/constructor/validate.any.js
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/error-interfaces-no-symbol-tostringtag.js b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/error-interfaces-no-symbol-tostringtag.js
new file mode 100644 (file)
index 0000000..572db0c
--- /dev/null
@@ -0,0 +1,13 @@
+// META: global=jsshell
+
+test(() => {
+  assert_not_own_property(WebAssembly.CompileError.prototype, Symbol.toStringTag);
+}, "WebAssembly.CompileError");
+
+test(() => {
+  assert_not_own_property(WebAssembly.LinkError.prototype, Symbol.toStringTag);
+}, "WebAssembly.LinkError");
+
+test(() => {
+  assert_not_own_property(WebAssembly.RuntimeError.prototype, Symbol.toStringTag);
+}, "WebAssembly.RuntimeError");
index f390f7e..6443b07 100644 (file)
@@ -34,4 +34,5 @@ PASS Explicit value 2 for type f64
 PASS Explicit value "3" for type f64 
 PASS Explicit value object with toString for type f64 
 PASS Explicit value object with valueOf for type f64 
+PASS Stray argument 
 
index 7a45cc4..270149e 100644 (file)
@@ -19,12 +19,12 @@ test(() => {
 }, "length");
 
 test(() => {
-  assert_throws(new TypeError(), () => new WebAssembly.Global());
+  assert_throws_js(TypeError, () => new WebAssembly.Global());
 }, "No arguments");
 
 test(() => {
   const argument = { "value": "i32" };
-  assert_throws(new TypeError(), () => WebAssembly.Global(argument));
+  assert_throws_js(TypeError, () => WebAssembly.Global(argument));
 }, "Calling");
 
 test(() => {
@@ -73,9 +73,9 @@ test(() => {
     {},
   ];
   for (const invalidArgument of invalidArguments) {
-    assert_throws(new TypeError(),
-                  () => new WebAssembly.Global(invalidArgument),
-                  `new Global(${format_value(invalidArgument)})`);
+    assert_throws_js(TypeError,
+                     () => new WebAssembly.Global(invalidArgument),
+                     `new Global(${format_value(invalidArgument)})`);
   }
 }, "Invalid descriptor argument");
 
@@ -83,15 +83,15 @@ test(() => {
   const invalidTypes = ["i16", "i128", "f16", "f128", "u32", "u64", "i32\0"];
   for (const value of invalidTypes) {
     const argument = { value };
-    assert_throws(new TypeError(), () => new WebAssembly.Global(argument));
+    assert_throws_js(TypeError, () => new WebAssembly.Global(argument));
   }
 }, "Invalid type argument");
 
 test(() => {
   const argument = { "value": "i64" };
   const global = new WebAssembly.Global(argument);
-  assert_throws(new TypeError(), () => global.value);
-  assert_throws(new TypeError(), () => global.valueOf());
+  assert_throws_js(TypeError, () => global.value);
+  assert_throws_js(TypeError, () => global.valueOf());
 }, "i64 with default");
 
 for (const type of ["i32", "f32", "f64"]) {
@@ -119,3 +119,9 @@ for (const type of ["i32", "f32", "f64"]) {
     }, `Explicit value ${name} for type ${type}`);
   }
 }
+
+test(() => {
+  const argument = { "value": "i32" };
+  const global = new WebAssembly.Global(argument, 0, {});
+  assert_Global(global, 0);
+}, "Stray argument");
index f390f7e..6443b07 100644 (file)
@@ -34,4 +34,5 @@ PASS Explicit value 2 for type f64
 PASS Explicit value "3" for type f64 
 PASS Explicit value object with toString for type f64 
 PASS Explicit value object with valueOf for type f64 
+PASS Stray argument 
 
index 2239b5e..312a2b1 100644 (file)
@@ -1,3 +1,4 @@
 
 PASS Object.prototype.toString on an Global 
+FAIL @@toStringTag exists on the prototype with the appropriate descriptor assert_own_property: expected property symbol "Symbol(Symbol.toStringTag)" missing
 
index ca02557..5f64d72 100644 (file)
@@ -5,3 +5,13 @@ test(() => {
   const global = new WebAssembly.Global(argument);
   assert_class_string(global, "WebAssembly.Global");
 }, "Object.prototype.toString on an Global");
+
+test(() => {
+  assert_own_property(WebAssembly.Global.prototype, Symbol.toStringTag);
+
+  const propDesc = Object.getOwnPropertyDescriptor(WebAssembly.Global.prototype, Symbol.toStringTag);
+  assert_equals(propDesc.value, "WebAssembly.Global", "value");
+  assert_equals(propDesc.configurable, true, "configurable");
+  assert_equals(propDesc.enumerable, false, "enumerable");
+  assert_equals(propDesc.writable, false, "writable");
+}, "@@toStringTag exists on the prototype with the appropriate descriptor");
index 2239b5e..312a2b1 100644 (file)
@@ -1,3 +1,4 @@
 
 PASS Object.prototype.toString on an Global 
+FAIL @@toStringTag exists on the prototype with the appropriate descriptor assert_own_property: expected property symbol "Symbol(Symbol.toStringTag)" missing
 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any-expected.txt
new file mode 100644 (file)
index 0000000..7cbdc7f
--- /dev/null
@@ -0,0 +1,55 @@
+
+PASS Branding 
+PASS Immutable i32 (missing) 
+PASS Immutable i32 with ToNumber side-effects (missing) 
+PASS Immutable i32 (undefined) 
+PASS Immutable i32 with ToNumber side-effects (undefined) 
+PASS Immutable i32 (null) 
+PASS Immutable i32 with ToNumber side-effects (null) 
+PASS Immutable i32 (false) 
+PASS Immutable i32 with ToNumber side-effects (false) 
+PASS Immutable i32 (empty string) 
+PASS Immutable i32 with ToNumber side-effects (empty string) 
+PASS Immutable i32 (zero) 
+PASS Immutable i32 with ToNumber side-effects (zero) 
+PASS Mutable i32 (true) 
+PASS Mutable i32 (one) 
+PASS Mutable i32 (string) 
+PASS Mutable i32 (true on prototype) 
+PASS Immutable f32 (missing) 
+PASS Immutable f32 with ToNumber side-effects (missing) 
+PASS Immutable f32 (undefined) 
+PASS Immutable f32 with ToNumber side-effects (undefined) 
+PASS Immutable f32 (null) 
+PASS Immutable f32 with ToNumber side-effects (null) 
+PASS Immutable f32 (false) 
+PASS Immutable f32 with ToNumber side-effects (false) 
+PASS Immutable f32 (empty string) 
+PASS Immutable f32 with ToNumber side-effects (empty string) 
+PASS Immutable f32 (zero) 
+PASS Immutable f32 with ToNumber side-effects (zero) 
+PASS Mutable f32 (true) 
+PASS Mutable f32 (one) 
+PASS Mutable f32 (string) 
+PASS Mutable f32 (true on prototype) 
+PASS Immutable f64 (missing) 
+PASS Immutable f64 with ToNumber side-effects (missing) 
+PASS Immutable f64 (undefined) 
+PASS Immutable f64 with ToNumber side-effects (undefined) 
+PASS Immutable f64 (null) 
+PASS Immutable f64 with ToNumber side-effects (null) 
+PASS Immutable f64 (false) 
+PASS Immutable f64 with ToNumber side-effects (false) 
+PASS Immutable f64 (empty string) 
+PASS Immutable f64 with ToNumber side-effects (empty string) 
+PASS Immutable f64 (zero) 
+PASS Immutable f64 with ToNumber side-effects (zero) 
+PASS Mutable f64 (true) 
+PASS Mutable f64 (one) 
+PASS Mutable f64 (string) 
+PASS Mutable f64 (true on prototype) 
+PASS i64 with default 
+PASS i64 with ToNumber side-effects 
+PASS Calling setter without argument 
+PASS Stray argument 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
@@ -23,8 +23,8 @@ test(() => {
   assert_equals(typeof setter, "function");
 
   for (const thisValue of thisValues) {
-    assert_throws(new TypeError(), () => getter.call(thisValue), `getter with this=${format_value(thisValue)}`);
-    assert_throws(new TypeError(), () => setter.call(thisValue, 1), `setter with this=${format_value(thisValue)}`);
+    assert_throws_js(TypeError, () => getter.call(thisValue), `getter with this=${format_value(thisValue)}`);
+    assert_throws_js(TypeError, () => setter.call(thisValue, 1), `setter with this=${format_value(thisValue)}`);
   }
 }, "Branding");
 
@@ -44,11 +44,27 @@ for (const type of ["i32", "f32", "f64"]) {
       assert_equals(global.value, 0, "initial value");
       assert_equals(global.valueOf(), 0, "initial valueOf");
 
-      assert_throws(new TypeError(), () => global.value = 1);
+      assert_throws_js(TypeError, () => global.value = 1);
 
       assert_equals(global.value, 0, "post-set value");
       assert_equals(global.valueOf(), 0, "post-set valueOf");
     }, `Immutable ${type} (${name})`);
+
+    test(t => {
+      opts.value = type;
+      const global = new WebAssembly.Global(opts);
+      assert_equals(global.value, 0, "initial value");
+      assert_equals(global.valueOf(), 0, "initial valueOf");
+
+      const value = {
+        valueOf: t.unreached_func("should not call valueOf"),
+        toString: t.unreached_func("should not call toString"),
+      };
+      assert_throws_js(TypeError, () => global.value = value);
+
+      assert_equals(global.value, 0, "post-set value");
+      assert_equals(global.valueOf(), 0, "post-set valueOf");
+    }, `Immutable ${type} with ToNumber side-effects (${name})`);
   }
 
   const mutableOptions = [
@@ -75,11 +91,20 @@ for (const type of ["i32", "f32", "f64"]) {
 test(() => {
   const argument = { "value": "i64", "mutable": true };
   const global = new WebAssembly.Global(argument);
-  assert_throws(new TypeError(), () => global.value);
-  assert_throws(new TypeError(), () => global.value = 0);
-  assert_throws(new TypeError(), () => global.valueOf());
+  assert_throws_js(TypeError, () => global.value);
+  assert_throws_js(TypeError, () => global.value = 0);
+  assert_throws_js(TypeError, () => global.valueOf());
 }, "i64 with default");
 
+test(t => {
+  const argument = { "value": "i64", "mutable": true };
+  const global = new WebAssembly.Global(argument);
+  const value = {
+    valueOf: t.unreached_func("should not call valueOf"),
+    toString: t.unreached_func("should not call toString"),
+  };
+  assert_throws_js(TypeError, () => global.value = value);
+}, "i64 with ToNumber side-effects");
 
 test(() => {
   const argument = { "value": "i32", "mutable": true };
@@ -90,5 +115,22 @@ test(() => {
   const setter = desc.set;
   assert_equals(typeof setter, "function");
 
-  assert_throws(new TypeError(), () => setter.call(global));
+  assert_throws_js(TypeError, () => setter.call(global));
 }, "Calling setter without argument");
+
+test(() => {
+  const argument = { "value": "i32", "mutable": true };
+  const global = new WebAssembly.Global(argument);
+  const desc = Object.getOwnPropertyDescriptor(WebAssembly.Global.prototype, "value");
+  assert_equals(typeof desc, "object");
+
+  const getter = desc.get;
+  assert_equals(typeof getter, "function");
+
+  const setter = desc.set;
+  assert_equals(typeof setter, "function");
+
+  assert_equals(getter.call(global, {}), 0);
+  assert_equals(setter.call(global, 1, {}), undefined);
+  assert_equals(global.value, 1);
+}, "Stray argument");
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any.worker-expected.txt
new file mode 100644 (file)
index 0000000..7cbdc7f
--- /dev/null
@@ -0,0 +1,55 @@
+
+PASS Branding 
+PASS Immutable i32 (missing) 
+PASS Immutable i32 with ToNumber side-effects (missing) 
+PASS Immutable i32 (undefined) 
+PASS Immutable i32 with ToNumber side-effects (undefined) 
+PASS Immutable i32 (null) 
+PASS Immutable i32 with ToNumber side-effects (null) 
+PASS Immutable i32 (false) 
+PASS Immutable i32 with ToNumber side-effects (false) 
+PASS Immutable i32 (empty string) 
+PASS Immutable i32 with ToNumber side-effects (empty string) 
+PASS Immutable i32 (zero) 
+PASS Immutable i32 with ToNumber side-effects (zero) 
+PASS Mutable i32 (true) 
+PASS Mutable i32 (one) 
+PASS Mutable i32 (string) 
+PASS Mutable i32 (true on prototype) 
+PASS Immutable f32 (missing) 
+PASS Immutable f32 with ToNumber side-effects (missing) 
+PASS Immutable f32 (undefined) 
+PASS Immutable f32 with ToNumber side-effects (undefined) 
+PASS Immutable f32 (null) 
+PASS Immutable f32 with ToNumber side-effects (null) 
+PASS Immutable f32 (false) 
+PASS Immutable f32 with ToNumber side-effects (false) 
+PASS Immutable f32 (empty string) 
+PASS Immutable f32 with ToNumber side-effects (empty string) 
+PASS Immutable f32 (zero) 
+PASS Immutable f32 with ToNumber side-effects (zero) 
+PASS Mutable f32 (true) 
+PASS Mutable f32 (one) 
+PASS Mutable f32 (string) 
+PASS Mutable f32 (true on prototype) 
+PASS Immutable f64 (missing) 
+PASS Immutable f64 with ToNumber side-effects (missing) 
+PASS Immutable f64 (undefined) 
+PASS Immutable f64 with ToNumber side-effects (undefined) 
+PASS Immutable f64 (null) 
+PASS Immutable f64 with ToNumber side-effects (null) 
+PASS Immutable f64 (false) 
+PASS Immutable f64 with ToNumber side-effects (false) 
+PASS Immutable f64 (empty string) 
+PASS Immutable f64 with ToNumber side-effects (empty string) 
+PASS Immutable f64 (zero) 
+PASS Immutable f64 with ToNumber side-effects (zero) 
+PASS Mutable f64 (true) 
+PASS Mutable f64 (one) 
+PASS Mutable f64 (string) 
+PASS Mutable f64 (true on prototype) 
+PASS i64 with default 
+PASS i64 with ToNumber side-effects 
+PASS Calling setter without argument 
+PASS Stray argument 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any.worker.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any.worker.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
index a100934..59fed4f 100644 (file)
@@ -1,35 +1,8 @@
-
-PASS Branding 
-PASS Immutable i32 (missing) 
-PASS Immutable i32 (undefined) 
-PASS Immutable i32 (null) 
-PASS Immutable i32 (false) 
-PASS Immutable i32 (empty string) 
-PASS Immutable i32 (zero) 
-PASS Mutable i32 (true) 
-PASS Mutable i32 (one) 
-PASS Mutable i32 (string) 
-PASS Mutable i32 (true on prototype) 
-PASS Immutable f32 (missing) 
-PASS Immutable f32 (undefined) 
-PASS Immutable f32 (null) 
-PASS Immutable f32 (false) 
-PASS Immutable f32 (empty string) 
-PASS Immutable f32 (zero) 
-PASS Mutable f32 (true) 
-PASS Mutable f32 (one) 
-PASS Mutable f32 (string) 
-PASS Mutable f32 (true on prototype) 
-PASS Immutable f64 (missing) 
-PASS Immutable f64 (undefined) 
-PASS Immutable f64 (null) 
-PASS Immutable f64 (false) 
-PASS Immutable f64 (empty string) 
-PASS Immutable f64 (zero) 
-PASS Mutable f64 (true) 
-PASS Mutable f64 (one) 
-PASS Mutable f64 (string) 
-PASS Mutable f64 (true on prototype) 
-PASS i64 with default 
-PASS Calling setter without argument 
-
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x579
+      RenderBlock {PRE} at (0,0) size 784x15
+        RenderText {#text} at (0,0) size 305x15
+          text run at (0,0) width 305: "{\"error\": {\"message\": \"\", \"code\": 404}}"
index a100934..59fed4f 100644 (file)
@@ -1,35 +1,8 @@
-
-PASS Branding 
-PASS Immutable i32 (missing) 
-PASS Immutable i32 (undefined) 
-PASS Immutable i32 (null) 
-PASS Immutable i32 (false) 
-PASS Immutable i32 (empty string) 
-PASS Immutable i32 (zero) 
-PASS Mutable i32 (true) 
-PASS Mutable i32 (one) 
-PASS Mutable i32 (string) 
-PASS Mutable i32 (true on prototype) 
-PASS Immutable f32 (missing) 
-PASS Immutable f32 (undefined) 
-PASS Immutable f32 (null) 
-PASS Immutable f32 (false) 
-PASS Immutable f32 (empty string) 
-PASS Immutable f32 (zero) 
-PASS Mutable f32 (true) 
-PASS Mutable f32 (one) 
-PASS Mutable f32 (string) 
-PASS Mutable f32 (true on prototype) 
-PASS Immutable f64 (missing) 
-PASS Immutable f64 (undefined) 
-PASS Immutable f64 (null) 
-PASS Immutable f64 (false) 
-PASS Immutable f64 (empty string) 
-PASS Immutable f64 (zero) 
-PASS Mutable f64 (true) 
-PASS Mutable f64 (one) 
-PASS Mutable f64 (string) 
-PASS Mutable f64 (true on prototype) 
-PASS i64 with default 
-PASS Calling setter without argument 
-
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x579
+      RenderBlock {PRE} at (0,0) size 784x15
+        RenderText {#text} at (0,0) size 305x15
+          text run at (0,0) width 305: "{\"error\": {\"message\": \"\", \"code\": 404}}"
index 176c5a7..0d4de93 100644 (file)
@@ -17,6 +17,12 @@ test(() => {
   const fn = WebAssembly.Global.prototype.valueOf;
 
   for (const thisValue of thisValues) {
-    assert_throws(new TypeError(), () => fn.call(thisValue), `this=${format_value(thisValue)}`);
+    assert_throws_js(TypeError, () => fn.call(thisValue), `this=${format_value(thisValue)}`);
   }
 }, "Branding");
+
+test(() => {
+  const argument = { "value": "i32" };
+  const global = new WebAssembly.Global(argument, 0);
+  assert_equals(global.valueOf({}), 0);
+}, "Stray argument");
index ab1f3ef..418ebdd 100644 (file)
@@ -16,5 +16,5 @@ None
 List of files:
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/constructor.any.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/toString.any.js
-/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-set.any.js
+/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/value-get-set.any.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/global/valueOf.any.js
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any-expected.txt
new file mode 100644 (file)
index 0000000..54b01a5
--- /dev/null
@@ -0,0 +1,65 @@
+
+PASS wasm-js-api interfaces. 
+PASS WebAssembly namespace: operation validate(BufferSource) 
+PASS WebAssembly namespace: operation compile(BufferSource) 
+PASS WebAssembly namespace: operation instantiate(BufferSource, object) 
+PASS WebAssembly namespace: operation instantiate(Module, object) 
+PASS Module interface: existence and properties of interface object 
+PASS Module interface object length 
+PASS Module interface object name 
+PASS Module interface: existence and properties of interface prototype object 
+PASS Module interface: existence and properties of interface prototype object's "constructor" property 
+PASS Module interface: existence and properties of interface prototype object's @@unscopables property 
+PASS Module interface: operation exports(Module) 
+PASS Module interface: operation imports(Module) 
+PASS Module interface: operation customSections(Module, DOMString) 
+FAIL Module must be primary interface of mod assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: Can't find variable: mod"
+FAIL Stringification of mod assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: Can't find variable: mod"
+FAIL Module interface: mod must inherit property "exports(Module)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: Can't find variable: mod"
+FAIL Module interface: calling exports(Module) on mod with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: Can't find variable: mod"
+FAIL Module interface: mod must inherit property "imports(Module)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: Can't find variable: mod"
+FAIL Module interface: calling imports(Module) on mod with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: Can't find variable: mod"
+FAIL Module interface: mod must inherit property "customSections(Module, DOMString)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: Can't find variable: mod"
+FAIL Module interface: calling customSections(Module, DOMString) on mod with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: Can't find variable: mod"
+PASS Instance interface: existence and properties of interface object 
+PASS Instance interface object length 
+PASS Instance interface object name 
+PASS Instance interface: existence and properties of interface prototype object 
+PASS Instance interface: existence and properties of interface prototype object's "constructor" property 
+PASS Instance interface: existence and properties of interface prototype object's @@unscopables property 
+PASS Instance interface: attribute exports 
+FAIL Instance must be primary interface of instance assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: Can't find variable: instance"
+FAIL Stringification of instance assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: Can't find variable: instance"
+FAIL Instance interface: instance must inherit property "exports" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: Can't find variable: instance"
+PASS Memory interface: existence and properties of interface object 
+PASS Memory interface object length 
+PASS Memory interface object name 
+PASS Memory interface: existence and properties of interface prototype object 
+PASS Memory interface: existence and properties of interface prototype object's "constructor" property 
+PASS Memory interface: existence and properties of interface prototype object's @@unscopables property 
+PASS Memory interface: operation grow(unsigned long) 
+PASS Memory interface: attribute buffer 
+PASS Memory must be primary interface of memory 
+PASS Stringification of memory 
+PASS Memory interface: memory must inherit property "grow(unsigned long)" with the proper type 
+PASS Memory interface: calling grow(unsigned long) on memory with too few arguments must throw TypeError 
+PASS Memory interface: memory must inherit property "buffer" with the proper type 
+PASS Table interface: existence and properties of interface object 
+PASS Table interface object length 
+PASS Table interface object name 
+PASS Table interface: existence and properties of interface prototype object 
+PASS Table interface: existence and properties of interface prototype object's "constructor" property 
+PASS Table interface: existence and properties of interface prototype object's @@unscopables property 
+PASS Table interface: operation grow(unsigned long) 
+PASS Table interface: operation get(unsigned long) 
+PASS Table interface: operation set(unsigned long, Function) 
+PASS Table interface: attribute length 
+PASS Global interface: existence and properties of interface object 
+PASS Global interface object length 
+PASS Global interface object name 
+PASS Global interface: existence and properties of interface prototype object 
+PASS Global interface: existence and properties of interface prototype object's "constructor" property 
+PASS Global interface: existence and properties of interface prototype object's @@unscopables property 
+PASS Global interface: operation valueOf() 
+PASS Global interface: attribute value 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.js b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.js
new file mode 100644 (file)
index 0000000..25298d3
--- /dev/null
@@ -0,0 +1,40 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+// META: script=../resources/load_wasm.js
+
+'use strict';
+
+// https://webassembly.github.io/spec/js-api/
+
+promise_test(async () => {
+  const srcs = ['wasm-js-api'];
+  const [wasm] = await Promise.all(
+    srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
+
+  const idl_array = new IdlArray();
+  idl_array.add_idls(wasm, {
+    // Note the prose requirements in the specification.
+    except: ['CompileError', 'LinkError', 'RuntimeError']
+  });
+
+  // https://github.com/web-platform-tests/wpt/issues/12850
+  idl_array.add_untested_idls('[Exposed=(Window,Worker)] interface ArrayBuffer {};');
+
+  // Ignored errors are surfaced in idlharness.js's test_object below.
+  try {
+    self.memory = new WebAssembly.Memory({initial: 1024});
+  } catch (e) { }
+
+  try {
+    self.mod = await createWasmModule();
+    self.instance = new WebAssembly.Instance(self.mod);
+  } catch (e) { }
+
+  idl_array.add_objects({
+    Memory: ['memory'],
+    Module: ['mod'],
+    Instance: ['instance'],
+  });
+  idl_array.test();
+}, 'wasm-js-api interfaces.');
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.worker-expected.txt
new file mode 100644 (file)
index 0000000..8666cea
--- /dev/null
@@ -0,0 +1,5 @@
+CONSOLE MESSAGE: NetworkError: Response is not 2xx
+
+Harness Error (FAIL), message = NetworkError: Response is not 2xx
+
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.worker.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.worker.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
index 2252a86..1841d80 100644 (file)
@@ -37,6 +37,7 @@ PASS new WebAssembly.Instance(module): Importing a global with an incorrectly-ty
 PASS new WebAssembly.Instance(module): Importing a global with an incorrectly-typed value: WebAssembly.Global 
 PASS new WebAssembly.Instance(module): Importing a global with an incorrectly-typed value: WebAssembly.Global.prototype 
 PASS new WebAssembly.Instance(module): Importing a global with an incorrectly-typed value: Object.create(WebAssembly.Global.prototype) 
+PASS new WebAssembly.Instance(module): Importing a global with an incorrectly-typed value: WebAssembly.Global object (wrong value type) 
 PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: undefined 
 PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: null 
 PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: true 
@@ -49,6 +50,7 @@ PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-type
 PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: WebAssembly.Memory 
 PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: WebAssembly.Memory.prototype 
 PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: Object.create(WebAssembly.Memory.prototype) 
+PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: WebAssembly.Memory object (too large) 
 PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: undefined 
 PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: null 
 PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: true 
@@ -61,4 +63,5 @@ PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed
 PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: WebAssembly.Table 
 PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: WebAssembly.Table.prototype 
 PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: Object.create(WebAssembly.Table.prototype) 
+PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: WebAssembly.Table object (too large) 
 
index 24c51c1..e88d02b 100644 (file)
@@ -1,5 +1,4 @@
 // META: global=jsshell
-// META: script=/wasm/jsapi/wasm-constants.js
 // META: script=/wasm/jsapi/wasm-module-builder.js
 // META: script=/wasm/jsapi/bad-imports.js
 
@@ -9,6 +8,6 @@ test_bad_imports((name, error, build, ...arguments) => {
     build(builder);
     const buffer = builder.toBuffer();
     const module = new WebAssembly.Module(buffer);
-    assert_throws(error, () => new WebAssembly.Instance(module, ...arguments));
+    assert_throws_js(error, () => new WebAssembly.Instance(module, ...arguments));
   }, `new WebAssembly.Instance(module): ${name}`);
 });
index 2252a86..1841d80 100644 (file)
@@ -37,6 +37,7 @@ PASS new WebAssembly.Instance(module): Importing a global with an incorrectly-ty
 PASS new WebAssembly.Instance(module): Importing a global with an incorrectly-typed value: WebAssembly.Global 
 PASS new WebAssembly.Instance(module): Importing a global with an incorrectly-typed value: WebAssembly.Global.prototype 
 PASS new WebAssembly.Instance(module): Importing a global with an incorrectly-typed value: Object.create(WebAssembly.Global.prototype) 
+PASS new WebAssembly.Instance(module): Importing a global with an incorrectly-typed value: WebAssembly.Global object (wrong value type) 
 PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: undefined 
 PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: null 
 PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: true 
@@ -49,6 +50,7 @@ PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-type
 PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: WebAssembly.Memory 
 PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: WebAssembly.Memory.prototype 
 PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: Object.create(WebAssembly.Memory.prototype) 
+PASS new WebAssembly.Instance(module): Importing memory with an incorrectly-typed value: WebAssembly.Memory object (too large) 
 PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: undefined 
 PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: null 
 PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: true 
@@ -61,4 +63,5 @@ PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed
 PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: WebAssembly.Table 
 PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: WebAssembly.Table.prototype 
 PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: Object.create(WebAssembly.Table.prototype) 
+PASS new WebAssembly.Instance(module): Importing table with an incorrectly-typed value: WebAssembly.Table object (too large) 
 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any-expected.txt
new file mode 100644 (file)
index 0000000..65873de
--- /dev/null
@@ -0,0 +1,3 @@
+
+FAIL constructor-caching assert_equals: expected object "[object WebAssembly.Global]" but got object "[object WebAssembly.Global]"
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.js b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.js
new file mode 100644 (file)
index 0000000..695b078
--- /dev/null
@@ -0,0 +1,54 @@
+// META: global=jsshell
+// META: script=/wasm/jsapi/wasm-module-builder.js
+
+function getExports() {
+  const builder = new WasmModuleBuilder();
+  builder
+    .addFunction("fn", kSig_v_d)
+    .addBody([])
+    .exportFunc();
+
+  builder.setTableBounds(1);
+  builder.addExportOfKind("table", kExternalTable, 0);
+  builder.addGlobal(kWasmI32, false).exportAs("global");
+  builder.addMemory(4, 8, true);
+
+  const buffer = builder.toBuffer();
+  const module = new WebAssembly.Module(buffer);
+  const instance = new WebAssembly.Instance(module);
+  return instance.exports;
+}
+
+test(() => {
+  const exports = getExports();
+
+  const builder = new WasmModuleBuilder();
+  const functionIndex = builder.addImport("module", "imported", kSig_v_d);
+  builder.addExport("exportedFunction", functionIndex);
+
+  const globalIndex = builder.addImportedGlobal("module", "global", kWasmI32);
+  builder.addExportOfKind("exportedGlobal", kExternalGlobal, globalIndex);
+
+  builder.addImportedMemory("module", "memory", 4);
+  builder.exportMemoryAs("exportedMemory");
+
+  const tableIndex = builder.addImportedTable("module", "table", 1);
+  builder.addExportOfKind("exportedTable", kExternalTable, tableIndex);
+
+  const buffer = builder.toBuffer();
+
+  const module = new WebAssembly.Module(buffer);
+  const instance = new WebAssembly.Instance(module, {
+    "module": {
+      "imported": exports.fn,
+      "global": exports.global,
+      "memory": exports.memory,
+      "table": exports.table,
+    }
+  });
+
+  assert_equals(instance.exports.exportedFunction, exports.fn);
+  assert_equals(instance.exports.exportedGlobal, exports.global);
+  assert_equals(instance.exports.exportedMemory, exports.memory);
+  assert_equals(instance.exports.exportedTable, exports.table);
+});
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.worker-expected.txt
new file mode 100644 (file)
index 0000000..65873de
--- /dev/null
@@ -0,0 +1,3 @@
+
+FAIL constructor-caching assert_equals: expected object "[object WebAssembly.Global]" but got object "[object WebAssembly.Global]"
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.worker.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.worker.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
index 209cfac..3f54f74 100644 (file)
@@ -3,10 +3,13 @@ PASS name
 PASS length 
 PASS No arguments 
 PASS Non-Module arguments 
-PASS Non-object imports 
 PASS Calling 
-PASS Empty module 
-PASS getter order for imports object 
+PASS Empty module without imports argument 
+PASS Empty module with undefined imports argument 
+PASS Empty module with empty imports argument 
+FAIL getter order for imports object assert_array_equals: property 1, expected "global1 getter" but got "memory getter"
 PASS imports 
-FAIL exports assert_false: fn: writable expected false got true
+FAIL No imports assert_array_equals: matching export keys property 2, expected "table" but got "global"
+FAIL exports and imports assert_false: fn: writable expected false got true
+PASS stray argument 
 
index 61a8f53..06c6d7a 100644 (file)
@@ -1,63 +1,7 @@
 // META: global=jsshell
-// META: script=/wasm/jsapi/wasm-constants.js
 // META: script=/wasm/jsapi/wasm-module-builder.js
 // META: script=/wasm/jsapi/assertions.js
-
-function assert_exported_function(fn, { name, length }, description) {
-  assert_equals(Object.getPrototypeOf(fn), Function.prototype,
-                `${description}: prototype`);
-
-  assert_function_name(fn, name, description);
-  assert_function_length(fn, length, description);
-}
-
-function assert_Instance(instance, expected_exports) {
-  assert_equals(Object.getPrototypeOf(instance), WebAssembly.Instance.prototype,
-                "prototype");
-  assert_true(Object.isExtensible(instance), "extensible");
-
-  assert_equals(instance.exports, instance.exports, "exports should be idempotent");
-  const exports = instance.exports;
-
-  assert_equals(Object.getPrototypeOf(exports), null, "exports prototype");
-  assert_false(Object.isExtensible(exports), "extensible exports");
-  for (const [key, expected] of Object.entries(expected_exports)) {
-    const property = Object.getOwnPropertyDescriptor(exports, key);
-    assert_equals(typeof property, "object", `${key} should be present`);
-    assert_false(property.writable, `${key}: writable`);
-    assert_true(property.enumerable, `${key}: enumerable`);
-    assert_false(property.configurable, `${key}: configurable`);
-    const actual = property.value;
-    assert_true(Object.isExtensible(actual), `${key}: extensible`);
-
-    switch (expected.kind) {
-    case "function":
-      assert_exported_function(actual, expected, `value of ${key}`);
-      break;
-    case "global":
-      assert_equals(Object.getPrototypeOf(actual), WebAssembly.Global.prototype,
-                    `value of ${key}: prototype`);
-      assert_equals(actual.value, expected.value, `value of ${key}: value`);
-      assert_equals(actual.valueOf(), expected.value, `value of ${key}: valueOf()`);
-      break;
-    case "memory":
-      assert_equals(Object.getPrototypeOf(actual), WebAssembly.Memory.prototype,
-                    `value of ${key}: prototype`);
-      assert_equals(Object.getPrototypeOf(actual.buffer), ArrayBuffer.prototype,
-                    `value of ${key}: prototype of buffer`);
-      assert_equals(actual.buffer.byteLength, 0x10000 * expected.size, `value of ${key}: size of buffer`);
-      const array = new Uint8Array(actual.buffer);
-      assert_equals(array[0], 0, `value of ${key}: first element of buffer`);
-      assert_equals(array[array.byteLength - 1], 0, `value of ${key}: last element of buffer`);
-      break;
-    case "table":
-      assert_equals(Object.getPrototypeOf(actual), WebAssembly.Table.prototype,
-                    `value of ${key}: prototype`);
-      assert_equals(actual.length, expected.length, `value of ${key}: length of table`);
-      break;
-    }
-  }
-}
+// META: script=/wasm/jsapi/instanceTestFactory.js
 
 let emptyModuleBinary;
 setup(() => {
@@ -73,7 +17,7 @@ test(() => {
 }, "length");
 
 test(() => {
-  assert_throws(new TypeError(), () => new WebAssembly.Instance());
+  assert_throws_js(TypeError, () => new WebAssembly.Instance());
 }, "No arguments");
 
 test(() => {
@@ -89,139 +33,22 @@ test(() => {
     WebAssembly.Module.prototype,
   ];
   for (const argument of invalidArguments) {
-    assert_throws(new TypeError(), () => new WebAssembly.Instance(argument),
-                  `new Instance(${format_value(argument)})`);
+    assert_throws_js(TypeError, () => new WebAssembly.Instance(argument),
+                     `new Instance(${format_value(argument)})`);
   }
 }, "Non-Module arguments");
 
 test(() => {
   const module = new WebAssembly.Module(emptyModuleBinary);
-  const invalidArguments = [
-    null,
-    true,
-    "",
-    Symbol(),
-    1,
-  ];
-  for (const argument of invalidArguments) {
-    assert_throws(new TypeError(), () => new WebAssembly.Instance(module, argument),
-                  `new Instance(module, ${format_value(argument)})`);
-  }
-}, "Non-object imports");
-
-test(() => {
-  const module = new WebAssembly.Module(emptyModuleBinary);
-  assert_throws(new TypeError(), () => WebAssembly.Instance(module));
+  assert_throws_js(TypeError, () => WebAssembly.Instance(module));
 }, "Calling");
 
-test(() => {
-  const module = new WebAssembly.Module(emptyModuleBinary);
-  const arguments = [
-    [],
-    [undefined],
-    [{}],
-  ];
-  for (const value of arguments) {
-    const instance = new WebAssembly.Instance(module, ...arguments);
-    assert_Instance(instance, {});
-  }
-}, "Empty module");
-
-test(() => {
-  const builder = new WasmModuleBuilder();
-  builder.addImportedGlobal("module", "global1", kWasmI32);
-  builder.addImportedGlobal("module", "global2", kWasmI32);
-  const buffer = builder.toBuffer();
-  const module = new WebAssembly.Module(buffer);
-  const order = [];
-  const imports = {
-    get module() {
-      order.push("module getter");
-      return {
-        get global1() {
-          order.push("global1 getter");
-          return 0;
-        },
-        get global2() {
-          order.push("global2 getter");
-          return 0;
-        },
-      }
-    },
-  };
-  new WebAssembly.Instance(module, imports);
-  const expected = [
-    "module getter",
-    "global1 getter",
-    "module getter",
-    "global2 getter",
-  ];
-  assert_array_equals(order, expected);
-}, "getter order for imports object");
-
-test(() => {
-  const builder = new WasmModuleBuilder();
-
-  builder.addImport("module", "fn", kSig_v_v);
-  builder.addImportedGlobal("module", "global", kWasmI32);
-  builder.addImportedMemory("module", "memory", 0, 128);
-  builder.addImportedTable("module", "table", 0, 128);
-
-  const buffer = builder.toBuffer();
-  const module = new WebAssembly.Module(buffer);
-  const instance = new WebAssembly.Instance(module, {
-    "module": {
-      "fn": function() {},
-      "global": 0,
-      "memory": new WebAssembly.Memory({ "initial": 64, maximum: 128 }),
-      "table": new WebAssembly.Table({ "element": "anyfunc", "initial": 64, maximum: 128 }),
-    },
-    get "module2"() {
-      assert_unreached("Should not get modules that are not imported");
-    },
-  });
-  assert_Instance(instance, {});
-}, "imports");
-
-test(() => {
-  const builder = new WasmModuleBuilder();
-
-  builder
-    .addFunction("fn", kSig_v_d)
-    .addBody([
-        kExprEnd
-    ])
-    .exportFunc();
-  builder
-    .addFunction("fn2", kSig_v_v)
-    .addBody([
-        kExprEnd
-    ])
-    .exportFunc();
-
-  builder.setFunctionTableLength(1);
-  builder.addExportOfKind("table", kExternalTable, 0);
-
-  builder.addGlobal(kWasmI32, true)
-    .exportAs("global")
-    .init = 7;
-  builder.addGlobal(kWasmF64, true)
-    .exportAs("global2")
-    .init = 1.2;
-
-  builder.addMemory(4, 8, true);
-
-  const buffer = builder.toBuffer()
-  const module = new WebAssembly.Module(buffer);
-
-  const instance = new WebAssembly.Instance(module, {});
-  const expected = {
-    "fn": { "kind": "function", "name": "0", "length": 1 },
-    "fn2": { "kind": "function", "name": "1", "length": 0 },
-    "table": { "kind": "table", "length": 1 },
-    "global": { "kind": "global", "value": 7 },
-    "global2": { "kind": "global", "value": 1.2 },
-    "memory": { "kind": "memory", "size": 4 },
-  };
-  assert_Instance(instance, expected);
-}, "exports");
+for (const [name, fn] of instanceTestFactory) {
+  test(() => {
+    const { buffer, args, exports, verify } = fn();
+    const module = new WebAssembly.Module(buffer);
+    const instance = new WebAssembly.Instance(module, ...args);
+    assert_Instance(instance, exports);
+    verify(instance);
+  }, name);
+}
index 209cfac..3f54f74 100644 (file)
@@ -3,10 +3,13 @@ PASS name
 PASS length 
 PASS No arguments 
 PASS Non-Module arguments 
-PASS Non-object imports 
 PASS Calling 
-PASS Empty module 
-PASS getter order for imports object 
+PASS Empty module without imports argument 
+PASS Empty module with undefined imports argument 
+PASS Empty module with empty imports argument 
+FAIL getter order for imports object assert_array_equals: property 1, expected "global1 getter" but got "memory getter"
 PASS imports 
-FAIL exports assert_false: fn: writable expected false got true
+FAIL No imports assert_array_equals: matching export keys property 2, expected "table" but got "global"
+FAIL exports and imports assert_false: fn: writable expected false got true
+PASS stray argument 
 
index 3142391..7c81a41 100644 (file)
@@ -1,5 +1,4 @@
 // META: global=jsshell
-// META: script=/wasm/jsapi/wasm-constants.js
 // META: script=/wasm/jsapi/wasm-module-builder.js
 
 let emptyModuleBinary;
@@ -29,7 +28,7 @@ test(() => {
   assert_equals(typeof desc.set, "undefined");
 
   for (const thisValue of thisValues) {
-    assert_throws(new TypeError(), () => getter.call(thisValue), `this=${format_value(thisValue)}`);
+    assert_throws_js(TypeError, () => getter.call(thisValue), `this=${format_value(thisValue)}`);
   }
 }, "Branding");
 
@@ -37,6 +36,20 @@ test(() => {
   const module = new WebAssembly.Module(emptyModuleBinary);
   const instance = new WebAssembly.Instance(module);
   const exports = instance.exports;
+
+  const desc = Object.getOwnPropertyDescriptor(WebAssembly.Instance.prototype, "exports");
+  assert_equals(typeof desc, "object");
+
+  const getter = desc.get;
+  assert_equals(typeof getter, "function");
+
+  assert_equals(getter.call(instance, {}), exports);
+}, "Stray argument");
+
+test(() => {
+  const module = new WebAssembly.Module(emptyModuleBinary);
+  const instance = new WebAssembly.Instance(module);
+  const exports = instance.exports;
   instance.exports = {};
   assert_equals(instance.exports, exports, "Should not change the exports");
 }, "Setting (sloppy mode)");
@@ -45,7 +58,7 @@ test(() => {
   const module = new WebAssembly.Module(emptyModuleBinary);
   const instance = new WebAssembly.Instance(module);
   const exports = instance.exports;
-  assert_throws(new TypeError(), () => {
+  assert_throws_js(TypeError, () => {
     "use strict";
     instance.exports = {};
   });
index 73038a9..a381c59 100644 (file)
@@ -1,3 +1,4 @@
 
 PASS Object.prototype.toString on an Instance 
+FAIL @@toStringTag exists on the prototype with the appropriate descriptor assert_own_property: expected property symbol "Symbol(Symbol.toStringTag)" missing
 
index 08dcb14..701ec8f 100644 (file)
@@ -1,5 +1,4 @@
 // META: global=jsshell
-// META: script=/wasm/jsapi/wasm-constants.js
 // META: script=/wasm/jsapi/wasm-module-builder.js
 
 test(() => {
@@ -8,3 +7,13 @@ test(() => {
   const instance = new WebAssembly.Instance(module);
   assert_class_string(instance, "WebAssembly.Instance");
 }, "Object.prototype.toString on an Instance");
+
+test(() => {
+  assert_own_property(WebAssembly.Instance.prototype, Symbol.toStringTag);
+
+  const propDesc = Object.getOwnPropertyDescriptor(WebAssembly.Instance.prototype, Symbol.toStringTag);
+  assert_equals(propDesc.value, "WebAssembly.Instance", "value");
+  assert_equals(propDesc.configurable, true, "configurable");
+  assert_equals(propDesc.enumerable, false, "enumerable");
+  assert_equals(propDesc.writable, false, "writable");
+}, "@@toStringTag exists on the prototype with the appropriate descriptor");
index 73038a9..a381c59 100644 (file)
@@ -1,3 +1,4 @@
 
 PASS Object.prototype.toString on an Instance 
+FAIL @@toStringTag exists on the prototype with the appropriate descriptor assert_own_property: expected property symbol "Symbol(Symbol.toStringTag)" missing
 
index e689698..37dd5af 100644 (file)
@@ -15,6 +15,7 @@ None
 ------------------------------------------------------------------------
 List of files:
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-bad-imports.any.js
+/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor-caching.any.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/constructor.any.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/exports.any.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instance/toString.any.js
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instanceTestFactory.js b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instanceTestFactory.js
new file mode 100644 (file)
index 0000000..c81672f
--- /dev/null
@@ -0,0 +1,224 @@
+const instanceTestFactory = [
+  [
+    "Empty module without imports argument",
+    function() {
+      return {
+        buffer: emptyModuleBinary,
+        args: [],
+        exports: {},
+        verify: () => {},
+      };
+    }
+  ],
+
+  [
+    "Empty module with undefined imports argument",
+    function() {
+      return {
+        buffer: emptyModuleBinary,
+        args: [undefined],
+        exports: {},
+        verify: () => {},
+      };
+    }
+  ],
+
+  [
+    "Empty module with empty imports argument",
+    function() {
+      return {
+        buffer: emptyModuleBinary,
+        args: [{}],
+        exports: {},
+        verify: () => {},
+      };
+    }
+  ],
+
+  [
+    "getter order for imports object",
+    function() {
+      const builder = new WasmModuleBuilder();
+      builder.addImportedGlobal("module", "global1", kWasmI32);
+      builder.addImportedGlobal("module2", "global3", kWasmI32);
+      builder.addImportedMemory("module", "memory", 0, 128);
+      builder.addImportedGlobal("module", "global2", kWasmI32);
+      const buffer = builder.toBuffer();
+      const order = [];
+
+      const imports = {
+        get module() {
+          order.push("module getter");
+          return {
+            get global1() {
+              order.push("global1 getter");
+              return 0;
+            },
+            get global2() {
+              order.push("global2 getter");
+              return 0;
+            },
+            get memory() {
+              order.push("memory getter");
+              return new WebAssembly.Memory({ "initial": 64, maximum: 128 });
+            },
+          }
+        },
+        get module2() {
+          order.push("module2 getter");
+          return {
+            get global3() {
+              order.push("global3 getter");
+              return 0;
+            },
+          }
+        },
+      };
+
+      const expected = [
+        "module getter",
+        "global1 getter",
+        "module2 getter",
+        "global3 getter",
+        "module getter",
+        "memory getter",
+        "module getter",
+        "global2 getter",
+      ];
+      return {
+        buffer,
+        args: [imports],
+        exports: {},
+        verify: () => assert_array_equals(order, expected),
+      };
+    }
+  ],
+
+  [
+    "imports",
+    function() {
+      const builder = new WasmModuleBuilder();
+
+      builder.addImport("module", "fn", kSig_v_v);
+      builder.addImportedGlobal("module", "global", kWasmI32);
+      builder.addImportedMemory("module", "memory", 0, 128);
+      builder.addImportedTable("module", "table", 0, 128);
+
+      const buffer = builder.toBuffer();
+      const imports = {
+        "module": {
+          "fn": function() {},
+          "global": 0,
+          "memory": new WebAssembly.Memory({ "initial": 64, maximum: 128 }),
+          "table": new WebAssembly.Table({ "element": "anyfunc", "initial": 64, maximum: 128 }),
+        },
+        get "module2"() {
+          assert_unreached("Should not get modules that are not imported");
+        },
+      };
+
+      return {
+        buffer,
+        args: [imports],
+        exports: {},
+        verify: () => {},
+      };
+    }
+  ],
+
+  [
+    "No imports",
+    function() {
+      const builder = new WasmModuleBuilder();
+
+      builder
+        .addFunction("fn", kSig_v_d)
+        .addBody([])
+        .exportFunc();
+      builder
+        .addFunction("fn2", kSig_v_v)
+        .addBody([])
+        .exportFunc();
+
+      builder.setTableBounds(1);
+      builder.addExportOfKind("table", kExternalTable, 0);
+
+      builder.addGlobal(kWasmI32, true)
+        .exportAs("global")
+        .init = 7;
+      builder.addGlobal(kWasmF64, true)
+        .exportAs("global2")
+        .init = 1.2;
+
+      builder.addMemory(4, 8, true);
+
+      const buffer = builder.toBuffer();
+
+      const exports = {
+        "fn": { "kind": "function", "name": "0", "length": 1 },
+        "fn2": { "kind": "function", "name": "1", "length": 0 },
+        "table": { "kind": "table", "length": 1 },
+        "global": { "kind": "global", "value": 7 },
+        "global2": { "kind": "global", "value": 1.2 },
+        "memory": { "kind": "memory", "size": 4 },
+      };
+
+      return {
+        buffer,
+        args: [],
+        exports,
+        verify: () => {},
+      };
+    }
+  ],
+
+  [
+    "exports and imports",
+    function() {
+      const value = 102;
+
+      const builder = new WasmModuleBuilder();
+
+      const index = builder.addImportedGlobal("module", "global", kWasmI32);
+      builder
+        .addFunction("fn", kSig_i_v)
+        .addBody([
+            kExprGlobalGet,
+            index,
+            kExprReturn,
+        ])
+        .exportFunc();
+
+      const buffer = builder.toBuffer();
+
+      const imports = {
+        "module": {
+          "global": value,
+        },
+      };
+
+      const exports = {
+        "fn": { "kind": "function", "name": "0", "length": 0 },
+      };
+
+      return {
+        buffer,
+        args: [imports],
+        exports,
+        verify: instance => assert_equals(instance.exports.fn(), value)
+      };
+    }
+  ],
+
+  [
+    "stray argument",
+    function() {
+      return {
+        buffer: emptyModuleBinary,
+        args: [{}, {}],
+        exports: {},
+        verify: () => {}
+      };
+    }
+  ],
+];
index dc892d7..229ff2e 100644 (file)
@@ -35,55 +35,37 @@ PASS WebAssembly.compile: length
 PASS WebAssembly.instantiate 
 PASS WebAssembly.instantiate: name 
 PASS WebAssembly.instantiate: length 
-FAIL WebAssembly.Module.exports assert_equals: expected (undefined) undefined but got (function) function "function exports() {
-    [native code]
-}"
+PASS WebAssembly.Module.exports 
 PASS WebAssembly.Module.exports: name 
 PASS WebAssembly.Module.exports: length 
-FAIL WebAssembly.Module.imports assert_equals: expected (undefined) undefined but got (function) function "function imports() {
-    [native code]
-}"
+PASS WebAssembly.Module.imports 
 PASS WebAssembly.Module.imports: name 
 PASS WebAssembly.Module.imports: length 
-FAIL WebAssembly.Module.customSections assert_equals: expected (undefined) undefined but got (function) function "function customSections() {
-    [native code]
-}"
+PASS WebAssembly.Module.customSections 
 PASS WebAssembly.Module.customSections: name 
 PASS WebAssembly.Module.customSections: length 
 PASS WebAssembly.Instance.exports 
 PASS WebAssembly.Instance.exports: getter 
 PASS WebAssembly.Instance.exports: setter 
-FAIL WebAssembly.Memory.grow assert_equals: expected (undefined) undefined but got (function) function "function grow() {
-    [native code]
-}"
+PASS WebAssembly.Memory.grow 
 PASS WebAssembly.Memory.grow: name 
 PASS WebAssembly.Memory.grow: length 
 PASS WebAssembly.Memory.buffer 
 PASS WebAssembly.Memory.buffer: getter 
 PASS WebAssembly.Memory.buffer: setter 
-FAIL WebAssembly.Table.grow assert_equals: expected (undefined) undefined but got (function) function "function grow() {
-    [native code]
-}"
+PASS WebAssembly.Table.grow 
 PASS WebAssembly.Table.grow: name 
 PASS WebAssembly.Table.grow: length 
-FAIL WebAssembly.Table.get assert_equals: expected (undefined) undefined but got (function) function "function get() {
-    [native code]
-}"
+PASS WebAssembly.Table.get 
 PASS WebAssembly.Table.get: name 
 PASS WebAssembly.Table.get: length 
-FAIL WebAssembly.Table.set assert_equals: expected (undefined) undefined but got (function) function "function set() {
-    [native code]
-}"
+PASS WebAssembly.Table.set 
 PASS WebAssembly.Table.set: name 
 PASS WebAssembly.Table.set: length 
 PASS WebAssembly.Table.length 
 PASS WebAssembly.Table.length: getter 
 PASS WebAssembly.Table.length: setter 
-FAIL WebAssembly.Global.valueOf assert_equals: expected function "function valueOf() {
-    [native code]
-}" but got function "function valueOf() {
-    [native code]
-}"
+PASS WebAssembly.Global.valueOf 
 PASS WebAssembly.Global.valueOf: name 
 PASS WebAssembly.Global.valueOf: length 
 PASS WebAssembly.Global.value 
index 5d76ac5..88940be 100644 (file)
@@ -9,7 +9,7 @@ function test_operations(object, object_name, operations) {
       assert_true(propdesc.writable, "writable");
       assert_true(propdesc.enumerable, "enumerable");
       assert_true(propdesc.configurable, "configurable");
-      assert_equals(propdesc.value, WebAssembly[name]);
+      assert_equals(propdesc.value, object[name]);
     }, `${object_name}.${name}`);
 
     test(() => {
@@ -63,11 +63,11 @@ test(() => {
 }, "WebAssembly: property descriptor");
 
 test(() => {
-  assert_throws(new TypeError(), () => WebAssembly());
+  assert_throws_js(TypeError, () => WebAssembly());
 }, "WebAssembly: calling");
 
 test(() => {
-  assert_throws(new TypeError(), () => new WebAssembly());
+  assert_throws_js(TypeError, () => new WebAssembly());
 }, "WebAssembly: constructing");
 
 const interfaces = [
index dc892d7..229ff2e 100644 (file)
@@ -35,55 +35,37 @@ PASS WebAssembly.compile: length
 PASS WebAssembly.instantiate 
 PASS WebAssembly.instantiate: name 
 PASS WebAssembly.instantiate: length 
-FAIL WebAssembly.Module.exports assert_equals: expected (undefined) undefined but got (function) function "function exports() {
-    [native code]
-}"
+PASS WebAssembly.Module.exports 
 PASS WebAssembly.Module.exports: name 
 PASS WebAssembly.Module.exports: length 
-FAIL WebAssembly.Module.imports assert_equals: expected (undefined) undefined but got (function) function "function imports() {
-    [native code]
-}"
+PASS WebAssembly.Module.imports 
 PASS WebAssembly.Module.imports: name 
 PASS WebAssembly.Module.imports: length 
-FAIL WebAssembly.Module.customSections assert_equals: expected (undefined) undefined but got (function) function "function customSections() {
-    [native code]
-}"
+PASS WebAssembly.Module.customSections 
 PASS WebAssembly.Module.customSections: name 
 PASS WebAssembly.Module.customSections: length 
 PASS WebAssembly.Instance.exports 
 PASS WebAssembly.Instance.exports: getter 
 PASS WebAssembly.Instance.exports: setter 
-FAIL WebAssembly.Memory.grow assert_equals: expected (undefined) undefined but got (function) function "function grow() {
-    [native code]
-}"
+PASS WebAssembly.Memory.grow 
 PASS WebAssembly.Memory.grow: name 
 PASS WebAssembly.Memory.grow: length 
 PASS WebAssembly.Memory.buffer 
 PASS WebAssembly.Memory.buffer: getter 
 PASS WebAssembly.Memory.buffer: setter 
-FAIL WebAssembly.Table.grow assert_equals: expected (undefined) undefined but got (function) function "function grow() {
-    [native code]
-}"
+PASS WebAssembly.Table.grow 
 PASS WebAssembly.Table.grow: name 
 PASS WebAssembly.Table.grow: length 
-FAIL WebAssembly.Table.get assert_equals: expected (undefined) undefined but got (function) function "function get() {
-    [native code]
-}"
+PASS WebAssembly.Table.get 
 PASS WebAssembly.Table.get: name 
 PASS WebAssembly.Table.get: length 
-FAIL WebAssembly.Table.set assert_equals: expected (undefined) undefined but got (function) function "function set() {
-    [native code]
-}"
+PASS WebAssembly.Table.set 
 PASS WebAssembly.Table.set: name 
 PASS WebAssembly.Table.set: length 
 PASS WebAssembly.Table.length 
 PASS WebAssembly.Table.length: getter 
 PASS WebAssembly.Table.length: setter 
-FAIL WebAssembly.Global.valueOf assert_equals: expected function "function valueOf() {
-    [native code]
-}" but got function "function valueOf() {
-    [native code]
-}"
+PASS WebAssembly.Global.valueOf 
 PASS WebAssembly.Global.valueOf: name 
 PASS WebAssembly.Global.valueOf: length 
 PASS WebAssembly.Global.value 
index b04460b..a835e65 100644 (file)
@@ -22,13 +22,27 @@ test(() => {
   assert_equals(typeof desc.set, "undefined");
 
   for (const thisValue of thisValues) {
-    assert_throws(new TypeError(), () => getter.call(thisValue), `this=${format_value(thisValue)}`);
+    assert_throws_js(TypeError, () => getter.call(thisValue), `this=${format_value(thisValue)}`);
   }
 }, "Branding");
 
 test(() => {
   const argument = { "initial": 0 };
   const memory = new WebAssembly.Memory(argument);
+  const buffer = memory.buffer;
+
+  const desc = Object.getOwnPropertyDescriptor(WebAssembly.Memory.prototype, "buffer");
+  assert_equals(typeof desc, "object");
+
+  const getter = desc.get;
+  assert_equals(typeof getter, "function");
+
+  assert_equals(getter.call(memory, {}), buffer);
+}, "Stray argument");
+
+test(() => {
+  const argument = { "initial": 0 };
+  const memory = new WebAssembly.Memory(argument);
   const memory2 = new WebAssembly.Memory(argument);
   const buffer = memory.buffer;
   assert_not_equals(buffer, memory2.buffer, "Need two distinct buffers");
@@ -42,7 +56,7 @@ test(() => {
   const memory2 = new WebAssembly.Memory(argument);
   const buffer = memory.buffer;
   assert_not_equals(buffer, memory2.buffer, "Need two distinct buffers");
-  assert_throws(new TypeError(), () => {
+  assert_throws_js(TypeError, () => {
     "use strict";
     memory.buffer = memory2.buffer;
   });
index 074a2e6..158a6ae 100644 (file)
@@ -17,8 +17,13 @@ PASS Out-of-range initial value in descriptor: 4294967296
 PASS Out-of-range maximum value in descriptor: 4294967296 
 PASS Out-of-range initial value in descriptor: 68719476736 
 PASS Out-of-range maximum value in descriptor: 68719476736 
+PASS Initial value exceeds maximum 
+FAIL Shared memory without maximum assert_throws_js: function "() => new WebAssembly.Memory({ "initial": 10, "shared": true })" did not throw
 PASS Proxy descriptor 
 PASS Order of evaluation for descriptor 
+FAIL Order of evaluation for descriptor (with shared) assert_array_equals: lengths differ, expected 5 got 4
 PASS Zero initial 
 PASS Non-zero initial 
+FAIL Stray argument WebAssembly.Memory expects exactly one argument
+FAIL Shared memory undefined is not an object (evaluating 'bufferType.prototype')
 
index f9907ca..03eed52 100644 (file)
@@ -8,15 +8,18 @@ function assert_Memory(memory, expected) {
 
   // https://github.com/WebAssembly/spec/issues/840
   assert_equals(memory.buffer, memory.buffer, "buffer should be idempotent");
-  assert_equals(Object.getPrototypeOf(memory.buffer), ArrayBuffer.prototype,
-                "prototype of buffer");
-  assert_true(Object.isExtensible(memory.buffer), "buffer extensibility");
+  const isShared = !!expected.shared;
+  const bufferType = isShared ? self.SharedArrayBuffer : ArrayBuffer;
+  assert_equals(Object.getPrototypeOf(memory.buffer), bufferType.prototype,
+                'prototype of buffer');
   assert_equals(memory.buffer.byteLength, 0x10000 * expected.size, "size of buffer");
   if (expected.size > 0) {
     const array = new Uint8Array(memory.buffer);
     assert_equals(array[0], 0, "first element of buffer");
     assert_equals(array[array.byteLength - 1], 0, "last element of buffer");
   }
+  assert_equals(isShared, Object.isFrozen(memory.buffer), "buffer frozen");
+  assert_not_equals(Object.isExtensible(memory.buffer), isShared, "buffer extensibility");
 }
 
 test(() => {
@@ -28,12 +31,12 @@ test(() => {
 }, "length");
 
 test(() => {
-  assert_throws(new TypeError(), () => new WebAssembly.Memory());
+  assert_throws_js(TypeError, () => new WebAssembly.Memory());
 }, "No arguments");
 
 test(() => {
   const argument = { "initial": 0 };
-  assert_throws(new TypeError(), () => WebAssembly.Memory(argument));
+  assert_throws_js(TypeError, () => WebAssembly.Memory(argument));
 }, "Calling");
 
 test(() => {
@@ -50,14 +53,14 @@ test(() => {
     {},
   ];
   for (const invalidArgument of invalidArguments) {
-    assert_throws(new TypeError(),
-                  () => new WebAssembly.Memory(invalidArgument),
-                  `new Memory(${format_value(invalidArgument)})`);
+    assert_throws_js(TypeError,
+                     () => new WebAssembly.Memory(invalidArgument),
+                     `new Memory(${format_value(invalidArgument)})`);
   }
 }, "Invalid descriptor argument");
 
 test(() => {
-  assert_throws(new TypeError(), () => new WebAssembly.Memory({ "initial": undefined }));
+  assert_throws_js(TypeError, () => new WebAssembly.Memory({ "initial": undefined }));
 }, "Undefined initial value in descriptor");
 
 const outOfRangeValues = [
@@ -71,15 +74,23 @@ const outOfRangeValues = [
 
 for (const value of outOfRangeValues) {
   test(() => {
-    assert_throws(new TypeError(), () => new WebAssembly.Memory({ "initial": value }));
+    assert_throws_js(TypeError, () => new WebAssembly.Memory({ "initial": value }));
   }, `Out-of-range initial value in descriptor: ${format_value(value)}`);
 
   test(() => {
-    assert_throws(new TypeError(), () => new WebAssembly.Memory({ "initial": 0, "maximum": value }));
+    assert_throws_js(TypeError, () => new WebAssembly.Memory({ "initial": 0, "maximum": value }));
   }, `Out-of-range maximum value in descriptor: ${format_value(value)}`);
 }
 
 test(() => {
+  assert_throws_js(RangeError, () => new WebAssembly.Memory({ "initial": 10, "maximum": 9 }));
+}, "Initial value exceeds maximum");
+
+test(() => {
+  assert_throws_js(TypeError, () => new WebAssembly.Memory({ "initial": 10, "shared": true }));
+}, "Shared memory without maximum");
+
+test(() => {
   const proxy = new Proxy({}, {
     has(o, x) {
       assert_unreached(`Should not call [[HasProperty]] with ${x}`);
@@ -124,6 +135,47 @@ test(() => {
   ]);
 }, "Order of evaluation for descriptor");
 
+test(t => {
+  const order = [];
+
+  new WebAssembly.Memory({
+    get maximum() {
+      order.push("maximum");
+      return {
+        valueOf() {
+          order.push("maximum valueOf");
+          return 1;
+        },
+      };
+    },
+
+    get initial() {
+      order.push("initial");
+      return {
+        valueOf() {
+          order.push("initial valueOf");
+          return 1;
+        },
+      };
+    },
+
+    get shared() {
+      order.push("shared");
+      return {
+        valueOf: t.unreached_func("should not call shared valueOf"),
+      };
+    },
+  });
+
+  assert_array_equals(order, [
+    "initial",
+    "initial valueOf",
+    "maximum",
+    "maximum valueOf",
+    "shared",
+  ]);
+}, "Order of evaluation for descriptor (with shared)");
+
 test(() => {
   const argument = { "initial": 0 };
   const memory = new WebAssembly.Memory(argument);
@@ -135,3 +187,15 @@ test(() => {
   const memory = new WebAssembly.Memory(argument);
   assert_Memory(memory, { "size": 4 });
 }, "Non-zero initial");
+
+test(() => {
+  const argument = { "initial": 0 };
+  const memory = new WebAssembly.Memory(argument, {});
+  assert_Memory(memory, { "size": 0 });
+}, "Stray argument");
+
+test(() => {
+  const argument = { "initial": 4, "maximum": 10, shared: true };
+  const memory = new WebAssembly.Memory(argument);
+  assert_Memory(memory, { "size": 4, "shared": true });
+}, "Shared memory");
index 074a2e6..158a6ae 100644 (file)
@@ -17,8 +17,13 @@ PASS Out-of-range initial value in descriptor: 4294967296
 PASS Out-of-range maximum value in descriptor: 4294967296 
 PASS Out-of-range initial value in descriptor: 68719476736 
 PASS Out-of-range maximum value in descriptor: 68719476736 
+PASS Initial value exceeds maximum 
+FAIL Shared memory without maximum assert_throws_js: function "() => new WebAssembly.Memory({ "initial": 10, "shared": true })" did not throw
 PASS Proxy descriptor 
 PASS Order of evaluation for descriptor 
+FAIL Order of evaluation for descriptor (with shared) assert_array_equals: lengths differ, expected 5 got 4
 PASS Zero initial 
 PASS Non-zero initial 
+FAIL Stray argument WebAssembly.Memory expects exactly one argument
+FAIL Shared memory undefined is not an object (evaluating 'bufferType.prototype')
 
index 33489b6..be91ba3 100644 (file)
@@ -16,4 +16,6 @@ PASS Out-of-range argument: 4294967296
 PASS Out-of-range argument: 68719476736 
 PASS Out-of-range argument: "0x100000000" 
 PASS Out-of-range argument: object "[object Object]" 
+PASS Stray argument 
+FAIL Growing shared memory does not detach old buffer assert_equals: Buffer before growing: constructor expected true but got false
 
index 9530039..0cea8b4 100644 (file)
@@ -1,10 +1,14 @@
 // META: global=jsshell
 
-function assert_ArrayBuffer(actual, expected, message) {
+function assert_ArrayBuffer(actual, { size=0, shared=false, detached=false }, message) {
   // https://github.com/WebAssembly/spec/issues/840
-  assert_equals(Object.getPrototypeOf(actual), ArrayBuffer.prototype,
-                `${message}: prototype`);
-  if (expected.detached) {
+  // See https://github.com/whatwg/html/issues/5380 for why not `self.SharedArrayBuffer`
+  const isShared = !("isView" in actual.constructor);
+  assert_equals(isShared, shared, `${message}: constructor`);
+  const sharedString = shared ? "Shared" : "";
+  assert_equals(actual.toString(), `[object ${sharedString}ArrayBuffer]`, `${message}: toString()`);
+  assert_equals(Object.getPrototypeOf(actual).toString(), `[object ${sharedString}ArrayBuffer]`, `${message}: prototype toString()`);
+  if (detached) {
     // https://github.com/tc39/ecma262/issues/678
     let byteLength;
     try {
@@ -14,8 +18,8 @@ function assert_ArrayBuffer(actual, expected, message) {
     }
     assert_equals(byteLength, 0, `${message}: detached size`);
   } else {
-    assert_equals(actual.byteLength, 0x10000 * expected.size, `${message}: size`);
-    if (expected.size > 0) {
+    assert_equals(actual.byteLength, 0x10000 * size, `${message}: size`);
+    if (size > 0) {
       const array = new Uint8Array(actual);
       assert_equals(array[0], 0, `${message}: first element`);
       assert_equals(array[array.byteLength - 1], 0, `${message}: last element`);
@@ -26,7 +30,7 @@ function assert_ArrayBuffer(actual, expected, message) {
 test(() => {
   const argument = { "initial": 0 };
   const memory = new WebAssembly.Memory(argument);
-  assert_throws(new TypeError(), () => memory.grow());
+  assert_throws_js(TypeError, () => memory.grow());
 }, "Missing arguments");
 
 test(t => {
@@ -50,7 +54,7 @@ test(t => {
   const fn = WebAssembly.Memory.prototype.grow;
 
   for (const thisValue of thisValues) {
-    assert_throws(new TypeError(), () => fn.call(thisValue, argument), `this=${format_value(thisValue)}`);
+    assert_throws_js(TypeError, () => fn.call(thisValue, argument), `this=${format_value(thisValue)}`);
   }
 }, "Branding");
 
@@ -144,7 +148,7 @@ test(() => {
   const oldMemory = memory.buffer;
   assert_ArrayBuffer(oldMemory, { "size": 1 }, "Buffer before growing");
 
-  assert_throws(new RangeError(), () => memory.grow(2));
+  assert_throws_js(RangeError, () => memory.grow(2));
   assert_equals(memory.buffer, oldMemory);
   assert_ArrayBuffer(memory.buffer, { "size": 1 }, "Buffer before trying to grow");
 }, "Zero initial growing too much");
@@ -165,6 +169,47 @@ for (const value of outOfRangeValues) {
   test(() => {
     const argument = { "initial": 0 };
     const memory = new WebAssembly.Memory(argument);
-    assert_throws(new TypeError(), () => memory.grow(value));
+    assert_throws_js(TypeError, () => memory.grow(value));
   }, `Out-of-range argument: ${format_value(value)}`);
 }
+
+test(() => {
+  const argument = { "initial": 0 };
+  const memory = new WebAssembly.Memory(argument);
+  const oldMemory = memory.buffer;
+  assert_ArrayBuffer(oldMemory, { "size": 0 }, "Buffer before growing");
+
+  const result = memory.grow(2, {});
+  assert_equals(result, 0);
+
+  const newMemory = memory.buffer;
+  assert_not_equals(oldMemory, newMemory);
+  assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing");
+  assert_ArrayBuffer(newMemory, { "size": 2 }, "New buffer after growing");
+}, "Stray argument");
+
+test(() => {
+  const argument = { "initial": 1, "maximum": 2, "shared": true };
+  const memory = new WebAssembly.Memory(argument);
+  const oldMemory = memory.buffer;
+  assert_ArrayBuffer(oldMemory, { "size": 1, "shared": true }, "Buffer before growing");
+
+  const result = memory.grow(1);
+  assert_equals(result, 1);
+
+  const newMemory = memory.buffer;
+  assert_not_equals(oldMemory, newMemory);
+  assert_ArrayBuffer(oldMemory, { "size": 1, "shared": true }, "Old buffer after growing");
+  assert_ArrayBuffer(newMemory, { "size": 2, "shared": true }, "New buffer after growing");
+
+  // The old and new buffers must have the same value for the
+  // [[ArrayBufferData]] internal slot.
+  const oldArray = new Uint8Array(oldMemory);
+  const newArray = new Uint8Array(newMemory);
+  assert_equals(oldArray[0], 0, "old first element");
+  assert_equals(newArray[0], 0, "new first element");
+  oldArray[0] = 1;
+  assert_equals(oldArray[0], 1, "old first element");
+  assert_equals(newArray[0], 1, "new first element");
+
+}, "Growing shared memory does not detach old buffer");
index 33489b6..be91ba3 100644 (file)
@@ -16,4 +16,6 @@ PASS Out-of-range argument: 4294967296
 PASS Out-of-range argument: 68719476736 
 PASS Out-of-range argument: "0x100000000" 
 PASS Out-of-range argument: object "[object Object]" 
+PASS Stray argument 
+FAIL Growing shared memory does not detach old buffer assert_equals: Buffer before growing: constructor expected true but got false
 
index 65e4440..d20f3b5 100644 (file)
@@ -1,3 +1,4 @@
 
 PASS Object.prototype.toString on an Memory 
+FAIL @@toStringTag exists on the prototype with the appropriate descriptor assert_own_property: expected property symbol "Symbol(Symbol.toStringTag)" missing
 
index 4e15d75..bb9081d 100644 (file)
@@ -5,3 +5,13 @@ test(() => {
   const memory = new WebAssembly.Memory(argument);
   assert_class_string(memory, "WebAssembly.Memory");
 }, "Object.prototype.toString on an Memory");
+
+test(() => {
+  assert_own_property(WebAssembly.Memory.prototype, Symbol.toStringTag);
+
+  const propDesc = Object.getOwnPropertyDescriptor(WebAssembly.Memory.prototype, Symbol.toStringTag);
+  assert_equals(propDesc.value, "WebAssembly.Memory", "value");
+  assert_equals(propDesc.configurable, true, "configurable");
+  assert_equals(propDesc.enumerable, false, "enumerable");
+  assert_equals(propDesc.writable, false, "writable");
+}, "@@toStringTag exists on the prototype with the appropriate descriptor");
index 65e4440..d20f3b5 100644 (file)
@@ -1,3 +1,4 @@
 
 PASS Object.prototype.toString on an Memory 
+FAIL @@toStringTag exists on the prototype with the appropriate descriptor assert_own_property: expected property symbol "Symbol(Symbol.toStringTag)" missing
 
index 32f183f..ac4cde2 100644 (file)
@@ -1,5 +1,4 @@
 // META: global=jsshell
-// META: script=/wasm/jsapi/wasm-constants.js
 // META: script=/wasm/jsapi/wasm-module-builder.js
 // META: script=/wasm/jsapi/assertions.js
 
@@ -17,11 +16,11 @@ test(() => {
 }, "length");
 
 test(() => {
-  assert_throws(new TypeError(), () => new WebAssembly.Module());
+  assert_throws_js(TypeError, () => new WebAssembly.Module());
 }, "No arguments");
 
 test(() => {
-  assert_throws(new TypeError(), () => WebAssembly.Module(emptyModuleBinary));
+  assert_throws_js(TypeError, () => WebAssembly.Module(emptyModuleBinary));
 }, "Calling");
 
 test(() => {
@@ -39,17 +38,22 @@ test(() => {
     Array.from(emptyModuleBinary),
   ];
   for (const argument of invalidArguments) {
-    assert_throws(new TypeError(), () => new WebAssembly.Module(argument),
-                  `new Module(${format_value(argument)})`);
+    assert_throws_js(TypeError, () => new WebAssembly.Module(argument),
+                     `new Module(${format_value(argument)})`);
   }
 }, "Invalid arguments");
 
 test(() => {
   const buffer = new Uint8Array();
-  assert_throws(new WebAssembly.CompileError(), () => new WebAssembly.Module(buffer));
+  assert_throws_js(WebAssembly.CompileError, () => new WebAssembly.Module(buffer));
 }, "Empty buffer");
 
 test(() => {
+  const buffer = new Uint8Array(Array.from(emptyModuleBinary).concat([0, 0]));
+  assert_throws_js(WebAssembly.CompileError, () => new WebAssembly.Module(buffer));
+}, "Invalid code");
+
+test(() => {
   const module = new WebAssembly.Module(emptyModuleBinary);
   assert_equals(Object.getPrototypeOf(module), WebAssembly.Module.prototype);
 }, "Prototype");
@@ -58,3 +62,8 @@ test(() => {
   const module = new WebAssembly.Module(emptyModuleBinary);
   assert_true(Object.isExtensible(module));
 }, "Extensibility");
+
+test(() => {
+  const module = new WebAssembly.Module(emptyModuleBinary, {});
+  assert_equals(Object.getPrototypeOf(module), WebAssembly.Module.prototype);
+}, "Stray argument");
index 4c8d91e..567ae1c 100644 (file)
@@ -6,5 +6,6 @@ PASS Empty module
 PASS Empty module: array caching 
 PASS Custom sections 
 PASS Custom sections with surrogate pairs 
-FAIL Custom sections with U+FFFD assert_equals: expected 1 but got 0
+PASS Custom sections with U+FFFD 
+PASS Stray argument 
 
index 58ac63b..8c215d1 100644 (file)
@@ -1,5 +1,4 @@
 // META: global=jsshell
-// META: script=/wasm/jsapi/wasm-constants.js
 // META: script=/wasm/jsapi/wasm-module-builder.js
 
 function assert_ArrayBuffer(buffer, expected) {
@@ -25,9 +24,9 @@ setup(() => {
 });
 
 test(() => {
-  assert_throws(new TypeError(), () => WebAssembly.Module.customSections());
+  assert_throws_js(TypeError, () => WebAssembly.Module.customSections());
   const module = new WebAssembly.Module(emptyModuleBinary);
-  assert_throws(new TypeError(), () => WebAssembly.Module.customSections(module));
+  assert_throws_js(TypeError, () => WebAssembly.Module.customSections(module));
 }, "Missing arguments");
 
 test(() => {
@@ -43,8 +42,8 @@ test(() => {
     WebAssembly.Module.prototype,
   ];
   for (const argument of invalidArguments) {
-    assert_throws(new TypeError(), () => WebAssembly.Module.customSections(argument, ""),
-                  `customSections(${format_value(argument)})`);
+    assert_throws_js(TypeError, () => WebAssembly.Module.customSections(argument, ""),
+                     `customSections(${format_value(argument)})`);
   }
 }, "Non-Module arguments");
 
@@ -82,22 +81,10 @@ test(() => {
   const bytes1 = [87, 101, 98, 65, 115, 115, 101, 109, 98, 108, 121];
   const bytes2 = [74, 83, 65, 80, 73];
 
-  const binary = new Binary;
-  binary.emit_section(kUnknownSectionCode, section => {
-    section.emit_string("name");
-    section.emit_bytes(bytes1);
-  });
-  binary.emit_section(kUnknownSectionCode, section => {
-    section.emit_string("name");
-    section.emit_bytes(bytes2);
-  });
-  binary.emit_section(kUnknownSectionCode, section => {
-    section.emit_string("foo");
-    section.emit_bytes(bytes1);
-  });
-
   const builder = new WasmModuleBuilder();
-  builder.addExplicitSection(binary);
+  builder.addCustomSection("name", bytes1);
+  builder.addCustomSection("name", bytes2);
+  builder.addCustomSection("foo", bytes1);
   const buffer = builder.toBuffer()
   const module = new WebAssembly.Module(buffer);
 
@@ -120,14 +107,8 @@ test(() => {
   const bytes = [87, 101, 98, 65, 115, 115, 101, 109, 98, 108, 121];
   const name = "yee\uD801\uDC37eey"
 
-  const binary = new Binary;
-  binary.emit_section(kUnknownSectionCode, section => {
-    section.emit_string(name);
-    section.emit_bytes(bytes);
-  });
-
   const builder = new WasmModuleBuilder();
-  builder.addExplicitSection(binary);
+  builder.addCustomSection(name, bytes);
   const buffer = builder.toBuffer();
   const module = new WebAssembly.Module(buffer);
 
@@ -141,14 +122,8 @@ test(() => {
 test(() => {
   const bytes = [87, 101, 98, 65, 115, 115, 101, 109, 98, 108, 121];
 
-  const binary = new Binary;
-  binary.emit_section(kUnknownSectionCode, section => {
-    section.emit_string("na\uFFFDme");
-    section.emit_bytes(bytes);
-  });
-
   const builder = new WasmModuleBuilder();
-  builder.addExplicitSection(binary);
+  builder.addCustomSection("na\uFFFDme", bytes);
   const buffer = builder.toBuffer();
   const module = new WebAssembly.Module(buffer);
 
@@ -156,7 +131,10 @@ test(() => {
   assert_sections(WebAssembly.Module.customSections(module, "na\uFFFDme"), [
     bytes,
   ]);
-  assert_sections(WebAssembly.Module.customSections(module, "na\uDC01me"), [
-    bytes,
-  ]);
+  assert_sections(WebAssembly.Module.customSections(module, "na\uDC01me"), []);
 }, "Custom sections with U+FFFD");
+
+test(() => {
+  const module = new WebAssembly.Module(emptyModuleBinary);
+  assert_sections(WebAssembly.Module.customSections(module, "", {}), []);
+}, "Stray argument");
index 4c8d91e..567ae1c 100644 (file)
@@ -6,5 +6,6 @@ PASS Empty module
 PASS Empty module: array caching 
 PASS Custom sections 
 PASS Custom sections with surrogate pairs 
-FAIL Custom sections with U+FFFD assert_equals: expected 1 but got 0
+PASS Custom sections with U+FFFD 
+PASS Stray argument 
 
index e63a885..1329c6a 100644 (file)
@@ -1,5 +1,4 @@
 // META: global=jsshell
-// META: script=/wasm/jsapi/wasm-constants.js
 // META: script=/wasm/jsapi/wasm-module-builder.js
 
 let emptyModuleBinary;
@@ -36,7 +35,7 @@ function assert_exports(exports, expected) {
 }
 
 test(() => {
-  assert_throws(new TypeError(), () => WebAssembly.Module.exports());
+  assert_throws_js(TypeError, () => WebAssembly.Module.exports());
 }, "Missing arguments");
 
 test(() => {
@@ -52,8 +51,8 @@ test(() => {
     WebAssembly.Module.prototype,
   ];
   for (const argument of invalidArguments) {
-    assert_throws(new TypeError(), () => WebAssembly.Module.exports(argument),
-                  `exports(${format_value(argument)})`);
+    assert_throws_js(TypeError, () => WebAssembly.Module.exports(argument),
+                     `exports(${format_value(argument)})`);
   }
 }, "Non-Module arguments");
 
@@ -92,18 +91,14 @@ test(() => {
 
   builder
     .addFunction("fn", kSig_v_v)
-    .addBody([
-        kExprEnd
-    ])
+    .addBody([])
     .exportFunc();
   builder
     .addFunction("fn2", kSig_v_v)
-    .addBody([
-        kExprEnd
-    ])
+    .addBody([])
     .exportFunc();
 
-  builder.setFunctionTableLength(1);
+  builder.setTableBounds(1);
   builder.addExportOfKind("table", kExternalTable, 0);
 
   builder.addGlobal(kWasmI32, true)
@@ -128,3 +123,9 @@ test(() => {
   ];
   assert_exports(exports, expected);
 }, "exports");
+
+test(() => {
+  const module = new WebAssembly.Module(emptyModuleBinary);
+  const exports = WebAssembly.Module.exports(module, {});
+  assert_exports(exports, []);
+}, "Stray argument");
index 640da59..9a7d611 100644 (file)
@@ -1,5 +1,4 @@
 // META: global=jsshell
-// META: script=/wasm/jsapi/wasm-constants.js
 // META: script=/wasm/jsapi/wasm-module-builder.js
 
 function assert_ModuleImportDescriptor(import_, expected) {
@@ -42,7 +41,7 @@ setup(() => {
 });
 
 test(() => {
-  assert_throws(new TypeError(), () => WebAssembly.Module.imports());
+  assert_throws_js(TypeError, () => WebAssembly.Module.imports());
 }, "Missing arguments");
 
 test(() => {
@@ -58,8 +57,8 @@ test(() => {
     WebAssembly.Module.prototype,
   ];
   for (const argument of invalidArguments) {
-    assert_throws(new TypeError(), () => WebAssembly.Module.imports(argument),
-                  `imports(${format_value(argument)})`);
+    assert_throws_js(TypeError, () => WebAssembly.Module.imports(argument),
+                     `imports(${format_value(argument)})`);
   }
 }, "Non-Module arguments");
 
@@ -118,3 +117,9 @@ test(() => {
   ];
   assert_imports(imports, expected);
 }, "imports");
+
+test(() => {
+  const module = new WebAssembly.Module(emptyModuleBinary);
+  const imports = WebAssembly.Module.imports(module, {});
+  assert_imports(imports, []);
+}, "Stray argument");
index b13e61e..e3f4e0a 100644 (file)
@@ -1,3 +1,4 @@
 
 PASS Object.prototype.toString on an Module 
+FAIL @@toStringTag exists on the prototype with the appropriate descriptor assert_own_property: expected property symbol "Symbol(Symbol.toStringTag)" missing
 
index d9231a1..7dd85a1 100644 (file)
@@ -1,5 +1,4 @@
 // META: global=jsshell
-// META: script=/wasm/jsapi/wasm-constants.js
 // META: script=/wasm/jsapi/wasm-module-builder.js
 
 test(() => {
@@ -7,3 +6,13 @@ test(() => {
   const module = new WebAssembly.Module(emptyModuleBinary);
   assert_class_string(module, "WebAssembly.Module");
 }, "Object.prototype.toString on an Module");
+
+test(() => {
+  assert_own_property(WebAssembly.Module.prototype, Symbol.toStringTag);
+
+  const propDesc = Object.getOwnPropertyDescriptor(WebAssembly.Module.prototype, Symbol.toStringTag);
+  assert_equals(propDesc.value, "WebAssembly.Module", "value");
+  assert_equals(propDesc.configurable, true, "configurable");
+  assert_equals(propDesc.enumerable, false, "enumerable");
+  assert_equals(propDesc.writable, false, "writable");
+}, "@@toStringTag exists on the prototype with the appropriate descriptor");
index b13e61e..e3f4e0a 100644 (file)
@@ -1,3 +1,4 @@
 
 PASS Object.prototype.toString on an Module 
+FAIL @@toStringTag exists on the prototype with the appropriate descriptor assert_own_property: expected property symbol "Symbol(Symbol.toStringTag)" missing
 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/proto-from-ctor-realm-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/proto-from-ctor-realm-expected.txt
new file mode 100644 (file)
index 0000000..4b25108
--- /dev/null
@@ -0,0 +1,122 @@
+
+FAIL WebAssembly.Module: cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: cross-realm NewTarget with `0` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: cross-realm NewTarget with `-1` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: cross-realm NewTarget with `""` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: cross-realm NewTarget with `"str"` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: cross-realm NewTarget with `symbol "Symbol()"` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: bound cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: bound bound cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: bound Proxy of cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: Proxy of cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: Proxy of Proxy of cross-realm NewTarget with `-0` prototype assert_true: expected true got false
+FAIL WebAssembly.Module: Proxy of bound cross-realm NewTarget with `NaN` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: cross-realm NewTarget with `0` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: cross-realm NewTarget with `-1` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: cross-realm NewTarget with `""` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: cross-realm NewTarget with `"str"` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: cross-realm NewTarget with `symbol "Symbol()"` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: bound cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: bound bound cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: bound Proxy of cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: Proxy of cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: Proxy of Proxy of cross-realm NewTarget with `-0` prototype assert_true: expected true got false
+FAIL WebAssembly.Instance: Proxy of bound cross-realm NewTarget with `NaN` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: cross-realm NewTarget with `0` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: cross-realm NewTarget with `-1` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: cross-realm NewTarget with `""` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: cross-realm NewTarget with `"str"` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: cross-realm NewTarget with `symbol "Symbol()"` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: bound cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: bound bound cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: bound Proxy of cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: Proxy of cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: Proxy of Proxy of cross-realm NewTarget with `-0` prototype assert_true: expected true got false
+FAIL WebAssembly.Memory: Proxy of bound cross-realm NewTarget with `NaN` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: cross-realm NewTarget with `0` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: cross-realm NewTarget with `-1` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: cross-realm NewTarget with `""` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: cross-realm NewTarget with `"str"` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: cross-realm NewTarget with `symbol "Symbol()"` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: bound cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: bound bound cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: bound Proxy of cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: Proxy of cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: Proxy of Proxy of cross-realm NewTarget with `-0` prototype assert_true: expected true got false
+FAIL WebAssembly.Table: Proxy of bound cross-realm NewTarget with `NaN` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: cross-realm NewTarget with `0` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: cross-realm NewTarget with `-1` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: cross-realm NewTarget with `""` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: cross-realm NewTarget with `"str"` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: cross-realm NewTarget with `symbol "Symbol()"` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: bound cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: bound bound cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: bound Proxy of cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: Proxy of cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: Proxy of Proxy of cross-realm NewTarget with `-0` prototype assert_true: expected true got false
+FAIL WebAssembly.Global: Proxy of bound cross-realm NewTarget with `NaN` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: cross-realm NewTarget with `0` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: cross-realm NewTarget with `-1` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: cross-realm NewTarget with `""` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: cross-realm NewTarget with `"str"` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: cross-realm NewTarget with `symbol "Symbol()"` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: bound cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: bound bound cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: bound Proxy of cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: Proxy of cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: Proxy of Proxy of cross-realm NewTarget with `-0` prototype assert_true: expected true got false
+FAIL WebAssembly.CompileError: Proxy of bound cross-realm NewTarget with `NaN` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: cross-realm NewTarget with `0` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: cross-realm NewTarget with `-1` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: cross-realm NewTarget with `""` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: cross-realm NewTarget with `"str"` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: cross-realm NewTarget with `symbol "Symbol()"` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: bound cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: bound bound cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: bound Proxy of cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: Proxy of cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: Proxy of Proxy of cross-realm NewTarget with `-0` prototype assert_true: expected true got false
+FAIL WebAssembly.LinkError: Proxy of bound cross-realm NewTarget with `NaN` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: cross-realm NewTarget with `0` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: cross-realm NewTarget with `-1` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: cross-realm NewTarget with `""` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: cross-realm NewTarget with `"str"` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: cross-realm NewTarget with `symbol "Symbol()"` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: bound cross-realm NewTarget with `undefined` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: bound bound cross-realm NewTarget with `null` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: bound Proxy of cross-realm NewTarget with `false` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: Proxy of cross-realm NewTarget with `true` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: Proxy of Proxy of cross-realm NewTarget with `-0` prototype assert_true: expected true got false
+FAIL WebAssembly.RuntimeError: Proxy of bound cross-realm NewTarget with `NaN` prototype assert_true: expected true got false
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/proto-from-ctor-realm.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/proto-from-ctor-realm.html
new file mode 100644 (file)
index 0000000..72931cc
--- /dev/null
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>WebAssembly JS API: Default [[Prototype]] value is from NewTarget's Realm</title>
+<link rel="help" href="https://heycam.github.io/webidl/#internally-create-a-new-object-implementing-the-interface">
+<link rel="help" href="https://tc39.es/ecma262/#sec-nativeerror">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="wasm-module-builder.js"></script>
+<body>
+<iframe id="constructor-iframe" hidden></iframe>
+<iframe id="new-target-iframe" hidden></iframe>
+<iframe id="other-iframe" hidden></iframe>
+<script>
+"use strict";
+
+const constructorRealm = document.querySelector("#constructor-iframe").contentWindow;
+const newTargetRealm = document.querySelector("#new-target-iframe").contentWindow;
+const otherRealm = document.querySelector("#other-iframe").contentWindow;
+
+const emptyModuleBinary = new WasmModuleBuilder().toBuffer();
+const interfaces = [
+  ["Module", emptyModuleBinary],
+  ["Instance", new WebAssembly.Module(emptyModuleBinary)],
+  ["Memory", {initial: 0}],
+  ["Table", {element: "anyfunc", initial: 0}],
+  ["Global", {value: "i32"}],
+
+  // See step 2 of https://tc39.es/ecma262/#sec-nativeerror
+  ["CompileError"],
+  ["LinkError"],
+  ["RuntimeError"],
+];
+
+const primitives = [
+  undefined,
+  null,
+  false,
+  true,
+  0,
+  -1,
+  "",
+  "str",
+  Symbol(),
+];
+
+const getNewTargets = function* (realm) {
+  for (const primitive of primitives) {
+    const newTarget = new realm.Function();
+    newTarget.prototype = primitive;
+    yield [newTarget, "cross-realm NewTarget with `" + format_value(primitive) + "` prototype"];
+  }
+
+  // GetFunctionRealm (https://tc39.es/ecma262/#sec-getfunctionrealm) coverage:
+  const bindOther = otherRealm.Function.prototype.bind;
+  const ProxyOther = otherRealm.Proxy;
+
+  const bound = new realm.Function();
+  bound.prototype = undefined;
+  yield [bindOther.call(bound), "bound cross-realm NewTarget with `undefined` prototype"];
+
+  const boundBound = new realm.Function();
+  boundBound.prototype = null;
+  yield [bindOther.call(bindOther.call(boundBound)), "bound bound cross-realm NewTarget with `null` prototype"];
+
+  const boundProxy = new realm.Function();
+  boundProxy.prototype = false;
+  yield [bindOther.call(new ProxyOther(boundProxy, {})), "bound Proxy of cross-realm NewTarget with `false` prototype"];
+
+  const proxy = new realm.Function();
+  proxy.prototype = true;
+  yield [new ProxyOther(proxy, {}), "Proxy of cross-realm NewTarget with `true` prototype"];
+
+  const proxyProxy = new realm.Function();
+  proxyProxy.prototype = -0;
+  yield [new ProxyOther(new ProxyOther(proxyProxy, {}), {}), "Proxy of Proxy of cross-realm NewTarget with `-0` prototype"];
+
+  const proxyBound = new realm.Function();
+  proxyBound.prototype = NaN;
+  yield [new ProxyOther(bindOther.call(proxyBound), {}), "Proxy of bound cross-realm NewTarget with `NaN` prototype"];
+};
+
+for (const [interfaceName, constructorArg] of interfaces) {
+  for (const [newTarget, testDescription] of getNewTargets(newTargetRealm)) {
+    test(() => {
+      const Constructor = constructorRealm.WebAssembly[interfaceName];
+      const object = Reflect.construct(Constructor, [constructorArg], newTarget);
+
+      const NewTargetConstructor = newTargetRealm.WebAssembly[interfaceName];
+      assert_true(object instanceof NewTargetConstructor);
+      assert_equals(Object.getPrototypeOf(object), NewTargetConstructor.prototype);
+    }, `WebAssembly.${interfaceName}: ${testDescription}`);
+  }
+}
+</script>
+</body>
index dde2fd7..b1aeaf1 100644 (file)
@@ -1,11 +1,13 @@
 function assert_equal_to_array(table, expected, message) {
   assert_equals(table.length, expected.length, `${message}: length`);
-  assert_throws(new RangeError(), () => table.get(-1), `${message}: table.get(-1)`);
+  // The argument check in get() happens before the range check, and negative numbers
+  // are illegal, hence will throw TypeError per spec.
+  assert_throws_js(TypeError, () => table.get(-1), `${message}: table.get(-1)`);
   for (let i = 0; i < expected.length; ++i) {
     assert_equals(table.get(i), expected[i], `${message}: table.get(${i} of ${expected.length})`);
   }
-  assert_throws(new RangeError(), () => table.get(expected.length),
-                `${message}: table.get(${expected.length} of ${expected.length})`);
-  assert_throws(new RangeError(), () => table.get(expected.length + 1),
-                `${message}: table.get(${expected.length + 1} of ${expected.length})`);
+  assert_throws_js(RangeError, () => table.get(expected.length),
+                   `${message}: table.get(${expected.length} of ${expected.length})`);
+  assert_throws_js(RangeError, () => table.get(expected.length + 1),
+                   `${message}: table.get(${expected.length + 1} of ${expected.length})`);
 }
index a312505..e685cf4 100644 (file)
@@ -22,6 +22,7 @@ PASS Out-of-range maximum value in descriptor: 68719476736
 PASS Initial value exceeds maximum 
 PASS Basic (zero) 
 PASS Basic (non-zero) 
+PASS Stray argument 
 PASS Proxy descriptor 
 PASS Type conversion for descriptor.element 
 PASS Order of evaluation for descriptor 
index e924bdb..5c9a6f1 100644 (file)
@@ -21,16 +21,16 @@ test(() => {
 }, "length");
 
 test(() => {
-  assert_throws(new TypeError(), () => new WebAssembly.Table());
+  assert_throws_js(TypeError, () => new WebAssembly.Table());
 }, "No arguments");
 
 test(() => {
   const argument = { "element": "anyfunc", "initial": 0 };
-  assert_throws(new TypeError(), () => WebAssembly.Table(argument));
+  assert_throws_js(TypeError, () => WebAssembly.Table(argument));
 }, "Calling");
 
 test(() => {
-  assert_throws(new TypeError(), () => new WebAssembly.Table({}));
+  assert_throws_js(TypeError, () => new WebAssembly.Table({}));
 }, "Empty descriptor");
 
 test(() => {
@@ -47,18 +47,18 @@ test(() => {
     {},
   ];
   for (const invalidArgument of invalidArguments) {
-    assert_throws(new TypeError(),
-                  () => new WebAssembly.Table(invalidArgument),
-                  `new Table(${format_value(invalidArgument)})`);
+    assert_throws_js(TypeError,
+                     () => new WebAssembly.Table(invalidArgument),
+                     `new Table(${format_value(invalidArgument)})`);
   }
 }, "Invalid descriptor argument");
 
 test(() => {
-  assert_throws(new TypeError(), () => new WebAssembly.Table({ "element": "anyfunc", "initial": undefined }));
+  assert_throws_js(TypeError, () => new WebAssembly.Table({ "element": "anyfunc", "initial": undefined }));
 }, "Undefined initial value in descriptor");
 
 test(() => {
-  assert_throws(new TypeError(), () => new WebAssembly.Table({ "element": undefined, "initial": 0 }));
+  assert_throws_js(TypeError, () => new WebAssembly.Table({ "element": undefined, "initial": 0 }));
 }, "Undefined element value in descriptor");
 
 const outOfRangeValues = [
@@ -72,16 +72,16 @@ const outOfRangeValues = [
 
 for (const value of outOfRangeValues) {
   test(() => {
-    assert_throws(new TypeError(), () => new WebAssembly.Table({ "element": "anyfunc", "initial": value }));
+    assert_throws_js(TypeError, () => new WebAssembly.Table({ "element": "anyfunc", "initial": value }));
   }, `Out-of-range initial value in descriptor: ${format_value(value)}`);
 
   test(() => {
-    assert_throws(new TypeError(), () => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value }));
+    assert_throws_js(TypeError, () => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value }));
   }, `Out-of-range maximum value in descriptor: ${format_value(value)}`);
 }
 
 test(() => {
-  assert_throws(new RangeError(), () => new WebAssembly.Table({ "element": "anyfunc", "initial": 10, "maximum": 9 }));
+  assert_throws_js(RangeError, () => new WebAssembly.Table({ "element": "anyfunc", "initial": 10, "maximum": 9 }));
 }, "Initial value exceeds maximum");
 
 test(() => {
@@ -97,6 +97,12 @@ test(() => {
 }, "Basic (non-zero)");
 
 test(() => {
+  const argument = { "element": "anyfunc", "initial": 0 };
+  const table = new WebAssembly.Table(argument, {});
+  assert_Table(table, { "length": 0 });
+}, "Stray argument");
+
+test(() => {
   const proxy = new Proxy({}, {
     has(o, x) {
       assert_unreached(`Should not call [[HasProperty]] with ${x}`);
index a312505..e685cf4 100644 (file)
@@ -22,6 +22,7 @@ PASS Out-of-range maximum value in descriptor: 68719476736
 PASS Initial value exceeds maximum 
 PASS Basic (zero) 
 PASS Basic (non-zero) 
+PASS Stray argument 
 PASS Proxy descriptor 
 PASS Type conversion for descriptor.element 
 PASS Order of evaluation for descriptor 
index dac3284..899f856 100644 (file)
@@ -3,12 +3,12 @@ PASS Missing arguments: get
 PASS Branding: get 
 PASS Missing arguments: set 
 PASS Branding: set 
-FAIL Basic assert_throws: undefined: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Growing assert_throws: undefined: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Setting out-of-bounds assert_throws: undefined: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Setting non-function assert_throws: undefined: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Setting non-wasm function assert_throws: undefined: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Setting non-wasm arrow function assert_throws: undefined: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
+PASS Basic 
+PASS Growing 
+PASS Setting out-of-bounds 
+PASS Setting non-function 
+PASS Setting non-wasm function 
+PASS Setting non-wasm arrow function 
 PASS Getting out-of-range argument: undefined 
 PASS Setting out-of-range argument: undefined 
 PASS Getting out-of-range argument: NaN 
@@ -28,4 +28,5 @@ PASS Setting out-of-range argument: "0x100000000"
 PASS Getting out-of-range argument: object "[object Object]" 
 PASS Setting out-of-range argument: object "[object Object]" 
 PASS Order of argument conversion 
+PASS Stray argument 
 
index 2bb43a9..4e0a5f8 100644 (file)
@@ -1,23 +1,18 @@
 // META: global=jsshell
-// META: script=/wasm/jsapi/wasm-constants.js
 // META: script=/wasm/jsapi/wasm-module-builder.js
 // META: script=assertions.js
 
-let functions;
+let functions = {};
 setup(() => {
   const builder = new WasmModuleBuilder();
 
   builder
     .addFunction("fn", kSig_v_d)
-    .addBody([
-        kExprEnd
-    ])
+    .addBody([])
     .exportFunc();
   builder
     .addFunction("fn2", kSig_v_v)
-    .addBody([
-        kExprEnd
-    ])
+    .addBody([])
     .exportFunc();
 
   const buffer = builder.toBuffer()
@@ -29,7 +24,7 @@ setup(() => {
 test(() => {
   const argument = { "element": "anyfunc", "initial": 5 };
   const table = new WebAssembly.Table(argument);
-  assert_throws(new TypeError(), () => table.get());
+  assert_throws_js(TypeError, () => table.get());
 }, "Missing arguments: get");
 
 test(t => {
@@ -53,15 +48,15 @@ test(t => {
   const fn = WebAssembly.Table.prototype.get;
 
   for (const thisValue of thisValues) {
-    assert_throws(new TypeError(), () => fn.call(thisValue, argument), `this=${format_value(thisValue)}`);
+    assert_throws_js(TypeError, () => fn.call(thisValue, argument), `this=${format_value(thisValue)}`);
   }
 }, "Branding: get");
 
 test(() => {
   const argument = { "element": "anyfunc", "initial": 5 };
   const table = new WebAssembly.Table(argument);
-  assert_throws(new TypeError(), () => table.set());
-  assert_throws(new TypeError(), () => table.set(0));
+  assert_throws_js(TypeError, () => table.set());
+  assert_throws_js(TypeError, () => table.set(0));
 }, "Missing arguments: set");
 
 test(t => {
@@ -85,7 +80,7 @@ test(t => {
   const fn = WebAssembly.Table.prototype.set;
 
   for (const thisValue of thisValues) {
-    assert_throws(new TypeError(), () => fn.call(thisValue, argument, null), `this=${format_value(thisValue)}`);
+    assert_throws_js(TypeError, () => fn.call(thisValue, argument, null), `this=${format_value(thisValue)}`);
   }
 }, "Branding: set");
 
@@ -131,8 +126,10 @@ test(() => {
 
   const {fn} = functions;
 
-  assert_throws(new RangeError(), () => table.set(-1, fn));
-  assert_throws(new RangeError(), () => table.set(5, fn));
+  // -1 is the wrong type hence the type check on entry gets this
+  // before the range check does.
+  assert_throws_js(TypeError, () => table.set(-1, fn));
+  assert_throws_js(RangeError, () => table.set(5, fn));
   assert_equal_to_array(table, [null, null, null, null, null]);
 }, "Setting out-of-bounds");
 
@@ -152,8 +149,8 @@ test(() => {
     {},
   ];
   for (const argument of invalidArguments) {
-    assert_throws(new TypeError(), () => table.set(0, argument),
-                  `set(${format_value(argument)})`);
+    assert_throws_js(TypeError, () => table.set(0, argument),
+                     `set(${format_value(argument)})`);
   }
   assert_equal_to_array(table, [null]);
 }, "Setting non-function");
@@ -164,7 +161,7 @@ test(() => {
   assert_equal_to_array(table, [null]);
 
   const fn = function() {};
-  assert_throws(new TypeError(), () => table.set(0, fn));
+  assert_throws_js(TypeError, () => table.set(0, fn));
   assert_equal_to_array(table, [null]);
 }, "Setting non-wasm function");
 
@@ -174,7 +171,7 @@ test(() => {
   assert_equal_to_array(table, [null]);
 
   const fn = () => {};
-  assert_throws(new TypeError(), () => table.set(0, fn));
+  assert_throws_js(TypeError, () => table.set(0, fn));
   assert_equal_to_array(table, [null]);
 }, "Setting non-wasm arrow function");
 
@@ -194,13 +191,13 @@ for (const value of outOfRangeValues) {
   test(() => {
     const argument = { "element": "anyfunc", "initial": 1 };
     const table = new WebAssembly.Table(argument);
-    assert_throws(new TypeError(), () => table.get(value));
+    assert_throws_js(TypeError, () => table.get(value));
   }, `Getting out-of-range argument: ${format_value(value)}`);
 
   test(() => {
     const argument = { "element": "anyfunc", "initial": 1 };
     const table = new WebAssembly.Table(argument);
-    assert_throws(new TypeError(), () => table.set(value, null));
+    assert_throws_js(TypeError, () => table.set(value, null));
   }, `Setting out-of-range argument: ${format_value(value)}`);
 }
 
@@ -214,7 +211,15 @@ test(() => {
       return 0;
     },
   };
-  assert_throws(new TypeError(), () => table.set(value, {}));
+  assert_throws_js(TypeError, () => table.set(value, {}));
   assert_equals(called, 1);
 }, "Order of argument conversion");
 
+test(() => {
+  const {fn} = functions;
+  const argument = { "element": "anyfunc", "initial": 1 };
+  const table = new WebAssembly.Table(argument);
+
+  assert_equals(table.get(0, {}), null);
+  assert_equals(table.set(0, fn, {}), undefined);
+}, "Stray argument");
index dac3284..899f856 100644 (file)
@@ -3,12 +3,12 @@ PASS Missing arguments: get
 PASS Branding: get 
 PASS Missing arguments: set 
 PASS Branding: set 
-FAIL Basic assert_throws: undefined: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Growing assert_throws: undefined: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Setting out-of-bounds assert_throws: undefined: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Setting non-function assert_throws: undefined: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Setting non-wasm function assert_throws: undefined: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Setting non-wasm arrow function assert_throws: undefined: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
+PASS Basic 
+PASS Growing 
+PASS Setting out-of-bounds 
+PASS Setting non-function 
+PASS Setting non-wasm function 
+PASS Setting non-wasm arrow function 
 PASS Getting out-of-range argument: undefined 
 PASS Setting out-of-range argument: undefined 
 PASS Getting out-of-range argument: NaN 
@@ -28,4 +28,5 @@ PASS Setting out-of-range argument: "0x100000000"
 PASS Getting out-of-range argument: object "[object Object]" 
 PASS Setting out-of-range argument: object "[object Object]" 
 PASS Order of argument conversion 
+PASS Stray argument 
 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any-expected.txt
new file mode 100644 (file)
index 0000000..d67fd93
--- /dev/null
@@ -0,0 +1,7 @@
+
+FAIL Grow with exported-function argument assert_equals: expected (function) function "function fn() {
+    [native code]
+}" but got (object) null
+FAIL Grow with non-function argument assert_throws_js: function "() => table.grow(2, {})" did not throw
+FAIL Grow with JS-function argument assert_throws_js: function "() => table.grow(2, () => true)" did not throw
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.js b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.js
new file mode 100644 (file)
index 0000000..edfb334
--- /dev/null
@@ -0,0 +1,42 @@
+// META: global=jsshell
+// META: script=assertions.js
+// META: script=/wasm/jsapi/wasm-constants.js
+// META: script=/wasm/jsapi/wasm-module-builder.js
+
+// Test cases for changes to the WebAssembly.Table.prototype.grow() API that
+// come in with the reftypes proposal: the API takes a default argument, which
+// for tables of anyfunc must be either an exported wasm function or null.
+//
+// See:
+//   https://github.com/WebAssembly/reference-types
+//   https://bugzilla.mozilla.org/show_bug.cgi?id=1507491
+//   https://github.com/WebAssembly/reference-types/issues/22
+
+test(() => {
+  const builder = new WasmModuleBuilder();
+  builder
+    .addFunction("fn", kSig_v_v)
+    .addBody([])
+    .exportFunc();
+  const bin = builder.toBuffer()
+  const argument = { "element": "anyfunc", "initial": 1 };
+  const table = new WebAssembly.Table(argument);
+  const fn = new WebAssembly.Instance(new WebAssembly.Module(bin)).exports.fn;
+  const result = table.grow(2, fn);
+  assert_equals(result, 1);
+  assert_equals(table.get(0), null);
+  assert_equals(table.get(1), fn);
+  assert_equals(table.get(2), fn);
+}, "Grow with exported-function argument");
+
+test(() => {
+  const argument = { "element": "anyfunc", "initial": 1 };
+  const table = new WebAssembly.Table(argument);
+  assert_throws_js(TypeError, () => table.grow(2, {}));
+}, "Grow with non-function argument");
+
+test(() => {
+  const argument = { "element": "anyfunc", "initial": 1 };
+  const table = new WebAssembly.Table(argument);
+  assert_throws_js(TypeError, () => table.grow(2, () => true));
+}, "Grow with JS-function argument");
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.worker-expected.txt
new file mode 100644 (file)
index 0000000..8666cea
--- /dev/null
@@ -0,0 +1,5 @@
+CONSOLE MESSAGE: NetworkError: Response is not 2xx
+
+Harness Error (FAIL), message = NetworkError: Response is not 2xx
+
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.worker.html b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.worker.html
new file mode 100644 (file)
index 0000000..2382913
--- /dev/null
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
index 60d21e0..27f2e55 100644 (file)
@@ -1,9 +1,9 @@
 
 PASS Missing arguments 
 PASS Branding 
-FAIL Basic assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Reached maximum assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Exceeded maximum assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
+PASS Basic 
+PASS Reached maximum 
+PASS Exceeded maximum 
 PASS Out-of-range argument: undefined 
 PASS Out-of-range argument: NaN 
 PASS Out-of-range argument: Infinity 
@@ -13,4 +13,5 @@ PASS Out-of-range argument: 4294967296
 PASS Out-of-range argument: 68719476736 
 PASS Out-of-range argument: "0x100000000" 
 PASS Out-of-range argument: object "[object Object]" 
+PASS Stray argument 
 
index d3efb51..f543cc6 100644 (file)
@@ -8,7 +8,7 @@ function nulls(n) {
 test(() => {
   const argument = { "element": "anyfunc", "initial": 5 };
   const table = new WebAssembly.Table(argument);
-  assert_throws(new TypeError(), () => table.grow());
+  assert_throws_js(TypeError, () => table.grow());
 }, "Missing arguments");
 
 test(t => {
@@ -32,7 +32,7 @@ test(t => {
   const fn = WebAssembly.Table.prototype.grow;
 
   for (const thisValue of thisValues) {
-    assert_throws(new TypeError(), () => fn.call(thisValue, argument), `this=${format_value(thisValue)}`);
+    assert_throws_js(TypeError, () => fn.call(thisValue, argument), `this=${format_value(thisValue)}`);
   }
 }, "Branding");
 
@@ -61,7 +61,7 @@ test(() => {
   const table = new WebAssembly.Table(argument);
   assert_equal_to_array(table, nulls(2), "before");
 
-  assert_throws(new RangeError(), () => table.grow(4));
+  assert_throws_js(RangeError, () => table.grow(4));
   assert_equal_to_array(table, nulls(2), "after");
 }, "Exceeded maximum");
 
@@ -81,6 +81,16 @@ for (const value of outOfRangeValues) {
   test(() => {
     const argument = { "element": "anyfunc", "initial": 1 };
     const table = new WebAssembly.Table(argument);
-    assert_throws(new TypeError(), () => table.grow(value));
+    assert_throws_js(TypeError, () => table.grow(value));
   }, `Out-of-range argument: ${format_value(value)}`);
 }
+
+test(() => {
+  const argument = { "element": "anyfunc", "initial": 5 };
+  const table = new WebAssembly.Table(argument);
+  assert_equal_to_array(table, nulls(5), "before");
+
+  const result = table.grow(3, null, {});
+  assert_equals(result, 5);
+  assert_equal_to_array(table, nulls(8), "after");
+}, "Stray argument");
index 60d21e0..27f2e55 100644 (file)
@@ -1,9 +1,9 @@
 
 PASS Missing arguments 
 PASS Branding 
-FAIL Basic assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Reached maximum assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
-FAIL Exceeded maximum assert_throws: before: table.get(-1) function "() => table.get(-1)" threw object "TypeError: Expect an integer argument in the range: [0, 2^32 - 1]" ("TypeError") expected object "RangeError" ("RangeError")
+PASS Basic 
+PASS Reached maximum 
+PASS Exceeded maximum 
 PASS Out-of-range argument: undefined 
 PASS Out-of-range argument: NaN 
 PASS Out-of-range argument: Infinity 
@@ -13,4 +13,5 @@ PASS Out-of-range argument: 4294967296
 PASS Out-of-range argument: 68719476736 
 PASS Out-of-range argument: "0x100000000" 
 PASS Out-of-range argument: object "[object Object]" 
+PASS Stray argument 
 
index a6a9661..f4e1148 100644 (file)
@@ -22,7 +22,7 @@ test(() => {
   assert_equals(typeof desc.set, "undefined");
 
   for (const thisValue of thisValues) {
-    assert_throws(new TypeError(), () => getter.call(thisValue), `this=${format_value(thisValue)}`);
+    assert_throws_js(TypeError, () => getter.call(thisValue), `this=${format_value(thisValue)}`);
   }
 }, "Branding");
 
@@ -30,6 +30,20 @@ test(() => {
   const argument = { "element": "anyfunc", "initial": 2 };
   const table = new WebAssembly.Table(argument);
   assert_equals(table.length, 2, "Initial length");
+
+  const desc = Object.getOwnPropertyDescriptor(WebAssembly.Table.prototype, "length");
+  assert_equals(typeof desc, "object");
+
+  const getter = desc.get;
+  assert_equals(typeof getter, "function");
+
+  assert_equals(getter.call(table, {}), 2);
+}, "Stray argument");
+
+test(() => {
+  const argument = { "element": "anyfunc", "initial": 2 };
+  const table = new WebAssembly.Table(argument);
+  assert_equals(table.length, 2, "Initial length");
   table.length = 4;
   assert_equals(table.length, 2, "Should not change the length");
 }, "Setting (sloppy mode)");
@@ -38,7 +52,7 @@ test(() => {
   const argument = { "element": "anyfunc", "initial": 2 };
   const table = new WebAssembly.Table(argument);
   assert_equals(table.length, 2, "Initial length");
-  assert_throws(new TypeError(), () => {
+  assert_throws_js(TypeError, () => {
     "use strict";
     table.length = 4;
   });
index 923d633..b047d31 100644 (file)
@@ -1,3 +1,4 @@
 
 PASS Object.prototype.toString on an Table 
+FAIL @@toStringTag exists on the prototype with the appropriate descriptor assert_own_property: expected property symbol "Symbol(Symbol.toStringTag)" missing
 
index e576477..708c17b 100644 (file)
@@ -5,3 +5,13 @@ test(() => {
   const table = new WebAssembly.Table(argument);
   assert_class_string(table, "WebAssembly.Table");
 }, "Object.prototype.toString on an Table");
+
+test(() => {
+  assert_own_property(WebAssembly.Table.prototype, Symbol.toStringTag);
+
+  const propDesc = Object.getOwnPropertyDescriptor(WebAssembly.Table.prototype, Symbol.toStringTag);
+  assert_equals(propDesc.value, "WebAssembly.Table", "value");
+  assert_equals(propDesc.configurable, true, "configurable");
+  assert_equals(propDesc.enumerable, false, "enumerable");
+  assert_equals(propDesc.writable, false, "writable");
+}, "@@toStringTag exists on the prototype with the appropriate descriptor");
index 923d633..b047d31 100644 (file)
@@ -1,3 +1,4 @@
 
 PASS Object.prototype.toString on an Table 
+FAIL @@toStringTag exists on the prototype with the appropriate descriptor assert_own_property: expected property symbol "Symbol(Symbol.toStringTag)" missing
 
index 6a9ecce..6720f7b 100644 (file)
@@ -17,6 +17,7 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/assertions.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/constructor.any.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/get-set.any.js
+/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow-reftypes.tentative.any.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/grow.any.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/length.any.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/table/toString.any.js
index c4c117f..3ab2cd7 100644 (file)
@@ -16,6 +16,9 @@ None
 List of files:
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/assertions.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/bad-imports.js
+/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/error-interfaces-no-symbol-tostringtag.js
+/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/idlharness.any.js
+/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/instanceTestFactory.js
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/interface.any.js
-/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/wasm-constants.js
+/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/proto-from-ctor-realm.html
 /LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/wasm-module-builder.js
diff --git a/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/wasm-constants.js b/LayoutTests/imported/w3c/web-platform-tests/wasm/jsapi/wasm-constants.js
deleted file mode 100644 (file)
index f056f9c..0000000
+++ /dev/null
@@ -1,374 +0,0 @@
-// Copyright 2015 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
-
-function bytes() {
-  var buffer = new ArrayBuffer(arguments.length);
-  var view = new Uint8Array(buffer);
-  for (var i = 0; i < arguments.length; i++) {
-    var val = arguments[i];
-    if ((typeof val) == "string") val = val.charCodeAt(0);
-    view[i] = val | 0;
-  }
-  return buffer;
-}
-
-// Header declaration constants
-var kWasmH0 = 0;
-var kWasmH1 = 0x61;
-var kWasmH2 = 0x73;
-var kWasmH3 = 0x6d;
-
-var kWasmV0 = 1;
-var kWasmV1 = 0;
-var kWasmV2 = 0;
-var kWasmV3 = 0;
-
-var kHeaderSize = 8;
-var kPageSize = 65536;
-
-function bytesWithHeader() {
-  var buffer = new ArrayBuffer(kHeaderSize + arguments.length);
-  var view = new Uint8Array(buffer);
-  view[0] = kWasmH0;
-  view[1] = kWasmH1;
-  view[2] = kWasmH2;
-  view[3] = kWasmH3;
-  view[4] = kWasmV0;
-  view[5] = kWasmV1;
-  view[6] = kWasmV2;
-  view[7] = kWasmV3;
-  for (var i = 0; i < arguments.length; i++) {
-    var val = arguments[i];
-    if ((typeof val) == "string") val = val.charCodeAt(0);
-    view[kHeaderSize + i] = val | 0;
-  }
-  return buffer;
-}
-
-let kDeclNoLocals = 0;
-
-// Section declaration constants
-let kUnknownSectionCode = 0;
-let kTypeSectionCode = 1;      // Function signature declarations
-let kImportSectionCode = 2;    // Import declarations
-let kFunctionSectionCode = 3;  // Function declarations
-let kTableSectionCode = 4;     // Indirect function table and other tables
-let kMemorySectionCode = 5;    // Memory attributes
-let kGlobalSectionCode = 6;    // Global declarations
-let kExportSectionCode = 7;    // Exports
-let kStartSectionCode = 8;     // Start function declaration
-let kElementSectionCode = 9;  // Elements section
-let kCodeSectionCode = 10;      // Function code
-let kDataSectionCode = 11;     // Data segments
-let kNameSectionCode = 12;     // Name section (encoded as string)
-
-let kWasmFunctionTypeForm = 0x60;
-let kWasmAnyFunctionTypeForm = 0x70;
-
-let kResizableMaximumFlag = 1;
-
-// Function declaration flags
-let kDeclFunctionName   = 0x01;
-let kDeclFunctionImport = 0x02;
-let kDeclFunctionLocals = 0x04;
-let kDeclFunctionExport = 0x08;
-
-// Local types
-let kWasmStmt = 0x40;
-let kWasmI32 = 0x7f;
-let kWasmI64 = 0x7e;
-let kWasmF32 = 0x7d;
-let kWasmF64 = 0x7c;
-let kWasmS128 = 0x7b;
-
-let kExternalFunction = 0;
-let kExternalTable = 1;
-let kExternalMemory = 2;
-let kExternalGlobal = 3;
-
-let kTableZero = 0;
-let kMemoryZero = 0;
-
-// Useful signatures
-let kSig_i_i = makeSig([kWasmI32], [kWasmI32]);
-let kSig_l_l = makeSig([kWasmI64], [kWasmI64]);
-let kSig_i_l = makeSig([kWasmI64], [kWasmI32]);
-let kSig_i_ii = makeSig([kWasmI32, kWasmI32], [kWasmI32]);
-let kSig_i_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], [kWasmI32]);
-let kSig_d_dd = makeSig([kWasmF64, kWasmF64], [kWasmF64]);
-let kSig_l_ll = makeSig([kWasmI64, kWasmI64], [kWasmI64]);
-let kSig_i_dd = makeSig([kWasmF64, kWasmF64], [kWasmI32]);
-let kSig_v_v = makeSig([], []);
-let kSig_i_v = makeSig([], [kWasmI32]);
-let kSig_l_v = makeSig([], [kWasmI64]);
-let kSig_f_v = makeSig([], [kWasmF64]);
-let kSig_d_v = makeSig([], [kWasmF64]);
-let kSig_v_i = makeSig([kWasmI32], []);
-let kSig_v_ii = makeSig([kWasmI32, kWasmI32], []);
-let kSig_v_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], []);
-let kSig_v_l = makeSig([kWasmI64], []);
-let kSig_v_d = makeSig([kWasmF64], []);
-let kSig_v_dd = makeSig([kWasmF64, kWasmF64], []);
-let kSig_v_ddi = makeSig([kWasmF64, kWasmF64, kWasmI32], []);
-let kSig_s_v = makeSig([], [kWasmS128]);
-
-function makeSig(params, results) {
-  return {params: params, results: results};
-}
-
-function makeSig_v_x(x) {
-  return makeSig([x], []);
-}
-
-function makeSig_v_xx(x) {
-  return makeSig([x, x], []);
-}
-
-function makeSig_r_v(r) {
-  return makeSig([], [r]);
-}
-
-function makeSig_r_x(r, x) {
-  return makeSig([x], [r]);
-}
-
-function makeSig_r_xx(r, x) {
-  return makeSig([x, x], [r]);
-}
-
-// Opcodes
-let kExprUnreachable = 0x00;
-let kExprNop = 0x01;
-let kExprBlock = 0x02;
-let kExprLoop = 0x03;
-let kExprIf = 0x04;
-let kExprElse = 0x05;
-let kExprTry = 0x06;
-let kExprCatch = 0x07;
-let kExprThrow = 0x08;
-let kExprEnd = 0x0b;
-let kExprBr = 0x0c;
-let kExprBrIf = 0x0d;
-let kExprBrTable = 0x0e;
-let kExprReturn = 0x0f;
-let kExprCallFunction = 0x10;
-let kExprCallIndirect = 0x11;
-let kExprDrop = 0x1a;
-let kExprSelect = 0x1b;
-let kExprGetLocal = 0x20;
-let kExprSetLocal = 0x21;
-let kExprTeeLocal = 0x22;
-let kExprGetGlobal = 0x23;
-let kExprSetGlobal = 0x24;
-let kExprI32Const = 0x41;
-let kExprI64Const = 0x42;
-let kExprF32Const = 0x43;
-let kExprF64Const = 0x44;
-let kExprI32LoadMem = 0x28;
-let kExprI64LoadMem = 0x29;
-let kExprF32LoadMem = 0x2a;
-let kExprF64LoadMem = 0x2b;
-let kExprI32LoadMem8S = 0x2c;
-let kExprI32LoadMem8U = 0x2d;
-let kExprI32LoadMem16S = 0x2e;
-let kExprI32LoadMem16U = 0x2f;
-let kExprI64LoadMem8S = 0x30;
-let kExprI64LoadMem8U = 0x31;
-let kExprI64LoadMem16S = 0x32;
-let kExprI64LoadMem16U = 0x33;
-let kExprI64LoadMem32S = 0x34;
-let kExprI64LoadMem32U = 0x35;
-let kExprI32StoreMem = 0x36;
-let kExprI64StoreMem = 0x37;
-let kExprF32StoreMem = 0x38;
-let kExprF64StoreMem = 0x39;
-let kExprI32StoreMem8 = 0x3a;
-let kExprI32StoreMem16 = 0x3b;
-let kExprI64StoreMem8 = 0x3c;
-let kExprI64StoreMem16 = 0x3d;
-let kExprI64StoreMem32 = 0x3e;
-let kExprMemorySize = 0x3f;
-let kExprGrowMemory = 0x40;
-let kExprI32Eqz = 0x45;
-let kExprI32Eq = 0x46;
-let kExprI32Ne = 0x47;
-let kExprI32LtS = 0x48;
-let kExprI32LtU = 0x49;
-let kExprI32GtS = 0x4a;
-let kExprI32GtU = 0x4b;
-let kExprI32LeS = 0x4c;
-let kExprI32LeU = 0x4d;
-let kExprI32GeS = 0x4e;
-let kExprI32GeU = 0x4f;
-let kExprI64Eqz = 0x50;
-let kExprI64Eq = 0x51;
-let kExprI64Ne = 0x52;
-let kExprI64LtS = 0x53;
-let kExprI64LtU = 0x54;
-let kExprI64GtS = 0x55;
-let kExprI64GtU = 0x56;
-let kExprI64LeS = 0x57;
-let kExprI64LeU = 0x58;
-let kExprI64GeS = 0x59;
-let kExprI64GeU = 0x5a;
-let kExprF32Eq = 0x5b;
-let kExprF32Ne = 0x5c;
-let kExprF32Lt = 0x5d;
-let kExprF32Gt = 0x5e;
-let kExprF32Le = 0x5f;
-let kExprF32Ge = 0x60;
-let kExprF64Eq = 0x61;
-let kExprF64Ne = 0x62;
-let kExprF64Lt = 0x63;
-let kExprF64Gt = 0x64;
-let kExprF64Le = 0x65;
-let kExprF64Ge = 0x66;
-let kExprI32Clz = 0x67;
-let kExprI32Ctz = 0x68;
-let kExprI32Popcnt = 0x69;
-let kExprI32Add = 0x6a;
-let kExprI32Sub = 0x6b;
-let kExprI32Mul = 0x6c;
-let kExprI32DivS = 0x6d;
-let kExprI32DivU = 0x6e;
-let kExprI32RemS = 0x6f;
-let kExprI32RemU = 0x70;
-let kExprI32And = 0x71;
-let kExprI32Ior = 0x72;
-let kExprI32Xor = 0x73;
-let kExprI32Shl = 0x74;
-let kExprI32ShrS = 0x75;
-let kExprI32ShrU = 0x76;
-let kExprI32Rol = 0x77;
-let kExprI32Ror = 0x78;
-let kExprI64Clz = 0x79;
-let kExprI64Ctz = 0x7a;
-let kExprI64Popcnt = 0x7b;
-let kExprI64Add = 0x7c;
-let kExprI64Sub = 0x7d;
-let kExprI64Mul = 0x7e;
-let kExprI64DivS = 0x7f;
-let kExprI64DivU = 0x80;
-let kExprI64RemS = 0x81;
-let kExprI64RemU = 0x82;
-let kExprI64And = 0x83;
-let kExprI64Ior = 0x84;
-let kExprI64Xor = 0x85;
-let kExprI64Shl = 0x86;
-let kExprI64ShrS = 0x87;
-let kExprI64ShrU = 0x88;
-let kExprI64Rol = 0x89;
-let kExprI64Ror = 0x8a;
-let kExprF32Abs = 0x8b;
-let kExprF32Neg = 0x8c;
-let kExprF32Ceil = 0x8d;
-let kExprF32Floor = 0x8e;
-let kExprF32Trunc = 0x8f;
-let kExprF32NearestInt = 0x90;
-let kExprF32Sqrt = 0x91;
-let kExprF32Add = 0x92;
-let kExprF32Sub = 0x93;
-let kExprF32Mul = 0x94;
-let kExprF32Div = 0x95;
-let kExprF32Min = 0x96;
-let kExprF32Max = 0x97;
-let kExprF32CopySign = 0x98;
-let kExprF64Abs = 0x99;
-let kExprF64Neg = 0x9a;
-let kExprF64Ceil = 0x9b;
-let kExprF64Floor = 0x9c;
-let kExprF64Trunc = 0x9d;
-let kExprF64NearestInt = 0x9e;
-let kExprF64Sqrt = 0x9f;
-let kExprF64Add = 0xa0;
-let kExprF64Sub = 0xa1;
-let kExprF64Mul = 0xa2;
-let kExprF64Div = 0xa3;
-let kExprF64Min = 0xa4;
-let kExprF64Max = 0xa5;
-let kExprF64CopySign = 0xa6;
-let kExprI32ConvertI64 = 0xa7;
-let kExprI32SConvertF32 = 0xa8;
-let kExprI32UConvertF32 = 0xa9;
-let kExprI32SConvertF64 = 0xaa;
-let kExprI32UConvertF64 = 0xab;
-let kExprI64SConvertI32 = 0xac;
-let kExprI64UConvertI32 = 0xad;
-let kExprI64SConvertF32 = 0xae;
-let kExprI64UConvertF32 = 0xaf;
-let kExprI64SConvertF64 = 0xb0;
-let kExprI64UConvertF64 = 0xb1;
-let kExprF32SConvertI32 = 0xb2;
-let kExprF32UConvertI32 = 0xb3;
-let kExprF32SConvertI64 = 0xb4;
-let kExprF32UConvertI64 = 0xb5;
-let kExprF32ConvertF64 = 0xb6;
-let kExprF64SConvertI32 = 0xb7;
-let kExprF64UConvertI32 = 0xb8;
-let kExprF64SConvertI64 = 0xb9;
-let kExprF64UConvertI64 = 0xba;
-let kExprF64ConvertF32 = 0xbb;
-let kExprI32ReinterpretF32 = 0xbc;
-let kExprI64ReinterpretF64 = 0xbd;
-let kExprF32ReinterpretI32 = 0xbe;
-let kExprF64ReinterpretI64 = 0xbf;
-
-let kTrapUnreachable          = 0;
-let kTrapMemOutOfBounds       = 1;
-let kTrapDivByZero            = 2;
-let kTrapDivUnrepresentable   = 3;
-let kTrapRemByZero            = 4;
-let kTrapFloatUnrepresentable = 5;
-let kTrapFuncInvalid          = 6;
-let kTrapFuncSigMismatch      = 7;
-let kTrapInvalidIndex         = 8;
-
-let kTrapMsgs = [
-  "unreachable",
-  "memory access out of bounds",
-  "divide by zero",
-  "divide result unrepresentable",
-  "remainder by zero",
-  "integer result unrepresentable",
-  "invalid function",
-  "function signature mismatch",
-  "invalid index into function table"
-];
-
-function assertTraps(trap, code) {
-    var threwException = true;
-    try {
-      if (typeof code === 'function') {
-        code();
-      } else {
-        eval(code);
-      }
-      threwException = false;
-    } catch (e) {
-      assertEquals("object", typeof e);
-      assertEquals(kTrapMsgs[trap], e.message);
-      // Success.
-      return;
-    }
-    throw new MjsUnitAssertionError("Did not trap, expected: " + kTrapMsgs[trap]);
-}
-
-function assertWasmThrows(value, code) {
-    assertEquals("number", typeof(value));
-    try {
-      if (typeof code === 'function') {
-        code();
-      } else {
-        eval(code);
-      }
-    } catch (e) {
-      assertEquals("number", typeof e);
-      assertEquals(value, e);
-      // Success.
-      return;
-    }
-    throw new MjsUnitAssertionError("Did not throw at all, expected: " + value);
-}
index 6e9284e..82c6e04 100644 (file)
 // found in the LICENSE file.
 
 // Used for encoding f32 and double constants to bits.
-let __buffer = new ArrayBuffer(8);
-let byte_view = new Int8Array(__buffer);
-let f32_view = new Float32Array(__buffer);
-let f64_view = new Float64Array(__buffer);
+let f32_view = new Float32Array(1);
+let f32_bytes_view = new Uint8Array(f32_view.buffer);
+let f64_view = new Float64Array(1);
+let f64_bytes_view = new Uint8Array(f64_view.buffer);
+
+// The bytes function receives one of
+//  - several arguments, each of which is either a number or a string of length
+//    1; if it's a string, the charcode of the contained character is used.
+//  - a single array argument containing the actual arguments
+//  - a single string; the returned buffer will contain the char codes of all
+//    contained characters.
+function bytes(...input) {
+  if (input.length == 1 && typeof input[0] == 'array') input = input[0];
+  if (input.length == 1 && typeof input[0] == 'string') {
+    let len = input[0].length;
+    let view = new Uint8Array(len);
+    for (let i = 0; i < len; i++) view[i] = input[0].charCodeAt(i);
+    return view.buffer;
+  }
+  let view = new Uint8Array(input.length);
+  for (let i = 0; i < input.length; i++) {
+    let val = input[i];
+    if (typeof val == 'string') {
+      assertEquals(1, val.length, 'string inputs must have length 1');
+      val = val.charCodeAt(0);
+    }
+    view[i] = val | 0;
+  }
+  return view.buffer;
+}
+
+// Header declaration constants
+var kWasmH0 = 0;
+var kWasmH1 = 0x61;
+var kWasmH2 = 0x73;
+var kWasmH3 = 0x6d;
+
+var kWasmV0 = 0x1;
+var kWasmV1 = 0;
+var kWasmV2 = 0;
+var kWasmV3 = 0;
+
+var kHeaderSize = 8;
+var kPageSize = 65536;
+var kSpecMaxPages = 65535;
+var kMaxVarInt32Size = 5;
+var kMaxVarInt64Size = 10;
+
+let kDeclNoLocals = 0;
+
+// Section declaration constants
+let kUnknownSectionCode = 0;
+let kTypeSectionCode = 1;        // Function signature declarations
+let kImportSectionCode = 2;      // Import declarations
+let kFunctionSectionCode = 3;    // Function declarations
+let kTableSectionCode = 4;       // Indirect function table and other tables
+let kMemorySectionCode = 5;      // Memory attributes
+let kGlobalSectionCode = 6;      // Global declarations
+let kExportSectionCode = 7;      // Exports
+let kStartSectionCode = 8;       // Start function declaration
+let kElementSectionCode = 9;     // Elements section
+let kCodeSectionCode = 10;       // Function code
+let kDataSectionCode = 11;       // Data segments
+let kDataCountSectionCode = 12;  // Data segment count (between Element & Code)
+let kExceptionSectionCode = 13;  // Exception section (between Global & Export)
+
+// Name section types
+let kModuleNameCode = 0;
+let kFunctionNamesCode = 1;
+let kLocalNamesCode = 2;
+
+let kWasmFunctionTypeForm = 0x60;
+let kWasmAnyFunctionTypeForm = 0x70;
+
+let kHasMaximumFlag = 1;
+let kSharedHasMaximumFlag = 3;
+
+// Segment flags
+let kActiveNoIndex = 0;
+let kPassive = 1;
+let kActiveWithIndex = 2;
+let kPassiveWithElements = 5;
+
+// Function declaration flags
+let kDeclFunctionName   = 0x01;
+let kDeclFunctionImport = 0x02;
+let kDeclFunctionLocals = 0x04;
+let kDeclFunctionExport = 0x08;
+
+// Local types
+let kWasmStmt = 0x40;
+let kWasmI32 = 0x7f;
+let kWasmI64 = 0x7e;
+let kWasmF32 = 0x7d;
+let kWasmF64 = 0x7c;
+let kWasmS128 = 0x7b;
+let kWasmAnyRef = 0x6f;
+let kWasmAnyFunc = 0x70;
+let kWasmExnRef = 0x68;
+
+let kExternalFunction = 0;
+let kExternalTable = 1;
+let kExternalMemory = 2;
+let kExternalGlobal = 3;
+let kExternalException = 4;
+
+let kTableZero = 0;
+let kMemoryZero = 0;
+let kSegmentZero = 0;
+
+let kExceptionAttribute = 0;
+
+// Useful signatures
+let kSig_i_i = makeSig([kWasmI32], [kWasmI32]);
+let kSig_l_l = makeSig([kWasmI64], [kWasmI64]);
+let kSig_i_l = makeSig([kWasmI64], [kWasmI32]);
+let kSig_i_ii = makeSig([kWasmI32, kWasmI32], [kWasmI32]);
+let kSig_i_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], [kWasmI32]);
+let kSig_v_iiii = makeSig([kWasmI32, kWasmI32, kWasmI32, kWasmI32], []);
+let kSig_f_ff = makeSig([kWasmF32, kWasmF32], [kWasmF32]);
+let kSig_d_dd = makeSig([kWasmF64, kWasmF64], [kWasmF64]);
+let kSig_l_ll = makeSig([kWasmI64, kWasmI64], [kWasmI64]);
+let kSig_i_dd = makeSig([kWasmF64, kWasmF64], [kWasmI32]);
+let kSig_v_v = makeSig([], []);
+let kSig_i_v = makeSig([], [kWasmI32]);
+let kSig_l_v = makeSig([], [kWasmI64]);
+let kSig_f_v = makeSig([], [kWasmF32]);
+let kSig_d_v = makeSig([], [kWasmF64]);
+let kSig_v_i = makeSig([kWasmI32], []);
+let kSig_v_ii = makeSig([kWasmI32, kWasmI32], []);
+let kSig_v_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], []);
+let kSig_v_l = makeSig([kWasmI64], []);
+let kSig_v_d = makeSig([kWasmF64], []);
+let kSig_v_dd = makeSig([kWasmF64, kWasmF64], []);
+let kSig_v_ddi = makeSig([kWasmF64, kWasmF64, kWasmI32], []);
+let kSig_ii_v = makeSig([], [kWasmI32, kWasmI32]);
+let kSig_iii_v = makeSig([], [kWasmI32, kWasmI32, kWasmI32]);
+let kSig_ii_i = makeSig([kWasmI32], [kWasmI32, kWasmI32]);
+let kSig_iii_i = makeSig([kWasmI32], [kWasmI32, kWasmI32, kWasmI32]);
+let kSig_ii_ii = makeSig([kWasmI32, kWasmI32], [kWasmI32, kWasmI32]);
+let kSig_iii_ii = makeSig([kWasmI32, kWasmI32], [kWasmI32, kWasmI32, kWasmI32]);
+
+let kSig_v_f = makeSig([kWasmF32], []);
+let kSig_f_f = makeSig([kWasmF32], [kWasmF32]);
+let kSig_f_d = makeSig([kWasmF64], [kWasmF32]);
+let kSig_d_d = makeSig([kWasmF64], [kWasmF64]);
+let kSig_r_r = makeSig([kWasmAnyRef], [kWasmAnyRef]);
+let kSig_a_a = makeSig([kWasmAnyFunc], [kWasmAnyFunc]);
+let kSig_e_e = makeSig([kWasmExnRef], [kWasmExnRef]);
+let kSig_i_r = makeSig([kWasmAnyRef], [kWasmI32]);
+let kSig_v_r = makeSig([kWasmAnyRef], []);
+let kSig_v_a = makeSig([kWasmAnyFunc], []);
+let kSig_v_e = makeSig([kWasmExnRef], []);
+let kSig_v_rr = makeSig([kWasmAnyRef, kWasmAnyRef], []);
+let kSig_v_aa = makeSig([kWasmAnyFunc, kWasmAnyFunc], []);
+let kSig_r_v = makeSig([], [kWasmAnyRef]);
+let kSig_a_v = makeSig([], [kWasmAnyFunc]);
+let kSig_a_i = makeSig([kWasmI32], [kWasmAnyFunc]);
+let kSig_e_v = makeSig([], [kWasmExnRef]);
+
+function makeSig(params, results) {
+  return {params: params, results: results};
+}
+
+function makeSig_v_x(x) {
+  return makeSig([x], []);
+}
+
+function makeSig_v_xx(x) {
+  return makeSig([x, x], []);
+}
+
+function makeSig_r_v(r) {
+  return makeSig([], [r]);
+}
+
+function makeSig_r_x(r, x) {
+  return makeSig([x], [r]);
+}
+
+function makeSig_r_xx(r, x) {
+  return makeSig([x, x], [r]);
+}
+
+// Opcodes
+let kExprUnreachable = 0x00;
+let kExprNop = 0x01;
+let kExprBlock = 0x02;
+let kExprLoop = 0x03;
+let kExprIf = 0x04;
+let kExprElse = 0x05;
+let kExprTry = 0x06;
+let kExprCatch = 0x07;
+let kExprThrow = 0x08;
+let kExprRethrow = 0x09;
+let kExprBrOnExn = 0x0a;
+let kExprEnd = 0x0b;
+let kExprBr = 0x0c;
+let kExprBrIf = 0x0d;
+let kExprBrTable = 0x0e;
+let kExprReturn = 0x0f;
+let kExprCallFunction = 0x10;
+let kExprCallIndirect = 0x11;
+let kExprReturnCall = 0x12;
+let kExprReturnCallIndirect = 0x13;
+let kExprDrop = 0x1a;
+let kExprSelect = 0x1b;
+let kExprLocalGet = 0x20;
+let kExprLocalSet = 0x21;
+let kExprLocalTee = 0x22;
+let kExprGlobalGet = 0x23;
+let kExprGlobalSet = 0x24;
+let kExprTableGet = 0x25;
+let kExprTableSet = 0x26;
+let kExprI32LoadMem = 0x28;
+let kExprI64LoadMem = 0x29;
+let kExprF32LoadMem = 0x2a;
+let kExprF64LoadMem = 0x2b;
+let kExprI32LoadMem8S = 0x2c;
+let kExprI32LoadMem8U = 0x2d;
+let kExprI32LoadMem16S = 0x2e;
+let kExprI32LoadMem16U = 0x2f;
+let kExprI64LoadMem8S = 0x30;
+let kExprI64LoadMem8U = 0x31;
+let kExprI64LoadMem16S = 0x32;
+let kExprI64LoadMem16U = 0x33;
+let kExprI64LoadMem32S = 0x34;
+let kExprI64LoadMem32U = 0x35;
+let kExprI32StoreMem = 0x36;
+let kExprI64StoreMem = 0x37;
+let kExprF32StoreMem = 0x38;
+let kExprF64StoreMem = 0x39;
+let kExprI32StoreMem8 = 0x3a;
+let kExprI32StoreMem16 = 0x3b;
+let kExprI64StoreMem8 = 0x3c;
+let kExprI64StoreMem16 = 0x3d;
+let kExprI64StoreMem32 = 0x3e;
+let kExprMemorySize = 0x3f;
+let kExprMemoryGrow = 0x40;
+let kExprI32Const = 0x41;
+let kExprI64Const = 0x42;
+let kExprF32Const = 0x43;
+let kExprF64Const = 0x44;
+let kExprI32Eqz = 0x45;
+let kExprI32Eq = 0x46;
+let kExprI32Ne = 0x47;
+let kExprI32LtS = 0x48;
+let kExprI32LtU = 0x49;
+let kExprI32GtS = 0x4a;
+let kExprI32GtU = 0x4b;
+let kExprI32LeS = 0x4c;
+let kExprI32LeU = 0x4d;
+let kExprI32GeS = 0x4e;
+let kExprI32GeU = 0x4f;
+let kExprI64Eqz = 0x50;
+let kExprI64Eq = 0x51;
+let kExprI64Ne = 0x52;
+let kExprI64LtS = 0x53;
+let kExprI64LtU = 0x54;
+let kExprI64GtS = 0x55;
+let kExprI64GtU = 0x56;
+let kExprI64LeS = 0x57;
+let kExprI64LeU = 0x58;
+let kExprI64GeS = 0x59;
+let kExprI64GeU = 0x5a;
+let kExprF32Eq = 0x5b;
+let kExprF32Ne = 0x5c;
+let kExprF32Lt = 0x5d;
+let kExprF32Gt = 0x5e;
+let kExprF32Le = 0x5f;
+let kExprF32Ge = 0x60;
+let kExprF64Eq = 0x61;
+let kExprF64Ne = 0x62;
+let kExprF64Lt = 0x63;
+let kExprF64Gt = 0x64;
+let kExprF64Le = 0x65;
+let kExprF64Ge = 0x66;
+let kExprI32Clz = 0x67;
+let kExprI32Ctz = 0x68;
+let kExprI32Popcnt = 0x69;
+let kExprI32Add = 0x6a;
+let kExprI32Sub = 0x6b;
+let kExprI32Mul = 0x6c;
+let kExprI32DivS = 0x6d;
+let kExprI32DivU = 0x6e;
+let kExprI32RemS = 0x6f;
+let kExprI32RemU = 0x70;
+let kExprI32And = 0x71;
+let kExprI32Ior = 0x72;
+let kExprI32Xor = 0x73;
+let kExprI32Shl = 0x74;
+let kExprI32ShrS = 0x75;
+let kExprI32ShrU = 0x76;
+let kExprI32Rol = 0x77;
+let kExprI32Ror = 0x78;
+let kExprI64Clz = 0x79;
+let kExprI64Ctz = 0x7a;
+let kExprI64Popcnt = 0x7b;
+let kExprI64Add = 0x7c;
+let kExprI64Sub = 0x7d;
+let kExprI64Mul = 0x7e;
+let kExprI64DivS = 0x7f;
+let kExprI64DivU = 0x80;
+let kExprI64RemS = 0x81;
+let kExprI64RemU = 0x82;
+let kExprI64And = 0x83;
+let kExprI64Ior = 0x84;
+let kExprI64Xor = 0x85;
+let kExprI64Shl = 0x86;
+let kExprI64ShrS = 0x87;
+let kExprI64ShrU = 0x88;
+let kExprI64Rol = 0x89;
+let kExprI64Ror = 0x8a;
+let kExprF32Abs = 0x8b;
+let kExprF32Neg = 0x8c;
+let kExprF32Ceil = 0x8d;
+let kExprF32Floor = 0x8e;
+let kExprF32Trunc = 0x8f;
+let kExprF32NearestInt = 0x90;
+let kExprF32Sqrt = 0x91;
+let kExprF32Add = 0x92;
+let kExprF32Sub = 0x93;
+let kExprF32Mul = 0x94;
+let kExprF32Div = 0x95;
+let kExprF32Min = 0x96;
+let kExprF32Max = 0x97;
+let kExprF32CopySign = 0x98;
+let kExprF64Abs = 0x99;
+let kExprF64Neg = 0x9a;
+let kExprF64Ceil = 0x9b;
+let kExprF64Floor = 0x9c;
+let kExprF64Trunc = 0x9d;
+let kExprF64NearestInt = 0x9e;
+let kExprF64Sqrt = 0x9f;
+let kExprF64Add = 0xa0;
+let kExprF64Sub = 0xa1;
+let kExprF64Mul = 0xa2;
+let kExprF64Div = 0xa3;
+let kExprF64Min = 0xa4;
+let kExprF64Max = 0xa5;
+let kExprF64CopySign = 0xa6;
+let kExprI32ConvertI64 = 0xa7;
+let kExprI32SConvertF32 = 0xa8;
+let kExprI32UConvertF32 = 0xa9;
+let kExprI32SConvertF64 = 0xaa;
+let kExprI32UConvertF64 = 0xab;
+let kExprI64SConvertI32 = 0xac;
+let kExprI64UConvertI32 = 0xad;
+let kExprI64SConvertF32 = 0xae;
+let kExprI64UConvertF32 = 0xaf;
+let kExprI64SConvertF64 = 0xb0;
+let kExprI64UConvertF64 = 0xb1;
+let kExprF32SConvertI32 = 0xb2;
+let kExprF32UConvertI32 = 0xb3;
+let kExprF32SConvertI64 = 0xb4;
+let kExprF32UConvertI64 = 0xb5;
+let kExprF32ConvertF64 = 0xb6;
+let kExprF64SConvertI32 = 0xb7;
+let kExprF64UConvertI32 = 0xb8;
+let kExprF64SConvertI64 = 0xb9;
+let kExprF64UConvertI64 = 0xba;
+let kExprF64ConvertF32 = 0xbb;
+let kExprI32ReinterpretF32 = 0xbc;
+let kExprI64ReinterpretF64 = 0xbd;
+let kExprF32ReinterpretI32 = 0xbe;
+let kExprF64ReinterpretI64 = 0xbf;
+let kExprI32SExtendI8 = 0xc0;
+let kExprI32SExtendI16 = 0xc1;
+let kExprI64SExtendI8 = 0xc2;
+let kExprI64SExtendI16 = 0xc3;
+let kExprI64SExtendI32 = 0xc4;
+let kExprRefNull = 0xd0;
+let kExprRefIsNull = 0xd1;
+let kExprRefFunc = 0xd2;
+
+// Prefix opcodes
+let kNumericPrefix = 0xfc;
+let kSimdPrefix = 0xfd;
+let kAtomicPrefix = 0xfe;
+
+// Numeric opcodes.
+let kExprMemoryInit = 0x08;
+let kExprDataDrop = 0x09;
+let kExprMemoryCopy = 0x0a;
+let kExprMemoryFill = 0x0b;
+let kExprTableInit = 0x0c;
+let kExprElemDrop = 0x0d;
+let kExprTableCopy = 0x0e;
+let kExprTableGrow = 0x0f;
+let kExprTableSize = 0x10;
+let kExprTableFill = 0x11;
+
+// Atomic opcodes.
+let kExprAtomicNotify = 0x00;
+let kExprI32AtomicWait = 0x01;
+let kExprI64AtomicWait = 0x02;
+let kExprI32AtomicLoad = 0x10;
+let kExprI32AtomicLoad8U = 0x12;
+let kExprI32AtomicLoad16U = 0x13;
+let kExprI32AtomicStore = 0x17;
+let kExprI32AtomicStore8U = 0x19;
+let kExprI32AtomicStore16U = 0x1a;
+let kExprI32AtomicAdd = 0x1e;
+let kExprI32AtomicAdd8U = 0x20;
+let kExprI32AtomicAdd16U = 0x21;
+let kExprI32AtomicSub = 0x25;
+let kExprI32AtomicSub8U = 0x27;
+let kExprI32AtomicSub16U = 0x28;
+let kExprI32AtomicAnd = 0x2c;
+let kExprI32AtomicAnd8U = 0x2e;
+let kExprI32AtomicAnd16U = 0x2f;
+let kExprI32AtomicOr = 0x33;
+let kExprI32AtomicOr8U = 0x35;
+let kExprI32AtomicOr16U = 0x36;
+let kExprI32AtomicXor = 0x3a;
+let kExprI32AtomicXor8U = 0x3c;
+let kExprI32AtomicXor16U = 0x3d;
+let kExprI32AtomicExchange = 0x41;
+let kExprI32AtomicExchange8U = 0x43;
+let kExprI32AtomicExchange16U = 0x44;
+let kExprI32AtomicCompareExchange = 0x48;
+let kExprI32AtomicCompareExchange8U = 0x4a;
+let kExprI32AtomicCompareExchange16U = 0x4b;
+
+let kExprI64AtomicLoad = 0x11;
+let kExprI64AtomicLoad8U = 0x14;
+let kExprI64AtomicLoad16U = 0x15;
+let kExprI64AtomicLoad32U = 0x16;
+let kExprI64AtomicStore = 0x18;
+let kExprI64AtomicStore8U = 0x1b;
+let kExprI64AtomicStore16U = 0x1c;
+let kExprI64AtomicStore32U = 0x1d;
+let kExprI64AtomicAdd = 0x1f;
+let kExprI64AtomicAdd8U = 0x22;
+let kExprI64AtomicAdd16U = 0x23;
+let kExprI64AtomicAdd32U = 0x24;
+let kExprI64AtomicSub = 0x26;
+let kExprI64AtomicSub8U = 0x29;
+let kExprI64AtomicSub16U = 0x2a;
+let kExprI64AtomicSub32U = 0x2b;
+let kExprI64AtomicAnd = 0x2d;
+let kExprI64AtomicAnd8U = 0x30;
+let kExprI64AtomicAnd16U = 0x31;
+let kExprI64AtomicAnd32U = 0x32;
+let kExprI64AtomicOr = 0x34;
+let kExprI64AtomicOr8U = 0x37;
+let kExprI64AtomicOr16U = 0x38;
+let kExprI64AtomicOr32U = 0x39;
+let kExprI64AtomicXor = 0x3b;
+let kExprI64AtomicXor8U = 0x3e;
+let kExprI64AtomicXor16U = 0x3f;
+let kExprI64AtomicXor32U = 0x40;
+let kExprI64AtomicExchange = 0x42;
+let kExprI64AtomicExchange8U = 0x45;
+let kExprI64AtomicExchange16U = 0x46;
+let kExprI64AtomicExchange32U = 0x47;
+let kExprI64AtomicCompareExchange = 0x49
+let kExprI64AtomicCompareExchange8U = 0x4c;
+let kExprI64AtomicCompareExchange16U = 0x4d;
+let kExprI64AtomicCompareExchange32U = 0x4e;
+
+// Simd opcodes.
+let kExprS128LoadMem = 0x00;
+let kExprS128StoreMem = 0x01;
+let kExprI32x4Splat = 0x0c;
+let kExprI32x4Eq = 0x2c;
+let kExprS1x4AllTrue = 0x75;
+let kExprF32x4Min = 0x9e;
+
+class Binary {
+  constructor() {
+    this.length = 0;
+    this.buffer = new Uint8Array(8192);
+  }
+
+  ensure_space(needed) {
+    if (this.buffer.length - this.length >= needed) return;
+    let new_capacity = this.buffer.length * 2;
+    while (new_capacity - this.length < needed) new_capacity *= 2;
+    let new_buffer = new Uint8Array(new_capacity);
+    new_buffer.set(this.buffer);
+    this.buffer = new_buffer;
+  }
+
+  trunc_buffer() {
+    return new Uint8Array(this.buffer.buffer, 0, this.length);
+  }
+
+  reset() {
+    this.length = 0;
+  }
 
-class Binary extends Array {
   emit_u8(val) {
-    this.push(val);
+    this.ensure_space(1);
+    this.buffer[this.length++] = val;
   }
 
   emit_u16(val) {
-    this.push(val & 0xff);
-    this.push((val >> 8) & 0xff);
+    this.ensure_space(2);
+    this.buffer[this.length++] = val;
+    this.buffer[this.length++] = val >> 8;
   }
 
   emit_u32(val) {
-    this.push(val & 0xff);
-    this.push((val >> 8) & 0xff);
-    this.push((val >> 16) & 0xff);
-    this.push((val >> 24) & 0xff);
+    this.ensure_space(4);
+    this.buffer[this.length++] = val;
+    this.buffer[this.length++] = val >> 8;
+    this.buffer[this.length++] = val >> 16;
+    this.buffer[this.length++] = val >> 24;
   }
 
-  emit_u32v(val) {
-    while (true) {
+  emit_leb_u(val, max_len) {
+    this.ensure_space(max_len);
+    for (let i = 0; i < max_len; ++i) {
       let v = val & 0xff;
       val = val >>> 7;
       if (val == 0) {
-        this.push(v);
-        break;
+        this.buffer[this.length++] = v;
+        return;
       }
-      this.push(v | 0x80);
+      this.buffer[this.length++] = v | 0x80;
     }
+    throw new Error("Leb value exceeds maximum length of " + max_len);
+  }
+
+  emit_u32v(val) {
+    this.emit_leb_u(val, kMaxVarInt32Size);
+  }
+
+  emit_u64v(val) {
+    this.emit_leb_u(val, kMaxVarInt64Size);
   }
 
   emit_bytes(data) {
-    for (let i = 0; i < data.length; i++) {
-      this.push(data[i] & 0xff);
-    }
+    this.ensure_space(data.length);
+    this.buffer.set(data, this.length);
+    this.length += data.length;
   }
 
   emit_string(string) {
@@ -61,20 +560,22 @@ class Binary extends Array {
   }
 
   emit_header() {
-    this.push(kWasmH0, kWasmH1, kWasmH2, kWasmH3,
-              kWasmV0, kWasmV1, kWasmV2, kWasmV3);
+    this.emit_bytes([
+      kWasmH0, kWasmH1, kWasmH2, kWasmH3, kWasmV0, kWasmV1, kWasmV2, kWasmV3
+    ]);
   }
 
   emit_section(section_code, content_generator) {
     // Emit section name.
     this.emit_u8(section_code);
     // Emit the section to a temporary buffer: its full length isn't know yet.
-    let section = new Binary;
+    const section = new Binary;
     content_generator(section);
     // Emit section length.
     this.emit_u32v(section.length);
     // Copy the temporary buffer.
-    this.push(...section);
+    // Avoid spread because {section} can be huge.
+    this.emit_bytes(section.trunc_buffer());
   }
 }
 
@@ -84,6 +585,16 @@ class WasmFunctionBuilder {
     this.name = name;
     this.type_index = type_index;
     this.body = [];
+    this.locals = [];
+    this.local_names = [];
+  }
+
+  numLocalNames() {
+    let num_local_names = 0;
+    for (let loc_name of this.local_names) {
+      if (loc_name !== undefined) ++num_local_names;
+    }
+    return num_local_names;
   }
 
   exportAs(name) {
@@ -97,12 +608,38 @@ class WasmFunctionBuilder {
   }
 
   addBody(body) {
+    for (let b of body) {
+      if (typeof b !== 'number' || (b & (~0xFF)) !== 0 )
+        throw new Error('invalid body (entries must be 8 bit numbers): ' + body);
+    }
+    this.body = body.slice();
+    // Automatically add the end for the function block to the body.
+    this.body.push(kExprEnd);
+    return this;
+  }
+
+  addBodyWithEnd(body) {
     this.body = body;
     return this;
   }
 
-  addLocals(locals) {
-    this.locals = locals;
+  getNumLocals() {
+    let total_locals = 0;
+    for (let l of this.locals) {
+      for (let type of ["i32", "i64", "f32", "f64", "s128"]) {
+        total_locals += l[type + "_count"] || 0;
+      }
+    }
+    return total_locals;
+  }
+
+  addLocals(locals, names) {
+    const old_num_locals = this.getNumLocals();
+    this.locals.push(locals);
+    if (names) {
+      const missing_names = old_num_locals - this.local_names.length;
+      this.local_names.push(...new Array(missing_names), ...names);
+    }
     return this;
   }
 
@@ -126,20 +663,38 @@ class WasmGlobalBuilder {
   }
 }
 
+class WasmTableBuilder {
+  constructor(module, type, initial_size, max_size) {
+    this.module = module;
+    this.type = type;
+    this.initial_size = initial_size;
+    this.has_max = max_size != undefined;
+    this.max_size = max_size;
+  }
+
+  exportAs(name) {
+    this.module.exports.push({name: name, kind: kExternalTable,
+                              index: this.index});
+    return this;
+  }
+}
+
 class WasmModuleBuilder {
   constructor() {
     this.types = [];
     this.imports = [];
     this.exports = [];
     this.globals = [];
+    this.tables = [];
+    this.exceptions = [];
     this.functions = [];
-    this.function_table = [];
-    this.function_table_length = 0;
-    this.function_table_inits = [];
-    this.segments = [];
+    this.element_segments = [];
+    this.data_segments = [];
     this.explicit = [];
     this.num_imported_funcs = 0;
     this.num_imported_globals = 0;
+    this.num_imported_tables = 0;
+    this.num_imported_exceptions = 0;
     return this;
   }
 
@@ -148,8 +703,8 @@ class WasmModuleBuilder {
     return this;
   }
 
-  addMemory(min, max, exp) {
-    this.memory = {min: min, max: max, exp: exp};
+  addMemory(min, max, exp, shared) {
+    this.memory = {min: min, max: max, exp: exp, shared: shared};
     return this;
   }
 
@@ -158,9 +713,30 @@ class WasmModuleBuilder {
     return this;
   }
 
+  stringToBytes(name) {
+    var result = new Binary();
+    result.emit_string(name);
+    return result.trunc_buffer()
+  }
+
+  createCustomSection(name, bytes) {
+    name = this.stringToBytes(name);
+    var section = new Binary();
+    section.emit_u8(kUnknownSectionCode);
+    section.emit_u32v(name.length + bytes.length);
+    section.emit_bytes(name);
+    section.emit_bytes(bytes);
+    return section.trunc_buffer();
+  }
+
+  addCustomSection(name, bytes) {
+    this.explicit.push(this.createCustomSection(name, bytes));
+  }
+
   addType(type) {
-    // TODO: canonicalize types?
     this.types.push(type);
+    var pl = type.params.length;  // should have params
+    var rl = type.results.length; // should have results
     return this.types.length - 1;
   }
 
@@ -171,6 +747,24 @@ class WasmModuleBuilder {
     return glob;
   }
 
+  addTable(type, initial_size, max_size = undefined) {
+    if (type != kWasmAnyRef && type != kWasmAnyFunc && type != kWasmExnRef) {
+      throw new Error(
+          'Tables must be of type kWasmAnyRef, kWasmAnyFunc, or kWasmExnRef');
+    }
+    let table = new WasmTableBuilder(this, type, initial_size, max_size);
+    table.index = this.tables.length + this.num_imported_tables;
+    this.tables.push(table);
+    return table;
+  }
+
+  addException(type) {
+    let type_index = (typeof type) == "number" ? type : this.addType(type);
+    let except_index = this.exceptions.length + this.num_imported_exceptions;
+    this.exceptions.push(type_index);
+    return except_index;
+  }
+
   addFunction(name, type) {
     let type_index = (typeof type) == "number" ? type : this.addType(type);
     let func = new WasmFunctionBuilder(this, name, type_index);
@@ -179,31 +773,51 @@ class WasmModuleBuilder {
     return func;
   }
 
-  addImport(module = "", name, type) {
+  addImport(module, name, type) {
+    if (this.functions.length != 0) {
+      throw new Error('Imported functions must be declared before local ones');
+    }
     let type_index = (typeof type) == "number" ? type : this.addType(type);
     this.imports.push({module: module, name: name, kind: kExternalFunction,
                        type: type_index});
     return this.num_imported_funcs++;
   }
 
-  addImportedGlobal(module = "", name, type) {
+  addImportedGlobal(module, name, type, mutable = false) {
+    if (this.globals.length != 0) {
+      throw new Error('Imported globals must be declared before local ones');
+    }
     let o = {module: module, name: name, kind: kExternalGlobal, type: type,
-             mutable: false}
+             mutable: mutable};
     this.imports.push(o);
     return this.num_imported_globals++;
   }
 
-  addImportedMemory(module = "", name, initial = 0, maximum) {
+  addImportedMemory(module, name, initial = 0, maximum, shared) {
     let o = {module: module, name: name, kind: kExternalMemory,
-             initial: initial, maximum: maximum};
+             initial: initial, maximum: maximum, shared: shared};
     this.imports.push(o);
     return this;
   }
 
-  addImportedTable(module = "", name, initial, maximum) {
+  addImportedTable(module, name, initial, maximum, type) {
+    if (this.tables.length != 0) {
+      throw new Error('Imported tables must be declared before local ones');
+    }
     let o = {module: module, name: name, kind: kExternalTable, initial: initial,
-             maximum: maximum};
+             maximum: maximum, type: type || kWasmAnyFunctionTypeForm};
     this.imports.push(o);
+    return this.num_imported_tables++;
+  }
+
+  addImportedException(module, name, type) {
+    if (this.exceptions.length != 0) {
+      throw new Error('Imported exceptions must be declared before local ones');
+    }
+    let type_index = (typeof type) == "number" ? type : this.addType(type);
+    let o = {module: module, name: name, kind: kExternalException, type: type_index};
+    this.imports.push(o);
+    return this.num_imported_exceptions++;
   }
 
   addExport(name, index) {
@@ -217,36 +831,64 @@ class WasmModuleBuilder {
   }
 
   addDataSegment(addr, data, is_global = false) {
-    this.segments.push({addr: addr, data: data, is_global: is_global});
-    return this.segments.length - 1;
+    this.data_segments.push(
+        {addr: addr, data: data, is_global: is_global, is_active: true});
+    return this.data_segments.length - 1;
+  }
+
+  addPassiveDataSegment(data) {
+    this.data_segments.push({data: data, is_active: false});
+    return this.data_segments.length - 1;
   }
 
   exportMemoryAs(name) {
     this.exports.push({name: name, kind: kExternalMemory, index: 0});
   }
 
-  addFunctionTableInit(base, is_global, array) {
-    this.function_table_inits.push({base: base, is_global: is_global,
-                                    array: array});
-    if (!is_global) {
-      var length = base + array.length;
-      if (length > this.function_table_length) {
-        this.function_table_length = length;
-      }
-    }
+  addElementSegment(table, base, is_global, array) {
+    this.element_segments.push({table: table, base: base, is_global: is_global,
+                                    array: array, is_active: true});
+    return this;
+  }
+
+  addPassiveElementSegment(array, is_import = false) {
+    this.element_segments.push({array: array, is_active: false});
     return this;
   }
 
   appendToTable(array) {
-    return this.addFunctionTableInit(this.function_table.length, false, array);
+    for (let n of array) {
+      if (typeof n != 'number')
+        throw new Error('invalid table (entries have to be numbers): ' + array);
+    }
+    if (this.tables.length == 0) {
+      this.addTable(kWasmAnyFunc, 0);
+    }
+    // Adjust the table to the correct size.
+    let table = this.tables[0];
+    const base = table.initial_size;
+    const table_size = base + array.length;
+    table.initial_size = table_size;
+    if (table.has_max && table_size > table.max_size) {
+      table.max_size = table_size;
+    }
+    return this.addElementSegment(0, base, false, array);
+  }
+
+  setTableBounds(min, max = undefined) {
+    if (this.tables.length != 0) {
+      throw new Error("The table bounds of table '0' have already been set.");
+    }
+    this.addTable(kWasmAnyFunc, min, max);
+    return this;
   }
 
-  setFunctionTableLength(length) {
-    this.function_table_length = length;
+  setName(name) {
+    this.name = name;
     return this;
   }
 
-  toArray(debug = false) {
+  toBuffer(debug = false) {
     let binary = new Binary;
     let wasm = this;
 
@@ -288,15 +930,23 @@ class WasmModuleBuilder {
             section.emit_u8(imp.mutable);
           } else if (imp.kind == kExternalMemory) {
             var has_max = (typeof imp.maximum) != "undefined";
-            section.emit_u8(has_max ? 1 : 0); // flags
+            var is_shared = (typeof imp.shared) != "undefined";
+            if (is_shared) {
+              section.emit_u8(has_max ? 3 : 2); // flags
+            } else {
+              section.emit_u8(has_max ? 1 : 0); // flags
+            }
             section.emit_u32v(imp.initial); // initial
             if (has_max) section.emit_u32v(imp.maximum); // maximum
           } else if (imp.kind == kExternalTable) {
-            section.emit_u8(kWasmAnyFunctionTypeForm);
+            section.emit_u8(imp.type);
             var has_max = (typeof imp.maximum) != "undefined";
             section.emit_u8(has_max ? 1 : 0); // flags
             section.emit_u32v(imp.initial); // initial
             if (has_max) section.emit_u32v(imp.maximum); // maximum
+          } else if (imp.kind == kExternalException) {
+            section.emit_u32v(kExceptionAttribute);
+            section.emit_u32v(imp.type);
           } else {
             throw new Error("unknown/unsupported import kind " + imp.kind);
           }
@@ -305,40 +955,45 @@ class WasmModuleBuilder {
     }
 
     // Add functions declarations
-    let has_names = false;
-    let names = false;
     if (wasm.functions.length > 0) {
       if (debug) print("emitting function decls @ " + binary.length);
       binary.emit_section(kFunctionSectionCode, section => {
         section.emit_u32v(wasm.functions.length);
         for (let func of wasm.functions) {
-          has_names = has_names || (func.name != undefined &&
-                                   func.name.length > 0);
           section.emit_u32v(func.type_index);
         }
       });
     }
 
-    // Add function_table.
-    if (wasm.function_table_length > 0) {
-      if (debug) print("emitting table @ " + binary.length);
+    // Add table section
+    if (wasm.tables.length > 0) {
+      if (debug) print ("emitting tables @ " + binary.length);
       binary.emit_section(kTableSectionCode, section => {
-        section.emit_u8(1);  // one table entry
-        section.emit_u8(kWasmAnyFunctionTypeForm);
-        section.emit_u8(1);
-        section.emit_u32v(wasm.function_table_length);
-        section.emit_u32v(wasm.function_table_length);
+        section.emit_u32v(wasm.tables.length);
+        for (let table of wasm.tables) {
+          section.emit_u8(table.type);
+          section.emit_u8(table.has_max);
+          section.emit_u32v(table.initial_size);
+          if (table.has_max) section.emit_u32v(table.max_size);
+        }
       });
     }
 
     // Add memory section
-    if (wasm.memory != undefined) {
+    if (wasm.memory !== undefined) {
       if (debug) print("emitting memory @ " + binary.length);
       binary.emit_section(kMemorySectionCode, section => {
         section.emit_u8(1);  // one memory entry
-        section.emit_u32v(kResizableMaximumFlag);
+        const has_max = wasm.memory.max !== undefined;
+        const is_shared = wasm.memory.shared !== undefined;
+        // Emit flags (bit 0: reszeable max, bit 1: shared memory)
+        if (is_shared) {
+          section.emit_u8(has_max ? kSharedHasMaximumFlag : 2);
+        } else {
+          section.emit_u8(has_max ? kHasMaximumFlag : 0);
+        }
         section.emit_u32v(wasm.memory.min);
-        section.emit_u32v(wasm.memory.max);
+        if (has_max) section.emit_u32v(wasm.memory.max);
       });
     }
 
@@ -359,32 +1014,34 @@ class WasmModuleBuilder {
               break;
             case kWasmI64:
               section.emit_u8(kExprI64Const);
-              section.emit_u8(global.init);
+              section.emit_u64v(global.init);
               break;
             case kWasmF32:
               section.emit_u8(kExprF32Const);
               f32_view[0] = global.init;
-              section.emit_u8(byte_view[0]);
-              section.emit_u8(byte_view[1]);
-              section.emit_u8(byte_view[2]);
-              section.emit_u8(byte_view[3]);
+              section.emit_bytes(f32_bytes_view);
               break;
             case kWasmF64:
               section.emit_u8(kExprF64Const);
               f64_view[0] = global.init;
-              section.emit_u8(byte_view[0]);
-              section.emit_u8(byte_view[1]);
-              section.emit_u8(byte_view[2]);
-              section.emit_u8(byte_view[3]);
-              section.emit_u8(byte_view[4]);
-              section.emit_u8(byte_view[5]);
-              section.emit_u8(byte_view[6]);
-              section.emit_u8(byte_view[7]);
+              section.emit_bytes(f64_bytes_view);
+              break;
+            case kWasmAnyFunc:
+            case kWasmAnyRef:
+              if (global.function_index !== undefined) {
+                section.emit_u8(kExprRefFunc);
+                section.emit_u32v(global.function_index);
+              } else {
+                section.emit_u8(kExprRefNull);
+              }
+              break;
+            case kWasmExnRef:
+              section.emit_u8(kExprRefNull);
               break;
             }
           } else {
             // Emit a global-index initializer.
-            section.emit_u8(kExprGetGlobal);
+            section.emit_u8(kExprGlobalGet);
             section.emit_u32v(global.init_index);
           }
           section.emit_u8(kExprEnd);  // end of init expression
@@ -392,8 +1049,20 @@ class WasmModuleBuilder {
       });
     }
 
+    // Add exceptions.
+    if (wasm.exceptions.length > 0) {
+      if (debug) print("emitting exceptions @ " + binary.length);
+      binary.emit_section(kExceptionSectionCode, section => {
+        section.emit_u32v(wasm.exceptions.length);
+        for (let type of wasm.exceptions) {
+          section.emit_u32v(kExceptionAttribute);
+          section.emit_u32v(type);
+        }
+      });
+    }
+
     // Add export table.
-    var mem_export = (wasm.memory != undefined && wasm.memory.exp);
+    var mem_export = (wasm.memory !== undefined && wasm.memory.exp);
     var exports_count = wasm.exports.length + (mem_export ? 1 : 0);
     if (exports_count > 0) {
       if (debug) print("emitting exports @ " + binary.length);
@@ -413,49 +1082,82 @@ class WasmModuleBuilder {
     }
 
     // Add start function section.
-    if (wasm.start_index != undefined) {
+    if (wasm.start_index !== undefined) {
       if (debug) print("emitting start function @ " + binary.length);
       binary.emit_section(kStartSectionCode, section => {
         section.emit_u32v(wasm.start_index);
       });
     }
 
-    // Add table elements.
-    if (wasm.function_table_inits.length > 0) {
-      if (debug) print("emitting table @ " + binary.length);
+    // Add element segments
+    if (wasm.element_segments.length > 0) {
+      if (debug) print("emitting element segments @ " + binary.length);
       binary.emit_section(kElementSectionCode, section => {
-        var inits = wasm.function_table_inits;
+        var inits = wasm.element_segments;
         section.emit_u32v(inits.length);
-        section.emit_u8(0); // table index
 
         for (let init of inits) {
-          if (init.is_global) {
-            section.emit_u8(kExprGetGlobal);
+          if (init.is_active) {
+            // Active segment.
+            if (init.table == 0) {
+              section.emit_u32v(kActiveNoIndex);
+            } else {
+              section.emit_u32v(kActiveWithIndex);
+              section.emit_u32v(init.table);
+            }
+            if (init.is_global) {
+              section.emit_u8(kExprGlobalGet);
+            } else {
+              section.emit_u8(kExprI32Const);
+            }
+            section.emit_u32v(init.base);
+            section.emit_u8(kExprEnd);
+            if (init.table != 0) {
+              section.emit_u8(kExternalFunction);
+            }
+            section.emit_u32v(init.array.length);
+            for (let index of init.array) {
+              section.emit_u32v(index);
+            }
           } else {
-            section.emit_u8(kExprI32Const);
-          }
-          section.emit_u32v(init.base);
-          section.emit_u8(kExprEnd);
-          section.emit_u32v(init.array.length);
-          for (let index of init.array) {
-            section.emit_u32v(index);
+            // Passive segment.
+            section.emit_u8(kPassiveWithElements);  // flags
+            section.emit_u8(kWasmAnyFunc);
+            section.emit_u32v(init.array.length);
+            for (let index of init.array) {
+              if (index === null) {
+                section.emit_u8(kExprRefNull);
+                section.emit_u8(kExprEnd);
+              } else {
+                section.emit_u8(kExprRefFunc);
+                section.emit_u32v(index);
+                section.emit_u8(kExprEnd);
+              }
+            }
           }
         }
       });
     }
 
+    // If there are any passive data segments, add the DataCount section.
+    if (wasm.data_segments.some(seg => !seg.is_active)) {
+      binary.emit_section(kDataCountSectionCode, section => {
+        section.emit_u32v(wasm.data_segments.length);
+      });
+    }
+
     // Add function bodies.
     if (wasm.functions.length > 0) {
       // emit function bodies
       if (debug) print("emitting code @ " + binary.length);
       binary.emit_section(kCodeSectionCode, section => {
         section.emit_u32v(wasm.functions.length);
+        let header = new Binary;
         for (let func of wasm.functions) {
+          header.reset();
           // Function body length will be patched later.
           let local_decls = [];
-          let l = func.locals;
-          if (l != undefined) {
-            let local_decls_count = 0;
+          for (let l of func.locals || []) {
             if (l.i32_count > 0) {
               local_decls.push({count: l.i32_count, type: kWasmI32});
             }
@@ -468,9 +1170,20 @@ class WasmModuleBuilder {
             if (l.f64_count > 0) {
               local_decls.push({count: l.f64_count, type: kWasmF64});
             }
+            if (l.s128_count > 0) {
+              local_decls.push({count: l.s128_count, type: kWasmS128});
+            }
+            if (l.anyref_count > 0) {
+              local_decls.push({count: l.anyref_count, type: kWasmAnyRef});
+            }
+            if (l.anyfunc_count > 0) {
+              local_decls.push({count: l.anyfunc_count, type: kWasmAnyFunc});
+            }
+            if (l.except_count > 0) {
+              local_decls.push({count: l.except_count, type: kWasmExnRef});
+            }
           }
 
-          let header = new Binary;
           header.emit_u32v(local_decls.length);
           for (let decl of local_decls) {
             header.emit_u32v(decl.count);
@@ -478,29 +1191,33 @@ class WasmModuleBuilder {
           }
 
           section.emit_u32v(header.length + func.body.length);
-          section.emit_bytes(header);
+          section.emit_bytes(header.trunc_buffer());
           section.emit_bytes(func.body);
         }
       });
     }
 
     // Add data segments.
-    if (wasm.segments.length > 0) {
+    if (wasm.data_segments.length > 0) {
       if (debug) print("emitting data segments @ " + binary.length);
       binary.emit_section(kDataSectionCode, section => {
-        section.emit_u32v(wasm.segments.length);
-        for (let seg of wasm.segments) {
-          section.emit_u8(0);  // linear memory index 0
-          if (seg.is_global) {
-            // initializer is a global variable
-            section.emit_u8(kExprGetGlobal);
-            section.emit_u32v(seg.addr);
+        section.emit_u32v(wasm.data_segments.length);
+        for (let seg of wasm.data_segments) {
+          if (seg.is_active) {
+            section.emit_u8(0);  // linear memory index 0 / flags
+            if (seg.is_global) {
+              // initializer is a global variable
+              section.emit_u8(kExprGlobalGet);
+              section.emit_u32v(seg.addr);
+            } else {
+              // initializer is a constant
+              section.emit_u8(kExprI32Const);
+              section.emit_u32v(seg.addr);
+            }
+            section.emit_u8(kExprEnd);
           } else {
-            // initializer is a constant
-            section.emit_u8(kExprI32Const);
-            section.emit_u32v(seg.addr);
+            section.emit_u8(kPassive);  // flags
           }
-          section.emit_u8(kExprEnd);
           section.emit_u32v(seg.data.length);
           section.emit_bytes(seg.data);
         }
@@ -513,43 +1230,110 @@ class WasmModuleBuilder {
       binary.emit_bytes(exp);
     }
 
-    // Add function names.
-    if (has_names) {
-      if (debug) print("emitting names @ " + binary.length);
+    // Add names.
+    let num_function_names = 0;
+    let num_functions_with_local_names = 0;
+    for (let func of wasm.functions) {
+      if (func.name !== undefined) ++num_function_names;
+      if (func.numLocalNames() > 0) ++num_functions_with_local_names;
+    }
+    if (num_function_names > 0 || num_functions_with_local_names > 0 ||
+        wasm.name !== undefined) {
+      if (debug) print('emitting names @ ' + binary.length);
       binary.emit_section(kUnknownSectionCode, section => {
-        section.emit_string("name");
-        var count = wasm.functions.length + wasm.num_imported_funcs;
-        section.emit_u32v(count);
-        for (var i = 0; i < wasm.num_imported_funcs; i++) {
-          section.emit_u8(0); // empty string
-          section.emit_u8(0); // local names count == 0
+        section.emit_string('name');
+        // Emit module name.
+        if (wasm.name !== undefined) {
+          section.emit_section(kModuleNameCode, name_section => {
+            name_section.emit_string(wasm.name);
+          });
         }
-        for (let func of wasm.functions) {
-          var name = func.name == undefined ? "" : func.name;
-          section.emit_string(name);
-          section.emit_u8(0);  // local names count == 0
+        // Emit function names.
+        if (num_function_names > 0) {
+          section.emit_section(kFunctionNamesCode, name_section => {
+            name_section.emit_u32v(num_function_names);
+            for (let func of wasm.functions) {
+              if (func.name === undefined) continue;
+              name_section.emit_u32v(func.index);
+              name_section.emit_string(func.name);
+            }
+          });
+        }
+        // Emit local names.
+        if (num_functions_with_local_names > 0) {
+          section.emit_section(kLocalNamesCode, name_section => {
+            name_section.emit_u32v(num_functions_with_local_names);
+            for (let func of wasm.functions) {
+              if (func.numLocalNames() == 0) continue;
+              name_section.emit_u32v(func.index);
+              name_section.emit_u32v(func.numLocalNames());
+              for (let i = 0; i < func.local_names.length; ++i) {
+                if (func.local_names[i] === undefined) continue;
+                name_section.emit_u32v(i);
+                name_section.emit_string(func.local_names[i]);
+              }
+            }
+          });
         }
       });
     }
 
-    return binary;
+    return binary.trunc_buffer();
   }
 
-  toBuffer(debug = false) {
-    let bytes = this.toArray(debug);
-    let buffer = new ArrayBuffer(bytes.length);
-    let view = new Uint8Array(buffer);
-    for (let i = 0; i < bytes.length; i++) {
-      let val = bytes[i];
-      if ((typeof val) == "string") val = val.charCodeAt(0);
-      view[i] = val | 0;
-    }
-    return new Uint8Array(buffer);
+  toArray(debug = false) {
+    return Array.from(this.toBuffer(debug));
   }
 
-  instantiate(...args) {
-    let module = new WebAssembly.Module(this.toBuffer());
-    let instance = new WebAssembly.Instance(module, ...args);
+  instantiate(ffi) {
+    let module = this.toModule();
+    let instance = new WebAssembly.Instance(module, ffi);
     return instance;
   }
+
+  asyncInstantiate(ffi) {
+    return WebAssembly.instantiate(this.toBuffer(), ffi)
+        .then(({module, instance}) => instance);
+  }
+
+  toModule(debug = false) {
+    return new WebAssembly.Module(this.toBuffer(debug));
+  }
+}
+
+function wasmSignedLeb(val, max_len = 5) {
+  let res = [];
+  for (let i = 0; i < max_len; ++i) {
+    let v = val & 0x7f;
+    // If {v} sign-extended from 7 to 32 bits is equal to val, we are done.
+    if (((v << 25) >> 25) == val) {
+      res.push(v);
+      return res;
+    }
+    res.push(v | 0x80);
+    val = val >> 7;
+  }
+  throw new Error(
+      'Leb value <' + val + '> exceeds maximum length of ' + max_len);
+}
+
+function wasmI32Const(val) {
+  return [kExprI32Const, ...wasmSignedLeb(val, 5)];
+}
+
+function wasmF32Const(f) {
+  f32_view[0] = f;
+  return [
+    kExprF32Const, f32_bytes_view[0], f32_bytes_view[1], f32_bytes_view[2],
+    f32_bytes_view[3]
+  ];
+}
+
+function wasmF64Const(f) {
+  f64_view[0] = f;
+  return [
+    kExprF64Const, f64_bytes_view[0], f64_bytes_view[1], f64_bytes_view[2],
+    f64_bytes_view[3], f64_bytes_view[4], f64_bytes_view[5], f64_bytes_view[6],
+    f64_bytes_view[7]
+  ];
 }
index 45c4942..dd721f1 100644 (file)
@@ -1,3 +1,29 @@
+2020-04-24  Alexey Shvayka  <shvaikalesh@gmail.com>
+
+        Fix WASM Error classes and re-sync wpt/wasm/jsapi from upstream
+        https://bugs.webkit.org/show_bug.cgi?id=210980
+
+        Reviewed by Keith Miller.
+
+        assert_throws_js() harness, which is extensively used by wpt/wasm/jsapi tests,
+        was recently updated to assert that passed constructors subclass Error in
+        spec-perfect way.
+
+        With this patch, WebAssembly errors have Error as [[Prototype]] of their constructors
+        and define correct "name" and "message" properties on their prototypes, aligning JSC
+        with the spec [1], V8 and SpiderMonkey.
+
+        [1]: https://webassembly.github.io/spec/js-api/#error-objects
+
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        * wasm/js/WebAssemblyCompileErrorPrototype.cpp:
+        (JSC::WebAssemblyCompileErrorPrototype::finishCreation):
+        * wasm/js/WebAssemblyLinkErrorPrototype.cpp:
+        (JSC::WebAssemblyLinkErrorPrototype::finishCreation):
+        * wasm/js/WebAssemblyRuntimeErrorPrototype.cpp:
+        (JSC::WebAssemblyRuntimeErrorPrototype::finishCreation):
+
 2020-04-24  Saam Barati  <sbarati@apple.com>
 
         Return BigInt32 whenever we can
index 19a48fb..d95df89 100644 (file)
@@ -1243,7 +1243,8 @@ capitalName ## Constructor* lowerName ## Constructor = featureFlag ? capitalName
             [] (LazyClassStructure::Initializer& init) { \
                 init.setPrototype(capitalName##Prototype::create(init.vm, init.global, capitalName##Prototype::createStructure(init.vm, init.global, init.global->prototypeBase ## Prototype()))); \
                 init.setStructure(instanceType::createStructure(init.vm, init.global, init.prototype)); \
-                init.setConstructor(capitalName ## Constructor::create(init.vm, capitalName ## Constructor::createStructure(init.vm, init.global, init.global->functionPrototype()), jsCast<capitalName ## Prototype*>(init.prototype))); \
+                auto* constructorPrototype = #prototypeBase == "error" ? init.global->m_errorStructure.constructor(init.global) : init.global->functionPrototype(); \
+                init.setConstructor(capitalName ## Constructor::create(init.vm, capitalName ## Constructor::createStructure(init.vm, init.global, constructorPrototype), jsCast<capitalName ## Prototype*>(init.prototype))); \
             }); \
     }
 
index 9289202..321338d 100644 (file)
@@ -57,6 +57,9 @@ Structure* WebAssemblyCompileErrorPrototype::createStructure(VM& vm, JSGlobalObj
 void WebAssemblyCompileErrorPrototype::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
+    ASSERT(inherits(vm, info()));
+    putDirectWithoutTransition(vm, vm.propertyNames->name, jsNontrivialString(vm, "CompileError"_s), static_cast<unsigned>(PropertyAttribute::DontEnum));
+    putDirectWithoutTransition(vm, vm.propertyNames->message, jsEmptyString(vm), static_cast<unsigned>(PropertyAttribute::DontEnum));
 }
 
 WebAssemblyCompileErrorPrototype::WebAssemblyCompileErrorPrototype(VM& vm, Structure* structure)
index a205a58..c7ce11c 100644 (file)
@@ -57,6 +57,9 @@ Structure* WebAssemblyLinkErrorPrototype::createStructure(VM& vm, JSGlobalObject
 void WebAssemblyLinkErrorPrototype::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
+    ASSERT(inherits(vm, info()));
+    putDirectWithoutTransition(vm, vm.propertyNames->name, jsNontrivialString(vm, "LinkError"_s), static_cast<unsigned>(PropertyAttribute::DontEnum));
+    putDirectWithoutTransition(vm, vm.propertyNames->message, jsEmptyString(vm), static_cast<unsigned>(PropertyAttribute::DontEnum));
 }
 
 WebAssemblyLinkErrorPrototype::WebAssemblyLinkErrorPrototype(VM& vm, Structure* structure)
index 4211965..f9731ae 100644 (file)
@@ -57,6 +57,9 @@ Structure* WebAssemblyRuntimeErrorPrototype::createStructure(VM& vm, JSGlobalObj
 void WebAssemblyRuntimeErrorPrototype::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
+    ASSERT(inherits(vm, info()));
+    putDirectWithoutTransition(vm, vm.propertyNames->name, jsNontrivialString(vm, "RuntimeError"_s), static_cast<unsigned>(PropertyAttribute::DontEnum));
+    putDirectWithoutTransition(vm, vm.propertyNames->message, jsEmptyString(vm), static_cast<unsigned>(PropertyAttribute::DontEnum));
 }
 
 WebAssemblyRuntimeErrorPrototype::WebAssemblyRuntimeErrorPrototype(VM& vm, Structure* structure)