diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2017-03-09 19:11:05 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-09 19:11:05 +0800 |
commit | b633706ce42576b7e2aa85a96c5691bde87e71ac (patch) | |
tree | 524e6ab7980d86f0837c188cdb35fe8aa77b7487 /lib | |
parent | e9920f7ca162ce062cc481b876be293d7324a714 (diff) | |
download | tracifyjs-b633706ce42576b7e2aa85a96c5691bde87e71ac.tar.gz tracifyjs-b633706ce42576b7e2aa85a96c5691bde87e71ac.zip |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/compress.js | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/lib/compress.js b/lib/compress.js index f6b76ec2..3964636f 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -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()) { |