enhance `conditionals` (#3243)
authorAlex Lam S.L <alexlamsl@gmail.com>
Wed, 29 Aug 2018 17:06:34 +0000 (01:06 +0800)
committerGitHub <noreply@github.com>
Wed, 29 Aug 2018 17:06:34 +0000 (01:06 +0800)
lib/compress.js
test/compress/conditionals.js

index 9e4ab31..53ed4af 100644 (file)
@@ -6047,20 +6047,22 @@ merge(Compressor.prototype, {
         //                   |
         //                   v
         // exp = foo ? something : something_else;
-        if (consequent instanceof AST_Assign
-            && alternative instanceof AST_Assign
-            && consequent.operator == alternative.operator
-            && consequent.left.equivalent_to(alternative.left)
-            && (!self.condition.has_side_effects(compressor)
-                || consequent.operator == "="
-                    && !consequent.left.has_side_effects(compressor))) {
+        var seq_tail = consequent.tail_node();
+        var alt_tail = alternative.tail_node();
+        if (seq_tail instanceof AST_Assign
+            && alt_tail instanceof AST_Assign
+            && seq_tail.operator == alt_tail.operator
+            && seq_tail.left.equivalent_to(alt_tail.left)
+            && (!condition.has_side_effects(compressor)
+                || seq_tail.operator == "="
+                    && !seq_tail.left.has_side_effects(compressor))) {
             return make_node(AST_Assign, self, {
-                operator: consequent.operator,
-                left: consequent.left,
+                operator: seq_tail.operator,
+                left: seq_tail.left,
                 right: make_node(AST_Conditional, self, {
-                    condition: self.condition,
-                    consequent: consequent.right,
-                    alternative: alternative.right
+                    condition: condition,
+                    consequent: pop_lhs(consequent),
+                    alternative: pop_lhs(alternative)
                 })
             });
         }
@@ -6071,12 +6073,12 @@ merge(Compressor.prototype, {
             && consequent.args.length > 0
             && consequent.args.length == alternative.args.length
             && consequent.expression.equivalent_to(alternative.expression)
-            && !self.condition.has_side_effects(compressor)
+            && !condition.has_side_effects(compressor)
             && !consequent.expression.has_side_effects(compressor)
             && typeof (arg_index = single_arg_diff()) == "number") {
             var node = consequent.clone();
             node.args[arg_index] = make_node(AST_Conditional, self, {
-                condition: self.condition,
+                condition: condition,
                 consequent: consequent.args[arg_index],
                 alternative: alternative.args[arg_index]
             });
@@ -6087,7 +6089,7 @@ merge(Compressor.prototype, {
             && consequent.alternative.equivalent_to(alternative)) {
             return make_node(AST_Conditional, self, {
                 condition: make_node(AST_Binary, self, {
-                    left: self.condition,
+                    left: condition,
                     operator: "&&",
                     right: consequent.condition
                 }),
@@ -6098,7 +6100,7 @@ merge(Compressor.prototype, {
         // x ? y : y --> x, y
         if (consequent.equivalent_to(alternative)) {
             return make_sequence(self, [
-                self.condition,
+                condition,
                 consequent
             ]).optimize(compressor);
         }
@@ -6107,7 +6109,7 @@ merge(Compressor.prototype, {
             && consequent.tail_node().equivalent_to(alternative.tail_node())) {
             return make_sequence(self, [
                 make_node(AST_Conditional, self, {
-                    condition: self.condition,
+                    condition: condition,
                     consequent: pop_seq(consequent),
                     alternative: pop_seq(alternative)
                 }),
@@ -6122,7 +6124,7 @@ merge(Compressor.prototype, {
                 operator: "||",
                 left: make_node(AST_Binary, self, {
                     operator: "&&",
-                    left: self.condition,
+                    left: condition,
                     right: consequent.left
                 }),
                 right: alternative
@@ -6132,24 +6134,24 @@ merge(Compressor.prototype, {
         if (is_true(self.consequent)) {
             if (is_false(self.alternative)) {
                 // c ? true : false ---> !!c
-                return booleanize(self.condition);
+                return booleanize(condition);
             }
             // c ? true : x ---> !!c || x
             return make_node(AST_Binary, self, {
                 operator: "||",
-                left: booleanize(self.condition),
+                left: booleanize(condition),
                 right: self.alternative
             });
         }
         if (is_false(self.consequent)) {
             if (is_true(self.alternative)) {
                 // c ? false : true ---> !c
-                return booleanize(self.condition.negate(compressor));
+                return booleanize(condition.negate(compressor));
             }
             // c ? false : x ---> !c && x
             return make_node(AST_Binary, self, {
                 operator: "&&",
-                left: booleanize(self.condition.negate(compressor)),
+                left: booleanize(condition.negate(compressor)),
                 right: self.alternative
             });
         }
@@ -6157,7 +6159,7 @@ merge(Compressor.prototype, {
             // c ? x : true ---> !c || x
             return make_node(AST_Binary, self, {
                 operator: "||",
-                left: booleanize(self.condition.negate(compressor)),
+                left: booleanize(condition.negate(compressor)),
                 right: self.consequent
             });
         }
@@ -6165,7 +6167,7 @@ merge(Compressor.prototype, {
             // c ? x : false ---> !!c && x
             return make_node(AST_Binary, self, {
                 operator: "&&",
-                left: booleanize(self.condition),
+                left: booleanize(condition),
                 right: self.consequent
             });
         }
@@ -6217,6 +6219,13 @@ merge(Compressor.prototype, {
             }
         }
 
+        function pop_lhs(node) {
+            if (!(node instanceof AST_Sequence)) return node.right;
+            var exprs = node.expressions.slice();
+            exprs.push(exprs.pop().right);
+            return make_sequence(node, exprs);
+        }
+
         function pop_seq(node) {
             if (!(node instanceof AST_Sequence)) return make_node(AST_Number, node, {
                 value: 0
index 577e787..35505c8 100644 (file)
@@ -1292,3 +1292,75 @@ to_and_or: {
     }
     expect_stdout: true
 }
+
+cond_seq_assign_1: {
+    options = {
+        conditionals: true,
+        sequences: true,
+    }
+    input: {
+        function f(a) {
+            var t;
+            if (a) {
+                t = "foo";
+                t = "bar";
+            } else {
+                console.log(t);
+                t = 42;
+            }
+            console.log(t);
+        }
+        f(f);
+        f();
+    }
+    expect: {
+        function f(a) {
+            var t;
+            t = a ? (t = "foo", "bar") : (console.log(t), 42),
+            console.log(t);
+        }
+        f(f),
+        f();
+    }
+    expect_stdout: [
+        "bar",
+        "undefined",
+        "42",
+    ]
+}
+
+cond_seq_assign_2: {
+    options = {
+        conditionals: true,
+        sequences: true,
+    }
+    input: {
+        function f(a) {
+            var t;
+            if (a) {
+                t = "foo";
+                a = "bar";
+            } else {
+                console.log(t);
+                t = 42;
+            }
+            console.log(t);
+        }
+        f(f);
+        f();
+    }
+    expect: {
+        function f(a) {
+            var t;
+            a ? (t = "foo", a = "bar") : (console.log(t), t = 42),
+            console.log(t);
+        }
+        f(f),
+        f();
+    }
+    expect_stdout: [
+        "foo",
+        "undefined",
+        "42",
+    ]
+}