Przeglądaj źródła

LibJS/JIT: Continue to outer `finally` before returning

Fixes #21854
Andreas Kling 1 rok temu
rodzic
commit
2372584b18

+ 8 - 3
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)

+ 15 - 0
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);
+});