From 3618ca242052d56ea20a05d94b6d46951567a8b5 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 25 Oct 2021 12:30:54 +0200 Subject: [PATCH] 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. --- Userland/Libraries/LibJS/Bytecode/BasicBlock.h | 1 + Userland/Libraries/LibJS/Bytecode/Interpreter.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibJS/Bytecode/BasicBlock.h b/Userland/Libraries/LibJS/Bytecode/BasicBlock.h index b3720c2a15..9078287777 100644 --- a/Userland/Libraries/LibJS/Bytecode/BasicBlock.h +++ b/Userland/Libraries/LibJS/Bytecode/BasicBlock.h @@ -39,6 +39,7 @@ private: }; struct UnwindInfo { + Executable const* executable; BasicBlock const* handler; BasicBlock const* finalizer; }; diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index c562e9cc54..db0755acc5 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -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