[parser] Drop name, prototype, constructor as contextual tokens
Change-Id: I19e23a1e91631a21d55bb5a42f1f538a655478f8 Reviewed-on: https://chromium-review.googlesource.com/c/1332233 Commit-Queue: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org> Cr-Commit-Position: refs/heads/master@{#57467}
This commit is contained in:
parent
aab18a4c3e
commit
66b9fedcb4
@ -225,6 +225,7 @@ class AstBigInt {
|
||||
F(next, "next") \
|
||||
F(number, "number") \
|
||||
F(object, "object") \
|
||||
F(private_constructor, "#constructor") \
|
||||
F(proto, "__proto__") \
|
||||
F(prototype, "prototype") \
|
||||
F(return, "return") \
|
||||
|
@ -219,6 +219,7 @@
|
||||
V(_, percent_string, "percent") \
|
||||
V(_, position_string, "position") \
|
||||
V(_, preventExtensions_string, "preventExtensions") \
|
||||
V(_, private_constructor_string, "#constructor") \
|
||||
V(_, Promise_string, "Promise") \
|
||||
V(_, promise_string, "promise") \
|
||||
V(_, proto_string, "__proto__") \
|
||||
|
@ -1011,10 +1011,13 @@ class ParserBase {
|
||||
bool* is_computed_name, bool* is_private);
|
||||
ExpressionT ParseObjectLiteral();
|
||||
ClassLiteralPropertyT ParseClassPropertyDefinition(
|
||||
ClassLiteralChecker* checker, ClassInfo* class_info,
|
||||
IdentifierT* property_name, bool has_extends, bool* is_computed_name,
|
||||
ClassLiteralProperty::Kind* property_kind, bool* is_static,
|
||||
bool* is_private);
|
||||
ClassInfo* class_info, IdentifierT* property_name, bool has_extends,
|
||||
bool* is_computed_name, ClassLiteralProperty::Kind* property_kind,
|
||||
bool* is_static, bool* is_private);
|
||||
void CheckClassFieldName(IdentifierT name, bool is_static);
|
||||
void CheckClassMethodName(IdentifierT name, ParsePropertyKind type,
|
||||
ParseFunctionFlags flags, bool is_static,
|
||||
bool* has_seen_constructor);
|
||||
ExpressionT ParseMemberInitializer(ClassInfo* class_info, int beg_pos,
|
||||
bool is_static);
|
||||
ObjectLiteralPropertyT ParseObjectPropertyDefinition(bool* has_seen_proto,
|
||||
@ -1312,36 +1315,6 @@ class ParserBase {
|
||||
return factory()->NewReturnStatement(expr, pos, end_pos);
|
||||
}
|
||||
|
||||
// Validation per ES6 class literals.
|
||||
class ClassLiteralChecker {
|
||||
public:
|
||||
explicit ClassLiteralChecker(ParserBase* parser)
|
||||
: parser_(parser), has_seen_constructor_(false) {}
|
||||
|
||||
void CheckClassMethodName(Token::Value property, ParsePropertyKind type,
|
||||
ParseFunctionFlags flags, bool is_static);
|
||||
void CheckClassFieldName(bool is_static);
|
||||
|
||||
private:
|
||||
bool IsConstructor() {
|
||||
return this->scanner()->CurrentMatchesContextualEscaped(
|
||||
Token::CONSTRUCTOR);
|
||||
}
|
||||
bool IsPrivateConstructor() {
|
||||
return this->scanner()->CurrentMatchesContextualEscaped(
|
||||
Token::PRIVATE_CONSTRUCTOR);
|
||||
}
|
||||
bool IsPrototype() {
|
||||
return this->scanner()->CurrentMatchesContextualEscaped(Token::PROTOTYPE);
|
||||
}
|
||||
|
||||
ParserBase* parser() const { return parser_; }
|
||||
Scanner* scanner() const { return parser_->scanner(); }
|
||||
|
||||
ParserBase* parser_;
|
||||
bool has_seen_constructor_;
|
||||
};
|
||||
|
||||
ModuleDescriptor* module() const {
|
||||
return scope()->AsModuleScope()->module();
|
||||
}
|
||||
@ -2116,10 +2089,9 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePropertyName(
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::ClassLiteralPropertyT
|
||||
ParserBase<Impl>::ParseClassPropertyDefinition(
|
||||
ClassLiteralChecker* checker, ClassInfo* class_info, IdentifierT* name,
|
||||
bool has_extends, bool* is_computed_name,
|
||||
ClassLiteralProperty::Kind* property_kind, bool* is_static,
|
||||
bool* is_private) {
|
||||
ClassInfo* class_info, IdentifierT* name, bool has_extends,
|
||||
bool* is_computed_name, ClassLiteralProperty::Kind* property_kind,
|
||||
bool* is_static, bool* is_private) {
|
||||
DCHECK_NOT_NULL(class_info);
|
||||
ParseFunctionFlags function_flags = ParseFunctionFlag::kIsNormal;
|
||||
*is_static = false;
|
||||
@ -2190,7 +2162,7 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
|
||||
return impl()->NullLiteralProperty();
|
||||
}
|
||||
if (!*is_computed_name) {
|
||||
checker->CheckClassFieldName(*is_static);
|
||||
CheckClassFieldName(*name, *is_static);
|
||||
}
|
||||
ExpressionT initializer =
|
||||
ParseMemberInitializer(class_info, property_beg_pos, *is_static);
|
||||
@ -2216,8 +2188,8 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
|
||||
// '{' FunctionBody '}'
|
||||
|
||||
if (!*is_computed_name) {
|
||||
checker->CheckClassMethodName(name_token, ParsePropertyKind::kMethod,
|
||||
function_flags, *is_static);
|
||||
CheckClassMethodName(*name, ParsePropertyKind::kMethod, function_flags,
|
||||
*is_static, &class_info->has_seen_constructor);
|
||||
}
|
||||
|
||||
FunctionKind kind = MethodKindFor(function_flags);
|
||||
@ -2247,8 +2219,8 @@ ParserBase<Impl>::ParseClassPropertyDefinition(
|
||||
bool is_get = kind == ParsePropertyKind::kAccessorGetter;
|
||||
|
||||
if (!*is_computed_name) {
|
||||
checker->CheckClassMethodName(name_token, kind,
|
||||
ParseFunctionFlag::kIsNormal, *is_static);
|
||||
CheckClassMethodName(*name, kind, ParseFunctionFlag::kIsNormal,
|
||||
*is_static, &class_info->has_seen_constructor);
|
||||
// Make sure the name expression is a string since we need a Name for
|
||||
// Runtime_DefineAccessorPropertyUnchecked and since we can determine
|
||||
// this statically we can skip the extra runtime check.
|
||||
@ -2368,7 +2340,6 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(bool* has_seen_proto,
|
||||
DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
|
||||
|
||||
if (!*is_computed_name &&
|
||||
(name_token == Token::IDENTIFIER || name_token == Token::STRING) &&
|
||||
impl()->IdentifierEquals(name, ast_value_factory()->proto_string())) {
|
||||
if (*has_seen_proto) {
|
||||
classifier()->RecordExpressionError(scanner()->location(),
|
||||
@ -4248,8 +4219,6 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
|
||||
AccumulateFormalParameterContainmentErrors();
|
||||
}
|
||||
|
||||
ClassLiteralChecker checker(this);
|
||||
|
||||
Expect(Token::LBRACE);
|
||||
|
||||
const bool has_extends = !impl()->IsNull(class_info.extends);
|
||||
@ -4267,7 +4236,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseClassLiteral(
|
||||
// property.
|
||||
bool is_constructor = !class_info.has_seen_constructor;
|
||||
ClassLiteralPropertyT property = ParseClassPropertyDefinition(
|
||||
&checker, &class_info, &property_name, has_extends, &is_computed_name,
|
||||
&class_info, &property_name, has_extends, &is_computed_name,
|
||||
&property_kind, &is_static, &is_private);
|
||||
if (!class_info.has_static_computed_names && is_static &&
|
||||
is_computed_name) {
|
||||
@ -5847,47 +5816,50 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
void ParserBase<Impl>::ClassLiteralChecker::CheckClassMethodName(
|
||||
Token::Value property, ParsePropertyKind type, ParseFunctionFlags flags,
|
||||
bool is_static) {
|
||||
void ParserBase<Impl>::CheckClassMethodName(IdentifierT name,
|
||||
ParsePropertyKind type,
|
||||
ParseFunctionFlags flags,
|
||||
bool is_static,
|
||||
bool* has_seen_constructor) {
|
||||
DCHECK(type == ParsePropertyKind::kMethod || IsAccessor(type));
|
||||
|
||||
if (property == Token::SMI || property == Token::NUMBER) return;
|
||||
AstValueFactory* avf = ast_value_factory();
|
||||
|
||||
if (is_static) {
|
||||
if (IsPrototype()) {
|
||||
this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
|
||||
if (impl()->IdentifierEquals(name, avf->prototype_string())) {
|
||||
ReportMessage(MessageTemplate::kStaticPrototype);
|
||||
return;
|
||||
}
|
||||
} else if (IsConstructor()) {
|
||||
} else if (impl()->IdentifierEquals(name, avf->constructor_string())) {
|
||||
if (flags != ParseFunctionFlag::kIsNormal || IsAccessor(type)) {
|
||||
MessageTemplate msg = (flags & ParseFunctionFlag::kIsGenerator) != 0
|
||||
? MessageTemplate::kConstructorIsGenerator
|
||||
: (flags & ParseFunctionFlag::kIsAsync) != 0
|
||||
? MessageTemplate::kConstructorIsAsync
|
||||
: MessageTemplate::kConstructorIsAccessor;
|
||||
this->parser()->ReportMessage(msg);
|
||||
ReportMessage(msg);
|
||||
return;
|
||||
}
|
||||
if (has_seen_constructor_) {
|
||||
this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor);
|
||||
if (*has_seen_constructor) {
|
||||
ReportMessage(MessageTemplate::kDuplicateConstructor);
|
||||
return;
|
||||
}
|
||||
has_seen_constructor_ = true;
|
||||
*has_seen_constructor = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
void ParserBase<Impl>::ClassLiteralChecker::CheckClassFieldName(
|
||||
bool is_static) {
|
||||
if (is_static && IsPrototype()) {
|
||||
this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
|
||||
void ParserBase<Impl>::CheckClassFieldName(IdentifierT name, bool is_static) {
|
||||
AstValueFactory* avf = ast_value_factory();
|
||||
if (is_static && impl()->IdentifierEquals(name, avf->prototype_string())) {
|
||||
ReportMessage(MessageTemplate::kStaticPrototype);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsConstructor() || IsPrivateConstructor()) {
|
||||
this->parser()->ReportMessage(MessageTemplate::kConstructorClassField);
|
||||
if (impl()->IdentifierEquals(name, avf->constructor_string()) ||
|
||||
impl()->IdentifierEquals(name, avf->private_constructor_string())) {
|
||||
ReportMessage(MessageTemplate::kConstructorClassField);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -37,13 +37,11 @@ PreParserIdentifier GetSymbolHelper(Scanner* scanner,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (scanner->current_contextual_token()) {
|
||||
case Token::CONSTRUCTOR:
|
||||
return PreParserIdentifier::Constructor();
|
||||
case Token::NAME:
|
||||
return PreParserIdentifier::Name();
|
||||
default:
|
||||
break;
|
||||
if (string == avf->constructor_string()) {
|
||||
return PreParserIdentifier::Constructor();
|
||||
}
|
||||
if (string == avf->name_string()) {
|
||||
return PreParserIdentifier::Name();
|
||||
}
|
||||
if (scanner->literal_contains_escapes()) {
|
||||
return PreParserIdentifier::Default();
|
||||
@ -390,7 +388,6 @@ PreParserStatement PreParser::BuildParameterInitializationBlock(
|
||||
|
||||
bool PreParser::IdentifierEquals(const PreParserIdentifier& identifier,
|
||||
const AstRawString* other) {
|
||||
DCHECK_EQ(identifier.string_ == nullptr, has_error());
|
||||
return identifier.string_ == other;
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,6 @@ static const Token::Value one_char_tokens[] = {
|
||||
KEYWORD("catch", Token::CATCH) \
|
||||
KEYWORD("class", Token::CLASS) \
|
||||
KEYWORD("const", Token::CONST) \
|
||||
KEYWORD("constructor", Token::CONSTRUCTOR) \
|
||||
KEYWORD("continue", Token::CONTINUE) \
|
||||
KEYWORD_GROUP('d') \
|
||||
KEYWORD("debugger", Token::DEBUGGER) \
|
||||
@ -196,7 +195,6 @@ static const Token::Value one_char_tokens[] = {
|
||||
KEYWORD_GROUP('m') \
|
||||
KEYWORD("meta", Token::META) \
|
||||
KEYWORD_GROUP('n') \
|
||||
KEYWORD("name", Token::NAME) \
|
||||
KEYWORD("new", Token::NEW) \
|
||||
KEYWORD("null", Token::NULL_LITERAL) \
|
||||
KEYWORD_GROUP('o') \
|
||||
@ -205,7 +203,6 @@ static const Token::Value one_char_tokens[] = {
|
||||
KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD) \
|
||||
KEYWORD("private", Token::FUTURE_STRICT_RESERVED_WORD) \
|
||||
KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD) \
|
||||
KEYWORD("prototype", Token::PROTOTYPE) \
|
||||
KEYWORD("public", Token::FUTURE_STRICT_RESERVED_WORD) \
|
||||
KEYWORD_GROUP('r') \
|
||||
KEYWORD("return", Token::RETURN) \
|
||||
@ -228,15 +225,13 @@ static const Token::Value one_char_tokens[] = {
|
||||
KEYWORD("while", Token::WHILE) \
|
||||
KEYWORD("with", Token::WITH) \
|
||||
KEYWORD_GROUP('y') \
|
||||
KEYWORD("yield", Token::YIELD) \
|
||||
KEYWORD_GROUP('#') \
|
||||
KEYWORD("#constructor", Token::PRIVATE_CONSTRUCTOR)
|
||||
KEYWORD("yield", Token::YIELD)
|
||||
|
||||
V8_INLINE Token::Value KeywordOrIdentifierToken(const uint8_t* input,
|
||||
int input_length) {
|
||||
DCHECK_GE(input_length, 1);
|
||||
const int kMinLength = 2;
|
||||
const int kMaxLength = 12;
|
||||
const int kMaxLength = 10;
|
||||
if (input_length < kMinLength || input_length > kMaxLength) {
|
||||
return Token::IDENTIFIER;
|
||||
}
|
||||
|
@ -202,11 +202,7 @@ namespace internal {
|
||||
C(TARGET, "target", 0) \
|
||||
C(META, "meta", 0) \
|
||||
C(AS, "as", 0) \
|
||||
C(FROM, "from", 0) \
|
||||
C(NAME, "name", 0) \
|
||||
C(CONSTRUCTOR, "constructor", 0) \
|
||||
C(PRIVATE_CONSTRUCTOR, "#constructor", 0) \
|
||||
C(PROTOTYPE, "prototype", 0)
|
||||
C(FROM, "from", 0)
|
||||
|
||||
class Token {
|
||||
public:
|
||||
@ -227,7 +223,7 @@ class Token {
|
||||
// Predicates
|
||||
static bool IsKeyword(Value token) { return token_type[token] == 'K'; }
|
||||
static bool IsContextualKeyword(Value token) {
|
||||
return IsInRange(token, GET, PROTOTYPE);
|
||||
return IsInRange(token, GET, FROM);
|
||||
}
|
||||
|
||||
static bool IsIdentifier(Value token, LanguageMode language_mode,
|
||||
|
@ -302,42 +302,42 @@ KNOWN_MAPS = {
|
||||
("RO_SPACE", 0x02739): (171, "Tuple2Map"),
|
||||
("RO_SPACE", 0x027d9): (173, "ArrayBoilerplateDescriptionMap"),
|
||||
("RO_SPACE", 0x02b19): (161, "InterceptorInfoMap"),
|
||||
("RO_SPACE", 0x04fa1): (153, "AccessCheckInfoMap"),
|
||||
("RO_SPACE", 0x04ff1): (154, "AccessorInfoMap"),
|
||||
("RO_SPACE", 0x05041): (155, "AccessorPairMap"),
|
||||
("RO_SPACE", 0x05091): (156, "AliasedArgumentsEntryMap"),
|
||||
("RO_SPACE", 0x050e1): (157, "AllocationMementoMap"),
|
||||
("RO_SPACE", 0x05131): (158, "AsyncGeneratorRequestMap"),
|
||||
("RO_SPACE", 0x05181): (159, "DebugInfoMap"),
|
||||
("RO_SPACE", 0x051d1): (160, "FunctionTemplateInfoMap"),
|
||||
("RO_SPACE", 0x05221): (162, "InterpreterDataMap"),
|
||||
("RO_SPACE", 0x05271): (163, "ModuleInfoEntryMap"),
|
||||
("RO_SPACE", 0x052c1): (164, "ModuleMap"),
|
||||
("RO_SPACE", 0x05311): (165, "ObjectTemplateInfoMap"),
|
||||
("RO_SPACE", 0x05361): (166, "PromiseCapabilityMap"),
|
||||
("RO_SPACE", 0x053b1): (167, "PromiseReactionMap"),
|
||||
("RO_SPACE", 0x05401): (168, "PrototypeInfoMap"),
|
||||
("RO_SPACE", 0x05451): (169, "ScriptMap"),
|
||||
("RO_SPACE", 0x054a1): (170, "StackFrameInfoMap"),
|
||||
("RO_SPACE", 0x054f1): (172, "Tuple3Map"),
|
||||
("RO_SPACE", 0x05541): (174, "WasmDebugInfoMap"),
|
||||
("RO_SPACE", 0x05591): (175, "WasmExportedFunctionDataMap"),
|
||||
("RO_SPACE", 0x055e1): (176, "CallableTaskMap"),
|
||||
("RO_SPACE", 0x05631): (177, "CallbackTaskMap"),
|
||||
("RO_SPACE", 0x05681): (178, "PromiseFulfillReactionJobTaskMap"),
|
||||
("RO_SPACE", 0x056d1): (179, "PromiseRejectReactionJobTaskMap"),
|
||||
("RO_SPACE", 0x05721): (180, "PromiseResolveThenableJobTaskMap"),
|
||||
("RO_SPACE", 0x05771): (181, "WeakFactoryCleanupJobTaskMap"),
|
||||
("RO_SPACE", 0x057c1): (182, "MicrotaskQueueMap"),
|
||||
("RO_SPACE", 0x05811): (183, "AllocationSiteWithWeakNextMap"),
|
||||
("RO_SPACE", 0x05861): (183, "AllocationSiteWithoutWeakNextMap"),
|
||||
("RO_SPACE", 0x058b1): (216, "LoadHandler1Map"),
|
||||
("RO_SPACE", 0x05901): (216, "LoadHandler2Map"),
|
||||
("RO_SPACE", 0x05951): (216, "LoadHandler3Map"),
|
||||
("RO_SPACE", 0x059a1): (224, "StoreHandler0Map"),
|
||||
("RO_SPACE", 0x059f1): (224, "StoreHandler1Map"),
|
||||
("RO_SPACE", 0x05a41): (224, "StoreHandler2Map"),
|
||||
("RO_SPACE", 0x05a91): (224, "StoreHandler3Map"),
|
||||
("RO_SPACE", 0x04fc1): (153, "AccessCheckInfoMap"),
|
||||
("RO_SPACE", 0x05011): (154, "AccessorInfoMap"),
|
||||
("RO_SPACE", 0x05061): (155, "AccessorPairMap"),
|
||||
("RO_SPACE", 0x050b1): (156, "AliasedArgumentsEntryMap"),
|
||||
("RO_SPACE", 0x05101): (157, "AllocationMementoMap"),
|
||||
("RO_SPACE", 0x05151): (158, "AsyncGeneratorRequestMap"),
|
||||
("RO_SPACE", 0x051a1): (159, "DebugInfoMap"),
|
||||
("RO_SPACE", 0x051f1): (160, "FunctionTemplateInfoMap"),
|
||||
("RO_SPACE", 0x05241): (162, "InterpreterDataMap"),
|
||||
("RO_SPACE", 0x05291): (163, "ModuleInfoEntryMap"),
|
||||
("RO_SPACE", 0x052e1): (164, "ModuleMap"),
|
||||
("RO_SPACE", 0x05331): (165, "ObjectTemplateInfoMap"),
|
||||
("RO_SPACE", 0x05381): (166, "PromiseCapabilityMap"),
|
||||
("RO_SPACE", 0x053d1): (167, "PromiseReactionMap"),
|
||||
("RO_SPACE", 0x05421): (168, "PrototypeInfoMap"),
|
||||
("RO_SPACE", 0x05471): (169, "ScriptMap"),
|
||||
("RO_SPACE", 0x054c1): (170, "StackFrameInfoMap"),
|
||||
("RO_SPACE", 0x05511): (172, "Tuple3Map"),
|
||||
("RO_SPACE", 0x05561): (174, "WasmDebugInfoMap"),
|
||||
("RO_SPACE", 0x055b1): (175, "WasmExportedFunctionDataMap"),
|
||||
("RO_SPACE", 0x05601): (176, "CallableTaskMap"),
|
||||
("RO_SPACE", 0x05651): (177, "CallbackTaskMap"),
|
||||
("RO_SPACE", 0x056a1): (178, "PromiseFulfillReactionJobTaskMap"),
|
||||
("RO_SPACE", 0x056f1): (179, "PromiseRejectReactionJobTaskMap"),
|
||||
("RO_SPACE", 0x05741): (180, "PromiseResolveThenableJobTaskMap"),
|
||||
("RO_SPACE", 0x05791): (181, "WeakFactoryCleanupJobTaskMap"),
|
||||
("RO_SPACE", 0x057e1): (182, "MicrotaskQueueMap"),
|
||||
("RO_SPACE", 0x05831): (183, "AllocationSiteWithWeakNextMap"),
|
||||
("RO_SPACE", 0x05881): (183, "AllocationSiteWithoutWeakNextMap"),
|
||||
("RO_SPACE", 0x058d1): (216, "LoadHandler1Map"),
|
||||
("RO_SPACE", 0x05921): (216, "LoadHandler2Map"),
|
||||
("RO_SPACE", 0x05971): (216, "LoadHandler3Map"),
|
||||
("RO_SPACE", 0x059c1): (224, "StoreHandler0Map"),
|
||||
("RO_SPACE", 0x05a11): (224, "StoreHandler1Map"),
|
||||
("RO_SPACE", 0x05a61): (224, "StoreHandler2Map"),
|
||||
("RO_SPACE", 0x05ab1): (224, "StoreHandler3Map"),
|
||||
("MAP_SPACE", 0x00139): (1057, "ExternalMap"),
|
||||
("MAP_SPACE", 0x00189): (1073, "JSMessageObjectMap"),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user