ref.js (5703B)
1 // Parsing and resolving. 2 3 var text = `(module 4 (rec 5 (type $cons (struct 6 (field $car i32) 7 (field $cdr (ref null $cons)))) 8 9 (type $odd (struct 10 (field $odd.x i32) 11 (field $to_even (ref null $even)))) 12 13 (type $even (struct 14 (field $even.x i32) 15 (field $to_odd (ref null $odd)))) 16 ) 17 18 ;; Use eqref on the API since struct types cannot be exposed outside the module yet. 19 20 (import "m" "f" (func $imp (param eqref) (result eqref))) 21 22 ;; The bodies do nothing since we have no operations on structs yet. 23 ;; Note none of these functions are exported, as they use Ref types in their signatures. 24 25 (func (param (ref null $cons)) (result i32) 26 (i32.const 0)) 27 28 (func $cdr (param $p (ref null $cons)) (result (ref null $cons)) 29 (local $l (ref null $cons)) 30 ;; store null value of correct type 31 (local.set $l (ref.null $cons)) 32 ;; store local of correct type 33 (local.set $l (local.get $p)) 34 ;; store call result of correct type 35 (local.set $l (call $cdr (local.get $p))) 36 ;; TODO: eventually also a test with global.get 37 ;; blocks and if with result type 38 (block (result (ref null $cons)) 39 (if (result (ref null $cons)) (i32.eqz (i32.const 0)) 40 (then (unreachable)) 41 (else (ref.null $cons))))) 42 43 (func (param (ref null $even)) (result (ref null $odd)) 44 (ref.null $odd)) 45 46 (func (param (ref null $odd)) (result (ref null $even)) 47 (ref.null $even)) 48 49 (func (param (ref null $cons)) 50 (call $cdr (local.get 0)) 51 drop 52 (call $imp (local.get 0)) 53 drop) 54 55 (func (param (ref null $cons)) 56 (drop (ref.eq (local.get 0) (ref.null $cons))) 57 (drop (ref.eq (ref.null $cons) (local.get 0))) 58 (drop (ref.eq (local.get 0) (ref.null $cons))) 59 (drop (ref.eq (ref.null $cons) (local.get 0)))) 60 )`; 61 62 // Validation 63 64 wasmValidateText(text); 65 66 // ref.is_null should work on any reference type 67 68 new WebAssembly.Module(wasmTextToBinary(` 69 (module 70 (type $s (struct)) 71 (func $null (param (ref null $s)) (result i32) 72 (ref.is_null (local.get 0)))) 73 `)) 74 75 // Automatic upcast to eqref 76 77 new WebAssembly.Module(wasmTextToBinary(` 78 (module 79 (type $s (struct (field i32))) 80 (func $f (param (ref null $s)) (call $g (local.get 0))) 81 (func $g (param eqref) (unreachable))) 82 `)); 83 84 // Misc failure modes 85 86 assertErrorMessage(() => wasmEvalText(` 87 (module 88 (func (param (ref null $odd)) (unreachable))) 89 `), 90 SyntaxError, /failed to find name/); 91 92 // Ref type mismatch in parameter is allowed through the prefix rule 93 // but not if the structs are incompatible. 94 95 wasmEvalText(` 96 (module 97 (type $s (struct (field i32))) 98 (type $t (struct (field i32))) 99 (func $f (param (ref null $s)) (unreachable)) 100 (func $g (param (ref null $t)) (call $f (local.get 0))) 101 )`); 102 103 assertErrorMessage(() => wasmEvalText(` 104 (module 105 (type $s (struct (field i32))) 106 (type $t (struct (field f32))) ;; Incompatible type 107 (func $f (param (ref null $s)) (unreachable)) 108 (func $g (param (ref null $t)) (call $f (local.get 0))) 109 )`), 110 WebAssembly.CompileError, /expression has type \(ref null.*\) but expected \(ref null.*\)/); 111 112 assertErrorMessage(() => wasmEvalText(` 113 (module 114 (type $s (struct (field i32))) 115 (type $t (struct (field (mut i32)))) ;; Incompatible mutability 116 (func $f (param (ref null $s)) (unreachable)) 117 (func $g (param (ref null $t)) (call $f (local.get 0))) 118 )`), 119 WebAssembly.CompileError, /expression has type \(ref null.*\) but expected \(ref null.*\)/); 120 121 // Ref type mismatch in assignment to local but the prefix rule allows 122 // the assignment to succeed if the structs are the same. 123 124 wasmEvalText(` 125 (module 126 (type $s (struct (field i32))) 127 (type $t (struct (field i32))) 128 (func $f (param (ref null $s)) (local (ref null $t)) (local.set 1 (local.get 0)))) 129 `) 130 131 assertErrorMessage(() => wasmEvalText(` 132 (module 133 (type $s (struct (field i32))) 134 (type $t (struct (field f32))) 135 (func $f (param (ref null $s)) (local (ref null $t)) (local.set 1 (local.get 0)))) 136 `), 137 WebAssembly.CompileError, /expression has type \(ref null.*\) but expected \(ref null.*\)/); 138 139 assertErrorMessage(() => wasmEvalText(` 140 (module 141 (type $s (struct (field i32))) 142 (type $t (struct (field (mut i32)))) 143 (func $f (param (ref null $s)) (unreachable)) 144 (func $g (param (ref null $t)) (call $f (local.get 0))) 145 )`), 146 WebAssembly.CompileError, /expression has type \(ref null.*\) but expected \(ref null.*\)/); 147 148 // Ref type mismatch in return but the prefix rule allows the return 149 // to succeed if the structs are the same. 150 151 wasmEvalText(` 152 (module 153 (type $s (struct (field i32))) 154 (type $t (struct (field i32))) 155 (func $f (param (ref null $s)) (result (ref null $t)) (local.get 0))) 156 `); 157 158 assertErrorMessage(() => wasmEvalText(` 159 (module 160 (type $s (struct (field i32))) 161 (type $t (struct (field f32))) 162 (func $f (param (ref null $s)) (result (ref null $t)) (local.get 0))) 163 `), 164 WebAssembly.CompileError, /expression has type \(ref null.*\) but expected \(ref null.*\)/); 165 166 assertErrorMessage(() => wasmEvalText(` 167 (module 168 (type $s (struct (field i32))) 169 (type $t (struct (field (mut i32)))) 170 (func $f (param (ref null $s)) (result (ref null $t)) (local.get 0))) 171 `), 172 WebAssembly.CompileError, /expression has type \(ref null.*\) but expected \(ref null.*\)/); 173 174 // No automatic downcast from eqref 175 176 assertErrorMessage(() => wasmEvalText(` 177 (module 178 (type $s (struct (field i32))) 179 (func $f (param eqref) (call $g (local.get 0))) 180 (func $g (param (ref null $s)) (unreachable))) 181 `), 182 WebAssembly.CompileError, /expression has type eqref but expected \(ref null.*\)/);