mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 17:27:35 +00:00
LibJS: Don't match async \n function as an async function declaration
This commit is contained in:
parent
c2ebaa9d87
commit
5010d4c20c
2 changed files with 27 additions and 5 deletions
|
@ -631,10 +631,15 @@ NonnullRefPtr<Statement> Parser::parse_statement(AllowLabelledFunction allow_lab
|
||||||
return result.release_nonnull();
|
return result.release_nonnull();
|
||||||
}
|
}
|
||||||
if (match_expression()) {
|
if (match_expression()) {
|
||||||
if (match(TokenType::Function) || (match(TokenType::Async) && next_token().type() == TokenType::Function) || match(TokenType::Class))
|
if (match(TokenType::Async)) {
|
||||||
|
auto lookahead_token = next_token();
|
||||||
|
if (lookahead_token.type() == TokenType::Function && !lookahead_token.trivia_contains_line_terminator())
|
||||||
|
syntax_error("Async function declaration not allowed in single-statement context");
|
||||||
|
} else if (match(TokenType::Function) || match(TokenType::Class)) {
|
||||||
syntax_error(String::formatted("{} declaration not allowed in single-statement context", m_state.current_token.name()));
|
syntax_error(String::formatted("{} declaration not allowed in single-statement context", m_state.current_token.name()));
|
||||||
if (match(TokenType::Let) && next_token().type() == TokenType::BracketOpen)
|
} else if (match(TokenType::Let) && next_token().type() == TokenType::BracketOpen) {
|
||||||
syntax_error(String::formatted("let followed by [ is not allowed in single-statement context"));
|
syntax_error(String::formatted("let followed by [ is not allowed in single-statement context"));
|
||||||
|
}
|
||||||
|
|
||||||
auto expr = parse_expression(0);
|
auto expr = parse_expression(0);
|
||||||
consume_or_insert_semicolon();
|
consume_or_insert_semicolon();
|
||||||
|
@ -3608,11 +3613,15 @@ bool Parser::match_declaration() const
|
||||||
return try_match_let_declaration();
|
return try_match_let_declaration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == TokenType::Async) {
|
||||||
|
auto lookahead_token = next_token();
|
||||||
|
return lookahead_token.type() == TokenType::Function && !lookahead_token.trivia_contains_line_terminator();
|
||||||
|
}
|
||||||
|
|
||||||
return type == TokenType::Function
|
return type == TokenType::Function
|
||||||
|| type == TokenType::Class
|
|| type == TokenType::Class
|
||||||
|| type == TokenType::Const
|
|| type == TokenType::Const
|
||||||
|| type == TokenType::Let
|
|| type == TokenType::Let;
|
||||||
|| (type == TokenType::Async && next_token().type() == TokenType::Function);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Token Parser::next_token() const
|
Token Parser::next_token() const
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
describe("parsing freestanding async functions", () => {
|
describe("parsing freestanding async functions", () => {
|
||||||
test("simple", () => {
|
test("simple", () => {
|
||||||
expect(`async function foo() {}`).toEval();
|
expect(`async function foo() {}`).toEval();
|
||||||
|
// Although it does not create an async function it is valid.
|
||||||
expect(`async
|
expect(`async
|
||||||
function foo() {}`).not.toEval();
|
function foo() {}`).toEval();
|
||||||
});
|
});
|
||||||
test("await expression", () => {
|
test("await expression", () => {
|
||||||
expect(`async function foo() { await bar(); }`).toEval();
|
expect(`async function foo() { await bar(); }`).toEval();
|
||||||
|
@ -167,6 +168,18 @@ describe("non async function declaration usage of async still works", () => {
|
||||||
const evalResult = eval("async >= 2");
|
const evalResult = eval("async >= 2");
|
||||||
expect(evalResult).toBeTrue();
|
expect(evalResult).toBeTrue();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("async with line ending does not create a function", () => {
|
||||||
|
expect(() => {
|
||||||
|
// The ignore is needed otherwise prettier puts a ';' after async.
|
||||||
|
// prettier-ignore
|
||||||
|
async
|
||||||
|
function f() {}
|
||||||
|
}).toThrowWithMessage(ReferenceError, "'async' is not defined");
|
||||||
|
|
||||||
|
expect(`async
|
||||||
|
function f() { await 3; }`).not.toEval();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("await cannot be used in class static init blocks", () => {
|
describe("await cannot be used in class static init blocks", () => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue