Dmitry Volyntsev
2018-11-12 15:38:17 UTC
details: http://hg.nginx.org/njs/rev/46364c618468
branches:
changeset: 648:46364c618468
user: Dmitry Volyntsev <***@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") },
branches:
changeset: 648:46364c618468
user: Dmitry Volyntsev <***@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") },