| Index: test/mjsunit/wasm/exceptions.js
|
| diff --git a/test/mjsunit/wasm/exceptions.js b/test/mjsunit/wasm/exceptions.js
|
| index b8d56ff6b55202b6cb1edbedbd088752529c3dbd..71bd5f18ed1fd6dd9b2cfdc2e084756148f14500 100644
|
| --- a/test/mjsunit/wasm/exceptions.js
|
| +++ b/test/mjsunit/wasm/exceptions.js
|
| @@ -7,7 +7,8 @@
|
| load("test/mjsunit/wasm/wasm-constants.js");
|
| load("test/mjsunit/wasm/wasm-module-builder.js");
|
|
|
| -var module = (function () {
|
| +// The following methods do not attempt to catch the exception they raise.
|
| +var test_throw = (function () {
|
| var builder = new WasmModuleBuilder();
|
|
|
| builder.addFunction("throw_param_if_not_zero", kSig_i_i)
|
| @@ -17,7 +18,7 @@ var module = (function () {
|
| kExprI32Ne,
|
| kExprIf, kAstStmt,
|
| kExprGetLocal, 0,
|
| - kExprThrow, kAstStmt,
|
| + kExprThrow,
|
| kExprEnd,
|
| kExprI32Const, 1
|
| ])
|
| @@ -26,7 +27,7 @@ var module = (function () {
|
| builder.addFunction("throw_20", kSig_v_v)
|
| .addBody([
|
| kExprI32Const, 20,
|
| - kExprThrow, kAstStmt
|
| + kExprThrow,
|
| ])
|
| .exportFunc()
|
|
|
| @@ -43,25 +44,340 @@ var module = (function () {
|
| kExprI32Mul,
|
| kExprI32Const, 20,
|
| kExprI32Sub,
|
| - kExprThrow, kAstStmt
|
| + kExprThrow,
|
| ])
|
| .exportFunc()
|
|
|
| return builder.instantiate();
|
| })();
|
|
|
| -// Check the module exists.
|
| -assertFalse(module === undefined);
|
| -assertFalse(module === null);
|
| -assertFalse(module === 0);
|
| -assertEquals("object", typeof module.exports);
|
| -assertEquals("function", typeof module.exports.throw_param_if_not_zero);
|
| -
|
| -assertEquals(1, module.exports.throw_param_if_not_zero(0));
|
| -assertWasmThrows(10, function() { module.exports.throw_param_if_not_zero(10) });
|
| -assertWasmThrows(-1, function() { module.exports.throw_param_if_not_zero(-1) });
|
| -assertWasmThrows(20, module.exports.throw_20);
|
| +// Check the test_throw exists.
|
| +assertFalse(test_throw === undefined);
|
| +assertFalse(test_throw === null);
|
| +assertFalse(test_throw === 0);
|
| +assertEquals("object", typeof test_throw.exports);
|
| +assertEquals("function", typeof test_throw.exports.throw_param_if_not_zero);
|
| +assertEquals("function", typeof test_throw.exports.throw_20);
|
| +assertEquals("function", typeof test_throw.exports.throw_expr_with_params);
|
| +
|
| +assertEquals(1, test_throw.exports.throw_param_if_not_zero(0));
|
| +assertWasmThrows(10, function() { test_throw.exports.throw_param_if_not_zero(10) });
|
| +assertWasmThrows(-1, function() { test_throw.exports.throw_param_if_not_zero(-1) });
|
| +assertWasmThrows(20, test_throw.exports.throw_20);
|
| assertWasmThrows(
|
| - -8, function() { module.exports.throw_expr_with_params(1.5, 2.5, 4); });
|
| + -8, function() { test_throw.exports.throw_expr_with_params(1.5, 2.5, 4); });
|
| assertWasmThrows(
|
| - 12, function() { module.exports.throw_expr_with_params(5.7, 2.5, 4); });
|
| + 12, function() { test_throw.exports.throw_expr_with_params(5.7, 2.5, 4); });
|
| +
|
| +// Now that we know throwing works, we test catching the exceptions we raise.
|
| +var test_catch = (function () {
|
| + var builder = new WasmModuleBuilder();
|
| +
|
| + // Helper function for throwing from js. It is imported by the Wasm module
|
| + // as throw_i.
|
| + function throw_value(value) {
|
| + throw value;
|
| + }
|
| + var sig_index = builder.addType(kSig_v_i);
|
| + var kJSThrowI = builder.addImport("throw_i", sig_index);
|
| +
|
| + // Helper function that throws a string. Wasm should not catch it.
|
| + function throw_string() {
|
| + throw "use wasm;";
|
| + }
|
| + sig_index = builder.addType(kSig_v_v);
|
| + var kJSThrowString = builder.addImport("throw_string", sig_index);
|
| +
|
| + // Helper function that throws undefined. Wasm should not catch it.
|
| + function throw_undefined() {
|
| + throw undefined;
|
| + }
|
| + var kJSThrowUndefined = builder.addImport("throw_undefined", sig_index);
|
| +
|
| + // Helper function that throws an fp. Wasm should not catch it.
|
| + function throw_fp() {
|
| + throw 10.5;
|
| + }
|
| + var kJSThrowFP = builder.addImport("throw_fp", sig_index);
|
| +
|
| + // Helper function that throws a large number. Wasm should not catch it.
|
| + function throw_large() {
|
| + throw 1e+28;
|
| + }
|
| + var kJSThrowLarge = builder.addImport("throw_large", sig_index);
|
| +
|
| + // Helper function for throwing from Wasm.
|
| + var kWasmThrowFunction =
|
| + builder.addFunction("throw", kSig_v_i)
|
| + .addBody([
|
| + kExprGetLocal, 0,
|
| + kExprThrow
|
| + ])
|
| + .index;
|
| +
|
| + // Scenario 1: Throw and catch appear on the same function. This should
|
| + // happen in case of inlining, for example.
|
| + builder.addFunction("same_scope", kSig_i_i)
|
| + .addBody([
|
| + kExprTry, kAstI32,
|
| + kExprGetLocal, 0,
|
| + kExprI32Const, 0,
|
| + kExprI32Ne,
|
| + kExprIf, kAstStmt,
|
| + kExprGetLocal, 0,
|
| + kExprThrow,
|
| + kExprUnreachable,
|
| + kExprEnd,
|
| + kExprI32Const, 63,
|
| + kExprCatch, 1,
|
| + kExprGetLocal, 1,
|
| + kExprEnd
|
| + ])
|
| + .addLocals({i32_count: 1})
|
| + .exportFunc()
|
| + .index;
|
| +
|
| + builder.addFunction("same_scope_ignore", kSig_i_i)
|
| + .addBody([
|
| + kExprTry, kAstI32,
|
| + kExprGetLocal, 0,
|
| + kExprThrow,
|
| + kExprUnreachable,
|
| + kExprCatch, 1,
|
| + kExprGetLocal, 0,
|
| + kExprEnd,
|
| + ])
|
| + .addLocals({i32_count: 1})
|
| + .exportFunc();
|
| +
|
| + builder.addFunction("same_scope_multiple", kSig_i_i)
|
| + // path = 0;
|
| + //
|
| + // try {
|
| + // try {
|
| + // try {
|
| + // if (p == 1)
|
| + // throw 1;
|
| + // path |= 2
|
| + // } catch (v) {
|
| + // path |= v | 4;
|
| + // throw path;
|
| + // }
|
| + // if (p == 2)
|
| + // throw path|8;
|
| + // path |= 16;
|
| + // } catch (v) {
|
| + // path |= v | 32;
|
| + // throw path;
|
| + // }
|
| + // if (p == 3)
|
| + // throw path|64;
|
| + // path |= 128
|
| + // } catch (v) {
|
| + // path |= v | 256;
|
| + // }
|
| + //
|
| + // return path;
|
| + //
|
| + // p == 1 -> path == 293
|
| + // p == 2 -> path == 298
|
| + // p == 3 -> path == 338
|
| + // else -> path == 146
|
| + .addBody([
|
| + kExprTry, kAstI32,
|
| + kExprTry, kAstI32,
|
| + kExprTry, kAstI32,
|
| + kExprGetLocal, 0,
|
| + kExprI32Const, 1,
|
| + kExprI32Eq,
|
| + kExprIf, kAstStmt,
|
| + kExprI32Const, 1,
|
| + kExprThrow,
|
| + kExprUnreachable,
|
| + kExprEnd,
|
| + kExprI32Const, 2,
|
| + kExprCatch, 1,
|
| + kExprGetLocal, 1,
|
| + kExprI32Const, 4,
|
| + kExprI32Ior,
|
| + kExprThrow,
|
| + kExprUnreachable,
|
| + kExprEnd,
|
| + kExprTeeLocal, 2,
|
| + kExprGetLocal, 0,
|
| + kExprI32Const, 2,
|
| + kExprI32Eq,
|
| + kExprIf, kAstStmt,
|
| + kExprGetLocal, 2,
|
| + kExprI32Const, 8,
|
| + kExprI32Ior,
|
| + kExprThrow,
|
| + kExprUnreachable,
|
| + kExprEnd,
|
| + kExprI32Const, 16,
|
| + kExprI32Ior,
|
| + kExprCatch, 1,
|
| + kExprGetLocal, 1,
|
| + kExprI32Const, 32,
|
| + kExprI32Ior,
|
| + kExprThrow,
|
| + kExprUnreachable,
|
| + kExprEnd,
|
| + kExprTeeLocal, 2,
|
| + kExprGetLocal, 0,
|
| + kExprI32Const, 3,
|
| + kExprI32Eq,
|
| + kExprIf, kAstStmt,
|
| + kExprGetLocal, 2,
|
| + kExprI32Const, /*64=*/ 192, 0,
|
| + kExprI32Ior,
|
| + kExprThrow,
|
| + kExprUnreachable,
|
| + kExprEnd,
|
| + kExprI32Const, /*128=*/ 128, 1,
|
| + kExprI32Ior,
|
| + kExprCatch, 1,
|
| + kExprGetLocal, 1,
|
| + kExprI32Const, /*256=*/ 128, 2,
|
| + kExprI32Ior,
|
| + kExprEnd,
|
| + ])
|
| + .addLocals({i32_count: 2})
|
| + .exportFunc();
|
| +
|
| + // Scenario 2: Catches an exception raised from the direct callee.
|
| + var kFromDirectCallee =
|
| + builder.addFunction("from_direct_callee", kSig_i_i)
|
| + .addBody([
|
| + kExprTry, kAstI32,
|
| + kExprGetLocal, 0,
|
| + kExprCallFunction, kWasmThrowFunction,
|
| + kExprI32Const, /*-1=*/ 127,
|
| + kExprCatch, 1,
|
| + kExprGetLocal, 1,
|
| + kExprEnd
|
| + ])
|
| + .addLocals({i32_count: 1})
|
| + .exportFunc()
|
| + .index;
|
| +
|
| + // Scenario 3: Catches an exception raised from an indirect callee.
|
| + var kFromIndirectCalleeHelper = kFromDirectCallee + 1;
|
| + builder.addFunction("from_indirect_callee_helper", kSig_v_ii)
|
| + .addBody([
|
| + kExprGetLocal, 0,
|
| + kExprI32Const, 0,
|
| + kExprI32GtS,
|
| + kExprIf, kAstStmt,
|
| + kExprGetLocal, 0,
|
| + kExprI32Const, 1,
|
| + kExprI32Sub,
|
| + kExprGetLocal, 1,
|
| + kExprI32Const, 1,
|
| + kExprI32Sub,
|
| + kExprCallFunction, kFromIndirectCalleeHelper,
|
| + kExprEnd,
|
| + kExprGetLocal, 1,
|
| + kExprCallFunction, kWasmThrowFunction,
|
| + ]);
|
| +
|
| + builder.addFunction("from_indirect_callee", kSig_i_i)
|
| + .addBody([
|
| + kExprTry, kAstI32,
|
| + kExprGetLocal, 0,
|
| + kExprI32Const, 0,
|
| + kExprCallFunction, kFromIndirectCalleeHelper,
|
| + kExprI32Const, /*-1=*/ 127,
|
| + kExprCatch, 1,
|
| + kExprGetLocal, 1,
|
| + kExprEnd
|
| + ])
|
| + .addLocals({i32_count: 1})
|
| + .exportFunc();
|
| +
|
| + // Scenario 4: Catches an exception raised in JS.
|
| + builder.addFunction("from_js", kSig_i_i)
|
| + .addBody([
|
| + kExprTry, kAstI32,
|
| + kExprGetLocal, 0,
|
| + kExprCallFunction, kJSThrowI,
|
| + kExprI32Const, /*-1=*/ 127,
|
| + kExprCatch, 1,
|
| + kExprGetLocal, 1,
|
| + kExprEnd,
|
| + ])
|
| + .addLocals({i32_count: 1})
|
| + .exportFunc();
|
| +
|
| + // Scenario 5: Does not catch an exception raised in JS if it is not a
|
| + // number.
|
| + builder.addFunction("string_from_js", kSig_v_v)
|
| + .addBody([
|
| + kExprCallFunction, kJSThrowString
|
| + ])
|
| + .exportFunc();
|
| +
|
| + builder.addFunction("fp_from_js", kSig_v_v)
|
| + .addBody([
|
| + kExprCallFunction, kJSThrowFP
|
| + ])
|
| + .exportFunc();
|
| +
|
| + builder.addFunction("large_from_js", kSig_v_v)
|
| + .addBody([
|
| + kExprCallFunction, kJSThrowLarge
|
| + ])
|
| + .exportFunc();
|
| +
|
| + builder.addFunction("undefined_from_js", kSig_v_v)
|
| + .addBody([
|
| + kExprCallFunction, kJSThrowUndefined
|
| + ])
|
| + .exportFunc();
|
| +
|
| + return builder.instantiate({
|
| + throw_i: throw_value,
|
| + throw_string: throw_string,
|
| + throw_fp: throw_fp,
|
| + throw_large, throw_large,
|
| + throw_undefined: throw_undefined
|
| + });
|
| +})();
|
| +
|
| +// Check the test_catch exists.
|
| +assertFalse(test_catch === undefined);
|
| +assertFalse(test_catch === null);
|
| +assertFalse(test_catch === 0);
|
| +assertEquals("object", typeof test_catch.exports);
|
| +assertEquals("function", typeof test_catch.exports.same_scope);
|
| +assertEquals("function", typeof test_catch.exports.same_scope_ignore);
|
| +assertEquals("function", typeof test_catch.exports.same_scope_multiple);
|
| +assertEquals("function", typeof test_catch.exports.from_direct_callee);
|
| +assertEquals("function", typeof test_catch.exports.from_indirect_callee);
|
| +assertEquals("function", typeof test_catch.exports.from_js);
|
| +assertEquals("function", typeof test_catch.exports.string_from_js);
|
| +
|
| +assertEquals(63, test_catch.exports.same_scope(0));
|
| +assertEquals(1024, test_catch.exports.same_scope(1024));
|
| +assertEquals(-3, test_catch.exports.same_scope(-3));
|
| +assertEquals(-1, test_catch.exports.same_scope_ignore(-1));
|
| +assertEquals(1, test_catch.exports.same_scope_ignore(1));
|
| +assertEquals(0x7FFFFFFF, test_catch.exports.same_scope_ignore(0x7FFFFFFF));
|
| +assertEquals(1024, test_catch.exports.same_scope_ignore(1024));
|
| +assertEquals(-1, test_catch.exports.same_scope_ignore(-1));
|
| +assertEquals(293, test_catch.exports.same_scope_multiple(1));
|
| +assertEquals(298, test_catch.exports.same_scope_multiple(2));
|
| +assertEquals(338, test_catch.exports.same_scope_multiple(3));
|
| +assertEquals(146, test_catch.exports.same_scope_multiple(0));
|
| +assertEquals(-10024, test_catch.exports.from_direct_callee(-10024));
|
| +assertEquals(3334333, test_catch.exports.from_direct_callee(3334333));
|
| +assertEquals(-1, test_catch.exports.from_direct_callee(0xFFFFFFFF));
|
| +assertEquals(0x7FFFFFFF, test_catch.exports.from_direct_callee(0x7FFFFFFF));
|
| +assertEquals(-10, test_catch.exports.from_indirect_callee(10));
|
| +assertEquals(-77, test_catch.exports.from_indirect_callee(77));
|
| +assertEquals(10, test_catch.exports.from_js(10));
|
| +assertEquals(-10, test_catch.exports.from_js(-10));
|
| +
|
| +assertThrowsEquals(test_catch.exports.string_from_js, "use wasm;");
|
| +assertThrowsEquals(test_catch.exports.large_from_js, 1e+28);
|
| +assertThrowsEquals(test_catch.exports.undefined_from_js, undefined);
|
|
|