Skip to content

Instantly share code, notes, and snippets.

@xeioex
Created February 11, 2019 14:11
Show Gist options
  • Save xeioex/6240f1300ca4e62b7c55651280beb8c3 to your computer and use it in GitHub Desktop.
Save xeioex/6240f1300ca4e62b7c55651280beb8c3 to your computer and use it in GitHub Desktop.
# HG changeset patch
# User hongzhidao <[email protected]>
# Date 1549700768 -28800
# Sat Feb 09 16:26:08 2019 +0800
# Node ID 08285ce7dd7c372869a29e317109235045028a90
# Parent 4e8940c1bef19a4b0a4e6d5206b3884f42739126
Improved njs_parser_property_token().
diff --git a/njs/njs_parser.c b/njs/njs_parser.c
--- a/njs/njs_parser.c
+++ b/njs/njs_parser.c
@@ -60,6 +60,7 @@ static njs_token_t njs_parser_object(njs
njs_parser_node_t *obj);
static njs_token_t njs_parser_array(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_node_t *obj);
+static nxt_int_t njs_parser_string_create(njs_vm_t *vm, njs_value_t *value);
static njs_token_t njs_parser_escape_string_create(njs_vm_t *vm,
njs_parser_t *parser, njs_value_t *value);
static njs_token_t njs_parser_unexpected_token(njs_vm_t *vm,
@@ -1756,9 +1757,11 @@ njs_parser_grouping_expression(njs_vm_t
njs_token_t
-njs_parser_property_token(njs_parser_t *parser)
+njs_parser_property_token(njs_vm_t *vm, njs_parser_t *parser)
{
- njs_token_t token;
+ nxt_int_t ret;
+ njs_token_t token;
+ njs_parser_node_t *node;
parser->lexer->property = 1;
@@ -1766,6 +1769,20 @@ njs_parser_property_token(njs_parser_t *
parser->lexer->property = 0;
+ if (token == NJS_TOKEN_NAME) {
+ node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING);
+ if (nxt_slow_path(node == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ ret = njs_parser_string_create(vm, &node->u.value);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ parser->node = node;
+ }
+
return token;
}
@@ -2183,7 +2200,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars
object->u.object = obj;
for ( ;; ) {
- token = njs_parser_property_token(parser);
+ token = njs_parser_property_token(vm, parser);
switch (token) {
@@ -2191,7 +2208,7 @@ njs_parser_object(njs_vm_t *vm, njs_pars
return njs_parser_token(parser);
case NJS_TOKEN_NAME:
- token = njs_parser_property_name(vm, parser);
+ token = njs_parser_token(parser);
break;
case NJS_TOKEN_NUMBER:
@@ -2351,7 +2368,7 @@ njs_parser_array(njs_vm_t *vm, njs_parse
}
-nxt_int_t
+static nxt_int_t
njs_parser_string_create(njs_vm_t *vm, njs_value_t *value)
{
u_char *p;
diff --git a/njs/njs_parser.h b/njs/njs_parser.h
--- a/njs/njs_parser.h
+++ b/njs/njs_parser.h
@@ -320,10 +320,8 @@ njs_token_t njs_parser_assignment_expres
njs_parser_t *parser, njs_token_t token);
njs_token_t njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser,
njs_token_t token);
-njs_token_t njs_parser_property_name(njs_vm_t *vm, njs_parser_t *parser);
-njs_token_t njs_parser_property_token(njs_parser_t *parser);
+njs_token_t njs_parser_property_token(njs_vm_t *vm, njs_parser_t *parser);
njs_token_t njs_parser_token(njs_parser_t *parser);
-nxt_int_t njs_parser_string_create(njs_vm_t *vm, njs_value_t *value);
njs_variable_t *njs_variable_resolve(njs_vm_t *vm, njs_parser_node_t *node);
njs_index_t njs_variable_typeof(njs_vm_t *vm, njs_parser_node_t *node);
njs_index_t njs_variable_index(njs_vm_t *vm, njs_parser_node_t *node);
diff --git a/njs/njs_parser_expression.c b/njs/njs_parser_expression.c
--- a/njs/njs_parser_expression.c
+++ b/njs/njs_parser_expression.c
@@ -984,7 +984,7 @@ njs_parser_property_expression(njs_vm_t
if (token == NJS_TOKEN_DOT) {
- token = njs_parser_property_token(parser);
+ token = njs_parser_property_token(vm, parser);
if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
return token;
}
@@ -993,7 +993,7 @@ njs_parser_property_expression(njs_vm_t
return NJS_TOKEN_ILLEGAL;
}
- token = njs_parser_property_name(vm, parser);
+ token = njs_parser_token(parser);
} else {
token = njs_parser_token(parser);
@@ -1014,28 +1014,6 @@ njs_parser_property_expression(njs_vm_t
}
-njs_token_t
-njs_parser_property_name(njs_vm_t *vm, njs_parser_t *parser)
-{
- nxt_int_t ret;
- njs_parser_node_t *node;
-
- node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING);
- if (nxt_slow_path(node == NULL)) {
- return NJS_TOKEN_ERROR;
- }
-
- ret = njs_parser_string_create(vm, &node->u.value);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NJS_TOKEN_ERROR;
- }
-
- parser->node = node;
-
- return njs_parser_token(parser);
-}
-
-
static njs_token_t
njs_parser_property_brackets(njs_vm_t *vm, njs_parser_t *parser,
njs_token_t token)
# HG changeset patch
# User hongzhidao <[email protected]>
# Date 1549704844 -28800
# Sat Feb 09 17:34:04 2019 +0800
# Node ID 64a0444aaa1a6c2688a7ba2173c5ed5c2b79c6e3
# Parent 08285ce7dd7c372869a29e317109235045028a90
Refactored njs_parser_terminal().
1) Introduced njs_parser_reference().
2) njs_parser_builtin_object() and njs_parser_builtin_function()
are refactored into njs_parser_builtin().
3) njs_parser_external() is simplified and renamed as
njs_external_lookup().
diff --git a/njs/njs_extern.c b/njs/njs_extern.c
--- a/njs/njs_extern.c
+++ b/njs/njs_extern.c
@@ -304,13 +304,13 @@ njs_extern_keys_array(njs_vm_t *vm, cons
njs_value_t *
-njs_parser_external(njs_vm_t *vm, njs_parser_t *parser)
+njs_external_lookup(njs_vm_t *vm, nxt_str_t *name, uint32_t hash)
{
nxt_lvlhsh_query_t lhq;
njs_extern_value_t *ev;
- lhq.key_hash = parser->lexer->key_hash;
- lhq.key = parser->lexer->text;
+ lhq.key_hash = hash;
+ lhq.key = *name;
lhq.proto = &njs_extern_value_hash_proto;
if (nxt_lvlhsh_find(&vm->externals_hash, &lhq) == NXT_OK) {
diff --git a/njs/njs_extern.h b/njs/njs_extern.h
--- a/njs/njs_extern.h
+++ b/njs/njs_extern.h
@@ -42,6 +42,7 @@ typedef struct {
njs_array_t *njs_extern_keys_array(njs_vm_t *vm, const njs_extern_t *external);
+njs_value_t *njs_external_lookup(njs_vm_t *vm, nxt_str_t *name, uint32_t hash);
nxt_int_t njs_external_match_native_function(njs_vm_t *vm,
njs_function_native_t func, nxt_str_t *name);
diff --git a/njs/njs_parser.c b/njs/njs_parser.c
--- a/njs/njs_parser.c
+++ b/njs/njs_parser.c
@@ -52,10 +52,9 @@ static njs_token_t njs_parser_throw_stat
njs_parser_t *parser);
static njs_token_t njs_parser_grouping_expression(njs_vm_t *vm,
njs_parser_t *parser);
-static njs_token_t njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
- njs_parser_node_t *node);
-static njs_token_t njs_parser_builtin_function(njs_vm_t *vm,
- njs_parser_t *parser, njs_parser_node_t *node);
+static nxt_int_t njs_parser_builtin(njs_vm_t *vm, njs_parser_t *parser,
+ njs_parser_node_t *node, njs_value_type_t type, nxt_str_t *name,
+ uint32_t hash);
static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_node_t *obj);
static njs_token_t njs_parser_array(njs_vm_t *vm, njs_parser_t *parser,
@@ -1805,156 +1804,22 @@ njs_parser_token(njs_parser_t *parser)
}
-njs_token_t
-njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token)
+static njs_parser_node_t *
+njs_parser_reference(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token,
+ nxt_str_t *name, uint32_t hash)
{
- double num;
njs_ret_t ret;
njs_value_t *ext;
njs_parser_node_t *node;
njs_parser_scope_t *scope;
- if (token == NJS_TOKEN_OPEN_PARENTHESIS) {
-
- token = njs_parser_token(parser);
- if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- return token;
- }
-
- token = njs_parser_expression(vm, parser, token);
- if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- return token;
- }
-
- return njs_parser_match(vm, parser, token, NJS_TOKEN_CLOSE_PARENTHESIS);
- }
-
- if (token == NJS_TOKEN_FUNCTION) {
- return njs_parser_function_expression(vm, parser);
- }
-
node = njs_parser_node_new(vm, parser, token);
if (nxt_slow_path(node == NULL)) {
- return NJS_TOKEN_ERROR;
+ return NULL;
}
switch (token) {
- case NJS_TOKEN_NAME:
- nxt_thread_log_debug("JS: %V", &parser->lexer->text);
-
- ext = njs_parser_external(vm, parser);
-
- if (ext != NULL) {
- node->token = NJS_TOKEN_EXTERNAL;
- node->u.value = *ext;
- node->index = (njs_index_t) ext;
- break;
- }
-
- ret = njs_parser_variable_reference(vm, parser, node, NJS_REFERENCE);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NJS_TOKEN_ERROR;
- }
-
- break;
-
- case NJS_TOKEN_OPEN_BRACE:
- node->token = NJS_TOKEN_OBJECT;
-
- nxt_thread_log_debug("JS: OBJECT");
-
- parser->node = node;
-
- token = njs_parser_object(vm, parser, node);
-
- if (parser->node != node) {
- /* The object is not empty. */
- node->left = parser->node;
- parser->node = node;
- }
-
- return token;
-
- case NJS_TOKEN_OPEN_BRACKET:
- node->token = NJS_TOKEN_ARRAY;
-
- nxt_thread_log_debug("JS: ARRAY");
-
- parser->node = node;
-
- token = njs_parser_array(vm, parser, node);
-
- if (parser->node != node) {
- /* The array is not empty. */
- node->left = parser->node;
- parser->node = node;
- }
-
- return token;
-
- case NJS_TOKEN_DIVISION:
- token = njs_regexp_literal(vm, parser, &node->u.value);
- if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- return token;
- }
-
- nxt_thread_log_debug("REGEX: '%V'", &parser->lexer->text);
-
- node->token = NJS_TOKEN_REGEXP;
-
- break;
-
- case NJS_TOKEN_STRING:
- nxt_thread_log_debug("JS: '%V'", &parser->lexer->text);
-
- ret = njs_parser_string_create(vm, &node->u.value);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NJS_TOKEN_ERROR;
- }
-
- break;
-
- case NJS_TOKEN_ESCAPE_STRING:
- node->token = NJS_TOKEN_STRING;
-
- nxt_thread_log_debug("JS: '%V'", &parser->lexer->text);
-
- ret = njs_parser_escape_string_create(vm, parser, &node->u.value);
- if (nxt_slow_path(ret != NJS_TOKEN_STRING)) {
- return ret;
- }
-
- break;
-
- case NJS_TOKEN_UNTERMINATED_STRING:
- njs_parser_syntax_error(vm, parser, "Unterminated string \"%V\"",
- &parser->lexer->text);
-
- return NJS_TOKEN_ILLEGAL;
-
- case NJS_TOKEN_NUMBER:
- nxt_thread_log_debug("JS: %f", parser->lexer->number);
-
- num = parser->lexer->number;
- node->u.value.data.u.number = num;
- node->u.value.type = NJS_NUMBER;
- node->u.value.data.truth = njs_is_number_true(num);
-
- break;
-
- case NJS_TOKEN_BOOLEAN:
- nxt_thread_log_debug("JS: boolean: %V", &parser->lexer->text);
-
- if (parser->lexer->number == 0) {
- node->u.value = njs_value_false;
-
- } else {
- node->u.value = njs_value_true;
- }
-
- break;
-
case NJS_TOKEN_NULL:
nxt_thread_log_debug("JS: null");
@@ -1992,16 +1857,21 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
case NJS_TOKEN_NJS:
case NJS_TOKEN_MATH:
case NJS_TOKEN_JSON:
- return njs_parser_builtin_object(vm, parser, node);
+ ret = njs_parser_builtin(vm, parser, node, NJS_OBJECT, name, hash);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+
+ break;
case NJS_TOKEN_ARGUMENTS:
nxt_thread_log_debug("JS: arguments");
if (parser->scope->type <= NJS_SCOPE_GLOBAL) {
njs_parser_syntax_error(vm, parser, "\"%V\" object "
- "in global scope", &parser->lexer->text);
-
- return NJS_TOKEN_ILLEGAL;
+ "in global scope", name);
+
+ return NULL;
}
break;
@@ -2088,10 +1958,205 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
case NJS_TOKEN_SET_TIMEOUT:
case NJS_TOKEN_SET_IMMEDIATE:
case NJS_TOKEN_CLEAR_TIMEOUT:
- return njs_parser_builtin_function(vm, parser, node);
+ ret = njs_parser_builtin(vm, parser, node, NJS_FUNCTION, name, hash);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+
+ break;
+
+ case NJS_TOKEN_NAME:
+ nxt_thread_log_debug("JS: %V", name);
+
+ ext = njs_external_lookup(vm, name, hash);
+
+ if (ext != NULL) {
+ node->token = NJS_TOKEN_EXTERNAL;
+ node->u.value = *ext;
+ node->index = (njs_index_t) ext;
+ break;
+ }
+
+ ret = njs_variable_reference(vm, parser->scope, node, name, hash,
+ NJS_REFERENCE);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+
+ break;
default:
- return njs_parser_unexpected_token(vm, parser, token);
+ njs_parser_unexpected_token(vm, parser, token);
+ return NULL;
+ }
+
+ return node;
+}
+
+
+njs_token_t
+njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token)
+{
+ double num;
+ njs_ret_t ret;
+ njs_lexer_t *lexer;
+ njs_parser_node_t *node;
+
+ lexer = parser->lexer;
+
+ if (token == NJS_TOKEN_OPEN_PARENTHESIS) {
+
+ token = njs_parser_token(parser);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ token = njs_parser_expression(vm, parser, token);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ return njs_parser_match(vm, parser, token, NJS_TOKEN_CLOSE_PARENTHESIS);
+ }
+
+ if (token == NJS_TOKEN_FUNCTION) {
+ return njs_parser_function_expression(vm, parser);
+ }
+
+ switch (token) {
+
+ case NJS_TOKEN_OPEN_BRACE:
+ nxt_thread_log_debug("JS: OBJECT");
+
+ node = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT);
+ if (nxt_slow_path(node == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ parser->node = node;
+
+ token = njs_parser_object(vm, parser, node);
+
+ if (parser->node != node) {
+ /* The object is not empty. */
+ node->left = parser->node;
+ parser->node = node;
+ }
+
+ return token;
+
+ case NJS_TOKEN_OPEN_BRACKET:
+ nxt_thread_log_debug("JS: ARRAY");
+
+ node = njs_parser_node_new(vm, parser, NJS_TOKEN_ARRAY);
+ if (nxt_slow_path(node == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ parser->node = node;
+
+ token = njs_parser_array(vm, parser, node);
+
+ if (parser->node != node) {
+ /* The array is not empty. */
+ node->left = parser->node;
+ parser->node = node;
+ }
+
+ return token;
+
+ case NJS_TOKEN_DIVISION:
+ node = njs_parser_node_new(vm, parser, NJS_TOKEN_REGEXP);
+ if (nxt_slow_path(node == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ token = njs_regexp_literal(vm, parser, &node->u.value);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ nxt_thread_log_debug("REGEX: '%V'", &lexer->text);
+
+ break;
+
+ case NJS_TOKEN_STRING:
+ nxt_thread_log_debug("JS: '%V'", &lexer->text);
+
+ node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING);
+ if (nxt_slow_path(node == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ ret = njs_parser_string_create(vm, &node->u.value);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ break;
+
+ case NJS_TOKEN_ESCAPE_STRING:
+ nxt_thread_log_debug("JS: '%V'", &lexer->text);
+
+ node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING);
+ if (nxt_slow_path(node == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ ret = njs_parser_escape_string_create(vm, parser, &node->u.value);
+ if (nxt_slow_path(ret != NJS_TOKEN_STRING)) {
+ return ret;
+ }
+
+ break;
+
+ case NJS_TOKEN_UNTERMINATED_STRING:
+ njs_parser_syntax_error(vm, parser, "Unterminated string \"%V\"",
+ &lexer->text);
+
+ return NJS_TOKEN_ILLEGAL;
+
+ case NJS_TOKEN_NUMBER:
+ num = lexer->number;
+ nxt_thread_log_debug("JS: %f", num);
+
+ node = njs_parser_node_new(vm, parser, NJS_TOKEN_NUMBER);
+ if (nxt_slow_path(node == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ node->u.value.data.u.number = num;
+ node->u.value.type = NJS_NUMBER;
+ node->u.value.data.truth = njs_is_number_true(num);
+
+ break;
+
+ case NJS_TOKEN_BOOLEAN:
+ nxt_thread_log_debug("JS: boolean: %V", &lexer->text);
+
+ node = njs_parser_node_new(vm, parser, NJS_TOKEN_BOOLEAN);
+ if (nxt_slow_path(node == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ if (parser->lexer->number == 0) {
+ node->u.value = njs_value_false;
+
+ } else {
+ node->u.value = njs_value_true;
+ }
+
+ break;
+
+ default:
+ node = njs_parser_reference(vm, parser, token, &lexer->text,
+ lexer->key_hash);
+
+ if (nxt_slow_path(node == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ break;
}
parser->node = node;
@@ -2100,12 +2165,10 @@ njs_parser_terminal(njs_vm_t *vm, njs_pa
}
-static njs_token_t
-njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser,
- njs_parser_node_t *node)
+static nxt_int_t
+njs_parser_builtin(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node,
+ njs_value_type_t type, nxt_str_t *name, uint32_t hash)
{
- uint32_t hash;
- nxt_str_t *name;
njs_ret_t ret;
nxt_uint_t index;
njs_variable_t *var;
@@ -2117,70 +2180,36 @@ njs_parser_builtin_object(njs_vm_t *vm,
scope = scope->parent;
}
- hash = parser->lexer->key_hash;
- name = &parser->lexer->text;
-
var = njs_variable_add(vm, scope, name, hash, NJS_VARIABLE_VAR);
if (nxt_slow_path(var == NULL)) {
- return NJS_TOKEN_ERROR;
+ return NXT_ERROR;
}
/* TODO: once */
- index = node->token - NJS_TOKEN_FIRST_OBJECT;
- var->value.data.u.object = &vm->shared->objects[index];
- var->value.type = NJS_OBJECT;
+ switch (type) {
+ case NJS_OBJECT:
+ index = node->token - NJS_TOKEN_FIRST_OBJECT;
+ var->value.data.u.object = &vm->shared->objects[index];
+ break;
+
+ case NJS_FUNCTION:
+ index = node->token - NJS_TOKEN_FIRST_FUNCTION;
+ var->value.data.u.function = &vm->shared->functions[index];
+ break;
+
+ default:
+ return NXT_ERROR;
+ }
+
+ var->value.type = type;
var->value.data.truth = 1;
ret = njs_variable_reference(vm, scope, node, name, hash, NJS_REFERENCE);
if (nxt_slow_path(ret != NXT_OK)) {
- return NJS_TOKEN_ERROR;
+ return NXT_ERROR;
}
- parser->node = node;
-
- return njs_parser_token(parser);
-}
-
-
-static njs_token_t
-njs_parser_builtin_function(njs_vm_t *vm, njs_parser_t *parser,
- njs_parser_node_t *node)
-{
- uint32_t hash;
- nxt_str_t *name;
- njs_ret_t ret;
- nxt_uint_t index;
- njs_variable_t *var;
- njs_parser_scope_t *scope;
-
- scope = parser->scope;
-
- while (scope->type != NJS_SCOPE_GLOBAL) {
- scope = scope->parent;
- }
-
- hash = parser->lexer->key_hash;
- name = &parser->lexer->text;
-
- var = njs_variable_add(vm, scope, name, hash, NJS_VARIABLE_VAR);
- if (nxt_slow_path(var == NULL)) {
- return NJS_TOKEN_ERROR;
- }
-
- /* TODO: once */
- index = node->token - NJS_TOKEN_FIRST_FUNCTION;
- var->value.data.u.function = &vm->shared->functions[index];
- var->value.type = NJS_FUNCTION;
- var->value.data.truth = 1;
-
- ret = njs_variable_reference(vm, scope, node, name, hash, NJS_REFERENCE);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NJS_TOKEN_ERROR;
- }
-
- parser->node = node;
-
- return njs_parser_token(parser);
+ return NXT_OK;
}
diff --git a/njs/njs_parser.h b/njs/njs_parser.h
--- a/njs/njs_parser.h
+++ b/njs/njs_parser.h
@@ -306,8 +306,6 @@ void njs_lexer_rollback(njs_lexer_t *lex
nxt_int_t njs_lexer_keywords_init(nxt_mp_t *mcp, nxt_lvlhsh_t *hash);
njs_token_t njs_lexer_keyword(njs_lexer_t *lexer);
-njs_value_t *njs_parser_external(njs_vm_t *vm, njs_parser_t *parser);
-
nxt_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_t *prev);
njs_token_t njs_parser_arguments(njs_vm_t *vm, njs_parser_t *parser,
# HG changeset patch
# User Dmitry Volyntsev <[email protected]>
# Date 1549894226 -10800
# Mon Feb 11 17:10:26 2019 +0300
# Node ID f6c506126c468ee25aefc2e99aa7013e68df6bf8
# Parent 64a0444aaa1a6c2688a7ba2173c5ed5c2b79c6e3
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,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 --git a/njs/njs_parser.c b/njs/njs_parser.c
--- a/njs/njs_parser.c
+++ b/njs/njs_parser.c
@@ -2213,13 +2213,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)) {
@@ -2231,12 +2247,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;
@@ -2262,14 +2283,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);
@@ -2279,7 +2315,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
@@ -2761,6 +2761,38 @@ 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 ({Math}).Math.sin"),
+ nxt_string("function") },
+
{ nxt_string("delete null"),
nxt_string("true") },
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment