diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ast.js | 8 | ||||
-rw-r--r-- | lib/compress.js | 45 | ||||
-rw-r--r-- | lib/utils.js | 6 |
3 files changed, 51 insertions, 8 deletions
@@ -929,10 +929,10 @@ TreeWalker.prototype = { } else { for (var i = stack.length; --i >= 0;) { var x = stack[i]; - 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); - } + if (x instanceof AST_Switch + || x instanceof AST_For + || x instanceof AST_ForIn + || x instanceof AST_DWLoop) return x; } } } 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; diff --git a/lib/utils.js b/lib/utils.js index 79039665..4d3d60f6 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -166,6 +166,12 @@ function string_template(text, props) { }); }; +function remove(array, el) { + for (var i = array.length; --i >= 0;) { + if (array[i] === el) array.splice(i, 1); + } +}; + function mergeSort(array, cmp) { if (array.length < 2) return array.slice(); function merge(a, b) { |