diff options
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/lib/compress.js b/lib/compress.js index 1af4a2d6..cde4b6f7 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -186,6 +186,14 @@ merge(Compressor.prototype, { return false; }; + function loop_body(x) { + if (x instanceof AST_Switch) return x; + if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) { + return (x.body instanceof AST_BlockStatement ? x.body : x); + } + return x; + }; + function tighten_body(statements, compressor) { var CHANGED; do { @@ -303,8 +311,13 @@ merge(Compressor.prototype, { } var ab = aborts(stat.body); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) - || (ab instanceof AST_Continue && self === compressor.loopcontrol_target(ab.label)))) { + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } CHANGED = true; var body = as_statement_array(stat.body).slice(0, -1); stat = stat.clone(); @@ -320,8 +333,13 @@ merge(Compressor.prototype, { } var ab = aborts(stat.alternative); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) - || (ab instanceof AST_Continue && self === compressor.loopcontrol_target(ab.label)))) { + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } CHANGED = true; stat = stat.clone(); stat.body = make_node(AST_BlockStatement, stat.body, { @@ -347,11 +365,26 @@ merge(Compressor.prototype, { function eliminate_dead_code(statements, compressor) { var has_quit = false; var orig = statements.length; + var self = compressor.self(); statements = statements.reduce(function(a, stat){ if (has_quit) { extract_declarations_from_unreachable_code(compressor, stat, a); } else { - a.push(stat); + if (stat instanceof AST_LoopControl) { + var lct = compressor.loopcontrol_target(stat.label); + if ((stat instanceof AST_Break + && lct instanceof AST_BlockStatement + && loop_body(lct) === self) || (stat instanceof AST_Continue + && loop_body(lct) === self)) { + if (stat.label) { + remove(stat.label.thedef.references, stat.label); + } + } else { + a.push(stat); + } + } else { + a.push(stat); + } if (aborts(stat)) has_quit = true; } return a; @@ -795,6 +828,10 @@ merge(Compressor.prototype, { }); OPT(AST_LabeledStatement, function(self, compressor){ + if (self.body instanceof AST_Break + && compressor.loopcontrol_target(self.body.label) === self.body) { + return make_node(AST_EmptyStatement, self); + } return self.label.references.length == 0 ? self.body : self; }); @@ -1227,7 +1264,7 @@ merge(Compressor.prototype, { var last_branch = self.body[self.body.length - 1]; if (last_branch) { var stat = last_branch.body[last_branch.body.length - 1]; // last statement - if (stat instanceof AST_Break && compressor.loopcontrol_target(stat.label) === self) + if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) last_branch.body.pop(); } return self; |