[class] Fix await-as-identifier cases in class static blocks

Bug: v8:11718
Change-Id: If903f5e336729fa55bec03acef40025ce20d6ce7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2898176
Reviewed-by: Marja Hölttä <marja@chromium.org>
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74614}
This commit is contained in:
Shu-yu Guo 2021-05-14 18:10:54 -07:00 committed by V8 LUCI CQ
parent 72b4ec49a2
commit 69a8284275
3 changed files with 28 additions and 10 deletions

View File

@ -181,6 +181,14 @@ inline bool BindsSuper(FunctionKind kind) {
IsClassConstructor(kind);
}
inline bool IsAwaitAsIdentifierDisallowed(FunctionKind kind) {
// 'await' is always disallowed as an identifier in module contexts. Callers
// should short-circuit the module case instead of calling this.
DCHECK(!IsModule(kind));
return IsAsyncFunction(kind) ||
kind == FunctionKind::kClassStaticInitializerFunction;
}
inline const char* FunctionKind2String(FunctionKind kind) {
switch (kind) {
case FunctionKind::kNormalFunction:

View File

@ -1060,14 +1060,14 @@ class ParserBase {
bool is_resumable() const {
return IsResumableFunction(function_state_->kind());
}
bool is_class_static_block() const {
return function_state_->kind() ==
FunctionKind::kClassStaticInitializerFunction;
}
bool is_await_allowed() const {
return is_async_function() || (flags().allow_harmony_top_level_await() &&
IsModule(function_state_->kind()));
}
bool is_await_as_identifier_disallowed() {
return flags().is_module() ||
IsAwaitAsIdentifierDisallowed(function_state_->kind());
}
const PendingCompilationErrorHandler* pending_error_handler() const {
return pending_error_handler_;
}
@ -1652,8 +1652,7 @@ ParserBase<Impl>::ParseAndClassifyIdentifier(Token::Value next) {
}
if (!Token::IsValidIdentifier(next, language_mode(), is_generator(),
flags().is_module() || is_async_function() ||
is_class_static_block())) {
is_await_as_identifier_disallowed())) {
ReportUnexpectedToken(next);
return impl()->EmptyIdentifierString();
}
@ -1677,7 +1676,8 @@ typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifier(
if (!Token::IsValidIdentifier(
next, language_mode(), IsGeneratorFunction(function_kind),
flags().is_module() || IsAsyncFunction(function_kind))) {
flags().is_module() ||
IsAwaitAsIdentifierDisallowed(function_kind))) {
ReportUnexpectedToken(next);
return impl()->EmptyIdentifierString();
}
@ -2570,9 +2570,8 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
// IdentifierReference Initializer?
DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
if (!Token::IsValidIdentifier(
name_token, language_mode(), is_generator(),
flags().is_module() || is_async_function())) {
if (!Token::IsValidIdentifier(name_token, language_mode(), is_generator(),
is_await_as_identifier_disallowed())) {
ReportUnexpectedToken(Next());
return impl()->NullLiteralProperty();
}

View File

@ -113,6 +113,11 @@
assertArrayEquals([undefined], log);
}
{
// 'await' is allowed as an identifier name in named function expressions.
class C { static { (function await() {}); } }
}
function assertDoesntParse(expr, context_start, context_end) {
assertThrows(() => {
eval(`${context_start} class C { static { ${expr} } } ${context_end}`);
@ -131,4 +136,10 @@ for (let [s, e] of [['', ''],
// 'await' is disallowed as an identifier.
assertDoesntParse('let await;', s, e);
assertDoesntParse('await;', s, e);
assertDoesntParse('function await() {}', s, e);
assertDoesntParse('class await() {}', s, e);
assertDoesntParse('try {} catch (await) {}', s, e);
assertDoesntParse('try {} catch ({await}) {}', s, e);
assertDoesntParse('var {await} = 0;', s, e);
assertDoesntParse('({await} = 0);', s, e);
}