fix corner case in `unsafe_math` (#4543)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 12 Jan 2021 04:07:01 +0000 (04:07 +0000)
committerGitHub <noreply@github.com>
Tue, 12 Jan 2021 04:07:01 +0000 (12:07 +0800)
fixes #4542

lib/compress.js
test/compress/numbers.js

index 578e73c..83d20e8 100644 (file)
@@ -9390,7 +9390,8 @@ merge(Compressor.prototype, {
                         || 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.right.right.has_side_effects(compressor))
+                    && !is_modify_array(self.right.right)) {
                     self = make_node(AST_Binary, self, {
                         operator: align(self.operator, self.right.operator),
                         left: make_node(AST_Binary, self.left, {
@@ -9534,6 +9535,21 @@ merge(Compressor.prototype, {
         }
         return try_evaluate(compressor, self);
 
+        function is_modify_array(node) {
+            var found = false;
+            node.walk(new TreeWalker(function(node) {
+                if (found) return true;
+                if (node instanceof AST_Assign) {
+                    if (node.left instanceof AST_PropAccess) return found = true;
+                } else if (node instanceof AST_Unary) {
+                    if (unary_side_effects[node.operator] && node.expression instanceof AST_PropAccess) {
+                        return found = true;
+                    }
+                }
+            }));
+            return found;
+        }
+
         function align(ref, op) {
             switch (ref) {
               case "-":
index 7a9a3a7..5a7000c 100644 (file)
@@ -1386,3 +1386,75 @@ issue_4142: {
     }
     expect_stdout: "0"
 }
+
+issue_4542_1: {
+    options = {
+        evaluate: true,
+        unsafe_math: true,
+    }
+    input: {
+        console.log(function(a) {
+            return a / (1 / (a[0] = 2));
+        }([ 3 ]));
+    }
+    expect: {
+        console.log(function(a) {
+            return a / (1 / (a[0] = 2));
+        }([ 3 ]));
+    }
+    expect_stdout: "4"
+}
+
+issue_4542_2: {
+    options = {
+        evaluate: true,
+        unsafe_math: true,
+    }
+    input: {
+        console.log(function(a) {
+            return a / (1 / --a[0]);
+        }([ 3 ]));
+    }
+    expect: {
+        console.log(function(a) {
+            return a / (1 / --a[0]);
+        }([ 3 ]));
+    }
+    expect_stdout: "4"
+}
+
+issue_4542_3: {
+    options = {
+        evaluate: true,
+        unsafe_math: true,
+    }
+    input: {
+        console.log(function(a) {
+            return a / (0 / (a[0] = 0, 1));
+        }([ 1 ]));
+    }
+    expect: {
+        console.log(function(a) {
+            return a / (0 / (a[0] = 0, 1));
+        }([ 1 ]));
+    }
+    expect_stdout: "NaN"
+}
+
+issue_4542_4: {
+    options = {
+        evaluate: true,
+        unsafe_math: true,
+    }
+    input: {
+        console.log(function(a) {
+            return a / (1 / (a.length = 1));
+        }([ 2, 3 ]));
+    }
+    expect: {
+        console.log(function(a) {
+            return a / (1 / (a.length = 1));
+        }([ 2, 3 ]));
+    }
+    expect_stdout: "2"
+}