diff options
Diffstat (limited to 'deps/v8/test/mjsunit/wasm/exceptions.js')
-rw-r--r-- | deps/v8/test/mjsunit/wasm/exceptions.js | 930 |
1 files changed, 413 insertions, 517 deletions
diff --git a/deps/v8/test/mjsunit/wasm/exceptions.js b/deps/v8/test/mjsunit/wasm/exceptions.js index 74d8e7dfb5..d165c8742d 100644 --- a/deps/v8/test/mjsunit/wasm/exceptions.js +++ b/deps/v8/test/mjsunit/wasm/exceptions.js @@ -1,84 +1,110 @@ -// Copyright 2015 the V8 project authors. All rights reserved. +// Copyright 2018 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --expose-wasm --experimental-wasm-eh +// Flags: --expose-wasm --experimental-wasm-eh --allow-natives-syntax load("test/mjsunit/wasm/wasm-constants.js"); load("test/mjsunit/wasm/wasm-module-builder.js"); -// The following method doesn't attempt to catch an raised exception. -var test_throw = (function () { - var builder = new WasmModuleBuilder(); +function assertWasmThrows(instance, runtime_id, values, code) { + try { + if (typeof code === 'function') { + code(); + } else { + eval(code); + } + } catch (e) { + assertInstanceof(e, WebAssembly.RuntimeError); + var e_runtime_id = %GetWasmExceptionId(e, instance); + assertTrue(Number.isInteger(e_runtime_id)); + assertEquals(e_runtime_id, runtime_id); + var e_values = %GetWasmExceptionValues(e); + assertArrayEquals(values, e_values); + return; // Success. + } + throw new MjsUnitAssertionError('Did not throw expected <' + runtime_id + + '> with values: ' + values); +} + +// First we just test that "except_ref" local variables are allowed. +(function TestLocalExceptRef() { + let builder = new WasmModuleBuilder(); + builder.addFunction("push_and_drop_except_ref", kSig_v_v) + .addBody([ + kExprGetLocal, 0, + kExprDrop, + ]).addLocals({except_count: 1}).exportFunc(); + let instance = builder.instantiate(); - builder.addException(kSig_v_v); + assertDoesNotThrow(instance.exports.push_and_drop_except_ref); +})(); +// The following method doesn't attempt to catch an raised exception. +(function TestThrowSimple() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_v); builder.addFunction("throw_if_param_not_zero", kSig_i_i) .addBody([ kExprGetLocal, 0, kExprI32Const, 0, kExprI32Ne, kExprIf, kWasmStmt, - kExprThrow, 0, + kExprThrow, except, kExprEnd, kExprI32Const, 1 ]).exportFunc(); + let instance = builder.instantiate(); - return builder.instantiate(); + assertEquals(1, instance.exports.throw_if_param_not_zero(0)); + assertWasmThrows(instance, except, [], () => instance.exports.throw_if_param_not_zero(10)); + assertWasmThrows(instance, except, [], () => instance.exports.throw_if_param_not_zero(-1)); })(); -// 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_if_param_not_zero); +// Test that empty try/catch blocks work. +(function TestCatchEmptyBlocks() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_v); + builder.addFunction("catch_empty_try", kSig_v_v) + .addBody([ + kExprTry, kWasmStmt, + kExprCatch, except, + kExprEnd, + ]).exportFunc(); + let instance = builder.instantiate(); -// Test expected behavior of throws -assertEquals(1, test_throw.exports.throw_if_param_not_zero(0)); -assertWasmThrows(0, [], function() { test_throw.exports.throw_if_param_not_zero(10) }); -assertWasmThrows(0, [], function() { test_throw.exports.throw_if_param_not_zero(-1) }); + assertDoesNotThrow(instance.exports.catch_empty_try); +})(); // Now that we know throwing works, we test catching the exceptions we raise. -var test_catch = (function () { - var builder = new WasmModuleBuilder(); - - builder.addException(kSig_v_v); +(function TestCatchSimple() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_v); builder.addFunction("simple_throw_catch_to_0_1", kSig_i_i) .addBody([ kExprTry, kWasmI32, kExprGetLocal, 0, kExprI32Eqz, kExprIf, kWasmStmt, - kExprThrow, 0, + kExprThrow, except, kExprEnd, - kExprI32Const, 1, - kExprCatch, 0, - kExprI32Const, 0, + kExprI32Const, 42, + kExprCatch, except, + kExprI32Const, 23, kExprEnd ]).exportFunc(); + let instance = builder.instantiate(); - return builder.instantiate(); + assertEquals(23, instance.exports.simple_throw_catch_to_0_1(0)); + assertEquals(42, instance.exports.simple_throw_catch_to_0_1(1)); })(); -// 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.simple_throw_catch_to_0_1); - -// Test expected behavior of simple catch. -assertEquals(0, test_catch.exports.simple_throw_catch_to_0_1(0)); -assertEquals(1, test_catch.exports.simple_throw_catch_to_0_1(1)); - // Test that we can distinguish which exception was thrown. -var test_catch_2 = (function () { - var builder = new WasmModuleBuilder(); - - builder.addException(kSig_v_v); - builder.addException(kSig_v_v); - builder.addException(kSig_v_v); +(function TestCatchComplex() { + let builder = new WasmModuleBuilder(); + let except1 = builder.addException(kSig_v_v); + let except2 = builder.addException(kSig_v_v); + let except3 = builder.addException(kSig_v_v); builder.addFunction("catch_different_exceptions", kSig_i_i) .addBody([ kExprTry, kWasmI32, @@ -86,172 +112,122 @@ var test_catch_2 = (function () { kExprGetLocal, 0, kExprI32Eqz, kExprIf, kWasmStmt, - kExprThrow, 0, + kExprThrow, except1, kExprElse, kExprGetLocal, 0, kExprI32Const, 1, kExprI32Eq, kExprIf, kWasmStmt, - kExprThrow, 1, + kExprThrow, except2, kExprElse, - kExprThrow, 2, + kExprThrow, except3, kExprEnd, kExprEnd, kExprI32Const, 2, - kExprCatch, 0, + kExprCatch, except1, kExprI32Const, 3, kExprEnd, - kExprCatch, 1, + kExprCatch, except2, kExprI32Const, 4, kExprEnd ]).exportFunc(); - return builder.instantiate(); -})(); - -assertFalse(test_catch_2 === undefined); -assertFalse(test_catch_2 === null); -assertFalse(test_catch_2 === 0); -assertEquals("object", typeof test_catch_2.exports); -assertEquals("function", typeof test_catch_2.exports.catch_different_exceptions); + let instance = builder.instantiate(); -assertEquals(3, test_catch_2.exports.catch_different_exceptions(0)); -assertEquals(4, test_catch_2.exports.catch_different_exceptions(1)); -assertWasmThrows(2, [], function() { test_catch_2.exports.catch_different_exceptions(2) }); + assertEquals(3, instance.exports.catch_different_exceptions(0)); + assertEquals(4, instance.exports.catch_different_exceptions(1)); + assertWasmThrows(instance, except3, [], () => instance.exports.catch_different_exceptions(2)); +})(); // Test throwing an exception with multiple values. -var test_throw_1_2 = (function() { - var builder = new WasmModuleBuilder(); - builder.addException(kSig_v_ii); +(function TestThrowMultipleValues() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_ii); builder.addFunction("throw_1_2", kSig_v_v) .addBody([ kExprI32Const, 1, kExprI32Const, 2, - kExprThrow, 0, + kExprThrow, except, ]).exportFunc(); + let instance = builder.instantiate(); - return builder.instantiate(); + assertWasmThrows(instance, except, [0, 1, 0, 2], () => instance.exports.throw_1_2()); })(); -assertFalse(test_throw_1_2 === undefined); -assertFalse(test_throw_1_2 === null); -assertFalse(test_throw_1_2 === 0); -assertEquals("object", typeof test_throw_1_2.exports); -assertEquals("function", typeof test_throw_1_2.exports.throw_1_2); - -assertWasmThrows(0, [0, 1, 0, 2], function() { test_throw_1_2.exports.throw_1_2(); }); - // Test throwing/catching the i32 parameter value. -var test_throw_catch_param_i = (function () { - var builder = new WasmModuleBuilder(); - builder.addException(kSig_v_i); +(function TestThrowCatchParamI() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_i); builder.addFunction("throw_catch_param", kSig_i_i) .addBody([ kExprTry, kWasmI32, kExprGetLocal, 0, - kExprThrow, 0, + kExprThrow, except, kExprI32Const, 2, - kExprCatch, 0, + kExprCatch, except, kExprReturn, kExprEnd, ]).exportFunc(); + let instance = builder.instantiate(); - return builder.instantiate(); + assertEquals(0, instance.exports.throw_catch_param(0)); + assertEquals(1, instance.exports.throw_catch_param(1)); + assertEquals(10, instance.exports.throw_catch_param(10)); })(); -assertFalse(test_throw_catch_param_i === undefined); -assertFalse(test_throw_catch_param_i === null); -assertFalse(test_throw_catch_param_i === 0); -assertEquals("object", typeof test_throw_catch_param_i.exports); -assertEquals("function", - typeof test_throw_catch_param_i.exports.throw_catch_param); - -assertEquals(0, test_throw_catch_param_i.exports.throw_catch_param(0)); -assertEquals(1, test_throw_catch_param_i.exports.throw_catch_param(1)); -assertEquals(10, test_throw_catch_param_i.exports.throw_catch_param(10)); - // Test the encoding of a thrown exception with an integer exception. - -var test_throw_param_i = (function () { - var builder = new WasmModuleBuilder(); - builder.addException(kSig_v_i); +(function TestThrowParamI() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_i); builder.addFunction("throw_param", kSig_v_i) .addBody([ kExprGetLocal, 0, - kExprThrow, 0, + kExprThrow, except, ]).exportFunc(); + let instance = builder.instantiate(); - return builder.instantiate(); + assertWasmThrows(instance, except, [0, 5], () => instance.exports.throw_param(5)); + assertWasmThrows(instance, except, [6, 31026], () => instance.exports.throw_param(424242)); })(); -assertFalse(test_throw_param_i === undefined); -assertFalse(test_throw_param_i === null); -assertFalse(test_throw_param_i === 0); -assertEquals("object", typeof test_throw_param_i.exports); -assertEquals("function", - typeof test_throw_param_i.exports.throw_param); - -assertWasmThrows(0, [0, 5], function() { test_throw_param_i.exports.throw_param(5); }); -assertWasmThrows(0, [6, 31026], - function() { test_throw_param_i.exports.throw_param(424242); }); - // Test throwing/catching the f32 parameter value. -var test_throw_catch_param_f = (function () { - var builder = new WasmModuleBuilder(); - builder.addException(kSig_v_f); +(function TestThrowCatchParamF() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_f); builder.addFunction("throw_catch_param", kSig_f_f) .addBody([ kExprTry, kWasmF32, kExprGetLocal, 0, - kExprThrow, 0, + kExprThrow, except, kExprF32Const, 0, 0, 0, 0, - kExprCatch, 0, + kExprCatch, except, kExprReturn, kExprEnd, ]).exportFunc(); + let instance = builder.instantiate(); - return builder.instantiate(); + assertEquals(5.0, instance.exports.throw_catch_param(5.0)); + assertEquals(10.5, instance.exports.throw_catch_param(10.5)); })(); -assertFalse(test_throw_catch_param_f === undefined); -assertFalse(test_throw_catch_param_f === null); -assertFalse(test_throw_catch_param_f === 0); -assertEquals("object", typeof test_throw_catch_param_f.exports); -assertEquals("function", - typeof test_throw_catch_param_f.exports.throw_catch_param); - -assertEquals(5.0, test_throw_catch_param_f.exports.throw_catch_param(5.0)); -assertEquals(10.5, test_throw_catch_param_f.exports.throw_catch_param(10.5)); - // Test the encoding of a thrown exception with a float value. - -var test_throw_param_f = (function () { - var builder = new WasmModuleBuilder(); - builder.addException(kSig_v_f); +(function TestThrowParamF() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_f); builder.addFunction("throw_param", kSig_v_f) .addBody([ kExprGetLocal, 0, - kExprThrow, 0, + kExprThrow, except, ]).exportFunc(); + let instance = builder.instantiate(); - return builder.instantiate(); + assertWasmThrows(instance, except, [16544, 0], () => instance.exports.throw_param(5.0)); + assertWasmThrows(instance, except, [16680, 0], () => instance.exports.throw_param(10.5)); })(); -assertFalse(test_throw_param_f === undefined); -assertFalse(test_throw_param_f === null); -assertFalse(test_throw_param_f === 0); -assertEquals("object", typeof test_throw_param_f.exports); -assertEquals("function", - typeof test_throw_param_f.exports.throw_param); - -assertWasmThrows(0, [16544, 0], - function() { test_throw_param_f.exports.throw_param(5.0); }); -assertWasmThrows(0, [16680, 0], - function() { test_throw_param_f.exports.throw_param(10.5); }); - // Test throwing/catching an I64 value -var test_throw_catch_param_l = (function () { - var builder = new WasmModuleBuilder(); - builder.addException(kSig_v_l); +(function TestThrowCatchParamL() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_l); builder.addFunction("throw_catch_param", kSig_i_i) .addBody([ kExprGetLocal, 0, @@ -259,9 +235,9 @@ var test_throw_catch_param_l = (function () { kExprSetLocal, 1, kExprTry, kWasmI32, kExprGetLocal, 1, - kExprThrow, 0, + kExprThrow, except, kExprI32Const, 2, - kExprCatch, 0, + kExprCatch, except, kExprGetLocal, 1, kExprI64Eq, kExprIf, kWasmI32, @@ -273,26 +249,17 @@ var test_throw_catch_param_l = (function () { kExprReturn, kExprEnd, ]).addLocals({i64_count: 1}).exportFunc(); + let instance = builder.instantiate(); - return builder.instantiate(); + assertEquals(1, instance.exports.throw_catch_param(5)); + assertEquals(1, instance.exports.throw_catch_param(0)); + assertEquals(1, instance.exports.throw_catch_param(-1)); })(); -assertFalse(test_throw_catch_param_l === undefined); -assertFalse(test_throw_catch_param_l === null); -assertFalse(test_throw_catch_param_l === 0); -assertEquals("object", typeof test_throw_catch_param_l.exports); -assertEquals("function", - typeof test_throw_catch_param_l.exports.throw_catch_param); - -assertEquals(1, test_throw_catch_param_l.exports.throw_catch_param(5)); -assertEquals(1, test_throw_catch_param_l.exports.throw_catch_param(0)); -assertEquals(1, test_throw_catch_param_l.exports.throw_catch_param(-1)); - // Test the encoding of a thrown exception with an I64 value. - -var test_throw_param_l = (function () { - var builder = new WasmModuleBuilder(); - builder.addException(kSig_v_l); +(function TestThrowParamL() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_l); builder.addFunction("throw_param", kSig_v_ii) .addBody([ kExprGetLocal, 0, @@ -302,428 +269,357 @@ var test_throw_param_l = (function () { kExprGetLocal, 1, kExprI64UConvertI32, kExprI64Ior, - kExprThrow, 0 + kExprThrow, except, ]).exportFunc(); + let instance = builder.instantiate(); - return builder.instantiate(); + assertWasmThrows(instance, except, [0, 10, 0, 5], () => instance.exports.throw_param(10, 5)); + assertWasmThrows(instance, except, [65535, 65535, 0, 13], () => instance.exports.throw_param(-1, 13)); })(); -assertFalse(test_throw_param_l === undefined); -assertFalse(test_throw_param_l === null); -assertFalse(test_throw_param_l === 0); -assertEquals("object", typeof test_throw_param_l.exports); -assertEquals("function", - typeof test_throw_param_l.exports.throw_param); - -assertWasmThrows(0, [0, 10, 0, 5], - function() { test_throw_param_l.exports.throw_param(10, 5); }); -assertWasmThrows(0, [65535, 65535, 0, 13], - function() { test_throw_param_l.exports.throw_param(-1, 13); }); - // Test throwing/catching the F64 parameter value -var test_throw_catch_param_d = (function () { - var builder = new WasmModuleBuilder(); - builder.addException(kSig_v_d); +(function TestThrowCatchParamD() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_d); builder.addFunction("throw_catch_param", kSig_d_d) .addBody([ kExprTry, kWasmF64, kExprGetLocal, 0, - kExprThrow, 0, + kExprThrow, except, kExprF64Const, 0, 0, 0, 0, 0, 0, 0, 0, - kExprCatch, 0, + kExprCatch, except, kExprReturn, kExprEnd, ]).exportFunc(); + let instance = builder.instantiate(); - return builder.instantiate(); + assertEquals(5.0, instance.exports.throw_catch_param(5.0)); + assertEquals(10.5, instance.exports.throw_catch_param(10.5)); })(); -assertFalse(test_throw_catch_param_d === undefined); -assertFalse(test_throw_catch_param_d === null); -assertFalse(test_throw_catch_param_d === 0); -assertEquals("object", typeof test_throw_catch_param_d.exports); -assertEquals("function", - typeof test_throw_catch_param_d.exports.throw_catch_param); - -assertEquals(5.0, test_throw_catch_param_d.exports.throw_catch_param(5.0)); -assertEquals(10.5, test_throw_catch_param_d.exports.throw_catch_param(10.5)); - // Test the encoding of a thrown exception with an f64 value. - -var test_throw_param_d = (function () { - var builder = new WasmModuleBuilder(); - builder.addException(kSig_v_d); +(function TestThrowParamD() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_d); builder.addFunction("throw_param", kSig_v_f) .addBody([ kExprGetLocal, 0, kExprF64ConvertF32, - kExprThrow, 0 + kExprThrow, except, ]).exportFunc(); + let instance = builder.instantiate(); - return builder.instantiate(); + assertWasmThrows(instance, except, [16404, 0, 0, 0], () => instance.exports.throw_param(5.0)); + assertWasmThrows(instance, except, [16739, 4816, 0, 0], () => instance.exports.throw_param(10000000.5)); })(); -assertFalse(test_throw_param_d === undefined); -assertFalse(test_throw_param_d === null); -assertFalse(test_throw_param_d === 0); -assertEquals("object", typeof test_throw_param_d.exports); -assertEquals("function", - typeof test_throw_param_d.exports.throw_param); - -assertWasmThrows(0, [16404, 0, 0, 0], - function() { test_throw_param_d.exports.throw_param(5.0); }); -assertWasmThrows(0, [16739, 4816, 0, 0], - function() { test_throw_param_d.exports.throw_param(10000000.5); }); - -/* TODO(kschimpf) Convert these tests to work for the proposed exceptions. - -// The following methods do not attempt to catch the exception they raise. -var test_throw = (function () { - var builder = new WasmModuleBuilder(); - +// Test the encoding of a computed parameter value. +(function TestThrowParamComputed() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_i); builder.addFunction("throw_expr_with_params", kSig_v_ddi) - .addBody([ - // p2 * (p0 + min(p0, p1))|0 - 20 - kExprGetLocal, 2, - kExprGetLocal, 0, - kExprGetLocal, 0, - kExprGetLocal, 1, - kExprF64Min, - kExprF64Add, - kExprI32SConvertF64, - kExprI32Mul, - kExprI32Const, 20, - kExprI32Sub, - kExprThrow, - ]) - .exportFunc() - - return builder.instantiate(); + .addBody([ + // p2 * (p0 + min(p0, p1))|0 - 20 + kExprGetLocal, 2, + kExprGetLocal, 0, + kExprGetLocal, 0, + kExprGetLocal, 1, + kExprF64Min, + kExprF64Add, + kExprI32SConvertF64, + kExprI32Mul, + kExprI32Const, 20, + kExprI32Sub, + kExprThrow, except, + ]).exportFunc() + let instance = builder.instantiate(); + + assertWasmThrows(instance, except, [65535, 65536-8], () => instance.exports.throw_expr_with_params(1.5, 2.5, 4)); + assertWasmThrows(instance, except, [0, 12], () => instance.exports.throw_expr_with_params(5.7, 2.5, 4)); })(); -// 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_expr_with_params); - -assertEquals(1, test_throw.exports.throw_param_if_not_zero(0)); -assertWasmThrows( - -8, function() { test_throw.exports.throw_expr_with_params(1.5, 2.5, 4); }); -assertWasmThrows( - 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); +// Now that we know catching works locally, we test catching exceptions that +// cross function boundaries and/or raised by JavaScript. +(function TestCatchCrossFunctions() { + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_i); + + // Helper function for throwing from JS. It is imported by the Wasm module + // as throw_i. + function throw_value(value) { + throw value; + } + let sig_index = builder.addType(kSig_v_i); + let 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); + let kJSThrowString = builder.addImport("", "throw_string", sig_index); + + // Helper function that throws undefined. Wasm should not catch it. + function throw_undefined() { + throw undefined; + } + let kJSThrowUndefined = builder.addImport("", "throw_undefined", sig_index); + + // Helper function that throws an fp. Wasm should not catch it. + function throw_fp() { + throw 10.5; + } + let 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; + } + let kJSThrowLarge = builder.addImport("", "throw_large", sig_index); + + // Helper function for throwing from WebAssembly. + let kWasmThrowFunction = + builder.addFunction("throw", kSig_v_i) + .addBody([ + kExprGetLocal, 0, + kExprThrow, except, + ]) + .index; - // Helper function for throwing from WebAssembly. - var kWasmThrowFunction = - builder.addFunction("throw", kSig_v_i) - .addBody([ + // 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, kWasmI32, + kExprGetLocal, 0, + kExprI32Const, 0, + kExprI32Ne, + kExprIf, kWasmStmt, kExprGetLocal, 0, - kExprThrow - ]) - .index; + kExprThrow, except, + kExprUnreachable, + kExprEnd, + kExprI32Const, 63, + kExprCatch, except, + kExprEnd + ]) + .exportFunc(); - // 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([ + builder.addFunction("same_scope_ignore", kSig_i_i) + .addBody([ kExprTry, kWasmI32, kExprGetLocal, 0, - kExprI32Const, 0, - kExprI32Ne, - kExprIf, kWasmStmt, - 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, kWasmI32, - 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([ + kExprThrow, except, + kExprUnreachable, + kExprCatch, except, + kExprEnd, + ]) + .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, kWasmI32, kExprTry, kWasmI32, kExprTry, kWasmI32, - kExprTry, kWasmI32, - kExprGetLocal, 0, - kExprI32Const, 1, - kExprI32Eq, - kExprIf, kWasmStmt, - kExprI32Const, 1, - kExprThrow, - kExprUnreachable, - kExprEnd, - kExprI32Const, 2, - kExprCatch, 1, - kExprGetLocal, 1, - kExprI32Const, 4, - kExprI32Ior, - kExprThrow, - kExprUnreachable, - kExprEnd, - kExprTeeLocal, 2, kExprGetLocal, 0, - kExprI32Const, 2, + kExprI32Const, 1, kExprI32Eq, kExprIf, kWasmStmt, - kExprGetLocal, 2, - kExprI32Const, 8, - kExprI32Ior, - kExprThrow, + kExprI32Const, 1, + kExprThrow, except, kExprUnreachable, kExprEnd, - kExprI32Const, 16, - kExprI32Ior, - kExprCatch, 1, - kExprGetLocal, 1, - kExprI32Const, 32, + kExprI32Const, 2, + kExprCatch, except, + kExprI32Const, 4, kExprI32Ior, - kExprThrow, + kExprThrow, except, kExprUnreachable, kExprEnd, - kExprTeeLocal, 2, + kExprTeeLocal, 1, kExprGetLocal, 0, - kExprI32Const, 3, + kExprI32Const, 2, kExprI32Eq, kExprIf, kWasmStmt, - kExprGetLocal, 2, - kExprI32Const, / *64=* / 192, 0, + kExprGetLocal, 1, + kExprI32Const, 8, kExprI32Ior, - kExprThrow, + kExprThrow, except, kExprUnreachable, kExprEnd, - kExprI32Const, / *128=* / 128, 1, + kExprI32Const, 16, kExprI32Ior, - kExprCatch, 1, + kExprCatch, except, + kExprI32Const, 32, + kExprI32Ior, + kExprThrow, except, + kExprUnreachable, + kExprEnd, + kExprTeeLocal, 1, + kExprGetLocal, 0, + kExprI32Const, 3, + kExprI32Eq, + kExprIf, kWasmStmt, kExprGetLocal, 1, - kExprI32Const, / *256=* / 128, 2, + kExprI32Const, /*64=*/ 192, 0, kExprI32Ior, + kExprThrow, except, + kExprUnreachable, kExprEnd, - ]) - .addLocals({i32_count: 2}) - .exportFunc(); + kExprI32Const, /*128=*/ 128, 1, + kExprI32Ior, + kExprCatch, except, + kExprI32Const, /*256=*/ 128, 2, + kExprI32Ior, + kExprEnd, + ]) + .addLocals({i32_count: 1}) + .exportFunc(); - // Scenario 2: Catches an exception raised from the direct callee. - var kFromDirectCallee = - builder.addFunction("from_direct_callee", kSig_i_i) - .addBody([ - kExprTry, kWasmI32, - 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([ + // Scenario 2: Catches an exception raised from the direct callee. + builder.addFunction("from_direct_callee", kSig_i_i) + .addBody([ + kExprTry, kWasmI32, kExprGetLocal, 0, - kExprI32Const, 0, - kExprI32GtS, - kExprIf, kWasmStmt, - kExprGetLocal, 0, - kExprI32Const, 1, - kExprI32Sub, - kExprGetLocal, 1, - kExprI32Const, 1, - kExprI32Sub, - kExprCallFunction, kFromIndirectCalleeHelper, - kExprEnd, - kExprGetLocal, 1, kExprCallFunction, kWasmThrowFunction, - ]); + kExprUnreachable, + kExprCatch, except, + kExprEnd, + ]) + .exportFunc(); - builder.addFunction("from_indirect_callee", kSig_i_i) - .addBody([ - kExprTry, kWasmI32, - kExprGetLocal, 0, - kExprI32Const, 0, - kExprCallFunction, kFromIndirectCalleeHelper, - kExprI32Const, / *-1=* / 127, - kExprCatch, 1, - kExprGetLocal, 1, - kExprEnd - ]) - .addLocals({i32_count: 1}) - .exportFunc(); + // Scenario 3: Catches an exception raised from an indirect callee. + let sig_v_i = builder.addType(kSig_v_i); + builder.appendToTable([kWasmThrowFunction, kWasmThrowFunction]); + builder.addFunction("from_indirect_callee", kSig_i_ii) + .addBody([ + kExprTry, kWasmI32, + kExprGetLocal, 0, + kExprGetLocal, 1, + kExprCallIndirect, sig_v_i, kTableZero, + kExprUnreachable, + kExprCatch, except, + kExprEnd + ]) + .exportFunc(); - // Scenario 4: Catches an exception raised in JS. - builder.addFunction("from_js", kSig_i_i) - .addBody([ - kExprTry, kWasmI32, - kExprGetLocal, 0, - kExprCallFunction, kJSThrowI, - kExprI32Const, / *-1=* / 127, - kExprCatch, 1, - kExprGetLocal, 1, - kExprEnd, - ]) - .addLocals({i32_count: 1}) - .exportFunc(); + // Scenario 4: Does not catch an exception raised in JS, even if primitive + // values are being used as exceptions. + builder.addFunction("i_from_js", kSig_i_i) + .addBody([ + kExprTry, kWasmI32, + kExprGetLocal, 0, + kExprCallFunction, kJSThrowI, + kExprUnreachable, + kExprCatch, except, + kExprUnreachable, + kExprEnd, + ]) + .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("string_from_js", kSig_v_v) + .addBody([ + kExprTry, kWasmStmt, + kExprCallFunction, kJSThrowString, + kExprCatch, except, + kExprUnreachable, + kExprEnd, + ]) + .exportFunc(); - builder.addFunction("fp_from_js", kSig_v_v) - .addBody([ - kExprCallFunction, kJSThrowFP - ]) - .exportFunc(); + builder.addFunction("fp_from_js", kSig_v_v) + .addBody([ + kExprTry, kWasmStmt, + kExprCallFunction, kJSThrowFP, + kExprCatch, except, + kExprUnreachable, + kExprEnd, + ]) + .exportFunc(); - builder.addFunction("large_from_js", kSig_v_v) - .addBody([ - kExprCallFunction, kJSThrowLarge - ]) - .exportFunc(); + builder.addFunction("large_from_js", kSig_v_v) + .addBody([ + kExprTry, kWasmStmt, + kExprCallFunction, kJSThrowLarge, + kExprCatch, except, + kExprUnreachable, + kExprEnd, + ]) + .exportFunc(); - builder.addFunction("undefined_from_js", kSig_v_v) - .addBody([ - kExprCallFunction, kJSThrowUndefined - ]) - .exportFunc(); + builder.addFunction("undefined_from_js", kSig_v_v) + .addBody([ + kExprTry, kWasmStmt, + kExprCallFunction, kJSThrowUndefined, + kExprCatch, except, + kExprUnreachable, + kExprEnd, + ]) + .exportFunc(); - return builder.instantiate({"": { + let instance = 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); -*/ + assertEquals(63, instance.exports.same_scope(0)); + assertEquals(1024, instance.exports.same_scope(1024)); + assertEquals(-3, instance.exports.same_scope(-3)); + assertEquals(-1, instance.exports.same_scope_ignore(-1)); + assertEquals(1, instance.exports.same_scope_ignore(1)); + assertEquals(0x7FFFFFFF, instance.exports.same_scope_ignore(0x7FFFFFFF)); + assertEquals(1024, instance.exports.same_scope_ignore(1024)); + assertEquals(-1, instance.exports.same_scope_ignore(-1)); + assertEquals(293, instance.exports.same_scope_multiple(1)); + assertEquals(298, instance.exports.same_scope_multiple(2)); + assertEquals(338, instance.exports.same_scope_multiple(3)); + assertEquals(146, instance.exports.same_scope_multiple(0)); + assertEquals(-10024, instance.exports.from_direct_callee(-10024)); + assertEquals(3334333, instance.exports.from_direct_callee(3334333)); + assertEquals(-1, instance.exports.from_direct_callee(0xFFFFFFFF)); + assertEquals(0x7FFFFFFF, instance.exports.from_direct_callee(0x7FFFFFFF)); + assertEquals(10, instance.exports.from_indirect_callee(10, 0)); + assertEquals(77, instance.exports.from_indirect_callee(77, 1)); + + assertThrowsEquals(() => instance.exports.i_from_js(10), 10); + assertThrowsEquals(() => instance.exports.i_from_js(-10), -10); + assertThrowsEquals(instance.exports.string_from_js, "use wasm"); + assertThrowsEquals(instance.exports.fp_from_js, 10.5); + assertThrowsEquals(instance.exports.large_from_js, 1e+28); + assertThrowsEquals(instance.exports.undefined_from_js, undefined); +})(); |