Bug 1853454 - wasm: Add exnref, try_table, and throw_ref. r=yury
[gecko.git] / js / src / jit-test / tests / wasm / exnref / try-table.js
blob1970f8d41ff38503c7fcfc0f8111ab51b58f2788
1 // A try_table acts like a block label
3   let {test} = wasmEvalText(`(module
4     (func (export "test") (result i32)
5       try_table
6         br 0
7         (return i32.const 0)
8       end
9       (return i32.const 1)
10     )
11   )`).exports;
12   assertEq(test(), 1);
15 // A try_table can have results
17   let {test} = wasmEvalText(`(module
18     (func (export "test") (result i32)
19       try_table (result i32)
20         i32.const 1
21         br 0
22       end
23     )
24   )`).exports;
25   assertEq(test(), 1);
28 // A try_table can have params
30   let {test} = wasmEvalText(`(module
31     (func (export "test") (result i32)
32       i32.const 1
33       try_table (param i32)
34         return
35       end
36       (return i32.const 0)
37     )
38   )`).exports;
39   assertEq(test(), 1);
42 // Test try_table catching exceptions
44   let {test} = wasmEvalText(`(module
45     (tag $A (param i32))
46     (tag $B (param i32))
47     (tag $C)
49     (table funcref (elem $throwA $throwB $throwC $doNothing))
51     (type $empty (func))
52     (func $throwA
53       i32.const 1
54       throw $A
55     )
56     (func $throwB
57       i32.const 2
58       throw $B
59     )
60     (func $throwC
61       throw $C
62     )
63     (func $doNothing)
65     (func (export "test") (param i32) (result i32)
66       block $handleA (result i32 exnref)
67         block $handleB (result i32 exnref)
68           block $handleUnknown (result exnref)
69             try_table
70               (catch_ref $A $handleA)
71               (catch_ref $B $handleB)
72               (catch_all_ref $handleUnknown)
74               (call_indirect (type $empty)
75                 local.get 0)
76             end
77             (; nothing threw ;)
78             i32.const -1
79             return
80           end
81           (; $handleUnknown ;)
82           drop
83           i32.const 3
84           return
85         end
86          (; $handleB ;)
87         drop
88         return
89       end
90       (; $handleA ;)
91       drop
92       return
93     )
94   )`).exports;
95   // Throwing A results in 1 from the payload from the catch
96   assertEq(test(0), 1);
97   // Throwing B results in 2 from the payload from the catch
98   assertEq(test(1), 2);
99   // Throwing C results in 3 from the constant in the catch_all
100   assertEq(test(2), 3);
101   // Not throwing anything gets -1 from the fallthrough
102   assertEq(test(3), -1);
105 // Test try_table catching exceptions without capturing the exnref
107   let {test} = wasmEvalText(`(module
108     (tag $A (param i32))
109     (tag $B (param i32))
110     (tag $C)
112     (table funcref (elem $throwA $throwB $throwC $doNothing))
114     (type $empty (func))
115     (func $throwA
116       i32.const 1
117       throw $A
118     )
119     (func $throwB
120       i32.const 2
121       throw $B
122     )
123     (func $throwC
124       throw $C
125     )
126     (func $doNothing)
128     (func (export "test") (param i32) (result i32)
129       block $handleA (result i32)
130         block $handleB (result i32)
131           block $handleUnknown
132             try_table
133               (catch $A $handleA)
134               (catch $B $handleB)
135               (catch_all $handleUnknown)
137               (call_indirect (type $empty)
138                 local.get 0)
139             end
140             (; nothing threw ;)
141             i32.const -1
142             return
143           end
144           (; $handleUnknown ;)
145           i32.const 3
146           return
147         end
148          (; $handleB ;)
149         return
150       end
151       (; $handleA ;)
152       return
153     )
154   )`).exports;
155   // Throwing A results in 1 from the payload from the catch
156   assertEq(test(0), 1);
157   // Throwing B results in 2 from the payload from the catch
158   assertEq(test(1), 2);
159   // Throwing C results in 3 from the constant in the catch_all
160   assertEq(test(2), 3);
161   // Not throwing anything gets -1 from the fallthrough
162   assertEq(test(3), -1);
165 // Test try_table catching and rethrowing JS exceptions
167   let tag = new WebAssembly.Tag({parameters: []});
168   let exn = new WebAssembly.Exception(tag, []);
169   let values = [...WasmExternrefValues, exn];
170   function throwJS(value) {
171     throw value;
172   }
173   let {test} = wasmEvalText(`(module
174     (import "" "tag" (tag $tag))
175     (import "" "throwJS" (func $throwJS (param externref)))
176     (func (export "test") (param externref)
177       try_table (result exnref) (catch_ref $tag 0) (catch_all_ref 0)
178         local.get 0
179         call $throwJS
180         return
181       end
182       throw_ref
183     )
184   )`, {"": {tag, throwJS}}).exports;
186   for (let value of values) {
187     // TODO: A JS null value should become a non-null exnref that can be
188     // rethrown without a trap.
189     if (value === null) {
190       continue;
191     }
193     try {
194       test(value);
195       assertEq(true, false);
196     } catch (thrownValue) {
197       assertEq(thrownValue, value);
198     }
199   }