summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Libraries/LibJS/Parser.cpp')
-rw-r--r--Userland/Libraries/LibJS/Parser.cpp32
1 files changed, 28 insertions, 4 deletions
diff --git a/Userland/Libraries/LibJS/Parser.cpp b/Userland/Libraries/LibJS/Parser.cpp
index 11a2a85467..730207be93 100644
--- a/Userland/Libraries/LibJS/Parser.cpp
+++ b/Userland/Libraries/LibJS/Parser.cpp
@@ -3,6 +3,7 @@
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, David Tuin <davidot@serenityos.org>
* Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
+ * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -420,6 +421,7 @@ Associativity Parser::operator_associativity(TokenType type) const
case TokenType::Typeof:
case TokenType::Void:
case TokenType::Delete:
+ case TokenType::Await:
case TokenType::Ampersand:
case TokenType::Caret:
case TokenType::Pipe:
@@ -1042,7 +1044,8 @@ NonnullRefPtr<ClassExpression> Parser::parse_class_expression(bool expect_class_
TemporaryChange function_context_rollback(m_state.in_function_context, false);
TemporaryChange generator_function_context_rollback(m_state.in_generator_function_context, false);
TemporaryChange async_function_context_rollback(m_state.in_async_function_context, false);
- TemporaryChange in_class_field_initializer_rollback(m_state.in_class_field_initializer, true);
+ TemporaryChange class_field_initializer_rollback(m_state.in_class_field_initializer, true);
+ TemporaryChange class_static_init_block_rollback(m_state.in_class_static_init_block, true);
ScopePusher static_init_scope = ScopePusher::static_init_block_scope(*this, *static_init_block);
parse_statement_list(static_init_block);
@@ -1253,6 +1256,10 @@ Parser::PrimaryExpressionParseResult Parser::parse_primary_expression()
if (!m_state.in_generator_function_context)
goto read_as_identifier;
return { parse_yield_expression(), false };
+ case TokenType::Await:
+ if (!m_state.in_async_function_context)
+ goto read_as_identifier;
+ return { parse_await_expression() };
case TokenType::PrivateIdentifier:
VERIFY(next_token().type() == TokenType::In);
if (!is_private_identifier_valid())
@@ -1934,6 +1941,7 @@ RefPtr<BindingPattern> Parser::synthesize_binding_pattern(Expression const& expr
parser.m_state.in_continue_context = m_state.in_continue_context;
parser.m_state.string_legacy_octal_escape_sequence_in_scope = m_state.string_legacy_octal_escape_sequence_in_scope;
parser.m_state.in_class_field_initializer = m_state.in_class_field_initializer;
+ parser.m_state.in_class_static_init_block = m_state.in_class_static_init_block;
auto result = parser.parse_binding_pattern(AllowDuplicates::Yes, AllowMemberExpressions::Yes);
if (parser.has_errors())
@@ -2085,6 +2093,22 @@ NonnullRefPtr<YieldExpression> Parser::parse_yield_expression()
return create_ast_node<YieldExpression>({ m_state.current_token.filename(), rule_start.position(), position() }, move(argument), yield_from);
}
+NonnullRefPtr<AwaitExpression> Parser::parse_await_expression()
+{
+ auto rule_start = push_start();
+
+ if (m_state.in_formal_parameter_context)
+ syntax_error("'Await' expression is not allowed in formal parameters of an async function");
+
+ consume(TokenType::Await);
+
+ auto precedence = g_operator_precedence.get(TokenType::Await);
+ auto associativity = operator_associativity(TokenType::Await);
+ auto argument = parse_expression(precedence, associativity);
+
+ return create_ast_node<AwaitExpression>({ m_state.current_token.filename(), rule_start.position(), position() }, move(argument));
+}
+
NonnullRefPtr<ReturnStatement> Parser::parse_return_statement()
{
auto rule_start = push_start();
@@ -3393,14 +3417,14 @@ bool Parser::match_identifier() const
if (m_state.current_token.value() == "yield"sv)
return !m_state.strict_mode && !m_state.in_generator_function_context;
if (m_state.current_token.value() == "await"sv)
- return m_program_type != Program::Type::Module && !m_state.in_async_function_context;
+ return m_program_type != Program::Type::Module && !m_state.in_async_function_context && !m_state.in_class_static_init_block;
return true;
}
return m_state.current_token.type() == TokenType::Identifier
|| m_state.current_token.type() == TokenType::Async
|| (m_state.current_token.type() == TokenType::Let && !m_state.strict_mode)
- || (m_state.current_token.type() == TokenType::Await && m_program_type != Program::Type::Module && !m_state.in_async_function_context)
+ || (m_state.current_token.type() == TokenType::Await && m_program_type != Program::Type::Module && !m_state.in_async_function_context && !m_state.in_class_static_init_block)
|| (m_state.current_token.type() == TokenType::Yield && !m_state.in_generator_function_context && !m_state.strict_mode); // See note in Parser::parse_identifier().
}
@@ -3482,7 +3506,7 @@ Token Parser::consume_identifier()
}
if (match(TokenType::Await)) {
- if (m_program_type == Program::Type::Module || m_state.in_async_function_context)
+ if (m_program_type == Program::Type::Module || m_state.in_async_function_context || m_state.in_class_static_init_block)
syntax_error("Identifier must not be a reserved word in modules ('await')");
return consume();
}