| // Copyright 2019 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 --allow-natives-syntax |
| |
| // Note that this test does not pass --experimental-wasm-anyref on purpose so |
| // that we make sure the two flags can be controlled separately/independently. |
| |
| load("test/mjsunit/wasm/wasm-module-builder.js"); |
| |
| // First we just test that "except_ref" global variables are allowed. |
| (function TestGlobalExceptRefSupported() { |
| print(arguments.callee.name); |
| let builder = new WasmModuleBuilder(); |
| let g = builder.addGlobal(kWasmExceptRef); |
| builder.addFunction("push_and_drop_except_ref", kSig_v_v) |
| .addBody([ |
| kExprGetGlobal, g.index, |
| kExprDrop, |
| ]).exportFunc(); |
| let instance = builder.instantiate(); |
| |
| assertDoesNotThrow(instance.exports.push_and_drop_except_ref); |
| })(); |
| |
| // Test default value that global "except_ref" variables are initialized with. |
| (function TestGlobalExceptRefDefaultValue() { |
| print(arguments.callee.name); |
| let builder = new WasmModuleBuilder(); |
| let g = builder.addGlobal(kWasmExceptRef); |
| builder.addFunction('push_and_return_except_ref', kSig_e_v) |
| .addBody([kExprGetGlobal, g.index]) |
| .exportFunc(); |
| let instance = builder.instantiate(); |
| |
| assertEquals(null, instance.exports.push_and_return_except_ref()); |
| })(); |
| |
| // Test storing a caught exception into an exported mutable "except_ref" global. |
| (function TestGlobalExceptRefSetCaught() { |
| print(arguments.callee.name); |
| let builder = new WasmModuleBuilder(); |
| let except = builder.addException(kSig_v_i); |
| let g = builder.addGlobal(kWasmExceptRef, true).exportAs("exn"); |
| builder.addFunction('catch_and_set_except_ref', kSig_v_i) |
| .addBody([ |
| kExprTry, kWasmStmt, |
| kExprGetLocal, 0, |
| kExprThrow, except, |
| kExprCatch, |
| kExprSetGlobal, g.index, |
| kExprEnd, |
| ]).exportFunc(); |
| let instance = builder.instantiate(); |
| |
| assertDoesNotThrow(() => instance.exports.catch_and_set_except_ref(23)); |
| let exception = instance.exports.exn.value; // Exported mutable global. |
| assertInstanceof(exception, WebAssembly.RuntimeError); |
| assertEquals(except, %GetWasmExceptionId(exception, instance)); |
| })(); |
| |
| // Test storing a parameter into an exported mutable "except_ref" global. |
| (function TestGlobalExceptRefSetParameter() { |
| print(arguments.callee.name); |
| let builder = new WasmModuleBuilder(); |
| let g = builder.addGlobal(kWasmExceptRef, true).exportAs("exn"); |
| builder.addFunction('set_param_except_ref', kSig_v_e) |
| .addBody([ |
| kExprTry, kWasmStmt, |
| kExprGetLocal, 0, |
| kExprRethrow, |
| kExprCatch, |
| kExprSetGlobal, g.index, |
| kExprEnd, |
| ]).exportFunc(); |
| let exception = "my fancy exception"; |
| let instance = builder.instantiate(); |
| |
| assertDoesNotThrow(() => instance.exports.set_param_except_ref(exception)); |
| assertEquals(exception, instance.exports.exn.value); |
| })(); |
| |
| // Test loading an imported "except_ref" global and re-throwing the exception. |
| (function TestGlobalExceptRefGetImportedAndRethrow() { |
| print(arguments.callee.name); |
| let builder = new WasmModuleBuilder(); |
| let g_index = builder.addImportedGlobal("m", "exn", kWasmExceptRef); |
| builder.addFunction('rethrow_except_ref', kSig_v_v) |
| .addBody([ |
| kExprGetGlobal, g_index, |
| kExprRethrow, |
| ]).exportFunc(); |
| let exception = "my fancy exception"; |
| let instance = builder.instantiate({ "m": { "exn": exception }}); |
| |
| assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception); |
| })(); |
| |
| // Test loading an exported mutable "except_ref" being changed from the outside. |
| (function TestGlobalExceptRefGetExportedMutableAndRethrow() { |
| print(arguments.callee.name); |
| let builder = new WasmModuleBuilder(); |
| let g = builder.addGlobal(kWasmExceptRef, true).exportAs("exn"); |
| builder.addFunction('rethrow_except_ref', kSig_v_v) |
| .addBody([ |
| kExprGetGlobal, g.index, |
| kExprRethrow, |
| ]).exportFunc(); |
| let instance = builder.instantiate(); |
| |
| let exception1 = instance.exports.exn.value = "my fancy exception"; |
| assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception1); |
| let exception2 = instance.exports.exn.value = "an even fancier exception"; |
| assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception2); |
| })(); |
| |
| // TODO(mstarzinger): Add the following test once proposal makes it clear how |
| // far interaction with the mutable globals proposal is intended to go. |
| // Test loading an imported mutable "except_ref" being changed from the outside. |
| /*(function TestGlobalExceptRefGetImportedMutableAndRethrow() { |
| print(arguments.callee.name); |
| let builder = new WasmModuleBuilder(); |
| let g_index = builder.addImportedGlobal("m", "exn", kWasmExceptRef, true); |
| builder.addFunction('rethrow_except_ref', kSig_v_v) |
| .addBody([ |
| kExprGetGlobal, g_index, |
| kExprRethrow, |
| ]).exportFunc(); |
| let exception1 = "my fancy exception"; |
| let desc = { value: 'except_ref', mutable: true }; |
| let mutable_global = new WebAssembly.Global(desc, exception1); |
| let instance = builder.instantiate({ "m": { "exn": mutable_global }}); |
| |
| assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception1); |
| let exception2 = mutable_global.value = "an even fancier exception"; |
| assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception2); |
| })();*/ |