fix corner case in unused (#3716)

This commit is contained in:
Alex Lam S.L
2020-02-12 23:46:16 +00:00
committed by GitHub
parent 2557148bba
commit 83a42716c3
4 changed files with 116 additions and 69 deletions

View File

@@ -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) {