enhance `sequences` (#3693)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 28 Jan 2020 01:58:01 +0000 (09:58 +0800)
committerGitHub <noreply@github.com>
Tue, 28 Jan 2020 01:58:01 +0000 (09:58 +0800)
lib/compress.js
test/compress/functions.js
test/compress/sequences.js

index e14d9d0..2a338ba 100644 (file)
@@ -5400,25 +5400,32 @@ merge(Compressor.prototype, {
         return self.definitions.length ? self : make_node(AST_EmptyStatement, self);
     });
 
-    AST_Call.DEFMETHOD("lift_sequences", function(compressor) {
-        if (!compressor.option("sequences")) return this;
-        var exp = this.expression;
-        if (!(exp instanceof AST_Sequence)) return this;
-        var tail = exp.tail_node();
-        if (needs_unbinding(compressor, tail) && !(this instanceof AST_New)) return this;
-        var expressions = exp.expressions.slice(0, -1);
-        var node = this.clone();
-        node.expression = tail;
-        expressions.push(node);
-        return make_sequence(this, expressions).optimize(compressor);
-    });
+    function lift_sequence_in_expression(node, compressor) {
+        var exp = node.expression;
+        if (!(exp instanceof AST_Sequence)) return node;
+        var x = exp.expressions.slice();
+        var e = node.clone();
+        e.expression = x.pop();
+        x.push(e);
+        return make_sequence(node, x);
+    }
 
     OPT(AST_Call, function(self, compressor) {
-        var seq = self.lift_sequences(compressor);
-        if (seq !== self) {
-            return seq;
-        }
         var exp = self.expression;
+        if (compressor.option("sequences")) {
+            if (exp instanceof AST_PropAccess) {
+                var seq = lift_sequence_in_expression(exp, compressor);
+                if (seq !== exp) {
+                    var call = self.clone();
+                    call.expression = seq.expressions.pop();
+                    seq.expressions.push(call);
+                    return seq.optimize(compressor);
+                }
+            } else if (!needs_unbinding(compressor, exp.tail_node())) {
+                var seq = lift_sequence_in_expression(self, compressor);
+                if (seq !== self) return seq.optimize(compressor);
+            }
+        }
         var fn = exp;
         if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) {
             fn = fn.fixed_value();
@@ -5989,9 +5996,9 @@ merge(Compressor.prototype, {
     });
 
     OPT(AST_New, function(self, compressor) {
-        var seq = self.lift_sequences(compressor);
-        if (seq !== self) {
-            return seq;
+        if (compressor.option("sequences")) {
+            var seq = lift_sequence_in_expression(self, compressor);
+            if (seq !== self) return seq.optimize(compressor);
         }
         if (compressor.option("unsafe")) {
             var exp = self.expression;
@@ -6047,19 +6054,12 @@ merge(Compressor.prototype, {
         }
     });
 
-    AST_Unary.DEFMETHOD("lift_sequences", function(compressor) {
-        if (compressor.option("sequences") && this.expression instanceof AST_Sequence) {
-            var x = this.expression.expressions.slice();
-            var e = this.clone();
-            e.expression = x.pop();
-            x.push(e);
-            return make_sequence(this, x).optimize(compressor);
-        }
-        return this;
-    });
-
     OPT(AST_UnaryPostfix, function(self, compressor) {
-        return self.lift_sequences(compressor);
+        if (compressor.option("sequences")) {
+            var seq = lift_sequence_in_expression(self, compressor);
+            if (seq !== self) return seq.optimize(compressor);
+        }
+        return self;
     });
 
     OPT(AST_UnaryPrefix, function(self, compressor) {
@@ -6076,9 +6076,9 @@ merge(Compressor.prototype, {
             }
             return make_sequence(self, [ e, make_node(AST_True, self) ]).optimize(compressor);
         }
-        var seq = self.lift_sequences(compressor);
-        if (seq !== self) {
-            return seq;
+        if (compressor.option("sequences")) {
+            var seq = lift_sequence_in_expression(self, compressor);
+            if (seq !== self) return seq.optimize(compressor);
         }
         if (compressor.option("side_effects") && self.operator == "void") {
             e = e.drop_side_effect_free(compressor);
@@ -6211,7 +6211,8 @@ merge(Compressor.prototype, {
             // result.  hence, force switch.
             reverse();
         }
-        self = self.lift_sequences(compressor);
+        var seq = self.lift_sequences(compressor);
+        if (seq !== self) return seq;
         if (compressor.option("assignments") && lazy_op[self.operator]) {
             var assign = self.right;
             // a || (a = x) => a = a || x
@@ -7127,7 +7128,8 @@ merge(Compressor.prototype, {
                     || parent instanceof AST_UnaryPrefix);
             }
         }
-        self = self.lift_sequences(compressor);
+        var seq = self.lift_sequences(compressor);
+        if (seq !== self) return seq;
         if (!compressor.option("assignments")) return self;
         if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) {
             // x = expr1 OP expr2
@@ -7486,6 +7488,10 @@ merge(Compressor.prototype, {
     }
 
     OPT(AST_Sub, function(self, compressor) {
+        if (compressor.option("sequences") && compressor.parent().TYPE != "Call") {
+            var seq = lift_sequence_in_expression(self, compressor);
+            if (seq !== self) return seq.optimize(compressor);
+        }
         var expr = self.expression;
         var prop = self.property;
         if (compressor.option("properties")) {
@@ -7650,6 +7656,10 @@ merge(Compressor.prototype, {
     });
 
     OPT(AST_Dot, function(self, compressor) {
+        if (compressor.option("sequences") && compressor.parent().TYPE != "Call") {
+            var seq = lift_sequence_in_expression(self, compressor);
+            if (seq !== self) return seq.optimize(compressor);
+        }
         if (self.property == "arguments" || self.property == "caller") {
             AST_Node.warn("Function.prototype.{prop} not supported [{file}:{line},{col}]", {
                 prop: self.property,
index c8bced5..ef51af7 100644 (file)
@@ -2244,7 +2244,7 @@ issue_3076: {
         var c = "PASS";
         (function(b) {
             var n = 2;
-            while (--b + (e = void 0, e && (c = "FAIL"), e = 5, 1).toString() && --n > 0);
+            while (--b + (e = void 0, e && (c = "FAIL"), e = 5, 1..toString()) && --n > 0);
             var e;
         })(2),
         console.log(c);
index fbca559..648f649 100644 (file)
@@ -910,15 +910,23 @@ call: {
             console.log(this === b ? "bar" : "baz");
         };
         (a, b)();
+        (a, b).c();
         (a, b.c)();
+        (a, b)["c"]();
+        (a, b["c"])();
         (a, function() {
             console.log(this === a);
         })();
         new (a, b)();
+        new (a, b).c();
         new (a, b.c)();
+        new (a, b)["c"]();
+        new (a, b["c"])();
         new (a, function() {
             console.log(this === a);
         })();
+        console.log(typeof (a, b).c);
+        console.log(typeof (a, b)["c"]);
     }
     expect: {
         var a = function() {
@@ -931,23 +939,39 @@ call: {
             console.log(this === b ? "bar" : "baz");
         },
         b(),
+        b.c(),
         (a, b.c)(),
+        b["c"](),
+        (a, b["c"])(),
         function() {
             console.log(this === a);
         }(),
         new b(),
         new b.c(),
+        new b.c(),
+        new b["c"](),
+        new b["c"](),
         new function() {
             console.log(this === a);
-        }();
+        }(),
+        console.log((a, typeof b.c)),
+        console.log((a, typeof b["c"]));
     }
     expect_stdout: [
         "foo",
+        "bar",
+        "baz",
+        "bar",
         "baz",
         "true",
         "foo",
         "baz",
+        "baz",
+        "baz",
+        "baz",
         "false",
+        "function",
+        "function",
     ]
 }