1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 03:57:43 +00:00

LibJS: Don't enter finally blocks upon yield in bytecode mode

This commit is contained in:
Hendiadyoin1 2022-12-06 20:45:38 +01:00 committed by Linus Groh
parent 088dc1b24b
commit 1f6a0ef6e0

View file

@ -75,8 +75,10 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
Bytecode::InstructionStreamIterator pc(m_current_block->instruction_stream()); Bytecode::InstructionStreamIterator pc(m_current_block->instruction_stream());
TemporaryChange temp_change { m_pc, &pc }; TemporaryChange temp_change { m_pc, &pc };
// FIXME: This is getting kinda spaghetti-y
bool will_jump = false; bool will_jump = false;
bool will_return = false; bool will_return = false;
bool will_yield = false;
while (!pc.at_end()) { while (!pc.at_end()) {
auto& instruction = *pc; auto& instruction = *pc;
auto ran_or_error = instruction.execute(*this); auto ran_or_error = instruction.execute(*this);
@ -113,6 +115,12 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
} }
if (!m_return_value.is_empty()) { if (!m_return_value.is_empty()) {
will_return = true; will_return = true;
// Note: A `yield` statement will not go through a finally statement,
// hence we need to set a flag to not do so,
// but we generate a Yield Operation in the case of returns in
// generators as well, so we need to check if it will actually
// continue or is a `return` in disguise
will_yield = instruction.type() == Instruction::Type::Yield && static_cast<Op::Yield const&>(instruction).continuation().has_value();
break; break;
} }
++pc; ++pc;
@ -121,7 +129,7 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
if (will_jump) if (will_jump)
continue; continue;
if (!unwind_contexts().is_empty()) { if (!unwind_contexts().is_empty() && !will_yield) {
auto& unwind_context = unwind_contexts().last(); auto& unwind_context = unwind_contexts().last();
if (unwind_context.executable == m_current_executable && unwind_context.finalizer) { if (unwind_context.executable == m_current_executable && unwind_context.finalizer) {
m_saved_return_value = make_handle(m_return_value); m_saved_return_value = make_handle(m_return_value);