Skip to content

Instantly share code, notes, and snippets.

@xeioex
Created February 8, 2019 18:19
Show Gist options
  • Save xeioex/1664cc5c76a6e8da12cc4e5d8abcfbeb to your computer and use it in GitHub Desktop.
Save xeioex/1664cc5c76a6e8da12cc4e5d8abcfbeb to your computer and use it in GitHub Desktop.
# HG changeset patch
# User Dmitry Volyntsev <[email protected]>
# Date 1549649826 -10800
# Fri Feb 08 21:17:06 2019 +0300
# Node ID 964ddb99f52d383b9e3f024bab64501c73da8eb8
# Parent 4e8940c1bef19a4b0a4e6d5206b3884f42739126
Added support for shorthand property names for Object literals.
diff --git a/njs/njs_lexer.c b/njs/njs_lexer.c
--- a/njs/njs_lexer.c
+++ b/njs/njs_lexer.c
@@ -459,7 +459,9 @@ 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 +500,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 --git a/njs/njs_parser.c b/njs/njs_parser.c
--- a/njs/njs_parser.c
+++ b/njs/njs_parser.c
@@ -2167,13 +2167,28 @@ njs_parser_builtin_function(njs_vm_t *vm
}
+/*
+ * 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_ret_t ret;
+ nxt_bool_t identifier;
+ njs_lexer_t *lexer;
njs_token_t token;
- njs_parser_node_t *stmt, *assign, *object, *propref, *left;
+ njs_parser_node_t *stmt, *assign, *object, *propref, *left, *expression;
left = NULL;
+ lexer = parser->lexer;
object = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT_VALUE);
if (nxt_slow_path(object == NULL)) {
@@ -2183,6 +2198,8 @@ njs_parser_object(njs_vm_t *vm, njs_pars
object->u.object = obj;
for ( ;; ) {
+ identifier = 0;
+
token = njs_parser_property_token(parser);
switch (token) {
@@ -2191,6 +2208,12 @@ njs_parser_object(njs_vm_t *vm, njs_pars
return njs_parser_token(parser);
case NJS_TOKEN_NAME:
+ if (lexer->property_token == NJS_TOKEN_NAME) {
+ identifier = 1;
+ name = lexer->text;
+ hash = lexer->key_hash;
+ }
+
token = njs_parser_property_name(vm, parser);
break;
@@ -2216,14 +2239,32 @@ 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 (identifier
+ && (token == NJS_TOKEN_COMMA || token == NJS_TOKEN_CLOSE_BRACE))
+ {
+ expression = njs_parser_node_new(vm, parser, NJS_TOKEN_NAME);
+ if (nxt_slow_path(expression == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ ret = njs_variable_reference(vm, parser->scope, expression, &name,
+ hash, NJS_REFERENCE);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ 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);
@@ -2233,7 +2274,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 --git a/njs/njs_parser.h b/njs/njs_parser.h
--- 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
--- a/njs/test/njs_unit_test.c
+++ b/njs/test/njs_unit_test.c
@@ -2770,6 +2770,29 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("delete undefined"),
nxt_string("SyntaxError: Delete of an unqualified identifier in 1") },
+ /* 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("({default})"),
+ nxt_string("SyntaxError: Unexpected token \"}\" in 1") },
+
+ { nxt_string("({this})"),
+ nxt_string("SyntaxError: Unexpected token \"}\" in 1") },
+
/* ES5FIX: "SyntaxError". */
{ nxt_string("delete NaN"),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment