From 69eec75b8ecbe39070236c99c01f17131252ae89 Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 12 Jan 2021 21:15:33 +0000 Subject: [PATCH 1/5] Async arrow node --- .../async_arrow_function_decl/mod.rs | 88 +++++++++++++++++++ boa/src/syntax/ast/node/declaration/mod.rs | 2 + 2 files changed, 90 insertions(+) create mode 100644 boa/src/syntax/ast/node/declaration/async_arrow_function_decl/mod.rs diff --git a/boa/src/syntax/ast/node/declaration/async_arrow_function_decl/mod.rs b/boa/src/syntax/ast/node/declaration/async_arrow_function_decl/mod.rs new file mode 100644 index 00000000000..c5c1250b7f0 --- /dev/null +++ b/boa/src/syntax/ast/node/declaration/async_arrow_function_decl/mod.rs @@ -0,0 +1,88 @@ +use crate::{ + builtins::function::FunctionFlags, + exec::Executable, + syntax::ast::node::{join_nodes, FormalParameter, Node, StatementList}, + Context, Result, Value, +}; +use gc::{Finalize, Trace}; +use std::fmt; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// +/// +/// +/// +/// More information: +/// - [ECMAScript reference][spec] +/// - [MDN documentation][mdn] +/// +/// [spec]: +/// [mdn]: +#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))] +#[derive(Clone, Debug, Trace, Finalize, PartialEq)] +pub struct AsyncArrowFunctionDecl { + params: Box<[FormalParameter]>, + body: StatementList, +} + +impl AsyncArrowFunctionDecl { + /// Creates a new `AsyncArrowFunctionDecl` AST node. + pub(in crate::syntax) fn new(params: P, body: B) -> Self + where + P: Into>, + B: Into, + { + Self { + params: params.into(), + body: body.into(), + } + } + + /// Gets the list of parameters of the arrow function. + pub(crate) fn params(&self) -> &[FormalParameter] { + &self.params + } + + /// Gets the body of the arrow function. + pub(crate) fn body(&self) -> &[Node] { + &self.body.items() + } + + /// Implements the display formatting with indentation. + pub(in crate::syntax::ast::node) fn display( + &self, + f: &mut fmt::Formatter<'_>, + indentation: usize, + ) -> fmt::Result { + write!(f, "async (")?; + join_nodes(f, &self.params)?; + f.write_str(") => ")?; + self.body.display(f, indentation) + } +} + +impl Executable for AsyncArrowFunctionDecl { + fn run(&self, context: &mut Context) -> Result { + Ok(context.create_function( + self.params().to_vec(), + self.body().to_vec(), + FunctionFlags::CALLABLE + | FunctionFlags::CONSTRUCTABLE + | FunctionFlags::LEXICAL_THIS_MODE, + )) + } +} + +impl fmt::Display for AsyncArrowFunctionDecl { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.display(f, 0) + } +} + +impl From for Node { + fn from(decl: AsyncArrowFunctionDecl) -> Self { + Self::AsyncArrowFunctionDecl(decl) + } +} diff --git a/boa/src/syntax/ast/node/declaration/mod.rs b/boa/src/syntax/ast/node/declaration/mod.rs index ac5a0dbbb92..b72f128d24f 100644 --- a/boa/src/syntax/ast/node/declaration/mod.rs +++ b/boa/src/syntax/ast/node/declaration/mod.rs @@ -1,6 +1,7 @@ //! Declaration nodes pub mod arrow_function_decl; +pub mod async_arrow_function_decl; pub mod async_function_decl; pub mod async_function_expr; pub mod const_decl_list; @@ -11,6 +12,7 @@ pub mod var_decl_list; pub use self::{ arrow_function_decl::ArrowFunctionDecl, + async_arrow_function_decl::AsyncArrowFunctionDecl, async_function_decl::AsyncFunctionDecl, async_function_expr::AsyncFunctionExpr, const_decl_list::{ConstDecl, ConstDeclList}, From dbbc61159ce1d9aa992e9f57794c2e543d1afa8b Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 12 Jan 2021 21:36:18 +0000 Subject: [PATCH 2/5] Bring over rest of code from previous branch --- .../async_arrow_function_decl/mod.rs | 4 +- boa/src/syntax/ast/node/mod.rs | 9 +- .../assignment/async_arrow_function.rs | 102 ++++++++++++++++++ .../expression/assignment/concise_body.rs | Bin 0 -> 4246 bytes .../expression/assignment/expression_body.rs | Bin 0 -> 1906 bytes .../parser/expression/assignment/mod.rs | 7 ++ .../primary/async_function_expression/mod.rs | 2 +- .../primary/function_expression/mod.rs | 2 +- .../primary/object_initializer/mod.rs | 4 +- boa/src/syntax/parser/function/mod.rs | 12 ++- .../hoistable/async_function_decl/mod.rs | 2 +- .../hoistable/function_decl/mod.rs | 2 +- 12 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 boa/src/syntax/parser/expression/assignment/async_arrow_function.rs create mode 100644 boa/src/syntax/parser/expression/assignment/concise_body.rs create mode 100644 boa/src/syntax/parser/expression/assignment/expression_body.rs diff --git a/boa/src/syntax/ast/node/declaration/async_arrow_function_decl/mod.rs b/boa/src/syntax/ast/node/declaration/async_arrow_function_decl/mod.rs index c5c1250b7f0..630768569c9 100644 --- a/boa/src/syntax/ast/node/declaration/async_arrow_function_decl/mod.rs +++ b/boa/src/syntax/ast/node/declaration/async_arrow_function_decl/mod.rs @@ -1,13 +1,13 @@ use crate::{ builtins::function::FunctionFlags, exec::Executable, + gc::{Finalize, Trace}, syntax::ast::node::{join_nodes, FormalParameter, Node, StatementList}, Context, Result, Value, }; -use gc::{Finalize, Trace}; use std::fmt; -#[cfg(feature = "serde")] +#[cfg(feature = "deser")] use serde::{Deserialize, Serialize}; /// diff --git a/boa/src/syntax/ast/node/mod.rs b/boa/src/syntax/ast/node/mod.rs index 06119dc9fd0..8c8b1fdf10e 100644 --- a/boa/src/syntax/ast/node/mod.rs +++ b/boa/src/syntax/ast/node/mod.rs @@ -29,8 +29,8 @@ pub use self::{ call::Call, conditional::{ConditionalOp, If}, declaration::{ - ArrowFunctionDecl, AsyncFunctionDecl, AsyncFunctionExpr, ConstDecl, ConstDeclList, - FunctionDecl, FunctionExpr, LetDecl, LetDeclList, VarDecl, VarDeclList, + ArrowFunctionDecl, AsyncArrowFunctionDecl, AsyncFunctionDecl, AsyncFunctionExpr, ConstDecl, + ConstDeclList, FunctionDecl, FunctionExpr, LetDecl, LetDeclList, VarDecl, VarDeclList, }, field::{GetConstField, GetField}, identifier::Identifier, @@ -72,6 +72,9 @@ pub enum Node { /// An assignment operator node. [More information](./operator/struct.Assign.html). Assign(Assign), + /// An async arrow function declaration node. [More information](./declaration/struct.AsyncArrowFunctionDecl.html). + AsyncArrowFunctionDecl(AsyncArrowFunctionDecl), + /// An async function declaration node. [More information](./declaration/struct.AsyncFunctionDecl.html). AsyncFunctionDecl(AsyncFunctionDecl), @@ -271,6 +274,7 @@ impl Node { Self::Assign(ref op) => Display::fmt(op, f), Self::LetDeclList(ref decl) => Display::fmt(decl, f), Self::ConstDeclList(ref decl) => Display::fmt(decl, f), + Self::AsyncArrowFunctionDecl(ref decl) => decl.display(f, indentation), Self::AsyncFunctionDecl(ref decl) => decl.display(f, indentation), Self::AsyncFunctionExpr(ref expr) => expr.display(f, indentation), Self::AwaitExpr(ref expr) => expr.display(f, indentation), @@ -282,6 +286,7 @@ impl Executable for Node { fn run(&self, context: &mut Context) -> Result { let _timer = BoaProfiler::global().start_event("Executable", "exec"); match *self { + Node::AsyncArrowFunctionDecl(ref decl) => decl.run(context), Node::AsyncFunctionDecl(ref decl) => decl.run(context), Node::AsyncFunctionExpr(ref function_expr) => function_expr.run(context), Node::AwaitExpr(ref expr) => expr.run(context), diff --git a/boa/src/syntax/parser/expression/assignment/async_arrow_function.rs b/boa/src/syntax/parser/expression/assignment/async_arrow_function.rs new file mode 100644 index 00000000000..4e59eb6ce21 --- /dev/null +++ b/boa/src/syntax/parser/expression/assignment/async_arrow_function.rs @@ -0,0 +1,102 @@ +/! Async Arrow function parsing. +//! +//! More information: +//! - [MDN documentation][mdn] +//! - [ECMAScript specification][spec] +//! +//! [mdn]: +//! [spec]: https://tc39.es/ecma262/#prod-AsyncArrowFunction + +use super::ConciseBody; +use crate::{ + syntax::{ + ast::{ + node::{AsyncArrowFunctionDecl, FormalParameter}, + Keyword, Punctuator, + }, + lexer::TokenKind, + parser::{ + error::{ErrorContext, ParseError}, + function::FormalParameters, + statement::BindingIdentifier, + AllowAwait, AllowIn, AllowYield, Cursor, TokenParser, + }, + }, + BoaProfiler, +}; + +use std::io::Read; + +/// Arrow function parsing. +/// +/// More information: +/// - [MDN documentation][mdn] +/// - [ECMAScript specification][spec] +/// +/// [mdn]: +/// [spec]: https://tc39.es/ecma262/#prod-AsyncArrowFunction +#[derive(Debug, Clone, Copy)] +pub(in crate::syntax::parser) struct AsyncArrowFunction { + allow_in: AllowIn, + allow_yield: AllowYield, + allow_await: AllowAwait, +} + +impl AsyncArrowFunction { + /// Creates a new `AsyncArrowFunction` parser. + pub(in crate::syntax::parser) fn new( + allow_in: I, + allow_yield: Y, + allow_await: A, + ) -> Self + where + I: Into, + Y: Into, + A: Into, + { + Self { + allow_in: allow_in.into(), + allow_yield: allow_yield.into(), + allow_await: allow_await.into(), + } + } +} + +impl TokenParser for AsyncArrowFunction +where + R: Read, +{ + type Output = AsyncArrowFunctionDecl; + + fn parse(self, cursor: &mut Cursor) -> Result { + let _timer = BoaProfiler::global().start_event("AsyncArrowFunction", "Parsing"); + cursor.expect( + TokenKind::Keyword(Keyword::Async), + "async arrow function parsing", + )?; + let token = cursor.peek_expect_no_lineterminator(0, "async arrow function parsing")?; + + let params = if let TokenKind::Punctuator(Punctuator::OpenParen) = &token.kind() { + // CoverCallExpressionAndAsyncArrowHead + cursor.expect(Punctuator::OpenParen, "async arrow function")?; + + let params = FormalParameters::new(false, true, true).parse(cursor)?; + cursor.expect(Punctuator::CloseParen, "async arrow function")?; + params + } else { + // AsyncArrowBindingIdentifier + let param = BindingIdentifier::new(self.allow_yield, true) + .parse(cursor) + .context("async arrow function")?; + Box::new([FormalParameter::new(param, None, false)]) + }; + + cursor.peek_expect_no_lineterminator(0, "async arrow function")?; + cursor.expect( + TokenKind::Punctuator(Punctuator::Arrow), + "async arrow function", + )?; + let body = ConciseBody::new(self.allow_in, true).parse(cursor)?; + Ok(AsyncArrowFunctionDecl::new(params, body)) + } +} diff --git a/boa/src/syntax/parser/expression/assignment/concise_body.rs b/boa/src/syntax/parser/expression/assignment/concise_body.rs new file mode 100644 index 0000000000000000000000000000000000000000..84ebe16129947dc15b6e726d6acf9f9ff161bce7 GIT binary patch literal 4246 zcmc&%?@!ZU5WdeQ{tp!sGZGm_6B7|Ih?o%NN5F4pfzqxpfoAj|12$OI9_{VEGDPL*W}VPIa#@*r|``%i2Rklq(J< zf32Fi?!)MJr|TP#v-gZ7oBCzQQucG@ouf_pH95m)AeXW^!D3x;8BHRJr0}%ZGoRve zGs#()H{zCRF6aY2Al@ zqsJK9zAN4W;c}Kjq?Uli39ual*%4}lyd49fH}VclCQ}!2O%O*cujMVii}D<@to0Px zuCJUBb@yTc795ujb}GwwELEw8dB>WwOf>uX9L!;5kY%jB7P#A$Be3>ZyYjkrras=W zQ_;>4Hs>e29YXF1I>mIEhZL(b#|kUDxw}+nhxfn(c+v+#xBDV7^WM*1br4`m`6GBY zfWOwoZxmzd^pHQ+{C#~X`XX!JrXRZ(`wWq|#QiYHJ@NB?euy>ih(y&oi+f#TaWghqP&M3a2A`NWh}?2FP_vQ*+C7lGw~Y9ie{B(uevi*G1WajV^zULR;h7< zmCU)svkm7PYv%=O#P$i#9u{rED*DY@KZ6g;Q;zX;5&BB|#W|%o8xhrVtnRDL)CBx2 zd)8JYx;Uk^&~3?I-N2G>v%2n5>_ZV#QZv!Sf%AoJdYfOtP7dO4BpRAo^fXFa#!}M@rPct6*Xpt z6RJ6THv1T9kw3;h2PAy5G9%&X*`^SYom0-;FWMVeWo>e={~OukM8p19H)E<<+0n{& zF3!)?DR=LxC94m17_+&L%+_~GaymnI7@*^|^vsjUGn|6h+x-7%$ou=mG3)a=@UP1Vo4Dn{GNRMzjTm}Y08Je51(c++ey=PR7He*sq6Z8`t| literal 0 HcmV?d00001 diff --git a/boa/src/syntax/parser/expression/assignment/expression_body.rs b/boa/src/syntax/parser/expression/assignment/expression_body.rs new file mode 100644 index 0000000000000000000000000000000000000000..8d9633c6790ad6acd6514f040a6a7c60afbeab3a GIT binary patch literal 1906 zcmb7FVQUjX5PhEo|HDB+5@-`p5UjBfs~_@3rTR^ZySqw<7XhV#_@t-Zsc% z^ujZB@#M5sT#6>8%(Eojp?eaH@SWN<`K+iXX^jjo@CpNmV8}5e^C_O=CEp>A9QR`C zq%#w5dFGUipSk#s@RcjEl;aoY9^P@hCdQivtyn22^Vpa4ev3XXo%M=(*R%;W(I+Fq zS8^xgoIDsqvX^Vi!Z*fK5OJItp8>HGY9r{U_jzku#rgCZ(Wo~kZ!2c~|6;VvoD-w6 zrYf%JBjqceHk_{>M14h#xKal$8pG7h>72gJ{|FP8jWKiB0$FmJ`MVb!T7W-X~jIB|JVHfq+!D7rh6oi&wj+BT05T7?Yl+O|7^d9sLitH<_j zj`15ayRw0+GvVm5s@vVf{Ma1Zw)yPdd5rIEi($X=V_cylb_nIFyVuz6oG40ab@gAn z_43-C-3yl=>qMT3HvctmzB+$`kG$RLNg5Np;cNXkbTDJhS8k|xbqil{>L?j~SU1(Z zea1WKy~cgkBMdd$-Nz5r!(;zZ>csvAhZqNY_e)XFom4oqGCXbFP$7Nx>KK2FxqmSK F{{Z4KB+UQ- literal 0 HcmV?d00001 diff --git a/boa/src/syntax/parser/expression/assignment/mod.rs b/boa/src/syntax/parser/expression/assignment/mod.rs index 0a7cf4c4d07..bbd3666b1fa 100644 --- a/boa/src/syntax/parser/expression/assignment/mod.rs +++ b/boa/src/syntax/parser/expression/assignment/mod.rs @@ -84,6 +84,13 @@ where // Arrow function match cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?.kind() { + // Async a => {} + TokenKind::Keyword(Keyword::Async) => { + return AsyncArrowFunction::new(self.allow_in, self.allow_yield, self.allow_await) + .parse(cursor) + .map(Node::AsyncArrowFunctionDecl); + } + // a=>{} TokenKind::Identifier(_) | TokenKind::Keyword(Keyword::Yield) diff --git a/boa/src/syntax/parser/expression/primary/async_function_expression/mod.rs b/boa/src/syntax/parser/expression/primary/async_function_expression/mod.rs index 3bc2a5e2712..c8aaf0bf801 100644 --- a/boa/src/syntax/parser/expression/primary/async_function_expression/mod.rs +++ b/boa/src/syntax/parser/expression/primary/async_function_expression/mod.rs @@ -65,7 +65,7 @@ where cursor.expect(Punctuator::OpenParen, "async function expression")?; - let params = FormalParameters::new(false, true).parse(cursor)?; + let params = FormalParameters::new(false, true, false).parse(cursor)?; cursor.expect(Punctuator::CloseParen, "async function expression")?; cursor.expect(Punctuator::OpenBlock, "async function expression")?; diff --git a/boa/src/syntax/parser/expression/primary/function_expression/mod.rs b/boa/src/syntax/parser/expression/primary/function_expression/mod.rs index 645a5888668..2ce2694a132 100644 --- a/boa/src/syntax/parser/expression/primary/function_expression/mod.rs +++ b/boa/src/syntax/parser/expression/primary/function_expression/mod.rs @@ -60,7 +60,7 @@ where cursor.expect(Punctuator::OpenParen, "function expression")?; - let params = FormalParameters::new(false, false).parse(cursor)?; + let params = FormalParameters::new(false, false, false).parse(cursor)?; cursor.expect(Punctuator::CloseParen, "function expression")?; cursor.expect(Punctuator::OpenBlock, "function expression")?; diff --git a/boa/src/syntax/parser/expression/primary/object_initializer/mod.rs b/boa/src/syntax/parser/expression/primary/object_initializer/mod.rs index 5138be9251e..4596fb12187 100644 --- a/boa/src/syntax/parser/expression/primary/object_initializer/mod.rs +++ b/boa/src/syntax/parser/expression/primary/object_initializer/mod.rs @@ -212,7 +212,7 @@ where "property method definition", )?; let first_param = cursor.peek(0)?.expect("current token disappeared").clone(); - let params = FormalParameters::new(false, false).parse(cursor)?; + let params = FormalParameters::new(false, false, false).parse(cursor)?; cursor.expect(Punctuator::CloseParen, "method definition")?; if idn == "get" { if !params.is_empty() { @@ -233,7 +233,7 @@ where } } prop_name => { - let params = FormalParameters::new(false, false).parse(cursor)?; + let params = FormalParameters::new(false, false, true).parse(cursor)?; cursor.expect(Punctuator::CloseParen, "method definition")?; ( MethodDefinitionKind::Ordinary, diff --git a/boa/src/syntax/parser/function/mod.rs b/boa/src/syntax/parser/function/mod.rs index 8340fe79640..e644547473e 100644 --- a/boa/src/syntax/parser/function/mod.rs +++ b/boa/src/syntax/parser/function/mod.rs @@ -27,23 +27,27 @@ use crate::{ }; use std::io::Read; -/// Formal parameters parsing. +/// UniqueFormalParameters / FormalParameters parsing. +/// +/// Due to the similarity between these productions we use a unique flag rather than +/// duplicating the code. /// /// More information: /// - [MDN documentation][mdn] /// - [ECMAScript specification][spec] /// /// [mdn]: https://developer.mozilla.org/en-US/docs/Glossary/Parameter -/// [spec]: https://tc39.es/ecma262/#prod-FormalParameters +/// [spec]: https://tc39.es/ecma262/#sec-function-definitions #[derive(Debug, Clone, Copy)] pub(in crate::syntax::parser) struct FormalParameters { allow_yield: AllowYield, allow_await: AllowAwait, + unique: bool, } impl FormalParameters { /// Creates a new `FormalParameters` parser. - pub(in crate::syntax::parser) fn new(allow_yield: Y, allow_await: A) -> Self + pub(in crate::syntax::parser) fn new(allow_yield: Y, allow_await: A, unique: bool) -> Self where Y: Into, A: Into, @@ -51,6 +55,7 @@ impl FormalParameters { Self { allow_yield: allow_yield.into(), allow_await: allow_await.into(), + unique, } } } @@ -62,6 +67,7 @@ where type Output = Box<[node::FormalParameter]>; fn parse(self, cursor: &mut Cursor) -> Result { + // TODO UniqueFormalParameters let _timer = BoaProfiler::global().start_event("FormalParameters", "Parsing"); cursor.set_goal(InputElement::RegExp); diff --git a/boa/src/syntax/parser/statement/declaration/hoistable/async_function_decl/mod.rs b/boa/src/syntax/parser/statement/declaration/hoistable/async_function_decl/mod.rs index 049b458b3be..763fa68fdd9 100644 --- a/boa/src/syntax/parser/statement/declaration/hoistable/async_function_decl/mod.rs +++ b/boa/src/syntax/parser/statement/declaration/hoistable/async_function_decl/mod.rs @@ -75,7 +75,7 @@ where cursor.expect(Punctuator::OpenParen, "async function declaration")?; - let params = FormalParameters::new(false, true).parse(cursor)?; + let params = FormalParameters::new(false, true, false).parse(cursor)?; cursor.expect(Punctuator::CloseParen, "async function declaration")?; cursor.expect(Punctuator::OpenBlock, "async function declaration")?; diff --git a/boa/src/syntax/parser/statement/declaration/hoistable/function_decl/mod.rs b/boa/src/syntax/parser/statement/declaration/hoistable/function_decl/mod.rs index f40045b5fd1..fdf0def453d 100644 --- a/boa/src/syntax/parser/statement/declaration/hoistable/function_decl/mod.rs +++ b/boa/src/syntax/parser/statement/declaration/hoistable/function_decl/mod.rs @@ -56,7 +56,7 @@ where cursor.expect(Punctuator::OpenParen, "function declaration")?; - let params = FormalParameters::new(false, false).parse(cursor)?; + let params = FormalParameters::new(false, false, false).parse(cursor)?; cursor.expect(Punctuator::CloseParen, "function declaration")?; cursor.expect(Punctuator::OpenBlock, "function declaration")?; From a27e981780a30e22d05b7fa8c4ec26990c95ae7f Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 12 Jan 2021 21:51:27 +0000 Subject: [PATCH 3/5] Fix various issues, remove expression_body from arrow_function --- .../async_arrow_function_decl/mod.rs | 2 +- .../expression/assignment/arrow_function.rs | 82 ++---------------- .../assignment/async_arrow_function.rs | 2 +- .../expression/assignment/concise_body.rs | Bin 4246 -> 2048 bytes .../expression/assignment/expression_body.rs | Bin 1906 -> 913 bytes .../parser/expression/assignment/mod.rs | 8 +- 6 files changed, 14 insertions(+), 80 deletions(-) diff --git a/boa/src/syntax/ast/node/declaration/async_arrow_function_decl/mod.rs b/boa/src/syntax/ast/node/declaration/async_arrow_function_decl/mod.rs index 630768569c9..8d6410151ba 100644 --- a/boa/src/syntax/ast/node/declaration/async_arrow_function_decl/mod.rs +++ b/boa/src/syntax/ast/node/declaration/async_arrow_function_decl/mod.rs @@ -71,7 +71,7 @@ impl Executable for AsyncArrowFunctionDecl { FunctionFlags::CALLABLE | FunctionFlags::CONSTRUCTABLE | FunctionFlags::LEXICAL_THIS_MODE, - )) + )?) } } diff --git a/boa/src/syntax/parser/expression/assignment/arrow_function.rs b/boa/src/syntax/parser/expression/assignment/arrow_function.rs index 43b717b7843..a29eed8c948 100644 --- a/boa/src/syntax/parser/expression/assignment/arrow_function.rs +++ b/boa/src/syntax/parser/expression/assignment/arrow_function.rs @@ -7,12 +7,12 @@ //! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions //! [spec]: https://tc39.es/ecma262/#sec-arrow-function-definitions -use super::AssignmentExpression; +use super::ConciseBody; use crate::syntax::lexer::TokenKind; use crate::{ syntax::{ ast::{ - node::{ArrowFunctionDecl, FormalParameter, Node, Return, StatementList}, + node::{ArrowFunctionDecl, FormalParameter}, Punctuator, }, parser::{ @@ -76,7 +76,8 @@ where // CoverParenthesizedExpressionAndArrowParameterList cursor.expect(Punctuator::OpenParen, "arrow function")?; - let params = FormalParameters::new(self.allow_yield, self.allow_await).parse(cursor)?; + let params = + FormalParameters::new(self.allow_yield, self.allow_await, false).parse(cursor)?; cursor.expect(Punctuator::CloseParen, "arrow function")?; params } else { @@ -89,80 +90,7 @@ where cursor.peek_expect_no_lineterminator(0, "arrow function")?; cursor.expect(TokenKind::Punctuator(Punctuator::Arrow), "arrow function")?; - let body = ConciseBody::new(self.allow_in).parse(cursor)?; + let body = ConciseBody::new(self.allow_in, false).parse(cursor)?; Ok(ArrowFunctionDecl::new(params, body)) } } - -/// -#[derive(Debug, Clone, Copy)] -struct ConciseBody { - allow_in: AllowIn, -} - -impl ConciseBody { - /// Creates a new `ConcideBody` parser. - fn new(allow_in: I) -> Self - where - I: Into, - { - Self { - allow_in: allow_in.into(), - } - } -} - -impl TokenParser for ConciseBody -where - R: Read, -{ - type Output = StatementList; - - fn parse(self, cursor: &mut Cursor) -> Result { - match cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?.kind() { - TokenKind::Punctuator(Punctuator::OpenBlock) => { - let _ = cursor.next(); - let body = FunctionBody::new(false, false).parse(cursor)?; - cursor.expect(Punctuator::CloseBlock, "arrow function")?; - Ok(body) - } - _ => Ok(StatementList::from(vec![Return::new( - ExpressionBody::new(self.allow_in, false).parse(cursor)?, - None, - ) - .into()])), - } - } -} - -/// -#[derive(Debug, Clone, Copy)] -struct ExpressionBody { - allow_in: AllowIn, - allow_await: AllowAwait, -} - -impl ExpressionBody { - /// Creates a new `ExpressionBody` parser. - fn new(allow_in: I, allow_await: A) -> Self - where - I: Into, - A: Into, - { - Self { - allow_in: allow_in.into(), - allow_await: allow_await.into(), - } - } -} - -impl TokenParser for ExpressionBody -where - R: Read, -{ - type Output = Node; - - fn parse(self, cursor: &mut Cursor) -> ParseResult { - AssignmentExpression::new(self.allow_in, false, self.allow_await).parse(cursor) - } -} diff --git a/boa/src/syntax/parser/expression/assignment/async_arrow_function.rs b/boa/src/syntax/parser/expression/assignment/async_arrow_function.rs index 4e59eb6ce21..975f424bf9f 100644 --- a/boa/src/syntax/parser/expression/assignment/async_arrow_function.rs +++ b/boa/src/syntax/parser/expression/assignment/async_arrow_function.rs @@ -1,4 +1,4 @@ -/! Async Arrow function parsing. +//! Async Arrow function parsing. //! //! More information: //! - [MDN documentation][mdn] diff --git a/boa/src/syntax/parser/expression/assignment/concise_body.rs b/boa/src/syntax/parser/expression/assignment/concise_body.rs index 84ebe16129947dc15b6e726d6acf9f9ff161bce7..990aaf1b24fe833bf366a154b829b0d9a4857868 100644 GIT binary patch literal 2048 zcmbtVZExE~4F2w4!L`630kS-Fz<^y67jBvX#+J5l`pqy>S)vln@||!mjg7$nedL{F zNo|2_n7&ANM?QSW<3l-vU|fS*h?_&B(U?lfcd9sEOdK8MI?!dcZ1%~?+`7yv9roIz8V?-&v)ZBjvyw$PY%*0=1i-}Lk*g}X(39-Vg zpuO2_2G>gFl|jaV87wH>e7MDID*2GIt+!tou#ZUf$ut6%B@&^pSRZ*8OtwdOLipPm z3tYqu$~t=ht3YGna;hp-3<}rORi1GsJ@Bm}z)F@%@BNAJ;b02u+xH)!P`TsE`lHQy zU&zh*{O0<0ahL0=v0xg^tFp!3ta<6}TI!S>{HHh>*JJuGqXpw}OwTl=64(fMw6-x~ zHnaJ!zo%$snD4VUzrC5gZnP?^8(nn*ExB;E>P2bMelLz9;jbx zC6QjLImVkwyRW1;H=S?u%G`UB0=7!k)N+$awQuSl0QjcU zNJ=r(9ulA6i_f|6J@^Ge|EC^xK&X^#d%2uP*_pvIfpOdzrgON%y7b;pkEro1!li(v zwCb|e$~>qoB*h|SH|UqV)ko^S(uyFWxR*AYbsYNLlaG4ps&KiQ4;9HvYV%=jCOy}c z0G4Mm30&;4LHOuw<1Ac_Ck!c=!&7B^%_2h?B#`?NAmHacd4zdD0exjwXk2YCIa475 zW&(an`1vv)q)!^mA6u-nLEJ^Z#BWozyH`5uJ%m_nwQKB+Ea-GcGc1Y+Ak6MO-Dr}X z$6(Zd5|IYwyISSD7_NpC*qfgkE!m=Pk*kIKKK( z&=VkW{ePie4iZ|Y%Yfe>cM)@nM}-ZI+?mlW%-L@ApA(|gY9D>Y{HJyJ5r&eFa2R3y ilMP1xLOOB1a6i4gIzAtGc#YzW*|%!l!~?Aj|12$OI9_{VEGDPL*W}VPIa#@*r|``%i2Rklq(J< zf32Fi?!)MJr|TP#v-gZ7oBCzQQucG@ouf_pH95m)AeXW^!D3x;8BHRJr0}%ZGoRve zGs#()H{zCRF6aY2Al@ zqsJK9zAN4W;c}Kjq?Uli39ual*%4}lyd49fH}VclCQ}!2O%O*cujMVii}D<@to0Px zuCJUBb@yTc795ujb}GwwELEw8dB>WwOf>uX9L!;5kY%jB7P#A$Be3>ZyYjkrras=W zQ_;>4Hs>e29YXF1I>mIEhZL(b#|kUDxw}+nhxfn(c+v+#xBDV7^WM*1br4`m`6GBY zfWOwoZxmzd^pHQ+{C#~X`XX!JrXRZ(`wWq|#QiYHJ@NB?euy>ih(y&oi+f#TaWghqP&M3a2A`NWh}?2FP_vQ*+C7lGw~Y9ie{B(uevi*G1WajV^zULR;h7< zmCU)svkm7PYv%=O#P$i#9u{rED*DY@KZ6g;Q;zX;5&BB|#W|%o8xhrVtnRDL)CBx2 zd)8JYx;Uk^&~3?I-N2G>v%2n5>_ZV#QZv!Sf%AoJdYfOtP7dO4BpRAo^fXFa#!}M@rPct6*Xpt z6RJ6THv1T9kw3;h2PAy5G9%&X*`^SYom0-;FWMVeWo>e={~OukM8p19H)E<<+0n{& zF3!)?DR=LxC94m17_+&L%+_~GaymnI7@*^|^vsjUGn|6h+x-7%$ou=mG3)a=@UP1Vo4Dn{GNRMzjTm}Y08Je51(c++ey=PR7He*sq6Z8`t| diff --git a/boa/src/syntax/parser/expression/assignment/expression_body.rs b/boa/src/syntax/parser/expression/assignment/expression_body.rs index 8d9633c6790ad6acd6514f040a6a7c60afbeab3a..57c8cf27662a7d7ded8bf8b7734c2f0042b0d5fe 100644 GIT binary patch literal 913 zcmZuwO>5jR5WVYH3vh6LDMzLoTQ?DfSQD+JJ-#e1**lDAK zrTOs8dru>85vjziBb{N#S9YsH%8(F}OH&&SfeyHClW4bvN>~zIqXX`r7 zd&T(s$lczoVL8GT>I`riMGP_ATHluR%hC%?qUJ|QFX_fo!xe5`ahU`!h8Qf z4F@HWHl>gGPp18S7WwC3o$;-M*Z;#rHbDQ?OP)v&@T5U>i$H0LBzo+`SbxyN+rOk7zKS!o4*d z8tK#~-bN$q#3V$v>qsOr1(OCLCDfcG31(OejQLddR6om?!b{o&aE122h){{bFa)l!m@?pjzgH0f+f)Is1d$;r@ez~2!l#f6!4IgQRK`Lr2^VGh8)fhl$d6c qT16dKGrXey)@z~nfMYCJ&RP_(7lWmF3vDKE6d^BD`_wppA^jIhry$h; literal 1906 zcmb7FVQUjX5PhEo|HDB+5@-`p5UjBfs~_@3rTR^ZySqw<7XhV#_@t-Zsc% z^ujZB@#M5sT#6>8%(Eojp?eaH@SWN<`K+iXX^jjo@CpNmV8}5e^C_O=CEp>A9QR`C zq%#w5dFGUipSk#s@RcjEl;aoY9^P@hCdQivtyn22^Vpa4ev3XXo%M=(*R%;W(I+Fq zS8^xgoIDsqvX^Vi!Z*fK5OJItp8>HGY9r{U_jzku#rgCZ(Wo~kZ!2c~|6;VvoD-w6 zrYf%JBjqceHk_{>M14h#xKal$8pG7h>72gJ{|FP8jWKiB0$FmJ`MVb!T7W-X~jIB|JVHfq+!D7rh6oi&wj+BT05T7?Yl+O|7^d9sLitH<_j zj`15ayRw0+GvVm5s@vVf{Ma1Zw)yPdd5rIEi($X=V_cylb_nIFyVuz6oG40ab@gAn z_43-C-3yl=>qMT3HvctmzB+$`kG$RLNg5Np;cNXkbTDJhS8k|xbqil{>L?j~SU1(Z zea1WKy~cgkBMdd$-Nz5r!(;zZ>csvAhZqNY_e)XFom4oqGCXbFP$7Nx>KK2FxqmSK F{{Z4KB+UQ- diff --git a/boa/src/syntax/parser/expression/assignment/mod.rs b/boa/src/syntax/parser/expression/assignment/mod.rs index bbd3666b1fa..fbe7b1dccf6 100644 --- a/boa/src/syntax/parser/expression/assignment/mod.rs +++ b/boa/src/syntax/parser/expression/assignment/mod.rs @@ -8,10 +8,16 @@ //! [spec]: https://tc39.es/ecma262/#sec-assignment-operators mod arrow_function; +mod async_arrow_function; +mod concise_body; mod conditional; mod exponentiation; +mod expression_body; -use self::{arrow_function::ArrowFunction, conditional::ConditionalExpression}; +use self::{ + arrow_function::ArrowFunction, async_arrow_function::AsyncArrowFunction, + concise_body::ConciseBody, conditional::ConditionalExpression, expression_body::ExpressionBody, +}; use crate::syntax::lexer::{Error as LexError, InputElement, TokenKind}; use crate::{ syntax::{ From be0e0b3cd06f04701af65eaa523abbf88ccebb3a Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 12 Jan 2021 22:12:50 +0000 Subject: [PATCH 4/5] Get existing tests passing --- .../expression/assignment/arrow_function.rs | 4 ++-- .../parser/expression/assignment/mod.rs | 22 +++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/boa/src/syntax/parser/expression/assignment/arrow_function.rs b/boa/src/syntax/parser/expression/assignment/arrow_function.rs index a29eed8c948..030e82c5a08 100644 --- a/boa/src/syntax/parser/expression/assignment/arrow_function.rs +++ b/boa/src/syntax/parser/expression/assignment/arrow_function.rs @@ -16,8 +16,8 @@ use crate::{ Punctuator, }, parser::{ - error::{ErrorContext, ParseError, ParseResult}, - function::{FormalParameters, FunctionBody}, + error::{ErrorContext, ParseError}, + function::FormalParameters, statement::BindingIdentifier, AllowAwait, AllowIn, AllowYield, Cursor, TokenParser, }, diff --git a/boa/src/syntax/parser/expression/assignment/mod.rs b/boa/src/syntax/parser/expression/assignment/mod.rs index fbe7b1dccf6..91096ee0a8f 100644 --- a/boa/src/syntax/parser/expression/assignment/mod.rs +++ b/boa/src/syntax/parser/expression/assignment/mod.rs @@ -90,11 +90,25 @@ where // Arrow function match cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?.kind() { - // Async a => {} + // Async a => {} or Async function or Async (a) => {} TokenKind::Keyword(Keyword::Async) => { - return AsyncArrowFunction::new(self.allow_in, self.allow_yield, self.allow_await) - .parse(cursor) - .map(Node::AsyncArrowFunctionDecl); + if let Some(next_token) = cursor.peek(1)? { + match *next_token.kind() { + TokenKind::Identifier(_) => { + return AsyncArrowFunction::new( + self.allow_in, + self.allow_yield, + self.allow_await, + ) + .parse(cursor) + .map(Node::AsyncArrowFunctionDecl); + } + TokenKind::Punctuator(Punctuator::OpenParen) => { + todo!("Async arrow func with () params"); + } + _ => {} + } + } } // a=>{} From 970534e03e7415080fbd2190058102fdccd92efe Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 12 Jan 2021 23:04:23 +0000 Subject: [PATCH 5/5] Add async arrow tests --- .../mod.rs} | 2 + .../assignment/async_arrow_function/tests.rs | 72 +++++++++++++++++++ .../parser/expression/assignment/mod.rs | 6 +- .../syntax/parser/expression/primary/mod.rs | 14 +++- 4 files changed, 90 insertions(+), 4 deletions(-) rename boa/src/syntax/parser/expression/assignment/{async_arrow_function.rs => async_arrow_function/mod.rs} (99%) create mode 100644 boa/src/syntax/parser/expression/assignment/async_arrow_function/tests.rs diff --git a/boa/src/syntax/parser/expression/assignment/async_arrow_function.rs b/boa/src/syntax/parser/expression/assignment/async_arrow_function/mod.rs similarity index 99% rename from boa/src/syntax/parser/expression/assignment/async_arrow_function.rs rename to boa/src/syntax/parser/expression/assignment/async_arrow_function/mod.rs index 975f424bf9f..ec9bf2dd3dd 100644 --- a/boa/src/syntax/parser/expression/assignment/async_arrow_function.rs +++ b/boa/src/syntax/parser/expression/assignment/async_arrow_function/mod.rs @@ -6,6 +6,8 @@ //! //! [mdn]: //! [spec]: https://tc39.es/ecma262/#prod-AsyncArrowFunction +#[cfg(test)] +mod tests; use super::ConciseBody; use crate::{ diff --git a/boa/src/syntax/parser/expression/assignment/async_arrow_function/tests.rs b/boa/src/syntax/parser/expression/assignment/async_arrow_function/tests.rs new file mode 100644 index 00000000000..98197d531f1 --- /dev/null +++ b/boa/src/syntax/parser/expression/assignment/async_arrow_function/tests.rs @@ -0,0 +1,72 @@ +use crate::syntax::{ + ast::node::{ + AsyncArrowFunctionDecl, BinOp, FormalParameter, Identifier, LetDecl, LetDeclList, Node, + Return, + }, + ast::op::NumOp, + parser::tests::check_parser, +}; + +/// Checks an arrow function with expression return. +#[test] +fn check_async_arrow() { + check_parser( + "async (a, b) => { return a + b; }", + vec![AsyncArrowFunctionDecl::new( + vec![ + FormalParameter::new("a", None, false), + FormalParameter::new("b", None, false), + ], + vec![Return::new( + BinOp::new(NumOp::Add, Identifier::from("a"), Identifier::from("b")), + None, + ) + .into()], + ) + .into()], + ); +} + +#[test] +fn check_async_arrow_assignment() { + check_parser( + "let foo = async (a) => { return a };", + vec![LetDeclList::from(vec![LetDecl::new::<_, Option>( + Identifier::from("foo"), + Some( + AsyncArrowFunctionDecl::new( + vec![FormalParameter::new("a", None, false)], + vec![Return::new::, Option<_>>( + Some(Identifier::from("a").into()), + None, + ) + .into()], + ) + .into(), + ), + )]) + .into()], + ); +} + +#[test] +fn check_async_arrow_assignment_noparenthesis() { + check_parser( + "let foo = async a => { return a };", + vec![LetDeclList::from(vec![LetDecl::new::<_, Option>( + Identifier::from("foo"), + Some( + AsyncArrowFunctionDecl::new( + vec![FormalParameter::new("a", None, false)], + vec![Return::new::, Option<_>>( + Some(Identifier::from("a").into()), + None, + ) + .into()], + ) + .into(), + ), + )]) + .into()], + ); +} diff --git a/boa/src/syntax/parser/expression/assignment/mod.rs b/boa/src/syntax/parser/expression/assignment/mod.rs index 91096ee0a8f..64a407508f0 100644 --- a/boa/src/syntax/parser/expression/assignment/mod.rs +++ b/boa/src/syntax/parser/expression/assignment/mod.rs @@ -88,6 +88,7 @@ where let _timer = BoaProfiler::global().start_event("AssignmentExpression", "Parsing"); cursor.set_goal(InputElement::Div); + println!("Assignment expression"); // Arrow function match cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?.kind() { // Async a => {} or Async function or Async (a) => {} @@ -104,9 +105,12 @@ where .map(Node::AsyncArrowFunctionDecl); } TokenKind::Punctuator(Punctuator::OpenParen) => { + println!("OpenParen"); todo!("Async arrow func with () params"); } - _ => {} + _ => { + println!("Async not open Paren / Identifier"); + } } } } diff --git a/boa/src/syntax/parser/expression/primary/mod.rs b/boa/src/syntax/parser/expression/primary/mod.rs index 16183f002ec..57db07fffba 100644 --- a/boa/src/syntax/parser/expression/primary/mod.rs +++ b/boa/src/syntax/parser/expression/primary/mod.rs @@ -82,9 +82,17 @@ where TokenKind::Keyword(Keyword::Function) => { FunctionExpression.parse(cursor).map(Node::from) } - TokenKind::Keyword(Keyword::Async) => AsyncFunctionExpression::new(self.allow_yield) - .parse(cursor) - .map(Node::from), + TokenKind::Keyword(Keyword::Async) => { + println!("Keyword async"); + match cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?.kind() { + TokenKind::Keyword(Keyword::Function) => { + AsyncFunctionExpression::new(self.allow_yield) + .parse(cursor) + .map(Node::from) + } + _ => Err(ParseError::unexpected(tok.clone(), "primary expression")), + } + } TokenKind::Punctuator(Punctuator::OpenParen) => { cursor.set_goal(InputElement::RegExp); let expr =