LibJS: Propagate finalizers into nested try-catch blocks without them

This commit is contained in:
Hendiadyoin1 2024-04-11 00:25:54 +02:00 committed by Andreas Kling
parent 865e651a7d
commit 301a1fc763
Notes: sideshowbarker 2024-07-17 18:08:55 +09:00
3 changed files with 59 additions and 2 deletions

View File

@ -2510,8 +2510,13 @@ Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> TryStatement::gener
if (m_finalizer)
generator.end_boundary(Bytecode::Generator::BlockBoundaryType::ReturnToFinally);
if (m_handler) {
if (!m_finalizer)
unwind_context.emplace(generator, OptionalNone());
if (!m_finalizer) {
auto const* parent_unwind_context = generator.current_unwind_context();
if (parent_unwind_context)
unwind_context.emplace(generator, parent_unwind_context->finalizer());
else
unwind_context.emplace(generator, OptionalNone());
}
unwind_context->set_handler(handler_target.value());
}

View File

@ -276,6 +276,8 @@ public:
return Operand(Operand::Type::Constant, m_constants.size() - 1);
}
UnwindContext const* current_unwind_context() const { return m_current_unwind_context; }
private:
VM& m_vm;

View File

@ -53,3 +53,53 @@ test("Nested try/catch/finally with exceptions", () => {
expect(level3CatchHasBeenExecuted).toBeTrue();
expect(level3FinallyHasBeenExecuted).toBeTrue();
});
test("Nested try/catch/finally with return in inner context", () => {
success = false;
(() => {
try {
try {
return;
} catch (e) {
expect().fail();
}
} finally {
success = true;
}
expect().fail();
})();
expect(success).toBeTrue();
});
test("Deeply nested try/catch/finally with return in inner context", () => {
success = 0;
(() => {
try {
try {
try {
try {
try {
return;
} catch (e) {
expect().fail();
} finally {
success += 4;
}
} catch (e) {
expect().fail();
}
} catch (e) {
expect().fail();
} finally {
success += 2;
}
} catch (e) {
expect().fail();
}
} finally {
success += 1;
}
expect().fail();
})();
expect(success).toBe(7);
});