From fbdfaa23b3a2a62757e85592b6090e8c88475ac6 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Wed, 24 Feb 2021 14:48:20 +0000 Subject: [PATCH] Decoupling parser structure from the main VM structure. vm->parser is only needed during parsing phase, so it can be eliminated. This improves dependencies tracking and readability. As a side effect it fixes #372 issue on Github: previously, Function constructor left VM context in inconsistent state if compilation failed. The direct root cause was that a function object was created, but because Function constructor ended prematurely the object was not fully initialized. This is not a problem by itself because usually this partially created object cannot be referenced. In the accumulative mode, which is only enabled in CLI, vm->parser was used to store the references to the variables from the previous iteration. --- src/njs_builtin.c | 6 +-- src/njs_function.c | 22 ++++------- src/njs_module.c | 10 +++-- src/njs_parser.c | 84 +++++++++++++++------------------------- src/njs_parser.h | 9 ++--- src/njs_regexp.c | 8 +--- src/njs_shell.c | 10 ++--- src/njs_variable.c | 23 ++++++----- src/njs_variable.h | 4 +- src/njs_vm.c | 63 +++++++++--------------------- src/njs_vm.h | 1 - src/test/njs_unit_test.c | 20 +++++++--- 12 files changed, 102 insertions(+), 158 deletions(-) diff --git a/src/njs_builtin.c b/src/njs_builtin.c index 2280cfa2..1d6ff5d0 100644 --- a/src/njs_builtin.c +++ b/src/njs_builtin.c @@ -613,10 +613,6 @@ njs_vm_expression_completions(njs_vm_t *vm, njs_str_t *expression) njs_lvlhsh_query_t lhq; njs_variable_node_t var_node; - if (njs_slow_path(vm->parser == NULL)) { - return NULL; - } - p = expression->start; end = p + expression->length; @@ -635,7 +631,7 @@ njs_vm_expression_completions(njs_vm_t *vm, njs_str_t *expression) var_node.key = (uintptr_t) lhq.value; - node = njs_rbtree_find(&vm->parser->scope->variables, &var_node.node); + node = njs_rbtree_find(vm->variables_hash, &var_node.node); if (njs_slow_path(node == NULL)) { return NULL; } diff --git a/src/njs_function.c b/src/njs_function.c index a6653a1d..c8679c42 100644 --- a/src/njs_function.c +++ b/src/njs_function.c @@ -874,7 +874,7 @@ njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_str_t str, file; njs_uint_t i; njs_lexer_t lexer; - njs_parser_t *parser; + njs_parser_t parser; njs_vm_code_t *code; njs_function_t *function; njs_generator_t generator; @@ -926,15 +926,6 @@ njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - vm->options.accumulative = 1; - - parser = njs_mp_zalloc(vm->mem_pool, sizeof(njs_parser_t)); - if (njs_slow_path(parser == NULL)) { - return NJS_ERROR; - } - - vm->parser = parser; - file = njs_str_value("runtime"); ret = njs_lexer_init(vm, &lexer, &file, str.start, str.start + str.length); @@ -942,10 +933,11 @@ njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return ret; } - parser->vm = vm; - parser->lexer = &lexer; + njs_memzero(&parser, sizeof(njs_parser_t)); + + parser.lexer = &lexer; - ret = njs_parser(parser, NULL); + ret = njs_parser(vm, &parser, NULL); if (njs_slow_path(ret != NJS_OK)) { return ret; } @@ -957,7 +949,7 @@ njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, * the global object in a portable way. */ - node = parser->node; + node = parser.node; type = &safe_ast[0]; for (; *type != NJS_TOKEN_ILLEGAL; type++, node = node->right) { @@ -971,7 +963,7 @@ njs_function_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - scope = parser->scope; + scope = parser.scope; ret = njs_variables_copy(vm, &scope->variables, vm->variables_hash); if (njs_slow_path(ret != NJS_OK)) { diff --git a/src/njs_module.c b/src/njs_module.c index 31ea7ee0..92edbb90 100644 --- a/src/njs_module.c +++ b/src/njs_module.c @@ -40,7 +40,7 @@ static njs_int_t njs_module_read(njs_vm_t *vm, int fd, njs_str_t *body); static njs_module_t *njs_module_find(njs_vm_t *vm, njs_str_t *name, njs_bool_t local); static njs_module_t *njs_module_add(njs_vm_t *vm, njs_str_t *name); -static njs_int_t njs_module_insert(njs_vm_t *vm, njs_module_t *module); +static njs_int_t njs_module_insert(njs_parser_t *parser, njs_module_t *module); njs_int_t @@ -273,7 +273,7 @@ njs_parser_module_after(njs_parser_t *parser, njs_lexer_token_t *token, module = (njs_module_t *) parser->target; if (module->index == 0) { - ret = njs_module_insert(parser->vm, module); + ret = njs_module_insert(parser, module); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -564,12 +564,14 @@ njs_module_add(njs_vm_t *vm, njs_str_t *name) static njs_int_t -njs_module_insert(njs_vm_t *vm, njs_module_t *module) +njs_module_insert(njs_parser_t *parser, njs_module_t *module) { + njs_vm_t *vm; njs_module_t **value; njs_parser_scope_t *scope; - scope = njs_parser_global_scope(vm); + scope = njs_parser_global_scope(parser); + vm = parser->vm; module->index = njs_scope_next_index(vm, scope, NJS_SCOPE_INDEX_LOCAL, &njs_value_undefined); diff --git a/src/njs_parser.c b/src/njs_parser.c index 879459e9..65347c56 100644 --- a/src/njs_parser.c +++ b/src/njs_parser.c @@ -503,23 +503,26 @@ njs_parser_reject(njs_parser_t *parser) njs_int_t -njs_parser(njs_parser_t *parser, njs_parser_t *prev) +njs_parser(njs_vm_t *vm, njs_parser_t *parser, njs_rbtree_t *prev_vars) { njs_int_t ret; njs_lexer_token_t *token; + parser->vm = vm; + + njs_set_undefined(&vm->retval); + ret = njs_parser_scope_begin(parser, NJS_SCOPE_GLOBAL); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - if (prev != NULL) { + if (prev_vars != NULL) { /* * Copy the global scope variables from the previous * iteration of the accumulative mode. */ - ret = njs_variables_copy(parser->vm, &parser->scope->variables, - &prev->scope->variables); + ret = njs_variables_copy(vm, &parser->scope->variables, prev_vars); if (ret != NJS_OK) { return ret; } @@ -551,7 +554,7 @@ njs_parser(njs_parser_t *parser, njs_parser_t *prev) return NJS_ERROR; } - if (njs_is_error(&parser->vm->retval)) { + if (njs_is_error(&vm->retval)) { return NJS_ERROR; } @@ -1196,11 +1199,14 @@ njs_parser_regexp_literal(njs_parser_t *parser, njs_lexer_token_t *token, { u_char *p; njs_str_t text; + njs_int_t ret; njs_lexer_t *lexer; - njs_value_t *value; + njs_value_t *value, retval; njs_regexp_flags_t flags; njs_regexp_pattern_t *pattern; + static const njs_value_t string_message = njs_string("message"); + value = &parser->node->u.value; lexer = parser->lexer; @@ -1269,6 +1275,18 @@ njs_parser_regexp_literal(njs_parser_t *parser, njs_lexer_token_t *token, text.length, flags); if (njs_slow_path(pattern == NULL)) { + ret = njs_value_property(parser->vm, &parser->vm->retval, + njs_value_arg(&string_message), + &retval); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + njs_string_get(&retval, &text); + njs_value_undefined_set(&parser->vm->retval); + + njs_parser_syntax_error(parser, "%V", &text); + return NJS_ERROR; } @@ -6460,7 +6478,7 @@ njs_parser_function_declaration(njs_parser_t *parser, njs_lexer_token_t *token, njs_lexer_consume_token(parser->lexer, 1); - var = njs_variable_add(parser->vm, parser->scope, unique_id, + var = njs_variable_add(parser, parser->scope, unique_id, NJS_VARIABLE_FUNCTION); if (var == NULL) { return NJS_ERROR; @@ -6552,7 +6570,7 @@ njs_parser_function_expression(njs_parser_t *parser, njs_lexer_token_t *token, } if (njs_lexer_token_is_binding_identifier(token)) { - var = njs_variable_add(parser->vm, parser->scope, token->unique_id, + var = njs_variable_add(parser, parser->scope, token->unique_id, NJS_VARIABLE_SHIM); if (var == NULL) { return NJS_ERROR; @@ -6649,7 +6667,7 @@ njs_parser_formal_parameters(njs_parser_t *parser, njs_lexer_token_t *token, default: /* SingleNameBinding */ if (njs_lexer_token_is_binding_identifier(token)) { - arg = njs_variable_add(parser->vm, parser->scope, + arg = njs_variable_add(parser, parser->scope, token->unique_id, NJS_VARIABLE_VAR); if (arg == NULL) { return NJS_ERROR; @@ -6764,7 +6782,7 @@ njs_parser_arrow_function(njs_parser_t *parser, njs_lexer_token_t *token, njs_parser_arrow_function_args_after); } else if (njs_lexer_token_is_binding_identifier(token)) { - arg = njs_variable_add(parser->vm, parser->scope, + arg = njs_variable_add(parser, parser->scope, token->unique_id, NJS_VARIABLE_VAR); if (arg == NULL) { return NJS_ERROR; @@ -7517,7 +7535,7 @@ njs_parser_variable_node(njs_parser_t *parser, uintptr_t unique_id, njs_variable_t *var; njs_parser_node_t *node; - var = njs_variable_add(parser->vm, parser->scope, unique_id, type); + var = njs_variable_add(parser, parser->scope, unique_id, type); if (njs_slow_path(var == NULL)) { return NULL; } @@ -7590,7 +7608,7 @@ njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token) return NULL; } - var = njs_variable_add(parser->vm, scope, token->unique_id, + var = njs_variable_add(parser, scope, token->unique_id, NJS_VARIABLE_VAR); if (njs_slow_path(var == NULL)) { return NULL; @@ -7625,7 +7643,7 @@ njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token) return NULL; } - var = njs_variable_add(parser->vm, scope, token->unique_id, + var = njs_variable_add(parser, scope, token->unique_id, NJS_VARIABLE_VAR); if (njs_slow_path(var == NULL)) { return NULL; @@ -8319,46 +8337,6 @@ njs_parser_unexpected_token(njs_vm_t *vm, njs_parser_t *parser, } -u_char * -njs_parser_trace_handler(njs_trace_t *trace, njs_trace_data_t *td, - u_char *start) -{ - u_char *p; - size_t size; - njs_vm_t *vm; - njs_lexer_t *lexer; - njs_parser_t *parser; - - size = njs_length("InternalError: "); - memcpy(start, "InternalError: ", size); - p = start + size; - - vm = trace->data; - - trace = trace->next; - p = trace->handler(trace, td, p); - - parser = vm->parser; - - if (parser != NULL && parser->lexer != NULL) { - lexer = parser->lexer; - - if (lexer->file.length != 0) { - njs_internal_error(vm, "%s in %V:%uD", start, &lexer->file, - parser->lexer->token->line); - } else { - njs_internal_error(vm, "%s in %uD", start, - parser->lexer->token->line); - } - - } else { - njs_internal_error(vm, "%s", start); - } - - return p; -} - - static void njs_parser_scope_error(njs_vm_t *vm, njs_parser_scope_t *scope, njs_object_type_t type, uint32_t line, const char *fmt, va_list args) diff --git a/src/njs_parser.h b/src/njs_parser.h index 62c6e5f3..4fe8ea5e 100644 --- a/src/njs_parser.h +++ b/src/njs_parser.h @@ -110,7 +110,8 @@ njs_int_t njs_parser_failed_state(njs_parser_t *parser, intptr_t njs_parser_scope_rbtree_compare(njs_rbtree_node_t *node1, njs_rbtree_node_t *node2); -njs_int_t njs_parser(njs_parser_t *parser, njs_parser_t *prev); +njs_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser, + njs_rbtree_t *prev_vars); njs_int_t njs_parser_module_lambda(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current); @@ -121,8 +122,6 @@ njs_token_type_t njs_parser_unexpected_token(njs_vm_t *vm, njs_parser_t *parser, njs_str_t *name, njs_token_type_t type); njs_int_t njs_parser_string_create(njs_vm_t *vm, njs_lexer_token_t *token, njs_value_t *value); -u_char *njs_parser_trace_handler(njs_trace_t *trace, njs_trace_data_t *td, - u_char *start); void njs_parser_lexer_error(njs_parser_t *parser, njs_object_type_t type, const char *fmt, ...); void njs_parser_node_error(njs_vm_t *vm, njs_parser_node_t *node, @@ -201,11 +200,11 @@ njs_parser_node_string(njs_vm_t *vm, njs_lexer_token_t *token, njs_inline njs_parser_scope_t * -njs_parser_global_scope(njs_vm_t *vm) +njs_parser_global_scope(njs_parser_t *parser) { njs_parser_scope_t *scope; - scope = vm->parser->scope; + scope = parser->scope; while (scope->type != NJS_SCOPE_GLOBAL) { scope = scope->parent; diff --git a/src/njs_regexp.c b/src/njs_regexp.c index 81dd2e5c..00a73e77 100644 --- a/src/njs_regexp.c +++ b/src/njs_regexp.c @@ -536,13 +536,7 @@ njs_regexp_compile_trace_handler(njs_trace_t *trace, njs_trace_data_t *td, trace = trace->next; p = trace->handler(trace, td, start); - if (vm->parser != NULL && vm->parser->lexer != NULL) { - njs_syntax_error(vm, "%*s in %uD", p - start, start, - vm->parser->lexer->line); - - } else { - njs_syntax_error(vm, "%*s", p - start, start); - } + njs_syntax_error(vm, "%*s", p - start, start); return p; } diff --git a/src/njs_shell.c b/src/njs_shell.c index be7a90df..8c5cf679 100644 --- a/src/njs_shell.c +++ b/src/njs_shell.c @@ -996,8 +996,8 @@ njs_completion_generator(const char *text, int state) cmpl->length = njs_strlen(text); cmpl->suffix_completions = NULL; - if (vm->parser != NULL) { - cmpl->node = njs_rbtree_min(&vm->parser->scope->variables); + if (vm->variables_hash != NULL) { + cmpl->node = njs_rbtree_min(vm->variables_hash); } } @@ -1005,12 +1005,12 @@ next: switch (cmpl->phase) { case NJS_COMPLETION_VAR: - if (vm->parser == NULL) { + variables = vm->variables_hash; + + if (variables == NULL) { njs_next_phase(cmpl); } - variables = &vm->parser->scope->variables; - while (njs_rbtree_is_there_successor(variables, cmpl->node)) { var_node = (njs_variable_node_t *) cmpl->node; diff --git a/src/njs_variable.c b/src/njs_variable.c index 57d43b57..6d485f71 100644 --- a/src/njs_variable.c +++ b/src/njs_variable.c @@ -9,7 +9,7 @@ #include -static njs_variable_t *njs_variable_scope_add(njs_vm_t *vm, +static njs_variable_t *njs_variable_scope_add(njs_parser_t *parser, njs_parser_scope_t *scope, uintptr_t unique_id, njs_variable_type_t type); static njs_int_t njs_variable_reference_resolve(njs_vm_t *vm, njs_variable_reference_t *vr, njs_parser_scope_t *node_scope); @@ -18,12 +18,12 @@ static njs_variable_t *njs_variable_alloc(njs_vm_t *vm, uintptr_t unique_id, njs_variable_t * -njs_variable_add(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t unique_id, - njs_variable_type_t type) +njs_variable_add(njs_parser_t *parser, njs_parser_scope_t *scope, + uintptr_t unique_id, njs_variable_type_t type) { njs_variable_t *var; - var = njs_variable_scope_add(vm, scope, unique_id, type); + var = njs_variable_scope_add(parser, scope, unique_id, type); if (njs_slow_path(var == NULL)) { return NULL; } @@ -33,7 +33,7 @@ njs_variable_add(njs_vm_t *vm, njs_parser_scope_t *scope, uintptr_t unique_id, do { scope = scope->parent; - var = njs_variable_scope_add(vm, scope, unique_id, type); + var = njs_variable_scope_add(parser, scope, unique_id, type); if (njs_slow_path(var == NULL)) { return NULL; } @@ -78,7 +78,7 @@ njs_variables_copy(njs_vm_t *vm, njs_rbtree_t *variables, static njs_variable_t * -njs_variable_scope_add(njs_vm_t *vm, njs_parser_scope_t *scope, +njs_variable_scope_add(njs_parser_t *parser, njs_parser_scope_t *scope, uintptr_t unique_id, njs_variable_type_t type) { njs_variable_t *var; @@ -104,7 +104,7 @@ njs_variable_scope_add(njs_vm_t *vm, njs_parser_scope_t *scope, if (scope->type == NJS_SCOPE_GLOBAL) { - if (vm->options.module) { + if (parser->vm->options.module) { if (type == NJS_VARIABLE_FUNCTION || var->type == NJS_VARIABLE_FUNCTION) { @@ -116,12 +116,12 @@ njs_variable_scope_add(njs_vm_t *vm, njs_parser_scope_t *scope, return var; } - var = njs_variable_alloc(vm, unique_id, type); + var = njs_variable_alloc(parser->vm, unique_id, type); if (njs_slow_path(var == NULL)) { goto memory_error; } - var_node_new = njs_variable_node_alloc(vm, var, unique_id); + var_node_new = njs_variable_node_alloc(parser->vm, var, unique_id); if (njs_slow_path(var_node_new == NULL)) { goto memory_error; } @@ -132,7 +132,7 @@ njs_variable_scope_add(njs_vm_t *vm, njs_parser_scope_t *scope, memory_error: - njs_memory_error(vm); + njs_memory_error(parser->vm); return NULL; @@ -140,8 +140,7 @@ fail: entry = njs_lexer_entry(unique_id); - njs_parser_syntax_error(vm->parser, - "\"%V\" has already been declared", + njs_parser_syntax_error(parser, "\"%V\" has already been declared", &entry->name); return NULL; } diff --git a/src/njs_variable.h b/src/njs_variable.h index f843a844..03348812 100644 --- a/src/njs_variable.h +++ b/src/njs_variable.h @@ -55,8 +55,8 @@ typedef struct { } njs_variable_node_t; -njs_variable_t *njs_variable_add(njs_vm_t *vm, njs_parser_scope_t *scope, - uintptr_t unique_id, njs_variable_type_t type); +njs_variable_t *njs_variable_add(njs_parser_t *parser, + njs_parser_scope_t *scope, uintptr_t unique_id, njs_variable_type_t type); njs_int_t njs_variables_copy(njs_vm_t *vm, njs_rbtree_t *variables, njs_rbtree_t *prev_variables); njs_variable_t * njs_label_add(njs_vm_t *vm, njs_parser_scope_t *scope, diff --git a/src/njs_vm.c b/src/njs_vm.c index bb6018ce..a4e708ec 100644 --- a/src/njs_vm.c +++ b/src/njs_vm.c @@ -68,7 +68,6 @@ njs_vm_create(njs_vm_opt_t *options) vm->trace.level = NJS_LEVEL_TRACE; vm->trace.size = 2048; - vm->trace.handler = njs_parser_trace_handler; vm->trace.data = vm; njs_set_undefined(&vm->retval); @@ -113,66 +112,48 @@ njs_vm_destroy(njs_vm_t *vm) njs_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end) { - njs_int_t ret; - njs_str_t ast; - njs_chb_t chain; - njs_lexer_t lexer; - njs_parser_t *parser, *prev; - njs_vm_code_t *code; - njs_generator_t generator; - njs_parser_scope_t *scope; - - if (vm->parser != NULL && !vm->options.accumulative) { - return NJS_ERROR; - } + njs_int_t ret; + njs_str_t ast; + njs_chb_t chain; + njs_lexer_t lexer; + njs_parser_t parser; + njs_vm_code_t *code; + njs_generator_t generator; if (vm->modules != NULL && vm->options.accumulative) { njs_module_reset(vm); } - parser = njs_mp_zalloc(vm->mem_pool, sizeof(njs_parser_t)); - if (njs_slow_path(parser == NULL)) { - return NJS_ERROR; - } - - prev = vm->parser; - vm->parser = parser; - ret = njs_lexer_init(vm, &lexer, &vm->options.file, *start, end); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } - parser->vm = vm; - parser->lexer = &lexer; + njs_memzero(&parser, sizeof(njs_parser_t)); - njs_set_undefined(&vm->retval); + parser.lexer = &lexer; - ret = njs_parser(parser, prev); + ret = njs_parser(vm, &parser, vm->variables_hash); if (njs_slow_path(ret != NJS_OK)) { - goto fail; + return NJS_ERROR; } - parser->lexer = NULL; - - scope = parser->scope; + *start = lexer.start; - ret = njs_variables_scope_reference(vm, scope); + ret = njs_variables_scope_reference(vm, parser.scope); if (njs_slow_path(ret != NJS_OK)) { - goto fail; + return NJS_ERROR; } - *start = lexer.start; - njs_memzero(&generator, sizeof(njs_generator_t)); - code = njs_generate_scope(vm, &generator, scope, &njs_entry_main); + code = njs_generate_scope(vm, &generator, parser.scope, &njs_entry_main); if (njs_slow_path(code == NULL)) { if (!njs_is_error(&vm->retval)) { njs_internal_error(vm, "njs_generate_scope() failed"); } - goto fail; + return NJS_ERROR; } vm->main_index = code - (njs_vm_code_t *) vm->codes->start; @@ -180,7 +161,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end) vm->global_scope = generator.local_scope; vm->scope_size = generator.scope_size; - vm->variables_hash = &scope->variables; + vm->variables_hash = &parser.scope->variables; if (vm->options.init && !vm->options.accumulative) { ret = njs_vm_init(vm); @@ -195,7 +176,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end) if (njs_slow_path(vm->options.ast)) { njs_chb_init(&chain, vm->mem_pool); - ret = njs_parser_serialize_ast(parser->node, &chain); + ret = njs_parser_serialize_ast(parser.node, &chain); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -210,13 +191,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end) njs_mp_free(vm->mem_pool, ast.start); } - return ret; - -fail: - - vm->parser = prev; - - return NJS_ERROR; + return NJS_OK; } diff --git a/src/njs_vm.h b/src/njs_vm.h index 3f63b7ab..c2329085 100644 --- a/src/njs_vm.h +++ b/src/njs_vm.h @@ -218,7 +218,6 @@ struct njs_vm_s { size_t stack_size; njs_vm_shared_t *shared; - njs_parser_t *parser; njs_regex_context_t *regex_context; njs_regex_match_data_t *single_match_data; diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 23588d22..722f7073 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -12696,25 +12696,26 @@ static njs_unit_test_t njs_test[] = njs_str("1") }, { njs_str("var sum = new Function('a', 'b', 'return a + b');" - "sum(2, 4);"), + "sum(2, 4);"), njs_str("6") }, { njs_str("var sum = new Function('a, b', 'return a + b');" - "sum(2, 4);"), + "sum(2, 4);"), njs_str("6") }, { njs_str("var sum = new Function('a, b', 'c', 'return a + b + c');" - "sum(2, 4, 4);"), + "sum(2, 4, 4);"), njs_str("10") }, { njs_str("(new Function({ toString() { return '...a'; }}, { toString() { return 'return a;' }}))(1,2,3)"), njs_str("1,2,3") }, { njs_str("var x = 10; function foo() { var x = 20; return new Function('return x;'); }" - "var f = foo(); f()"), + "var f = foo(); f()"), njs_str("10") }, - { njs_str("var fn = (function() { return new Function('return this'); }).call({}), o = {}; fn.call(o) == o && fn.bind(o).call(this) == o"), + { njs_str("var fn = (function() { return new Function('return this'); }).call({}), o = {}; " + "fn.call(o) == o && fn.bind(o).call(this) == o"), njs_str("true") }, { njs_str("(new Function('return this'))() === globalThis"), @@ -12733,6 +12734,10 @@ static njs_unit_test_t njs_test[] = { njs_str("var o = {}; (new Function('return this')).call(o) === o"), njs_str("true") }, + { njs_str("(new Function('function foo(){return 1}; return foo()'))();" + "foo"), + njs_str("ReferenceError: \"foo\" is not defined") }, + { njs_str("this.NN = {}; var f = Function('eval = 42;'); f()"), njs_str("SyntaxError: Identifier \"eval\" is forbidden as left-hand in assignment in runtime:1") }, @@ -20315,6 +20320,11 @@ static njs_unit_test_t njs_shell_test[] = "Number.prototype.test" ENTER), njs_str("test") }, + { njs_str("try {(new Function('function foo(){return 1}; ()=>{}breakhere'))} catch (e) {}" ENTER + "foo()" ENTER), + njs_str("ReferenceError: \"foo\" is not defined\n" + " at main (:1)\n") }, + /* Error handling */ { njs_str("var a = ;" ENTER -- 2.47.3