@@ -630,15 +630,20 @@ merge(Compressor.prototype, {
|
|||||||
// elements. If the node has been successfully reduced to a
|
// elements. If the node has been successfully reduced to a
|
||||||
// constant, then the second element tells us the value;
|
// constant, then the second element tells us the value;
|
||||||
// otherwise the second element is missing. The first element
|
// otherwise the second element is missing. The first element
|
||||||
// of the array is always an AST_Node descendant; when
|
// of the array is always an AST_Node descendant; if
|
||||||
// evaluation was successful it's a node that represents the
|
// evaluation was successful it's a node that represents the
|
||||||
// constant; otherwise it's the original node.
|
// constant; otherwise it's the original or a replacement node.
|
||||||
AST_Node.DEFMETHOD("evaluate", function(compressor){
|
AST_Node.DEFMETHOD("evaluate", function(compressor){
|
||||||
if (!compressor.option("evaluate")) return [ this ];
|
if (!compressor.option("evaluate")) return [ this ];
|
||||||
try {
|
try {
|
||||||
var val = this._eval(compressor);
|
var val = this._eval(compressor);
|
||||||
var ast = val instanceof AST_Binary ? val : make_node_from_constant(compressor, val, this);
|
if (val instanceof AST_Node) {
|
||||||
return [ best_of(ast, this), val ];
|
// we didn't really reduce it to a constant, so
|
||||||
|
// the return array should contain only one
|
||||||
|
// node; but perhaps it's a better one.
|
||||||
|
return [ best_of(val, this) ];
|
||||||
|
}
|
||||||
|
return [ best_of(make_node_from_constant(compressor, val, this), this), val ];
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
if (ex !== def) throw ex;
|
if (ex !== def) throw ex;
|
||||||
return [ this ];
|
return [ this ];
|
||||||
@@ -750,10 +755,56 @@ merge(Compressor.prototype, {
|
|||||||
if (this.expression instanceof AST_Dot
|
if (this.expression instanceof AST_Dot
|
||||||
&& this.expression.expression instanceof AST_Array
|
&& this.expression.expression instanceof AST_Array
|
||||||
&& this.expression.property == "join") {
|
&& this.expression.property == "join") {
|
||||||
var x = this.expression.expression.elements.map(function(el){
|
var separator = this.args.length == 0 ? "," : ev(this.args[0], compressor);
|
||||||
return ev(el, compressor);
|
if (separator instanceof AST_Node) throw def; // not a constant
|
||||||
|
var elements = this.expression.expression.elements.map(function(el){
|
||||||
|
return el.evaluate(compressor); // doesn't throw.
|
||||||
});
|
});
|
||||||
return x.join(ev(this.args[0], compressor));
|
elements = elements.reduce(function(a, el){
|
||||||
|
if (a.length == 0 || el.length == 1) {
|
||||||
|
a.push(el);
|
||||||
|
} else {
|
||||||
|
var last = a[a.length - 1];
|
||||||
|
if (last.length == 2) {
|
||||||
|
// it's a constant
|
||||||
|
var val = "" + last[1] + separator + el[1];
|
||||||
|
a[a.length - 1] = [
|
||||||
|
make_node_from_constant(compressor, val, last[0]),
|
||||||
|
val
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
a.push(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}, []);
|
||||||
|
if (elements.length == 0) return "";
|
||||||
|
if (elements.length == 1) return elements[0][0];
|
||||||
|
if (separator == "") {
|
||||||
|
var first;
|
||||||
|
if (elements[0][0] instanceof AST_String
|
||||||
|
|| elements[1][0] instanceof AST_String) {
|
||||||
|
first = elements.shift()[0];
|
||||||
|
} else {
|
||||||
|
first = make_node(AST_String, this, { value: "" });
|
||||||
|
}
|
||||||
|
return elements.reduce(function(prev, el){
|
||||||
|
return make_node(AST_Binary, el[0], {
|
||||||
|
operator : "+",
|
||||||
|
left : prev,
|
||||||
|
right : el[0],
|
||||||
|
});
|
||||||
|
}, first);
|
||||||
|
}
|
||||||
|
// need this awkward cloning to not affect original element
|
||||||
|
// best_of will decide which one to get through.
|
||||||
|
var node = this.clone();
|
||||||
|
node.expression = node.expression.clone();
|
||||||
|
node.expression.expression = node.expression.expression.clone();
|
||||||
|
node.expression.expression.elements = elements.map(function(el){
|
||||||
|
return el[0];
|
||||||
|
});
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw def;
|
throw def;
|
||||||
@@ -1918,11 +1969,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var exp = self.evaluate(compressor);
|
|
||||||
if (exp.length > 1) {
|
|
||||||
if (best_of(exp[0], self) !== self)
|
|
||||||
return exp[0];
|
|
||||||
}
|
|
||||||
if (compressor.option("comparisons")) {
|
if (compressor.option("comparisons")) {
|
||||||
if (!(compressor.parent() instanceof AST_Binary)
|
if (!(compressor.parent() instanceof AST_Binary)
|
||||||
|| compressor.parent() instanceof AST_Assign) {
|
|| compressor.parent() instanceof AST_Assign) {
|
||||||
@@ -1942,7 +1988,7 @@ merge(Compressor.prototype, {
|
|||||||
&& self.left.operator == "+" && self.left.is_string(compressor)) {
|
&& self.left.operator == "+" && self.left.is_string(compressor)) {
|
||||||
return self.left;
|
return self.left;
|
||||||
}
|
}
|
||||||
return self;
|
return self.evaluate(compressor)[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_SymbolRef, function(self, compressor){
|
OPT(AST_SymbolRef, function(self, compressor){
|
||||||
|
|||||||
@@ -20,16 +20,55 @@ constant_join: {
|
|||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var a = [ "foo", "bar", "baz" ].join("");
|
var a = [ "foo", "bar", "baz" ].join("");
|
||||||
|
var a1 = [ "foo", "bar", "baz" ].join();
|
||||||
var b = [ "foo", 1, 2, 3, "bar" ].join("");
|
var b = [ "foo", 1, 2, 3, "bar" ].join("");
|
||||||
var c = [ boo(), "foo", 1, 2, 3, "bar", bar() ].join("");
|
var c = [ boo(), "foo", 1, 2, 3, "bar", bar() ].join("");
|
||||||
|
var c1 = [ boo(), bar(), "foo", 1, 2, 3, "bar", bar() ].join("");
|
||||||
|
var c2 = [ 1, 2, "foo", "bar", baz() ].join("");
|
||||||
var d = [ "foo", 1 + 2 + "bar", "baz" ].join("-");
|
var d = [ "foo", 1 + 2 + "bar", "baz" ].join("-");
|
||||||
var e = [].join(foo + bar);
|
var e = [].join(foo + bar);
|
||||||
|
var f = [].join("");
|
||||||
|
var g = [].join("foo");
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "foobarbaz";
|
var a = "foobarbaz";
|
||||||
|
var a1 = "foo,bar,baz";
|
||||||
var b = "foo123bar";
|
var b = "foo123bar";
|
||||||
var c = [ boo(), "foo", 1, 2, 3, "bar", bar() ].join(""); // we could still shorten this one, but oh well.
|
var c = boo() + "foo123bar" + bar();
|
||||||
|
var c1 = "" + boo() + bar() + "foo123bar" + bar();
|
||||||
|
var c2 = "12foobar" + baz();
|
||||||
var d = "foo-3bar-baz";
|
var d = "foo-3bar-baz";
|
||||||
var e = [].join(foo + bar);
|
var e = [].join(foo + bar);
|
||||||
|
var f = "";
|
||||||
|
var g = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constant_join_2: {
|
||||||
|
options = {
|
||||||
|
unsafe : true,
|
||||||
|
evaluate : true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
var a = [ "foo", "bar", boo(), "baz", "x", "y" ].join("");
|
||||||
|
var b = [ "foo", "bar", boo(), "baz", "x", "y" ].join("-");
|
||||||
|
var c = [ "foo", "bar", boo(), "baz", "x", "y" ].join("really-long-separator");
|
||||||
|
var d = [ "foo", "bar", boo(),
|
||||||
|
[ "foo", 1, 2, 3, "bar" ].join("+"),
|
||||||
|
"baz", "x", "y" ].join("-");
|
||||||
|
var e = [ "foo", "bar", boo(),
|
||||||
|
[ "foo", 1, 2, 3, "bar" ].join("+"),
|
||||||
|
"baz", "x", "y" ].join("really-long-separator");
|
||||||
|
var f = [ "str", "str" + variable, "foo", "bar", "moo" + foo ].join("");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "foobar" + boo() + "bazxy";
|
||||||
|
var b = [ "foo-bar", boo(), "baz-x-y" ].join("-");
|
||||||
|
var c = [ "foo", "bar", boo(), "baz", "x", "y" ].join("really-long-separator");
|
||||||
|
var d = [ "foo-bar", boo(), "foo+1+2+3+bar-baz-x-y" ].join("-");
|
||||||
|
var e = [ "foo", "bar", boo(),
|
||||||
|
"foo+1+2+3+bar",
|
||||||
|
"baz", "x", "y" ].join("really-long-separator");
|
||||||
|
var f = "str" + ("str" + variable) + "foobar" + ("moo" + foo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user