[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");