diff --git a/boa/src/syntax/parser/cursor/buffered_lexer/mod.rs b/boa/src/syntax/parser/cursor/buffered_lexer/mod.rs index 3e96b95545..976c9eda48 100644 --- a/boa/src/syntax/parser/cursor/buffered_lexer/mod.rs +++ b/boa/src/syntax/parser/cursor/buffered_lexer/mod.rs @@ -11,7 +11,7 @@ use std::io::Read; mod tests; /// The maximum number of tokens which can be peeked ahead. -const MAX_PEEK_SKIP: usize = 2; +const MAX_PEEK_SKIP: usize = 3; /// The fixed size of the buffer used for storing values that are peeked ahead. /// @@ -46,6 +46,8 @@ where None::, None::, None::, + None::, + None::, ], read_index: 0, write_index: 0, diff --git a/boa/src/syntax/parser/cursor/buffered_lexer/tests.rs b/boa/src/syntax/parser/cursor/buffered_lexer/tests.rs index 5dc16736c4..a79ad9afc4 100644 --- a/boa/src/syntax/parser/cursor/buffered_lexer/tests.rs +++ b/boa/src/syntax/parser/cursor/buffered_lexer/tests.rs @@ -208,7 +208,7 @@ fn peek_skip_next_till_end() { let mut cur = BufferedLexer::from(&b"a b c d e f g h i"[..]); let mut peeked: [Option; super::MAX_PEEK_SKIP + 1] = - [None::, None::, None::]; + [None::, None::, None::, None::]; loop { for (i, peek) in peeked.iter_mut().enumerate() { diff --git a/boa/src/syntax/parser/expression/assignment/arrow_function.rs b/boa/src/syntax/parser/expression/assignment/arrow_function.rs index 299e41497c..43b717b784 100644 --- a/boa/src/syntax/parser/expression/assignment/arrow_function.rs +++ b/boa/src/syntax/parser/expression/assignment/arrow_function.rs @@ -70,8 +70,8 @@ where fn parse(self, cursor: &mut Cursor) -> Result { let _timer = BoaProfiler::global().start_event("ArrowFunction", "Parsing"); - let next_token = cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?; + let params = if let TokenKind::Punctuator(Punctuator::OpenParen) = &next_token.kind() { // CoverParenthesizedExpressionAndArrowParameterList cursor.expect(Punctuator::OpenParen, "arrow function")?; diff --git a/boa/src/syntax/parser/expression/assignment/mod.rs b/boa/src/syntax/parser/expression/assignment/mod.rs index 9516b8af30..0a7cf4c4d0 100644 --- a/boa/src/syntax/parser/expression/assignment/mod.rs +++ b/boa/src/syntax/parser/expression/assignment/mod.rs @@ -145,7 +145,7 @@ where TokenKind::Punctuator(Punctuator::CloseParen) => { // Need to check if the token after the close paren is an arrow, if so then this is an ArrowFunction // otherwise it is an expression of the form (b). - if let Some(t) = cursor.peek(2)? { + if let Some(t) = cursor.peek(3)? { if t.kind() == &TokenKind::Punctuator(Punctuator::Arrow) { return ArrowFunction::new( diff --git a/boa/src/syntax/parser/function/tests.rs b/boa/src/syntax/parser/function/tests.rs index 52e7f922f6..33378540f8 100644 --- a/boa/src/syntax/parser/function/tests.rs +++ b/boa/src/syntax/parser/function/tests.rs @@ -1,6 +1,7 @@ use crate::syntax::{ ast::node::{ - ArrowFunctionDecl, BinOp, FormalParameter, FunctionDecl, Identifier, Node, Return, + ArrowFunctionDecl, BinOp, FormalParameter, FunctionDecl, Identifier, LetDecl, LetDeclList, + Node, Return, }, ast::op::NumOp, parser::tests::check_parser, @@ -176,3 +177,193 @@ fn check_arrow_empty_return_semicolon_insertion() { .into()], ); } + +#[test] +fn check_arrow_assignment() { + check_parser( + "let foo = (a) => { return a };", + vec![LetDeclList::from(vec![LetDecl::new::<_, Option>( + Identifier::from("foo"), + Some( + ArrowFunctionDecl::new( + vec![FormalParameter::new("a", None, false)], + vec![Return::new::, Option<_>>( + Some(Identifier::from("a").into()), + None, + ) + .into()], + ) + .into(), + ), + )]) + .into()], + ); +} + +#[test] +fn check_arrow_assignment_nobrackets() { + check_parser( + "let foo = (a) => a;", + vec![LetDeclList::from(vec![LetDecl::new::<_, Option>( + Identifier::from("foo"), + Some( + ArrowFunctionDecl::new( + vec![FormalParameter::new("a", None, false)], + vec![Return::new::, Option<_>>( + Some(Identifier::from("a").into()), + None, + ) + .into()], + ) + .into(), + ), + )]) + .into()], + ); +} + +#[test] +fn check_arrow_assignment_noparenthesis() { + check_parser( + "let foo = a => { return a };", + vec![LetDeclList::from(vec![LetDecl::new::<_, Option>( + Identifier::from("foo"), + Some( + ArrowFunctionDecl::new( + vec![FormalParameter::new("a", None, false)], + vec![Return::new::, Option<_>>( + Some(Identifier::from("a").into()), + None, + ) + .into()], + ) + .into(), + ), + )]) + .into()], + ); +} + +#[test] +fn check_arrow_assignment_noparenthesis_nobrackets() { + check_parser( + "let foo = a => a;", + vec![LetDeclList::from(vec![LetDecl::new::<_, Option>( + Identifier::from("foo"), + Some( + ArrowFunctionDecl::new( + vec![FormalParameter::new("a", None, false)], + vec![Return::new::, Option<_>>( + Some(Identifier::from("a").into()), + None, + ) + .into()], + ) + .into(), + ), + )]) + .into()], + ); +} + +#[test] +fn check_arrow_assignment_2arg() { + check_parser( + "let foo = (a, b) => { return a };", + vec![LetDeclList::from(vec![LetDecl::new::<_, Option>( + Identifier::from("foo"), + Some( + ArrowFunctionDecl::new( + vec![ + FormalParameter::new("a", None, false), + FormalParameter::new("b", None, false), + ], + vec![Return::new::, Option<_>>( + Some(Identifier::from("a").into()), + None, + ) + .into()], + ) + .into(), + ), + )]) + .into()], + ); +} + +#[test] +fn check_arrow_assignment_2arg_nobrackets() { + check_parser( + "let foo = (a, b) => a;", + vec![LetDeclList::from(vec![LetDecl::new::<_, Option>( + Identifier::from("foo"), + Some( + ArrowFunctionDecl::new( + vec![ + FormalParameter::new("a", None, false), + FormalParameter::new("b", None, false), + ], + vec![Return::new::, Option<_>>( + Some(Identifier::from("a").into()), + None, + ) + .into()], + ) + .into(), + ), + )]) + .into()], + ); +} + +#[test] +fn check_arrow_assignment_3arg() { + check_parser( + "let foo = (a, b, c) => { return a };", + vec![LetDeclList::from(vec![LetDecl::new::<_, Option>( + Identifier::from("foo"), + Some( + ArrowFunctionDecl::new( + vec![ + FormalParameter::new("a", None, false), + FormalParameter::new("b", None, false), + FormalParameter::new("c", None, false), + ], + vec![Return::new::, Option<_>>( + Some(Identifier::from("a").into()), + None, + ) + .into()], + ) + .into(), + ), + )]) + .into()], + ); +} + +#[test] +fn check_arrow_assignment_3arg_nobrackets() { + check_parser( + "let foo = (a, b, c) => a;", + vec![LetDeclList::from(vec![LetDecl::new::<_, Option>( + Identifier::from("foo"), + Some( + ArrowFunctionDecl::new( + vec![ + FormalParameter::new("a", None, false), + FormalParameter::new("b", None, false), + FormalParameter::new("c", None, false), + ], + vec![Return::new::, Option<_>>( + Some(Identifier::from("a").into()), + None, + ) + .into()], + ) + .into(), + ), + )]) + .into()], + ); +}