introduce spread (#4346)

fixes #4345
This commit is contained in:
Alex Lam S.L
2020-12-07 22:51:20 +00:00
committed by GitHub
parent 336336f53f
commit c587d7917d
4 changed files with 95 additions and 48 deletions

View File

@@ -84,6 +84,7 @@ function Compressor(options, false_by_default) {
reduce_vars : !false_by_default,
sequences : !false_by_default,
side_effects : !false_by_default,
spread : !false_by_default,
strings : !false_by_default,
switches : !false_by_default,
top_retain : null,
@@ -9724,27 +9725,10 @@ merge(Compressor.prototype, {
});
});
function is_integer(key) {
return /^[0-9]+$/.test(key);
}
OPT(AST_Spread, function(self, compressor) {
if (compressor.option("properties")) {
var exp = self.expression;
if (compressor.parent() instanceof AST_Object) {
if (exp instanceof AST_Object && all(exp.properties, function(node) {
return node instanceof AST_ObjectKeyVal;
})) return List.splice(exp.properties.map(function(node) {
var key = node.key;
if (!(key instanceof AST_Node) && is_integer(key)) {
node = node.clone();
node.key = make_node(AST_Number, node, {
value: +key
});
}
return node;
}));
} else if (exp instanceof AST_Array) return List.splice(exp.elements.map(function(node) {
var exp = self.expression;
if (compressor.option("spread") && exp instanceof AST_Array && !(compressor.parent() instanceof AST_Object)) {
return List.splice(exp.elements.map(function(node) {
return node instanceof AST_Hole ? make_node(AST_Undefined, node).optimize(compressor) : node;
}));
}
@@ -10014,40 +9998,69 @@ merge(Compressor.prototype, {
});
OPT(AST_Object, function(self, compressor) {
if (!compressor.option("objects") || compressor.has_directive("use strict")) return self;
for (var i = self.properties.length; --i >= 0;) {
var prop = self.properties[i];
var key = prop.key;
if (key instanceof AST_Node) key = key.evaluate(compressor);
if (is_integer(key)) break;
if (key !== prop.key) prop.key = "" + key;
}
if (!compressor.option("objects")) return self;
var changed = false;
var computed_int = false;
var has_computed = false;
var keep_duplicate = compressor.has_directive("use strict");
var keys = new Dictionary();
var values = [];
self.properties.forEach(function(prop) {
if (prop instanceof AST_ObjectKeyVal && typeof prop.key == "string") {
if (prop.value.has_side_effects(compressor)) flush();
keys.add(prop.key, prop.value);
if (!(prop instanceof AST_Spread)) return process(prop);
var exp = prop.expression;
if (exp instanceof AST_Object && all(exp.properties, function(node) {
return node instanceof AST_ObjectKeyVal;
})) {
changed = true;
has_computed = true;
exp.properties.forEach(process);
} else {
flush();
values.push(prop);
}
});
flush();
if (self.properties.length != values.length) return make_node(AST_Object, self, {
return changed ? make_node(AST_Object, self, {
properties: values
});
return self;
}) : self;
function flush() {
keys.each(function(expressions, key) {
keys.each(function(props) {
if (props.length == 1) return values.push(props[0]);
changed = true;
var tail = keep_duplicate && props.pop();
values.push(make_node(AST_ObjectKeyVal, self, {
key: key,
value: make_sequence(self, expressions)
key: props[0].key,
value: make_sequence(self, props.map(function(prop) {
return prop.value;
}))
}));
if (tail) values.push(tail);
});
keys = new Dictionary();
}
function process(prop) {
var key = prop.key;
if (key instanceof AST_Node) {
has_computed = true;
key = key.evaluate(compressor);
if (key !== prop.key) key = prop.key = "" + key;
}
if (prop instanceof AST_ObjectKeyVal && typeof key == "string") {
if (prop.value.has_side_effects(compressor)) flush();
keys.add(key, prop);
} else {
flush();
values.push(prop);
}
if (has_computed && !computed_int && typeof key == "string" && /^[0-9]+$/.test(key)) {
computed_int = true;
prop.key = make_node(AST_Number, prop, {
value: +key
});
}
}
});
OPT(AST_Return, function(self, compressor) {