Concatenate strings also on the right-hand side of an expression that cannot be evaluated. Fix #126
E.g. converts: a+'Hello'+'World' to a+'HelloWorld'
This commit is contained in:
@@ -636,7 +636,8 @@ merge(Compressor.prototype, {
|
||||
AST_Node.DEFMETHOD("evaluate", function(compressor){
|
||||
if (!compressor.option("evaluate")) return [ this ];
|
||||
try {
|
||||
var val = this._eval(), ast = make_node_from_constant(compressor, val, this);
|
||||
var val = this._eval(compressor);
|
||||
var ast = val instanceof AST_Binary ? val : make_node_from_constant(compressor, val, this);
|
||||
return [ best_of(ast, this), val ];
|
||||
} catch(ex) {
|
||||
if (ex !== def) throw ex;
|
||||
@@ -653,8 +654,8 @@ merge(Compressor.prototype, {
|
||||
// places too. :-( Wish JS had multiple inheritance.
|
||||
throw def;
|
||||
});
|
||||
function ev(node) {
|
||||
return node._eval();
|
||||
function ev(node, compressor) {
|
||||
return node._eval(compressor);
|
||||
};
|
||||
def(AST_Node, function(){
|
||||
throw def; // not constant
|
||||
@@ -662,69 +663,87 @@ merge(Compressor.prototype, {
|
||||
def(AST_Constant, function(){
|
||||
return this.getValue();
|
||||
});
|
||||
def(AST_UnaryPrefix, function(){
|
||||
def(AST_UnaryPrefix, function(compressor){
|
||||
var e = this.expression;
|
||||
switch (this.operator) {
|
||||
case "!": return !ev(e);
|
||||
case "!": return !ev(e, compressor);
|
||||
case "typeof":
|
||||
// Function would be evaluated to an array and so typeof would
|
||||
// incorrectly return 'object'. Hence making is a special case.
|
||||
if (e instanceof AST_Function) return typeof function(){};
|
||||
|
||||
e = ev(e);
|
||||
e = ev(e, compressor);
|
||||
|
||||
// typeof <RegExp> returns "object" or "function" on different platforms
|
||||
// so cannot evaluate reliably
|
||||
if (e instanceof RegExp) throw def;
|
||||
|
||||
return typeof e;
|
||||
case "void": return void ev(e);
|
||||
case "~": return ~ev(e);
|
||||
case "void": return void ev(e, compressor);
|
||||
case "~": return ~ev(e, compressor);
|
||||
case "-":
|
||||
e = ev(e);
|
||||
e = ev(e, compressor);
|
||||
if (e === 0) throw def;
|
||||
return -e;
|
||||
case "+": return +ev(e);
|
||||
case "+": return +ev(e, compressor);
|
||||
}
|
||||
throw def;
|
||||
});
|
||||
def(AST_Binary, function(){
|
||||
def(AST_Binary, function(c){
|
||||
var left = this.left, right = this.right;
|
||||
switch (this.operator) {
|
||||
case "&&" : return ev(left) && ev(right);
|
||||
case "||" : return ev(left) || ev(right);
|
||||
case "|" : return ev(left) | ev(right);
|
||||
case "&" : return ev(left) & ev(right);
|
||||
case "^" : return ev(left) ^ ev(right);
|
||||
case "+" : return ev(left) + ev(right);
|
||||
case "*" : return ev(left) * ev(right);
|
||||
case "/" : return ev(left) / ev(right);
|
||||
case "%" : return ev(left) % ev(right);
|
||||
case "-" : return ev(left) - ev(right);
|
||||
case "<<" : return ev(left) << ev(right);
|
||||
case ">>" : return ev(left) >> ev(right);
|
||||
case ">>>" : return ev(left) >>> ev(right);
|
||||
case "==" : return ev(left) == ev(right);
|
||||
case "===" : return ev(left) === ev(right);
|
||||
case "!=" : return ev(left) != ev(right);
|
||||
case "!==" : return ev(left) !== ev(right);
|
||||
case "<" : return ev(left) < ev(right);
|
||||
case "<=" : return ev(left) <= ev(right);
|
||||
case ">" : return ev(left) > ev(right);
|
||||
case ">=" : return ev(left) >= ev(right);
|
||||
case "in" : return ev(left) in ev(right);
|
||||
case "instanceof" : return ev(left) instanceof ev(right);
|
||||
case "&&" : return ev(left, c) && ev(right, c);
|
||||
case "||" : return ev(left, c) || ev(right, c);
|
||||
case "|" : return ev(left, c) | ev(right, c);
|
||||
case "&" : return ev(left, c) & ev(right, c);
|
||||
case "^" : return ev(left, c) ^ ev(right, c);
|
||||
case "+" :
|
||||
// handle concatenating strings even if the left part cannot
|
||||
// be evaluated, e.g. (variable + "str") + "str"
|
||||
if (!(c instanceof Compressor)) {
|
||||
throw new Error("Compressor must be passed!!");
|
||||
}
|
||||
if (left instanceof AST_Binary && left.operator == "+" && left.is_string(c)) {
|
||||
return make_node(AST_Binary, this, {
|
||||
operator: "+",
|
||||
left: left.left,
|
||||
right: make_node(AST_String, null, {
|
||||
value : "" + ev(left.right, c) + ev(right, c),
|
||||
start : left.right.start,
|
||||
end : right.end
|
||||
})
|
||||
});
|
||||
} else {
|
||||
return ev(left, c) + ev(right, c);
|
||||
}
|
||||
case "*" : return ev(left, c) * ev(right, c);
|
||||
case "/" : return ev(left, c) / ev(right, c);
|
||||
case "%" : return ev(left, c) % ev(right, c);
|
||||
case "-" : return ev(left, c) - ev(right, c);
|
||||
case "<<" : return ev(left, c) << ev(right, c);
|
||||
case ">>" : return ev(left, c) >> ev(right, c);
|
||||
case ">>>" : return ev(left, c) >>> ev(right, c);
|
||||
case "==" : return ev(left, c) == ev(right, c);
|
||||
case "===" : return ev(left, c) === ev(right, c);
|
||||
case "!=" : return ev(left, c) != ev(right, c);
|
||||
case "!==" : return ev(left, c) !== ev(right, c);
|
||||
case "<" : return ev(left, c) < ev(right, c);
|
||||
case "<=" : return ev(left, c) <= ev(right, c);
|
||||
case ">" : return ev(left, c) > ev(right, c);
|
||||
case ">=" : return ev(left, c) >= ev(right, c);
|
||||
case "in" : return ev(left, c) in ev(right, c);
|
||||
case "instanceof" : return ev(left, c) instanceof ev(right, c);
|
||||
}
|
||||
throw def;
|
||||
});
|
||||
def(AST_Conditional, function(){
|
||||
return ev(this.condition)
|
||||
? ev(this.consequent)
|
||||
: ev(this.alternative);
|
||||
def(AST_Conditional, function(compressor){
|
||||
return ev(this.condition, compressor)
|
||||
? ev(this.consequent, compressor)
|
||||
: ev(this.alternative, compressor);
|
||||
});
|
||||
def(AST_SymbolRef, function(){
|
||||
def(AST_SymbolRef, function(compressor){
|
||||
var d = this.definition();
|
||||
if (d && d.constant && d.init) return ev(d.init);
|
||||
if (d && d.constant && d.init) return ev(d.init, compressor);
|
||||
throw def;
|
||||
});
|
||||
})(function(node, func){
|
||||
|
||||
Reference in New Issue
Block a user