fix corner case in `sequences` (#4798)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 18 Mar 2021 00:31:55 +0000 (00:31 +0000)
committerGitHub <noreply@github.com>
Thu, 18 Mar 2021 00:31:55 +0000 (08:31 +0800)
lib/compress.js
test/compress/sequences.js

index c655803..2224e14 100644 (file)
@@ -9443,14 +9443,9 @@ merge(Compressor.prototype, {
             && !(exp instanceof AST_SymbolRef
                 || exp instanceof AST_PropAccess
                 || is_identifier_atom(exp))) {
-            if (exp instanceof AST_Sequence) {
-                exp = exp.expressions.slice();
-                exp.push(make_node(AST_True, self));
-                return make_sequence(self, exp).optimize(compressor);
-            }
             return make_sequence(self, [ exp, make_node(AST_True, self) ]).optimize(compressor);
         }
-        if (compressor.option("sequences") && !(op == "typeof" && is_undeclared_ref(exp.tail_node()))) {
+        if (compressor.option("sequences") && can_lift()) {
             var seq = lift_sequence_in_expression(self, compressor);
             if (seq !== self) return seq.optimize(compressor);
         }
@@ -9500,6 +9495,17 @@ merge(Compressor.prototype, {
         // avoids infinite recursion of numerals
         return op == "-" && (exp instanceof AST_Number || exp instanceof AST_Infinity)
             ? self : try_evaluate(compressor, self);
+
+        function can_lift() {
+            switch (op) {
+              case "delete":
+                return !is_identifier_atom(exp.tail_node());
+              case "typeof":
+                return !is_undeclared_ref(exp.tail_node());
+              default:
+                return true;
+            }
+        }
     });
 
     OPT(AST_Await, function(self, compressor) {
index 90de197..cc05fd7 100644 (file)
@@ -564,6 +564,34 @@ delete_seq_3: {
 }
 
 delete_seq_4: {
+    options = {
+        booleans: true,
+        evaluate: false,
+        sequences: true,
+        side_effects: true,
+    }
+    input: {
+        function f() {}
+        console.log(delete (f(), undefined));
+        console.log(delete (f(), void 0));
+        console.log(delete (f(), Infinity));
+        console.log(delete (f(), 1 / 0));
+        console.log(delete (f(), NaN));
+        console.log(delete (f(), 0 / 0));
+    }
+    expect: {
+        function f() {}
+        console.log(delete void f()),
+        console.log(delete void f()),
+        console.log((f(), delete (1 / 0))),
+        console.log((f(), delete (1 / 0))),
+        console.log(delete (f(), NaN)),
+        console.log((f(), delete(0 / 0)));
+    }
+    expect_stdout: true
+}
+
+delete_seq_4_evaluate: {
     options = {
         booleans: true,
         evaluate: true,
@@ -592,6 +620,35 @@ delete_seq_4: {
 }
 
 delete_seq_5: {
+    options = {
+        booleans: true,
+        evaluate: false,
+        keep_infinity: true,
+        sequences: true,
+        side_effects: true,
+    }
+    input: {
+        function f() {}
+        console.log(delete (f(), undefined));
+        console.log(delete (f(), void 0));
+        console.log(delete (f(), Infinity));
+        console.log(delete (f(), 1 / 0));
+        console.log(delete (f(), NaN));
+        console.log(delete (f(), 0 / 0));
+    }
+    expect: {
+        function f() {}
+        console.log(delete void f()),
+        console.log(delete void f()),
+        console.log(delete (f(), Infinity)),
+        console.log((f(), delete (1 / 0))),
+        console.log(delete (f(), NaN)),
+        console.log((f(), delete (0 / 0)));
+    }
+    expect_stdout: true
+}
+
+delete_seq_5_evaluate: {
     options = {
         booleans: true,
         evaluate: true,