diff --git a/Userland/Libraries/LibJS/JIT/Compiler.cpp b/Userland/Libraries/LibJS/JIT/Compiler.cpp index 9b461f92c6..b26efd471e 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.cpp +++ b/Userland/Libraries/LibJS/JIT/Compiler.cpp @@ -2899,9 +2899,14 @@ void Compiler::compile_continue_pending_unwind(Bytecode::Op::ContinuePendingUnwi Assembler::Operand::Register(GPR1), label_for(op.resume_target().block())); - // finish the pending return from the try block - store_vm_register(Bytecode::Register::return_value(), GPR0); - jump_to_exit(); + if (auto const* finalizer = m_current_block->finalizer()) { + // The current block has its own finalizer, we have to jump there instead of returning. + m_assembler.jump(label_for(*finalizer)); + } else { + // finish the pending return from the try block + store_vm_register(Bytecode::Register::return_value(), GPR0); + jump_to_exit(); + } } static void cxx_create_lexical_environment(VM& vm) diff --git a/Userland/Libraries/LibJS/Tests/try-return-finally.js b/Userland/Libraries/LibJS/Tests/try-return-finally.js index b134fc88ef..f0fb85dccd 100644 --- a/Userland/Libraries/LibJS/Tests/try-return-finally.js +++ b/Userland/Libraries/LibJS/Tests/try-return-finally.js @@ -9,3 +9,18 @@ test("return from try followed by finally with function call inside", () => { expect(value).toBe(1); }); + +test("return from outer finally with nested unwind contexts", () => { + let value = (() => { + try { + try { + return 1; + } finally { + } + } finally { + return 2; + } + })(); + + expect(value).toBe(2); +});