From 8428326ea120dece51b70d7bba63dda8eda14fd6 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sun, 29 Oct 2017 04:11:26 +0800 Subject: enhance `properties` (#2412) - trim array items only if `side_effects` - extend to non-identifier properties --- lib/compress.js | 151 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 86 insertions(+), 65 deletions(-) (limited to 'lib') diff --git a/lib/compress.js b/lib/compress.js index 4817ec5f..a1db985c 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -4537,59 +4537,72 @@ merge(Compressor.prototype, { }); OPT(AST_Sub, function(self, compressor){ + var expr = self.expression; + var prop = self.property; if (compressor.option("properties")) { - var prop = self.property; - if (prop instanceof AST_String) { - prop = prop.getValue(); - if (is_identifier_string(prop)) { + var key = prop.evaluate(compressor); + if (key !== prop) { + var property = "" + key; + if (is_identifier_string(property) + && property.length <= prop.print_to_string().length + 1) { return make_node(AST_Dot, self, { - expression : self.expression, - property : prop + expression: expr, + property: property }).optimize(compressor); } - var v = parseFloat(prop); - if (!isNaN(v) && v.toString() == prop) { - self.property = make_node(AST_Number, self.property, { - value: v - }); + if (!(prop instanceof AST_Number)) { + var value = parseFloat(property); + if (value.toString() == property) { + prop = self.property = make_node(AST_Number, prop, { + value: value + }); + } } } - if (prop instanceof AST_Number && self.expression instanceof AST_Array) { - prop = prop.getValue(); - var elements = self.expression.elements; - if (prop in elements) { - var flatten = true; - var values = []; - for (var i = elements.length; --i > prop;) { - var value = elements[i].drop_side_effect_free(compressor); - if (value) { - values.unshift(value); - if (flatten && value.has_side_effects(compressor)) flatten = false; - } - } - var retValue = elements[prop]; - retValue = retValue instanceof AST_Hole ? make_node(AST_Undefined, retValue) : retValue; - if (!flatten) values.unshift(retValue); - while (--i >= 0) { - var value = elements[i].drop_side_effect_free(compressor); - if (value) values.unshift(value); - else prop--; + } + if (is_lhs(self, compressor.parent())) return self; + if (compressor.option("properties") && key !== prop) { + var node = self.flatten_object(property); + if (node) { + expr = self.expression = node.expression; + prop = self.property = node.property; + } + } + if (compressor.option("properties") && compressor.option("side_effects") + && prop instanceof AST_Number && expr instanceof AST_Array) { + var index = prop.getValue(); + var elements = expr.elements; + if (index in elements) { + var flatten = true; + var values = []; + for (var i = elements.length; --i > index;) { + var value = elements[i].drop_side_effect_free(compressor); + if (value) { + values.unshift(value); + if (flatten && value.has_side_effects(compressor)) flatten = false; } - if (flatten) { - values.push(retValue); - return make_sequence(self, values).optimize(compressor); - } else return make_node(AST_Sub, self, { - expression: make_node(AST_Array, self.expression, { - elements: values - }), - property: make_node(AST_Number, self.property, { - value: prop - }) - }); } + var retValue = elements[index]; + retValue = retValue instanceof AST_Hole ? make_node(AST_Undefined, retValue) : retValue; + if (!flatten) values.unshift(retValue); + while (--i >= 0) { + var value = elements[i].drop_side_effect_free(compressor); + if (value) values.unshift(value); + else index--; + } + if (flatten) { + values.push(retValue); + return make_sequence(self, values).optimize(compressor); + } else return make_node(AST_Sub, self, { + expression: make_node(AST_Array, expr, { + elements: values + }), + property: make_node(AST_Number, prop, { + value: index + }) + }); } } - if (is_lhs(self, compressor.parent())) return self; var ev = self.evaluate(compressor); if (ev !== self) { ev = make_node_from_constant(ev, self).optimize(compressor); @@ -4609,6 +4622,33 @@ merge(Compressor.prototype, { return result; }); + AST_PropAccess.DEFMETHOD("flatten_object", function(key) { + var expr = this.expression; + if (expr instanceof AST_Object) { + var props = expr.properties; + for (var i = props.length; --i >= 0;) { + var prop = props[i]; + if ("" + prop.key == key) { + if (!all(props, function(prop) { + return prop instanceof AST_ObjectKeyVal; + })) break; + var value = prop.value; + if (value instanceof AST_Function && value.contains_this()) break; + return make_node(AST_Sub, this, { + expression: make_node(AST_Array, expr, { + elements: props.map(function(prop) { + return prop.value; + }) + }), + property: make_node(AST_Number, this, { + value: i + }) + }); + } + } + } + }); + OPT(AST_Dot, function(self, compressor){ var def = self.resolve_defines(compressor); if (def) { @@ -4637,28 +4677,9 @@ merge(Compressor.prototype, { } } if (is_lhs(self, compressor.parent())) return self; - if (compressor.option("properties") && self.expression instanceof AST_Object) { - var props = self.expression.properties; - for (var i = props.length; --i >= 0;) { - var prop = props[i]; - if (prop.key === self.property) { - if (!all(props, function(prop) { - return prop instanceof AST_ObjectKeyVal; - })) break; - var value = prop.value; - if (value instanceof AST_Function && value.contains_this()) break; - return make_node(AST_Sub, self, { - expression: make_node(AST_Array, self.expression, { - elements: props.map(function(prop) { - return prop.value; - }) - }), - property: make_node(AST_Number, self, { - value: i - }) - }).optimize(compressor); - } - } + if (compressor.option("properties")) { + var node = self.flatten_object(self.property); + if (node) return node.optimize(compressor); } var ev = self.evaluate(compressor); if (ev !== self) { -- cgit v1.2.3