Browse Source

Fix parsing of `async` in for-of loops (#3745)

pull/3751/head
raskad 8 months ago committed by GitHub
parent
commit
9e9d71ff91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 17
      core/parser/src/parser/expression/assignment/mod.rs
  2. 26
      core/parser/src/parser/expression/tests.rs
  3. 29
      core/parser/src/parser/statement/iteration/for_statement.rs

17
core/parser/src/parser/expression/assignment/mod.rs

@ -141,15 +141,22 @@ where
1
};
let peek_1 = cursor.peek(1, interner).or_abrupt()?.kind().clone();
if !cursor
.peek_is_line_terminator(skip_n, interner)
.or_abrupt()?
&& matches!(
cursor.peek(1, interner).or_abrupt()?.kind(),
&& (matches!(peek_1, TokenKind::Punctuator(Punctuator::OpenParen))
|| (matches!(
peek_1,
TokenKind::IdentifierName(_)
| TokenKind::Keyword((Keyword::Yield | Keyword::Await, _))
| TokenKind::Punctuator(Punctuator::OpenParen)
)
| TokenKind::Keyword((
Keyword::Yield | Keyword::Await | Keyword::Of,
_
))
) && matches!(
cursor.peek(2, interner).or_abrupt()?.kind(),
TokenKind::Punctuator(Punctuator::Arrow)
)))
{
return Ok(
AsyncArrowFunction::new(self.name, self.allow_in, self.allow_yield)

26
core/parser/src/parser/expression/tests.rs

@ -10,7 +10,8 @@ use boa_ast::{
},
Call, Identifier, Parenthesized, RegExpLiteral,
},
Declaration, Expression, Statement,
function::{AsyncArrowFunction, FormalParameter, FormalParameterList},
Declaration, Expression, Script, Statement,
};
use boa_interner::{Interner, Sym};
use boa_macros::utf16;
@ -685,6 +686,29 @@ fn check_logical_expressions() {
check_invalid_script("a || b ?? c");
}
#[test]
fn parse_async_arrow_function_named_of() {
let interner = &mut Interner::default();
check_script_parser(
"async of => {}",
vec![
Statement::Expression(Expression::from(AsyncArrowFunction::new(
None,
FormalParameterList::from_parameters(vec![FormalParameter::new(
Variable::from_identifier(
Identifier::new(interner.get_or_intern_static("of", utf16!("of"))),
None,
),
false,
)]),
Script::default(),
)))
.into(),
],
interner,
);
}
macro_rules! check_non_reserved_identifier {
($keyword:literal) => {{
let interner = &mut Interner::default();

29
core/parser/src/parser/statement/iteration/for_statement.rs

@ -111,6 +111,7 @@ where
}
};
let mut init_is_async_of = false;
let init = match cursor.peek(0, interner).or_abrupt()?.kind().clone() {
TokenKind::Keyword((Keyword::Var, _)) => {
cursor.advance(interner);
@ -135,19 +136,18 @@ where
.into(),
),
TokenKind::Keyword((Keyword::Async, false)) if !r#await => {
match cursor.peek(1, interner).or_abrupt()?.kind() {
TokenKind::Keyword((Keyword::Of, _)) => {
return Err(Error::lex(LexError::Syntax(
"invalid left-hand side expression 'async' of a for-of loop".into(),
init_position,
)));
if matches!(
cursor.peek(1, interner).or_abrupt()?.kind(),
TokenKind::Keyword((Keyword::Of, false))
) {
init_is_async_of = true;
}
_ => Some(
Some(
Expression::new(None, false, self.allow_yield, self.allow_await)
.parse(cursor, interner)?
.into(),
),
}
)
}
TokenKind::Punctuator(Punctuator::Semicolon) => None,
_ => Some(
@ -181,6 +181,17 @@ where
{
return Err(Error::general("unexpected token", position));
}
if init_is_async_of
&& init
== ForLoopInitializer::Expression(ast::Expression::Identifier(
Identifier::new(Sym::ASYNC),
))
{
return Err(Error::lex(LexError::Syntax(
"invalid left-hand side expression 'async' of a for-of loop".into(),
init_position,
)));
}
let in_loop = kw == &Keyword::In;
let init = initializer_to_iterable_loop_initializer(

Loading…
Cancel
Save