enhance `conditionals` (#3798)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sat, 18 Apr 2020 14:32:22 +0000 (15:32 +0100)
committerGitHub <noreply@github.com>
Sat, 18 Apr 2020 14:32:22 +0000 (22:32 +0800)
lib/compress.js
test/compress/conditionals.js
test/compress/drop-unused.js
test/compress/issue-1639.js

index 3aa9f0b..872e2bb 100644 (file)
@@ -5222,50 +5222,53 @@ merge(Compressor.prototype, {
             self.body = self.alternative || make_node(AST_EmptyStatement, self);
             self.alternative = tmp;
         }
-        if (self.body instanceof AST_SimpleStatement
-            && self.alternative instanceof AST_SimpleStatement) {
-            return make_node(AST_SimpleStatement, self, {
-                body: make_node(AST_Conditional, self, {
-                    condition   : self.condition,
-                    consequent  : self.body.body,
-                    alternative : self.alternative.body
-                })
-            }).optimize(compressor);
-        }
-        if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
-            if (self_condition_length === negated_length && !negated_is_best
-                && self.condition instanceof AST_Binary && self.condition.operator == "||") {
-                // although the code length of self.condition and negated are the same,
-                // negated does not require additional surrounding parentheses.
-                // see https://github.com/mishoo/UglifyJS2/issues/979
-                negated_is_best = true;
-            }
-            if (negated_is_best) return make_node(AST_SimpleStatement, self, {
-                body: make_node(AST_Binary, self, {
-                    operator : "||",
-                    left     : negated,
-                    right    : self.body.body
-                }).transform(compressor)
-            }).optimize(compressor);
-            return make_node(AST_SimpleStatement, self, {
-                body: make_node(AST_Binary, self, {
-                    operator : "&&",
-                    left     : self.condition,
-                    right    : self.body.body
-                }).transform(compressor)
+        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);
+        if (body_exprs && alt_exprs) {
+            if (var_defs.length > 0) body.push(make_node(AST_Var, self, {
+                definitions: 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, {
+                        operator : "||",
+                        left     : self.condition,
+                        right    : make_sequence(self.alternative, alt_exprs)
+                    }).transform(compressor) : self.condition.clone()
+                }).optimize(compressor));
+            } else if (alt_exprs.length == 0) {
+                if (self_condition_length === negated_length && !negated_is_best
+                    && self.condition instanceof AST_Binary && self.condition.operator == "||") {
+                    // although the code length of self.condition and negated are the same,
+                    // negated does not require additional surrounding parentheses.
+                    // see https://github.com/mishoo/UglifyJS2/issues/979
+                    negated_is_best = true;
+                }
+                body.push(make_node(AST_SimpleStatement, self, {
+                    body: make_node(AST_Binary, self, {
+                        operator : negated_is_best ? "||" : "&&",
+                        left     : negated_is_best ? negated : self.condition,
+                        right    : make_sequence(self.body, body_exprs)
+                    }).transform(compressor)
+                }).optimize(compressor));
+            } else {
+                body.push(make_node(AST_SimpleStatement, self, {
+                    body: make_node(AST_Conditional, self, {
+                        condition   : self.condition,
+                        consequent  : make_sequence(self.body, body_exprs),
+                        alternative : make_sequence(self.alternative, alt_exprs)
+                    })
+                }).optimize(compressor));
+            }
+            refs.forEach(function(ref) {
+                ref.definition().references.push(ref);
+            });
+            return make_node(AST_BlockStatement, self, {
+                body: body
             }).optimize(compressor);
         }
         if (is_empty(self.body)) {
-            if (is_empty(self.alternative)) return make_node(AST_SimpleStatement, self.condition, {
-                body: self.condition.clone()
-            }).optimize(compressor);
-            if (self.alternative instanceof AST_SimpleStatement) return make_node(AST_SimpleStatement, self, {
-                body: make_node(AST_Binary, self, {
-                    operator : "||",
-                    left     : self.condition,
-                    right    : self.alternative.body
-                }).transform(compressor)
-            }).optimize(compressor);
             self = make_node(AST_If, self, {
                 condition: negated,
                 body: self.alternative,
@@ -5320,6 +5323,56 @@ merge(Compressor.prototype, {
         }
         if (compressor.option("typeofs")) mark_locally_defined(self.condition, self.body, self.alternative);
         return self;
+
+        function sequencesize(stat, defuns, var_defs, refs) {
+            if (stat == null) return [];
+            if (stat instanceof AST_BlockStatement) {
+                var exprs = [];
+                for (var i = 0; i < stat.body.length; i++) {
+                    var line = stat.body[i];
+                    if (line instanceof AST_Defun) {
+                        defuns.push(line);
+                    } else if (line instanceof AST_EmptyStatement) {
+                        continue;
+                    } else if (line instanceof AST_SimpleStatement) {
+                        if (!compressor.option("sequences") && exprs.length > 0) return;
+                        exprs.push(line.body);
+                    } else if (line instanceof AST_Var) {
+                        if (!compressor.option("sequences") && exprs.length > 0) return;
+                        line.definitions.forEach(process_var_def);
+                    } else {
+                        return;
+                    }
+                }
+                return exprs;
+            }
+            if (stat instanceof AST_Defun) {
+                defuns.push(stat);
+                return [];
+            }
+            if (stat instanceof AST_EmptyStatement) return [];
+            if (stat instanceof AST_SimpleStatement) return [ stat.body ];
+            if (stat instanceof AST_Var) {
+                var exprs = [];
+                stat.definitions.forEach(process_var_def);
+                return exprs;
+            }
+
+            function process_var_def(var_def) {
+                var_defs.push(make_node(AST_VarDef, var_def, {
+                    name: var_def.name,
+                    value: null
+                }));
+                if (!var_def.value) return;
+                var ref = make_node(AST_SymbolRef, var_def.name, var_def.name);
+                exprs.push(make_node(AST_Assign, var_def, {
+                    operator: "=",
+                    left: ref,
+                    right: var_def.value
+                }));
+                refs.push(ref);
+            }
+        }
     });
 
     OPT(AST_Switch, function(self, compressor) {
index c4ae909..b78f726 100644 (file)
@@ -1384,7 +1384,7 @@ hoist_decl: {
     }
     expect: {
         var a, b;
-        x() ? y() : z();
+        (x() ? y : z)();
     }
 }
 
index 0f4c6dc..38f132b 100644 (file)
@@ -1173,6 +1173,7 @@ var_catch_toplevel: {
                 x();
             } catch (a) {
                 var a;
+                var a;
             }
         }();
     }
index 1579e06..6633eb2 100644 (file)
@@ -22,8 +22,10 @@ issue_1639_1: {
         console.log(a, b);
     }
     expect: {
-        for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
-            if (--b, 0) var ignore = 0;
+        for (var a = 100, b = 10, L1 = 5; --L1 > 0;) {
+            var ignore;
+            --b;
+        }
         console.log(a, b);
     }
     expect_stdout: "100 6"