Skip to content

Commit

Permalink
enhance collapse_vars (#5556)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl committed Jul 12, 2022
1 parent 154edf0 commit 24443b6
Showing 1 changed file with 106 additions and 99 deletions.
205 changes: 106 additions & 99 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -1675,6 +1675,7 @@ Compressor.prototype.compress = function(node) {
if (may_throw && parent.bcatch && parent.bcatch !== node) return true;
}
}
return false;
}

var identifier_atom = makePredicate("Infinity NaN undefined");
Expand Down Expand Up @@ -1917,7 +1918,7 @@ Compressor.prototype.compress = function(node) {
var in_lambda = last_of(compressor, function(node) {
return node instanceof AST_Lambda;
});
var block_scope, in_loop, in_try, scope;
var block_scope, iife_in_try, in_iife_single, in_loop, in_try, scope;
find_loop_scope_try();
var changed, last_changed, max_iter = 10;
do {
Expand Down Expand Up @@ -2490,10 +2491,10 @@ Compressor.prototype.compress = function(node) {
var after = stop_after;
var if_hit = stop_if_hit;
for (var i = 0; !abort && i < fn.argnames.length; i++) {
if (may_throw_arg(reject, fn.argnames[i], node.args[i])) abort = true;
if (arg_may_throw(reject, fn.argnames[i], node.args[i])) abort = true;
}
if (!abort) {
if (fn.rest && may_throw_arg(reject, fn.rest, make_node(AST_Array, node, {
if (fn.rest && arg_may_throw(reject, fn.rest, make_node(AST_Array, node, {
elements: node.args.slice(i),
}))) {
abort = true;
Expand Down Expand Up @@ -2579,128 +2580,134 @@ Compressor.prototype.compress = function(node) {
}
}

function may_throw_arg(reject, node, value) {
function arg_may_throw(reject, node, value) {
if (node instanceof AST_DefaultValue) {
return reject(node.value)
|| may_throw_arg(reject, node.name, node.value)
|| !is_undefined(value) && may_throw_arg(reject, node.name, value);
|| arg_may_throw(reject, node.name, node.value)
|| !is_undefined(value) && arg_may_throw(reject, node.name, value);
}
if (!value) return !(node instanceof AST_Symbol);
if (node instanceof AST_Destructured) {
if (node.rest && may_throw_arg(reject, node.rest)) return true;
if (node.rest && arg_may_throw(reject, node.rest)) return true;
if (node instanceof AST_DestructuredArray) {
if (value instanceof AST_Array) return !all(node.elements, function(element, index) {
return !may_throw_arg(reject, element, value[index]);
return !arg_may_throw(reject, element, value[index]);
});
return value.is_string(compressor) && !all(node.elements, function(element) {
return !may_throw_arg(reject, element);
return !arg_may_throw(reject, element);
});
}
if (node instanceof AST_DestructuredObject) {
if (value.may_throw_on_access(compressor)) return true;
return !all(node.properties, function(prop) {
if (prop.key instanceof AST_Node && reject(prop.key)) return false;
return !may_throw_arg(reject, prop.value);
return !arg_may_throw(reject, prop.value);
});
}
}
}

function extract_args() {
var iife, fn = compressor.self();
if (fn instanceof AST_LambdaExpression
&& !is_generator(fn)
&& !fn.uses_arguments
&& !fn.pinned()
&& (iife = compressor.parent()) instanceof AST_Call
&& iife.expression === fn
&& is_iife_single(iife)
&& all(iife.args, function(arg) {
return !(arg instanceof AST_Spread);
})) {
var fn_strict = fn.in_strict_mode(compressor)
&& !fn.parent_scope.resolve(true).in_strict_mode(compressor);
var check_arg = false, has_await;
if (is_async(fn)) {
check_arg = true;
has_await = function(node) {
return node instanceof AST_Symbol && node.name == "await";
};
} else {
check_arg = find_try(compressor, 1, iife, null, true, true);
has_await = function(node) {
return node instanceof AST_Await && !tw.find_parent(AST_Scope);
};
if (in_iife_single === false) return;
var iife = compressor.parent(), fn = compressor.self();
if (in_iife_single === undefined) {
if (!(fn instanceof AST_LambdaExpression)
|| is_generator(fn)
|| fn.uses_arguments
|| fn.pinned()
|| !(iife instanceof AST_Call)
|| iife.expression !== fn
|| !all(iife.args, function(arg) {
return !(arg instanceof AST_Spread);
})) {
in_iife_single = false;
return;
}
var arg_scope = null;
var tw = new TreeWalker(function(node, descend) {
if (!arg) return true;
if (has_await(node) || node instanceof AST_Yield) {
arg = null;
return true;
}
if (node instanceof AST_ObjectIdentity && (fn_strict || !arg_scope)) {
arg = null;
return true;
}
if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) {
var s = node.definition().scope;
if (s !== scope) while (s = s.parent_scope) {
if (s === scope) return true;
}
arg = null;
}
if (node instanceof AST_Scope && !is_arrow(node)) {
var save_scope = arg_scope;
arg_scope = node;
descend();
arg_scope = save_scope;
return true;
}
});
args = iife.args.slice();
var len = args.length;
var names = new Dictionary();
for (var i = fn.argnames.length; --i >= 0;) {
var sym = fn.argnames[i];
var arg = args[i];
var value = null;
if (sym instanceof AST_DefaultValue) {
value = sym.value;
sym = sym.name;
args[len + i] = value;
}
if (sym instanceof AST_Destructured) {
if (check_arg && may_throw_arg(function(node) {
return node.has_side_effects(compressor);
}, sym, arg)) {
candidates.length = 0;
break;
}
args[len + i] = fn.argnames[i];
continue;
if (!is_iife_single(iife)) return;
in_iife_single = true;
}
var fn_strict = fn.in_strict_mode(compressor)
&& !fn.parent_scope.resolve(true).in_strict_mode(compressor);
var has_await;
if (is_async(fn)) {
has_await = function(node) {
return node instanceof AST_Symbol && node.name == "await";
};
iife_in_try = true;
} else {
has_await = function(node) {
return node instanceof AST_Await && !tw.find_parent(AST_Scope);
};
if (iife_in_try === undefined) iife_in_try = find_try(compressor, 1, iife, null, true, true);
}
var arg_scope = null;
var tw = new TreeWalker(function(node, descend) {
if (!arg) return true;
if (has_await(node) || node instanceof AST_Yield) {
arg = null;
return true;
}
if (node instanceof AST_ObjectIdentity && (fn_strict || !arg_scope)) {
arg = null;
return true;
}
if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) {
var s = node.definition().scope;
if (s !== scope) while (s = s.parent_scope) {
if (s === scope) return true;
}
if (names.has(sym.name)) continue;
names.set(sym.name, true);
if (value) arg = is_undefined(arg) ? value : null;
if (!arg && !value) {
arg = make_node(AST_Undefined, sym).transform(compressor);
} else if (arg instanceof AST_Lambda && arg.pinned()) {
arg = null;
} else if (arg) {
arg.walk(tw);
arg = null;
}
if (node instanceof AST_Scope && !is_arrow(node)) {
var save_scope = arg_scope;
arg_scope = node;
descend();
arg_scope = save_scope;
return true;
}
});
args = iife.args.slice();
var len = args.length;
var names = new Dictionary();
for (var i = fn.argnames.length; --i >= 0;) {
var sym = fn.argnames[i];
var arg = args[i];
var value = null;
if (sym instanceof AST_DefaultValue) {
value = sym.value;
sym = sym.name;
args[len + i] = value;
}
if (sym instanceof AST_Destructured) {
if (iife_in_try && arg_may_throw(function(node) {
return node.has_side_effects(compressor);
}, sym, arg)) {
candidates.length = 0;
break;
}
if (!arg) continue;
var candidate = make_node(AST_VarDef, sym, {
name: sym,
value: arg,
});
candidate.name_index = i;
candidate.arg_index = value ? len + i : i;
candidates.unshift([ candidate ]);
args[len + i] = fn.argnames[i];
continue;
}
if (fn.rest) args.push(fn.rest);
if (names.has(sym.name)) continue;
names.set(sym.name, true);
if (value) arg = is_undefined(arg) ? value : null;
if (!arg && !value) {
arg = make_node(AST_Undefined, sym).transform(compressor);
} else if (arg instanceof AST_Lambda && arg.pinned()) {
arg = null;
} else if (arg) {
arg.walk(tw);
}
if (!arg) continue;
var candidate = make_node(AST_VarDef, sym, {
name: sym,
value: arg,
});
candidate.name_index = i;
candidate.arg_index = value ? len + i : i;
candidates.unshift([ candidate ]);
}
if (fn.rest) args.push(fn.rest);
}

function extract_candidates(expr, unused) {
Expand Down

0 comments on commit 24443b6

Please sign in to comment.