aboutsummaryrefslogtreecommitdiff
path: root/lib/compress.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compress.js')
-rw-r--r--lib/compress.js152
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;