Browse Source

LibJS/Bytecode: Restore old environments when an exception is caught

Unwind contexts now remember the lexical and variable environments in
effect when they were created. If an exception is caught, we revert
to those environments in the running execution context.
Andreas Kling 2 năm trước cách đây
mục cha
commit
ce634957c1

+ 4 - 0
Userland/Libraries/LibJS/Bytecode/BasicBlock.h

@@ -9,6 +9,7 @@
 #include <AK/Badge.h>
 #include <AK/Badge.h>
 #include <AK/DeprecatedString.h>
 #include <AK/DeprecatedString.h>
 #include <LibJS/Forward.h>
 #include <LibJS/Forward.h>
+#include <LibJS/Heap/Handle.h>
 
 
 namespace JS::Bytecode {
 namespace JS::Bytecode {
 
 
@@ -16,6 +17,9 @@ struct UnwindInfo {
     Executable const* executable;
     Executable const* executable;
     BasicBlock const* handler;
     BasicBlock const* handler;
     BasicBlock const* finalizer;
     BasicBlock const* finalizer;
+
+    Handle<Environment> lexical_environment;
+    Handle<Environment> variable_environment;
 };
 };
 
 
 class BasicBlock {
 class BasicBlock {

+ 8 - 1
Userland/Libraries/LibJS/Bytecode/Interpreter.cpp

@@ -91,6 +91,8 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
                 if (unwind_context.executable != m_current_executable)
                 if (unwind_context.executable != m_current_executable)
                     break;
                     break;
                 if (unwind_context.handler) {
                 if (unwind_context.handler) {
+                    vm().running_execution_context().lexical_environment = unwind_context.lexical_environment;
+                    vm().running_execution_context().variable_environment = unwind_context.variable_environment;
                     m_current_block = unwind_context.handler;
                     m_current_block = unwind_context.handler;
                     unwind_context.handler = nullptr;
                     unwind_context.handler = nullptr;
 
 
@@ -205,7 +207,12 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
 
 
 void Interpreter::enter_unwind_context(Optional<Label> handler_target, Optional<Label> finalizer_target)
 void Interpreter::enter_unwind_context(Optional<Label> handler_target, Optional<Label> finalizer_target)
 {
 {
-    unwind_contexts().empend(m_current_executable, handler_target.has_value() ? &handler_target->block() : nullptr, finalizer_target.has_value() ? &finalizer_target->block() : nullptr);
+    unwind_contexts().empend(
+        m_current_executable,
+        handler_target.has_value() ? &handler_target->block() : nullptr,
+        finalizer_target.has_value() ? &finalizer_target->block() : nullptr,
+        vm().running_execution_context().lexical_environment,
+        vm().running_execution_context().variable_environment);
 }
 }
 
 
 void Interpreter::leave_unwind_context()
 void Interpreter::leave_unwind_context()