aboutsummaryrefslogtreecommitdiff
path: root/lib/compress.js
diff options
context:
space:
mode:
authorMihai Bazon <mihai@bazon.net>2013-09-22 13:12:34 +0300
committerMihai Bazon <mihai@bazon.net>2013-09-22 13:14:42 +0300
commit583fac0a0f4f5ae9b71a051730b4834a190f6387 (patch)
treeefb640e25e282cc9dac18052dc7c18f179121f87 /lib/compress.js
parente8158279ff08af915c634eeec4cfabda1ff4022e (diff)
downloadtracifyjs-583fac0a0f4f5ae9b71a051730b4834a190f6387.tar.gz
tracifyjs-583fac0a0f4f5ae9b71a051730b4834a190f6387.zip
More dirty handling of [ ... ].join() in unsafe mode
Close #300
Diffstat (limited to 'lib/compress.js')
-rw-r--r--lib/compress.js72
1 files changed, 59 insertions, 13 deletions
diff --git a/lib/compress.js b/lib/compress.js
index abf2001d..f71ba4ab 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -630,15 +630,20 @@ merge(Compressor.prototype, {
// elements. If the node has been successfully reduced to a
// constant, then the second element tells us the value;
// 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
- // constant; otherwise it's the original node.
+ // constant; otherwise it's the original or a replacement node.
AST_Node.DEFMETHOD("evaluate", function(compressor){
if (!compressor.option("evaluate")) return [ this ];
try {
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 ];
+ if (val instanceof AST_Node) {
+ // 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) {
if (ex !== def) throw ex;
return [ this ];
@@ -750,10 +755,56 @@ merge(Compressor.prototype, {
if (this.expression instanceof AST_Dot
&& this.expression.expression instanceof AST_Array
&& this.expression.property == "join") {
- var x = this.expression.expression.elements.map(function(el){
- return ev(el, compressor);
+ var separator = this.args.length == 0 ? "," : ev(this.args[0], 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.
+ });
+ 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 x.join(ev(this.args[0], compressor));
+ return node;
}
}
throw def;
@@ -1918,11 +1969,6 @@ merge(Compressor.prototype, {
}
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.parent() instanceof AST_Binary)
|| compressor.parent() instanceof AST_Assign) {
@@ -1942,7 +1988,7 @@ merge(Compressor.prototype, {
&& self.left.operator == "+" && self.left.is_string(compressor)) {
return self.left;
}
- return self;
+ return self.evaluate(compressor)[0];
});
OPT(AST_SymbolRef, function(self, compressor){