Skip to content

Commit

Permalink
enhance conditionals (#3643)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl committed Dec 22, 2019
1 parent 519a00b commit 75aa6ef
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 33 deletions.
72 changes: 48 additions & 24 deletions lib/compress.js
Expand Up @@ -7005,25 +7005,42 @@ merge(Compressor.prototype, {
});
}
}
// x ? y(a) : y(b) --> y(x ? a : b)
var arg_index;
// x ? y : y --> x, y
if (consequent.equivalent_to(alternative)) return make_sequence(self, [
condition,
consequent
]).optimize(compressor);
if (consequent instanceof AST_Call
&& alternative.TYPE === consequent.TYPE
&& consequent.args.length > 0
&& consequent.args.length == alternative.args.length
&& consequent.expression.equivalent_to(alternative.expression)
&& !condition.has_side_effects(compressor)
&& !consequent.expression.has_side_effects(compressor)
&& typeof (arg_index = single_arg_diff()) == "number") {
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;
&& 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;
}
}
// x?y?z:a:a --> x&&y?z:a
// x ? (y ? a : b) : b --> x && y ? a : b
if (consequent instanceof AST_Conditional
&& consequent.alternative.equivalent_to(alternative)) {
return make_node(AST_Conditional, self, {
Expand All @@ -7036,12 +7053,18 @@ merge(Compressor.prototype, {
alternative: alternative
});
}
// x ? y : y --> x, y
if (consequent.equivalent_to(alternative)) {
return make_sequence(self, [
condition,
consequent
]).optimize(compressor);
// x ? a : (y ? a : b)--> x || y ? a : b
if (alternative instanceof AST_Conditional
&& consequent.equivalent_to(alternative.consequent)) {
return make_node(AST_Conditional, self, {
condition: make_node(AST_Binary, self, {
left: condition,
operator: "||",
right: alternative.condition
}),
consequent: consequent,
alternative: alternative.alternative
});
}
// x ? (y, w) : (z, w) --> x ? y : z, w
if ((consequent instanceof AST_Sequence || alternative instanceof AST_Sequence)
Expand Down Expand Up @@ -7145,17 +7168,18 @@ merge(Compressor.prototype, {
&& node.expression.getValue());
}

function single_arg_diff() {
function arg_diff() {
var a = consequent.args;
var b = alternative.args;
for (var i = 0, len = a.length; 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;
if (!a[j].equivalent_to(b[j])) return -2;
}
return i;
}
}
return -1;
}

function can_shift_lhs_of_tail(node) {
Expand Down
8 changes: 4 additions & 4 deletions test/compress/comparisons.js
Expand Up @@ -33,10 +33,10 @@ unsafe_comps: {
}
expect: {
var obj1, obj2;
obj2 < obj1 ? g1() : f1();
obj1 < obj2 ? f2() : g2();
obj1 < obj2 ? g3() : f3();
obj2 < obj1 ? f4() : g4();
(obj2 < obj1 ? g1 : f1)();
(obj1 < obj2 ? f2 : g2)();
(obj1 < obj2 ? g3 : f3)();
(obj2 < obj1 ? f4 : g4)();
}
}

Expand Down
67 changes: 65 additions & 2 deletions test/compress/conditionals.js
Expand Up @@ -41,7 +41,7 @@ ifs_2: {
}
expect: {
foo ? x() : bar ? y() : baz && z();
foo ? x() : bar ? y() : baz ? z() : t();
(foo ? x : bar ? y : baz ? z : t)();
}
}

Expand Down Expand Up @@ -289,7 +289,7 @@ cond_5: {
}
}
expect: {
some_condition() && some_other_condition() ? do_something() : alternate();
(some_condition() && some_other_condition() ? do_something : alternate)();
some_condition() && some_other_condition() && do_something();
}
}
Expand Down Expand Up @@ -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: {
options = {
booleans: true,
Expand Down
4 changes: 2 additions & 2 deletions test/compress/issue-1034.js
Expand Up @@ -30,7 +30,7 @@ non_hoisted_function_after_return: {
}
expect: {
function foo(x) {
return x ? bar() : baz();
return (x ? bar : baz)();
function bar() { return 7 }
function baz() { return 8 }
}
Expand Down Expand Up @@ -181,7 +181,7 @@ non_hoisted_function_after_return_strict: {
expect: {
"use strict";
function foo(x) {
return x ? bar() : baz();
return (x ? bar : baz)();
function bar() { return 7 }
function baz() { return 8 }
}
Expand Down
2 changes: 1 addition & 1 deletion test/compress/issue-640.js
Expand Up @@ -21,7 +21,7 @@ cond_5: {
}
}
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();
}
}
Expand Down

0 comments on commit 75aa6ef

Please sign in to comment.