From: Dmitry Volyntsev Date: Mon, 12 Nov 2018 15:27:05 +0000 (+0300) Subject: Allowing variables and functions to be redeclared. X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=48e02ed8bfd06ce8e12cb0d2594d6a85a2decf50;p=njs.git Allowing variables and functions to be redeclared. --- diff --git a/njs/njs_function.c b/njs/njs_function.c index b9fcd64b..11cc42c5 100644 --- a/njs/njs_function.c +++ b/njs/njs_function.c @@ -412,7 +412,7 @@ njs_function_call(njs_vm_t *vm, njs_index_t retval, size_t advance) 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 --git a/njs/njs_function.h b/njs/njs_function.h index e6b35e31..27fc6b69 100644 --- a/njs/njs_function.h +++ b/njs/njs_function.h @@ -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 --git a/njs/njs_generator.c b/njs/njs_generator.c index 1ee7072a..75549050 100644 --- a/njs/njs_generator.c +++ b/njs/njs_generator.c @@ -2007,6 +2007,11 @@ njs_generate_function_declaration(njs_vm_t *vm, njs_parser_t *parser, 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, njs_function_lambda_t *lambda, 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, njs_function_lambda_t *lambda, 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 --git a/njs/njs_parser.c b/njs/njs_parser.c index bdfc0a5c..9f88041c 100644 --- a/njs/njs_parser.c +++ b/njs/njs_parser.c @@ -496,7 +496,7 @@ njs_parser_function_declaration(njs_vm_t *vm, njs_parser_t *parser) 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 *vm, njs_parser_t *parser) } 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_function_lambda_t *lambda, 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 --git a/njs/njs_variable.c b/njs/njs_variable.c index fa8253bb..945c221f 100644 --- a/njs/njs_variable.c +++ b/njs/njs_variable.c @@ -119,12 +119,17 @@ njs_variable_add(njs_vm_t *vm, njs_parser_t *parser, njs_variable_type_t type) } } + 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_parser_t *parser, njs_variable_type_t type) 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 --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 73c8dbca..f43e962f 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -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 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("var f = 1; function f() {}"), - nxt_string("SyntaxError: Identifier \"f\" has already been declared in 1") }, + { 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") },