From df506439b16c550f7e8da30b392f17b0ca4c2e4a Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Tue, 4 Feb 2020 04:57:32 +0000 Subject: [PATCH] fix corner case in `sequences` (#3704) fixes #3703 --- lib/compress.js | 89 ++++++++++++++++++++++---------------- lib/output.js | 2 + test/compress/sequences.js | 19 ++++++++ 3 files changed, 72 insertions(+), 38 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 5d14963f..32d0b67d 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -6162,34 +6162,43 @@ merge(Compressor.prototype, { }); AST_Binary.DEFMETHOD("lift_sequences", function(compressor) { - if (compressor.option("sequences")) { - if (this.left instanceof AST_Sequence) { - var x = this.left.expressions.slice(); + if (this.left instanceof AST_PropAccess) { + if (!(this.left.expression instanceof AST_Sequence)) return this; + var x = this.left.expression.expressions.slice(); + var e = this.clone(); + e.left = e.left.clone(); + e.left.expression = x.pop(); + x.push(e); + return make_sequence(this, x); + } + if (this.left instanceof AST_Sequence) { + var x = this.left.expressions.slice(); + var e = this.clone(); + e.left = x.pop(); + x.push(e); + return make_sequence(this, x); + } + if (this.right instanceof AST_Sequence) { + if (this.left.has_side_effects(compressor)) return this; + var assign = this.operator == "=" && this.left instanceof AST_SymbolRef; + var x = this.right.expressions; + var last = x.length - 1; + for (var i = 0; i < last; i++) { + if (!assign && x[i].has_side_effects(compressor)) break; + } + if (i == last) { + x = x.slice(); var e = this.clone(); - e.left = x.pop(); + e.right = x.pop(); x.push(e); - return make_sequence(this, x).optimize(compressor); - } - if (this.right instanceof AST_Sequence && !this.left.has_side_effects(compressor)) { - var assign = this.operator == "=" && this.left instanceof AST_SymbolRef; - var x = this.right.expressions; - var last = x.length - 1; - for (var i = 0; i < last; i++) { - if (!assign && x[i].has_side_effects(compressor)) break; - } - if (i == last) { - x = x.slice(); - var e = this.clone(); - e.right = x.pop(); - x.push(e); - return make_sequence(this, x).optimize(compressor); - } else if (i > 0) { - var e = this.clone(); - e.right = make_sequence(this.right, x.slice(i)); - x = x.slice(0, i); - x.push(e); - return make_sequence(this, x).optimize(compressor); - } + return make_sequence(this, x); + } + if (i > 0) { + var e = this.clone(); + e.right = make_sequence(this.right, x.slice(i)); + x = x.slice(0, i); + x.push(e); + return make_sequence(this, x); } } return this; @@ -6240,8 +6249,10 @@ merge(Compressor.prototype, { // result. hence, force switch. reverse(); } - var seq = self.lift_sequences(compressor); - if (seq !== self) return seq; + if (compressor.option("sequences")) { + var seq = self.lift_sequences(compressor); + if (seq !== self) return seq.optimize(compressor); + } if (compressor.option("assignments") && lazy_op[self.operator]) { var assign = self.right; // a || (a = x) => a = a || x @@ -7158,8 +7169,10 @@ merge(Compressor.prototype, { || parent instanceof AST_UnaryPrefix); } } - var seq = self.lift_sequences(compressor); - if (seq !== self) return seq; + if (compressor.option("sequences")) { + var seq = self.lift_sequences(compressor); + if (seq !== self) return seq.optimize(compressor); + } if (!compressor.option("assignments")) return self; if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) { // x = expr1 OP expr2 @@ -7587,10 +7600,6 @@ 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")) { @@ -7661,6 +7670,10 @@ merge(Compressor.prototype, { } } if (is_lhs(compressor.self(), parent)) return self; + if (compressor.option("sequences") && compressor.parent().TYPE != "Call") { + var seq = lift_sequence_in_expression(self, compressor); + if (seq !== self) return seq.optimize(compressor); + } if (key !== prop) { var sub = self.flatten_object(property, compressor); if (sub) { @@ -7755,10 +7768,6 @@ 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, @@ -7768,6 +7777,10 @@ merge(Compressor.prototype, { }); } if (is_lhs(compressor.self(), compressor.parent())) return self; + if (compressor.option("sequences") && compressor.parent().TYPE != "Call") { + var seq = lift_sequence_in_expression(self, compressor); + if (seq !== self) return seq.optimize(compressor); + } if (compressor.option("unsafe_proto") && self.expression instanceof AST_Dot && self.expression.property == "prototype") { diff --git a/lib/output.js b/lib/output.js index a63671c6..86c0931e 100644 --- a/lib/output.js +++ b/lib/output.js @@ -783,6 +783,8 @@ function OutputStream(options) { var p = output.parent(); if (p instanceof AST_PropAccess && p.expression === this) { var value = this.value; + // https://github.com/mishoo/UglifyJS2/issues/115 + // https://github.com/mishoo/UglifyJS2/pull/1009 if (value < 0 || /^0/.test(make_num(value))) { return true; } diff --git a/test/compress/sequences.js b/test/compress/sequences.js index 648f6491..c0b77127 100644 --- a/test/compress/sequences.js +++ b/test/compress/sequences.js @@ -1093,3 +1093,22 @@ issue_3490_2: { } expect_stdout: "PASS 42" } + +issue_3703: { + options = { + evaluate: true, + sequences: true, + unsafe: true, + } + input: { + var a = "FAIL"; + while ((a = "PASS", 0).foo = 0); + console.log(a); + } + expect: { + var a = "FAIL"; + while (a = "PASS", (0).foo = 0); + console.log(a); + } + expect_stdout: "PASS" +} -- 2.34.1