enhance unused (#5064)

This commit is contained in:
Alex Lam S.L
2021-07-10 12:58:57 +01:00
committed by GitHub
parent 450aabaaa0
commit f67dd31cbb
7 changed files with 497 additions and 186 deletions

View File

@@ -6368,10 +6368,11 @@ merge(Compressor.prototype, {
var assign = props.assign.drop_side_effect_free(compressor);
if (assign) props.unshift(assign);
}
if (parent instanceof AST_Sequence && parent.tail_node() !== node) {
value = value.drop_side_effect_free(compressor);
if (!(parent instanceof AST_Sequence)
|| parent.tail_node() === node
|| value.has_side_effects(compressor)) {
props.push(value);
}
if (value) props.push(value);
switch (props.length) {
case 0:
return List.skip;
@@ -6491,18 +6492,19 @@ merge(Compressor.prototype, {
if (def.value) def.value = def.value.transform(tt);
var value = def.value;
if (def.name instanceof AST_Destructured) {
var name = trim_destructured(def.name, value, function(node) {
var trimmed = trim_destructured(def.name, value, function(node) {
if (!drop_vars) return node;
if (node.definition().id in in_use_ids) return node;
if (is_catch(node)) return node;
if (is_var && !can_drop_symbol(node)) return node;
return null;
});
if (name) {
}, true);
if (trimmed.name) {
def.name = trimmed.name;
def.value = value = trimmed.value;
flush();
} else {
value = value.drop_side_effect_free(compressor);
if (value) side_effects.push(value);
} else if (trimmed.value) {
side_effects.push(trimmed.value);
}
return;
}
@@ -6648,7 +6650,7 @@ merge(Compressor.prototype, {
if (side_effects.length > 0) {
if (tail.length == 0) {
body.push(make_node(AST_SimpleStatement, node, {
body: make_sequence(node, side_effects)
body: make_sequence(node, side_effects),
}));
} else if (value) {
side_effects.push(value);
@@ -6656,7 +6658,7 @@ merge(Compressor.prototype, {
} else {
def.value = make_node(AST_UnaryPrefix, def, {
operator: "void",
expression: make_sequence(def, side_effects)
expression: make_sequence(def, side_effects),
});
}
side_effects = [];
@@ -6708,11 +6710,16 @@ merge(Compressor.prototype, {
if (node instanceof AST_Assign) {
descend(node, tt);
if (node.left instanceof AST_Destructured) {
var lhs = trim_destructured(node.left, node.right, function(node) {
var trimmed = trim_destructured(node.left, node.right, function(node) {
return node;
});
if (!lhs) return node.right;
node.left = lhs;
}, node.write_only);
if (!trimmed.name) {
if (trimmed.value) return trimmed.value;
if (parent instanceof AST_Sequence && parent.tail_node() !== node) return List.skip;
return make_node(AST_Number, node, { value: 0 });
}
node.left = trimmed.name;
node.right = trimmed.value;
}
return node;
}
@@ -7023,111 +7030,240 @@ merge(Compressor.prototype, {
return node;
}
function trim_destructured(node, value, process) {
function trim_destructured(node, value, process, drop) {
var trimmer = new TreeTransformer(function(node) {
if (node instanceof AST_DefaultValue) {
if (compressor.option("default_values") && value && value.is_defined(compressor)) {
node = node.name;
} else {
return trim_default(trimmer, node);
var trimmed = trim_default(trimmer, node);
if (!trimmed && drop && value) value = value.drop_side_effect_free(compressor);
return trimmed;
}
}
if (node instanceof AST_DestructuredArray) {
var save = value;
if (value instanceof AST_SymbolRef) value = value.fixed_value();
var save_drop = drop;
var save_value = value;
if (value instanceof AST_SymbolRef) {
drop = false;
value = value.fixed_value();
}
var values = value instanceof AST_Array && value.elements;
var elements = [];
var elements = [], newValues = [], pos = 0;
node.elements.forEach(function(element, index) {
value = values && values[index];
if (value instanceof AST_Spread) value = values = null;
if (element instanceof AST_Hole) return;
if (value instanceof AST_Hole) {
value = null;
} else if (value instanceof AST_Spread) {
newValues.length = pos;
fill_holes(save_value, newValues);
[].push.apply(newValues, values.slice(index));
save_value.elements = newValues;
value = values = false;
}
element = element.transform(trimmer);
if (element) elements[index] = element;
if (element) elements[pos] = element;
if (value) newValues[pos] = value;
if (element || value || !drop || !values) pos++;
});
value = values && make_node(AST_Array, save_value, {
elements: values.slice(node.elements.length),
});
if (node.rest) {
if (compressor.option("rests")) {
value = values && make_node(AST_Array, save, {
elements: values.slice(node.elements.length),
});
node.rest = node.rest.transform(trimmer);
} else {
node.rest = node.rest.transform(tt);
}
var was_drop = drop;
drop = false;
node.rest = node.rest.transform(compressor.option("rests") ? trimmer : tt);
drop = was_drop;
if (node.rest) elements.length = pos;
}
value = save;
if (node.rest) {
elements.length = node.elements.length;
} else if (values && elements.length == 0) {
if (drop && value && !node.rest) value = value.drop_side_effect_free(compressor);
if (value instanceof AST_Array) {
value = value.elements;
} else if (value instanceof AST_Sequence) {
value = value.expressions;
} else if (value) {
value = [ value ];
}
if (value && value.length) {
newValues.length = pos;
[].push.apply(newValues, value);
}
value = save_value;
drop = save_drop;
if (values && value instanceof AST_Array) {
fill_holes(value, newValues);
value.elements = newValues;
}
if (!node.rest && (value instanceof AST_Array
|| value && value.is_string(compressor))) switch (elements.length) {
case 0:
if (drop) value = value.drop_side_effect_free(compressor);
return null;
case 1:
if (!drop) break;
var sym = elements[0];
if (!(sym instanceof AST_Symbol)) break;
value = make_node(AST_Sub, node, {
expression: value,
property: make_node(AST_Number, node, { value: 0 }),
});
return sym;
}
fill_holes(node, elements);
node.elements = elements;
return node;
}
if (node instanceof AST_DestructuredObject) {
var save = value;
if (value instanceof AST_SymbolRef) value = value.fixed_value();
var values;
if (value instanceof AST_Object) {
values = Object.create(null);
for (var i = 0; i < value.properties.length; i++) {
var prop = value.properties[i];
if (typeof prop.key != "string") {
values = null;
break;
}
values[prop.key] = prop.value;
}
var save_drop = drop;
var save_value = value;
if (value instanceof AST_SymbolRef) {
drop = false;
value = value.fixed_value();
}
var prop_keys, prop_map;
if (value instanceof AST_Object) {
prop_keys = [];
prop_map = Object.create(null);
value.properties.forEach(function(prop, index) {
if (prop instanceof AST_ObjectSetter) return;
if (prop instanceof AST_Spread) return prop_map = false;
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_map[key] = prop;
}
prop_keys[index] = key;
});
}
if (node.rest) {
value = false;
node.rest = node.rest.transform(compressor.option("rests") ? trimmer : tt);
}
var can_drop = Object.create(null);
var drop_keys = drop && Object.create(null);
var properties = [];
node.properties.forEach(function(prop) {
var retain;
if (prop.key instanceof AST_Node) {
prop.key = prop.key.transform(tt);
value = null;
retain = prop.key.has_side_effects(compressor);
} else {
value = values && values[prop.key];
retain = false;
node.properties.map(function(prop) {
var key = prop.key;
if (key instanceof AST_Node) {
prop.key = key = key.transform(tt);
key = key.evaluate(compressor, true);
}
if ((retain || node.rest) && is_decl(prop.value)) {
prop.value = prop.value.transform(tt);
properties.push(prop);
if (key instanceof AST_Node) {
drop_keys = false;
} else {
var newValue = prop.value.transform(trimmer);
if (!newValue && node.rest) {
if (prop.value instanceof AST_DestructuredArray) {
newValue = make_node(AST_DestructuredArray, prop.value, { elements: [] });
} else {
newValue = make_node(AST_DestructuredObject, prop.value, { properties: [] });
can_drop[key] = !(key in can_drop);
}
return key;
}).forEach(function(key, index) {
var prop = node.properties[index], trimmed;
if (key instanceof AST_Node) {
drop = false;
value = false;
trimmed = prop.value.transform(trimmer) || retain_lhs(prop.value);
} else {
drop = drop_keys && can_drop[key];
var mapped = prop_map && prop_map[key];
if (mapped) {
value = mapped.value;
if (value instanceof AST_Accessor) value = false;
} else {
value = false;
}
trimmed = prop.value.transform(trimmer);
if (!trimmed) {
if (node.rest || prop.key instanceof AST_Node) trimmed = retain_lhs(prop.value);
if (drop_keys && !(key in drop_keys)) {
if (mapped) {
drop_keys[key] = mapped;
if (value === null) prop_map[key] = false;
} else {
drop_keys[key] = true;
}
}
} else if (drop_keys) {
drop_keys[key] = false;
}
if (newValue) {
prop.value = newValue;
properties.push(prop);
}
if (value) mapped.value = value;
}
if (trimmed) {
prop.value = trimmed;
properties.push(prop);
}
});
if (node.rest) {
if (compressor.option("rests")) {
value = values && make_node(AST_Object, save, {
properties: [],
});
node.rest = node.rest.transform(trimmer);
} else {
node.rest = node.rest.transform(tt);
value = save_value;
drop = save_drop;
if (drop_keys && prop_keys) value.properties = value.properties.filter(function(prop, index) {
if (prop instanceof AST_ObjectSetter) return false;
if (prop instanceof AST_Spread) return true;
var key = prop_keys[index];
if (key instanceof AST_Node) return true;
if (key in drop_keys) {
var mapped = drop_keys[key];
if (!mapped) return true;
if (mapped === prop) return prop_map[key];
} else if (node.rest) {
return true;
}
}
value = save;
if (properties.length == 0 && !node.rest && value && !value.may_throw_on_access(compressor)) {
var trimmed = prop.value.drop_side_effect_free(compressor);
if (!trimmed) {
if (!(prop.key instanceof AST_Node)) return false;
trimmed = make_node(AST_Number, prop, { value: 0 });
}
prop.value = trimmed;
return true;
});
if (value && !node.rest) switch (properties.length) {
case 0:
if (value.may_throw_on_access(compressor, true)) break;
if (drop) value = value.drop_side_effect_free(compressor);
return null;
case 1:
if (!drop) break;
var prop = properties[0];
if (prop.key instanceof AST_Node) break;
if (!(prop.value instanceof AST_Symbol)) break;
value = make_node(AST_Sub, node, {
expression: value,
property: make_node_from_constant(prop.key, prop),
});
return prop.value;
}
node.properties = properties;
return node;
}
return process(node);
if (node instanceof AST_Hole) {
node = null;
} else {
node = process(node);
}
if (!node && drop && value) value = value.drop_side_effect_free(compressor);
return node;
});
return node.transform(trimmer);
return {
name: node.transform(trimmer),
value: value,
};
function retain_lhs(node) {
if (node instanceof AST_Destructured) {
if (value === null) {
value = make_node(AST_Number, node, { value: 0 });
} else if (value) {
if (value.may_throw_on_access(compressor, true)) value = make_sequence(node, [
value,
make_node(AST_Number, node, { value: 0 }),
]);
} else if (node instanceof AST_DestructuredArray) {
return make_node(AST_DestructuredArray, node, { elements: [] });
}
return make_node(AST_DestructuredObject, node, { properties: [] });
}
if (node instanceof AST_DefaultValue) node = node.name;
node.__unused = null;
return node;
}
}
});
@@ -11831,15 +11967,15 @@ merge(Compressor.prototype, {
});
function safe_to_flatten(value, compressor) {
if (value instanceof AST_SymbolRef) {
value = value.fixed_value();
}
if (!value) return false;
if (!(value instanceof AST_Lambda)) return true;
var parent = compressor.parent();
if (parent.TYPE != "Call") return true;
if (parent.expression !== compressor.self()) return true;
return !value.contains_this();
if (value instanceof AST_SymbolRef) {
value = value.fixed_value();
if (!value) return false;
}
return value instanceof AST_Lambda && !value.contains_this();
}
OPT(AST_Sub, function(self, compressor) {