[njs] Added Object shorthand methods and computed property names.

Dmitry Volyntsev xeioex at nginx.com
Fri Jul 19 21:31:14 UTC 2019


details:   https://hg.nginx.org/njs/rev/97ab91a7c7f5
branches:  
changeset: 1064:97ab91a7c7f5
user:      hongzhidao <hongzhidao at gmail.com>
date:      Tue Jul 02 22:24:11 2019 -0400
description:
Added Object shorthand methods and computed property names.

This closes #182 issue on Github.

diffstat:

 njs/njs_parser.c          |   4 +--
 njs/njs_parser.h          |   2 +
 njs/njs_parser_terminal.c |  57 ++++++++++++++++++++++++++++++++++++++++++----
 njs/njs_vm.c              |   5 +---
 njs/test/njs_unit_test.c  |  36 ++++++++++++++++++++++++++++-
 5 files changed, 89 insertions(+), 15 deletions(-)

diffs (190 lines):

diff -r 9da8ebc3dc07 -r 97ab91a7c7f5 njs/njs_parser.c
--- a/njs/njs_parser.c	Fri Jul 19 23:27:53 2019 +0300
+++ b/njs/njs_parser.c	Tue Jul 02 22:24:11 2019 -0400
@@ -24,8 +24,6 @@ static njs_token_t njs_parser_labelled_s
     njs_parser_t *parser);
 static njs_token_t njs_parser_function_declaration(njs_vm_t *vm,
     njs_parser_t *parser);
-static njs_token_t njs_parser_function_lambda(njs_vm_t *vm,
-    njs_parser_t *parser, njs_function_lambda_t *lambda, njs_token_t token);
 static njs_token_t njs_parser_lambda_arguments(njs_vm_t *vm,
     njs_parser_t *parser, njs_function_lambda_t *lambda, njs_index_t index,
     njs_token_t token);
@@ -757,7 +755,7 @@ njs_parser_function_expression(njs_vm_t 
 }
 
 
