blob: f91132401e96559585d98cc3b704e99230c96fce [file] [log] [blame]
// 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: --experimental-wasm-eh --experimental-wasm-reftypes --allow-natives-syntax
load("test/mjsunit/wasm/wasm-module-builder.js");
load("test/mjsunit/wasm/exceptions-utils.js");
// Test the encoding of a thrown exception with a null-ref value.
(function TestThrowRefNull() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_r);
builder.addFunction("throw_null", kSig_v_v)
.addBody([
kExprRefNull, kWasmExternRef,
kExprThrow, except,
]).exportFunc();
let instance = builder.instantiate();
assertWasmThrows(instance, except, [null], () => instance.exports.throw_null());
})();
// Test throwing/catching the null-ref value.
(function TestThrowCatchRefNull() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_r);
builder.addFunction("throw_catch_null", kSig_i_i)
.addBody([
kExprTry, kWasmExternRef,
kExprLocalGet, 0,
kExprI32Eqz,
kExprIf, kWasmExternRef,
kExprRefNull, kWasmExternRef,
kExprThrow, except,
kExprElse,
kExprI32Const, 42,
kExprReturn,
kExprEnd,
kExprCatch,
kExprBrOnExn, 0, except,
kExprRethrow,
kExprEnd,
kExprRefIsNull,
kExprIf, kWasmI32,
kExprI32Const, 23,
kExprElse,
kExprUnreachable,
kExprEnd,
]).exportFunc();
let instance = builder.instantiate();
assertEquals(23, instance.exports.throw_catch_null(0));
assertEquals(42, instance.exports.throw_catch_null(1));
})();
// Test the encoding of a thrown exception with a reference type value.
(function TestThrowRefParam() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_r);
builder.addFunction("throw_param", kSig_v_r)
.addBody([
kExprLocalGet, 0,
kExprThrow, except,
]).exportFunc();
let instance = builder.instantiate();
let o = new Object();
assertWasmThrows(instance, except, [o], () => instance.exports.throw_param(o));
assertWasmThrows(instance, except, [1], () => instance.exports.throw_param(1));
assertWasmThrows(instance, except, [2.3], () => instance.exports.throw_param(2.3));
assertWasmThrows(instance, except, ["str"], () => instance.exports.throw_param("str"));
})();
// Test throwing/catching the reference type value.
(function TestThrowCatchRefParam() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_r);
builder.addFunction("throw_catch_param", kSig_r_r)
.addBody([
kExprTry, kWasmExternRef,
kExprLocalGet, 0,
kExprThrow, except,
kExprCatch,
kExprBrOnExn, 0, except,
kExprRethrow,
kExprEnd,
]).exportFunc();
let instance = builder.instantiate();
let o = new Object();
assertEquals(o, instance.exports.throw_catch_param(o));
assertEquals(1, instance.exports.throw_catch_param(1));
assertEquals(2.3, instance.exports.throw_catch_param(2.3));
assertEquals("str", instance.exports.throw_catch_param("str"));
})();
// Test throwing/catching a function reference type value.
(function TestThrowCatchAnyFunc() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_a);
builder.addFunction("throw_catch_local", kSig_a_v)
.addLocals(kWasmAnyFunc, 1)
.addBody([
kExprTry, kWasmAnyFunc,
kExprLocalGet, 0,
kExprThrow, except,
kExprCatch,
kExprBrOnExn, 0, except,
kExprRethrow,
kExprEnd,
]).exportFunc();
let instance = builder.instantiate();
assertEquals(null, instance.exports.throw_catch_local());
})();
// Test throwing/catching an encapsulated exception type value.
(function TestThrowCatchExnRef() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_e);
builder.addFunction("throw_catch_param", kSig_e_e)
.addBody([
kExprTry, kWasmExnRef,
kExprLocalGet, 0,
kExprThrow, except,
kExprCatch,
kExprBrOnExn, 0, except,
kExprRethrow,
kExprEnd,
]).exportFunc();
let instance = builder.instantiate();
let e = new Error("my encapsulated error");
assertEquals(e, instance.exports.throw_catch_param(e));
assertEquals(1, instance.exports.throw_catch_param(1));
assertEquals(2.3, instance.exports.throw_catch_param(2.3));
assertEquals("str", instance.exports.throw_catch_param("str"));
})();
// Test storing and loading to/from an exception type table.
(function TestTableExnRef() {
print(arguments.callee.name);
let kSig_e_i = makeSig([kWasmI32], [kWasmExnRef]);
let kSig_v_ie = makeSig([kWasmI32, kWasmExnRef], []);
let builder = new WasmModuleBuilder();
let table = builder.addTable(kWasmExnRef, 2).exportAs("table");
builder.addFunction("table_load", kSig_e_i)
.addBody([
kExprLocalGet, 0,
kExprTableGet, table.index
]).exportFunc();
builder.addFunction("table_store", kSig_v_ie)
.addBody([
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprTableSet, table.index
]).exportFunc();
let instance = builder.instantiate();
let e0 = new Error("my encapsulated error");
let e1 = new Error("my other encapsulated error");
assertNull(instance.exports.table_load(0));
assertNull(instance.exports.table_load(1));
assertNull(instance.exports.table.get(0));
assertNull(instance.exports.table.get(1));
instance.exports.table_store(0, e0);
assertSame(e0, instance.exports.table_load(0));
assertNull(instance.exports.table_load(1));
assertSame(e0, instance.exports.table.get(0));
assertNull(instance.exports.table.get(1));
instance.exports.table.set(1, e1);
assertSame(e0, instance.exports.table_load(0));
assertSame(e1, instance.exports.table_load(1));
assertSame(e0, instance.exports.table.get(0));
assertSame(e1, instance.exports.table.get(1));
})();
// 'br_on_exn' on a null-ref value should trap.
(function TestBrOnExnNullSimple() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_r);
builder.addFunction('br_on_exn_null', kSig_v_v)
.addBody([
kExprRefNull, kWasmExnRef,
kExprBrOnExn, 0, except,
kExprDrop
]).exportFunc();
let instance = builder.instantiate();
assertTraps(kTrapBrOnExnNull, () => instance.exports.br_on_exn_null());
})();
(function TestBrOnExnNullFromJS() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_i);
let imp = builder.addImport('imp', 'ort', kSig_i_i);
let kConstant0 = 11;
let kNoMatch = 13;
builder.addFunction('call_import', kSig_i_i)
.addBody([
kExprTry, kWasmI32,
kExprLocalGet, 0,
kExprCallFunction, imp,
kExprCatch,
kExprBrOnExn, 0, except,
kExprDrop,
kExprI32Const, kNoMatch,
kExprEnd
]).exportFunc();
let instance;
function js_import(i) {
if (i == 0) return kConstant0; // Will return kConstant0.
if (i == 1) throw new Error('1'); // Will not match.
if (i == 2) throw null; // Will trap.
throw undefined; // Will not match.
}
instance = builder.instantiate({imp: {ort: js_import}});
assertEquals(kConstant0, instance.exports.call_import(0));
assertEquals(kNoMatch, instance.exports.call_import(1));
assertTraps(kTrapBrOnExnNull, () => instance.exports.call_import(2));
assertEquals(kNoMatch, instance.exports.call_import(3));
})();
// 'rethrow' on a null-ref value should trap.
(function TestRethrowNullSimple() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_r);
builder.addFunction('rethrow_null', kSig_v_v)
.addBody([
kExprRefNull, kWasmExnRef,
kExprRethrow
]).exportFunc();
let instance = builder.instantiate();
assertTraps(kTrapRethrowNull, () => instance.exports.rethrow_null());
})();
(function TestRethrowNullFromJS() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_i);
let imp = builder.addImport('imp', 'ort', kSig_i_i);
let kSuccess = 11;
builder.addFunction('call_import', kSig_i_i)
.addBody([
kExprTry, kWasmI32,
kExprLocalGet, 0,
kExprCallFunction, imp,
kExprCatch,
kExprRethrow,
kExprEnd
]).exportFunc();
let instance;
function js_import(i) {
if (i == 0) return kSuccess; // Will return kSuccess.
if (i == 1) throw new Error('1'); // Will rethrow.
if (i == 2) throw null; // Will trap.
throw undefined; // Will rethrow.
}
instance = builder.instantiate({imp: {ort: js_import}});
assertEquals(kSuccess, instance.exports.call_import(0));
assertThrows(() => instance.exports.call_import(1), Error, '1');
assertTraps(kTrapRethrowNull, () => instance.exports.call_import(2));
assertThrowsEquals(() => instance.exports.call_import(3), undefined);
})();