From: Alex Lam S.L Date: Tue, 31 Dec 2019 03:51:21 +0000 (+0800) Subject: enhance `evaluate` (#3660) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=a2e4c2fd979782c1dd526fc1ac0b14490adb3344;p=UglifyJS.git enhance `evaluate` (#3660) --- diff --git a/lib/compress.js b/lib/compress.js index 76ad3996..3f6bc893 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -2023,7 +2023,7 @@ merge(Compressor.prototype, { var value = stat.body.value; //--- // pretty silly case, but: - // if (foo()) return; return; ==> foo(); return; + // if (foo()) return; return; => foo(); return; if (!value && !stat.alternative && (in_lambda && !next || next instanceof AST_Return && !next.value)) { CHANGED = true; @@ -2033,7 +2033,7 @@ merge(Compressor.prototype, { continue; } //--- - // if (foo()) return x; return y; ==> return foo() ? x : y; + // if (foo()) return x; return y; => return foo() ? x : y; if (value && !stat.alternative && next instanceof AST_Return && next.value) { CHANGED = true; stat = stat.clone(); @@ -2043,7 +2043,7 @@ merge(Compressor.prototype, { continue; } //--- - // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined; + // if (foo()) return x; [ return ; ] => return foo() ? x : undefined; if (value && !stat.alternative && (!next && in_lambda && multiple_if_returns || next instanceof AST_Return)) { @@ -2057,7 +2057,7 @@ merge(Compressor.prototype, { continue; } //--- - // if (a) return b; if (c) return d; e; ==> return a ? b : c ? d : void e; + // if (a) return b; if (c) return d; e; => return a ? b : c ? d : void e; // // if sequences is not enabled, this can lead to an endless loop (issue #866). // however, with sequences on this helps producing slightly better output for @@ -6025,7 +6025,7 @@ merge(Compressor.prototype, { } else if (compressor.in_boolean_context()) switch (self.operator) { case "!": if (e instanceof AST_UnaryPrefix && e.operator == "!") { - // !!foo ==> foo, if we're in boolean context + // !!foo => foo, if we're in boolean context return e.expression; } if (e instanceof AST_Binary) { @@ -6317,9 +6317,9 @@ merge(Compressor.prototype, { return self.left.optimize(compressor); } } - // x || false && y ---> x ? y : false + // (x || false) && y => x ? y : false if (self.left.operator == "||") { - var lr = self.left.right.evaluate(compressor); + var lr = self.left.right.tail_node().evaluate(compressor); if (!lr) return make_node(AST_Conditional, self, { condition: self.left.left, consequent: self.right, @@ -6351,8 +6351,9 @@ merge(Compressor.prototype, { ]).optimize(compressor); } else self.truthy = true; } + // x && true || y => x ? true : y if (self.left.operator == "&&") { - var lr = self.left.right.evaluate(compressor); + var lr = self.left.right.is_truthy() || self.left.right.tail_node().evaluate(compressor); if (lr && !(lr instanceof AST_Node)) return make_node(AST_Conditional, self, { condition: self.left.left, consequent: self.left.right, @@ -6650,10 +6651,10 @@ merge(Compressor.prototype, { return node.optimize(compressor); } } - // x && (y && z) ==> x && y && z - // x || (y || z) ==> x || y || z - // x + ("y" + z) ==> x + "y" + z - // "x" + (y + "z")==> "x" + y + "z" + // x && (y && z) => x && y && z + // x || (y || z) => x || y || z + // x + ("y" + z) => x + "y" + z + // "x" + (y + "z") => "x" + y + "z" if (self.right instanceof AST_Binary && self.right.operator == self.operator && (lazy_op[self.operator] @@ -7055,7 +7056,7 @@ merge(Compressor.prototype, { if (self.right.left instanceof AST_SymbolRef && self.right.left.name == self.left.name && ASSIGN_OPS[self.right.operator]) { - // x = x - 2 ---> x -= 2 + // x = x - 2 => x -= 2 self.operator = self.right.operator + "="; self.right = self.right.right; } @@ -7063,7 +7064,7 @@ merge(Compressor.prototype, { && self.right.right.name == self.left.name && ASSIGN_OPS_COMMUTATIVE[self.right.operator] && !self.right.left.has_side_effects(compressor)) { - // x = 2 & x ---> x &= 2 + // x = 2 & x => x &= 2 self.operator = self.right.operator + "="; self.right = self.right.left; } @@ -7132,7 +7133,7 @@ merge(Compressor.prototype, { var condition = self.condition; var consequent = self.consequent; var alternative = self.alternative; - // x?x:y --> x||y + // x ? x : y => x || y if (condition instanceof AST_SymbolRef && consequent instanceof AST_SymbolRef && condition.definition() === consequent.definition()) { @@ -7169,7 +7170,7 @@ merge(Compressor.prototype, { }); } } - // x ? y : y --> x, y + // x ? y : y => x, y if (consequent.equivalent_to(alternative)) return make_sequence(self, [ condition, consequent @@ -7178,7 +7179,7 @@ merge(Compressor.prototype, { && alternative.TYPE === consequent.TYPE && consequent.args.length == alternative.args.length) { var arg_index = arg_diff(); - // x ? y(a) : z(a) --> (x ? y : z)(a) + // x ? y(a) : z(a) => (x ? y : z)(a) if (arg_index == -1 && !(consequent.expression instanceof AST_PropAccess) && !(alternative.expression instanceof AST_PropAccess)) { @@ -7190,7 +7191,7 @@ merge(Compressor.prototype, { }); return node; } - // x ? y(a) : y(b) --> y(x ? a : b) + // x ? y(a) : y(b) => y(x ? a : b) if (arg_index >= 0 && consequent.expression.equivalent_to(alternative.expression) && !condition.has_side_effects(compressor) @@ -7204,7 +7205,7 @@ merge(Compressor.prototype, { return node; } } - // x ? (y ? a : b) : b --> x && y ? a : b + // x ? (y ? a : b) : b => x && y ? a : b if (consequent instanceof AST_Conditional && consequent.alternative.equivalent_to(alternative)) { return make_node(AST_Conditional, self, { @@ -7217,7 +7218,7 @@ merge(Compressor.prototype, { alternative: alternative }); } - // x ? a : (y ? a : b)--> x || y ? a : b + // x ? a : (y ? a : b) => x || y ? a : b if (alternative instanceof AST_Conditional && consequent.equivalent_to(alternative.consequent)) { return make_node(AST_Conditional, self, { @@ -7230,7 +7231,7 @@ merge(Compressor.prototype, { alternative: alternative.alternative }); } - // x ? (y, w) : (z, w) --> x ? y : z, w + // x ? (y, w) : (z, w) => x ? y : z, w if ((consequent instanceof AST_Sequence || alternative instanceof AST_Sequence) && consequent.tail_node().equivalent_to(alternative.tail_node())) { return make_sequence(self, [ @@ -7242,7 +7243,7 @@ merge(Compressor.prototype, { consequent.tail_node() ]).optimize(compressor); } - // x ? y || z : z --> x && y || z + // x ? y || z : z => x && y || z if (consequent instanceof AST_Binary && consequent.operator == "||" && consequent.right.equivalent_to(alternative)) { @@ -7259,10 +7260,10 @@ merge(Compressor.prototype, { var in_bool = compressor.option("booleans") && compressor.in_boolean_context(); if (is_true(consequent)) { if (is_false(alternative)) { - // c ? true : false ---> !!c + // c ? true : false => !!c return booleanize(condition); } - // c ? true : x ---> !!c || x + // c ? true : x => !!c || x return make_node(AST_Binary, self, { operator: "||", left: booleanize(condition), @@ -7271,10 +7272,10 @@ merge(Compressor.prototype, { } if (is_false(consequent)) { if (is_true(alternative)) { - // c ? false : true ---> !c + // c ? false : true => !c return booleanize(condition.negate(compressor)); } - // c ? false : x ---> !c && x + // c ? false : x => !c && x return make_node(AST_Binary, self, { operator: "&&", left: booleanize(condition.negate(compressor)), @@ -7282,7 +7283,7 @@ merge(Compressor.prototype, { }); } if (is_true(alternative)) { - // c ? x : true ---> !c || x + // c ? x : true => !c || x return make_node(AST_Binary, self, { operator: "||", left: booleanize(condition.negate(compressor)), @@ -7290,7 +7291,7 @@ merge(Compressor.prototype, { }); } if (is_false(alternative)) { - // c ? x : false ---> !!c && x + // c ? x : false => !!c && x return make_node(AST_Binary, self, { operator: "&&", left: booleanize(condition),