From: Alex Lam S.L Date: Sun, 22 Dec 2019 04:29:32 +0000 (+0000) Subject: enhance `conditionals` (#3643) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=75aa6ef8483e6ccde0999cd6d21e695d84703ac0;p=UglifyJS.git enhance `conditionals` (#3643) --- diff --git a/lib/compress.js b/lib/compress.js index c5b67569..c00b9f07 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -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, { @@ -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) @@ -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) { diff --git a/test/compress/comparisons.js b/test/compress/comparisons.js index bb140fd8..a4e0acc9 100644 --- a/test/compress/comparisons.js +++ b/test/compress/comparisons.js @@ -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)(); } } diff --git a/test/compress/conditionals.js b/test/compress/conditionals.js index 3e7a0927..3f3df72d 100644 --- a/test/compress/conditionals.js +++ b/test/compress/conditionals.js @@ -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)(); } } @@ -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(); } } @@ -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, diff --git a/test/compress/issue-1034.js b/test/compress/issue-1034.js index e8b69187..316d6a75 100644 --- a/test/compress/issue-1034.js +++ b/test/compress/issue-1034.js @@ -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 } } @@ -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 } } diff --git a/test/compress/issue-640.js b/test/compress/issue-640.js index 88b63abd..394d6ba2 100644 --- a/test/compress/issue-640.js +++ b/test/compress/issue-640.js @@ -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(); } }