enhance conditionals (#4106)
This commit is contained in:
@@ -8456,24 +8456,16 @@ merge(Compressor.prototype, {
|
||||
condition,
|
||||
consequent
|
||||
]).optimize(compressor);
|
||||
if (consequent instanceof AST_Call
|
||||
&& alternative.TYPE === consequent.TYPE
|
||||
&& consequent.args.length == alternative.args.length) {
|
||||
var arg_index = arg_diff();
|
||||
// x ? y.p : z.p => (x ? y : z).p
|
||||
// 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.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)
|
||||
if (arg_index >= 0
|
||||
var arg_index;
|
||||
if (consequent instanceof AST_Call
|
||||
&& 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)) {
|
||||
@@ -8485,7 +8477,6 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
return node;
|
||||
}
|
||||
}
|
||||
// x ? (y ? a : b) : b => x && y ? a : b
|
||||
if (consequent instanceof AST_Conditional
|
||||
&& consequent.alternative.equivalent_to(alternative)) {
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user