mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 10:58:12 +00:00
LibJS: Require initializer for 'const' variable declaration
This commit is contained in:
parent
812e3ecedd
commit
563d3c8055
3 changed files with 21 additions and 14 deletions
|
@ -1374,26 +1374,24 @@ Vector<FunctionNode::Parameter> Parser::parse_function_parameters(int& function_
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration(bool with_semicolon)
|
NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration(bool for_loop_variable_declaration)
|
||||||
{
|
{
|
||||||
DeclarationKind declaration_kind;
|
DeclarationKind declaration_kind;
|
||||||
|
|
||||||
switch (m_parser_state.m_current_token.type()) {
|
switch (m_parser_state.m_current_token.type()) {
|
||||||
case TokenType::Var:
|
case TokenType::Var:
|
||||||
declaration_kind = DeclarationKind::Var;
|
declaration_kind = DeclarationKind::Var;
|
||||||
consume(TokenType::Var);
|
|
||||||
break;
|
break;
|
||||||
case TokenType::Let:
|
case TokenType::Let:
|
||||||
declaration_kind = DeclarationKind::Let;
|
declaration_kind = DeclarationKind::Let;
|
||||||
consume(TokenType::Let);
|
|
||||||
break;
|
break;
|
||||||
case TokenType::Const:
|
case TokenType::Const:
|
||||||
declaration_kind = DeclarationKind::Const;
|
declaration_kind = DeclarationKind::Const;
|
||||||
consume(TokenType::Const);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
consume();
|
||||||
|
|
||||||
NonnullRefPtrVector<VariableDeclarator> declarations;
|
NonnullRefPtrVector<VariableDeclarator> declarations;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -1402,6 +1400,8 @@ NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration(bool with_
|
||||||
if (match(TokenType::Equals)) {
|
if (match(TokenType::Equals)) {
|
||||||
consume();
|
consume();
|
||||||
init = parse_expression(2);
|
init = parse_expression(2);
|
||||||
|
} else if (!for_loop_variable_declaration && declaration_kind == DeclarationKind::Const) {
|
||||||
|
syntax_error("Missing initializer in 'const' variable declaration");
|
||||||
}
|
}
|
||||||
declarations.append(create_ast_node<VariableDeclarator>(create_ast_node<Identifier>(move(id)), move(init)));
|
declarations.append(create_ast_node<VariableDeclarator>(create_ast_node<Identifier>(move(id)), move(init)));
|
||||||
if (match(TokenType::Comma)) {
|
if (match(TokenType::Comma)) {
|
||||||
|
@ -1410,7 +1410,7 @@ NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration(bool with_
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (with_semicolon)
|
if (!for_loop_variable_declaration)
|
||||||
consume_or_insert_semicolon();
|
consume_or_insert_semicolon();
|
||||||
|
|
||||||
auto declaration = create_ast_node<VariableDeclaration>(declaration_kind, move(declarations));
|
auto declaration = create_ast_node<VariableDeclaration>(declaration_kind, move(declarations));
|
||||||
|
@ -1651,9 +1651,15 @@ NonnullRefPtr<Statement> Parser::parse_for_statement()
|
||||||
m_parser_state.m_let_scopes.append(NonnullRefPtrVector<VariableDeclaration>());
|
m_parser_state.m_let_scopes.append(NonnullRefPtrVector<VariableDeclaration>());
|
||||||
in_scope = true;
|
in_scope = true;
|
||||||
}
|
}
|
||||||
init = parse_variable_declaration(false);
|
init = parse_variable_declaration(true);
|
||||||
if (match_for_in_of())
|
if (match_for_in_of())
|
||||||
return parse_for_in_of_statement(*init);
|
return parse_for_in_of_statement(*init);
|
||||||
|
if (static_cast<VariableDeclaration&>(*init).declaration_kind() == DeclarationKind::Const) {
|
||||||
|
for (auto& declaration : static_cast<VariableDeclaration&>(*init).declarations()) {
|
||||||
|
if (!declaration.init())
|
||||||
|
syntax_error("Missing initializer in 'const' variable declaration");
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
syntax_error("Unexpected token in for loop");
|
syntax_error("Unexpected token in for loop");
|
||||||
}
|
}
|
||||||
|
@ -1686,15 +1692,11 @@ NonnullRefPtr<Statement> Parser::parse_for_statement()
|
||||||
NonnullRefPtr<Statement> Parser::parse_for_in_of_statement(NonnullRefPtr<ASTNode> lhs)
|
NonnullRefPtr<Statement> Parser::parse_for_in_of_statement(NonnullRefPtr<ASTNode> lhs)
|
||||||
{
|
{
|
||||||
if (lhs->is_variable_declaration()) {
|
if (lhs->is_variable_declaration()) {
|
||||||
auto declarations = static_cast<VariableDeclaration*>(lhs.ptr())->declarations();
|
auto declarations = static_cast<VariableDeclaration&>(*lhs).declarations();
|
||||||
if (declarations.size() > 1) {
|
if (declarations.size() > 1)
|
||||||
syntax_error("multiple declarations not allowed in for..in/of");
|
syntax_error("multiple declarations not allowed in for..in/of");
|
||||||
lhs = create_ast_node<ErrorExpression>();
|
if (declarations.first().init() != nullptr)
|
||||||
}
|
|
||||||
if (declarations.first().init() != nullptr) {
|
|
||||||
syntax_error("variable initializer not allowed in for..in/of");
|
syntax_error("variable initializer not allowed in for..in/of");
|
||||||
lhs = create_ast_node<ErrorExpression>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
auto in_or_of = consume();
|
auto in_or_of = consume();
|
||||||
auto rhs = parse_expression(0);
|
auto rhs = parse_expression(0);
|
||||||
|
|
|
@ -66,7 +66,7 @@ public:
|
||||||
NonnullRefPtr<BlockStatement> parse_block_statement();
|
NonnullRefPtr<BlockStatement> parse_block_statement();
|
||||||
NonnullRefPtr<BlockStatement> parse_block_statement(bool& is_strict);
|
NonnullRefPtr<BlockStatement> parse_block_statement(bool& is_strict);
|
||||||
NonnullRefPtr<ReturnStatement> parse_return_statement();
|
NonnullRefPtr<ReturnStatement> parse_return_statement();
|
||||||
NonnullRefPtr<VariableDeclaration> parse_variable_declaration(bool with_semicolon = true);
|
NonnullRefPtr<VariableDeclaration> parse_variable_declaration(bool for_loop_variable_declaration = false);
|
||||||
NonnullRefPtr<Statement> parse_for_statement();
|
NonnullRefPtr<Statement> parse_for_statement();
|
||||||
NonnullRefPtr<Statement> parse_for_in_of_statement(NonnullRefPtr<ASTNode> lhs);
|
NonnullRefPtr<Statement> parse_for_in_of_statement(NonnullRefPtr<ASTNode> lhs);
|
||||||
NonnullRefPtr<IfStatement> parse_if_statement();
|
NonnullRefPtr<IfStatement> parse_if_statement();
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
test("missing initializer in 'const' variable declaration is syntax error", () => {
|
||||||
|
expect("const foo").not.toEval();
|
||||||
|
expect("const foo = 1, bar").not.toEval();
|
||||||
|
expect("const foo = 1, bar, baz = 2").not.toEval();
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue