Browse Source

LibJS: Fix crash in bytecode generator on https://twinings.co.uk/

If the current block has already been terminated, we should just skip
creating a per-iteration environment.
Andreas Kling 1 year ago
parent
commit
9a7e6158af

+ 10 - 6
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -1042,9 +1042,12 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> ForStatement::generate_
         }
         }
     };
     };
 
 
-    // CreatePerIterationEnvironment where lastIterationEnv is the variable
-    // scope created above for bound identifiers
-    generate_per_iteration_bindings();
+    if (m_init) {
+        // CreatePerIterationEnvironment where lastIterationEnv is the variable
+        // scope created above for bound identifiers
+        generate_per_iteration_bindings();
+    }
+
     body_block_ptr = &generator.make_block();
     body_block_ptr = &generator.make_block();
 
 
     if (m_update)
     if (m_update)
@@ -1082,10 +1085,11 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> ForStatement::generate_
     generator.end_breakable_scope();
     generator.end_breakable_scope();
     generator.end_continuable_scope();
     generator.end_continuable_scope();
 
 
-    // CreatePerIterationEnvironment where lastIterationEnv is the environment
-    // created by the previous CreatePerIterationEnvironment setup
-    generate_per_iteration_bindings();
     if (!generator.is_current_block_terminated()) {
     if (!generator.is_current_block_terminated()) {
+        // CreatePerIterationEnvironment where lastIterationEnv is the environment
+        // created by the previous CreatePerIterationEnvironment setup
+        generate_per_iteration_bindings();
+
         if (m_update) {
         if (m_update) {
             generator.emit<Bytecode::Op::Jump>(Bytecode::Label { *update_block_ptr });
             generator.emit<Bytecode::Op::Jump>(Bytecode::Label { *update_block_ptr });
         } else {
         } else {

+ 12 - 0
Userland/Libraries/LibJS/Tests/for-loop-per-iteration-env-bug.js

@@ -0,0 +1,12 @@
+test("check that codegen doesn't crash", () => {
+    function func(x) {
+        expect(x()).toBe(0);
+    }
+
+    function go() {
+        for (let i = 0; ; ) {
+            func(() => i);
+            break;
+        }
+    }
+});