fix corner case in `sequences` (#4073)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 25 Aug 2020 17:26:49 +0000 (18:26 +0100)
committerGitHub <noreply@github.com>
Tue, 25 Aug 2020 17:26:49 +0000 (01:26 +0800)
lib/ast.js
lib/compress.js
test/compress/sequences.js

index b6d4ebb..73f4696 100644 (file)
@@ -288,10 +288,13 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
             var label = node.label;
             var def = this.label;
             node.walk(new TreeWalker(function(node) {
-                if (node instanceof AST_LoopControl && node.label && node.label.thedef === def) {
+                if (node instanceof AST_LoopControl) {
+                    if (!node.label || node.label.thedef !== def) return;
                     node.label.thedef = label;
                     label.references.push(node);
+                    return true;
                 }
+                if (node instanceof AST_Scope) return true;
             }));
         }
         return node;
index 3f0ea21..4744566 100644 (file)
@@ -554,13 +554,6 @@ merge(Compressor.prototype, {
             if (is_arguments(def) && node.property instanceof AST_Number) def.reassigned = true;
         }
 
-        var suppressor = new TreeWalker(function(node) {
-            if (!(node instanceof AST_Symbol)) return;
-            var d = node.definition();
-            if (!d) return;
-            if (node instanceof AST_SymbolRef) push_ref(d, node);
-            d.fixed = false;
-        });
         def(AST_Accessor, function(tw, descend, compressor) {
             push(tw);
             reset_variables(tw, compressor, this);
@@ -740,11 +733,19 @@ merge(Compressor.prototype, {
             return true;
         });
         def(AST_ForIn, function(tw) {
-            this.init.walk(suppressor);
             this.object.walk(tw);
             var saved_loop = tw.in_loop;
             tw.in_loop = this;
             push(tw);
+            var init = this.init;
+            init.walk(tw);
+            if (init instanceof AST_Var) {
+                init = init.definitions[0].name;
+            } else while (init instanceof AST_PropAccess) {
+                init = init.expression.tail_node();
+            }
+            var def = init.definition();
+            if (def) def.fixed = false;
             this.body.walk(tw);
             pop(tw);
             tw.in_loop = saved_loop;
@@ -8521,7 +8522,9 @@ merge(Compressor.prototype, {
             }
         }
         if (is_lhs(compressor.self(), parent)) return self;
-        if (compressor.option("sequences") && compressor.parent().TYPE != "Call") {
+        if (compressor.option("sequences")
+            && parent.TYPE != "Call"
+            && !(parent instanceof AST_ForIn && parent.init === self)) {
             var seq = lift_sequence_in_expression(self, compressor);
             if (seq !== self) return seq.optimize(compressor);
         }
@@ -8632,8 +8635,11 @@ merge(Compressor.prototype, {
                 col: self.start.col
             });
         }
-        if (is_lhs(compressor.self(), compressor.parent())) return self;
-        if (compressor.option("sequences") && compressor.parent().TYPE != "Call") {
+        var parent = compressor.parent();
+        if (is_lhs(compressor.self(), parent)) return self;
+        if (compressor.option("sequences")
+            && parent.TYPE != "Call"
+            && !(parent instanceof AST_ForIn && parent.init === self)) {
             var seq = lift_sequence_in_expression(self, compressor);
             if (seq !== self) return seq.optimize(compressor);
         }
index c0b7712..32db63d 100644 (file)
@@ -877,7 +877,7 @@ for_init_var: {
     expect_stdout: "PASS"
 }
 
-forin: {
+forin_1: {
     options = {
         sequences: true,
     }
@@ -895,6 +895,49 @@ forin: {
     expect_stdout: "PASS"
 }
 
+forin_2: {
+    options = {
+        evaluate: true,
+        inline: true,
+        reduce_vars: true,
+        sequences: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var o = {
+            p: 1,
+            q: 2,
+        };
+        var k = "k";
+        for ((console.log("exp"), o)[function() {
+            console.log("prop");
+            return k;
+        }()] in function() {
+            console.log("obj");
+            return o;
+        }())
+            console.log(o.k, o[o.k]);
+    }
+    expect: {
+        var o = {
+            p: 1,
+            q: 2,
+        };
+        for ((console.log("exp"), o)[console.log("prop"), "k"] in console.log("obj"), o)
+            console.log(o.k, o[o.k]);
+    }
+    expect_stdout: [
+        "obj",
+        "exp",
+        "prop",
+        "p 1",
+        "exp",
+        "prop",
+        "q 2",
+    ]
+}
+
 call: {
     options = {
         sequences: true,