[njs] Added support for shorthand property names for Object literals.
Dmitry Volyntsev
xeioex at nginx.com
Mon Feb 11 15:16:23 UTC 2019
details: https://hg.nginx.org/njs/rev/eb099f4faf40
branches:
changeset: 774:eb099f4faf40
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Mon Feb 11 18:15:43 2019 +0300
description:
Added support for shorthand property names for Object literals.
This closes #87 issue on Github.
diffstat:
njs/njs_lexer.c | 8 +++++-
njs/njs_parser.c | 56 +++++++++++++++++++++++++++++++++++++++--------
njs/njs_parser.h | 3 ++
njs/test/njs_unit_test.c | 38 ++++++++++++++++++++++++++++++++
4 files changed, 93 insertions(+), 12 deletions(-)
diffs (190 lines):
diff -r a091eaa9d8eb -r eb099f4faf40 njs/njs_lexer.c
--- a/njs/njs_lexer.c Sat Feb 09 17:34:04 2019 +0800
+++ b/njs/njs_lexer.c Mon Feb 11 18:15:43 2019 +0300
@@ -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_cha
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 -r a091eaa9d8eb -r eb099f4faf40 njs/njs_parser.c
--- a/njs/njs_parser.c Sat Feb 09 17:34:04 2019 +0800
+++ b/njs/njs_parser.c Mon Feb 11 18:15:43 2019 +0300
@@ -2215,13 +2215,29 @@ njs_parser_builtin(njs_vm_t *vm, njs_par
}
+/*
+ * 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_pars
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_pars
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;
- }
-
- token = njs_parser_assignment_expression(vm, parser, token);
- 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;
+ }
+
+ } 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_pars
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 -r a091eaa9d8eb -r eb099f4faf40 njs/njs_parser.h
--- a/njs/njs_parser.h Sat Feb 09 17:34:04 2019 +0800
+++ b/njs/njs_parser.h Mon Feb 11 18:15:43 2019 +0300
@@ -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 -r a091eaa9d8eb -r eb099f4faf40 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Sat Feb 09 17:34:04 2019 +0800
+++ b/njs/test/njs_unit_test.c Mon Feb 11 18:15:43 2019 +0300
@@ -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") },
More information about the nginx-devel
mailing list