diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2020-01-15 04:05:58 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-15 04:05:58 +0800 |
commit | 91d87ae6633ba66706df32e8b955061c0e9d788f (patch) | |
tree | f180984236d5e40d16a5af8ed5b9c9f9aed9b30d /lib | |
parent | 5beb7e4797097d2b35d45a4fec7c08f91eef615b (diff) | |
download | tracifyjs-91d87ae6633ba66706df32e8b955061c0e9d788f.tar.gz tracifyjs-91d87ae6633ba66706df32e8b955061c0e9d788f.zip |
fix corner case in `unsafe_math` (#3683)
fixes #3682
Diffstat (limited to 'lib')
-rw-r--r-- | lib/compress.js | 81 |
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) { |