Skip to content

Commit c5b968f

Browse files
authored
[js-api] Update basic and identity tests for exnref (#316)
This updates `basic.tentative.any.js` and `identity.tentative.any.js` tests to use the new instructions (`try_table` and `throw_ref`). In addition to converting existing tests to use the new instruction while maintaining the semantics, I added a new test in `basic.tentative.any.js` that makes use of all four `catch` clause variants to show all catch clauses works well in JS API tests. These new tests reauire `--js-flags=--experimental-wasm-exnref` argument to chrome, which is not currently supported in WPT out of the box. I've instead confirmed these run with chrome web tests infrastructure (https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/web_tests.md#Running-Web-Tests).
1 parent 5837755 commit c5b968f

File tree

3 files changed

+146
-53
lines changed

3 files changed

+146
-53
lines changed

test/js-api/exception/basic.tentative.any.js

Lines changed: 76 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ function assert_throws_wasm(fn, message) {
1313
promise_test(async () => {
1414
const kSig_v_r = makeSig([kWasmExternRef], []);
1515
const builder = new WasmModuleBuilder();
16-
const tagIndex = builder.addTag(kSig_v_r);
16+
const tagIndexExternref = builder.addTag(kSig_v_r);
1717
builder.addFunction("throw_param", kSig_v_r)
1818
.addBody([
1919
kExprLocalGet, 0,
20-
kExprThrow, tagIndex,
20+
kExprThrow, tagIndexExternref,
2121
])
2222
.exportFunc();
2323
const buffer = builder.toBuffer();
@@ -44,11 +44,11 @@ promise_test(async () => {
4444

4545
promise_test(async () => {
4646
const builder = new WasmModuleBuilder();
47-
const tagIndex = builder.addTag(kSig_v_a);
47+
const tagIndexAnyref = builder.addTag(kSig_v_a);
4848
builder.addFunction("throw_null", kSig_v_v)
4949
.addBody([
5050
kExprRefNull, kAnyFuncCode,
51-
kExprThrow, tagIndex,
51+
kExprThrow, tagIndexAnyref,
5252
])
5353
.exportFunc();
5454
const buffer = builder.toBuffer();
@@ -58,11 +58,11 @@ promise_test(async () => {
5858

5959
promise_test(async () => {
6060
const builder = new WasmModuleBuilder();
61-
const tagIndex = builder.addTag(kSig_v_i);
61+
const tagIndexI32 = builder.addTag(kSig_v_i);
6262
builder.addFunction("throw_int", kSig_v_v)
6363
.addBody([
6464
...wasmI32Const(7),
65-
kExprThrow, tagIndex,
65+
kExprThrow, tagIndexI32,
6666
])
6767
.exportFunc();
6868
const buffer = builder.toBuffer();
@@ -73,12 +73,18 @@ promise_test(async () => {
7373
promise_test(async () => {
7474
const builder = new WasmModuleBuilder();
7575
const fnIndex = builder.addImport("module", "fn", kSig_v_v);
76-
const tagIndex= builder.addTag(kSig_v_r);
76+
const tagIndexExternref = builder.addTag(kSig_v_r);
77+
7778
builder.addFunction("catch_exception", kSig_r_v)
7879
.addBody([
79-
kExprTry, kWasmVoid,
80-
kExprCallFunction, fnIndex,
81-
kExprCatch, tagIndex,
80+
kExprBlock, kWasmVoid,
81+
kExprBlock, kExternRefCode,
82+
kExprTryTable, kWasmVoid, 1,
83+
kCatchNoRef, tagIndexExternref, 0,
84+
kExprCallFunction, fnIndex,
85+
kExprEnd,
86+
kExprBr, 1,
87+
kExprEnd,
8288
kExprReturn,
8389
kExprEnd,
8490
kExprRefNull, kExternRefCode,
@@ -100,10 +106,15 @@ promise_test(async () => {
100106
const fnIndex = builder.addImport("module", "fn", kSig_v_v);
101107
builder.addFunction("catch_and_rethrow", kSig_r_v)
102108
.addBody([
103-
kExprTry, kWasmVoid,
104-
kExprCallFunction, fnIndex,
105-
kExprCatchAll,
106-
kExprRethrow, 0x00,
109+
kExprBlock, kWasmVoid,
110+
kExprBlock, kExnRefCode,
111+
kExprTryTable, kWasmVoid, 1,
112+
kCatchAllRef, 0,
113+
kExprCallFunction, fnIndex,
114+
kExprEnd,
115+
kExprBr, 1,
116+
kExprEnd,
117+
kExprThrowRef,
107118
kExprEnd,
108119
kExprRefNull, kExternRefCode,
109120
])
@@ -118,3 +129,54 @@ promise_test(async () => {
118129
});
119130
assert_throws_exactly(error, () => instance.exports.catch_and_rethrow());
120131
}, "Imported JS function throws, Wasm catches and rethrows");
132+
133+
promise_test(async () => {
134+
const builder = new WasmModuleBuilder();
135+
const fnIndex = builder.addImport("module", "fn", kSig_v_v);
136+
const tagI32 = new WebAssembly.Tag({ parameters: ["i32"] });
137+
const tagIndexI32 = builder.addImportedTag("module", "tagI32", kSig_v_i);
138+
const exn = new WebAssembly.Exception(tagI32, [42]);
139+
const kSig_ie_v = makeSig([], [kWasmI32, kExnRefCode]);
140+
const sig_ie_v = builder.addType(kSig_ie_v);
141+
142+
builder.addFunction("all_catch_clauses", kSig_i_v)
143+
.addBody([
144+
kExprBlock, kWasmVoid,
145+
kExprBlock, kExnRefCode,
146+
kExprBlock, sig_ie_v,
147+
kExprBlock, kWasmVoid,
148+
kExprBlock, kWasmI32,
149+
kExprTryTable, kWasmVoid, 4,
150+
kCatchNoRef, tagIndexI32, 0,
151+
kCatchAllNoRef, 1,
152+
kCatchRef, tagIndexI32, 2,
153+
kCatchAllRef, 3,
154+
kExprCallFunction, fnIndex,
155+
kExprEnd,
156+
kExprBr, 4,
157+
kExprEnd,
158+
kExprReturn,
159+
kExprEnd,
160+
kExprBr, 2,
161+
kExprEnd,
162+
kExprDrop,
163+
kExprDrop,
164+
kExprBr, 1,
165+
kExprEnd,
166+
kExprDrop,
167+
kExprEnd,
168+
kExprI32Const, 0,
169+
])
170+
.exportFunc();
171+
172+
const buffer = builder.toBuffer();
173+
174+
const fn = () => {
175+
throw exn;
176+
};
177+
const {instance} = await WebAssembly.instantiate(buffer, {
178+
module: { fn, tagI32: tagI32 }
179+
});
180+
const result = instance.exports.all_catch_clauses();
181+
assert_equals(result, 42);
182+
}, "try-table uses all four kinds of catch clauses, one of which catches an exception");

test/js-api/exception/identity.tentative.any.js

Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ test(() => {
2222
let wasmTagExnSamePayload = null;
2323
let wasmTagExnDiffPayload = null;
2424

25+
const kSig_ie_v = makeSig([], [kWasmI32, kExnRefCode]);
26+
const sig_ie_v = builder.addType(kSig_ie_v);
27+
2528
const imports = {
2629
module: {
2730
throwJSTagExn: function() { throw jsTagExn; },
@@ -31,55 +34,73 @@ test(() => {
3134
};
3235

3336
// Call a JS function that throws an exception using a JS-defined tag, catches
34-
// it with a 'catch' instruction, and rethrows it.
37+
// it with a 'catch_ref' instruction, and rethrows it.
3538
builder
36-
.addFunction("catch_js_tag_rethrow", kSig_v_v)
39+
.addFunction("catch_ref_js_tag_throw_ref", kSig_v_v)
3740
.addBody([
38-
kExprTry, kWasmVoid,
39-
kExprCallFunction, throwJSTagExnIndex,
40-
kExprCatch, jsTagIndex,
41-
kExprDrop,
42-
kExprRethrow, 0x00,
41+
kExprBlock, kWasmVoid,
42+
kExprBlock, sig_ie_v,
43+
kExprTryTable, kWasmVoid, 1,
44+
kCatchRef, jsTagIndex, 0,
45+
kExprCallFunction, throwJSTagExnIndex,
46+
kExprEnd,
47+
kExprBr, 1,
48+
kExprEnd,
49+
kExprThrowRef,
4350
kExprEnd
4451
])
4552
.exportFunc();
4653

4754
// Call a JS function that throws an exception using a Wasm-defined tag,
48-
// catches it with a 'catch' instruction, and rethrows it.
55+
// catches it with a 'catch_ref' instruction, and rethrows it.
4956
builder
50-
.addFunction("catch_wasm_tag_rethrow", kSig_v_v)
57+
.addFunction("catch_ref_wasm_tag_throw_ref", kSig_v_v)
5158
.addBody([
52-
kExprTry, kWasmVoid,
53-
kExprCallFunction, throwWasmTagExnIndex,
54-
kExprCatch, wasmTagIndex,
55-
kExprDrop,
56-
kExprRethrow, 0x00,
59+
kExprBlock, kWasmVoid,
60+
kExprBlock, sig_ie_v,
61+
kExprTryTable, kWasmVoid, 1,
62+
kCatchRef, wasmTagIndex, 0,
63+
kExprCallFunction, throwWasmTagExnIndex,
64+
kExprEnd,
65+
kExprBr, 1,
66+
kExprEnd,
67+
kExprThrowRef,
5768
kExprEnd
5869
])
5970
.exportFunc();
6071

6172
// Call a JS function that throws an exception using a JS-defined tag, catches
62-
// it with a 'catch_all' instruction, and rethrows it.
73+
// it with a 'catch_all_ref' instruction, and rethrows it.
6374
builder
64-
.addFunction("catch_all_js_tag_rethrow", kSig_v_v)
75+
.addFunction("catch_all_ref_js_tag_throw_ref", kSig_v_v)
6576
.addBody([
66-
kExprTry, kWasmVoid,
67-
kExprCallFunction, throwJSTagExnIndex,
68-
kExprCatchAll,
69-
kExprRethrow, 0x00,
77+
kExprBlock, kWasmVoid,
78+
kExprBlock, kExnRefCode,
79+
kExprTryTable, kWasmVoid, 1,
80+
kCatchAllRef, 0,
81+
kExprCallFunction, throwJSTagExnIndex,
82+
kExprEnd,
83+
kExprBr, 1,
84+
kExprEnd,
85+
kExprThrowRef,
7086
kExprEnd
7187
])
7288
.exportFunc();
7389

7490
// Call a JS function that throws an exception using a Wasm-defined tag,
75-
// catches it with a 'catch_all' instruction, and rethrows it.
91+
// catches it with a 'catch_all_ref' instruction, and rethrows it.
7692
builder
77-
.addFunction("catch_all_wasm_tag_rethrow", kSig_v_v)
93+
.addFunction("catch_all_ref_wasm_tag_throw_ref", kSig_v_v)
7894
.addBody([
79-
kExprTry, kWasmVoid,
80-
kExprCallFunction, throwWasmTagExnIndex,
81-
kExprCatchAll,
82-
kExprRethrow, 0x00,
95+
kExprBlock, kWasmVoid,
96+
kExprBlock, kExnRefCode,
97+
kExprTryTable, kWasmVoid, 1,
98+
kCatchAllRef, 0,
99+
kExprCallFunction, throwWasmTagExnIndex,
100+
kExprEnd,
101+
kExprBr, 1,
102+
kExprEnd,
103+
kExprThrowRef,
83104
kExprEnd
84105
])
85106
.exportFunc();
@@ -89,12 +110,17 @@ test(() => {
89110
builder
90111
.addFunction("catch_js_tag_return_payload", kSig_i_v)
91112
.addBody([
92-
kExprTry, kWasmI32,
93-
kExprCallFunction, throwJSTagExnIndex,
94-
kExprI32Const, 0x00,
95-
kExprCatch, jsTagIndex,
113+
kExprBlock, kWasmVoid,
114+
kExprBlock, kWasmI32,
115+
kExprTryTable, kWasmVoid, 1,
116+
kCatchNoRef, jsTagIndex, 0,
117+
kExprCallFunction, throwJSTagExnIndex,
118+
kExprEnd,
119+
kExprBr, 1,
120+
kExprEnd,
96121
kExprReturn,
97-
kExprEnd
122+
kExprEnd,
123+
kExprI32Const, 0
98124
])
99125
.exportFunc();
100126

@@ -103,9 +129,14 @@ test(() => {
103129
builder
104130
.addFunction("catch_js_tag_throw_payload", kSig_v_v)
105131
.addBody([
106-
kExprTry, kWasmVoid,
107-
kExprCallFunction, throwJSTagExnIndex,
108-
kExprCatch, jsTagIndex,
132+
kExprBlock, kWasmVoid,
133+
kExprBlock, kWasmI32,
134+
kExprTryTable, kWasmVoid, 1,
135+
kCatchNoRef, jsTagIndex, 0,
136+
kExprCallFunction, throwJSTagExnIndex,
137+
kExprEnd,
138+
kExprBr, 1,
139+
kExprEnd,
109140
kExprThrow, jsTagIndex,
110141
kExprEnd
111142
])
@@ -117,7 +148,7 @@ test(() => {
117148
// The exception object's identity should be preserved across 'rethrow's in
118149
// Wasm code. Do tests with a tag defined in JS.
119150
try {
120-
result.instance.exports.catch_js_tag_rethrow();
151+
result.instance.exports.catch_ref_js_tag_throw_ref();
121152
} catch (e) {
122153
assert_equals(e, jsTagExn);
123154
// Even if they have the same payload, they are different objects, so they
@@ -126,7 +157,7 @@ test(() => {
126157
assert_not_equals(e, jsTagExnDiffPayload);
127158
}
128159
try {
129-
result.instance.exports.catch_all_js_tag_rethrow();
160+
result.instance.exports.catch_all_ref_js_tag_throw_ref();
130161
} catch (e) {
131162
assert_equals(e, jsTagExn);
132163
assert_not_equals(e, jsTagExnSamePayload);
@@ -139,14 +170,14 @@ test(() => {
139170
wasmTagExnSamePayload = new WebAssembly.Exception(wasmTag, [42]);
140171
wasmTagExnDiffPayload = new WebAssembly.Exception(wasmTag, [53]);
141172
try {
142-
result.instance.exports.catch_wasm_tag_rethrow();
173+
result.instance.exports.catch_ref_wasm_tag_throw_ref();
143174
} catch (e) {
144175
assert_equals(e, wasmTagExn);
145176
assert_not_equals(e, wasmTagExnSamePayload);
146177
assert_not_equals(e, wasmTagExnDiffPayload);
147178
}
148179
try {
149-
result.instance.exports.catch_all_wasm_tag_rethrow();
180+
result.instance.exports.catch_all_ref_wasm_tag_throw_ref();
150181
} catch (e) {
151182
assert_equals(e, wasmTagExn);
152183
assert_not_equals(e, wasmTagExnSamePayload);

test/legacy/exceptions/js-api/basic.tentative.any.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ promise_test(async () => {
7373
promise_test(async () => {
7474
const builder = new WasmModuleBuilder();
7575
const fnIndex = builder.addImport("module", "fn", kSig_v_v);
76-
const tagIndex= builder.addTag(kSig_v_r);
76+
const tagIndex = builder.addTag(kSig_v_r);
7777
builder.addFunction("catch_exception", kSig_r_v)
7878
.addBody([
7979
kExprTry, kWasmVoid,

0 commit comments

Comments
 (0)