Merge branch 'master' into harmony

This commit is contained in:
Richard van Velzen
2015-12-26 17:55:38 +01:00
16 changed files with 609 additions and 124 deletions

View File

@@ -199,7 +199,7 @@ merge(Compressor.prototype, {
};
function tighten_body(statements, compressor) {
var CHANGED;
var CHANGED, max_iter = 10;
do {
CHANGED = false;
if (compressor.option("angular")) {
@@ -218,7 +218,7 @@ merge(Compressor.prototype, {
if (compressor.option("join_vars")) {
statements = join_consecutive_vars(statements, compressor);
}
} while (CHANGED);
} while (CHANGED && max_iter-- > 0);
if (compressor.option("negate_iife")) {
negate_iifes(statements, compressor);
@@ -392,7 +392,12 @@ merge(Compressor.prototype, {
continue loop;
}
//---
if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement
// XXX: what was the intention of this case?
// if sequences is not enabled, this can lead to an endless loop (issue #866).
// however, with sequences on this helps producing slightly better output for
// the example code.
if (compressor.option("sequences")
&& ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement
&& (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) {
CHANGED = true;
ret.push(make_node(AST_Return, ret[0], {
@@ -729,6 +734,32 @@ merge(Compressor.prototype, {
return [ this ];
}
});
AST_Node.DEFMETHOD("is_constant", function(compressor){
// Accomodate when compress option evaluate=false
// as well as the common constant expressions !0 and !1
return this instanceof AST_Constant
|| (this instanceof AST_UnaryPrefix && this.operator == "!"
&& this.expression instanceof AST_Constant)
|| this.evaluate(compressor).length > 1;
});
// Obtain the constant value of an expression already known to be constant.
// Result only valid iff this.is_constant(compressor) is true.
AST_Node.DEFMETHOD("constant_value", function(compressor){
// Accomodate when option evaluate=false.
if (this instanceof AST_Constant) return this.value;
// Accomodate the common constant expressions !0 and !1 when option evaluate=false.
if (this instanceof AST_UnaryPrefix
&& this.operator == "!"
&& this.expression instanceof AST_Constant) {
return !this.expression.value;
}
var result = this.evaluate(compressor)
if (result.length > 1) {
return result[1];
}
// should never be reached
return undefined;
});
def(AST_Statement, function(){
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
});
@@ -1006,7 +1037,7 @@ merge(Compressor.prototype, {
/* -----[ optimizers ]----- */
OPT(AST_Directive, function(self, compressor){
if (self.scope.has_directive(self.value) !== self.scope) {
if (compressor.has_directive(self.value) === "up") {
return make_node(AST_EmptyStatement, self);
}
return self;
@@ -2472,32 +2503,48 @@ merge(Compressor.prototype, {
alternative: alternative
});
}
// x=y?1:1 --> x=1
if (consequent instanceof AST_Constant
&& alternative instanceof AST_Constant
// y?1:1 --> 1
if (consequent.is_constant(compressor)
&& alternative.is_constant(compressor)
&& consequent.equivalent_to(alternative)) {
var consequent_value = consequent.constant_value();
if (self.condition.has_side_effects(compressor)) {
return AST_Seq.from_array([self.condition, make_node_from_constant(compressor, consequent.value, self)]);
return AST_Seq.from_array([self.condition, make_node_from_constant(compressor, consequent_value, self)]);
} else {
return make_node_from_constant(compressor, consequent.value, self);
return make_node_from_constant(compressor, consequent_value, self);
}
}
// x=y?true:false --> x=!!y
if (consequent instanceof AST_True
&& alternative instanceof AST_False) {
// y?true:false --> !!y
if (is_true(consequent) && is_false(alternative)) {
self.condition = self.condition.negate(compressor);
return make_node(AST_UnaryPrefix, self.condition, {
operator: "!",
expression: self.condition
});
}
// x=y?false:true --> x=!y
if (consequent instanceof AST_False
&& alternative instanceof AST_True) {
// y?false:true --> !y
if (is_false(consequent) && is_true(alternative)) {
return self.condition.negate(compressor)
}
return self;
// AST_True or !0
function is_true(node) {
return node instanceof AST_True
|| (node instanceof AST_UnaryPrefix
&& node.operator == "!"
&& node.expression instanceof AST_Constant
&& !node.expression.value);
}
// AST_False or !1
function is_false(node) {
return node instanceof AST_False
|| (node instanceof AST_UnaryPrefix
&& node.operator == "!"
&& node.expression instanceof AST_Constant
&& !!node.expression.value);
}
});
OPT(AST_Boolean, function(self, compressor){
@@ -2569,4 +2616,11 @@ merge(Compressor.prototype, {
OPT(AST_Object, literals_in_boolean_context);
OPT(AST_RegExp, literals_in_boolean_context);
OPT(AST_Return, function(self, compressor){
if (self.value instanceof AST_Undefined) {
self.value = null;
}
return self;
});
})();