aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2018-02-13 01:41:22 +0800
committerGitHub <noreply@github.com>2018-02-13 01:41:22 +0800
commit0c4f315c026e607d00dd74ad7417344a937bf6dd (patch)
tree83b5324ae53679633bda9b0f50abb62e951f8014
parent0809699bdc7b1c249c7bbe02924a4a861aff8bea (diff)
downloadtracifyjs-0c4f315c026e607d00dd74ad7417344a937bf6dd.tar.gz
tracifyjs-0c4f315c026e607d00dd74ad7417344a937bf6dd.zip
fix corner case in `collapse_vars` (#2909)
fixes #2908
-rw-r--r--lib/compress.js32
-rw-r--r--test/compress/collapse_vars.js29
2 files changed, 51 insertions, 10 deletions
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"
+}