From 49f0d461e125071330f7d45a4d8b44aeb8734b0c Mon Sep 17 00:00:00 2001
From: luozijun <luozijun.assistant@gmail.com>
Date: Wed, 27 Feb 2019 05:09:22 +0800
Subject: [PATCH] Support async keyword

---
 ratel-transformer/src/es2015/arrow.rs |  1 +
 ratel/src/ast/function.rs             |  1 +
 ratel/src/astgen/expression.rs        |  7 +++++
 ratel/src/astgen/function.rs          |  1 +
 ratel/src/astgen/statement.rs         |  3 ++
 ratel/src/parser/expression.rs        |  2 ++
 ratel/src/parser/function.rs          | 41 ++++++++++++++++++++++-----
 ratel/src/parser/mod.rs               |  5 +++-
 ratel/src/parser/statement.rs         | 14 +++++----
 9 files changed, 62 insertions(+), 13 deletions(-)

diff --git a/ratel-transformer/src/es2015/arrow.rs b/ratel-transformer/src/es2015/arrow.rs
index c01ea7b..e8e4f71 100644
--- a/ratel-transformer/src/es2015/arrow.rs
+++ b/ratel-transformer/src/es2015/arrow.rs
@@ -35,6 +35,7 @@ impl<'ast> Visitor<'ast> for TransformArrow<'ast> {
         self.ctx.swap(*ptr, Function {
             name: OptionalName::empty(),
             generator: false,
+            is_async: false,
             params: node.params,
             body,
         });
diff --git a/ratel/src/ast/function.rs b/ratel/src/ast/function.rs
index ce75f8b..8c183c2 100644
--- a/ratel/src/ast/function.rs
+++ b/ratel/src/ast/function.rs
@@ -66,6 +66,7 @@ impl<'ast> From<Option<IdentifierNode<'ast>>> for OptionalName<'ast> {
 pub struct Function<'ast, N: Name<'ast>> {
     pub name: N,
     pub generator: bool,
+    pub is_async: bool,
     pub params: PatternList<'ast>,
     pub body: BlockNode<'ast, Statement<'ast>>,
 }
diff --git a/ratel/src/astgen/expression.rs b/ratel/src/astgen/expression.rs
index f9732ee..f1b7289 100644
--- a/ratel/src/astgen/expression.rs
+++ b/ratel/src/astgen/expression.rs
@@ -927,6 +927,7 @@ mod test {
                                         "value": {
                                             "type": "FunctionExpression",
                                             "generator": false,
+                                            "is_async": false,
                                             "id": null,
                                             "params": [
                                                 {
@@ -974,6 +975,7 @@ mod test {
             {
               "type": "FunctionDeclaration",
               "generator": false,
+              "is_async": false,
               "id": {
                 "type": "Identifier",
                 "name": "Handler",
@@ -1095,6 +1097,7 @@ mod test {
                 {
                     "type": "FunctionDeclaration",
                     "generator": false,
+                    "is_async": false,
                     "id": {
                         "type": "Identifier",
                         "name": "foo",
@@ -1376,6 +1379,7 @@ mod test {
                 {
                     "type": "FunctionDeclaration",
                     "generator": false,
+                    "is_async": false,
                     "id": {
                         "type": "Identifier",
                         "name": "foo",
@@ -1403,6 +1407,7 @@ mod test {
                 {
                     "type": "FunctionDeclaration",
                     "generator": false,
+                    "is_async": false,
                     "id": {
                         "type": "Identifier",
                         "name": "foo",
@@ -1538,6 +1543,7 @@ mod test {
                             "value": {
                                 "type": "FunctionExpression",
                                 "generator": false,
+                                "is_async": false,
                                 "id": null,
                                 "params": [],
                                 "body": {
@@ -1593,6 +1599,7 @@ mod test {
                             "value": {
                                 "type": "FunctionExpression",
                                 "generator": false,
+                                "is_async": false,
                                 "id": null,
                                 "params": [],
                                 "body": {
diff --git a/ratel/src/astgen/function.rs b/ratel/src/astgen/function.rs
index 63bb687..7caf961 100644
--- a/ratel/src/astgen/function.rs
+++ b/ratel/src/astgen/function.rs
@@ -122,6 +122,7 @@ where
     {
         self.in_loc(serializer, N::IN_FUNCTION, 3, |state| {
             state.serialize_field("generator", &self.generator)?;
+            state.serialize_field("is_async", &self.is_async)?;
             state.serialize_field("id", &self.name)?;
             state.serialize_field("params", &self.params)?;
             state.serialize_field("body", &self.body)
diff --git a/ratel/src/astgen/statement.rs b/ratel/src/astgen/statement.rs
index 43b1f93..2e99ded 100644
--- a/ratel/src/astgen/statement.rs
+++ b/ratel/src/astgen/statement.rs
@@ -946,6 +946,7 @@ mod test {
                 {
                     "type": "FunctionDeclaration",
                     "generator": false,
+                    "is_async": false,
                     "id": {
                         "type": "Identifier",
                         "name": "foo",
@@ -973,6 +974,7 @@ mod test {
                 {
                     "type": "FunctionDeclaration",
                     "generator": true,
+                    "is_async": false,
                     "id": {
                         "type": "Identifier",
                         "name": "foo",
@@ -1000,6 +1002,7 @@ mod test {
                 {
                     "type": "FunctionDeclaration",
                     "generator": false,
+                    "is_async": false,
                     "id": {
                         "type": "Identifier",
                         "name": "foo",
diff --git a/ratel/src/parser/expression.rs b/ratel/src/parser/expression.rs
index 7b3aebc..4d214a1 100644
--- a/ratel/src/parser/expression.rs
+++ b/ratel/src/parser/expression.rs
@@ -1033,6 +1033,7 @@ mod test {
         let expected = Function {
             name: None.into(),
             generator: false,
+            is_async: false,
             params: NodeList::empty(),
             body: mock.empty_block()
         };
@@ -1048,6 +1049,7 @@ mod test {
         let expected = Function {
             name: mock.name("foo"),
             generator: false,
+            is_async: false,
             params: NodeList::empty(),
             body: mock.empty_block()
         };
diff --git a/ratel/src/parser/function.rs b/ratel/src/parser/function.rs
index a9bcbdd..57ee5bb 100644
--- a/ratel/src/parser/function.rs
+++ b/ratel/src/parser/function.rs
@@ -59,31 +59,40 @@ impl<'ast> Parse<'ast> for Pattern<'ast> {
     }
 }
 
-impl<'ast, N> Parse<'ast> for Function<'ast, N> where
+impl<'ast, N> Function<'ast, N> where
     N: Name<'ast> + Parse<'ast, Output = N>,
 {
-    type Output = Self;
-
     #[inline]
-    fn parse(par: &mut Parser<'ast>) -> Self::Output {
-        let generator: bool = if par.lexer.token == OperatorMultiplication {
+    pub fn with_async_flag(par: &mut Parser<'ast>, is_async: bool) -> Function<'ast, N> {
+        let is_generator: bool = if par.lexer.token == OperatorMultiplication {
             par.lexer.consume();
             true
         } else {
             false
         };
-
         let name = N::parse(par);
 
         Function {
             name,
-            generator,
+            generator: is_generator,
+            is_async,
             params: par.params(),
             body: par.block(),
         }
     }
 }
 
+impl<'ast, N> Parse<'ast> for Function<'ast, N> where
+    N: Name<'ast> + Parse<'ast, Output = N>,
+{
+    type Output = Self;
+
+    #[inline]
+    fn parse(par: &mut Parser<'ast>) -> Self::Output {
+        Self::with_async_flag(par, false)
+    }
+}
+
 impl<'ast, N> Parse<'ast> for Node<'ast, Function<'ast, N>> where
     N: Name<'ast> + Parse<'ast, Output = N>,
 {
@@ -400,6 +409,7 @@ mod test {
             Function {
                 name: mock.name("foo"),
                 generator: false,
+                is_async: false,
                 params: NodeList::empty(),
                 body: mock.empty_block(),
             }
@@ -418,6 +428,7 @@ mod test {
                 Function {
                     name: mock.name("foo"),
                     generator: true,
+                    is_async: false,
                     params: NodeList::empty(),
                     body: mock.empty_block(),
                 }
@@ -434,6 +445,7 @@ mod test {
                 Function {
                     name: mock.name("foo"),
                     generator: true,
+                    is_async: false,
                     params: NodeList::empty(),
                     body: mock.empty_block(),
                 }
@@ -450,6 +462,7 @@ mod test {
                 Function {
                     name: mock.name("foo"),
                     generator: true,
+                    is_async: false,
                     params: NodeList::empty(),
                     body: mock.empty_block(),
                 }
@@ -468,6 +481,7 @@ mod test {
             Function {
                 name: mock.name("foo"),
                 generator: false,
+                is_async: false,
                 params: mock.list([
                     Pattern::Identifier("bar"),
                     Pattern::Identifier("baz"),
@@ -488,6 +502,7 @@ mod test {
             Function {
                 name: mock.name("foo"),
                 generator: false,
+                is_async: false,
                 params: NodeList::empty(),
                 body: mock.block([
                     mock.ptr("bar"),
@@ -508,6 +523,7 @@ mod test {
             Function {
                 name: mock.name("foo"),
                 generator: false,
+                is_async: false,
                 params: mock.list([
                     Pattern::AssignmentPattern {
                         left: mock.ptr(Pattern::Identifier("a")),
@@ -541,6 +557,7 @@ mod test {
             Function {
                 name: mock.name("foo"),
                 generator: false,
+                is_async: false,
                 params: mock.list([
                     Pattern::Identifier("a"),
                     Pattern::Identifier("b"),
@@ -569,6 +586,7 @@ mod test {
             Function {
                 name: mock.name("foo"),
                 generator: false,
+                is_async: false,
                 params: mock.list([
                     Pattern::RestElement {
                         argument: mock.ptr("rest"),
@@ -589,6 +607,7 @@ mod test {
             Function {
                 name: mock.name("foo"),
                 generator: false,
+                is_async: false,
                 params: mock.list([
                     Pattern::Identifier("a"),
                     Pattern::AssignmentPattern {
@@ -667,6 +686,7 @@ mod test {
                         value: mock.ptr(Function {
                             name: EmptyName,
                             generator: false,
+                            is_async: false,
                             params: mock.list([
                                 Pattern::Identifier("bar"),
                                 Pattern::Identifier("baz")
@@ -716,6 +736,7 @@ mod test {
                         value: mock.ptr(Function {
                             name: EmptyName,
                             generator: false,
+                            is_async: false,
                             params: mock.list([
                                 Pattern::Identifier("bar"),
                                 Pattern::Identifier("baz")
@@ -732,6 +753,7 @@ mod test {
                         value: mock.ptr(Function {
                             name: EmptyName,
                             generator: false,
+                            is_async: false,
                             params: mock.list([
                                 Pattern::Identifier("moon")
                             ]),
@@ -747,6 +769,7 @@ mod test {
                         value: mock.ptr(Function {
                             name: EmptyName,
                             generator: false,
+                            is_async: false,
                             params: NodeList::empty(),
                             body: mock.empty_block()
                         })
@@ -758,6 +781,7 @@ mod test {
                         value: mock.ptr(Function {
                             name: EmptyName,
                             generator: false,
+                            is_async: false,
                             params: NodeList::empty(),
                             body: mock.empty_block()
                         })
@@ -769,6 +793,7 @@ mod test {
                         value: mock.ptr(Function {
                             name: EmptyName,
                             generator: false,
+                            is_async: false,
                             params: NodeList::empty(),
                             body: mock.empty_block()
                         })
@@ -867,6 +892,7 @@ mod test {
                         value: mock.ptr(Function {
                             name: EmptyName,
                             generator: false,
+                            is_async: false,
                             params: mock.list([
                                 Pattern::Identifier("foo")
                             ]),
@@ -880,6 +906,7 @@ mod test {
                         value: mock.ptr(Function {
                             name: EmptyName,
                             generator: false,
+                            is_async: false,
                             params: mock.list([
                                 Pattern::Identifier("bar")
                             ]),
diff --git a/ratel/src/parser/mod.rs b/ratel/src/parser/mod.rs
index 9b99d1a..c5566d0 100644
--- a/ratel/src/parser/mod.rs
+++ b/ratel/src/parser/mod.rs
@@ -171,7 +171,10 @@ impl<'ast> Parser<'ast> {
                 self.lexer.consume();
                 ident
             },
-            _ => self.error()
+            _ => {
+                println!("eeeee:.....", );
+                self.error()
+            }
         }
     }
 
diff --git a/ratel/src/parser/statement.rs b/ratel/src/parser/statement.rs
index 30ab6c3..1e2124e 100644
--- a/ratel/src/parser/statement.rs
+++ b/ratel/src/parser/statement.rs
@@ -80,7 +80,7 @@ create_handlers! {
     const BRK  = |par| par.break_statement();
     const THRW = |par| par.throw_statement();
     const CONT = |par| par.continue_statement();
-    const FUNC = |par| par.function_statement();
+    const FUNC = |par| par.function_statement_with_async(false);
     const CLAS = |par| par.class_statement();
     const IF   = |par| par.if_statement();
     const WHL  = |par| par.while_statement();
@@ -190,9 +190,12 @@ impl<'ast> Parser<'ast> {
     pub fn labeled_or_expression_statement(&mut self) -> StatementNode<'ast> {
         let label = self.lexer.token_as_str();
         let (start, end) = self.lexer.loc();
-
+        
         self.lexer.consume();
-
+        if label == "async" && self.lexer.token == Function {
+            return self.function_statement_with_async(true);
+        }
+        
         if self.lexer.token == Colon {
             self.lexer.consume();
 
@@ -213,9 +216,9 @@ impl<'ast> Parser<'ast> {
     }
 
     #[inline]
-    pub fn function_statement(&mut self) -> StatementNode<'ast> {
+    pub fn function_statement_with_async(&mut self, is_async: bool) -> StatementNode<'ast> {
         let start = self.lexer.start_then_consume();
-        let function = Function::parse(self);
+        let function = Function::with_async_flag(self, is_async);
 
         self.alloc_at_loc(start, function.body.end, function)
     }
@@ -1158,6 +1161,7 @@ mod test {
             Function {
                 name: mock.name("foo"),
                 generator: false,
+                is_async: false,
                 params: NodeList::empty(),
                 body: mock.empty_block(),
             }