enhance `booleans` (#3661)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 31 Dec 2019 05:10:05 +0000 (13:10 +0800)
committerGitHub <noreply@github.com>
Tue, 31 Dec 2019 05:10:05 +0000 (13:10 +0800)
lib/ast.js
lib/compress.js
test/compress/collapse_vars.js
test/compress/transform.js

index 11d1f36..f205235 100644 (file)
@@ -964,12 +964,13 @@ TreeWalker.prototype = {
     in_boolean_context: function() {
         var self = this.self();
         for (var i = 0, p; p = this.parent(i); i++) {
-            if (p instanceof AST_SimpleStatement
-                || p instanceof AST_Conditional && p.condition === self
+            if (p instanceof AST_Conditional && p.condition === self
                 || p instanceof AST_DWLoop && p.condition === self
                 || p instanceof AST_For && p.condition === self
                 || p instanceof AST_If && p.condition === self
                 || p instanceof AST_Return && p.in_bool
+                || p instanceof AST_Sequence && p.tail_node() !== self
+                || p instanceof AST_SimpleStatement
                 || p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
                 return true;
             }
index 3f6bc89..38d0906 100644 (file)
@@ -2021,6 +2021,7 @@ merge(Compressor.prototype, {
 
                 if (stat instanceof AST_If && stat.body instanceof AST_Return) {
                     var value = stat.body.value;
+                    var in_bool = stat.body.in_bool || next instanceof AST_Return && next.in_bool;
                     //---
                     // pretty silly case, but:
                     // if (foo()) return; return; => foo(); return;
@@ -2034,7 +2035,7 @@ merge(Compressor.prototype, {
                     }
                     //---
                     // if (foo()) return x; return y; => return foo() ? x : y;
-                    if (value && !stat.alternative && next instanceof AST_Return && next.value) {
+                    if ((in_bool || value) && !stat.alternative && next instanceof AST_Return) {
                         CHANGED = true;
                         stat = stat.clone();
                         stat.alternative = next;
@@ -2044,16 +2045,13 @@ merge(Compressor.prototype, {
                     }
                     //---
                     // if (foo()) return x; [ return ; ] => return foo() ? x : undefined;
-                    if (value && !stat.alternative
-                        && (!next && in_lambda && multiple_if_returns
-                            || next instanceof AST_Return)) {
+                    if (!stat.alternative && !next && in_lambda && (in_bool || value && multiple_if_returns)) {
                         CHANGED = true;
                         stat = stat.clone();
-                        stat.alternative = next || make_node(AST_Return, stat, {
+                        stat.alternative = make_node(AST_Return, stat, {
                             value: null
                         });
                         statements.splice(i, 1, stat.transform(compressor));
-                        if (next) statements.splice(j, 1);
                         continue;
                     }
                     //---
@@ -5104,13 +5102,17 @@ merge(Compressor.prototype, {
         if (self.body instanceof AST_Exit
             && self.alternative instanceof AST_Exit
             && self.body.TYPE == self.alternative.TYPE) {
-            return make_node(self.body.CTOR, self, {
+            var exit = make_node(self.body.CTOR, self, {
                 value: make_node(AST_Conditional, self, {
                     condition   : self.condition,
                     consequent  : self.body.value || make_node(AST_Undefined, self.body),
                     alternative : self.alternative.value || make_node(AST_Undefined, self.alternative)
-                }).transform(compressor)
-            }).optimize(compressor);
+                })
+            });
+            if (exit instanceof AST_Return) {
+                exit.in_bool = self.body.in_bool || self.alternative.in_bool;
+            }
+            return exit;
         }
         if (self.body instanceof AST_If
             && !self.body.alternative
@@ -7321,12 +7323,15 @@ merge(Compressor.prototype, {
                     && node.expression instanceof AST_Constant
                     && !node.expression.value);
         }
-        // AST_False or !1
+        // AST_False or !1 or void 0
         function is_false(node) {
             return node instanceof AST_False
                 || in_bool
-                    && node instanceof AST_Constant
-                    && !node.value
+                    && (node instanceof AST_Constant
+                            && !node.value
+                        || node instanceof AST_UnaryPrefix
+                            && node.operator == "void"
+                            && !node.expression.has_side_effects(compressor))
                 || (node instanceof AST_UnaryPrefix
                     && node.operator == "!"
                     && node.expression instanceof AST_Constant
index 796fdb3..a597527 100644 (file)
@@ -5863,8 +5863,8 @@ issue_2974: {
         var c = 0;
         (function(b) {
             var a = 2;
-            for (; b.null = -4, c++, b.null && --a > 0;);
-        })(!0),
+            for (;c++, (!0).null && --a > 0;);
+        })(),
         console.log(c);
     }
     expect_stdout: "1"
index 867b8ad..66f19bd 100644 (file)
@@ -103,6 +103,7 @@ if_return: {
         booleans: true,
         conditionals: true,
         if_return: true,
+        passes: 2,
         sequences: true,
         side_effects: true,
     }