diff options
-rw-r--r-- | lib/compress.js | 31 | ||||
-rw-r--r-- | test/compress/collapse_vars.js | 76 |
2 files changed, 93 insertions, 14 deletions
diff --git a/lib/compress.js b/lib/compress.js index 2d0a03ae..c402e3ba 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -913,8 +913,8 @@ merge(Compressor.prototype, { } function tighten_body(statements, compressor) { - var scope = compressor.find_parent(AST_Scope); - var in_loop = is_in_node(AST_IterationStatement); + var in_loop, in_try, scope; + find_loop_scope_try(); var CHANGED, max_iter = 10; do { CHANGED = false; @@ -937,13 +937,20 @@ merge(Compressor.prototype, { } } while (CHANGED && max_iter-- > 0); - function is_in_node(type) { - if (compressor.self() instanceof type) return true; - for (var node, level = 0; node = compressor.parent(level); level++) { - if (node instanceof type) return true; - if (node instanceof AST_Scope) break; - } - return false; + function find_loop_scope_try() { + var node = compressor.self(), level = 0; + do { + if (node instanceof AST_Catch || node instanceof AST_Finally) { + level++; + } else if (node instanceof AST_IterationStatement) { + in_loop = true; + } else if (node instanceof AST_Scope) { + scope = node; + break; + } else if (node instanceof AST_Try) { + in_try = true; + } + } while (node = compressor.parent(level++)); } // Search from right to left for assignment-like expressions: @@ -958,7 +965,6 @@ merge(Compressor.prototype, { if (scope.uses_eval || scope.uses_with) return statements; var args; var candidates = []; - var in_try = is_in_node(AST_Try); var stat_index = statements.length; var scanner = new TreeTransformer(function(node, descend) { if (abort) return node; @@ -1433,7 +1439,10 @@ merge(Compressor.prototype, { if (def.orig.length == 1 && def.orig[0] instanceof AST_SymbolDefun) return false; if (def.scope !== scope) return true; return !all(def.references, function(ref) { - return ref.scope === scope; + var s = ref.scope; + // "block" scope within AST_Catch + if (s.TYPE == "Scope") s = s.parent_scope; + return s === scope; }); } diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index ecf64241..60505509 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -2219,8 +2219,8 @@ unused_orig: { console.log(function(b) { var c = b; for (var d in c) { - var a = c[0]; - return --b + a; + var a; + return --b + c[0]; } a && a.NaN; }([2]), a); @@ -4666,7 +4666,7 @@ issue_2931: { expect_stdout: "undefined" } -issue_2954: { +issue_2954_1: { options = { collapse_vars: true, } @@ -4700,3 +4700,73 @@ issue_2954: { } expect_stdout: "PASS" } + +issue_2954_2: { + options = { + collapse_vars: true, + } + input: { + var a = "FAIL_1", b; + try { + throw 0; + } catch (e) { + do { + b = function() { + throw new Error("PASS"); + }(); + a = "FAIL_2"; + b && b.c; + } while (0); + } + console.log(a); + } + expect: { + var a = "FAIL_1", b; + try { + throw 0; + } catch (e) { + do { + a = "FAIL_2"; + (b = function() { + throw new Error("PASS"); + }()) && b.c; + } while (0); + } + console.log(a); + } + expect_stdout: Error("PASS") +} + +issue_2954_3: { + options = { + collapse_vars: true, + } + input: { + var a = "FAIL_1", b; + try { + } finally { + do { + b = function() { + throw new Error("PASS"); + }(); + a = "FAIL_2"; + b && b.c; + } while (0); + } + console.log(a); + } + expect: { + var a = "FAIL_1", b; + try { + } finally { + do { + a = "FAIL_2"; + (b = function() { + throw new Error("PASS"); + }()) && b.c; + } while (0); + } + console.log(a); + } + expect_stdout: Error("PASS") +} |