diff --git a/lib/compress.js b/lib/compress.js index de07080f82..92e8d3a3ff 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -4828,10 +4828,12 @@ merge(Compressor.prototype, { for (var i = 0, len = self.body.length; i < len && !exact_match; i++) { branch = self.body[i]; if (branch instanceof AST_Default) { - if (!default_branch) { - default_branch = branch; + var prev = body[body.length - 1]; + if (default_branch || is_break(branch.body[0], compressor) && (!prev || aborts(prev))) { + eliminate_branch(branch, prev); + continue; } else { - eliminate_branch(branch, body[body.length - 1]); + default_branch = branch; } } else if (!(value instanceof AST_Node)) { var exp = branch.expression.evaluate(compressor); @@ -4857,7 +4859,14 @@ merge(Compressor.prototype, { prev.body = []; } } - body.push(branch); + 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); + } } while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]); if (body.length > 0) { @@ -4866,8 +4875,7 @@ merge(Compressor.prototype, { self.body = body; while (branch = body[body.length - 1]) { var stat = branch.body[branch.body.length - 1]; - if (stat instanceof AST_Break && compressor.loopcontrol_target(stat) === self) - branch.body.pop(); + 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 (body.pop() === default_branch) default_branch = null; @@ -4885,8 +4893,7 @@ merge(Compressor.prototype, { if (has_break || node instanceof AST_Lambda || node instanceof AST_SimpleStatement) return true; - if (node instanceof AST_Break && tw.loopcontrol_target(node) === self) - has_break = true; + if (is_break(node, tw)) has_break = true; }); self.walk(tw); if (!has_break) { @@ -4905,6 +4912,10 @@ merge(Compressor.prototype, { } return self; + function is_break(node, tw) { + return node instanceof AST_Break && tw.loopcontrol_target(node) === self; + } + 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 547843fae2..b41247b49d 100644 --- a/test/compress/switch.js +++ b/test/compress/switch.js @@ -261,13 +261,13 @@ drop_default_1: { } input: { switch (foo) { - case 'bar': baz(); + case "bar": baz(); default: } } expect: { switch (foo) { - case 'bar': baz(); + case "bar": baz(); } } } @@ -279,14 +279,14 @@ drop_default_2: { } input: { switch (foo) { - case 'bar': baz(); break; + case "bar": baz(); break; default: break; } } expect: { switch (foo) { - case 'bar': baz(); + case "bar": baz(); } } } @@ -298,7 +298,7 @@ keep_default: { } input: { switch (foo) { - case 'bar': baz(); + case "bar": baz(); default: something(); break; @@ -306,7 +306,7 @@ keep_default: { } expect: { switch (foo) { - case 'bar': baz(); + case "bar": baz(); default: something(); } @@ -347,21 +347,48 @@ issue_1663: { expect_stdout: true } -drop_case: { +drop_case_1: { options = { dead_code: true, switches: true, } input: { switch (foo) { - case 'bar': baz(); break; - case 'moo': + case "bar": baz(); break; + case "moo": break; } } expect: { switch (foo) { - case 'bar': baz(); + case "bar": baz(); + } + } +} + +drop_case_2: { + options = { + dead_code: true, + switches: true, + } + input: { + switch (foo) { + case "bar": + bar(); + break; + default: + case "moo": + moo(); + break; + } + } + expect: { + switch (foo) { + case "bar": + bar(); + break; + default: + moo(); } } } @@ -373,14 +400,14 @@ keep_case: { } input: { switch (foo) { - case 'bar': baz(); break; + case "bar": baz(); break; case moo: break; } } expect: { switch (foo) { - case 'bar': baz(); break; + case "bar": baz(); break; case moo: } } @@ -494,7 +521,7 @@ issue_1674: { expect_stdout: "PASS" } -issue_1679: { +issue_1679_1: { options = { dead_code: true, evaluate: true, @@ -521,6 +548,34 @@ issue_1679: { 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) { @@ -534,12 +589,29 @@ issue_1679: { } break; case (a++): + break; } } f(); console.log(a, b); } - expect_stdout: true + expect: { + var a = 100, b = 10; + function f() { + switch (--b) { + case b--: + switch (0) { + default: + case a--: + } + break; + case (a++): + } + } + f(); + console.log(a, b); + } + expect_stdout: "99 8" } issue_1680_1: { @@ -864,3 +936,65 @@ issue_1750: { } expect_stdout: "0 2" } + +drop_switch_1: { + options = { + dead_code: true, + switches: true, + } + input: { + switch (foo) { + default: + break; + case "bar": + break; + } + } + expect: { + foo; + } +} + +drop_switch_2: { + options = { + dead_code: true, + switches: true, + } + input: { + switch (foo) { + default: + case "bar": + baz(); + } + } + expect: { + foo; + baz(); + } +} + +drop_switch_3: { + options = { + dead_code: true, + switches: true, + } + input: { + console.log(function() { + switch (0) { + default: + return "PASS"; + case 1: + } + }()); + } + expect: { + console.log(function() { + switch (0) { + default: + return "PASS"; + case 1: + } + }()); + } + expect_stdout: "PASS" +}