enhance `join_vars` (#4643)
authorAlex Lam S.L <alexlamsl@gmail.com>
Wed, 10 Feb 2021 20:59:25 +0000 (20:59 +0000)
committerGitHub <noreply@github.com>
Wed, 10 Feb 2021 20:59:25 +0000 (04:59 +0800)
lib/compress.js
test/compress/join_vars.js

index 3d85719..1eed09b 100644 (file)
@@ -3049,13 +3049,13 @@ merge(Compressor.prototype, {
             statements.length = n;
         }
 
+        function extract_exprs(body) {
+            if (body instanceof AST_Assign) return [ body ];
+            if (body instanceof AST_Sequence) return body.expressions.slice();
+        }
+
         function join_assigns(defn, body, keep) {
-            var exprs;
-            if (body instanceof AST_Assign) {
-                exprs = [ body ];
-            } else if (body instanceof AST_Sequence) {
-                exprs = body.expressions.slice();
-            }
+            var exprs = extract_exprs(body);
             if (!exprs) return;
             var trimmed = false;
             for (var i = exprs.length - 1; --i >= 0;) {
@@ -3082,6 +3082,17 @@ merge(Compressor.prototype, {
             return trimmed && exprs;
         }
 
+        function merge_assigns(prev, defn) {
+            if (!(prev instanceof AST_SimpleStatement)) return;
+            if (declarations_only(defn)) return;
+            var exprs = extract_exprs(prev.body);
+            if (!exprs) return;
+            var definitions = [];
+            if (!join_var_assign(definitions, exprs.reverse(), 0)) return;
+            defn.definitions = definitions.reverse().concat(defn.definitions);
+            return exprs.reverse();
+        }
+
         function merge_conditional_assignments(var_def, exprs, keep) {
             if (!compressor.option("conditionals")) return;
             if (var_def.name instanceof AST_Destructured) return;
@@ -3173,9 +3184,20 @@ merge(Compressor.prototype, {
                     } else if (defs && defs.TYPE == stat.TYPE && declarations_only(stat)) {
                         defs.definitions = defs.definitions.concat(stat.definitions);
                         CHANGED = true;
+                    } else if (stat instanceof AST_Var) {
+                        var exprs = merge_assigns(prev, stat);
+                        if (exprs) {
+                            if (exprs.length) {
+                                prev.body = make_sequence(prev, exprs);
+                                j++;
+                            }
+                            CHANGED = true;
+                        } else {
+                            j++;
+                        }
+                        statements[j] = defs = stat;
                     } else {
                         statements[++j] = stat;
-                        if (stat instanceof AST_Var) defs = stat;
                     }
                     continue;
                 } else if (stat instanceof AST_Exit) {
@@ -3199,6 +3221,15 @@ merge(Compressor.prototype, {
                         CHANGED = true;
                     } else if (stat.init instanceof AST_Var) {
                         defs = stat.init;
+                        exprs = merge_assigns(prev, stat.init);
+                        if (exprs) {
+                            CHANGED = true;
+                            if (exprs.length == 0) {
+                                statements[j] = merge_defns(stat);
+                                continue;
+                            }
+                            prev.body = make_sequence(prev, exprs);
+                        }
                     }
                 } else if (stat instanceof AST_ForEnumeration) {
                     if (defs && defs.TYPE == stat.init.TYPE) {
index aec6a91..21b76aa 100644 (file)
@@ -1055,3 +1055,75 @@ issue_3916: {
     }
     expect_stdout: "object PASS true PASS"
 }
+
+assign_var: {
+    options = {
+        join_vars: true,
+    }
+    input: {
+        b = "foo";
+        var a = [ , "bar" ];
+        console.log(b);
+        for (var b in a)
+            console.log(b, a[b]);
+    }
+    expect: {
+        var b = "foo", a = [ , "bar" ], b;
+        console.log(b);
+        for (b in a)
+            console.log(b, a[b]);
+    }
+    expect_stdout: [
+        "foo",
+        "1 bar",
+    ]
+}
+
+assign_for_var: {
+    options = {
+        join_vars: true,
+    }
+    input: {
+        i = "foo",
+        a = new Array(i, "bar");
+        for (var i = 2; --i >= 0;) {
+            console.log(a[i]);
+            for (var a in i);
+        }
+    }
+    expect: {
+        for (var i = "foo", a = new Array(i, "bar"), i = 2; --i >= 0;) {
+            console.log(a[i]);
+            for (var a in i);
+        }
+    }
+    expect_stdout: [
+        "bar",
+        "foo",
+    ]
+}
+
+assign_sequence_var: {
+    options = {
+        join_vars: true,
+    }
+    input: {
+        var a = 0, b = 1;
+        console.log(a),
+        a++,
+        b = 2;
+        var c = 3;
+        console.log(a, b, c);
+    }
+    expect: {
+        var a = 0, b = 1;
+        console.log(a),
+        a++;
+        var b = 2, c = 3;
+        console.log(a, b, c);
+    }
+    expect_stdout: [
+        "0",
+        "1 2 3",
+    ]
+}