]> git.kaiwu.me - njs.git/commitdiff
Added async support for object initializer.
authorAlexander Borisov <alexander.borisov@nginx.com>
Thu, 2 Sep 2021 16:33:32 +0000 (19:33 +0300)
committerAlexander Borisov <alexander.borisov@nginx.com>
Thu, 2 Sep 2021 16:33:32 +0000 (19:33 +0300)
src/njs_async.c
src/njs_generator.c
src/njs_lexer.h
src/njs_parser.c
src/test/njs_unit_test.c

index 97ce87ff17f0b86ed99a5d0e06797b1297d14309..f27c2eebf8984a2799a31e60b690a9893c9e5f71 100644 (file)
@@ -172,13 +172,6 @@ njs_async_context_free(njs_vm_t *vm, njs_async_ctx_t *ctx)
 
 static const njs_object_prop_t  njs_async_constructor_properties[] =
 {
-    {
-        .type = NJS_PROPERTY,
-        .name = njs_string("name"),
-        .value = njs_string("AsyncFunction"),
-        .configurable = 1,
-    },
-
     {
         .type = NJS_PROPERTY,
         .name = njs_string("length"),
@@ -202,6 +195,13 @@ const njs_object_init_t  njs_async_constructor_init = {
 
 static const njs_object_prop_t  njs_async_prototype_properties[] =
 {
+    {
+        .type = NJS_PROPERTY,
+        .name = njs_string("name"),
+        .value = njs_string("AsyncFunction"),
+        .configurable = 1,
+    },
+
     {
         .type = NJS_PROPERTY,
         .name = njs_wellknown_symbol(NJS_SYMBOL_TO_STRING_TAG),
index eb32411ceef2c7fec11ee720919912e8c87a3e47..f2e3bde9e430176b21f7c2cbc079ca655b9bc5e7 100644 (file)
@@ -666,6 +666,7 @@ njs_generate(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node)
         return njs_generate_function_expression(vm, generator, node);
 
     case NJS_TOKEN_FUNCTION:
+    case NJS_TOKEN_ASYNC_FUNCTION:
         return njs_generate_function(vm, generator, node);
 
     case NJS_TOKEN_REGEXP:
@@ -3100,7 +3101,7 @@ njs_generate_function(njs_vm_t *vm, njs_generator_t *generator,
     njs_generate_code(generator, njs_vmcode_function_t, function,
                       NJS_VMCODE_FUNCTION, 1, node);
     function->lambda = lambda;
-    function->async = 0;
+    function->async = (node->token_type == NJS_TOKEN_ASYNC_FUNCTION);
 
     node->index = njs_generate_object_dest_index(vm, generator, node);
     if (njs_slow_path(node->index == NJS_INDEX_ERROR)) {
index b20c5934b45ad81de19ec66120293d1a97a7f698..e3bd1dc8dfdf4c8c68a9bcdf42fa7c398d372f61 100644 (file)
@@ -148,6 +148,7 @@ typedef enum {
     NJS_TOKEN_ARGUMENT,
     NJS_TOKEN_RETURN,
 
+    NJS_TOKEN_ASYNC_FUNCTION,
     NJS_TOKEN_ASYNC_FUNCTION_DECLARATION,
     NJS_TOKEN_ASYNC_FUNCTION_EXPRESSION,
 
index 8ea51c26ec7120b7085495971e3cfa02cf141a73..cc36632076b593a92cf139ca246f3c643417999a 100644 (file)
@@ -58,6 +58,10 @@ static njs_int_t njs_parser_property_definition_after(njs_parser_t *parser,
     njs_lexer_token_t *token, njs_queue_link_t *current);
 static njs_int_t njs_parser_computed_property_name_after(njs_parser_t *parser,
     njs_lexer_token_t *token, njs_queue_link_t *current);
+static njs_int_t njs_parser_computed_property_async_after(njs_parser_t *parser,
+    njs_lexer_token_t *token, njs_queue_link_t *current);
+static njs_int_t njs_parser_computed_property_name_handler(njs_parser_t *parser,
+    njs_lexer_token_t *token, njs_queue_link_t *current, njs_bool_t async);
 
 static njs_int_t njs_parser_initializer(njs_parser_t *parser,
     njs_lexer_token_t *token, njs_queue_link_t *current);
@@ -1931,6 +1935,38 @@ njs_parser_property_definition(njs_parser_t *parser, njs_lexer_token_t *token,
     case NJS_TOKEN_ELLIPSIS:
         return njs_parser_not_supported(parser, token);
 
+    case NJS_TOKEN_ASYNC:
+        token = njs_lexer_peek_token(parser->lexer, token, 0);
+        if (token == NULL) {
+            return NJS_ERROR;
+        }
+
+        if (token->type == NJS_TOKEN_OPEN_BRACKET) {
+            njs_lexer_consume_token(parser->lexer, 2);
+
+            njs_parser_next(parser, njs_parser_assignment_expression);
+
+            return njs_parser_after(parser, current, temp, 1,
+                                    njs_parser_computed_property_async_after);
+        }
+
+        if (!njs_lexer_token_is_identifier_name(token)) {
+            return njs_parser_failed(parser);
+        }
+
+        next = njs_lexer_peek_token(parser->lexer, token, 0);
+        if (next == NULL) {
+            return NJS_ERROR;
+        }
+
+        if (next->type == NJS_TOKEN_OPEN_PARENTHESIS) {
+            goto method_definition;
+        }
+
+        njs_lexer_consume_token(parser->lexer, 1);
+
+        return njs_parser_failed(parser);
+
     default:
         if (!njs_lexer_token_is_identifier_name(token)) {
             return njs_parser_reject(parser);
@@ -2044,7 +2080,24 @@ static njs_int_t
 njs_parser_computed_property_name_after(njs_parser_t *parser,
     njs_lexer_token_t *token, njs_queue_link_t *current)
 {
-    njs_parser_node_t  *expr;
+    return njs_parser_computed_property_name_handler(parser, token, current, 0);
+}
+
+
+static njs_int_t
+njs_parser_computed_property_async_after(njs_parser_t *parser,
+    njs_lexer_token_t *token, njs_queue_link_t *current)
+{
+    return njs_parser_computed_property_name_handler(parser, token, current, 1);
+}
+
+
+static njs_int_t
+njs_parser_computed_property_name_handler(njs_parser_t *parser,
+    njs_lexer_token_t *token, njs_queue_link_t *current, njs_bool_t async)
+{
+    njs_token_type_t   type;
+    njs_parser_node_t  *expr, *target;
 
     if (token->type != NJS_TOKEN_CLOSE_BRACKET) {
         return njs_parser_failed(parser);
@@ -2057,20 +2110,24 @@ njs_parser_computed_property_name_after(njs_parser_t *parser,
         return NJS_ERROR;
     }
 
+    target = parser->target;
+
     /*
      * For further identification.
      * In njs_parser_property_definition_after() index will be reset to zero.
      */
     parser->node->index = NJS_TOKEN_OPEN_BRACKET;
 
-    parser->target->right = parser->node;
+    target->right = parser->node;
 
-    if (token->type == NJS_TOKEN_COLON) {
+    if (!async && token->type == NJS_TOKEN_COLON) {
         return njs_parser_property_name(parser, current, 1);
 
     /* MethodDefinition */
     } else if (token->type == NJS_TOKEN_OPEN_PARENTHESIS) {
-        expr = njs_parser_node_new(parser, NJS_TOKEN_FUNCTION);
+        type = (async) ? NJS_TOKEN_ASYNC_FUNCTION : NJS_TOKEN_FUNCTION;
+
+        expr = njs_parser_node_new(parser, type);
         if (expr == NULL) {
             return NJS_ERROR;
         }
@@ -7196,9 +7253,23 @@ static njs_int_t
 njs_parser_method_definition(njs_parser_t *parser, njs_lexer_token_t *token,
     njs_queue_link_t *current)
 {
+    njs_token_type_t   type;
     njs_lexer_token_t  *next;
     njs_parser_node_t  *expr;
 
+    type = NJS_TOKEN_FUNCTION;
+
+    if (token->type == NJS_TOKEN_ASYNC) {
+        njs_lexer_consume_token(parser->lexer, 1);
+
+        token = njs_lexer_token(parser->lexer, 0);
+        if (token == NULL) {
+            return NJS_ERROR;
+        }
+
+        type = NJS_TOKEN_ASYNC_FUNCTION;
+    }
+
     switch (token->type) {
     /* PropertyName */
     case NJS_TOKEN_STRING:
@@ -7225,7 +7296,7 @@ njs_parser_method_definition(njs_parser_t *parser, njs_lexer_token_t *token,
         return njs_parser_failed(parser);
     }
 
-    expr = njs_parser_node_new(parser, NJS_TOKEN_FUNCTION);
+    expr = njs_parser_node_new(parser, type);
     if (expr == NULL) {
         return NJS_ERROR;
     }
@@ -7453,6 +7524,9 @@ njs_parser_function_lambda(njs_parser_t *parser,
         return NJS_ERROR;
     }
 
+    parser->scope->async =
+                        (parser->node->token_type == NJS_TOKEN_ASYNC_FUNCTION);
+
     parser->node = NULL;
     parser->target = expr;
 
index 3e0d4dcc86949ae664c28f8b33704d5f4aad0b43..5dd2318c66b99dfce62849b9f3c38d7e1d178b76 100644 (file)
@@ -20520,6 +20520,12 @@ static njs_unit_test_t  njs_test[] =
 
     { njs_str("async function af() {await encrypt({},}"),
       njs_str("SyntaxError: Unexpected token \"}\" in 1") },
+
+    { njs_str("let x = {async af() {await Promise.resolve(1)}}; x.af"),
+      njs_str("[object AsyncFunction]") },
+
+    { njs_str("let name = 'af', x = {async [name]() {await Promise.resolve(1)}}; x.af"),
+      njs_str("[object AsyncFunction]") },
 };