mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
LibJS: Allow labelled functions in certain contexts
Also disallow duplicated labels.
This commit is contained in:
parent
4cc95ae39d
commit
b16c02d6b4
Notes:
sideshowbarker
2024-07-18 05:37:19 +09:00
Author: https://github.com/davidot Commit: https://github.com/SerenityOS/serenity/commit/b16c02d6b4c Pull-request: https://github.com/SerenityOS/serenity/pull/9085 Reviewed-by: https://github.com/IdanHo Reviewed-by: https://github.com/linusg ✅ Reviewed-by: https://github.com/trflynn89
2 changed files with 45 additions and 11 deletions
|
@ -298,7 +298,7 @@ NonnullRefPtr<Program> Parser::parse_program(bool starts_in_strict_mode)
|
|||
program->append(parse_declaration());
|
||||
parsing_directives = false;
|
||||
} else if (match_statement()) {
|
||||
auto statement = parse_statement();
|
||||
auto statement = parse_statement(AllowLabelledFunction::Yes);
|
||||
program->append(statement);
|
||||
if (statement_is_use_strict_directive(statement)) {
|
||||
if (parsing_directives) {
|
||||
|
@ -363,7 +363,7 @@ NonnullRefPtr<Declaration> Parser::parse_declaration()
|
|||
}
|
||||
}
|
||||
|
||||
NonnullRefPtr<Statement> Parser::parse_statement()
|
||||
NonnullRefPtr<Statement> Parser::parse_statement(AllowLabelledFunction allow_labelled_function)
|
||||
{
|
||||
auto rule_start = push_start();
|
||||
switch (m_state.current_token.type()) {
|
||||
|
@ -401,8 +401,8 @@ NonnullRefPtr<Statement> Parser::parse_statement()
|
|||
consume();
|
||||
return create_ast_node<EmptyStatement>({ m_state.current_token.filename(), rule_start.position(), position() });
|
||||
default:
|
||||
if (match(TokenType::Identifier)) {
|
||||
auto result = try_parse_labelled_statement();
|
||||
if (match_identifier_name()) {
|
||||
auto result = try_parse_labelled_statement(allow_labelled_function);
|
||||
if (!result.is_null())
|
||||
return result.release_nonnull();
|
||||
}
|
||||
|
@ -534,7 +534,7 @@ RefPtr<FunctionExpression> Parser::try_parse_arrow_function_expression(bool expe
|
|||
move(parameters), function_length, FunctionKind::Regular, is_strict, true);
|
||||
}
|
||||
|
||||
RefPtr<Statement> Parser::try_parse_labelled_statement()
|
||||
RefPtr<Statement> Parser::try_parse_labelled_statement(AllowLabelledFunction allow_function)
|
||||
{
|
||||
save_state();
|
||||
auto rule_start = push_start();
|
||||
|
@ -542,6 +542,11 @@ RefPtr<Statement> Parser::try_parse_labelled_statement()
|
|||
load_state();
|
||||
};
|
||||
|
||||
if (match(TokenType::Yield) && (m_state.strict_mode || m_state.in_generator_function_context)) {
|
||||
syntax_error("'yield' label not allowed in this context");
|
||||
return {};
|
||||
}
|
||||
|
||||
auto identifier = consume_identifier_reference().value();
|
||||
if (!match(TokenType::Colon))
|
||||
return {};
|
||||
|
@ -549,14 +554,37 @@ RefPtr<Statement> Parser::try_parse_labelled_statement()
|
|||
|
||||
if (!match_statement())
|
||||
return {};
|
||||
|
||||
if (match(TokenType::Function) && (allow_function == AllowLabelledFunction::No || m_state.strict_mode)) {
|
||||
syntax_error("Not allowed to declare a function here");
|
||||
return {};
|
||||
}
|
||||
|
||||
if (m_state.labels_in_scope.contains(identifier))
|
||||
syntax_error(String::formatted("Label '{}' has already been declared", identifier));
|
||||
m_state.labels_in_scope.set(identifier);
|
||||
auto statement = parse_statement();
|
||||
|
||||
RefPtr<Statement> labelled_statement;
|
||||
|
||||
if (match(TokenType::Function)) {
|
||||
auto function_declaration = parse_function_node<FunctionDeclaration>();
|
||||
m_state.current_scope->function_declarations.append(function_declaration);
|
||||
auto hoisting_target = m_state.current_scope->get_current_function_scope();
|
||||
hoisting_target->hoisted_function_declarations.append({ function_declaration, *m_state.current_scope });
|
||||
if (function_declaration->kind() == FunctionKind::Generator)
|
||||
syntax_error("Generator functions cannot be defined in labelled statements");
|
||||
|
||||
labelled_statement = move(function_declaration);
|
||||
} else {
|
||||
labelled_statement = parse_statement();
|
||||
}
|
||||
|
||||
m_state.labels_in_scope.remove(identifier);
|
||||
|
||||
statement->set_label(identifier);
|
||||
labelled_statement->set_label(identifier);
|
||||
state_rollback_guard.disarm();
|
||||
discard_saved_state();
|
||||
return statement;
|
||||
return labelled_statement.release_nonnull();
|
||||
}
|
||||
|
||||
RefPtr<MetaProperty> Parser::try_parse_new_target_expression()
|
||||
|
@ -1632,7 +1660,7 @@ NonnullRefPtr<BlockStatement> Parser::parse_block_statement(bool& is_strict, boo
|
|||
block->append(parse_declaration());
|
||||
parsing_directives = false;
|
||||
} else if (match_statement()) {
|
||||
auto statement = parse_statement();
|
||||
auto statement = parse_statement(AllowLabelledFunction::Yes);
|
||||
block->append(statement);
|
||||
if (statement_is_use_strict_directive(statement)) {
|
||||
if (parsing_directives) {
|
||||
|
|
|
@ -50,7 +50,13 @@ public:
|
|||
};
|
||||
|
||||
NonnullRefPtr<Declaration> parse_declaration();
|
||||
NonnullRefPtr<Statement> parse_statement();
|
||||
|
||||
enum class AllowLabelledFunction {
|
||||
No,
|
||||
Yes
|
||||
};
|
||||
|
||||
NonnullRefPtr<Statement> parse_statement(AllowLabelledFunction allow_labelled_function = AllowLabelledFunction::No);
|
||||
NonnullRefPtr<BlockStatement> parse_block_statement();
|
||||
NonnullRefPtr<BlockStatement> parse_block_statement(bool& is_strict, bool error_on_binding = false);
|
||||
NonnullRefPtr<ReturnStatement> parse_return_statement();
|
||||
|
@ -91,7 +97,7 @@ public:
|
|||
NonnullRefPtr<ExportStatement> parse_export_statement(Program& program);
|
||||
|
||||
RefPtr<FunctionExpression> try_parse_arrow_function_expression(bool expect_parens);
|
||||
RefPtr<Statement> try_parse_labelled_statement();
|
||||
RefPtr<Statement> try_parse_labelled_statement(AllowLabelledFunction allow_function);
|
||||
RefPtr<MetaProperty> try_parse_new_target_expression();
|
||||
|
||||
struct Error {
|
||||
|
|
Loading…
Reference in a new issue