augment evaluate to extract within objects (#1425)
- gated by `unsafe` - replaces previous optimisation specific to String.length - "123"[0] => 1 - [1, 2, 3][0] => 1 - [1, 2, 3].length => 3 - does not apply to objects with overridden prototype functions
This commit is contained in:
committed by
Richard van Velzen
parent
48284844a4
commit
0d7d4918eb
@@ -152,6 +152,12 @@ merge(Compressor.prototype, {
|
||||
|
||||
AST_Node.DEFMETHOD("clear_opt_flags", function(){
|
||||
this.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var d = node.definition();
|
||||
if (d && d.init) {
|
||||
delete d.init._evaluated;
|
||||
}
|
||||
}
|
||||
if (!(node instanceof AST_Directive || node instanceof AST_Constant)) {
|
||||
node._squeezed = false;
|
||||
node._optimized = false;
|
||||
@@ -992,13 +998,20 @@ merge(Compressor.prototype, {
|
||||
// constant; otherwise it's the original or a replacement node.
|
||||
AST_Node.DEFMETHOD("evaluate", function(compressor){
|
||||
if (!compressor.option("evaluate")) return [ this ];
|
||||
var val;
|
||||
try {
|
||||
var val = this._eval(compressor);
|
||||
return [ best_of(make_node_from_constant(compressor, val, this), this), val ];
|
||||
val = this._eval(compressor);
|
||||
} catch(ex) {
|
||||
if (ex !== def) throw ex;
|
||||
return [ this ];
|
||||
}
|
||||
var node;
|
||||
try {
|
||||
node = make_node_from_constant(compressor, val, this);
|
||||
} catch(ex) {
|
||||
return [ this ];
|
||||
}
|
||||
return [ best_of(node, this), val ];
|
||||
});
|
||||
AST_Node.DEFMETHOD("is_constant", function(compressor){
|
||||
// Accomodate when compress option evaluate=false
|
||||
@@ -1047,6 +1060,32 @@ merge(Compressor.prototype, {
|
||||
def(AST_Constant, function(){
|
||||
return this.getValue();
|
||||
});
|
||||
def(AST_Array, function(compressor){
|
||||
if (compressor.option("unsafe")) {
|
||||
return this.elements.map(function(element) {
|
||||
return ev(element, compressor);
|
||||
});
|
||||
}
|
||||
throw def;
|
||||
});
|
||||
def(AST_Object, function(compressor){
|
||||
if (compressor.option("unsafe")) {
|
||||
var val = {};
|
||||
for (var i = 0, len = this.properties.length; i < len; i++) {
|
||||
var prop = this.properties[i];
|
||||
var key = prop.key;
|
||||
if (key instanceof AST_Node) {
|
||||
key = ev(key, compressor);
|
||||
}
|
||||
if (typeof Object.prototype[key] === 'function') {
|
||||
throw def;
|
||||
}
|
||||
val[key] = ev(prop.value, compressor);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
throw def;
|
||||
});
|
||||
def(AST_UnaryPrefix, function(compressor){
|
||||
var e = this.expression;
|
||||
switch (this.operator) {
|
||||
@@ -1114,6 +1153,12 @@ merge(Compressor.prototype, {
|
||||
try {
|
||||
var d = this.definition();
|
||||
if (d && (d.constant || compressor.option("reduce_vars") && !d.modified) && d.init) {
|
||||
if (compressor.option("unsafe")) {
|
||||
if (!HOP(d.init, '_evaluated')) {
|
||||
d.init._evaluated = ev(d.init, compressor);
|
||||
}
|
||||
return d.init._evaluated;
|
||||
}
|
||||
return ev(d.init, compressor);
|
||||
}
|
||||
} finally {
|
||||
@@ -1121,11 +1166,16 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
throw def;
|
||||
});
|
||||
def(AST_Dot, function(compressor){
|
||||
if (compressor.option("unsafe") && this.property == "length") {
|
||||
var str = ev(this.expression, compressor);
|
||||
if (typeof str == "string")
|
||||
return str.length;
|
||||
def(AST_PropAccess, function(compressor){
|
||||
if (compressor.option("unsafe")) {
|
||||
var key = this.property;
|
||||
if (key instanceof AST_Node) {
|
||||
key = ev(key, compressor);
|
||||
}
|
||||
var val = ev(this.expression, compressor);
|
||||
if (val && HOP(val, key)) {
|
||||
return val[key];
|
||||
}
|
||||
}
|
||||
throw def;
|
||||
});
|
||||
@@ -2890,7 +2940,7 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
}
|
||||
}
|
||||
return self;
|
||||
return self.evaluate(compressor)[0];
|
||||
});
|
||||
|
||||
OPT(AST_Dot, function(self, compressor){
|
||||
|
||||
Reference in New Issue
Block a user