From: Alex Lam S.L Date: Thu, 3 May 2018 11:14:56 +0000 (+0800) Subject: compress `AST_Sequence` within `AST_Call` (#3117) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=d51a00a4508022e54e257d93442abff42c4442b7;p=UglifyJS.git compress `AST_Sequence` within `AST_Call` (#3117) --- diff --git a/lib/compress.js b/lib/compress.js index 60293187..49abc54b 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -908,7 +908,7 @@ merge(Compressor.prototype, { // the func (becomes lexical instead of global). function maintain_this_binding(parent, orig, val) { if (parent instanceof AST_UnaryPrefix && parent.operator == "delete" - || parent instanceof AST_Call && parent.expression === orig + || parent.TYPE == "Call" && parent.expression === orig && (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name == "eval")) { return make_sequence(orig, [ make_node(AST_Number, orig, { value: 0 }), val ]); } @@ -4456,7 +4456,24 @@ merge(Compressor.prototype, { return self; }); - OPT(AST_Call, function(self, compressor){ + 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 (tail instanceof AST_PropAccess && !(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); + }); + + OPT(AST_Call, function(self, compressor) { + var seq = self.lift_sequences(compressor); + if (seq !== self) { + return seq; + } var exp = self.expression; var fn = exp; if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) { @@ -4964,7 +4981,11 @@ merge(Compressor.prototype, { } }); - OPT(AST_New, function(self, compressor){ + OPT(AST_New, function(self, compressor) { + var seq = self.lift_sequences(compressor); + if (seq !== self) { + return seq; + } if (compressor.option("unsafe")) { var exp = self.expression; if (is_undeclared_ref(exp)) { @@ -5020,14 +5041,12 @@ merge(Compressor.prototype, { }); AST_Unary.DEFMETHOD("lift_sequences", function(compressor){ - if (compressor.option("sequences")) { - if (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); - } + 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; }); diff --git a/test/compress/sequences.js b/test/compress/sequences.js index 12acbcf7..8aede12b 100644 --- a/test/compress/sequences.js +++ b/test/compress/sequences.js @@ -876,3 +876,59 @@ forin: { } expect_stdout: "PASS" } + +call: { + options = { + sequences: true, + } + input: { + var a = function() { + return this; + }(); + function b() { + console.log("foo"); + } + b.c = function() { + console.log(this === b ? "bar" : "baz"); + }; + (a, b)(); + (a, b.c)(); + (a, function() { + console.log(this === a); + })(); + new (a, b)(); + new (a, b.c)(); + new (a, function() { + console.log(this === a); + })(); + } + expect: { + var a = function() { + return this; + }(); + function b() { + console.log("foo"); + } + b.c = function() { + console.log(this === b ? "bar" : "baz"); + }, + a, b(), + (a, b.c)(), + a, function() { + console.log(this === a); + }(), + a, new b(), + a, new b.c(), + a, new function() { + console.log(this === a); + }(); + } + expect_stdout: [ + "foo", + "baz", + "true", + "foo", + "baz", + "false", + ] +}