aboutsummaryrefslogtreecommitdiff
path: root/lib/compress.js
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-12-07 22:51:20 +0000
committerGitHub <noreply@github.com>2020-12-08 06:51:20 +0800
commitc587d7917d445e97ed8580251547870256237b63 (patch)
tree689b1c396045071e8e94e1ef3b68a798b7437551 /lib/compress.js
parent336336f53f7f1ba161abc7834da190504afeb27b (diff)
downloadtracifyjs-c587d7917d445e97ed8580251547870256237b63.tar.gz
tracifyjs-c587d7917d445e97ed8580251547870256237b63.zip
introduce `spread` (#4346)
fixes #4345
Diffstat (limited to 'lib/compress.js')
-rw-r--r--lib/compress.js87
1 files changed, 50 insertions, 37 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 21ecc5e5..1b5b8be6 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -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) {