fix corner case in `conditionals` (#5233)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 23 Dec 2021 14:25:02 +0000 (14:25 +0000)
committerGitHub <noreply@github.com>
Thu, 23 Dec 2021 14:25:02 +0000 (22:25 +0800)
fixes #5232

lib/compress.js
test/compress/conditionals.js
test/reduce.js

index b48d7bc..46b59b9 100644 (file)
@@ -8792,17 +8792,58 @@ Compressor.prototype.compress = function(node) {
             self.body = self.alternative || make_node(AST_EmptyStatement, self);
             self.alternative = tmp;
         }
-        var body = [], var_defs = [], refs = [];
-        var body_exprs = sequencesize(self.body, body, var_defs, refs);
-        var alt_exprs = sequencesize(self.alternative, body, var_defs, refs);
+        var body_defuns = [];
+        var body_var_defs = [];
+        var body_refs = [];
+        var body_exprs = sequencesize(self.body, body_defuns, body_var_defs, body_refs);
+        var alt_defuns = [];
+        var alt_var_defs = [];
+        var alt_refs = [];
+        var alt_exprs = sequencesize(self.alternative, alt_defuns, alt_var_defs, alt_refs);
         if (body_exprs instanceof AST_BlockStatement || alt_exprs instanceof AST_BlockStatement) {
+            var body = [], var_defs = [];
+            if (body_exprs) {
+                [].push.apply(body, body_defuns);
+                [].push.apply(var_defs, body_var_defs);
+                if (body_exprs instanceof AST_BlockStatement) {
+                    self.body = body_exprs;
+                } else if (body_exprs.length == 0) {
+                    self.body = make_node(AST_EmptyStatement, self.body);
+                } else {
+                    self.body = make_node(AST_SimpleStatement, self.body, {
+                        body: make_sequence(self.body, body_exprs),
+                    });
+                }
+                body_refs.forEach(function(ref) {
+                    ref.definition().references.push(ref);
+                });
+            }
+            if (alt_exprs) {
+                [].push.apply(body, alt_defuns);
+                [].push.apply(var_defs, alt_var_defs);
+                if (alt_exprs instanceof AST_BlockStatement) {
+                    self.alternative = alt_exprs;
+                } else if (alt_exprs.length == 0) {
+                    self.alternative = null;
+                } else {
+                    self.alternative = make_node(AST_SimpleStatement, self.alternative, {
+                        body: make_sequence(self.alternative, alt_exprs),
+                    });
+                }
+                alt_refs.forEach(function(ref) {
+                    ref.definition().references.push(ref);
+                });
+            }
             if (var_defs.length > 0) body.push(make_node(AST_Var, self, { definitions: var_defs }));
-            body.push(self);
-            if (body_exprs instanceof AST_BlockStatement) self.body = body_exprs;
-            if (alt_exprs instanceof AST_BlockStatement) self.alternative = alt_exprs;
-            return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
+            if (body.length > 0) {
+                body.push(self);
+                return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
+            }
         } else if (body_exprs && alt_exprs) {
-            if (var_defs.length > 0) body.push(make_node(AST_Var, self, { definitions: var_defs }));
+            var body = body_defuns.concat(alt_defuns);
+            if (body_var_defs.length > 0 || alt_var_defs.length > 0) body.push(make_node(AST_Var, self, {
+                definitions: body_var_defs.concat(alt_var_defs),
+            }));
             if (body_exprs.length == 0) {
                 body.push(make_node(AST_SimpleStatement, self.condition, {
                     body: alt_exprs.length > 0 ? make_node(AST_Binary, self, {
@@ -8835,7 +8876,10 @@ Compressor.prototype.compress = function(node) {
                     }),
                 }).optimize(compressor));
             }
-            refs.forEach(function(ref) {
+            body_refs.forEach(function(ref) {
+                ref.definition().references.push(ref);
+            });
+            alt_refs.forEach(function(ref) {
                 ref.definition().references.push(ref);
             });
             return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
index 84559c3..a7a9607 100644 (file)
@@ -1924,3 +1924,86 @@ object_super: {
     expect_stdout: "PASS"
     node_version: ">=4"
 }
+
+issue_5232_1: {
+    options = {
+        conditionals: true,
+    }
+    input: {
+        (function() {
+            if (Math) {
+                function f() {}
+                for (var a in [ 42 ])
+                    console.log(typeof f);
+            } else {
+                var b = null;
+                return true;
+            }
+        })();
+    }
+    expect: {
+        (function() {
+            var b;
+            if (!Math)
+                return b = null, true;
+            function f() {}
+            for (var a in [ 42 ]) console.log(typeof f);
+        })();
+    }
+    expect_stdout: "function"
+}
+
+issue_5232_2: {
+    options = {
+        conditionals: true,
+    }
+    input: {
+        console.log(function() {
+            if (!Math);
+            else {
+                var b = null;
+                return "PASS";
+            }
+        }());
+    }
+    expect: {
+        console.log(function() {
+            var b;
+            if (Math)
+                return b = null, "PASS";
+        }());
+    }
+    expect_stdout: "PASS"
+}
+
+issue_5232_3: {
+    options = {
+        conditionals: true,
+    }
+    input: {
+        console.log(function() {
+            return function() {
+                if (console)
+                    console.log("PASS");
+                else {
+                    var a = null;
+                    return "FAIL";
+                }
+            };
+        }()());
+    }
+    expect: {
+        console.log(function() {
+            return function() {
+                var a;
+                if (!console)
+                    return a = null, "FAIL";
+                console.log("PASS");
+            };
+        }()());
+    }
+    expect_stdout: [
+        "PASS",
+        "undefined",
+    ]
+}
index 30272de..28d06c4 100644 (file)
@@ -548,7 +548,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
             }));
             var before_iterations = testcase;
             for (var c = 0; c < max_iterations; ++c) {
-                if (verbose && pass == 1 && c % 25 == 0) {
+                if (verbose && c % (pass == 1 ? 25 : 100) == 0) {
                     log("// reduce test pass " + pass + ", iteration " + c + ": " + testcase.length + " bytes");
                 }
                 var CHANGED = false;