aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-01-15 04:05:58 +0800
committerGitHub <noreply@github.com>2020-01-15 04:05:58 +0800
commit91d87ae6633ba66706df32e8b955061c0e9d788f (patch)
treef180984236d5e40d16a5af8ed5b9c9f9aed9b30d /lib
parent5beb7e4797097d2b35d45a4fec7c08f91eef615b (diff)
downloadtracifyjs-91d87ae6633ba66706df32e8b955061c0e9d788f.tar.gz
tracifyjs-91d87ae6633ba66706df32e8b955061c0e9d788f.zip
fix corner case in `unsafe_math` (#3683)
fixes #3682
Diffstat (limited to 'lib')
-rw-r--r--lib/compress.js81
1 files changed, 63 insertions, 18 deletions
diff --git a/lib/compress.js b/lib/compress.js
index e645bd4e..ffa5a644 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -2485,6 +2485,60 @@ merge(Compressor.prototype, {
node.DEFMETHOD("is_truthy", func);
});
+ // is_negative_zero()
+ // return true if the node may represent -0
+ (function(def) {
+ def(AST_Node, return_true);
+ def(AST_Array, return_false);
+ function binary(op, left, right) {
+ switch (op) {
+ case "-":
+ return left.is_negative_zero()
+ && (!(right instanceof AST_Constant) || right.value == 0);
+ case "&&":
+ case "||":
+ case "*":
+ return left.is_negative_zero() || right.is_negative_zero();
+ case "/":
+ case "%":
+ return left.is_negative_zero();
+ default:
+ return false;
+ }
+ }
+ def(AST_Assign, function() {
+ var op = this.operator;
+ if (op == "=") return this.right.is_negative_zero();
+ return binary(op.slice(0, -1), this.left, this.right);
+ });
+ def(AST_Binary, function() {
+ return binary(this.operator, this.left, this.right);
+ });
+ def(AST_Constant, function() {
+ return this.value == 0 && 1 / this.value < 0;
+ });
+ def(AST_Lambda, return_false);
+ def(AST_Object, return_false);
+ def(AST_RegExp, return_false);
+ def(AST_Sequence, function() {
+ return this.tail_node().is_negative_zero();
+ });
+ def(AST_SymbolRef, function() {
+ var fixed = this.fixed_value();
+ if (!fixed) return true;
+ this.is_negative_zero = return_true;
+ var result = fixed.is_negative_zero();
+ delete this.is_negative_zero;
+ return result;
+ });
+ def(AST_UnaryPrefix, function() {
+ return this.operator == "+" && this.expression.is_negative_zero()
+ || this.operator == "-";
+ });
+ })(function(node, func) {
+ node.DEFMETHOD("is_negative_zero", func);
+ });
+
// may_throw_on_access()
// returns true if this node may be null, undefined or contain `AST_Accessor`
(function(def) {
@@ -6111,7 +6165,6 @@ merge(Compressor.prototype, {
});
var indexFns = makePredicate("indexOf lastIndexOf");
- var minus_zero_op = makePredicate("- * / %");
var commutativeOperators = makePredicate("== === != !== * & | ^");
function is_object(node) {
return node instanceof AST_Array
@@ -6533,6 +6586,7 @@ merge(Compressor.prototype, {
&& (self.operator != "+"
|| self.right.left.is_boolean(compressor)
|| self.right.left.is_number(compressor))
+ && (self.operator != "-" || !self.left.is_negative_zero())
&& (self.right.left.is_constant_expression()
|| !self.right.right.has_side_effects(compressor))) {
self = make_node(AST_Binary, self, {
@@ -6567,7 +6621,12 @@ merge(Compressor.prototype, {
self = make_binary(self, self.left.operator, lhs, self.left.right);
} else if (self.left.right instanceof AST_Constant) {
var rhs = make_binary(self.left, align(self.left.operator, self.operator), self.left.right, self.right, self.left.right.start, self.right.end);
- self = make_binary(self, self.left.operator, self.left.left, rhs);
+ if (self.left.operator != "-"
+ || !self.right.value
+ || rhs.evaluate(compressor)
+ || !self.left.left.is_negative_zero()) {
+ self = make_binary(self, self.left.operator, self.left.left, rhs);
+ }
}
}
break;
@@ -6580,7 +6639,7 @@ merge(Compressor.prototype, {
operator: "+",
expression: self.right
}).optimize(compressor);
- if (self.right.is_number(compressor) && !may_be_minus_zero(self.right)) return self.right;
+ if (self.right.is_number(compressor) && !self.right.is_negative_zero()) return self.right;
}
break;
// 1 * n => n
@@ -6601,7 +6660,7 @@ merge(Compressor.prototype, {
operator: "+",
expression: self.left
}).optimize(compressor);
- if (self.left.is_number(compressor) && !may_be_minus_zero(self.left)) return self.left;
+ if (self.left.is_number(compressor) && !self.left.is_negative_zero()) return self.left;
}
break;
// n - 0 => n
@@ -6756,20 +6815,6 @@ merge(Compressor.prototype, {
&& self.left.expression instanceof AST_Number && self.left.expression.value == 1;
}
}
-
- function may_be_minus_zero(node) {
- var ev = node.evaluate(compressor);
- if (ev instanceof AST_Node) {
- var op = ev.operator;
- if (!op) return true;
- if (ev instanceof AST_Assign) {
- if (op == "=") return may_be_minus_zero(ev.right);
- op = op.slice(0, -1);
- }
- if (minus_zero_op[op]) return true;
- if (ev instanceof AST_UnaryPrefix && op == "+") return true;
- } else if (ev == 0 && 1 / ev < 0) return true;
- }
});
function recursive_ref(compressor, def) {