fix corner cases in `join_vars` (#3790)
authorAlex Lam S.L <alexlamsl@gmail.com>
Fri, 17 Apr 2020 18:53:26 +0000 (19:53 +0100)
committerGitHub <noreply@github.com>
Fri, 17 Apr 2020 18:53:26 +0000 (02:53 +0800)
fixes #3789
fixes #3791

lib/compress.js
test/compress/collapse_vars.js
test/compress/join_vars.js
test/ufuzz/index.js

index 2491757..70ac9b8 100644 (file)
@@ -2330,7 +2330,7 @@ merge(Compressor.prototype, {
             statements.length = n;
         }
 
-        function join_assigns(defn, body) {
+        function join_assigns(defn, body, keep) {
             var exprs;
             if (body instanceof AST_Assign) {
                 exprs = [ body ];
@@ -2352,14 +2352,14 @@ merge(Compressor.prototype, {
             if (defn instanceof AST_Definitions) {
                 var def = defn.definitions[defn.definitions.length - 1];
                 if (trim_assigns(def.name, def.value, exprs)) trimmed = true;
-                if (join_var_assign(defn.definitions, exprs)) trimmed = true;
+                if (join_var_assign(defn.definitions, exprs, keep || 0)) trimmed = true;
             }
             return trimmed && exprs;
         }
 
-        function join_var_assign(definitions, exprs) {
+        function join_var_assign(definitions, exprs, keep) {
             var trimmed = false;
-            while (exprs.length) {
+            while (exprs.length > keep) {
                 var expr = exprs[0];
                 if (!(expr instanceof AST_Assign)) break;
                 if (expr.operator != "=") break;
@@ -2367,7 +2367,9 @@ merge(Compressor.prototype, {
                 if (!(lhs instanceof AST_SymbolRef)) break;
                 if (is_undeclared_ref(lhs)) break;
                 var def = lhs.definition();
-                if (def.scope !== definitions[0].name.scope) break;
+                if (def.scope !== lhs.scope) break;
+                if (def.orig.length > def.eliminated + 1) break;
+                if (def.orig[0].TYPE != "SymbolVar") break;
                 var name = make_node(AST_SymbolVar, lhs, lhs);
                 definitions.push(make_node(AST_VarDef, expr, {
                     name: name,
@@ -2478,7 +2480,7 @@ merge(Compressor.prototype, {
 
             function join_assigns_expr(value) {
                 statements[++j] = stat;
-                var exprs = join_assigns(prev, value);
+                var exprs = join_assigns(prev, value, 1);
                 if (!exprs) return value;
                 CHANGED = true;
                 var tail = value.tail_node();
@@ -6045,11 +6047,21 @@ merge(Compressor.prototype, {
 
         function can_inject_symbols() {
             var catches = Object.create(null);
+            var child;
+            scope = compressor.self();
             do {
+                child = scope;
                 scope = compressor.parent(++level);
                 if (scope instanceof AST_Catch) {
                     catches[scope.argname.name] = true;
-                } else if (scope instanceof AST_IterationStatement) {
+                } else if (scope instanceof AST_DWLoop) {
+                    in_loop = [];
+                } else if (scope instanceof AST_For) {
+                    if (scope.init === child) continue;
+                    in_loop = [];
+                } else if (scope instanceof AST_ForIn) {
+                    if (scope.init === child) continue;
+                    if (scope.object === child) continue;
                     in_loop = [];
                 } else if (scope instanceof AST_SymbolRef) {
                     if (scope.fixed_value() instanceof AST_Scope) return false;
index a916726..fd421a2 100644 (file)
@@ -804,7 +804,7 @@ collapse_vars_assignment: {
         function log(x) { return console.log(x), x; }
         function f0(c) {
             var a = 3 / c;
-            return a;
+            return a = a;
         }
         function f1(c) {
             return 1 - 3 / c;
index bfbebde..9901c48 100644 (file)
@@ -663,3 +663,122 @@ issue_3788: {
         "PASS",
     ]
 }
+
+issue_3789_1: {
+    options = {
+        join_vars: true,
+    }
+    input: {
+        try {
+            c;
+            console.log("FAIL");
+        } catch (e) {
+            console.log("PASS");
+        }
+        try {} catch (c) {
+            var a;
+            c = 0;
+        }
+    }
+    expect: {
+        try {
+            c;
+            console.log("FAIL");
+        } catch (e) {
+            console.log("PASS");
+        }
+        try {} catch (c) {
+            var a;
+            c = 0;
+        }
+    }
+    expect_stdout: "PASS"
+}
+
+issue_3789_2: {
+    options = {
+        join_vars: true,
+    }
+    input: {
+        try {
+            c;
+            console.log("FAIL");
+        } catch (e) {
+            console.log("PASS");
+        }
+        try {} catch (c) {
+            try {} catch (c) {
+                var a;
+                c = 0;
+            }
+        }
+    }
+    expect: {
+        try {
+            c;
+            console.log("FAIL");
+        } catch (e) {
+            console.log("PASS");
+        }
+        try {} catch (c) {
+            try {} catch (c) {
+                var a;
+                c = 0;
+            }
+        }
+    }
+    expect_stdout: "PASS"
+}
+
+issue_3791_1: {
+    options = {
+        collapse_vars: true,
+        join_vars: true,
+        toplevel: true,
+    }
+    input: {
+        var a = "PASS";
+        switch (a) {
+          case console:
+        }
+        var a = a;
+        console.log(a);
+    }
+    expect: {
+        var a;
+        switch (a = "PASS") {
+          case console:
+        }
+        var a = a;
+        console.log(a);
+    }
+    expect_stdout: "PASS"
+}
+
+issue_3791_2: {
+    options = {
+        collapse_vars: true,
+        join_vars: true,
+    }
+    input: {
+        function f(a) {
+            var b;
+            return b = a || g;
+            function g() {
+                return b;
+            }
+        }
+        console.log(typeof f()());
+    }
+    expect: {
+        function f(a) {
+            var b;
+            return b = a || g;
+            function g() {
+                return b;
+            }
+        }
+        console.log(typeof f()());
+    }
+    expect_stdout: "function"
+}
index 24bf86d..ec2a442 100644 (file)
@@ -1156,7 +1156,7 @@ for (var round = 1; round <= num_iterations; round++) {
             uglify_code = uglify_code.code;
             uglify_result = sandbox.run_code(uglify_code, toplevel);
             ok = sandbox.same_stdout(original_result, uglify_result);
-            if (!ok && typeof uglify_result == "string" && o.compress.unsafe_math) {
+            if (!ok && typeof uglify_result == "string" && o.compress && o.compress.unsafe_math) {
                 ok = fuzzy_match(original_result, uglify_result);
                 if (!ok) {
                     var fuzzy_result = sandbox.run_code(original_code.replace(/( - 0\.1){3}/g, " - 0.3"), toplevel);