enhance conditionals (#3643)
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user