From: Alex Lam S.L Date: Thu, 20 Aug 2020 16:35:39 +0000 (+0100) Subject: enhance `conditionals` & `switches` (#4058) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=a153176469d49b851b884b96261f01ea8026ba82;p=UglifyJS.git enhance `conditionals` & `switches` (#4058) --- diff --git a/lib/compress.js b/lib/compress.js index c9892ce2..8bc8b37e 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -5916,28 +5916,57 @@ merge(Compressor.prototype, { } body[0].body = decl.concat(body[0].body); self.body = body; - if (body.length == 1 && (body[0] === exact_match || body[0] === default_branch)) { - var has_break = false; - var tw = new TreeWalker(function(node) { - if (has_break - || node instanceof AST_Lambda - || node instanceof AST_SimpleStatement) return true; - if (is_break(node, tw)) has_break = true; + if (compressor.option("conditionals")) switch (body.length) { + case 1: + if (!no_break(self)) break; + var exp = body[0].expression; + var statements = body[0].body.slice(); + if (body[0] !== default_branch && body[0] !== exact_match) return make_node(AST_If, self, { + condition: make_node(AST_Binary, self, { + operator: "===", + left: self.expression, + right: exp, + }), + body: make_node(AST_BlockStatement, self, { + body: statements, + }), + alternative: null, + }).optimize(compressor); + if (exp) statements.unshift(make_node(AST_SimpleStatement, exp, { + body: exp, + })); + statements.unshift(make_node(AST_SimpleStatement, self.expression, { + body:self.expression, + })); + return make_node(AST_BlockStatement, self, { + body: statements, + }).optimize(compressor); + case 2: + if (!member(default_branch, body)) break; + var statements = body[0].body.slice(); + var exclusive = statements.length && is_break(statements[statements.length - 1], compressor); + if (exclusive) statements.pop(); + if (!all(statements, no_break)) break; + var alternative = body[1].body.length && make_node(AST_BlockStatement, body[1], body[1]); + var node = make_node(AST_If, self, { + condition: make_node(AST_Binary, self, body[0] === default_branch ? { + operator: "!==", + left: self.expression, + right: body[1].expression, + } : { + operator: "===", + left: self.expression, + right: body[0].expression, + }), + body: make_node(AST_BlockStatement, body[0], { + body: statements, + }), + alternative: exclusive && alternative || null, }); - self.walk(tw); - if (!has_break) { - var statements = body[0].body.slice(); - var exp = body[0].expression; - if (exp) statements.unshift(make_node(AST_SimpleStatement, exp, { - body: exp - })); - statements.unshift(make_node(AST_SimpleStatement, self.expression, { - body:self.expression - })); - return make_node(AST_BlockStatement, self, { - body: statements - }).optimize(compressor); - } + if (!exclusive && alternative) node = make_node(AST_BlockStatement, self, { + body: [ node, alternative ], + }); + return node.optimize(compressor); } return self; @@ -5945,6 +5974,18 @@ merge(Compressor.prototype, { return node instanceof AST_Break && tw.loopcontrol_target(node) === self; } + function no_break(node) { + var found = false; + var tw = new TreeWalker(function(node) { + if (found + || node instanceof AST_Lambda + || node instanceof AST_SimpleStatement) return true; + if (is_break(node, tw)) found = true; + }); + node.walk(tw); + return !found; + } + function eliminate_branch(branch, prev) { if (prev && !aborts(prev)) { prev.body = prev.body.concat(branch.body); diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 77782cfd..8ed827a7 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -2031,6 +2031,7 @@ issue_1670_4: { issue_1670_5: { options = { + conditionals: true, dead_code: true, evaluate: true, keep_fargs: false, @@ -2062,6 +2063,7 @@ issue_1670_5: { issue_1670_6: { options = { + conditionals: true, dead_code: true, evaluate: true, keep_fargs: false, diff --git a/test/compress/switch.js b/test/compress/switch.js index 1de676e3..83bc40f5 100644 --- a/test/compress/switch.js +++ b/test/compress/switch.js @@ -1,5 +1,6 @@ constant_switch_1: { options = { + conditionals: true, dead_code: true, evaluate: true, side_effects: true, @@ -19,6 +20,7 @@ constant_switch_1: { constant_switch_2: { options = { + conditionals: true, dead_code: true, evaluate: true, side_effects: true, @@ -39,6 +41,7 @@ constant_switch_2: { constant_switch_3: { options = { + conditionals: true, dead_code: true, evaluate: true, side_effects: true, @@ -60,6 +63,7 @@ constant_switch_3: { constant_switch_4: { options = { + conditionals: true, dead_code: true, evaluate: true, side_effects: true, @@ -86,6 +90,7 @@ constant_switch_4: { constant_switch_5: { options = { + conditionals: true, dead_code: true, evaluate: true, side_effects: true, @@ -120,6 +125,7 @@ constant_switch_5: { constant_switch_6: { options = { + conditionals: true, dead_code: true, evaluate: true, side_effects: true, @@ -154,6 +160,7 @@ constant_switch_6: { constant_switch_7: { options = { + conditionals: true, dead_code: true, evaluate: true, side_effects: true, @@ -197,6 +204,7 @@ constant_switch_7: { constant_switch_8: { options = { + conditionals: true, dead_code: true, evaluate: true, side_effects: true, @@ -226,6 +234,7 @@ constant_switch_8: { constant_switch_9: { options = { + conditionals: true, dead_code: true, evaluate: true, side_effects: true, @@ -315,6 +324,7 @@ keep_default: { issue_1663: { options = { + conditionals: true, dead_code: true, evaluate: true, side_effects: true, @@ -551,6 +561,7 @@ issue_441_2: { issue_1674: { options = { + conditionals: true, dead_code: true, evaluate: true, side_effects: true, @@ -876,6 +887,7 @@ beautify: { issue_1758: { options = { + conditionals: true, dead_code: true, switches: true, } @@ -898,15 +910,16 @@ issue_1758: { issue_2535: { options = { + conditionals: true, dead_code: true, evaluate: true, switches: true, } input: { switch(w(), 42) { - case 13: x(); - case 42: y(); - default: z(); + case 13: x(); + case 42: y(); + default: z(); } } expect: { @@ -919,6 +932,7 @@ issue_2535: { issue_1750: { options = { + conditionals: true, dead_code: true, evaluate: true, switches: true, @@ -963,6 +977,7 @@ drop_switch_1: { drop_switch_2: { options = { + conditionals: true, dead_code: true, switches: true, } @@ -1007,6 +1022,7 @@ drop_switch_3: { drop_switch_4: { options = { + conditionals: true, dead_code: true, switches: true, } @@ -1028,3 +1044,109 @@ drop_switch_4: { } expect_stdout: "PASS" } + +drop_switch_5: { + options = { + conditionals: true, + dead_code: true, + switches: true, + } + input: { + switch (A) { + case B: + x(); + default: + } + switch (C) { + default: + y(); + case D: + } + } + expect: { + A === B && x(); + C !== D && y(); + } +} + +drop_switch_6: { + options = { + conditionals: true, + dead_code: true, + switches: true, + } + input: { + switch (A) { + case B: + default: + x(); + } + switch (C) { + default: + case D: + y(); + } + } + expect: { + A === B; + x(); + C !== D; + y(); + } +} + +drop_switch_7: { + options = { + conditionals: true, + dead_code: true, + switches: true, + } + input: { + switch (A) { + case B: + w(); + default: + x(); + } + switch (C) { + default: + y(); + case D: + z(); + } + } + expect: { + A === B && w(); + x(); + C !== D && y(); + z(); + } +} + +drop_switch_8: { + options = { + conditionals: true, + dead_code: true, + switches: true, + } + input: { + switch (A) { + case B: + w(); + break; + default: + x(); + } + switch (C) { + default: + y(); + break; + case D: + z(); + } + } + expect: { + (A === B ? w : x)(); + (C !== D ? y : z)(); + } +}