diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2020-12-07 22:51:20 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-08 06:51:20 +0800 |
commit | c587d7917d445e97ed8580251547870256237b63 (patch) | |
tree | 689b1c396045071e8e94e1ef3b68a798b7437551 /lib/compress.js | |
parent | 336336f53f7f1ba161abc7834da190504afeb27b (diff) | |
download | tracifyjs-c587d7917d445e97ed8580251547870256237b63.tar.gz tracifyjs-c587d7917d445e97ed8580251547870256237b63.zip |
introduce `spread` (#4346)
fixes #4345
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 87 |
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) { |