summaryrefslogtreecommitdiff
path: root/deps/v8/test/mjsunit/wasm/exceptions.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/mjsunit/wasm/exceptions.js')
-rw-r--r--deps/v8/test/mjsunit/wasm/exceptions.js930
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);
+})();