From d79347dd4afd6ca1b4706314a799c537b478d6db Mon Sep 17 00:00:00 2001 From: Hendiadyoin1 Date: Sun, 19 May 2024 16:45:38 +0200 Subject: [PATCH] LibJS: Remove an old VERIFY from break handling in try-finally blocks The VERIFY assumed that we either have a finally block which we already visited through a previous boundary or have no finally block what so ever; But since 301a1fc7631bb862f003cc2ebfab37a42e5fdbc5 we propagate finalizers through unwind scopes breaking that assumption. --- .../Libraries/LibJS/Bytecode/Generator.cpp | 2 - .../LibJS/Tests/try-finally-break.js | 40 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index aeaf595644..1315f20262 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -902,7 +902,6 @@ void Generator::generate_scoped_jump(JumpType type) } break; case Unwind: - VERIFY(last_was_finally || !m_current_unwind_context->finalizer().has_value()); if (!last_was_finally) { VERIFY(m_current_unwind_context && m_current_unwind_context->handler().has_value()); emit(); @@ -944,7 +943,6 @@ void Generator::generate_labelled_jump(JumpType type, DeprecatedFlyString const& for (; current_boundary > 0; --current_boundary) { auto boundary = m_boundaries[current_boundary - 1]; if (boundary == BlockBoundaryType::Unwind) { - VERIFY(last_was_finally || !m_current_unwind_context->finalizer().has_value()); if (!last_was_finally) { VERIFY(m_current_unwind_context && m_current_unwind_context->handler().has_value()); emit(); diff --git a/Userland/Libraries/LibJS/Tests/try-finally-break.js b/Userland/Libraries/LibJS/Tests/try-finally-break.js index 76c4cf72ed..162c3ed5da 100644 --- a/Userland/Libraries/LibJS/Tests/try-finally-break.js +++ b/Userland/Libraries/LibJS/Tests/try-finally-break.js @@ -450,3 +450,43 @@ test("Throw while breaking with nested try-catch-finally with throw in finalizer expect(executionOrder).toEqual([1, 2, 3, 4, 5]); }); + +test("Labelled break with nested mixed try-catch/finally", () => { + const executionOrder = []; + scope: { + try { + try { + executionOrder.push(1); + break scope; + } catch { + expect.fail("Entered catch"); + } + expect.fail("Continued after inner try"); + } finally { + executionOrder.push(2); + } + expect.fail("Continued after outer try"); + } + + expect(executionOrder).toEqual([1, 2]); +}); + +test("Break with nested mixed try-catch/finally", () => { + const executionOrder = []; + do { + try { + try { + executionOrder.push(1); + break; + } catch { + expect.fail("Entered catch"); + } + expect.fail("Continued after inner try"); + } finally { + executionOrder.push(2); + } + expect.fail("Continued after outer try"); + } while (expect.fail("Continued after do-while loop")); + + expect(executionOrder).toEqual([1, 2]); +});