[class] Throw early errors for fields with constructor and prototype name

See https://tc39.github.io/proposal-class-fields/#sec-static-semantics-early-errors

Bug: v8:5367
Change-Id: I0329d1b41c4658b733df47397fbcc2c16bad117e
Reviewed-on: https://chromium-review.googlesource.com/792946
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49672}
diff --git a/src/messages.h b/src/messages.h
index a5e5c75..cd340d0 100644
--- a/src/messages.h
+++ b/src/messages.h
@@ -298,6 +298,7 @@
   T(CircularStructure, "Converting circular structure to JSON")                \
   T(ConstructAbstractClass, "Abstract class % not directly constructable")     \
   T(ConstAssign, "Assignment to constant variable.")                           \
+  T(ConstructorClassField, "Classes may not have a field named 'constructor'") \
   T(ConstructorNonCallable,                                                    \
     "Class constructor % cannot be invoked without 'new'")                     \
   T(ConstructorNotFunction, "Constructor % requires 'new'")                    \
@@ -486,7 +487,8 @@
     "small")                                                                   \
   T(SharedArrayBufferSpeciesThis,                                              \
     "SharedArrayBuffer subclass returned this from species constructor")       \
-  T(StaticPrototype, "Classes may not have static property named prototype")   \
+  T(StaticPrototype,                                                           \
+    "Classes may not have a static property named 'prototype'")                \
   T(StrictDeleteProperty, "Cannot delete property '%' of %")                   \
   T(StrictPoisonPill,                                                          \
     "'caller', 'callee', and 'arguments' properties may not be accessed on "   \
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
index 9313d43..cea0659 100644
--- a/src/parsing/parser-base.h
+++ b/src/parsing/parser-base.h
@@ -1433,6 +1433,7 @@
     void CheckClassMethodName(Token::Value property, PropertyKind type,
                               bool is_generator, bool is_async, bool is_static,
                               bool* ok);
+    void CheckClassFieldName(bool is_static, bool* ok);
 
    private:
     bool IsConstructor() {
@@ -2316,6 +2317,10 @@
     case PropertyKind::kValueProperty:
       if (allow_harmony_public_fields()) {
         *property_kind = ClassLiteralProperty::FIELD;
+        if (!*is_computed_name) {
+          checker->CheckClassFieldName(*is_static,
+                                       CHECK_OK_CUSTOM(NullLiteralProperty));
+        }
         ExpressionT initializer = ParseClassFieldInitializer(
             class_info, *is_static, CHECK_OK_CUSTOM(NullLiteralProperty));
         ExpectSemicolon(CHECK_OK_CUSTOM(NullLiteralProperty));
@@ -6141,6 +6146,22 @@
   }
 }
 
+template <typename Impl>
+void ParserBase<Impl>::ClassLiteralChecker::CheckClassFieldName(bool is_static,
+                                                                bool* ok) {
+  if (is_static && IsPrototype()) {
+    this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
+    *ok = false;
+    return;
+  }
+
+  if (IsConstructor()) {
+    this->parser()->ReportMessage(MessageTemplate::kConstructorClassField);
+    *ok = false;
+    return;
+  }
+}
+
 #undef CHECK_OK
 #undef CHECK_OK_CUSTOM
 #undef CHECK_OK_VOID
diff --git a/test/cctest/interpreter/bytecode_expectations/AsyncGenerators.golden b/test/cctest/interpreter/bytecode_expectations/AsyncGenerators.golden
index 85fe6b6..312316c 100644
--- a/test/cctest/interpreter/bytecode_expectations/AsyncGenerators.golden
+++ b/test/cctest/interpreter/bytecode_expectations/AsyncGenerators.golden
@@ -428,7 +428,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(18),
                 B(LdaConstant), U8(16),
                 B(Star), R(19),
diff --git a/test/cctest/interpreter/bytecode_expectations/ForAwaitOf.golden b/test/cctest/interpreter/bytecode_expectations/ForAwaitOf.golden
index 8a825de..16e36dd 100644
--- a/test/cctest/interpreter/bytecode_expectations/ForAwaitOf.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ForAwaitOf.golden
@@ -143,7 +143,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(19),
                 B(LdaConstant), U8(13),
                 B(Star), R(20),
@@ -432,7 +432,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(19),
                 B(LdaConstant), U8(13),
                 B(Star), R(20),
@@ -743,7 +743,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(19),
                 B(LdaConstant), U8(13),
                 B(Star), R(20),
@@ -991,7 +991,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(16),
                 B(LdaConstant), U8(10),
                 B(Star), R(17),
diff --git a/test/cctest/interpreter/bytecode_expectations/ForOf.golden b/test/cctest/interpreter/bytecode_expectations/ForOf.golden
index d1382de..caf3e26c 100644
--- a/test/cctest/interpreter/bytecode_expectations/ForOf.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ForOf.golden
@@ -86,7 +86,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(11),
                 B(LdaConstant), U8(8),
                 B(Star), R(12),
@@ -227,7 +227,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(12),
                 B(LdaConstant), U8(8),
                 B(Star), R(13),
@@ -380,7 +380,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(11),
                 B(LdaConstant), U8(8),
                 B(Star), R(12),
@@ -523,7 +523,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(10),
                 B(LdaConstant), U8(10),
                 B(Star), R(11),
diff --git a/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden b/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden
index 25ba73f..57b2b27 100644
--- a/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ForOfLoop.golden
@@ -90,7 +90,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(13),
                 B(LdaConstant), U8(7),
                 B(Star), R(14),
@@ -268,7 +268,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(13),
                 B(LdaConstant), U8(11),
                 B(Star), R(14),
@@ -422,7 +422,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(11),
                 B(LdaConstant), U8(9),
                 B(Star), R(12),
@@ -524,7 +524,7 @@
                 B(JumpIfUndefined), U8(6),
                 B(Ldar), R(6),
                 B(JumpIfNotNull), U8(16),
-                B(LdaSmi), I8(72),
+                B(LdaSmi), I8(73),
                 B(Star), R(17),
                 B(LdaConstant), U8(4),
                 B(Star), R(18),
@@ -580,7 +580,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(16),
                 B(LdaConstant), U8(9),
                 B(Star), R(17),
@@ -754,7 +754,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(16),
                 B(LdaConstant), U8(10),
                 B(Star), R(17),
@@ -953,7 +953,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(15),
                 B(LdaConstant), U8(14),
                 B(Star), R(16),
@@ -1116,7 +1116,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(20),
                 B(LdaConstant), U8(7),
                 B(Star), R(21),
@@ -1358,7 +1358,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(20),
                 B(LdaConstant), U8(9),
                 B(Star), R(21),
diff --git a/test/cctest/interpreter/bytecode_expectations/Generators.golden b/test/cctest/interpreter/bytecode_expectations/Generators.golden
index dd34297..8068bc1 100644
--- a/test/cctest/interpreter/bytecode_expectations/Generators.golden
+++ b/test/cctest/interpreter/bytecode_expectations/Generators.golden
@@ -257,7 +257,7 @@
                 B(TestTypeOf), U8(6),
                 B(JumpIfFalse), U8(4),
                 B(Jump), U8(18),
-                B(Wide), B(LdaSmi), I16(142),
+                B(Wide), B(LdaSmi), I16(143),
                 B(Star), R(14),
                 B(LdaConstant), U8(15),
                 B(Star), R(15),
diff --git a/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden b/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden
index 66c6a1a..ec2d310 100644
--- a/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden
+++ b/test/cctest/interpreter/bytecode_expectations/StandardForLoop.golden
@@ -231,7 +231,7 @@
                 B(JumpIfUndefined), U8(6),
                 B(Ldar), R(3),
                 B(JumpIfNotNull), U8(16),
-                B(LdaSmi), I8(72),
+                B(LdaSmi), I8(73),
                 B(Star), R(4),
                 B(LdaConstant), U8(1),
                 B(Star), R(5),
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index d155745..8149592 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -4825,6 +4825,9 @@
   const char* class_body_data[] = {
     "a : 0",
     "a =",
+    "static constructor",
+    "static prototype",
+    "constructor",
     "*a = 0",
     "*a",
     "get a",
diff --git a/test/message/fail/class-field-constructor.js b/test/message/fail/class-field-constructor.js
new file mode 100644
index 0000000..baeb04e
--- /dev/null
+++ b/test/message/fail/class-field-constructor.js
@@ -0,0 +1,9 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --harmony-public-fields
+
+class X {
+  constructor = function() {};
+}
diff --git a/test/message/fail/class-field-constructor.out b/test/message/fail/class-field-constructor.out
new file mode 100644
index 0000000..51f2695
--- /dev/null
+++ b/test/message/fail/class-field-constructor.out
@@ -0,0 +1,4 @@
+*%(basename)s:8: SyntaxError: Classes may not have a field named 'constructor'
+  constructor = function() {};
+  ^^^^^^^^^^^
+SyntaxError: Classes may not have a field named 'constructor'
\ No newline at end of file
diff --git a/test/message/fail/class-field-static-constructor.js b/test/message/fail/class-field-static-constructor.js
new file mode 100644
index 0000000..b64cf62
--- /dev/null
+++ b/test/message/fail/class-field-static-constructor.js
@@ -0,0 +1,9 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --harmony-public-fields
+
+class X {
+  static constructor = function() {};
+}
diff --git a/test/message/fail/class-field-static-constructor.out b/test/message/fail/class-field-static-constructor.out
new file mode 100644
index 0000000..6831d83
--- /dev/null
+++ b/test/message/fail/class-field-static-constructor.out
@@ -0,0 +1,4 @@
+*%(basename)s:8: SyntaxError: Classes may not have a field named 'constructor'
+  static constructor = function() {};
+         ^^^^^^^^^^^
+SyntaxError: Classes may not have a field named 'constructor'
\ No newline at end of file
diff --git a/test/message/fail/class-field-static-prototype.js b/test/message/fail/class-field-static-prototype.js
new file mode 100644
index 0000000..da81204
--- /dev/null
+++ b/test/message/fail/class-field-static-prototype.js
@@ -0,0 +1,9 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --harmony-public-fields
+
+class X {
+  static prototype = function() {};
+}
diff --git a/test/message/fail/class-field-static-prototype.out b/test/message/fail/class-field-static-prototype.out
new file mode 100644
index 0000000..06d6a75
--- /dev/null
+++ b/test/message/fail/class-field-static-prototype.out
@@ -0,0 +1,4 @@
+*%(basename)s:8: SyntaxError: Classes may not have a static property named 'prototype'
+  static prototype = function() {};
+         ^^^^^^^^^
+SyntaxError: Classes may not have a static property named 'prototype'
\ No newline at end of file
diff --git a/test/webkit/class-syntax-declaration-expected.txt b/test/webkit/class-syntax-declaration-expected.txt
index a424edf..c198f26 100644
--- a/test/webkit/class-syntax-declaration-expected.txt
+++ b/test/webkit/class-syntax-declaration-expected.txt
@@ -26,9 +26,9 @@
 PASS class X { set constructor() {} } threw exception SyntaxError: Class constructor may not be an accessor.
 PASS class X { constructor() {} static constructor() { return staticMethodValue; } } did not throw exception.
 PASS class X { constructor() {} static constructor() { return staticMethodValue; } }; X.constructor() is staticMethodValue
-PASS class X { constructor() {} static prototype() {} } threw exception SyntaxError: Classes may not have static property named prototype.
-PASS class X { constructor() {} static get prototype() {} } threw exception SyntaxError: Classes may not have static property named prototype.
-PASS class X { constructor() {} static set prototype() {} } threw exception SyntaxError: Classes may not have static property named prototype.
+PASS class X { constructor() {} static prototype() {} } threw exception SyntaxError: Classes may not have a static property named 'prototype'.
+PASS class X { constructor() {} static get prototype() {} } threw exception SyntaxError: Classes may not have a static property named 'prototype'.
+PASS class X { constructor() {} static set prototype() {} } threw exception SyntaxError: Classes may not have a static property named 'prototype'.
 PASS class X { constructor() {} prototype() { return instanceMethodValue; } } did not throw exception.
 PASS class X { constructor() {} prototype() { return instanceMethodValue; } }; (new X).prototype() is instanceMethodValue
 PASS class X { constructor() {} set foo(a) {} } did not throw exception.
diff --git a/test/webkit/class-syntax-declaration.js b/test/webkit/class-syntax-declaration.js
index 775a335..bc6c31d 100644
--- a/test/webkit/class-syntax-declaration.js
+++ b/test/webkit/class-syntax-declaration.js
@@ -64,9 +64,9 @@
 shouldNotThrow("class X { constructor() {} static constructor() { return staticMethodValue; } }");
 shouldBe("class X { constructor() {} static constructor() { return staticMethodValue; } }; X.constructor()", "staticMethodValue");
 
-shouldThrow("class X { constructor() {} static prototype() {} }", "'SyntaxError: Classes may not have static property named prototype'");
-shouldThrow("class X { constructor() {} static get prototype() {} }", "'SyntaxError: Classes may not have static property named prototype'");
-shouldThrow("class X { constructor() {} static set prototype() {} }", "'SyntaxError: Classes may not have static property named prototype'");
+shouldThrow("class X { constructor() {} static prototype() {} }", '"SyntaxError: Classes may not have a static property named \'prototype\'"');
+shouldThrow("class X { constructor() {} static get prototype() {} }", '"SyntaxError: Classes may not have a static property named \'prototype\'"');
+shouldThrow("class X { constructor() {} static set prototype() {} }", '"SyntaxError: Classes may not have a static property named \'prototype\'"');
 shouldNotThrow("class X { constructor() {} prototype() { return instanceMethodValue; } }");
 shouldBe("class X { constructor() {} prototype() { return instanceMethodValue; } }; (new X).prototype()", "instanceMethodValue");
 
diff --git a/test/webkit/class-syntax-expression-expected.txt b/test/webkit/class-syntax-expression-expected.txt
index 5bcaf00..acda627 100644
--- a/test/webkit/class-syntax-expression-expected.txt
+++ b/test/webkit/class-syntax-expression-expected.txt
@@ -24,9 +24,9 @@
 PASS x = class { set constructor() {} } threw exception SyntaxError: Class constructor may not be an accessor.
 PASS x = class { constructor() {} static constructor() { return staticMethodValue; } } did not throw exception.
 PASS x = class { constructor() {} static constructor() { return staticMethodValue; } }; x.constructor() is staticMethodValue
-PASS x = class { constructor() {} static prototype() {} } threw exception SyntaxError: Classes may not have static property named prototype.
-PASS x = class { constructor() {} static get prototype() {} } threw exception SyntaxError: Classes may not have static property named prototype.
-PASS x = class { constructor() {} static set prototype() {} } threw exception SyntaxError: Classes may not have static property named prototype.
+PASS x = class { constructor() {} static prototype() {} } threw exception SyntaxError: Classes may not have a static property named 'prototype'.
+PASS x = class { constructor() {} static get prototype() {} } threw exception SyntaxError: Classes may not have a static property named 'prototype'.
+PASS x = class { constructor() {} static set prototype() {} } threw exception SyntaxError: Classes may not have a static property named 'prototype'.
 PASS x = class  { constructor() {} prototype() { return instanceMethodValue; } } did not throw exception.
 PASS x = class { constructor() {} prototype() { return instanceMethodValue; } }; (new x).prototype() is instanceMethodValue
 PASS x = class { constructor() {} set foo(a) {} } did not throw exception.
diff --git a/test/webkit/class-syntax-expression.js b/test/webkit/class-syntax-expression.js
index ab6dc0e..0cea5d7 100644
--- a/test/webkit/class-syntax-expression.js
+++ b/test/webkit/class-syntax-expression.js
@@ -62,9 +62,9 @@
 shouldNotThrow("x = class { constructor() {} static constructor() { return staticMethodValue; } }");
 shouldBe("x = class { constructor() {} static constructor() { return staticMethodValue; } }; x.constructor()", "staticMethodValue");
 
-shouldThrow("x = class { constructor() {} static prototype() {} }", "'SyntaxError: Classes may not have static property named prototype'");
-shouldThrow("x = class { constructor() {} static get prototype() {} }", "'SyntaxError: Classes may not have static property named prototype'");
-shouldThrow("x = class { constructor() {} static set prototype() {} }", "'SyntaxError: Classes may not have static property named prototype'");
+shouldThrow("x = class { constructor() {} static prototype() {} }", '"SyntaxError: Classes may not have a static property named \'prototype\'"');
+shouldThrow("x = class { constructor() {} static get prototype() {} }", '"SyntaxError: Classes may not have a static property named \'prototype\'"');
+shouldThrow("x = class { constructor() {} static set prototype() {} }", '"SyntaxError: Classes may not have a static property named \'prototype\'"');
 shouldNotThrow("x = class  { constructor() {} prototype() { return instanceMethodValue; } }");
 shouldBe("x = class { constructor() {} prototype() { return instanceMethodValue; } }; (new x).prototype()", "instanceMethodValue");