});
}
}
- // 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, {
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)
&& 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) {
}
expect: {
foo ? x() : bar ? y() : baz && z();
- foo ? x() : bar ? y() : baz ? z() : t();
+ (foo ? x : bar ? y : baz ? z : t)();
}
}
}
}
expect: {
- some_condition() && some_other_condition() ? do_something() : alternate();
+ (some_condition() && some_other_condition() ? do_something : alternate)();
some_condition() && some_other_condition() && do_something();
}
}
}
}
+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,