enhance conditionals (#3643)

This commit is contained in:
Alex Lam S.L
2019-12-22 04:29:32 +00:00
committed by GitHub
parent 519a00bd8a
commit 75aa6ef848
5 changed files with 120 additions and 33 deletions

View File

@@ -7005,25 +7005,42 @@ merge(Compressor.prototype, {
}); });
} }
} }
// x ? y(a) : y(b) --> y(x ? a : b) // x ? y : y --> x, y
var arg_index; if (consequent.equivalent_to(alternative)) return make_sequence(self, [
condition,
consequent
]).optimize(compressor);
if (consequent instanceof AST_Call if (consequent instanceof AST_Call
&& alternative.TYPE === consequent.TYPE && alternative.TYPE === consequent.TYPE
&& consequent.args.length > 0 && consequent.args.length == alternative.args.length) {
&& consequent.args.length == alternative.args.length 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)
&& typeof (arg_index = single_arg_diff()) == "number") { && !(alternative.expression instanceof AST_PropAccess)) {
var node = consequent.clone(); var node = consequent.clone();
node.args[arg_index] = make_node(AST_Conditional, self, { node.expression = make_node(AST_Conditional, self, {
condition: condition, condition: condition,
consequent: consequent.args[arg_index], consequent: consequent.expression,
alternative: alternative.args[arg_index] 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?z:a:a --> x&&y?z:a // x ? (y ? a : b) : b --> x && y ? a : b
if (consequent instanceof AST_Conditional if (consequent instanceof AST_Conditional
&& consequent.alternative.equivalent_to(alternative)) { && consequent.alternative.equivalent_to(alternative)) {
return make_node(AST_Conditional, self, { return make_node(AST_Conditional, self, {
@@ -7036,12 +7053,18 @@ merge(Compressor.prototype, {
alternative: alternative alternative: alternative
}); });
} }
// x ? y : y --> x, y // x ? a : (y ? a : b)--> x || y ? a : b
if (consequent.equivalent_to(alternative)) { if (alternative instanceof AST_Conditional
return make_sequence(self, [ && consequent.equivalent_to(alternative.consequent)) {
condition, return make_node(AST_Conditional, self, {
consequent condition: make_node(AST_Binary, self, {
]).optimize(compressor); left: condition,
operator: "||",
right: alternative.condition
}),
consequent: consequent,
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) if ((consequent instanceof AST_Sequence || alternative instanceof AST_Sequence)
@@ -7145,17 +7168,18 @@ merge(Compressor.prototype, {
&& node.expression.getValue()); && node.expression.getValue());
} }
function single_arg_diff() { function arg_diff() {
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++) { for (var i = 0, len = a.length; 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; if (!a[j].equivalent_to(b[j])) return -2;
} }
return i; return i;
} }
} }
return -1;
} }
function can_shift_lhs_of_tail(node) { function can_shift_lhs_of_tail(node) {

View File

@@ -33,10 +33,10 @@ unsafe_comps: {
} }
expect: { expect: {
var obj1, obj2; var obj1, obj2;
obj2 < obj1 ? g1() : f1(); (obj2 < obj1 ? g1 : f1)();
obj1 < obj2 ? f2() : g2(); (obj1 < obj2 ? f2 : g2)();
obj1 < obj2 ? g3() : f3(); (obj1 < obj2 ? g3 : f3)();
obj2 < obj1 ? f4() : g4(); (obj2 < obj1 ? f4 : g4)();
} }
} }

View File

@@ -41,7 +41,7 @@ ifs_2: {
} }
expect: { expect: {
foo ? x() : bar ? y() : baz && z(); foo ? x() : bar ? y() : baz && z();
foo ? x() : bar ? y() : baz ? z() : t(); (foo ? x : bar ? y : baz ? z : t)();
} }
} }
@@ -289,7 +289,7 @@ cond_5: {
} }
} }
expect: { expect: {
some_condition() && some_other_condition() ? do_something() : alternate(); (some_condition() && some_other_condition() ? do_something : alternate)();
some_condition() && some_other_condition() && do_something(); some_condition() && some_other_condition() && do_something();
} }
} }
@@ -663,6 +663,69 @@ cond_9: {
} }
} }
cond_10: {
options = {
conditionals: true,
if_return: true,
}
input: {
function f(a) {
if (1 == a) return "foo";
if (2 == a) return "foo";
if (3 == a) return "foo";
if (4 == a) return 42;
if (5 == a) return "foo";
if (6 == a) return "foo";
return "bar";
}
console.log(f(1), f(2), f(3), f(4), f(5), f(6), f(7));
}
expect: {
function f(a) {
return 1 == a || 2 == a || 3 == a ? "foo" : 4 == a ? 42 : 5 == a || 6 == a ? "foo" : "bar";
}
console.log(f(1), f(2), f(3), f(4), f(5), f(6), f(7));
}
expect_stdout: "foo foo foo 42 foo foo bar"
}
cond_11: {
options = {
conditionals: true,
}
input: {
var o = {
p: "foo",
q: function() {
return this.p;
}
};
function f() {
return "bar";
}
function g(a) {
return a ? f() : o.q();
}
console.log(g(0), g(1));
}
expect: {
var o = {
p: "foo",
q: function() {
return this.p;
}
};
function f() {
return "bar";
}
function g(a) {
return a ? f() : o.q();
}
console.log(g(0), g(1));
}
expect_stdout: "foo bar"
}
ternary_boolean_consequent: { ternary_boolean_consequent: {
options = { options = {
booleans: true, booleans: true,

View File

@@ -30,7 +30,7 @@ non_hoisted_function_after_return: {
} }
expect: { expect: {
function foo(x) { function foo(x) {
return x ? bar() : baz(); return (x ? bar : baz)();
function bar() { return 7 } function bar() { return 7 }
function baz() { return 8 } function baz() { return 8 }
} }
@@ -181,7 +181,7 @@ non_hoisted_function_after_return_strict: {
expect: { expect: {
"use strict"; "use strict";
function foo(x) { function foo(x) {
return x ? bar() : baz(); return (x ? bar : baz)();
function bar() { return 7 } function bar() { return 7 }
function baz() { return 8 } function baz() { return 8 }
} }

View File

@@ -21,7 +21,7 @@ cond_5: {
} }
} }
expect: { expect: {
some_condition() && some_other_condition() ? do_something() : alternate(); (some_condition() && some_other_condition() ? do_something : alternate)();
if (some_condition() && some_other_condition()) do_something(); if (some_condition() && some_other_condition()) do_something();
} }
} }