support `new.target` (#4746)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sat, 6 Mar 2021 23:11:36 +0000 (23:11 +0000)
committerGitHub <noreply@github.com>
Sat, 6 Mar 2021 23:11:36 +0000 (07:11 +0800)
fixes #4745

lib/ast.js
lib/parse.js
test/compress/classes.js
test/compress/functions.js

index e46fb2e..1a1e045 100644 (file)
@@ -1812,10 +1812,17 @@ var AST_Super = DEFNODE("Super", null, {
 var AST_This = DEFNODE("This", null, {
     $documentation: "The `this` symbol",
     _validate: function() {
-        if (this.name !== "this") throw new Error('name must be "this"');
+        if (this.TYPE == "This" && this.name !== "this") throw new Error('name must be "this"');
     },
 }, AST_ObjectIdentity);
 
+var AST_NewTarget = DEFNODE("NewTarget", null, {
+    $documentation: "The `new.target` symbol",
+    _validate: function() {
+        if (this.name !== "new.target") throw new Error('name must be "new.target": ' + this.name);
+    },
+}, AST_This);
+
 var AST_Template = DEFNODE("Template", "expressions strings tag", {
     $documentation: "A template literal, i.e. tag`str1${expr1}...strN${exprN}strN+1`",
     $propdoc: {
index 0798062..835ac21 100644 (file)
@@ -1736,6 +1736,15 @@ function parse($TEXT, options) {
     var new_ = function(allow_calls) {
         var start = S.token;
         expect_token("operator", "new");
+        if (is("punc", ".") && is_token(peek(), "name", "target")) {
+            next();
+            next();
+            return new AST_NewTarget({
+                name: "new.target",
+                start: start,
+                end: prev(),
+            })
+        }
         var newexp = expr_atom(false), args;
         if (is("punc", "(")) {
             next();
index 93819bf..a1b4f0c 100644 (file)
@@ -1225,3 +1225,22 @@ issue_4725_2: {
     expect_stdout: "PASS"
     node_version: ">=4"
 }
+
+new_target: {
+    input: {
+        console.log(typeof new class {
+            constructor() {
+                this.f = () => new.target;
+            }
+        }().f());
+    }
+    expect: {
+        console.log(typeof new class {
+            constructor() {
+                this.f = () => new.target;
+            }
+        }().f());
+    }
+    expect_stdout: "function"
+    node_version: ">=6"
+}
index 30779c1..856dbce 100644 (file)
@@ -5752,3 +5752,22 @@ issue_4725_2: {
     expect_stdout: "PASS"
     node_version: ">=4"
 }
+
+new_target: {
+    input: {
+        console.log(typeof new function() {
+            return new.target;
+        }, function() {
+            return new.target;
+        }());
+    }
+    expect: {
+        console.log(typeof new function() {
+            return new.target;
+        }(), function() {
+            return new.target;
+        }());
+    }
+    expect_stdout: "function undefined"
+    node_version: ">=6"
+}