-static njs_token_t
+njs_token_t
 njs_parser_function_lambda(njs_vm_t *vm, njs_parser_t *parser,
     njs_function_lambda_t *lambda, njs_token_t token)
 {
diff -r 9da8ebc3dc07 -r 97ab91a7c7f5 njs/njs_parser.h
--- a/njs/njs_parser.h	Fri Jul 19 23:27:53 2019 +0300
+++ b/njs/njs_parser.h	Tue Jul 02 22:24:11 2019 -0400
@@ -95,6 +95,8 @@ njs_token_t njs_parser_template_literal(
 njs_parser_node_t *njs_parser_argument(njs_vm_t *vm, njs_parser_t *parser,
     njs_parser_node_t *expr, njs_index_t index);
 nxt_int_t njs_parser_string_create(njs_vm_t *vm, njs_value_t *value);
+njs_token_t njs_parser_function_lambda(njs_vm_t *vm, njs_parser_t *parser,
+    njs_function_lambda_t *lambda, njs_token_t token);
 njs_token_t njs_parser_lambda_statements(njs_vm_t *vm, njs_parser_t *parser,
     njs_token_t token);
 njs_variable_t *njs_variable_resolve(njs_vm_t *vm, njs_parser_node_t *node);
diff -r 9da8ebc3dc07 -r 97ab91a7c7f5 njs/njs_parser_terminal.c
--- a/njs/njs_parser_terminal.c	Fri Jul 19 23:27:53 2019 +0300
+++ b/njs/njs_parser_terminal.c	Tue Jul 02 22:24:11 2019 -0400
@@ -480,12 +480,13 @@ njs_parser_builtin(njs_vm_t *vm, njs_par
 static njs_token_t
 njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj)
 {
-    uint32_t           hash, token_line;
-    nxt_int_t          ret;
-    nxt_str_t          name;
-    njs_token_t        token, prop_token;
-    njs_lexer_t        *lexer;
-    njs_parser_node_t  *object, *property, *expression;
+    uint32_t               hash, token_line;
+    nxt_int_t              ret;
+    nxt_str_t              name;
+    njs_token_t            token, prop_token;
+    njs_lexer_t            *lexer;
+    njs_parser_node_t      *object, *property, *expression;
+    njs_function_lambda_t  *lambda;
 
     lexer = parser->lexer;
 
@@ -513,6 +514,26 @@ njs_parser_object(njs_vm_t *vm, njs_pars
         case NJS_TOKEN_CLOSE_BRACE:
             goto done;
 
+        case NJS_TOKEN_OPEN_BRACKET:
+            token = njs_parser_token(vm, parser);
+            if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+                return token;
+            }
+
+            if (token == NJS_TOKEN_CLOSE_BRACKET) {
+                return NJS_TOKEN_ILLEGAL;
+            }
+
+            token = njs_parser_assignment_expression(vm, parser, token);
+            if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+                return token;
+            }
+
+            property = parser->node;
+
+            token = njs_parser_match(vm, parser, token, NJS_TOKEN_CLOSE_BRACKET);
+            break;
+
         case NJS_TOKEN_NUMBER:
         case NJS_TOKEN_STRING:
         case NJS_TOKEN_ESCAPE_STRING:
@@ -576,6 +597,30 @@ njs_parser_object(njs_vm_t *vm, njs_pars
             expression = parser->node;
             break;
 
+        case NJS_TOKEN_OPEN_PARENTHESIS:
+            expression = njs_parser_node_new(vm, parser,
+                                             NJS_TOKEN_FUNCTION_EXPRESSION);
+            if (nxt_slow_path(expression == NULL)) {
+                return NJS_TOKEN_ERROR;
+            }
+
+            expression->token_line = njs_parser_token_line(parser);
+            parser->node = expression;
+
+            lambda = njs_function_lambda_alloc(vm, 0);
+            if (nxt_slow_path(lambda == NULL)) {
+                return NJS_TOKEN_ERROR;
+            }
+
+            expression->u.value.data.u.lambda = lambda;
+
+            token = njs_parser_function_lambda(vm, parser, lambda, token);
+            if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+                return token;
+            }
+
+            break;
+
         default:
             return NJS_TOKEN_ILLEGAL;
         }
diff -r 9da8ebc3dc07 -r 97ab91a7c7f5 njs/njs_vm.c
--- a/njs/njs_vm.c	Fri Jul 19 23:27:53 2019 +0300
+++ b/njs/njs_vm.c	Tue Jul 02 22:24:11 2019 -0400
@@ -478,11 +478,8 @@ njs_vmcode_property_init(njs_vm_t *vm, n
         break;
 
     case NJS_OBJECT:
-        ret = njs_primitive_value_to_string(vm, &name, property);
+        ret = njs_value_to_string(vm, &name, property);
         if (nxt_slow_path(ret != NXT_OK)) {
-            njs_internal_error(vm, "failed conversion of type \"%s\" "
-                               "to string while property initialization",
-                               njs_type_string(property->type));
             return NXT_ERROR;
         }
 
diff -r 9da8ebc3dc07 -r 97ab91a7c7f5 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Fri Jul 19 23:27:53 2019 +0300
+++ b/njs/test/njs_unit_test.c	Tue Jul 02 22:24:11 2019 -0400
@@ -3126,7 +3126,7 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("var x = { a: 1 }, b = delete x.a; x.a +' '+ b"),
       nxt_string("undefined true") },
 
-    /* Shorthand Object literals. */
+    /* Object shorthand property. */
 
     { nxt_string("var a = 1; njs.dump({a})"),
       nxt_string("{a:1}") },
@@ -3173,6 +3173,38 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("delete undefined"),
       nxt_string("SyntaxError: Delete of an unqualified identifier in 1") },
 
+    /* Object shorthand methods. */
+
+    { nxt_string("var o = {m(){}}; new o.m();"),
+      nxt_string("TypeError: function is not a constructor") },
+
+    { nxt_string("var o = {sum(a, b){return a + b;}}; o.sum(1, 2)"),
+      nxt_string("3") },
+
+    /* Object computed property. */
+
+    { nxt_string("var o = { [0]: 1, [-0]: 2 }; o[0];"),
+      nxt_string("2") },
+
+    { nxt_string("var k = 'abc'.split('');var o = {[k[0]]: 'baz'}; o.a"),
+      nxt_string("baz") },
+
+    { nxt_string("var k = {}; var o = {[k]() {return 'baz'}}; o[k]()"),
+      nxt_string("baz") },
+
+    { nxt_string("njs.dump({[{toString(){return 'xx'}}]:1})"),
+      nxt_string("{xx:1}") },
+
+    { nxt_string("var o = {}; Object.defineProperty(o, 'toString', {value:()=>'xx'});"
+                 "njs.dump({[o]:1})"),
+      nxt_string("{xx:1}") },
+
+    { nxt_string("({[{toString(){return {}}}]:1})"),
+      nxt_string("TypeError: Cannot convert object to primitive value") },
+
+    { nxt_string("var o = { [new Number(12345)]: 1000 }; o[12345]"),
+      nxt_string("1000") },
+
     /* ES5FIX: "SyntaxError". */
 
     { nxt_string("delete NaN"),
@@ -3248,7 +3280,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("4") },
 
     { nxt_string("({[]:1})"),
-      nxt_string("SyntaxError: Unexpected token \"[\" in 1") },
+      nxt_string("SyntaxError: Unexpected token \"]\" in 1") },
 
     { nxt_string("({'AB\\ncd':1})['AB\\ncd']"),
       nxt_string("1") },


More information about the nginx-devel mailing list