fix corner cases in unused (#5449)

fixes #5448
This commit is contained in:
Alex Lam S.L
2022-05-17 10:03:06 +01:00
committed by GitHub
parent a968ddc78c
commit 27727e6926
3 changed files with 150 additions and 39 deletions

View File

@@ -6934,7 +6934,9 @@ Compressor.prototype.compress = function(node) {
} }
var argnames = node.argnames; var argnames = node.argnames;
var rest = node.rest; var rest = node.rest;
var after = false, before = false;
if (rest) { if (rest) {
before = true;
if (!args || spread < argnames.length || rest instanceof AST_SymbolFunarg) { if (!args || spread < argnames.length || rest instanceof AST_SymbolFunarg) {
rest = rest.transform(trimmer); rest = rest.transform(trimmer);
} else { } else {
@@ -6947,8 +6949,7 @@ Compressor.prototype.compress = function(node) {
args.length = argnames.length; args.length = argnames.length;
if (trimmed.value.elements.length) [].push.apply(args, trimmed.value.elements); if (trimmed.value.elements.length) [].push.apply(args, trimmed.value.elements);
} }
if (rest instanceof AST_Destructured && !rest.rest if (rest instanceof AST_Destructured && !rest.rest) {
&& (!node.uses_arguments || tt.has_directive("use strict"))) {
if (rest instanceof AST_DestructuredArray) { if (rest instanceof AST_DestructuredArray) {
if (rest.elements.length == 0) rest = null; if (rest.elements.length == 0) rest = null;
} else if (rest.properties.length == 0) { } else if (rest.properties.length == 0) {
@@ -6956,7 +6957,10 @@ Compressor.prototype.compress = function(node) {
} }
} }
node.rest = rest; node.rest = rest;
if (rest) trim = false; if (rest) {
trim = false;
after = true;
}
} }
var default_length = trim ? -1 : node.length(); var default_length = trim ? -1 : node.length();
for (var i = argnames.length; --i >= 0;) { for (var i = argnames.length; --i >= 0;) {
@@ -6973,29 +6977,43 @@ Compressor.prototype.compress = function(node) {
sym.unused = true; sym.unused = true;
} }
} else { } else {
before = true;
var funarg; var funarg;
if (!args || spread < i) { if (!args || spread < i) {
funarg = sym.transform(trimmer); funarg = sym.transform(trimmer);
} else { } else {
funarg = trim_destructured(sym, args[i], function(node) { var trimmed = trim_destructured(sym, args[i], function(node) {
return node.definition().id in in_use_ids ? node : null; return node.definition().id in in_use_ids ? node : null;
}, !node.uses_arguments, sym).name; }, !node.uses_arguments, sym);
funarg = trimmed.name;
if (trimmed.value) args[i] = trimmed.value;
} }
if (funarg) { if (funarg) {
trim = false; trim = false;
argnames[i] = funarg;
if (!after) after = !(funarg instanceof AST_SymbolFunarg);
} else if (trim) { } else if (trim) {
log_default(sym, "Dropping unused default argument {name}"); log_default(sym, "Dropping unused default argument {name}");
argnames.pop(); argnames.pop();
} else if (i > default_length) { } else if (i > default_length) {
log_default(sym, "Dropping unused default argument assignment {name}"); log_default(sym, "Dropping unused default argument assignment {name}");
if (sym.name instanceof AST_SymbolFunarg) sym.name.unused = true; if (sym.name instanceof AST_SymbolFunarg) {
sym.name.unused = true;
} else {
after = true;
}
argnames[i] = sym.name; argnames[i] = sym.name;
} else { } else {
log_default(sym, "Dropping unused default argument value {name}"); log_default(sym, "Dropping unused default argument value {name}");
argnames[i] = sym = sym.clone();
sym.value = make_node(AST_Number, sym, { value: 0 }); sym.value = make_node(AST_Number, sym, { value: 0 });
after = true;
} }
} }
} }
if (before && !after && node.uses_arguments && !tt.has_directive("use strict")) {
node.rest = make_node(AST_DestructuredArray, node, { elements: [] });
}
fns_with_marked_args.push(node); fns_with_marked_args.push(node);
} }
} }
@@ -7555,6 +7573,7 @@ Compressor.prototype.compress = function(node) {
var value = node.value.drop_side_effect_free(compressor); var value = node.value.drop_side_effect_free(compressor);
if (!value) return null; if (!value) return null;
log(node.name, "Side effects in default value of unused variable {name}"); log(node.name, "Side effects in default value of unused variable {name}");
node = node.clone();
node.name.unused = null; node.name.unused = null;
node.value = value; node.value = value;
} }
@@ -7632,6 +7651,7 @@ Compressor.prototype.compress = function(node) {
drop = save_drop; drop = save_drop;
if (values && newValues) { if (values && newValues) {
fill_holes(value, newValues); fill_holes(value, newValues);
value = value.clone();
value.elements = newValues; value.elements = newValues;
} }
if (!node.rest && (value instanceof AST_Array if (!node.rest && (value instanceof AST_Array
@@ -7665,20 +7685,25 @@ Compressor.prototype.compress = function(node) {
drop = false; drop = false;
value = value.fixed_value(); value = value.fixed_value();
} }
var prop_keys, prop_map; var prop_keys, prop_map, values;
if (value instanceof AST_Object) { if (value instanceof AST_Object) {
prop_keys = []; prop_keys = [];
prop_map = new Dictionary(); prop_map = new Dictionary();
value.properties.forEach(function(prop, index) { values = value.properties.map(function(prop, index) {
if (prop instanceof AST_Spread) return prop_map = false; prop = prop.clone();
var key = prop.key; if (prop instanceof AST_Spread) {
if (key instanceof AST_Node) key = key.evaluate(compressor, true);
if (key instanceof AST_Node) {
prop_map = false; prop_map = false;
} else if (prop_map && !(prop instanceof AST_ObjectSetter)) { } else {
prop_map.set(key, prop); var key = prop.key;
if (key instanceof AST_Node) key = key.evaluate(compressor, true);
if (key instanceof AST_Node) {
prop_map = false;
} else if (prop_map && !(prop instanceof AST_ObjectSetter)) {
prop_map.set(key, prop);
}
prop_keys[index] = key;
} }
prop_keys[index] = key; return prop;
}); });
} }
if (node.rest) { if (node.rest) {
@@ -7743,27 +7768,30 @@ Compressor.prototype.compress = function(node) {
}); });
value = save_value; value = save_value;
drop = save_drop; drop = save_drop;
if (drop_keys && prop_keys) value.properties = List(value.properties, function(prop, index) { if (drop_keys && prop_keys) {
if (prop instanceof AST_Spread) return prop; value = value.clone();
var key = prop_keys[index]; value.properties = List(values, function(prop, index) {
if (key instanceof AST_Node) return prop; if (prop instanceof AST_Spread) return prop;
if (drop_keys.has(key)) { var key = prop_keys[index];
var mapped = drop_keys.get(key); if (key instanceof AST_Node) return prop;
if (!mapped) return prop; if (drop_keys.has(key)) {
if (mapped === prop) return prop_map.get(key) || List.skip; var mapped = drop_keys.get(key);
} else if (node.rest) { if (!mapped) return prop;
return prop; if (mapped === prop) return prop_map.get(key) || List.skip;
} } else if (node.rest) {
var trimmed = prop.value.drop_side_effect_free(compressor); return prop;
if (trimmed) { }
prop.value = trimmed; var trimmed = prop.value.drop_side_effect_free(compressor);
return prop; if (trimmed) {
} prop.value = trimmed;
return retain_key(prop) ? make_node(AST_ObjectKeyVal, prop, { return prop;
key: prop.key, }
value: make_node(AST_Number, prop, { value: 0 }), return retain_key(prop) ? make_node(AST_ObjectKeyVal, prop, {
}) : List.skip; key: prop.key,
}); value: make_node(AST_Number, prop, { value: 0 }),
}) : List.skip;
});
}
if (value && !node.rest) switch (properties.length) { if (value && !node.rest) switch (properties.length) {
case 0: case 0:
if (node === root) break; if (node === root) break;

View File

@@ -2313,3 +2313,85 @@ issue_5444_3: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=6" node_version: ">=6"
} }
issue_5448_1: {
options = {
reduce_vars: true,
unused: true,
}
input: {
(function(a = typeof console.log) {
do {
var b = [ ...a ];
} while (console.log("PASS"));
})();
}
expect: {
(function(a = console.log) {
do {} while (console.log("PASS"));
})();
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5448_2: {
options = {
keep_fargs: true,
reduce_vars: true,
unused: true,
}
input: {
(function(a = typeof console) {
do {
var b = [ ...a ];
} while (console.log("PASS"));
})();
}
expect: {
(function(a = 0) {
do {} while (console.log("PASS"));
})();
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5448_3: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var [ a = typeof console ] = [ void console.log("PASS") ];
var b = [ ...a ];
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5448_4: {
options = {
evaluate: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var { p: a = typeof console } = { p: void console.log("PASS") };
var b = [ ...a ];
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -3020,6 +3020,7 @@ issue_5074_method_pure_getters: {
issue_5085_1: { issue_5085_1: {
options = { options = {
evaluate: true, evaluate: true,
passes: 2,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
unsafe: true, unsafe: true,
@@ -3032,8 +3033,7 @@ issue_5085_1: {
} }
expect: { expect: {
var a = "PASS"; var a = "PASS";
var b = [ 42 ][0]; 42;
b;
console.log(a); console.log(a);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -3043,6 +3043,7 @@ issue_5085_1: {
issue_5085_2: { issue_5085_2: {
options = { options = {
evaluate: true, evaluate: true,
passes: 2,
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
unsafe: true, unsafe: true,
@@ -3059,7 +3060,7 @@ issue_5085_2: {
expect: { expect: {
var a = "PASS"; var a = "PASS";
(function(b) { (function(b) {
b = [ 42 ][0]; 0;
})(); })();
console.log(a); console.log(a);
} }