Skip to content

Commit

Permalink
fix corner case in unused (#3716)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl committed Feb 12, 2020
1 parent 2557148 commit 83a4271
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 69 deletions.
123 changes: 66 additions & 57 deletions lib/compress.js
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand All @@ -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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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")) {
Expand All @@ -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":
Expand Down Expand Up @@ -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) {
Expand Down
52 changes: 45 additions & 7 deletions test/compress/drop-unused.js
Expand Up @@ -1191,10 +1191,10 @@ issue_2105_1: {
input: {
!function(factory) {
factory();
}( function() {
}(function() {
return function(fn) {
fn()().prop();
}( function() {
}(function() {
function bar() {
var quux = function() {
console.log("PASS");
Expand All @@ -1205,7 +1205,7 @@ issue_2105_1: {
return { prop: foo };
}
return bar;
} );
});
});
}
expect: {
Expand Down Expand Up @@ -1235,10 +1235,10 @@ issue_2105_2: {
input: {
!function(factory) {
factory();
}( function() {
}(function() {
return function(fn) {
fn()().prop();
}( function() {
}(function() {
function bar() {
var quux = function() {
console.log("PASS");
Expand All @@ -1249,7 +1249,7 @@ issue_2105_2: {
return { prop: foo };
}
return bar;
} );
});
});
}
expect: {
Expand All @@ -1258,6 +1258,44 @@ issue_2105_2: {
expect_stdout: "PASS"
}

issue_2105_3: {
options = {
inline: true,
passes: 2,
reduce_vars: true,
unused: true,
}
input: {
!function(factory) {
factory();
}(function() {
return function(fn) {
fn()().prop();
}(function() {
function bar() {
var quux = function() {
console.log("PASS");
}, foo = function() {
console.log;
quux();
};
return { prop: foo };
}
return bar;
});
});
}
expect: {
!void void {
prop: function() {
console.log;
void console.log("PASS");
}
}.prop();
}
expect_stdout: "PASS"
}

issue_2226_1: {
options = {
side_effects: true,
Expand Down Expand Up @@ -2330,7 +2368,7 @@ function_parameter_ie8: {
(function() {
(function f() {
console.log("PASS");
})(0);
})();
})();
}
expect_stdout: "PASS"
Expand Down
2 changes: 1 addition & 1 deletion test/compress/functions.js
Expand Up @@ -1276,7 +1276,7 @@ issue_2630_3: {
(function() {
(function f1(a) {
f2();
--x >= 0 && f1({});
--x >= 0 && f1();
})(a++);
function f2() {
a++;
Expand Down
8 changes: 4 additions & 4 deletions test/compress/keep_fargs.js
Expand Up @@ -728,7 +728,7 @@ issue_2630_3: {
(function() {
(function f1() {
f2();
--x >= 0 && f1({});
--x >= 0 && f1();
})(a++);
function f2() {
a++;
Expand Down Expand Up @@ -1369,7 +1369,7 @@ recursive_iife_1: {
}
expect: {
console.log(function f(a, b) {
return b || f("FAIL", "PASS");
return b || f(0, "PASS");
}());
}
expect_stdout: "PASS"
Expand All @@ -1388,7 +1388,7 @@ recursive_iife_2: {
}
expect: {
console.log(function f(a, b) {
return b || f("FAIL", "PASS");
return b || f(0, "PASS");
}(0, 0));
}
expect_stdout: "PASS"
Expand Down Expand Up @@ -1416,7 +1416,7 @@ recursive_iife_3: {
var a = 1, c = "PASS";
(function() {
(function f(b, d, e) {
a-- && f(null, 42, 0);
a-- && f(0, 42, 0);
e && (c = "FAIL");
d && d.p;
})();
Expand Down

0 comments on commit 83a4271

Please sign in to comment.