mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 22:57:44 +00:00
LibJS/Bytecode: Do not rethrow caught exception from finally
If the exception from the `try` block has already been caught by `catch`, we need to clear the saved exception before entering `finally` so that ContinuePendingUnwind will not re-throw it. 9 new passes on test262 :^)
This commit is contained in:
parent
93b3f12680
commit
e3f65f215d
2 changed files with 9 additions and 2 deletions
|
@ -19,6 +19,8 @@ struct UnwindInfo {
|
||||||
BasicBlock const* finalizer;
|
BasicBlock const* finalizer;
|
||||||
|
|
||||||
JS::GCPtr<Environment> lexical_environment;
|
JS::GCPtr<Environment> lexical_environment;
|
||||||
|
|
||||||
|
bool handler_called { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
class BasicBlock {
|
class BasicBlock {
|
||||||
|
|
|
@ -242,10 +242,10 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Realm& realm, Execu
|
||||||
auto& unwind_context = unwind_contexts().last();
|
auto& unwind_context = unwind_contexts().last();
|
||||||
if (unwind_context.executable != m_current_executable)
|
if (unwind_context.executable != m_current_executable)
|
||||||
break;
|
break;
|
||||||
if (unwind_context.handler) {
|
if (unwind_context.handler && !unwind_context.handler_called) {
|
||||||
vm().running_execution_context().lexical_environment = unwind_context.lexical_environment;
|
vm().running_execution_context().lexical_environment = unwind_context.lexical_environment;
|
||||||
m_current_block = unwind_context.handler;
|
m_current_block = unwind_context.handler;
|
||||||
unwind_context.handler = nullptr;
|
unwind_context.handler_called = true;
|
||||||
|
|
||||||
accumulator() = exception_value;
|
accumulator() = exception_value;
|
||||||
m_saved_exception = {};
|
m_saved_exception = {};
|
||||||
|
@ -254,6 +254,11 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Realm& realm, Execu
|
||||||
}
|
}
|
||||||
if (unwind_context.finalizer) {
|
if (unwind_context.finalizer) {
|
||||||
m_current_block = unwind_context.finalizer;
|
m_current_block = unwind_context.finalizer;
|
||||||
|
// If an exception was thrown inside the corresponding `catch` block, we need to rethrow it
|
||||||
|
// from the `finally` block. But if the exception is from the `try` block, and has already been
|
||||||
|
// handled by `catch`, we swallow it.
|
||||||
|
if (!unwind_context.handler_called)
|
||||||
|
m_saved_exception = {};
|
||||||
will_jump = true;
|
will_jump = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue