fix & improve function argument compression (#1584)

- one-use function call => IIFE should take `eval()` & `arguments` into account
- if unused parameter cannot be eliminated, replace it with `0`

fixes #1583
This commit is contained in:
Alex Lam S.L
2017-03-09 19:11:05 +08:00
committed by GitHub
parent e9920f7ca1
commit b633706ce4
3 changed files with 171 additions and 13 deletions

View File

@@ -281,6 +281,9 @@ merge(Compressor.prototype, {
if (node instanceof AST_Function
&& (iife = tw.parent()) instanceof AST_Call
&& iife.expression === node) {
// Virtually turn IIFE parameters into variable definitions:
// (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})()
// So existing transformation rules can work on them.
node.argnames.forEach(function(arg, i) {
var d = arg.definition();
d.fixed = iife.args[i] || make_node(AST_Undefined, iife);
@@ -1810,10 +1813,12 @@ merge(Compressor.prototype, {
node.name = null;
}
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
if (!compressor.option("keep_fargs")) {
for (var a = node.argnames, i = a.length; --i >= 0;) {
var sym = a[i];
if (!(sym.definition().id in in_use_ids)) {
var trim = !compressor.option("keep_fargs");
for (var a = node.argnames, i = a.length; --i >= 0;) {
var sym = a[i];
if (!(sym.definition().id in in_use_ids)) {
sym.__unused = true;
if (trim) {
a.pop();
compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", {
name : sym.name,
@@ -1822,7 +1827,9 @@ merge(Compressor.prototype, {
col : sym.start.col
});
}
else break;
}
else {
trim = false;
}
}
}
@@ -2609,6 +2616,9 @@ merge(Compressor.prototype, {
exp = def.fixed;
if (compressor.option("unused")
&& def.references.length == 1
&& !(def.scope.uses_arguments
&& def.orig[0] instanceof AST_SymbolFunarg)
&& !def.scope.uses_eval
&& compressor.find_parent(AST_Scope) === def.scope) {
self.expression = exp;
}
@@ -2617,16 +2627,26 @@ merge(Compressor.prototype, {
if (compressor.option("unused")
&& exp instanceof AST_Function
&& !exp.uses_arguments
&& !exp.uses_eval
&& self.args.length > exp.argnames.length) {
var end = exp.argnames.length;
for (var i = end, len = self.args.length; i < len; i++) {
var node = self.args[i].drop_side_effect_free(compressor);
if (node) {
self.args[end++] = node;
&& !exp.uses_eval) {
var pos = 0, last = 0;
for (var i = 0, len = self.args.length; i < len; i++) {
var trim = i >= exp.argnames.length;
if (trim || exp.argnames[i].__unused) {
var node = self.args[i].drop_side_effect_free(compressor);
if (node) {
self.args[pos++] = node;
} else if (!trim) {
self.args[pos++] = make_node(AST_Number, self.args[i], {
value: 0
});
continue;
}
} else {
self.args[pos++] = self.args[i];
}
last = pos;
}
self.args.length = end;
self.args.length = last;
}
if (compressor.option("unsafe")) {
if (exp instanceof AST_SymbolRef && exp.undeclared()) {