1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-18 21:35:06 +00:00

LibJS: Propagate exceptions across bytecode executable boundaries

To support situations like this:

    function foo() { throw 1; }

    try {
        foo();
    } catch (e) {
    }

Each unwind context now keeps track of its origin executable.

When an exception is thrown, we return from run() immediately if the
nearest unwind context isn't in the current executable.

This causes a natural unwind to the point where we find the
catch/finally block(s) to jump into.
This commit is contained in:
Andreas Kling 2021-10-25 12:30:54 +02:00
parent 5a099b98cd
commit 3618ca2420
2 changed files with 4 additions and 1 deletions

View file

@ -82,6 +82,8 @@ Value Interpreter::run(Executable const& executable, BasicBlock const* entry_poi
if (m_unwind_contexts.is_empty())
break;
auto& unwind_context = m_unwind_contexts.last();
if (unwind_context.executable != m_current_executable)
break;
if (unwind_context.handler) {
block = unwind_context.handler;
unwind_context.handler = nullptr;
@ -156,7 +158,7 @@ Value Interpreter::run(Executable const& executable, BasicBlock const* entry_poi
void Interpreter::enter_unwind_context(Optional<Label> handler_target, Optional<Label> finalizer_target)
{
m_unwind_contexts.empend(handler_target.has_value() ? &handler_target->block() : nullptr, finalizer_target.has_value() ? &finalizer_target->block() : nullptr);
m_unwind_contexts.empend(m_current_executable, handler_target.has_value() ? &handler_target->block() : nullptr, finalizer_target.has_value() ? &finalizer_target->block() : nullptr);
}
void Interpreter::leave_unwind_context()