From: Alex Lam S.L Date: Wed, 29 Aug 2018 17:06:34 +0000 (+0800) Subject: enhance `conditionals` (#3243) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=2bdaca10ae05136843d8e99da50925091a593373;p=UglifyJS.git enhance `conditionals` (#3243) --- diff --git a/lib/compress.js b/lib/compress.js index 9e4ab315..53ed4afc 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -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 diff --git a/test/compress/conditionals.js b/test/compress/conditionals.js index 577e7871..35505c87 100644 --- a/test/compress/conditionals.js +++ b/test/compress/conditionals.js @@ -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", + ] +}