From: Alex Lam S.L Date: Mon, 12 Feb 2018 17:41:22 +0000 (+0800) Subject: fix corner case in `collapse_vars` (#2909) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=0c4f315c026e607d00dd74ad7417344a937bf6dd;p=UglifyJS.git fix corner case in `collapse_vars` (#2909) fixes #2908 --- diff --git a/lib/compress.js b/lib/compress.js index 2b796dcc..ad691f7a 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -972,13 +972,13 @@ merge(Compressor.prototype, { || node instanceof AST_Try || node instanceof AST_With || parent instanceof AST_For && node !== parent.init - || (side_effects || !replace_all) + || !replace_all && (node instanceof AST_SymbolRef && !node.is_declared(compressor))) { abort = true; return node; } // Stop only if candidate is found within conditional branches - if (!stop_if_hit && (side_effects || !replace_all) + if (!stop_if_hit && (!lhs_local || !replace_all) && (parent instanceof AST_Binary && lazy_op(parent.operator) && parent.left !== node || parent instanceof AST_Conditional && parent.condition !== node || parent instanceof AST_If && parent.condition !== node)) { @@ -1096,17 +1096,12 @@ merge(Compressor.prototype, { var stop_if_hit = null; var lhs = get_lhs(candidate); if (!lhs || is_lhs_read_only(lhs) || lhs.has_side_effects(compressor)) continue; + var lhs_local = is_lhs_local(lhs); // Locate symbols which may execute code outside of scanning range var lvalues = get_lvalues(candidate); if (lhs instanceof AST_SymbolRef) lvalues[lhs.name] = false; - var replace_all = value_def; - if (!replace_all && lhs instanceof AST_SymbolRef) { - var def = lhs.definition(); - if (def.references.length - def.replaced == (candidate instanceof AST_VarDef ? 1 : 2)) { - replace_all = true; - } - } var side_effects = value_has_side_effects(candidate); + var replace_all = replace_all_symbols(); var may_throw = candidate.may_throw(compressor); var funarg = candidate.name instanceof AST_SymbolFunarg; var hit = funarg; @@ -1151,7 +1146,7 @@ merge(Compressor.prototype, { hit_index++; } branch.expression = branch.expression.transform(scanner); - if (side_effects || !replace_all) break; + if (!replace_all) break; } } abort = true; @@ -1393,11 +1388,28 @@ merge(Compressor.prototype, { })); } + function is_lhs_local(lhs) { + while (lhs instanceof AST_PropAccess) lhs = lhs.expression; + return lhs instanceof AST_SymbolRef && lhs.definition().scope === scope; + } + function value_has_side_effects(expr) { if (expr instanceof AST_Unary) return false; return get_rvalue(expr).has_side_effects(compressor); } + function replace_all_symbols() { + if (side_effects) return false; + if (value_def) return true; + if (lhs instanceof AST_SymbolRef) { + var def = lhs.definition(); + if (def.references.length - def.replaced == (candidate instanceof AST_VarDef ? 1 : 2)) { + return true; + } + } + return false; + } + function may_modify(sym) { var def = sym.definition(); if (def.orig.length == 1 && def.orig[0] instanceof AST_SymbolDefun) return false; diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index ed1d8d97..2c7bbdeb 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -4517,3 +4517,32 @@ issue_2891_2: { } expect_stdout: true } + +issue_2908: { + options = { + collapse_vars: true, + } + input: { + var a = 0, b = 0; + function f(c) { + if (1 == c) return; + a++; + if (2 == c) b = a; + } + f(0); + f(2); + console.log(b); + } + expect: { + var a = 0, b = 0; + function f(c) { + if (1 == c) return; + a++; + if (2 == c) b = a; + } + f(0); + f(2); + console.log(b); + } + expect_stdout: "2" +}