aboutsummaryrefslogtreecommitdiff
path: root/lib/compress.js
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 /lib/compress.js
parent0809699bdc7b1c249c7bbe02924a4a861aff8bea (diff)
downloadtracifyjs-0c4f315c026e607d00dd74ad7417344a937bf6dd.tar.gz
tracifyjs-0c4f315c026e607d00dd74ad7417344a937bf6dd.zip
fix corner case in `collapse_vars` (#2909)
fixes #2908
Diffstat (limited to 'lib/compress.js')
-rw-r--r--lib/compress.js32
1 files changed, 22 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;