From: Alex Lam S.L Date: Tue, 15 Sep 2020 21:51:42 +0000 (+0100) Subject: enhance `conditionals` (#4106) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=20391850518f4050917a4812af07520eb47cfecf;p=UglifyJS.git enhance `conditionals` (#4106) --- diff --git a/lib/compress.js b/lib/compress.js index 52ed0e61..dbf4e09d 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -8456,35 +8456,26 @@ merge(Compressor.prototype, { condition, consequent ]).optimize(compressor); + // x ? y.p : z.p => (x ? y : z).p + // x ? y(a) : z(a) => (x ? y : z)(a) + // x ? y.f(a) : z.f(a) => (x ? y : z).f(a) + var combined = combine_tail(consequent, alternative, true); + if (combined) return combined; + // x ? y(a) : y(b) => y(x ? a : b) + var arg_index; if (consequent instanceof AST_Call - && alternative.TYPE === consequent.TYPE - && consequent.args.length == alternative.args.length) { - var arg_index = arg_diff(); - // x ? y(a) : z(a) => (x ? y : z)(a) - if (arg_index == -1 - && !(consequent.expression instanceof AST_PropAccess) - && !(alternative.expression instanceof AST_PropAccess)) { - var node = consequent.clone(); - node.expression = make_node(AST_Conditional, self, { - condition: condition, - consequent: consequent.expression, - alternative: alternative.expression - }); - return node; - } - // x ? y(a) : y(b) => y(x ? a : b) - if (arg_index >= 0 - && consequent.expression.equivalent_to(alternative.expression) - && !condition.has_side_effects(compressor) - && !consequent.expression.has_side_effects(compressor)) { - var node = consequent.clone(); - node.args[arg_index] = make_node(AST_Conditional, self, { - condition: condition, - consequent: consequent.args[arg_index], - alternative: alternative.args[arg_index] - }); - return node; - } + && alternative.TYPE == consequent.TYPE + && (arg_index = arg_diff(consequent, alternative)) >= 0 + && consequent.expression.equivalent_to(alternative.expression) + && !condition.has_side_effects(compressor) + && !consequent.expression.has_side_effects(compressor)) { + var node = consequent.clone(); + node.args[arg_index] = make_node(AST_Conditional, self, { + condition: condition, + consequent: consequent.args[arg_index], + alternative: alternative.args[arg_index] + }); + return node; } // x ? (y ? a : b) : b => x && y ? a : b if (consequent instanceof AST_Conditional @@ -8685,10 +8676,12 @@ merge(Compressor.prototype, { && node.expression.value); } - function arg_diff() { + function arg_diff(consequent, alternative) { var a = consequent.args; var b = alternative.args; - for (var i = 0, len = a.length; i < len; i++) { + var len = a.length; + if (len != b.length) return -2; + for (var i = 0; i < len; i++) { if (!a[i].equivalent_to(b[i])) { for (var j = i + 1; j < len; j++) { if (!a[j].equivalent_to(b[j])) return -2; @@ -8699,6 +8692,32 @@ merge(Compressor.prototype, { return -1; } + function is_tail_equivalent(consequent, alternative) { + if (consequent.TYPE != alternative.TYPE) return; + if (consequent instanceof AST_Call) { + if (arg_diff(consequent, alternative) != -1) return; + return consequent.TYPE != "Call" + || !(consequent.expression instanceof AST_PropAccess + || alternative.expression instanceof AST_PropAccess) + || is_tail_equivalent(consequent.expression, alternative.expression); + } + if (consequent instanceof AST_Dot) return consequent.property == alternative.property; + if (consequent instanceof AST_Sub) return consequent.property.equivalent_to(alternative.property); + } + + function combine_tail(consequent, alternative, top) { + if (!is_tail_equivalent(consequent, alternative)) return !top && make_node(AST_Conditional, self, { + condition: condition, + consequent: consequent, + alternative: alternative + }); + var exp = combine_tail(consequent.expression, alternative.expression); + if (!exp) return; + var node = consequent.clone(); + node.expression = exp; + return node; + } + function can_shift_lhs_of_tail(node) { return node === node.tail_node() || all(node.expressions.slice(0, -1), function(expr) { return !expr.has_side_effects(compressor); diff --git a/test/compress/conditionals.js b/test/compress/conditionals.js index ab9c4108..4d54b83a 100644 --- a/test/compress/conditionals.js +++ b/test/compress/conditionals.js @@ -783,6 +783,28 @@ cond_12: { } } +cond_13: { + options = { + conditionals: true, + } + input: { + x ? y(a) : z(a); + x ? y.f(a) : z.f(a); + x ? y.f(a) : z.g(a); + x ? y.f()(a) : z.g()(a); + x ? y.f.u(a) : z.g.u(a); + x ? y.f().u(a) : z.g().u(a); + } + expect: { + (x ? y : z)(a); + (x ? y : z).f(a); + x ? y.f(a) : z.g(a); + (x ? y.f() : z.g())(a); + (x ? y.f : z.g).u(a); + (x ? y.f() : z.g()).u(a); + } +} + ternary_boolean_consequent: { options = { booleans: true,