Commit ffda54fb authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

[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: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49672}
parent 90405027
......@@ -298,6 +298,7 @@ class ErrorUtils : public AllStatic {
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 @@ class ErrorUtils : public AllStatic {
"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 " \
......
......@@ -1433,6 +1433,7 @@ class ParserBase {
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 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
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 @@ void ParserBase<Impl>::ClassLiteralChecker::CheckClassMethodName(
}
}
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
......
......@@ -428,7 +428,7 @@ bytecodes: [
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),
......
......@@ -143,7 +143,7 @@ bytecodes: [
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 @@ bytecodes: [
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 @@ bytecodes: [
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 @@ bytecodes: [
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),
......
......@@ -86,7 +86,7 @@ bytecodes: [
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 @@ bytecodes: [
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 @@ bytecodes: [
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 @@ bytecodes: [
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),
......
......@@ -90,7 +90,7 @@ bytecodes: [
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 @@ bytecodes: [
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 @@ bytecodes: [
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 @@ bytecodes: [
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 @@ bytecodes: [
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 @@ bytecodes: [
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 @@ bytecodes: [
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 @@ bytecodes: [
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 @@ bytecodes: [
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),
......
......@@ -257,7 +257,7 @@ bytecodes: [
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),
......
......@@ -231,7 +231,7 @@ bytecodes: [
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),
......
......@@ -4825,6 +4825,9 @@ TEST(ClassFieldsErrors) {
const char* class_body_data[] = {
"a : 0",
"a =",
"static constructor",
"static prototype",
"constructor",
"*a = 0",
"*a",
"get a",
......
// 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() {};
}
*%(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
// 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() {};
}
*%(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
// 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() {};
}
*%(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
......@@ -26,9 +26,9 @@ PASS class X { get constructor() {} } threw exception SyntaxError: Class constru
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.
......
......@@ -64,9 +64,9 @@ shouldThrow("class X { set constructor() {} }", "'SyntaxError: Class constructor
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");
......
......@@ -24,9 +24,9 @@ PASS x = class { get constructor() {} } threw exception SyntaxError: Class const
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.
......
......@@ -62,9 +62,9 @@ shouldThrow("x = class { set constructor() {} }", "'SyntaxError: Class construct
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");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment