mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:18:11 +00:00
LibJS: Stop unwinding and reset exception for TryStatement finalizer
This fixes two issues with running a TryStatement finalizer: - Temporarily store and clear the exception, if any, so we can run the finalizer block statement without it getting in our way, which could have unexpected side effects otherwise (and will likely return early somewhere). - Stop unwinding so more than one child node of the finalizer BlockStatement is executed if an exception has been thrown previously (which would have called unwind(ScopeType::Try)). Re-throwing as described above ensures we still unwind after the finalizer, if necessary. Also add some tests specifically for try/catch/finally blocks, we didn't have any!
This commit is contained in:
parent
ec43f73b74
commit
75dac35d0e
3 changed files with 231 additions and 1 deletions
|
@ -1786,8 +1786,20 @@ Value TryStatement::execute(Interpreter& interpreter, GlobalObject& global_objec
|
|||
}
|
||||
}
|
||||
|
||||
if (m_finalizer)
|
||||
if (m_finalizer) {
|
||||
// Keep, if any, and then clear the current exception so we can
|
||||
// execute() the finalizer without an exception in our way.
|
||||
auto* previous_exception = interpreter.exception();
|
||||
interpreter.clear_exception();
|
||||
interpreter.stop_unwind();
|
||||
m_finalizer->execute(interpreter, global_object);
|
||||
// If we previously had an exception and the finalizer didn't
|
||||
// throw a new one, restore the old one.
|
||||
// FIXME: This will print debug output in throw_exception() for
|
||||
// a seconds time with INTERPRETER_DEBUG enabled.
|
||||
if (previous_exception && !interpreter.exception())
|
||||
interpreter.throw_exception(previous_exception);
|
||||
}
|
||||
|
||||
return js_undefined();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue