diff --git a/lib/compress.js b/lib/compress.js index b5c67c2d..3102d76f 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1818,27 +1818,34 @@ Compressor.prototype.compress = function(node) { function tighten_body(statements, compressor) { var in_loop, in_try, scope; find_loop_scope_try(); - var CHANGED, max_iter = 10; + var changed, last_changed, max_iter = 10; do { - CHANGED = false; - eliminate_spurious_blocks(statements); + last_changed = changed; + changed = 0; + if (eliminate_spurious_blocks(statements)) changed = 1; + if (!changed && last_changed == 1) break; if (compressor.option("dead_code")) { - eliminate_dead_code(statements, compressor); + if (eliminate_dead_code(statements, compressor)) changed = 2; + if (!changed && last_changed == 2) break; } if (compressor.option("if_return")) { - handle_if_return(statements, compressor); + if (handle_if_return(statements, compressor)) changed = 3; + if (!changed && last_changed == 3) break; } if (compressor.sequences_limit > 0) { - sequencesize(statements, compressor); - sequencesize_2(statements, compressor); + if (sequencesize(statements, compressor)) changed = 4; + if (!changed && last_changed == 4) break; + if (sequencesize_2(statements, compressor)) changed = 5; + if (!changed && last_changed == 5) break; } if (compressor.option("join_vars")) { - join_consecutive_vars(statements); + if (join_consecutive_vars(statements)) changed = 6; + if (!changed && last_changed == 6) break; } if (compressor.option("collapse_vars")) { - collapse(statements, compressor); + if (collapse(statements, compressor)) changed = 7; } - } while (CHANGED && max_iter-- > 0); + } while (changed && max_iter-- > 0); return statements; function find_loop_scope_try() { @@ -1874,10 +1881,11 @@ Compressor.prototype.compress = function(node) { // Will not attempt to collapse assignments into or past code blocks // which are not sequentially executed, e.g. loops and conditionals. function collapse(statements, compressor) { - if (scope.pinned()) return statements; + if (scope.pinned()) return; var args; var assignments = new Dictionary(); var candidates = []; + var changed = false; var declare_only = new Dictionary(); var force_single; var stat_index = statements.length; @@ -1924,7 +1932,7 @@ Compressor.prototype.compress = function(node) { } else { replaced++; } - CHANGED = abort = true; + changed = abort = true; AST_Node.info("Collapsing {node} [{file}:{line},{col}]", { node: node, file: node.start.file, @@ -2137,11 +2145,12 @@ Compressor.prototype.compress = function(node) { && !compressor.exposed(def); value_def.last_ref = false; value_def.single_use = false; - CHANGED = true; + changed = true; } if (replaced && !remove_candidate(candidate)) statements.splice(stat_index, 1); } } + return changed; function signal_abort(node) { if (abort) return node; @@ -3094,12 +3103,12 @@ Compressor.prototype.compress = function(node) { } function eliminate_spurious_blocks(statements) { - var seen_dirs = []; + var changed = false, seen_dirs = []; for (var i = 0; i < statements.length;) { var stat = statements[i]; if (stat instanceof AST_BlockStatement) { if (all(stat.body, safe_to_trim)) { - CHANGED = true; + changed = true; eliminate_spurious_blocks(stat.body); [].splice.apply(statements, [i, 1].concat(stat.body)); i += stat.body.length; @@ -3108,22 +3117,24 @@ Compressor.prototype.compress = function(node) { } if (stat instanceof AST_Directive) { if (member(stat.value, seen_dirs)) { - CHANGED = true; + changed = true; statements.splice(i, 1); continue; } seen_dirs.push(stat.value); } if (stat instanceof AST_EmptyStatement) { - CHANGED = true; + changed = true; statements.splice(i, 1); continue; } i++; } + return changed; } function handle_if_return(statements, compressor) { + var changed = false; var self = compressor.self(); var parent = compressor.parent(); var in_lambda = last_of(function(node) { @@ -3138,13 +3149,13 @@ Compressor.prototype.compress = function(node) { if (in_lambda && !next && stat instanceof AST_Return) { if (!stat.value) { - CHANGED = true; + changed = true; statements.splice(i, 1); continue; } var tail = stat.value.tail_node(); if (tail instanceof AST_UnaryPrefix && tail.operator == "void") { - CHANGED = true; + changed = true; var body; if (tail === stat.value) { body = tail.expression; @@ -3163,7 +3174,7 @@ Compressor.prototype.compress = function(node) { var ab = aborts(stat.body); if (can_merge_flow(ab)) { if (ab.label) remove(ab.label.thedef.references, ab); - CHANGED = true; + changed = true; stat = stat.clone(); stat.condition = stat.condition.negate(compressor); var body = as_statement_array_with_return(stat.body, ab); @@ -3181,7 +3192,7 @@ Compressor.prototype.compress = function(node) { if (ab && !stat.alternative && stat.body instanceof AST_BlockStatement && next instanceof AST_Jump) { var negated = stat.condition.negate(compressor); if (negated.print_to_string().length <= stat.condition.print_to_string().length) { - CHANGED = true; + changed = true; stat = stat.clone(); stat.condition = negated; statements[j] = stat.body; @@ -3195,7 +3206,7 @@ Compressor.prototype.compress = function(node) { var alt = aborts(stat.alternative); if (can_merge_flow(alt)) { if (alt.label) remove(alt.label.thedef.references, alt); - CHANGED = true; + changed = true; stat = stat.clone(); stat.body = make_node(AST_BlockStatement, stat.body, { body: as_statement_array(stat.body).concat(extract_functions()) @@ -3231,7 +3242,7 @@ Compressor.prototype.compress = function(node) { // if (foo()) return; return; ---> foo(); return; if (!value && !stat.alternative && (in_lambda && !next || next instanceof AST_Return && !next.value)) { - CHANGED = true; + changed = true; statements[i] = make_node(AST_SimpleStatement, stat.condition, { body: stat.condition }); @@ -3240,7 +3251,7 @@ Compressor.prototype.compress = function(node) { //--- // if (foo()) return x; return y; ---> return foo() ? x : y; if (!stat.alternative && next instanceof AST_Return) { - CHANGED = true; + changed = true; stat = stat.clone(); stat.alternative = next; statements.splice(i, 1, stat.transform(compressor)); @@ -3250,7 +3261,7 @@ Compressor.prototype.compress = function(node) { //--- // if (foo()) return x; [ return ; ] ---> return foo() ? x : undefined; if (!stat.alternative && !next && in_lambda && (in_bool || value && multiple_if_returns)) { - CHANGED = true; + changed = true; stat = stat.clone(); stat.alternative = make_node(AST_Return, stat, { value: null @@ -3268,7 +3279,7 @@ Compressor.prototype.compress = function(node) { if (compressor.option("sequences") && in_lambda && !stat.alternative && (!prev && in_iife || prev instanceof AST_If && prev.body instanceof AST_Return) && next_index(j) == statements.length && next instanceof AST_SimpleStatement) { - CHANGED = true; + changed = true; stat = stat.clone(); stat.alternative = make_node(AST_BlockStatement, next, { body: [ @@ -3284,6 +3295,7 @@ Compressor.prototype.compress = function(node) { } } } + return changed; function has_multiple_if_returns(statements) { var n = 0; @@ -3411,7 +3423,7 @@ Compressor.prototype.compress = function(node) { if (has_quit) has_quit.forEach(function(stat) { extract_declarations_from_unreachable_code(compressor, stat, statements); }); - CHANGED = statements.length != len; + return statements.length != len; } function sequencesize(statements, compressor) { @@ -3439,7 +3451,7 @@ Compressor.prototype.compress = function(node) { } push_seq(); statements.length = n; - if (n != len) CHANGED = true; + return n != len; } function to_simple_statement(block, decls) { @@ -3459,13 +3471,7 @@ Compressor.prototype.compress = function(node) { } function sequencesize_2(statements, compressor) { - function cons_seq(right) { - n--; - CHANGED = true; - var left = prev.body; - return make_sequence(left, [ left, right ]); - } - var n = 0, prev; + var changed = false, n = 0, prev; for (var i = 0; i < statements.length; i++) { var stat = statements[i]; if (prev) { @@ -3488,7 +3494,7 @@ Compressor.prototype.compress = function(node) { else { stat.init = prev.body; n--; - CHANGED = true; + changed = true; } } } @@ -3518,7 +3524,7 @@ Compressor.prototype.compress = function(node) { i += len; n += len + 1; prev = null; - CHANGED = true; + changed = true; continue; } } @@ -3526,6 +3532,14 @@ Compressor.prototype.compress = function(node) { prev = stat instanceof AST_SimpleStatement ? stat : null; } statements.length = n; + return changed; + + function cons_seq(right) { + n--; + changed = true; + var left = prev.body; + return make_sequence(left, [ left, right ]); + } } function extract_exprs(body) { @@ -3680,17 +3694,17 @@ Compressor.prototype.compress = function(node) { } function join_consecutive_vars(statements) { - var defs; + var changed = false, defs; for (var i = 0, j = -1; i < statements.length; i++) { var stat = statements[i]; var prev = statements[j]; if (stat instanceof AST_Definitions) { if (prev && prev.TYPE == stat.TYPE) { prev.definitions = prev.definitions.concat(stat.definitions); - CHANGED = true; + changed = true; } else if (defs && defs.TYPE == stat.TYPE && declarations_only(stat)) { defs.definitions = defs.definitions.concat(stat.definitions); - CHANGED = true; + changed = true; } else if (stat instanceof AST_Var) { var exprs = merge_assigns(prev, stat); if (exprs) { @@ -3698,7 +3712,7 @@ Compressor.prototype.compress = function(node) { prev.body = make_sequence(prev, exprs); j++; } - CHANGED = true; + changed = true; } else { j++; } @@ -3712,7 +3726,7 @@ Compressor.prototype.compress = function(node) { } else if (stat instanceof AST_For) { var exprs = join_assigns(prev, stat.init); if (exprs) { - CHANGED = true; + changed = true; stat.init = exprs.length ? make_sequence(stat.init, exprs) : null; } else if (prev instanceof AST_Var && (!stat.init || stat.init.TYPE == prev.TYPE)) { if (stat.init) { @@ -3720,17 +3734,17 @@ Compressor.prototype.compress = function(node) { } defs = stat.init = prev; statements[j] = merge_defns(stat); - CHANGED = true; + changed = true; continue; } else if (defs && stat.init && defs.TYPE == stat.init.TYPE && declarations_only(stat.init)) { defs.definitions = defs.definitions.concat(stat.init.definitions); stat.init = null; - CHANGED = true; + changed = true; } else if (stat.init instanceof AST_Var) { defs = stat.init; exprs = merge_assigns(prev, stat.init); if (exprs) { - CHANGED = true; + changed = true; if (exprs.length == 0) { statements[j] = merge_defns(stat); continue; @@ -3749,7 +3763,7 @@ Compressor.prototype.compress = function(node) { name.definition().references.push(ref); }); defs.definitions = defns; - CHANGED = true; + changed = true; } stat.object = join_assigns_expr(stat.object); } else if (stat instanceof AST_If) { @@ -3757,7 +3771,7 @@ Compressor.prototype.compress = function(node) { } else if (stat instanceof AST_SimpleStatement) { var exprs = join_assigns(prev, stat.body); if (exprs) { - CHANGED = true; + changed = true; if (!exprs.length) continue; stat.body = make_sequence(stat.body, exprs); } @@ -3769,11 +3783,12 @@ Compressor.prototype.compress = function(node) { statements[++j] = defs ? merge_defns(stat) : stat; } statements.length = j + 1; + return changed; function join_assigns_expr(value) { var exprs = join_assigns(prev, value, 1); if (!exprs) return value; - CHANGED = true; + changed = true; var tail = value.tail_node(); if (exprs[exprs.length - 1] !== tail) exprs.push(tail.left); return make_sequence(value, exprs); @@ -3788,7 +3803,7 @@ Compressor.prototype.compress = function(node) { if (parent instanceof AST_ForEnumeration && parent.init === node) return node; if (!declarations_only(node)) return node; defs.definitions = defs.definitions.concat(node.definitions); - CHANGED = true; + changed = true; if (parent instanceof AST_For && parent.init === node) return null; return in_list ? List.skip : make_node(AST_EmptyStatement, node); }