Browse Source

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.
Hendiadyoin1 1 year ago
parent
commit
d79347dd4a

+ 0 - 2
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<Bytecode::Op::LeaveUnwindContext>();
@@ -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<Bytecode::Op::LeaveUnwindContext>();

+ 40 - 0
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]);
+});