diff options
author | Hendiadyoin1 <leon.a@serenityos.org> | 2022-12-06 20:45:38 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2023-02-26 19:40:09 +0100 |
commit | 1f6a0ef6e0dd26447275e9f19e84f0d5c0216c8e (patch) | |
tree | 0b15abf0ff81b3bcf3e21d41143c672124df3898 /Userland | |
parent | 088dc1b24b8160da93946b60d5eab56e9f6fe692 (diff) | |
download | serenity-1f6a0ef6e0dd26447275e9f19e84f0d5c0216c8e.zip |
LibJS: Don't enter finally blocks upon `yield` in bytecode mode
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Interpreter.cpp | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index d7ec282ec4..2f91b8bf3a 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -75,8 +75,10 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e Bytecode::InstructionStreamIterator pc(m_current_block->instruction_stream()); TemporaryChange temp_change { m_pc, &pc }; + // FIXME: This is getting kinda spaghetti-y bool will_jump = false; bool will_return = false; + bool will_yield = false; while (!pc.at_end()) { auto& instruction = *pc; 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()) { 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; } ++pc; @@ -121,7 +129,7 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e if (will_jump) continue; - if (!unwind_contexts().is_empty()) { + if (!unwind_contexts().is_empty() && !will_yield) { auto& unwind_context = unwind_contexts().last(); if (unwind_context.executable == m_current_executable && unwind_context.finalizer) { m_saved_return_value = make_handle(m_return_value); |