diff --git a/lib/compress.js b/lib/compress.js index 4daf605738..c92a774818 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -6025,10 +6025,7 @@ Compressor.prototype.compress = function(node) { } if (node instanceof AST_Binary) { if (!lazy_op[node.operator]) return; - node.left.walk(tw); - push(); - node.right.walk(tw); - pop(); + walk_cond(node); return true; } if (node instanceof AST_Break) { @@ -6053,13 +6050,7 @@ Compressor.prototype.compress = function(node) { return true; } if (node instanceof AST_Conditional) { - node.condition.walk(tw); - push(); - node.consequent.walk(tw); - pop(); - push(); - node.alternative.walk(tw); - pop(); + walk_cond(node.condition, node.consequent, node.alternative); return true; } if (node instanceof AST_Continue) { @@ -6100,15 +6091,7 @@ Compressor.prototype.compress = function(node) { return true; } if (node instanceof AST_If) { - node.condition.walk(tw); - push(); - node.body.walk(tw); - pop(); - if (node.alternative) { - push(); - node.alternative.walk(tw); - pop(); - } + walk_cond(node.condition, node.body, node.alternative); return true; } if (node instanceof AST_LabeledStatement) { @@ -6276,6 +6259,41 @@ Compressor.prototype.compress = function(node) { } return true; } + + function walk_cond(condition, consequent, alternative) { + var save = segment; + var segments = [ save, save ]; + if (condition instanceof AST_Binary) switch (condition.operator) { + case "&&": + segments[0] = walk_cond(condition.left, condition.right)[0]; + break; + case "||": + case "??": + segments[1] = walk_cond(condition.left, null, condition.right)[1]; + break; + default: + condition.walk(tw); + break; + } else if (condition instanceof AST_Conditional) { + walk_cond(condition.condition, condition.consequent, condition.alternative); + } else { + condition.walk(tw); + } + segment = segments[0]; + if (consequent) { + push(); + consequent.walk(tw); + } + segments[0] = segment; + segment = segments[1]; + if (alternative) { + push(); + alternative.walk(tw); + } + segments[1] = segment; + segment = save; + return segments; + } }); tw.directives = Object.create(compressor.directives); self.walk(tw); diff --git a/test/compress/merge_vars.js b/test/compress/merge_vars.js index 3d46b1f06c..8d69731b54 100644 --- a/test/compress/merge_vars.js +++ b/test/compress/merge_vars.js @@ -169,6 +169,158 @@ conditional_branch: { expect_stdout: "PASS" } +conditional_chain_1: { + options = { + merge_vars: true, + } + input: { + function f(a, b) { + var c, d; + if (a && (c = a)) + console.log(c); + else + b || (d = b) ? console.log("foo") : console.log(d); + } + f("", null); + f("", true); + f(42, null); + f(42, true); + } + expect: { + function f(a, b) { + var a, a; + if (a && (a = a)) + console.log(a); + else + b || (a = b) ? console.log("foo") : console.log(a); + } + f("", null); + f("", true); + f(42, null); + f(42, true); + } + expect_stdout: [ + "null", + "foo", + "42", + "42", + ] +} + +conditional_chain_2: { + options = { + merge_vars: true, + } + input: { + function f(a, b) { + var c, d; + if (a && (c = a)) + console.log(c); + else + b || (d = b) ? console.log(c) : console.log(d); + } + f("", null); + f("", true); + f(42, null); + f(42, true); + } + expect: { + function f(a, b) { + var c, a; + if (a && (c = a)) + console.log(c); + else + b || (a = b) ? console.log(c) : console.log(a); + } + f("", null); + f("", true); + f(42, null); + f(42, true); + } + expect_stdout: [ + "null", + "undefined", + "42", + "42", + ] +} + +conditional_chain_3: { + options = { + merge_vars: true, + } + input: { + function f(a, b) { + var c, d; + if (a && (c = a) || b || (d = b)) + console.log(c); + else + console.log(d); + } + f("", null); + f("", true); + f(42, null); + f(42, true); + } + expect: { + function f(a, b) { + var c, a; + if (a && (c = a) || b || (a = b)) + console.log(c); + else + console.log(a); + } + f("", null); + f("", true); + f(42, null); + f(42, true); + } + expect_stdout: [ + "null", + "undefined", + "42", + "42", + ] +} + +conditional_chain_4: { + options = { + merge_vars: true, + } + input: { + function f(a, b) { + var c, d; + if (a && b ? c = a : d = b) + console.log(c); + else + console.log(d); + } + f("", null); + f("", true); + f(42, null); + f(42, true); + } + expect: { + function f(a, b) { + var c, d; + if (a && b ? c = a : d = b) + console.log(c); + else + console.log(d); + } + f("", null); + f("", true); + f(42, null); + f(42, true); + } + expect_stdout: [ + "null", + "undefined", + "null", + "42", + ] +} + if_branch: { options = { merge_vars: true,