diff --git a/lib/compress.js b/lib/compress.js index f1557848..c2a547eb 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1951,13 +1951,26 @@ Compressor.prototype.compress = function(node) { return statements; function last_of(compressor, predicate) { - var block = compressor.self(), stat, level = 0; + var block = compressor.self(), level = 0; do { - do { + if (block instanceof AST_Catch || block instanceof AST_Finally) { + block = compressor.parent(level++); + } else if (block instanceof AST_LabeledStatement) { + block = block.body; + } + var stat = null; + while (true) { if (predicate(block)) return true; block = compressor.parent(level++); - } while (block instanceof AST_If && (stat = block)); - } while ((block instanceof AST_BlockStatement || block instanceof AST_Scope) + if (!(block instanceof AST_If)) break; + stat = block; + } + } while (stat + && (block instanceof AST_BlockStatement + || block instanceof AST_Catch + || block instanceof AST_Finally + || block instanceof AST_Scope + || block instanceof AST_Try) && is_last_statement(block.body, stat)); } @@ -3677,6 +3690,11 @@ Compressor.prototype.compress = function(node) { function eliminate_dead_code(statements, compressor) { var has_quit; var self = compressor.self(); + if (self instanceof AST_Catch || self instanceof AST_Finally) { + self = compressor.parent(); + } else if (self instanceof AST_LabeledStatement) { + self = self.body; + } for (var i = 0, n = 0, len = statements.length; i < len; i++) { var stat = statements[i]; if (stat instanceof AST_LoopControl) { @@ -5965,10 +5983,19 @@ Compressor.prototype.compress = function(node) { }); OPT(AST_LabeledStatement, function(self, compressor) { - if (compressor.option("dead_code") - && self.body instanceof AST_Break - && compressor.loopcontrol_target(self.body) === self.body) { - return make_node(AST_EmptyStatement, self); + if (self.body instanceof AST_If || self.body instanceof AST_Break) { + var body = tighten_body([ self.body ], compressor); + switch (body.length) { + case 0: + self.body = make_node(AST_EmptyStatement, self); + break; + case 1: + self.body = body[0]; + break; + default: + self.body = make_node(AST_BlockStatement, self, { body: body }); + break; + } } return compressor.option("unused") && self.label.references.length == 0 ? self.body : self; }); diff --git a/test/compress/labels.js b/test/compress/labels.js index 4bf32648..42dd3251 100644 --- a/test/compress/labels.js +++ b/test/compress/labels.js @@ -111,6 +111,7 @@ labels_5: { labels_6: { options = { dead_code: true, + unused: true, } input: { out: break out; @@ -208,6 +209,59 @@ labels_10: { expect_stdout: "PASS" } +labels_11: { + options = { + conditionals: true, + if_return: true, + unused: true, + } + input: { + L: if (console.log("PASS")) + break L; + } + expect: { + console.log("PASS"); + } + expect_stdout: "PASS" +} + +labels_12: { + options = { + conditionals: true, + dead_code: true, + if_return: true, + unused: true, + } + input: { + L: try { + if (console.log("foo")) + break L; + throw "bar"; + } catch (e) { + console.log(e); + break L; + } finally { + if (console.log("baz")) + break L; + } + } + expect: { + try { + if (!console.log("foo")) + throw "bar"; + } catch (e) { + console.log(e); + } finally { + console.log("baz") + } + } + expect_stdout: [ + "foo", + "bar", + "baz", + ] +} + issue_4466_1: { mangle = { v8: false,