enhance conditionals (#4106)
This commit is contained in:
@@ -8456,35 +8456,26 @@ merge(Compressor.prototype, {
|
|||||||
condition,
|
condition,
|
||||||
consequent
|
consequent
|
||||||
]).optimize(compressor);
|
]).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
|
if (consequent instanceof AST_Call
|
||||||
&& alternative.TYPE === consequent.TYPE
|
&& alternative.TYPE == consequent.TYPE
|
||||||
&& consequent.args.length == alternative.args.length) {
|
&& (arg_index = arg_diff(consequent, alternative)) >= 0
|
||||||
var arg_index = arg_diff();
|
&& consequent.expression.equivalent_to(alternative.expression)
|
||||||
// x ? y(a) : z(a) => (x ? y : z)(a)
|
&& !condition.has_side_effects(compressor)
|
||||||
if (arg_index == -1
|
&& !consequent.expression.has_side_effects(compressor)) {
|
||||||
&& !(consequent.expression instanceof AST_PropAccess)
|
var node = consequent.clone();
|
||||||
&& !(alternative.expression instanceof AST_PropAccess)) {
|
node.args[arg_index] = make_node(AST_Conditional, self, {
|
||||||
var node = consequent.clone();
|
condition: condition,
|
||||||
node.expression = make_node(AST_Conditional, self, {
|
consequent: consequent.args[arg_index],
|
||||||
condition: condition,
|
alternative: alternative.args[arg_index]
|
||||||
consequent: consequent.expression,
|
});
|
||||||
alternative: alternative.expression
|
return node;
|
||||||
});
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// x ? (y ? a : b) : b => x && y ? a : b
|
// x ? (y ? a : b) : b => x && y ? a : b
|
||||||
if (consequent instanceof AST_Conditional
|
if (consequent instanceof AST_Conditional
|
||||||
@@ -8685,10 +8676,12 @@ merge(Compressor.prototype, {
|
|||||||
&& node.expression.value);
|
&& node.expression.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function arg_diff() {
|
function arg_diff(consequent, alternative) {
|
||||||
var a = consequent.args;
|
var a = consequent.args;
|
||||||
var b = alternative.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])) {
|
if (!a[i].equivalent_to(b[i])) {
|
||||||
for (var j = i + 1; j < len; j++) {
|
for (var j = i + 1; j < len; j++) {
|
||||||
if (!a[j].equivalent_to(b[j])) return -2;
|
if (!a[j].equivalent_to(b[j])) return -2;
|
||||||
@@ -8699,6 +8692,32 @@ merge(Compressor.prototype, {
|
|||||||
return -1;
|
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) {
|
function can_shift_lhs_of_tail(node) {
|
||||||
return node === node.tail_node() || all(node.expressions.slice(0, -1), function(expr) {
|
return node === node.tail_node() || all(node.expressions.slice(0, -1), function(expr) {
|
||||||
return !expr.has_side_effects(compressor);
|
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: {
|
ternary_boolean_consequent: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user