aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2017-10-29 04:11:26 +0800
committerGitHub <noreply@github.com>2017-10-29 04:11:26 +0800
commit8428326ea120dece51b70d7bba63dda8eda14fd6 (patch)
tree8c634bb30a6845048dee5cc27590a4a654d7ac24 /lib
parent31f82091930b39ebb5d9358951c39ae20cf8057e (diff)
downloadtracifyjs-8428326ea120dece51b70d7bba63dda8eda14fd6.tar.gz
tracifyjs-8428326ea120dece51b70d7bba63dda8eda14fd6.zip
enhance `properties` (#2412)
- trim array items only if `side_effects` - extend to non-identifier properties
Diffstat (limited to 'lib')
-rw-r--r--lib/compress.js151
1 files changed, 86 insertions, 65 deletions
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) {