From 277132f70d6a44f84fa71b03d64cce435c65c183 Mon Sep 17 00:00:00 2001 From: Luke Wilde Date: Fri, 25 Nov 2022 23:15:44 +0000 Subject: [PATCH] LibJS/Bytecode: Store unwind contexts inside RegisterWindow Unwind contexts need to be preserved as we exit and re-enter a generator. For example, this would previously crash when returning from the try statement after yielding as we lost the unwind context when yielding, but still have a LeaveUnwindContext instruction from running `perform_needed_unwinds` when generating the return statement. ```js function* a() { try { return (yield 1); } catch {} } iter = a(); iter.next(); iter.next(); ``` --- Userland/Libraries/LibJS/Bytecode/Interpreter.cpp | 14 +++++++------- Userland/Libraries/LibJS/Bytecode/Interpreter.h | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index e7b60f9618..41eb283228 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -65,7 +65,7 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e if (in_frame) m_register_windows.append(in_frame); else - m_register_windows.append(make(MarkedVector(vm().heap()), MarkedVector(vm().heap()), MarkedVector(vm().heap()))); + m_register_windows.append(make(MarkedVector(vm().heap()), MarkedVector(vm().heap()), MarkedVector(vm().heap()), Vector {})); registers().resize(executable.number_of_registers); @@ -81,9 +81,9 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e if (ran_or_error.is_error()) { auto exception_value = *ran_or_error.throw_completion().value(); m_saved_exception = make_handle(exception_value); - if (m_unwind_contexts.is_empty()) + if (unwind_contexts().is_empty()) break; - auto& unwind_context = m_unwind_contexts.last(); + auto& unwind_context = unwind_contexts().last(); if (unwind_context.executable != m_current_executable) break; if (unwind_context.handler) { @@ -92,7 +92,7 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e // If there's no finalizer, there's nowhere for the handler block to unwind to, so the unwind context is no longer needed. if (!unwind_context.finalizer) - m_unwind_contexts.take_last(); + unwind_contexts().take_last(); accumulator() = exception_value; m_saved_exception = {}; @@ -101,7 +101,7 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e } if (unwind_context.finalizer) { m_current_block = unwind_context.finalizer; - m_unwind_contexts.take_last(); + unwind_contexts().take_last(); will_jump = true; break; } @@ -179,12 +179,12 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e void Interpreter::enter_unwind_context(Optional