1
Fork 0
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:
Linus Groh 2020-09-11 23:30:00 +01:00 committed by Andreas Kling
parent ec43f73b74
commit 75dac35d0e
3 changed files with 231 additions and 1 deletions

View file

@ -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();
}