enhance `join_vars` (#3804)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sun, 19 Apr 2020 22:37:46 +0000 (23:37 +0100)
committerGitHub <noreply@github.com>
Sun, 19 Apr 2020 22:37:46 +0000 (06:37 +0800)
lib/compress.js
test/compress/issue-1639.js
test/compress/join_vars.js

index 6742aef..e40e1d2 100644 (file)
@@ -2447,6 +2447,7 @@ merge(Compressor.prototype, {
                         statements[++j] = stat;
                         defs = stat;
                     }
+                    continue;
                 } else if (stat instanceof AST_Exit) {
                     stat.value = join_assigns_expr(stat.value);
                 } else if (stat instanceof AST_For) {
@@ -2454,21 +2455,20 @@ merge(Compressor.prototype, {
                     if (exprs) {
                         CHANGED = true;
                         stat.init = exprs.length ? make_sequence(stat.init, exprs) : null;
-                        statements[++j] = stat;
                     } else if (prev instanceof AST_Var && (!stat.init || stat.init.TYPE == prev.TYPE)) {
                         if (stat.init) {
                             prev.definitions = prev.definitions.concat(stat.init.definitions);
                         }
-                        stat.init = prev;
-                        statements[j] = stat;
+                        defs = stat.init = prev;
+                        statements[j] = merge_defns(stat);
                         CHANGED = true;
+                        continue;
                     } else if (defs && stat.init && defs.TYPE == stat.init.TYPE && declarations_only(stat.init)) {
                         defs.definitions = defs.definitions.concat(stat.init.definitions);
                         stat.init = null;
-                        statements[++j] = stat;
                         CHANGED = true;
-                    } else {
-                        statements[++j] = stat;
+                    } else if (stat.init instanceof AST_Definitions) {
+                        defs = stat.init;
                     }
                 } else if (stat instanceof AST_ForIn) {
                     stat.object = join_assigns_expr(stat.object);
@@ -2481,19 +2481,16 @@ merge(Compressor.prototype, {
                         if (!exprs.length) continue;
                         stat.body = make_sequence(stat.body, exprs);
                     }
-                    statements[++j] = stat;
                 } else if (stat instanceof AST_Switch) {
                     stat.expression = join_assigns_expr(stat.expression);
                 } else if (stat instanceof AST_With) {
                     stat.expression = join_assigns_expr(stat.expression);
-                } else {
-                    statements[++j] = stat;
                 }
+                statements[++j] = defs ? merge_defns(stat) : stat;
             }
             statements.length = j + 1;
 
             function join_assigns_expr(value) {
-                statements[++j] = stat;
                 var exprs = join_assigns(prev, value, 1);
                 if (!exprs) return value;
                 CHANGED = true;
@@ -2501,6 +2498,23 @@ merge(Compressor.prototype, {
                 if (exprs[exprs.length - 1] !== tail) exprs.push(tail.left);
                 return make_sequence(value, exprs);
             }
+
+            function merge_defns(stat) {
+                return stat.transform(new TreeTransformer(function(node, descend, in_list) {
+                    if (node instanceof AST_Definitions) {
+                        if (defs === node) return node;
+                        if (defs.TYPE != node.TYPE) return node;
+                        var parent = this.parent();
+                        if (parent instanceof AST_ForIn && parent.init === node) return node;
+                        if (!declarations_only(node)) return node;
+                        defs.definitions = defs.definitions.concat(node.definitions);
+                        CHANGED = true;
+                        return in_list ? List.skip : make_node(AST_EmptyStatement, node);
+                    }
+                    if (node instanceof AST_Scope) return node;
+                    if (!(node instanceof AST_Statement)) return node;
+                }));
+            }
         }
     }
 
index 6633eb2..4bf74f3 100644 (file)
@@ -22,8 +22,7 @@ issue_1639_1: {
         console.log(a, b);
     }
     expect: {
-        for (var a = 100, b = 10, L1 = 5; --L1 > 0;) {
-            var ignore;
+        for (var a = 100, b = 10, L1 = 5, ignore; --L1 > 0;) {
             --b;
         }
         console.log(a, b);
index 4e8d3b5..078ba35 100644 (file)
@@ -815,3 +815,84 @@ issue_3795: {
     }
     expect_stdout: "PASS"
 }
+
+if_body: {
+    options = {
+        join_vars: true,
+    }
+    input: {
+        var a;
+        if (x)
+            var b;
+        else
+            var c;
+    }
+    expect: {
+        var a, b, c;
+        if (x);
+        else;
+    }
+}
+
+if_switch: {
+    options = {
+        join_vars: true,
+    }
+    input: {
+        var a;
+        if (x) switch (y) {
+          case 1:
+            var b;
+          default:
+            var c;
+        }
+    }
+    expect: {
+        var a, b, c;
+        if (x) switch (y) {
+          case 1:
+          default:
+        }
+    }
+}
+
+loop_body_1: {
+    options = {
+        join_vars: true,
+    }
+    input: {
+        var a;
+        for (;x;)
+            var b;
+    }
+    expect: {
+        for (var a, b; x;);
+    }
+}
+
+loop_body_2: {
+    options = {
+        join_vars: true,
+    }
+    input: {
+        for (var a; x;)
+            var b;
+    }
+    expect: {
+        for (var a, b; x;);
+    }
+}
+
+loop_body_3: {
+    options = {
+        join_vars: true,
+    }
+    input: {
+        var a;
+        for (var b; x;)
+            var c;
+    }
+    expect: {
+        for (var a, b, c; x;);
+    }
+}