fix corner case in `evaluate` (#4800)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 18 Mar 2021 03:31:20 +0000 (03:31 +0000)
committerGitHub <noreply@github.com>
Thu, 18 Mar 2021 03:31:20 +0000 (11:31 +0800)
fixes #4799

lib/compress.js
test/compress/functions.js

index 2224e14..81298cb 100644 (file)
@@ -1429,6 +1429,7 @@ merge(Compressor.prototype, {
         }
     }
 
+    var identifier_atom = makePredicate("Infinity NaN undefined");
     function is_lhs_read_only(lhs, compressor) {
         if (lhs instanceof AST_ObjectIdentity) return true;
         if (lhs instanceof AST_PropAccess) {
@@ -1616,13 +1617,6 @@ merge(Compressor.prototype, {
             || compressor.option("unsafe") && global_names[this.name];
     });
 
-    var identifier_atom = makePredicate("Infinity NaN undefined");
-    function is_identifier_atom(node) {
-        return node instanceof AST_Infinity
-            || node instanceof AST_NaN
-            || node instanceof AST_Undefined;
-    }
-
     function declarations_only(node) {
         return all(node.definitions, function(var_def) {
             return !var_def.value;
@@ -9438,11 +9432,7 @@ merge(Compressor.prototype, {
     OPT(AST_UnaryPrefix, function(self, compressor) {
         var op = self.operator;
         var exp = self.expression;
-        if (compressor.option("evaluate")
-            && op == "delete"
-            && !(exp instanceof AST_SymbolRef
-                || exp instanceof AST_PropAccess
-                || is_identifier_atom(exp))) {
+        if (compressor.option("evaluate") && op == "delete" && !may_not_delete(exp)) {
             return make_sequence(self, [ exp, make_node(AST_True, self) ]).optimize(compressor);
         }
         if (compressor.option("sequences") && can_lift()) {
@@ -9496,10 +9486,19 @@ merge(Compressor.prototype, {
         return op == "-" && (exp instanceof AST_Number || exp instanceof AST_Infinity)
             ? self : try_evaluate(compressor, self);
 
+        function may_not_delete(node) {
+            return node instanceof AST_Infinity
+                || node instanceof AST_NaN
+                || node instanceof AST_NewTarget
+                || node instanceof AST_PropAccess
+                || node instanceof AST_SymbolRef
+                || node instanceof AST_Undefined;
+        }
+
         function can_lift() {
             switch (op) {
               case "delete":
-                return !is_identifier_atom(exp.tail_node());
+                return !may_not_delete(exp.tail_node());
               case "typeof":
                 return !is_undeclared_ref(exp.tail_node());
               default:
index 2c529f0..f0e0d50 100644 (file)
@@ -5851,6 +5851,24 @@ new_target_collapse_vars: {
     node_version: ">=6"
 }
 
+new_target_delete: {
+    options = {
+        evaluate: true,
+    }
+    input: {
+        new function() {
+            console.log(delete new.target);
+        }();
+    }
+    expect: {
+        new function() {
+            console.log(delete new.target);
+        }();
+    }
+    expect_stdout: true
+    node_version: ">=6"
+}
+
 new_target_reduce_vars: {
     options = {
         evaluate: true,