Skip to content

Commit

Permalink
[js-api] Add tests for WebAssembly.JSTag (#319)
Browse files Browse the repository at this point in the history
This adds tests for `WebAssembly.JSTag`. The tests are adapted from
https://github.com/v8/v8/blob/main/test/mjsunit/wasm/exnref-api.js.

Confirmed that they run successfully with web test infrastructure in
Chrome with `--js-flags=--experimental-wasm-exnref` command line
argument. The only thing failing there was the shadowrealm test, which I
think we should add a separate expectation files like the existing
`***.tentative.any.shadowrealm-expected.txt` in
https://github.com/chromium/chromium/tree/main/third_party/blink/web_tests/external/wpt/wasm/jsapi/exception.
But given that we don't host these files in this EH repo, I'll just
upload the js files.
  • Loading branch information
aheejin committed Jul 4, 2024
1 parent c5b968f commit 4c93161
Showing 1 changed file with 121 additions and 0 deletions.
121 changes: 121 additions & 0 deletions test/js-api/exception/jsTag.tentative.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// META: global=window,dedicatedworker,jsshell,shadowrealm
// META: script=/wasm/jsapi/assertions.js
// META: script=/wasm/jsapi/wasm-module-builder.js

test(() => {
assert_throws_js(TypeError, () => new WebAssembly.Exception(WebAssembly.JSTag, [{}]))
}, "Creating a WebAssembly.Exception with JSTag explicitly is not allowed");

promise_test(async () => {
const builder = new WasmModuleBuilder();
const jsTag = builder.addImportedTag("module", "JSTag", kSig_v_r);

const throwRefFn = builder.addImport("module", "throw_ref", kSig_r_r);
const sig_r_v = builder.addType(kSig_r_v);
const kSig_re_v = makeSig([], [kExternRefCode, kExnRefCode]);
const sig_re_v = builder.addType(kSig_re_v);

// Calls throw_ref, catches an exception with 'try_table - catch JSTag', and
// returns it
builder.addFunction("catch_js_tag_and_return", kSig_r_r)
.addBody([
kExprBlock, sig_r_v,
kExprTryTable, sig_r_v, 1,
kCatchNoRef, jsTag, 0,
kExprLocalGet, 0,
kExprCallFunction, throwRefFn,
kExprEnd,
kExprEnd,
])
.exportFunc();

// Calls throw_ref, catches an exception with 'try_table - catch_ref JSTag',
// and returns it
builder.addFunction("catch_ref_js_tag_and_return", kSig_r_r)
.addBody([
kExprBlock, sig_re_v,
kExprTryTable, sig_r_v, 1,
kCatchRef, jsTag, 0,
kExprLocalGet, 0,
kExprCallFunction, throwRefFn,
kExprEnd,
kExprReturn,
kExprEnd,
kExprDrop,
])
.exportFunc();

// Calls throw_ref, catches an exception with 'try_table - catch_ref JSTag',
// and rethrows it (with throw_ref)
builder.addFunction("catch_ref_js_tag_and_throw_ref", kSig_r_r)
.addBody([
kExprBlock, sig_re_v,
kExprTryTable, sig_r_v, 1,
kCatchRef, jsTag, 0,
kExprLocalGet, 0,
kExprCallFunction, throwRefFn,
kExprEnd,
kExprReturn,
kExprEnd,
kExprThrowRef,
])
.exportFunc();

function throw_ref(x) {
throw x;
}
const buffer = builder.toBuffer();
const {instance} = await WebAssembly.instantiate(buffer, {
module: { throw_ref, JSTag: WebAssembly.JSTag }
});

const obj = {};
const wasmTag = new WebAssembly.Tag({parameters:['externref']});
const exn = new WebAssembly.Exception(wasmTag, [obj]);

// Test catch w/ return:
// This throws obj as a JS exception so it should be caught by the program and
// be returned as the original obj.
assert_equals(obj, instance.exports.catch_js_tag_and_return(obj));
// This is a WebAssembly.Exception, so the exception should just pass through
// the program without being caught.
assert_throws_exactly(exn, () => instance.exports.catch_js_tag_and_return(exn));

// Test catch_ref w/ return:
// This throws obj as a JS exception so it should be caught by the program and
// be returned as the original obj.
assert_equals(obj, instance.exports.catch_ref_js_tag_and_return(obj));
// This is a WebAssembly.Exception, so the exception should just pass through
// the program without being caught.
assert_throws_exactly(exn, () => instance.exports.catch_ref_js_tag_and_return(exn));

// Test catch_ref w/ throw_ref:
// This throws obj as a JS exception so it should be caught by the program and
// be rethrown.
assert_throws_exactly(obj, () => instance.exports.catch_ref_js_tag_and_throw_ref(obj));
// This is a WebAssembly.Exception, so the exception should just pass through
// the program without being caught.
assert_throws_exactly(exn, () => instance.exports.catch_ref_js_tag_and_throw_ref(exn));
}, "JS tag catching tests");

promise_test(async () => {
const builder = new WasmModuleBuilder();
const jsTag = builder.addImportedTag("module", "JSTag", kSig_v_r);

// Throw a JS object with WebAssembly.JSTag and check that we can catch it
// as-is from JavaScript.
builder.addFunction("throw_js_tag", kSig_v_r)
.addBody([
kExprLocalGet, 0,
kExprThrow, jsTag,
])
.exportFunc();

const buffer = builder.toBuffer();
const {instance} = await WebAssembly.instantiate(buffer, {
module: { JSTag: WebAssembly.JSTag }
});

const obj = {};
assert_throws_exactly(obj, () => instance.exports.throw_js_tag(obj));
}, "JS tag throwing test");

0 comments on commit 4c93161

Please sign in to comment.