enhance `collapse_vars` (#5186)
authorAlex Lam S.L <alexlamsl@gmail.com>
Wed, 24 Nov 2021 09:28:36 +0000 (09:28 +0000)
committerGitHub <noreply@github.com>
Wed, 24 Nov 2021 09:28:36 +0000 (17:28 +0800)
closes #5182

lib/ast.js
lib/compress.js
test/compress/collapse_vars.js

index c4866f8..344d2ee 100644 (file)
@@ -1999,7 +1999,7 @@ TreeWalker.prototype = {
     },
     find_parent: function(type) {
         var stack = this.stack;
-        for (var i = stack.length; --i >= 0;) {
+        for (var i = stack.length - 1; --i >= 0;) {
             var x = stack[i];
             if (x instanceof type) return x;
         }
index 3df34c4..115408d 100644 (file)
@@ -2906,8 +2906,9 @@ merge(Compressor.prototype, {
                         if (!value) {
                             value = node;
                             var def = node.definition();
+                            var escaped = node.fixed && node.fixed.escaped || def.escaped;
                             if (!def.undeclared
-                                && (def.assignments || !def.escaped || def.escaped.cross_scope)
+                                && (def.assignments || !escaped || escaped.cross_scope)
                                 && (has_escaped(def, node.scope, node, tw.parent()) || !same_scope(def))) {
                                 well_defined = false;
                             }
@@ -2915,8 +2916,11 @@ merge(Compressor.prototype, {
                     } else if (node instanceof AST_ObjectIdentity) {
                         value = node;
                     }
-                    if (value) lvalues.add(node.name, is_modified(compressor, tw, node, value, 0));
-                    if (find_arguments && node instanceof AST_Sub) {
+                    if (value) {
+                        lvalues.add(node.name, is_modified(compressor, tw, node, value, 0));
+                    } else if (node instanceof AST_Lambda) {
+                        if (!(tw.find_parent(AST_Call) || tw.find_parent(AST_Scope))) return true;
+                    } else if (find_arguments && node instanceof AST_Sub) {
                         scope.each_argname(function(argname) {
                             if (!compressor.option("reduce_vars") || argname.definition().assignments) {
                                 if (!argname.definition().fixed) well_defined = false;
@@ -3023,7 +3027,10 @@ merge(Compressor.prototype, {
                     return false;
                 }
                 var def = lhs.definition();
-                return def.references.length - def.replaced == referenced;
+                if (def.references.length - def.replaced == referenced) return true;
+                return def.fixed && lhs.fixed && def.references.filter(function(ref) {
+                    return ref.fixed === lhs.fixed;
+                }).length == referenced;
             }
 
             function symbol_in_lvalues(sym, parent) {
index 0df9d72..16d8dc3 100644 (file)
@@ -9253,13 +9253,13 @@ issue_4920_2: {
         console.log(b);
     }
     expect: {
-        var o = {
+        var o;
+        var a = "PASS", b;
+        ({
             get PASS() {
                 a = "FAIL";
             },
-        };
-        var a = "PASS", b;
-        o[b = a];
+        })[b = a];
         console.log(b);
     }
     expect_stdout: "PASS"
@@ -9283,16 +9283,47 @@ issue_4920_3: {
     }
     expect: {
         var log = console.log;
-        var o = {
+        var o;
+        var a = "PASS", b;
+        ({
             get PASS() {
                 a = "FAIL";
             },
+        })[b = a];
+        log(b);
+    }
+    expect_stdout: "PASS"
+}
+
+issue_4920_4: {
+    options = {
+        collapse_vars: true,
+        toplevel: true,
+    }
+    input: {
+        var log = console.log;
+        var o = {
+            get [(a = "FAIL 1", "PASS")]() {
+                a = "FAIL 2";
+            },
+        };
+        var a = "PASS", b;
+        o[b = a];
+        log(b);
+    }
+    expect: {
+        var log = console.log;
+        var o = {
+            get [(a = "FAIL 1", "PASS")]() {
+                a = "FAIL 2";
+            },
         };
         var a = "PASS", b;
         o[b = a];
         log(b);
     }
     expect_stdout: "PASS"
+    node_version: ">=4"
 }
 
 issue_4935: {
@@ -9482,3 +9513,56 @@ issue_5112_2: {
     }
     expect_stdout: "PASS"
 }
+
+issue_5182: {
+    options = {
+        arrows: true,
+        collapse_vars: true,
+        evaluate: true,
+        hoist_props: true,
+        inline: true,
+        merge_vars: true,
+        passes: 3,
+        reduce_vars: true,
+        sequences: true,
+        side_effects: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var con = console;
+        global.log = con.log;
+        var jump = function(x) {
+            console.log("JUMP:", x * 10);
+            return x + x;
+        };
+        var jump2 = jump;
+        var run = function(x) {
+            console.log("RUN:", x * -10);
+            return x * x;
+        };
+        var run2 = run;
+        var bar = (x, y) => {
+            console.log("BAR:", x + y);
+            return x - y;
+        };
+        var bar2 = bar;
+        var obj = {
+            foo: bar2,
+            go: run2,
+            not_used: jump2,
+        };
+        console.log(obj.foo(1, 2), global.log("PASS"));
+    }
+    expect: {
+        var obj = console;
+        global.log = obj.log,
+        console.log((console.log("BAR:", 3), -1), global.log("PASS"));
+    }
+    expect_stdout: [
+        "BAR: 3",
+        "PASS",
+        "-1 undefined",
+    ]
+    node_version: ">=4"
+}