diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2020-02-12 23:46:16 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-12 23:46:16 +0000 |
commit | 83a42716c37eb644c490454d7f2119b1fe8158b1 (patch) | |
tree | 773bc0657e4965f2358c2c56b254a4b0256661d7 /lib | |
parent | 2557148bba9e380004c69551aa07f2f424d65159 (diff) | |
download | tracifyjs-83a42716c37eb644c490454d7f2119b1fe8158b1.tar.gz tracifyjs-83a42716c37eb644c490454d7f2119b1fe8158b1.zip |
fix corner case in `unused` (#3716)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/compress.js | 123 |
1 files changed, 66 insertions, 57 deletions
diff --git a/lib/compress.js b/lib/compress.js index 55e40ef2..8a33b474 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -4001,6 +4001,8 @@ merge(Compressor.prototype, { }; // pass 3: we should drop declarations not in_use var unused_fn_names = []; + var calls_to_drop_args = []; + var fns_with_marked_args = []; var tt = new TreeTransformer(function(node, descend, in_list) { var parent = tt.parent(); if (drop_vars) { @@ -4041,6 +4043,7 @@ merge(Compressor.prototype, { } } } + if (node instanceof AST_Call) calls_to_drop_args.push(node); if (scope !== self) return; if (node instanceof AST_Function && node.name && drop_fn_name(node.name.definition())) { unused_fn_names.push(node); @@ -4059,6 +4062,7 @@ merge(Compressor.prototype, { trim = false; } } + fns_with_marked_args.push(node); } if (drop_funcs && node instanceof AST_Defun && node !== self) { var def = node.name.definition(); @@ -4252,6 +4256,9 @@ merge(Compressor.prototype, { unused_fn_names.forEach(function(fn) { fn.name = null; }); + calls_to_drop_args.forEach(function(call) { + drop_unused_call_args(call, compressor, fns_with_marked_args); + }); function log(sym, text, props) { AST_Node[sym.unreferenced() ? "warn" : "info"](text, props); @@ -5448,6 +5455,62 @@ merge(Compressor.prototype, { return make_sequence(node, x); } + function drop_unused_call_args(call, compressor, fns_with_marked_args) { + var exp = call.expression; + var fn = exp instanceof AST_SymbolRef ? exp.fixed_value() : exp; + if (!(fn instanceof AST_Lambda)) return; + if (fn.uses_arguments) return; + if (fn.pinned()) return; + if (fns_with_marked_args && fns_with_marked_args.indexOf(fn) < 0) return; + var args = call.args; + var pos = 0, last = 0; + var drop_fargs = fn === exp && !fn.name && compressor.drop_fargs(fn, call); + var side_effects = []; + for (var i = 0; i < args.length; i++) { + var trim = i >= fn.argnames.length; + if (trim || fn.argnames[i].__unused) { + var node = args[i].drop_side_effect_free(compressor); + if (drop_fargs) { + fn.argnames.splice(i, 1); + args.splice(i, 1); + if (node) side_effects.push(node); + i--; + continue; + } else if (node) { + side_effects.push(node); + args[pos++] = make_sequence(call, side_effects); + side_effects = []; + } else if (!trim) { + if (side_effects.length) { + node = make_sequence(call, side_effects); + side_effects = []; + } else { + node = make_node(AST_Number, args[i], { + value: 0 + }); + } + args[pos++] = node; + continue; + } + } else { + side_effects.push(args[i]); + args[pos++] = make_sequence(call, side_effects); + side_effects = []; + } + last = pos; + } + if (drop_fargs) for (; i < fn.argnames.length; i++) { + if (fn.argnames[i].__unused) fn.argnames.splice(i--, 1); + } + args.length = last; + if (!side_effects.length) return; + var arg = make_sequence(call, side_effects); + args.push(args.length < fn.argnames.length ? make_node(AST_UnaryPrefix, call, { + operator: "void", + expression: arg + }) : arg); + } + OPT(AST_Call, function(self, compressor) { var exp = self.expression; if (compressor.option("sequences")) { @@ -5464,63 +5527,7 @@ merge(Compressor.prototype, { if (seq !== self) return seq.optimize(compressor); } } - var fn = exp; - if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) { - fn = fn.fixed_value(); - } - var is_func = fn instanceof AST_Lambda; - if (compressor.option("unused") - && is_func - && !fn.uses_arguments - && !fn.pinned()) { - var pos = 0, last = 0; - var drop_fargs = exp === fn && !fn.name && compressor.drop_fargs(fn, self); - var side_effects = []; - for (var i = 0; i < self.args.length; i++) { - var trim = i >= fn.argnames.length; - if (trim || fn.argnames[i].__unused) { - var node = self.args[i].drop_side_effect_free(compressor); - if (drop_fargs) { - fn.argnames.splice(i, 1); - self.args.splice(i, 1); - if (node) side_effects.push(node); - i--; - continue; - } else if (node) { - side_effects.push(node); - self.args[pos++] = make_sequence(self, side_effects); - side_effects = []; - } else if (!trim) { - if (side_effects.length) { - node = make_sequence(self, side_effects); - side_effects = []; - } else { - node = make_node(AST_Number, self.args[i], { - value: 0 - }); - } - self.args[pos++] = node; - continue; - } - } else { - side_effects.push(self.args[i]); - self.args[pos++] = make_sequence(self, side_effects); - side_effects = []; - } - last = pos; - } - if (drop_fargs) for (; i < fn.argnames.length; i++) { - if (fn.argnames[i].__unused) fn.argnames.splice(i--, 1); - } - self.args.length = last; - if (side_effects.length) { - var arg = make_sequence(self, side_effects); - self.args.push(self.args.length < fn.argnames.length ? make_node(AST_UnaryPrefix, self, { - operator: "void", - expression: arg - }) : arg); - } - } + if (compressor.option("unused")) drop_unused_call_args(self, compressor); if (compressor.option("unsafe")) { if (is_undeclared_ref(exp)) switch (exp.name) { case "Array": @@ -5786,6 +5793,8 @@ merge(Compressor.prototype, { } } } + var fn = exp instanceof AST_SymbolRef ? exp.fixed_value() : exp; + var is_func = fn instanceof AST_Lambda; var stat = is_func && fn.first_statement(); var can_inline = compressor.option("inline") && !self.is_expr_pure(compressor); if (exp === fn && can_inline && stat instanceof AST_Return) { |