From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- js/src/jit-test/tests/wasm/exceptions/js-api.js | 490 ++++++++++++++++++++++++ 1 file changed, 490 insertions(+) create mode 100644 js/src/jit-test/tests/wasm/exceptions/js-api.js (limited to 'js/src/jit-test/tests/wasm/exceptions/js-api.js') diff --git a/js/src/jit-test/tests/wasm/exceptions/js-api.js b/js/src/jit-test/tests/wasm/exceptions/js-api.js new file mode 100644 index 0000000000..4c2f018808 --- /dev/null +++ b/js/src/jit-test/tests/wasm/exceptions/js-api.js @@ -0,0 +1,490 @@ +// Tests for wasm exception proposal JS API features. + +load(libdir + "eqArrayHelper.js"); + +// WebAssembly.Tag tests. +assertErrorMessage( + () => WebAssembly.Tag(), + TypeError, + /calling a builtin Tag constructor without new is forbidden/ +); + +assertErrorMessage( + () => new WebAssembly.Tag(), + TypeError, + /At least 1 argument required/ +); + +assertErrorMessage( + () => new WebAssembly.Tag(3), + TypeError, + /first argument must be a tag descriptor/ +); + +assertErrorMessage( + () => new WebAssembly.Tag({ parameters: ["foobar"] }), + TypeError, + /bad value type/ +); + +new WebAssembly.Tag({ parameters: [] }); +new WebAssembly.Tag({ parameters: ["i32"] }); +new WebAssembly.Tag({ parameters: ["i32", "externref"] }); + +wasmEvalText(`(module (import "m" "e" (tag)))`, { + m: { e: new WebAssembly.Tag({ parameters: [] }) }, +}); + +wasmEvalText(`(module (import "m" "e" (tag (param i32))))`, { + m: { e: new WebAssembly.Tag({ parameters: ["i32"] }) }, +}); + +wasmEvalText(`(module (import "m" "e" (tag (param i32 i64))))`, { + m: { e: new WebAssembly.Tag({ parameters: ["i32", "i64"] }) }, +}); + +assertErrorMessage( + () => + wasmEvalText(`(module (import "m" "e" (tag (param i32))))`, { + m: { e: new WebAssembly.Tag({ parameters: [] }) }, + }), + WebAssembly.LinkError, + /imported tag 'm.e' signature mismatch/ +); + +assertErrorMessage( + () => + wasmEvalText(`(module (import "m" "e" (tag (param))))`, { + m: { e: new WebAssembly.Tag({ parameters: ["i32"] }) }, + }), + WebAssembly.LinkError, + /imported tag 'm.e' signature mismatch/ +); + +// Test WebAssembly.Tag methods. +// TODO: add runtime detection for js-types +// { +// let params = [ +// [], +// ["i32"], +// ["i32", "i64"], +// ["f32", "externref"], +// ["i32", "i64", "f32", "f64"], +// ]; + +// for (const arg of params) { +// const tag = new WebAssembly.Tag({ parameters: arg }); +// assertEqArray(tag.type().parameters, arg); +// } +// } + +// WebAssembly.Exception tests. +assertErrorMessage( + () => WebAssembly.Exception(), + TypeError, + /calling a builtin Exception constructor without new is forbidden/ +); + +assertErrorMessage( + () => new WebAssembly.Exception(), + TypeError, + /At least 2 arguments required/ +); + +assertErrorMessage( + () => new WebAssembly.Exception(3, []), + TypeError, + /first argument must be a WebAssembly.Tag/ +); + +const { tag1, tag2, tag3, tag4, tag5, tag6, tag7, tag8, tag9 } = wasmEvalText( + `(module + (tag (export "tag1") (param)) + (tag (export "tag2") (param i32)) + (tag (export "tag3") (param i32 f32)) + (tag (export "tag4") (param i32 externref i32)) + (tag (export "tag5") (param i32 externref i32 externref)) + (tag (export "tag6") (param funcref)) + (tag (export "tag7") (param i64)) + (tag (export "tag8") (param i32 f64)) + (tag (export "tag9") (param externref funcref)))` +).exports; + +new WebAssembly.Exception(tag1, []); +new WebAssembly.Exception(tag2, [3]); +new WebAssembly.Exception(tag3, [3, 5.5]); +new WebAssembly.Exception(tag4, [3, "foo", 4]); +new WebAssembly.Exception(tag5, [3, "foo", 4, "bar"]); + +assertErrorMessage( + () => new WebAssembly.Exception(tag2, []), + TypeError, + /expected 1 values but got 0/ +); + +assertErrorMessage( + () => new WebAssembly.Exception(tag2, [3n]), + TypeError, + /can't convert BigInt to number/ +); + +assertErrorMessage( + () => new WebAssembly.Exception(tag6, [undefined]), + TypeError, + /can only pass WebAssembly exported functions to funcref/ +); + +assertErrorMessage( + () => new WebAssembly.Exception(tag7, [undefined]), + TypeError, + /can't convert undefined to BigInt/ +); + +assertErrorMessage( + () => new WebAssembly.Exception(tag7, {}), + TypeError, + /\({}\) is not iterable/ +); + +assertErrorMessage( + () => new WebAssembly.Exception(tag7, 1), + TypeError, + /second argument must be an object/ +); + +// Test Exception methods. +{ + const exn1 = new WebAssembly.Exception(tag1, []); + assertEq(exn1.is(tag1), true); + assertEq(exn1.is(tag2), false); + assertErrorMessage( + () => exn1.is(), + TypeError, + /At least 1 argument required/ + ); + assertErrorMessage( + () => exn1.is(5), + TypeError, + /first argument must be a WebAssembly.Tag/ + ); + + const exn2 = new WebAssembly.Exception(tag2, [3]); + assertEq(exn2.getArg(tag2, 0), 3); + + assertEq(new WebAssembly.Exception(tag2, [undefined]).getArg(tag2, 0), 0); + + const exn4 = new WebAssembly.Exception(tag4, [3, "foo", 4]); + assertEq(exn4.getArg(tag4, 0), 3); + assertEq(exn4.getArg(tag4, 1), "foo"); + assertEq(exn4.getArg(tag4, 2), 4); + + const exn5 = new WebAssembly.Exception(tag5, [3, "foo", 4, "bar"]); + assertEq(exn5.getArg(tag5, 3), "bar"); + + const { funcref } = wasmEvalText( + `(module (func (export "funcref")))` + ).exports; + const exn9 = new WebAssembly.Exception(tag9, ["foo", funcref]); + assertEq(exn9.getArg(tag9, 0), "foo"); + assertEq(exn9.getArg(tag9, 1), funcref); + + assertErrorMessage( + () => exn2.getArg(), + TypeError, + /At least 2 arguments required/ + ); + assertErrorMessage( + () => exn2.getArg(5, 0), + TypeError, + /first argument must be a WebAssembly.Tag/ + ); + assertErrorMessage( + () => exn2.getArg(tag2, "foo"), + TypeError, + /bad Exception getArg index/ + ); + assertErrorMessage( + () => exn2.getArg(tag2, 10), + RangeError, + /bad Exception getArg index/ + ); +} + +// Test throwing a JS constructed exception to Wasm. +assertEq( + wasmEvalText( + `(module + (import "m" "exn" (tag $exn (param i32))) + (import "m" "f" (func $f)) + (func (export "f") (result i32) + try (result i32) + call $f + (i32.const 0) + catch $exn + end))`, + { + m: { + exn: tag2, + f: () => { + throw new WebAssembly.Exception(tag2, [42]); + }, + }, + } + ).exports.f(), + 42 +); + +assertEqArray( + wasmEvalText( + `(module + (import "m" "exn" (tag $exn (param i32 f32))) + (import "m" "f" (func $f)) + (func (export "f") (result i32 f32) + try (result i32 f32) + call $f + (i32.const 0) + (f32.const 0) + catch $exn + end))`, + { + m: { + exn: tag3, + f: () => { + throw new WebAssembly.Exception(tag3, [42, 5.5]); + }, + }, + } + ).exports.f(), + [42, 5.5] +); + +assertEqArray( + wasmEvalText( + `(module + (import "m" "exn" (tag $exn (param i32 f64))) + (import "m" "f" (func $f)) + (func (export "f") (result i32 f64) + try (result i32 f64) + call $f + (i32.const 0) + (f64.const 0) + catch $exn + end))`, + { + m: { + exn: tag8, + f: () => { + throw new WebAssembly.Exception(tag8, [9999, 9999]); + }, + }, + } + ).exports.f(), + [9999, 9999] +); + +assertEqArray( + wasmEvalText( + `(module + (import "m" "exn" (tag $exn (param i32 externref i32))) + (import "m" "f" (func $f)) + (func (export "f") (result i32 externref i32) + try (result i32 externref i32) + call $f + (i32.const 0) + (ref.null extern) + (i32.const 0) + catch $exn + end))`, + { + m: { + exn: tag4, + f: () => { + throw new WebAssembly.Exception(tag4, [42, "foo", 42]); + }, + }, + } + ).exports.f(), + [42, "foo", 42] +); + +assertEqArray( + wasmEvalText( + `(module + (import "m" "exn" (tag $exn (param i32 externref i32 externref))) + (import "m" "f" (func $f)) + (func (export "f") (result i32 externref i32 externref) + try (result i32 externref i32 externref) + call $f + (i32.const 0) + (ref.null extern) + (i32.const 0) + (ref.null extern) + catch $exn + end))`, + { + m: { + exn: tag5, + f: () => { + throw new WebAssembly.Exception(tag5, [42, "foo", 42, "bar"]); + }, + }, + } + ).exports.f(), + [42, "foo", 42, "bar"] +); + +{ + const { funcref } = wasmEvalText( + `(module (func (export "funcref")))` + ).exports; + assertEqArray( + wasmEvalText( + `(module + (import "m" "exn" (tag $exn (param externref funcref))) + (import "m" "f" (func $f)) + (func (export "f") (result externref funcref) + try (result externref funcref) + call $f + (ref.null extern) + (ref.null func) + catch $exn + end))`, + { + m: { + exn: tag9, + f: () => { + throw new WebAssembly.Exception(tag9, ["foo", funcref]); + }, + }, + } + ).exports.f(), + ["foo", funcref] + ); +} + +assertEq( + wasmEvalText( + `(module + (import "m" "exn" (tag $exn)) + (import "m" "f" (func $f)) + (func (export "f") (result i32) + try (result i32) + call $f + (i32.const 0) + catch $exn + (i32.const 0) + catch_all + (i32.const 1) + end))`, + { + m: { + exn: tag1, + f: () => { + throw new WebAssembly.Exception(tag2, [42]); + }, + }, + } + ).exports.f(), + 1 +); + +{ + const exn = new WebAssembly.Tag({ parameters: ["i32"] }); + assertEq( + wasmEvalText( + `(module + (import "m" "exn" (tag $exn (param i32))) + (import "m" "f" (func $f)) + (func (export "f") (result i32) + try (result i32) + call $f + (i32.const 0) + catch $exn + end))`, + { + m: { + exn, + f: () => { + throw new WebAssembly.Exception(exn, [42]); + }, + }, + } + ).exports.f(), + 42 + ); +} + +{ + const exn1 = new WebAssembly.Tag({ parameters: ["i32"] }); + const exn2 = new WebAssembly.Tag({ parameters: ["i32"] }); + assertEq( + wasmEvalText( + `(module + (import "m" "exn" (tag $exn (param i32))) + (import "m" "f" (func $f)) + (func (export "f") (result i32) + try (result i32) + call $f + (i32.const 0) + catch $exn + catch_all + (i32.const 1) + end))`, + { + m: { + exn: exn1, + f: () => { + throw new WebAssembly.Exception(exn2, [42]); + }, + }, + } + ).exports.f(), + 1 + ); +} + +// Test `getArg` on a Wasm-thrown exception. +assertEq( + (() => { + try { + wasmEvalText( + `(module + (import "m" "exn" (tag $exn (param i32 f64))) + (func (export "f") + (i32.const 9999) + (f64.const 9999) + throw $exn))`, + { m: { exn: tag8 } } + ).exports.f(); + } catch (exn) { + return exn.getArg(tag8, 1); + } + })(), + 9999 +); + +assertEqArray( + (() => { + try { + wasmEvalText( + `(module + (import "m" "exn" (tag $exn (param i32 externref i32 externref))) + (func (export "f") (param externref externref) + (i32.const 1) + (local.get 0) + (i32.const 2) + (local.get 1) + throw $exn))`, + { m: { exn: tag5 } } + ).exports.f("foo", "bar"); + } catch (exn) { + return [ + exn.getArg(tag5, 0), + exn.getArg(tag5, 1), + exn.getArg(tag5, 2), + exn.getArg(tag5, 3), + ]; + } + })(), + [1, "foo", 2, "bar"] +); -- cgit v1.2.3