summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/gc/js-boundary.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/wasm/gc/js-boundary.js')
-rw-r--r--js/src/jit-test/tests/wasm/gc/js-boundary.js123
1 files changed, 123 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/gc/js-boundary.js b/js/src/jit-test/tests/wasm/gc/js-boundary.js
new file mode 100644
index 0000000000..029bf576c2
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/gc/js-boundary.js
@@ -0,0 +1,123 @@
+// |jit-test| skip-if: !wasmGcEnabled()
+
+// Tests of dynamic type checks
+test('anyref', WasmAnyrefValues, []);
+test('eqref', WasmEqrefValues, WasmNonAnyrefValues);
+test('structref', WasmStructrefValues, WasmNonAnyrefValues);
+test('arrayref', WasmArrayrefValues, WasmNonAnyrefValues);
+let { newStruct } = wasmEvalText(`
+ (module
+ (type $s (struct))
+ (func (export "newStruct") (result anyref)
+ struct.new $s)
+ )`).exports;
+test('(ref null 0)', [newStruct()], WasmNonAnyrefValues, '(type (struct))');
+test('nullref', [null], WasmNonAnyrefValues);
+
+function test(type, validValues, invalidValues, typeSection = "") {
+ const CheckError = /can only pass|bad type/;
+
+ // 1. Exported function params
+ let {a} = wasmEvalText(`(module
+ ${typeSection}
+ (func (export "a") (param ${type}))
+ )`).exports;
+ for (let val of invalidValues) {
+ assertErrorMessage(() => a(val), TypeError, CheckError);
+ }
+ for (let val of validValues) {
+ a(val);
+ }
+
+ // 2. Imported function results
+ for (let val of invalidValues) {
+ function returnVal() {
+ return val;
+ }
+ let {test} = wasmEvalText(`(module
+ ${typeSection}
+ (func $returnVal (import "" "returnVal") (result ${type}))
+ (func (export "test")
+ call $returnVal
+ drop
+ )
+ )`, {"": {returnVal}}).exports;
+ assertErrorMessage(() => test(), TypeError, CheckError);
+ }
+ for (let val of validValues) {
+ function returnVal() {
+ return val;
+ }
+ let {test} = wasmEvalText(`(module
+ ${typeSection}
+ (func $returnVal (import "" "returnVal") (result ${type}))
+ (func (export "test")
+ call $returnVal
+ drop
+ )
+ )`, {"": {returnVal}}).exports;
+ test(val);
+ }
+
+ // TODO: the rest of the tests cannot handle type sections yet.
+ if (typeSection !== "") {
+ return;
+ }
+
+ // 3. Global value setter
+ for (let val of validValues) {
+ // Construct global from JS-API with initial value
+ let a = new WebAssembly.Global({value: type}, val);
+ assertEq(a.value, val, 'roundtrip matches');
+
+ // Construct global from JS-API with null value, then set
+ let b = new WebAssembly.Global({value: type, mutable: true}, null);
+ b.value = val;
+ assertEq(b.value, val, 'roundtrip matches');
+ }
+ for (let val of invalidValues) {
+ // Construct global from JS-API with initial value
+ assertErrorMessage(() => new WebAssembly.Global({value: type}, val),
+ TypeError,
+ CheckError);
+
+ // Construct global from JS-API with null value, then set
+ let a = new WebAssembly.Global({value: type, mutable: true}, null);
+ assertErrorMessage(() => a.value = val,
+ TypeError,
+ CheckError);
+ }
+
+ // 4. Table set method
+ for (let val of validValues) {
+ let table = new WebAssembly.Table({element: type, initial: 1, maximum: 1});
+ table.set(0, val);
+ assertEq(table.get(0), val, 'roundtrip matches');
+ }
+ for (let val of invalidValues) {
+ let table = new WebAssembly.Table({element: type, initial: 1, maximum: 1});
+ assertErrorMessage(() => table.set(0, val),
+ TypeError,
+ CheckError);
+ }
+}
+
+// Verify that GC objects are opaque
+for (const val of WasmGcObjectValues) {
+ assertEq(Reflect.getPrototypeOf(val), null);
+ assertEq(Reflect.setPrototypeOf(val, null), true);
+ assertEq(Reflect.setPrototypeOf(val, {}), false);
+ assertEq(Reflect.isExtensible(val), false);
+ assertEq(Reflect.preventExtensions(val), false);
+ assertEq(Reflect.getOwnPropertyDescriptor(val, "anything"), undefined);
+ assertEq(Reflect.defineProperty(val, "anything", { value: 42 }), false);
+ assertEq(Reflect.has(val, "anything"), false);
+ assertEq(Reflect.get(val, "anything"), undefined);
+ assertErrorMessage(() => { Reflect.set(val, "anything", 3); }, TypeError, /can't modify/);
+ assertErrorMessage(() => { Reflect.deleteProperty(val, "anything"); }, TypeError, /can't modify/);
+ assertEq(Reflect.ownKeys(val).length, 0, `gc objects should not have keys, but this one had: ${Reflect.ownKeys(val)}`);
+ for (const i in val) {
+ throw new Error(`GC objects should have no enumerable properties, but had ${i}`);
+ }
+ assertEq(val[Symbol.iterator], undefined, "GC objects should not be iterable");
+}