Skip to content

Commit

Permalink
fix corner cases in collapse_vars (#4978)
Browse files Browse the repository at this point in the history
fixes #4977
  • Loading branch information
alexlamsl committed May 29, 2021
1 parent d40631f commit 7fa1dea
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 18 deletions.
49 changes: 36 additions & 13 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,7 @@ merge(Compressor.prototype, {
d.escaped.push(parent);
if (depth > 1 && !(value && value.is_constant_expression(scope))) depth = 1;
if (!d.escaped.depth || d.escaped.depth > depth) d.escaped.depth = depth;
if (d.scope !== scope) d.escaped.cross_scope = true;
return;
} else if (value_in_use(node, parent)) {
mark_escaped(tw, d, scope, parent, parent, level + 1, depth);
Expand Down Expand Up @@ -1973,6 +1974,7 @@ merge(Compressor.prototype, {
var read_toplevel = false;
var modify_toplevel = false;
// Locate symbols which may execute code outside of scanning range
var well_defined = true;
var lvalues = get_lvalues(candidate);
var lhs_local = is_lhs_local(lhs);
var rvalue = get_rvalue(candidate);
Expand Down Expand Up @@ -2173,11 +2175,18 @@ merge(Compressor.prototype, {
}
if (node instanceof AST_ObjectIdentity) return symbol_in_lvalues(node, parent);
if (node instanceof AST_PropAccess) {
if (side_effects) return true;
var exp = node.expression;
return side_effects
|| exp instanceof AST_SymbolRef && is_arguments(exp.definition())
|| !value_def && (in_try || !lhs_local)
&& !node.optional && exp.may_throw_on_access(compressor);
if (exp instanceof AST_SymbolRef && is_arguments(exp.definition())) return true;
if (compressor.option("unsafe")) {
if (is_undeclared_ref(exp) && global_names[exp.name]) return false;
if (is_static_fn(exp)) return false;
}
if (!well_defined) return true;
if (value_def) return false;
if (!in_try && lhs_local) return false;
if (node.optional) return false;
return exp.may_throw_on_access(compressor);
}
if (node instanceof AST_Spread) return true;
if (node instanceof AST_SymbolRef) {
Expand Down Expand Up @@ -2537,8 +2546,7 @@ merge(Compressor.prototype, {
}
if (parent instanceof AST_PropAccess) {
var exp = parent.expression;
if (exp === node) return find_stop_value(parent, level + 1);
return find_stop_expr(exp, find_stop_value, node, parent, level);
return exp === node ? find_stop_value(parent, level + 1) : node;
}
if (parent instanceof AST_Sequence) {
return (parent.tail_node() === node ? find_stop_value : find_stop_unused)(parent, level + 1);
Expand Down Expand Up @@ -2770,20 +2778,31 @@ merge(Compressor.prototype, {

function get_lvalues(expr) {
var lvalues = new Dictionary();
if (expr instanceof AST_VarDef) lvalues.add(expr.name.name, lhs);
if (expr instanceof AST_VarDef) {
if (!expr.name.definition().fixed) well_defined = false;
lvalues.add(expr.name.name, lhs);
}
var find_arguments = scope.uses_arguments && !compressor.has_directive("use strict");
var scan_toplevel = scope instanceof AST_Toplevel;
var tw = new TreeWalker(function(node) {
var value;
if (node instanceof AST_SymbolRef) {
value = node.fixed_value() || node;
value = node.fixed_value();
if (!value) {
value = node;
var def = node.definition();
if (!def.undeclared && (def.assignments || !def.escaped || def.escaped.cross_scope)) {
well_defined = false;
}
}
} else if (node instanceof AST_ObjectIdentity) {
value = node;
}
if (value) lvalues.add(node.name, is_modified(compressor, tw, node, value, 0));
if (find_arguments && node instanceof AST_Sub) {
scope.each_argname(function(argname) {
if (!compressor.option("reduce_vars") || argname.definition().assignments) {
if (!argname.definition().fixed) well_defined = false;
lvalues.add(argname.name, true);
}
});
Expand Down Expand Up @@ -4290,6 +4309,14 @@ merge(Compressor.prototype, {
],
});

function is_static_fn(node) {
if (!(node instanceof AST_Dot)) return false;
var expr = node.expression;
if (!is_undeclared_ref(expr)) return false;
var static_fn = static_fns[expr.name];
return static_fn && (static_fn[node.property] || expr.name == "Math" && node.property == "random");
}

// Accomodate when compress option evaluate=false
// as well as the common constant expressions !0 and -1
(function(def) {
Expand Down Expand Up @@ -4912,11 +4939,7 @@ merge(Compressor.prototype, {
if (global_pure_fns[expr.name]) return true;
if (this instanceof AST_New && global_pure_constructors[expr.name]) return true;
}
if (expr instanceof AST_Dot && is_undeclared_ref(expr.expression)) {
var static_fn = static_fns[expr.expression.name];
return static_fn && (static_fn[expr.property]
|| expr.expression.name == "Math" && expr.property == "random");
}
if (is_static_fn(expr)) return true;
}
return compressor.option("annotations") && this.pure || !compressor.pure_funcs(this);
});
Expand Down
1 change: 1 addition & 0 deletions test/compress/annotations.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ issue_3858: {
collapse_vars: true,
inline: true,
keep_fargs: false,
unsafe: true,
unused: true,
}
input: {
Expand Down
1 change: 1 addition & 0 deletions test/compress/arrows.js
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ collapse_value: {
arrows: true,
collapse_vars: true,
keep_fargs: false,
unsafe: true,
unused: true,
}
input: {
Expand Down
1 change: 1 addition & 0 deletions test/compress/classes.js
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,7 @@ collapse_non_strict: {
collapse_rhs: {
options = {
collapse_vars: true,
unsafe: true,
}
input: {
"use strict";
Expand Down

0 comments on commit 7fa1dea

Please sign in to comment.