From: Alex Lam S.L Date: Sun, 29 Dec 2019 13:16:53 +0000 (+0800) Subject: fix corner case in `evaluate` (#3656) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=78c8efd851411a3605f667e78efaa342a1c65b53;p=UglifyJS.git fix corner case in `evaluate` (#3656) fixes #3655 --- diff --git a/lib/compress.js b/lib/compress.js index 9045a8dd..9c60d0ae 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -5998,6 +5998,7 @@ 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 @@ -6459,11 +6460,11 @@ merge(Compressor.prototype, { // 0 + n => n case "+": if (self.left.value == 0) { - if (self.right.is_number(compressor)) return self.right; if (self.right.is_boolean(compressor)) return make_node(AST_UnaryPrefix, self, { operator: "+", expression: self.right }).optimize(compressor); + if (self.right.is_number(compressor) && !may_be_minus_zero(self.right)) return self.right; } break; // 1 * n => n @@ -6479,8 +6480,12 @@ merge(Compressor.prototype, { if (self.right instanceof AST_Number && !self.left.is_constant()) switch (self.operator) { // n + 0 => n case "+": - if (self.right.value == 0 && (self.left.is_boolean(compressor) || self.left.is_number(compressor))) { - return self.left; + if (self.right.value == 0) { + if (self.left.is_boolean(compressor)) return make_node(AST_UnaryPrefix, self, { + operator: "+", + expression: self.left + }).optimize(compressor); + if (self.left.is_number(compressor) && !may_be_minus_zero(self.left)) return self.left; } break; // n - 0 => n @@ -6635,6 +6640,20 @@ 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) { diff --git a/test/compress/numbers.js b/test/compress/numbers.js index 07e93f60..f49996a4 100644 --- a/test/compress/numbers.js +++ b/test/compress/numbers.js @@ -1075,14 +1075,53 @@ issue_3653: { } expect: { console.log(0 - (console && 0)); - console.log(0 - (console && 0)); + console.log(0 - (console && 0) + 0); console.log(0 - (0 - (console && 0))); console.log(0 - (console && 0)); console.log(1 / (0 - (console && 0))); + console.log(0 - (console && 0) + 0); console.log(0 - (console && 0)); console.log(0 - (console && 0)); console.log(0 - (console && 0)); - console.log(0 - (console && 0)); + } + expect_stdout: [ + "0", + "0", + "0", + "0", + "Infinity", + "0", + "0", + "0", + "0", + ] +} + +issue_3655: { + options = { + evaluate: true, + } + input: { + console.log(0 + 0 * -[].length); + console.log(0 + (0 + 0 * -[].length)); + console.log(0 - (0 + 0 * -[].length)); + console.log(1 * (0 + 0 * -[].length)); + console.log(1 / (0 + 0 * -[].length)); + console.log((0 + 0 * -[].length) + 0); + console.log((0 + 0 * -[].length) - 0); + console.log((0 + 0 * -[].length) * 1); + console.log((0 + 0 * -[].length) / 1); + } + expect: { + console.log(0 + 0 * -[].length); + console.log(0 + 0 * -[].length); + console.log(0 - (0 + 0 * -[].length)); + console.log(0 + 0 * -[].length); + console.log(1 / (0 + 0 * -[].length)); + console.log(0 + 0 * -[].length); + console.log(0 + 0 * -[].length); + console.log(0 + 0 * -[].length); + console.log(0 + 0 * -[].length); } expect_stdout: [ "0",