From: Dmitry Volyntsev Date: Mon, 11 Feb 2019 15:15:43 +0000 (+0300) Subject: Added support for shorthand property names for Object literals. X-Git-Tag: 0.2.8~28 X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=113c228339fe7bc009edfb40a42b5fe1e078427f;p=njs.git Added support for shorthand property names for Object literals. This closes #87 issue on Github. --- diff --git a/njs/njs_lexer.c b/njs/njs_lexer.c index acf4400b..469499bd 100644 --- a/njs/njs_lexer.c +++ b/njs/njs_lexer.c @@ -459,7 +459,8 @@ njs_lexer_next_token(njs_lexer_t *lexer) static njs_token_t njs_lexer_word(njs_lexer_t *lexer, u_char c) { - u_char *p; + u_char *p; + njs_token_t token; /* TODO: UTF-8 */ @@ -498,11 +499,14 @@ njs_lexer_word(njs_lexer_t *lexer, u_char c) lexer->start = p; lexer->text.length = p - lexer->text.start; + token = njs_lexer_keyword(lexer); + if (lexer->property) { + lexer->property_token = token; return NJS_TOKEN_NAME; } - return njs_lexer_keyword(lexer); + return token; } diff --git a/njs/njs_parser.c b/njs/njs_parser.c index 31c9c725..7141c801 100644 --- a/njs/njs_parser.c +++ b/njs/njs_parser.c @@ -2215,13 +2215,29 @@ njs_parser_builtin(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node, } +/* + * ES6: 12.2.6 Object Initializer + * Supported syntax: + * PropertyDefinition: + * PropertyName : AssignmentExpression + * IdentifierReference + * PropertyName: + * IdentifierName, StringLiteral, NumericLiteral. + */ static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj) { + uint32_t hash; + nxt_str_t name; njs_token_t token; - njs_parser_node_t *stmt, *assign, *object, *propref, *left; + njs_lexer_t *lexer; + njs_parser_node_t *stmt, *assign, *object, *propref, *left, *expression; left = NULL; + lexer = parser->lexer; + + /* GCC and Clang complain about uninitialized hash. */ + hash = 0; object = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT_VALUE); if (nxt_slow_path(object == NULL)) { @@ -2233,12 +2249,17 @@ njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj) for ( ;; ) { token = njs_parser_property_token(vm, parser); + name.start = NULL; + switch (token) { case NJS_TOKEN_CLOSE_BRACE: return njs_parser_token(parser); case NJS_TOKEN_NAME: + name = lexer->text; + hash = lexer->key_hash; + token = njs_parser_token(parser); break; @@ -2264,14 +2285,29 @@ njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj) propref->left = object; propref->right = parser->node; - token = njs_parser_match(vm, parser, token, NJS_TOKEN_COLON); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; - } + if (name.start != NULL + && (token == NJS_TOKEN_COMMA || token == NJS_TOKEN_CLOSE_BRACE) + && lexer->property_token != NJS_TOKEN_THIS + && lexer->property_token != NJS_TOKEN_GLOBAL_THIS) + { + expression = njs_parser_reference(vm, parser, lexer->property_token, + &name, hash); + if (nxt_slow_path(expression == NULL)) { + return NJS_TOKEN_ERROR; + } - token = njs_parser_assignment_expression(vm, parser, token); - if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { - return token; + } else { + token = njs_parser_match(vm, parser, token, NJS_TOKEN_COLON); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + token = njs_parser_assignment_expression(vm, parser, token); + if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { + return token; + } + + expression = parser->node; } assign = njs_parser_node_new(vm, parser, NJS_TOKEN_ASSIGNMENT); @@ -2281,7 +2317,7 @@ njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj) assign->u.operation = njs_vmcode_move; assign->left = propref; - assign->right = parser->node; + assign->right = expression; stmt = njs_parser_node_new(vm, parser, NJS_TOKEN_STATEMENT); if (nxt_slow_path(stmt == NULL)) { diff --git a/njs/njs_parser.h b/njs/njs_parser.h index a2b536fd..63b9d948 100644 --- a/njs/njs_parser.h +++ b/njs/njs_parser.h @@ -210,7 +210,10 @@ typedef enum { typedef struct { njs_token_t token:16; njs_token_t prev_token:16; + uint8_t property; /* 1 bit */ + njs_token_t property_token:16; + uint32_t key_hash; uint32_t token_line; diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 95fae275..90b5db41 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -2761,6 +2761,44 @@ 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. */ + + { nxt_string("var a = 1; njs.dump({a})"), + nxt_string("{a:1}") }, + + { nxt_string("var a = 1, b; njs.dump({a,b})"), + nxt_string("{a:1,b:undefined}") }, + + { nxt_string("var a = 1, b = 2; ({a,b,c})"), + nxt_string("ReferenceError: \"c\" is not defined in 1") }, + + { nxt_string("var a = 1, b = 2; njs.dump({a,b,c:3})"), + nxt_string("{a:1,b:2,c:3}") }, + + { nxt_string("var b = 2, c = 3; njs.dump({a:1,b,c})"), + nxt_string("{a:1,b:2,c:3}") }, + + { nxt_string("({1})"), + nxt_string("SyntaxError: Unexpected token \"}\" in 1") }, + + { nxt_string("({default})"), + nxt_string("SyntaxError: Unexpected token \"}\" in 1") }, + + { nxt_string("({var})"), + nxt_string("SyntaxError: Unexpected token \"}\" in 1") }, + + { nxt_string("({this})"), + nxt_string("SyntaxError: Unexpected token \"}\" in 1") }, + + { nxt_string("typeof ({Number}).Number"), + nxt_string("function") }, + + { nxt_string("typeof ({eval}).eval"), + nxt_string("function") }, + + { nxt_string("typeof ({Math}).Math.sin"), + nxt_string("function") }, + { nxt_string("delete null"), nxt_string("true") },