From 910799ca9921ed435df3fd149a1fb2ab77dedbc5 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Thu, 14 Nov 2019 02:29:55 +0800 Subject: [PATCH] fix corner case in `switches` (#3585) --- lib/compress.js | 38 ++++++++----- test/compress/switch.js | 122 +++++++++++++++++++++++++--------------- 2 files changed, 100 insertions(+), 60 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index e97427bc..668293d2 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -4872,25 +4872,23 @@ merge(Compressor.prototype, { prev.body = []; } } - if (default_branch - && default_branch.body.length == 0 - && body[body.length - 1] === default_branch - && !branch.expression.has_side_effects(compressor)) { - default_branch.body = branch.body.slice(); - } else { - body.push(branch); - } + body.push(branch); } while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]); - if (body.length > 0) { - body[0].body = decl.concat(body[0].body); - } - self.body = body; while (branch = body[body.length - 1]) { var stat = branch.body[branch.body.length - 1]; if (is_break(stat, compressor)) branch.body.pop(); - if (branch.body.length || branch instanceof AST_Case - && (default_branch || branch.expression.has_side_effects(compressor))) break; + if (branch === default_branch) { + if (!is_body_empty(branch)) break; + } else if (branch.expression.has_side_effects(compressor)) { + break; + } else if (default_branch) { + if (!is_body_empty(default_branch)) break; + if (body[body.length - 2] !== default_branch) break; + default_branch.body = default_branch.body.concat(branch.body); + branch.body = []; + } else if (!is_body_empty(branch)) break; + eliminate_branch(branch); if (body.pop() === default_branch) default_branch = null; } if (body.length == 0) { @@ -4900,6 +4898,8 @@ merge(Compressor.prototype, { })) }).optimize(compressor); } + 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) { @@ -4929,6 +4929,16 @@ merge(Compressor.prototype, { return node instanceof AST_Break && tw.loopcontrol_target(node) === self; } + function is_body_empty(branch) { + return all(branch.body, function(stat) { + return is_empty(stat) + || stat instanceof AST_Defun + || stat instanceof AST_Var && all(stat.definitions, function(var_def) { + return !var_def.value; + }); + }); + } + function eliminate_branch(branch, prev) { if (prev && !aborts(prev)) { prev.body = prev.body.concat(branch.body); diff --git a/test/compress/switch.js b/test/compress/switch.js index b41247b4..1de676e3 100644 --- a/test/compress/switch.js +++ b/test/compress/switch.js @@ -393,6 +393,57 @@ drop_case_2: { } } +drop_case_3: { + options = { + dead_code: true, + switches: true, + } + input: { + var c = "PASS"; + switch ({}.p) { + default: + case void 0: + break; + case c = "FAIL": + } + console.log(c); + } + expect: { + var c = "PASS"; + switch ({}.p) { + default: + case void 0: + break; + case c = "FAIL": + } + console.log(c); + } + expect_stdout: "PASS" +} + +drop_case_4: { + options = { + dead_code: true, + switches: true, + } + input: { + switch (0) { + case [ a, typeof b ]: + default: + var a; + } + console.log("PASS"); + } + expect: { + switch (0) { + case [ a, typeof b ]: + var a; + } + console.log("PASS"); + } + expect_stdout: "PASS" +} + keep_case: { options = { dead_code: true, @@ -521,7 +572,7 @@ issue_1674: { expect_stdout: "PASS" } -issue_1679_1: { +issue_1679: { options = { dead_code: true, evaluate: true, @@ -548,34 +599,6 @@ issue_1679_1: { console.log(a, b); } expect: { - var a = 100, b = 10; - function f() { - switch (--b) { - default: - break; - case b--: - switch (0) { - default: - case a--: - } - break; - case (a++): - } - } - f(); - console.log(a, b); - } - expect_stdout: "99 8" -} - -issue_1679_2: { - options = { - dead_code: true, - evaluate: true, - passes: 2, - switches: true, - } - input: { var a = 100, b = 10; function f() { switch (--b) { @@ -589,23 +612,6 @@ issue_1679_2: { } break; case (a++): - break; - } - } - f(); - console.log(a, b); - } - expect: { - var a = 100, b = 10; - function f() { - switch (--b) { - case b--: - switch (0) { - default: - case a--: - } - break; - case (a++): } } f(); @@ -998,3 +1004,27 @@ drop_switch_3: { } expect_stdout: "PASS" } + +drop_switch_4: { + options = { + dead_code: true, + switches: true, + } + input: { + var a = "FAIL"; + switch (0) { + default: + case a: + var b = a = "PASS"; + break; + } + console.log(a); + } + expect: { + var a = "FAIL"; + 0; + var b = a = "PASS"; + console.log(a); + } + expect_stdout: "PASS" +} -- 2.34.1