diff --git a/src/wasm/function-body-decoder-impl.h b/src/wasm/function-body-decoder-impl.h index 10a57b37aa..d9063c7fbd 100644 --- a/src/wasm/function-body-decoder-impl.h +++ b/src/wasm/function-body-decoder-impl.h @@ -2484,16 +2484,11 @@ class WasmFullDecoder : public WasmDecoder { while (next_try < control_depth() && !control_at(next_try)->is_try()) { next_try++; } - if (next_try == control_depth()) { - this->DecodeError("delegate does not target a try-catch"); - return 0; - } FallThruTo(c); CALL_INTERFACE_IF_PARENT_REACHABLE(Delegate, next_try, c); current_code_reachable_ = this->ok() && control_.back().reachable(); EndControl(); PopControl(c); - c->reachability = control_at(1)->innerReachability(); return 1 + imm.length; } diff --git a/src/wasm/graph-builder-interface.cc b/src/wasm/graph-builder-interface.cc index d0f2f24846..0857c04dc3 100644 --- a/src/wasm/graph-builder-interface.cc +++ b/src/wasm/graph-builder-interface.cc @@ -629,6 +629,12 @@ class WasmGraphBuildingInterface { if (block->try_info->might_throw()) { // Merge the current env into the target handler's env. SetEnv(block->try_info->catch_env); + if (depth == decoder->control_depth()) { + builder_->Rethrow(block->try_info->exception); + builder_->TerminateThrow(effect(), control()); + return; + } + DCHECK(decoder->control_at(depth)->is_try()); TryInfo* target_try = decoder->control_at(depth)->try_info; Goto(decoder, target_try->catch_env); diff --git a/test/mjsunit/wasm/exceptions.js b/test/mjsunit/wasm/exceptions.js index c222290a7c..e7915cebe8 100644 --- a/test/mjsunit/wasm/exceptions.js +++ b/test/mjsunit/wasm/exceptions.js @@ -1039,3 +1039,20 @@ load("test/mjsunit/wasm/exceptions-utils.js"); instance = builder.instantiate(); assertEquals(2, instance.exports.test()); })(); + +(function TestDelegateToCaller() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let except = builder.addException(kSig_v_v); + builder.addFunction('test', kSig_v_v) + .addBody([ + kExprTry, kWasmStmt, + kExprTry, kWasmStmt, + kExprThrow, except, + kExprDelegate, 1, + kExprCatchAll, + kExprEnd + ]).exportFunc(); + instance = builder.instantiate(); + assertTraps(WebAssembly.RuntimeError, () => instance.exports.test()); +})(); diff --git a/test/unittests/wasm/function-body-decoder-unittest.cc b/test/unittests/wasm/function-body-decoder-unittest.cc index dd6d364264..c0068e79fe 100644 --- a/test/unittests/wasm/function-body-decoder-unittest.cc +++ b/test/unittests/wasm/function-body-decoder-unittest.cc @@ -2900,14 +2900,16 @@ TEST_F(FunctionBodyDecoderTest, TryDelegate) { {WASM_TRY_OP, WASM_BLOCK(WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 0)), kExprCatch, ex, kExprEnd}); + ExpectValidates( + sigs.v_v(), + {WASM_BLOCK(WASM_TRY_OP, WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 2), + kExprCatch, ex, kExprEnd)}); - // delegate after catch. - // delegate after catch_all. ExpectFailure( sigs.v_v(), - {WASM_BLOCK(WASM_TRY_OP, WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 1), + {WASM_BLOCK(WASM_TRY_OP, WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 3), kExprCatch, ex, kExprEnd)}, - kAppendEnd, "delegate does not target a try-catch"); + kAppendEnd, "invalid branch depth: 3"); ExpectFailure( sigs.v_v(), {WASM_TRY_OP, WASM_TRY_OP, kExprCatch, ex, kExprDelegate, 0, kExprEnd},