[njs] Allowing variables and functions to be redeclared.

Dmitry Volyntsev xeioex at nginx.com
Mon Nov 12 15:38:17 UTC 2018


details:   http://hg.nginx.org/njs/rev/46364c618468
branches:  
changeset: 648:46364c618468
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Mon Nov 12 18:27:05 2018 +0300
description:
Allowing variables and functions to be redeclared.

diffstat:

 njs/njs_function.c       |   2 +-
 njs/njs_function.h       |   6 ++----
 njs/njs_generator.c      |   9 +++++++--
 njs/njs_parser.c         |   6 +++---
 njs/njs_variable.c       |  17 +++++++----------
 njs/test/njs_unit_test.c |  33 ++++++++++++++++++++++++++++-----
 6 files changed, 48 insertions(+), 25 deletions(-)

diffs (173 lines):

diff -r f1da98bdd82f -r 46364c618468 njs/njs_function.c
--- a/njs/njs_function.c	Mon Nov 12 17:22:14 2018 +0300
+++ b/njs/njs_function.c	Mon Nov 12 18:27:05 2018 +0300
@@ -412,7 +412,7 @@ njs_function_call(njs_vm_t *vm, njs_inde
     frame->return_address = vm->current + advance;
 
     lambda = function->u.lambda;
-    vm->current = lambda->u.start;
+    vm->current = lambda->start;
 
 #if (NXT_DEBUG)
     vm->scopes[NJS_SCOPE_CALLEE_ARGUMENTS] = NULL;
diff -r f1da98bdd82f -r 46364c618468 njs/njs_function.h
--- a/njs/njs_function.h	Mon Nov 12 17:22:14 2018 +0300
+++ b/njs/njs_function.h	Mon Nov 12 18:27:05 2018 +0300
@@ -36,10 +36,8 @@ struct njs_function_lambda_s {
     njs_value_t                    *local_scope;
     njs_value_t                    *closure_scope;
 
-    union {
-        u_char                     *start;
-        njs_parser_t               *parser;
-    } u;
+    u_char                         *start;
+    njs_parser_t                   *parser;
 };
 
 
diff -r f1da98bdd82f -r 46364c618468 njs/njs_generator.c
--- a/njs/njs_generator.c	Mon Nov 12 17:22:14 2018 +0300
+++ b/njs/njs_generator.c	Mon Nov 12 18:27:05 2018 +0300
@@ -2007,6 +2007,11 @@ njs_generate_function_declaration(njs_vm
         return NXT_ERROR;
     }
 
+    if (!njs_is_function(&var->value)) {
+        /* A variable was declared with the same name. */
+        return NXT_OK;
+    }
+
     lambda = var->value.data.u.function->u.lambda;
 
     ret = njs_generate_function_scope(vm, lambda, node);
@@ -2032,7 +2037,7 @@ njs_generate_function_scope(njs_vm_t *vm
     nxt_array_t   *closure;
     njs_parser_t  *parser;
 
-    parser = lambda->u.parser;
+    parser = lambda->parser;
     node = node->right;
 
     parser->code_size += node->scope->argument_closures
@@ -2058,7 +2063,7 @@ njs_generate_function_scope(njs_vm_t *vm
 
         lambda->local_size = parser->scope_size;
         lambda->local_scope = parser->local_scope;
-        lambda->u.start = parser->code_start;
+        lambda->start = parser->code_start;
     }
 
     return ret;
diff -r f1da98bdd82f -r 46364c618468 njs/njs_parser.c
--- a/njs/njs_parser.c	Mon Nov 12 17:22:14 2018 +0300
+++ b/njs/njs_parser.c	Mon Nov 12 18:27:05 2018 +0300
@@ -496,7 +496,7 @@ njs_parser_function_declaration(njs_vm_t
         return NJS_TOKEN_ERROR;
     }
 
-    function->u.lambda->u.parser = parser;
+    function->u.lambda->parser = parser;
 
     token = njs_parser_function_lambda(vm, function->u.lambda, token);
 
@@ -578,7 +578,7 @@ njs_parser_function_expression(njs_vm_t 
     }
 
     node->u.value.data.u.lambda = lambda;
-    lambda->u.parser = parser;
+    lambda->parser = parser;
 
     token = njs_parser_function_lambda(vm, lambda, token);
 
@@ -619,7 +619,7 @@ njs_parser_function_lambda(njs_vm_t *vm,
     njs_variable_t     *arg;
     njs_parser_node_t  *node, *body, *last;
 
-    parser = lambda->u.parser;
+    parser = lambda->parser;
 
     ret = njs_parser_scope_begin(vm, parser, NJS_SCOPE_FUNCTION);
     if (nxt_slow_path(ret != NXT_OK)) {
diff -r f1da98bdd82f -r 46364c618468 njs/njs_variable.c
--- a/njs/njs_variable.c	Mon Nov 12 17:22:14 2018 +0300
+++ b/njs/njs_variable.c	Mon Nov 12 18:27:05 2018 +0300
@@ -119,12 +119,17 @@ njs_variable_add(njs_vm_t *vm, njs_parse
         }
     }
 
+    if (nxt_lvlhsh_find(&scope->variables, &lhq) == NXT_OK) {
+        var = lhq.value;
+        return var;
+    }
+
     var = njs_variable_alloc(vm, &lhq.key, type);
     if (nxt_slow_path(var == NULL)) {
         return var;
     }
 
-    lhq.replace = vm->options.accumulative;
+    lhq.replace = 0;
     lhq.value = var;
     lhq.pool = vm->mem_cache_pool;
 
@@ -137,15 +142,7 @@ njs_variable_add(njs_vm_t *vm, njs_parse
     nxt_mem_cache_free(vm->mem_cache_pool, var->name.start);
     nxt_mem_cache_free(vm->mem_cache_pool, var);
 
-    if (ret == NXT_ERROR) {
-        return NULL;
-    }
-
-    /* ret == NXT_DECLINED. */
-
-    njs_parser_syntax_error(vm, parser, "Identifier \"%.*s\" "
-                            "has already been declared",
-                            (int) lhq.key.length, lhq.key.start);
+    njs_type_error(vm, "lvlhsh insert failed");
 
     return NULL;
 }
diff -r f1da98bdd82f -r 46364c618468 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Mon Nov 12 17:22:14 2018 +0300
+++ b/njs/test/njs_unit_test.c	Mon Nov 12 18:27:05 2018 +0300
@@ -75,11 +75,34 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("if(1)if(0){0?0:0}else\nvar a\nelse\nvar b"),
       nxt_string("undefined") },
 
-    { nxt_string("function f(){} function f(){}"),
-      nxt_string("SyntaxError: Identifier \"f\" has already been declared in 1") },
-
-    { nxt_string("var f = 1; function f() {}"),
-      nxt_string("SyntaxError: Identifier \"f\" has already been declared in 1") },
+    { nxt_string("var a = 1; var a; a"),
+      nxt_string("1") },
+
+    { nxt_string("(function (x) {if (x) { var a = 3; return a} else { var a = 4; return a}})(1)"),
+      nxt_string("3") },
+
+    { nxt_string("(function (x) {if (x) { var a = 3; return a} else { var a = 4; return a}})(0)"),
+      nxt_string("4") },
+
+    { nxt_string("function f(){return 2}; var f; f()"),
+      nxt_string("2") },
+
+    { nxt_string("function f(){return 2}; var f = 1; f()"),
+      nxt_string("TypeError: number is not a function") },
+
+    { nxt_string("function f(){return 1}; function f(){return 2}; f()"),
+      nxt_string("2") },
+
+    { nxt_string("var f = 1; function f() {}; f"),
+      nxt_string("1") },
+
+#if 0 /* TODO */
+    { nxt_string("var a; Object.getOwnPropertyDescriptor(this, 'a').value"),
+      nxt_string("undefined") },
+
+    { nxt_string("this.a = 1; a"),
+      nxt_string("1") },
+#endif
 
     { nxt_string("f() = 1"),
       nxt_string("ReferenceError: Invalid left-hand side in assignment in 1") },


More information about the nginx-devel mailing list