|
| 1 | +// META: global=window,dedicatedworker,jsshell,shadowrealm |
| 2 | +// META: script=/wasm/jsapi/assertions.js |
| 3 | +// META: script=/wasm/jsapi/wasm-module-builder.js |
| 4 | + |
| 5 | +test(() => { |
| 6 | + assert_throws_js(TypeError, () => new WebAssembly.Exception(WebAssembly.JSTag, [{}])) |
| 7 | +}, "Creating a WebAssembly.Exception with JSTag explicitly is not allowed"); |
| 8 | + |
| 9 | +promise_test(async () => { |
| 10 | + const builder = new WasmModuleBuilder(); |
| 11 | + const jsTag = builder.addImportedTag("module", "JSTag", kSig_v_r); |
| 12 | + |
| 13 | + const throwRefFn = builder.addImport("module", "throw_ref", kSig_r_r); |
| 14 | + const sig_r_v = builder.addType(kSig_r_v); |
| 15 | + const kSig_re_v = makeSig([], [kExternRefCode, kExnRefCode]); |
| 16 | + const sig_re_v = builder.addType(kSig_re_v); |
| 17 | + |
| 18 | + // Calls throw_ref, catches an exception with 'try_table - catch JSTag', and |
| 19 | + // returns it |
| 20 | + builder.addFunction("catch_js_tag_and_return", kSig_r_r) |
| 21 | + .addBody([ |
| 22 | + kExprBlock, sig_r_v, |
| 23 | + kExprTryTable, sig_r_v, 1, |
| 24 | + kCatchNoRef, jsTag, 0, |
| 25 | + kExprLocalGet, 0, |
| 26 | + kExprCallFunction, throwRefFn, |
| 27 | + kExprEnd, |
| 28 | + kExprEnd, |
| 29 | + ]) |
| 30 | + .exportFunc(); |
| 31 | + |
| 32 | + // Calls throw_ref, catches an exception with 'try_table - catch_ref JSTag', |
| 33 | + // and returns it |
| 34 | + builder.addFunction("catch_ref_js_tag_and_return", kSig_r_r) |
| 35 | + .addBody([ |
| 36 | + kExprBlock, sig_re_v, |
| 37 | + kExprTryTable, sig_r_v, 1, |
| 38 | + kCatchRef, jsTag, 0, |
| 39 | + kExprLocalGet, 0, |
| 40 | + kExprCallFunction, throwRefFn, |
| 41 | + kExprEnd, |
| 42 | + kExprReturn, |
| 43 | + kExprEnd, |
| 44 | + kExprDrop, |
| 45 | + ]) |
| 46 | + .exportFunc(); |
| 47 | + |
| 48 | + // Calls throw_ref, catches an exception with 'try_table - catch_ref JSTag', |
| 49 | + // and rethrows it (with throw_ref) |
| 50 | + builder.addFunction("catch_ref_js_tag_and_throw_ref", kSig_r_r) |
| 51 | + .addBody([ |
| 52 | + kExprBlock, sig_re_v, |
| 53 | + kExprTryTable, sig_r_v, 1, |
| 54 | + kCatchRef, jsTag, 0, |
| 55 | + kExprLocalGet, 0, |
| 56 | + kExprCallFunction, throwRefFn, |
| 57 | + kExprEnd, |
| 58 | + kExprReturn, |
| 59 | + kExprEnd, |
| 60 | + kExprThrowRef, |
| 61 | + ]) |
| 62 | + .exportFunc(); |
| 63 | + |
| 64 | + function throw_ref(x) { |
| 65 | + throw x; |
| 66 | + } |
| 67 | + const buffer = builder.toBuffer(); |
| 68 | + const {instance} = await WebAssembly.instantiate(buffer, { |
| 69 | + module: { throw_ref, JSTag: WebAssembly.JSTag } |
| 70 | + }); |
| 71 | + |
| 72 | + const obj = {}; |
| 73 | + const wasmTag = new WebAssembly.Tag({parameters:['externref']}); |
| 74 | + const exn = new WebAssembly.Exception(wasmTag, [obj]); |
| 75 | + |
| 76 | + // Test catch w/ return: |
| 77 | + // This throws obj as a JS exception so it should be caught by the program and |
| 78 | + // be returned as the original obj. |
| 79 | + assert_equals(obj, instance.exports.catch_js_tag_and_return(obj)); |
| 80 | + // This is a WebAssembly.Exception, so the exception should just pass through |
| 81 | + // the program without being caught. |
| 82 | + assert_throws_exactly(exn, () => instance.exports.catch_js_tag_and_return(exn)); |
| 83 | + |
| 84 | + // Test catch_ref w/ return: |
| 85 | + // This throws obj as a JS exception so it should be caught by the program and |
| 86 | + // be returned as the original obj. |
| 87 | + assert_equals(obj, instance.exports.catch_ref_js_tag_and_return(obj)); |
| 88 | + // This is a WebAssembly.Exception, so the exception should just pass through |
| 89 | + // the program without being caught. |
| 90 | + assert_throws_exactly(exn, () => instance.exports.catch_ref_js_tag_and_return(exn)); |
| 91 | + |
| 92 | + // Test catch_ref w/ throw_ref: |
| 93 | + // This throws obj as a JS exception so it should be caught by the program and |
| 94 | + // be rethrown. |
| 95 | + assert_throws_exactly(obj, () => instance.exports.catch_ref_js_tag_and_throw_ref(obj)); |
| 96 | + // This is a WebAssembly.Exception, so the exception should just pass through |
| 97 | + // the program without being caught. |
| 98 | + assert_throws_exactly(exn, () => instance.exports.catch_ref_js_tag_and_throw_ref(exn)); |
| 99 | +}, "JS tag catching tests"); |
| 100 | + |
| 101 | +promise_test(async () => { |
| 102 | + const builder = new WasmModuleBuilder(); |
| 103 | + const jsTag = builder.addImportedTag("module", "JSTag", kSig_v_r); |
| 104 | + |
| 105 | + // Throw a JS object with WebAssembly.JSTag and check that we can catch it |
| 106 | + // as-is from JavaScript. |
| 107 | + builder.addFunction("throw_js_tag", kSig_v_r) |
| 108 | + .addBody([ |
| 109 | + kExprLocalGet, 0, |
| 110 | + kExprThrow, jsTag, |
| 111 | + ]) |
| 112 | + .exportFunc(); |
| 113 | + |
| 114 | + const buffer = builder.toBuffer(); |
| 115 | + const {instance} = await WebAssembly.instantiate(buffer, { |
| 116 | + module: { JSTag: WebAssembly.JSTag } |
| 117 | + }); |
| 118 | + |
| 119 | + const obj = {}; |
| 120 | + assert_throws_exactly(obj, () => instance.exports.throw_js_tag(obj)); |
| 121 | +}, "JS tag throwing test"); |
0 commit comments