summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/gc/ref.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/wasm/gc/ref.js')
-rw-r--r--js/src/jit-test/tests/wasm/gc/ref.js202
1 files changed, 202 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/gc/ref.js b/js/src/jit-test/tests/wasm/gc/ref.js
new file mode 100644
index 0000000000..a55b0c8f02
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/gc/ref.js
@@ -0,0 +1,202 @@
+// |jit-test| skip-if: !wasmGcEnabled()
+
+// Parsing and resolving.
+
+var text = `(module
+ (rec
+ (type $cons (struct
+ (field $car i32)
+ (field $cdr (ref null $cons))))
+
+ (type $odd (struct
+ (field $odd.x i32)
+ (field $to_even (ref null $even))))
+
+ (type $even (struct
+ (field $even.x i32)
+ (field $to_odd (ref null $odd))))
+ )
+
+ ;; Use eqref on the API since struct types cannot be exposed outside the module yet.
+
+ (import "m" "f" (func $imp (param eqref) (result eqref)))
+
+ ;; The bodies do nothing since we have no operations on structs yet.
+ ;; Note none of these functions are exported, as they use Ref types in their signatures.
+
+ (func (param (ref null $cons)) (result i32)
+ (i32.const 0))
+
+ (func $cdr (param $p (ref null $cons)) (result (ref null $cons))
+ (local $l (ref null $cons))
+ ;; store null value of correct type
+ (local.set $l (ref.null $cons))
+ ;; store local of correct type
+ (local.set $l (local.get $p))
+ ;; store call result of correct type
+ (local.set $l (call $cdr (local.get $p)))
+ ;; TODO: eventually also a test with global.get
+ ;; blocks and if with result type
+ (block (result (ref null $cons))
+ (if (result (ref null $cons)) (i32.eqz (i32.const 0))
+ (then (unreachable))
+ (else (ref.null $cons)))))
+
+ (func (param (ref null $even)) (result (ref null $odd))
+ (ref.null $odd))
+
+ (func (param (ref null $odd)) (result (ref null $even))
+ (ref.null $even))
+
+ (func (param (ref null $cons))
+ (call $cdr (local.get 0))
+ drop
+ (call $imp (local.get 0))
+ drop)
+
+ (func (param (ref null $cons))
+ (drop (ref.eq (local.get 0) (ref.null $cons)))
+ (drop (ref.eq (ref.null $cons) (local.get 0)))
+ (drop (ref.eq (local.get 0) (ref.null $cons)))
+ (drop (ref.eq (ref.null $cons) (local.get 0))))
+ )`;
+
+// Validation
+
+wasmValidateText(text);
+
+// ref.is_null should work on any reference type
+
+new WebAssembly.Module(wasmTextToBinary(`
+(module
+ (type $s (struct))
+ (func $null (param (ref null $s)) (result i32)
+ (ref.is_null (local.get 0))))
+`))
+
+// Automatic upcast to eqref
+
+new WebAssembly.Module(wasmTextToBinary(`
+(module
+ (type $s (struct (field i32)))
+ (func $f (param (ref null $s)) (call $g (local.get 0)))
+ (func $g (param eqref) (unreachable)))
+`));
+
+// Misc failure modes
+
+assertErrorMessage(() => wasmEvalText(`
+(module
+ (func (param (ref null $odd)) (unreachable)))
+`),
+SyntaxError, /failed to find name/);
+
+// Ref type mismatch in parameter is allowed through the prefix rule
+// but not if the structs are incompatible.
+
+wasmEvalText(`
+(module
+ (type $s (struct (field i32)))
+ (type $t (struct (field i32)))
+ (func $f (param (ref null $s)) (unreachable))
+ (func $g (param (ref null $t)) (call $f (local.get 0)))
+)`);
+
+assertErrorMessage(() => wasmEvalText(`
+(module
+ (type $s (struct (field i32)))
+ (type $t (struct (field f32))) ;; Incompatible type
+ (func $f (param (ref null $s)) (unreachable))
+ (func $g (param (ref null $t)) (call $f (local.get 0)))
+)`),
+WebAssembly.CompileError, /expression has type \(ref null.*\) but expected \(ref null.*\)/);
+
+assertErrorMessage(() => wasmEvalText(`
+(module
+ (type $s (struct (field i32)))
+ (type $t (struct (field (mut i32)))) ;; Incompatible mutability
+ (func $f (param (ref null $s)) (unreachable))
+ (func $g (param (ref null $t)) (call $f (local.get 0)))
+)`),
+WebAssembly.CompileError, /expression has type \(ref null.*\) but expected \(ref null.*\)/);
+
+// Ref type mismatch in assignment to local but the prefix rule allows
+// the assignment to succeed if the structs are the same.
+
+wasmEvalText(`
+(module
+ (type $s (struct (field i32)))
+ (type $t (struct (field i32)))
+ (func $f (param (ref null $s)) (local (ref null $t)) (local.set 1 (local.get 0))))
+`)
+
+assertErrorMessage(() => wasmEvalText(`
+(module
+ (type $s (struct (field i32)))
+ (type $t (struct (field f32)))
+ (func $f (param (ref null $s)) (local (ref null $t)) (local.set 1 (local.get 0))))
+`),
+WebAssembly.CompileError, /expression has type \(ref null.*\) but expected \(ref null.*\)/);
+
+assertErrorMessage(() => wasmEvalText(`
+(module
+ (type $s (struct (field i32)))
+ (type $t (struct (field (mut i32))))
+ (func $f (param (ref null $s)) (unreachable))
+ (func $g (param (ref null $t)) (call $f (local.get 0)))
+)`),
+WebAssembly.CompileError, /expression has type \(ref null.*\) but expected \(ref null.*\)/);
+
+// Ref type mismatch in return but the prefix rule allows the return
+// to succeed if the structs are the same.
+
+wasmEvalText(`
+(module
+ (type $s (struct (field i32)))
+ (type $t (struct (field i32)))
+ (func $f (param (ref null $s)) (result (ref null $t)) (local.get 0)))
+`);
+
+assertErrorMessage(() => wasmEvalText(`
+(module
+ (type $s (struct (field i32)))
+ (type $t (struct (field f32)))
+ (func $f (param (ref null $s)) (result (ref null $t)) (local.get 0)))
+`),
+WebAssembly.CompileError, /expression has type \(ref null.*\) but expected \(ref null.*\)/);
+
+assertErrorMessage(() => wasmEvalText(`
+(module
+ (type $s (struct (field i32)))
+ (type $t (struct (field (mut i32))))
+ (func $f (param (ref null $s)) (result (ref null $t)) (local.get 0)))
+`),
+WebAssembly.CompileError, /expression has type \(ref null.*\) but expected \(ref null.*\)/);
+
+if (!wasmFunctionReferencesEnabled()) {
+ // Ref type can't reference a function type
+
+ assertErrorMessage(() => wasmEvalText(`
+(module
+ (type $x (func (param i32)))
+ (func $f (param (ref null $x)) (unreachable)))
+`),
+ WebAssembly.CompileError, /does not reference a gc type/);
+
+ assertErrorMessage(() => wasmEvalText(`
+(module
+ (type (func (param i32)))
+ (func $f (param (ref null 0)) (unreachable)))
+`),
+ WebAssembly.CompileError, /does not reference a gc type/);
+}
+
+// No automatic downcast from eqref
+
+assertErrorMessage(() => wasmEvalText(`
+(module
+ (type $s (struct (field i32)))
+ (func $f (param eqref) (call $g (local.get 0)))
+ (func $g (param (ref null $s)) (unreachable)))
+`),
+WebAssembly.CompileError, /expression has type eqref but expected \(ref null.*\)/);