diff options
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 152 |
1 files changed, 83 insertions, 69 deletions
diff --git a/lib/compress.js b/lib/compress.js index 03c1f590..6d8c1f8f 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -2437,9 +2437,10 @@ merge(Compressor.prototype, { || this.operator == "=" && this.right.is_number(compressor); }); def(AST_Binary, function(compressor) { - return binary[this.operator] || this.operator == "+" - && this.left.is_number(compressor) - && this.right.is_number(compressor); + if (binary[this.operator]) return true; + if (this.operator != "+") return false; + return (this.left.is_boolean(compressor) || this.left.is_number(compressor)) + && (this.right.is_boolean(compressor) || this.right.is_number(compressor)); }); var fn = makePredicate([ "charCodeAt", @@ -5777,6 +5778,7 @@ merge(Compressor.prototype, { } } if (compressor.option("evaluate")) { + var associative = true; switch (self.operator) { case "&&": var ll = fuzzy_eval(self.left); @@ -5845,9 +5847,6 @@ merge(Compressor.prototype, { }).optimize(compressor); } break; - } - var associative = true; - switch (self.operator) { case "+": // "foo" + ("bar" + x) => "foobar" + x if (self.left instanceof AST_Constant @@ -5927,13 +5926,38 @@ merge(Compressor.prototype, { }); break; } + case "-": + // a - -b => a + b + if (self.right instanceof AST_UnaryPrefix + && self.right.operator == "-" + && self.left.is_number(compressor)) { + self = make_node(AST_Binary, self, { + operator: "+", + left: self.left, + right: self.right.expression + }); + break; + } case "*": + case "/": associative = compressor.option("unsafe_math"); + // +a - b => a - b + // a - +b => a - b + if (self.operator != "+") { + if (self.left instanceof AST_UnaryPrefix && self.left.operator == "+") { + self.left = self.left.expression; + } + if (self.right instanceof AST_UnaryPrefix && self.right.operator == "+") { + self.right = self.right.expression; + } + } case "&": case "|": case "^": // a + +b => +b + a - if (self.left.is_number(compressor) + if (self.operator != "-" + && self.operator != "/" + && self.left.is_number(compressor) && self.right.is_number(compressor) && reversible() && !(self.left instanceof AST_Binary @@ -5951,77 +5975,56 @@ merge(Compressor.prototype, { self = best_of(compressor, self, reversed); } } - if (associative && self.is_number(compressor)) { - // a + (b + c) => (a + b) + c - if (self.right instanceof AST_Binary - && self.right.operator == self.operator) { - self = make_node(AST_Binary, self, { + if (!associative || !self.is_number(compressor)) break; + // a + (b + c) => (a + b) + c + if (self.right instanceof AST_Binary + && self.right.operator != "%" + && PRECEDENCE[self.right.operator] == PRECEDENCE[self.operator]) { + self = make_node(AST_Binary, self, { + operator: align(self.operator, self.right.operator), + left: make_node(AST_Binary, self.left, { operator: self.operator, + left: self.left, + right: self.right.left, + start: self.left.start, + end: self.right.left.end + }), + right: self.right.right + }); + } + // (2 * n) * 3 => 6 * n + // (n + 2) + 3 => n + 5 + if (self.right instanceof AST_Constant + && self.left instanceof AST_Binary + && self.left.operator != "%" + && PRECEDENCE[self.left.operator] == PRECEDENCE[self.operator]) { + if (self.left.left instanceof AST_Constant) { + self = make_node(AST_Binary, self, { + operator: self.left.operator, left: make_node(AST_Binary, self.left, { operator: self.operator, - left: self.left, - right: self.right.left, - start: self.left.start, - end: self.right.left.end + left: self.left.left, + right: self.right, + start: self.left.left.start, + end: self.right.end }), - right: self.right.right + right: self.left.right }); - } - // (n + 2) + 3 => 5 + n - // (2 * n) * 3 => 6 + n - if (self.right instanceof AST_Constant - && self.left instanceof AST_Binary - && self.left.operator == self.operator) { - if (self.left.left instanceof AST_Constant) { - self = make_node(AST_Binary, self, { - operator: self.operator, - left: make_node(AST_Binary, self.left, { - operator: self.operator, - left: self.left.left, - right: self.right, - start: self.left.left.start, - end: self.right.end - }), - right: self.left.right - }); - } else if (self.left.right instanceof AST_Constant) { - self = make_node(AST_Binary, self, { - operator: self.operator, - left: make_node(AST_Binary, self.left, { - operator: self.operator, - left: self.left.right, - right: self.right, - start: self.left.right.start, - end: self.right.end - }), - right: self.left.left - }); - } - } - // (a | 1) | (2 | d) => (3 | a) | b - if (self.left instanceof AST_Binary - && self.left.operator == self.operator - && self.left.right instanceof AST_Constant - && self.right instanceof AST_Binary - && self.right.operator == self.operator - && self.right.left instanceof AST_Constant) { + } else if (self.left.right instanceof AST_Constant) { self = make_node(AST_Binary, self, { - operator: self.operator, - left: make_node(AST_Binary, self.left, { - operator: self.operator, - left: make_node(AST_Binary, self.left.left, { - operator: self.operator, - left: self.left.right, - right: self.right.left, - start: self.left.right.start, - end: self.right.left.end - }), - right: self.left.left - }), - right: self.right.right + operator: self.left.operator, + left: self.left.left, + right: make_node(AST_Binary, self.left, { + operator: align(self.left.operator, self.operator), + left: self.left.right, + right: self.right, + start: self.left.right.start, + end: self.right.end + }) }); } } + break; } } if (compressor.option("unsafe")) { @@ -6086,6 +6089,17 @@ merge(Compressor.prototype, { } return self; + function align(ref, op) { + switch (ref) { + case "-": + return op == "+" ? "-" : "+"; + case "/": + return op == "*" ? "/" : "*"; + default: + return op; + } + } + function fuzzy_eval(node) { if (node.truthy) return true; if (node.falsy) return false; |