[njs] Improved working with undefined symbols.
Alexander Borisov
alexander.borisov at nginx.com
Wed May 22 18:05:22 UTC 2019
details: https://hg.nginx.org/njs/rev/88c5787352b2
branches:
changeset: 978:88c5787352b2
user: Alexander Borisov <alexander.borisov at nginx.com>
date: Wed May 22 21:01:39 2019 +0300
description:
Improved working with undefined symbols.
Throwing ReferenceError in runtime.
This closes #150 issue on GitHub.
diffstat:
njs/njs_disassembler.c | 8 ++++++++
njs/njs_generator.c | 33 ++++++++++++++++++++++++++++++---
njs/njs_variable.c | 19 +++----------------
njs/njs_variable.h | 1 +
njs/njs_vm.c | 15 +++++++++++++++
njs/njs_vm.h | 9 +++++++++
njs/test/njs_unit_test.c | 24 ++++++++++++++++++++++++
7 files changed, 90 insertions(+), 19 deletions(-)
diffs (244 lines):
diff -r 260d9d4f29ee -r 88c5787352b2 njs/njs_disassembler.c
--- a/njs/njs_disassembler.c Tue May 21 21:15:21 2019 +0300
+++ b/njs/njs_disassembler.c Wed May 22 21:01:39 2019 +0300
@@ -411,6 +411,14 @@ njs_disassemble(u_char *start, u_char *e
continue;
}
+ if (operation == njs_vmcode_reference_error) {
+ nxt_printf("%05uz REFERENCE ERROR\n", p - start);
+
+ p += sizeof(njs_vmcode_reference_error_t);
+
+ continue;
+ }
+
code_name = code_names;
n = nxt_nitems(code_names);
diff -r 260d9d4f29ee -r 88c5787352b2 njs/njs_generator.c
--- a/njs/njs_generator.c Tue May 21 21:15:21 2019 +0300
+++ b/njs/njs_generator.c Wed May 22 21:01:39 2019 +0300
@@ -174,6 +174,8 @@ static nxt_noinline nxt_int_t njs_genera
njs_generator_t *generator, njs_parser_node_t *node);
static nxt_noinline nxt_int_t njs_generate_index_release(njs_vm_t *vm,
njs_generator_t *generator, njs_index_t index);
+static nxt_int_t njs_generate_reference_error(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
static nxt_int_t njs_generate_function_debug(njs_vm_t *vm,
const nxt_str_t *name, njs_function_lambda_t *lambda,
@@ -550,7 +552,7 @@ njs_generate_name(njs_vm_t *vm, njs_gene
var = njs_variable_resolve(vm, node);
if (nxt_slow_path(var == NULL)) {
- return NXT_ERROR;
+ return njs_generate_reference_error(vm, generator, node);
}
if (var->type == NJS_VARIABLE_FUNCTION) {
@@ -606,7 +608,7 @@ njs_generate_variable(njs_vm_t *vm, njs_
index = njs_variable_index(vm, node);
if (nxt_slow_path(index == NJS_INDEX_NONE)) {
- return NXT_ERROR;
+ return njs_generate_reference_error(vm, generator, node);
}
node->index = index;
@@ -2304,7 +2306,7 @@ njs_generate_function_declaration(njs_vm
var = njs_variable_resolve(vm, node);
if (nxt_slow_path(var == NULL)) {
- return NXT_ERROR;
+ return njs_generate_reference_error(vm, generator, node);
}
if (!njs_is_function(&var->value)) {
@@ -2591,6 +2593,10 @@ njs_generate_function_call(njs_vm_t *vm,
name = node;
}
+ if (node->u.reference.not_defined) {
+ return NXT_OK;
+ }
+
njs_generate_code(generator, njs_vmcode_function_frame_t, func,
njs_vmcode_function_frame, 2, 0);
func_offset = njs_code_offset(generator, func);
@@ -3273,6 +3279,27 @@ njs_generate_index_release(njs_vm_t *vm,
static nxt_int_t
+njs_generate_reference_error(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_vmcode_reference_error_t *ref_err;
+
+ if (nxt_slow_path(!node->u.reference.not_defined)) {
+ njs_internal_error(vm, "variable is not defined but not_defined "
+ "is not set");
+ return NJS_ERROR;
+ }
+
+ njs_generate_code(generator, njs_vmcode_reference_error_t, ref_err,
+ njs_vmcode_reference_error, 0, 0);
+
+ ref_err->token_line = node->token_line;
+
+ return njs_name_copy(vm, &ref_err->name, &node->u.reference.name);
+}
+
+
+static nxt_int_t
njs_generate_function_debug(njs_vm_t *vm, const nxt_str_t *name,
njs_function_lambda_t *lambda, njs_parser_node_t *node)
{
diff -r 260d9d4f29ee -r 88c5787352b2 njs/njs_variable.c
--- a/njs/njs_variable.c Tue May 21 21:15:21 2019 +0300
+++ b/njs/njs_variable.c Wed May 22 21:01:39 2019 +0300
@@ -280,7 +280,6 @@ njs_variables_scope_resolve(njs_vm_t *vm
{
njs_ret_t ret;
nxt_queue_t *nested;
- njs_variable_t *var;
nxt_queue_link_t *lnk;
njs_parser_node_t *node;
nxt_lvlhsh_each_t lhe;
@@ -321,13 +320,7 @@ njs_variables_scope_resolve(njs_vm_t *vm
}
}
- var = njs_variable_resolve(vm, node);
-
- if (nxt_slow_path(var == NULL)) {
- if (vr->type != NJS_TYPEOF) {
- return NXT_ERROR;
- }
- }
+ (void) njs_variable_resolve(vm, node);
}
}
@@ -415,7 +408,8 @@ njs_variable_resolve(njs_vm_t *vm, njs_p
ret = njs_variable_reference_resolve(vm, vr, node->scope);
if (nxt_slow_path(ret != NXT_OK)) {
- goto not_found;
+ node->u.reference.not_defined = 1;
+ return NULL;
}
scope_index = vr->scope_index;
@@ -455,13 +449,6 @@ njs_variable_resolve(njs_vm_t *vm, njs_p
node->index = index;
return var;
-
-not_found:
-
- njs_parser_node_error(vm, node, NJS_OBJECT_REF_ERROR,
- "\"%V\" is not defined", &vr->name);
-
- return NULL;
}
diff -r 260d9d4f29ee -r 88c5787352b2 njs/njs_variable.h
--- a/njs/njs_variable.h Tue May 21 21:15:21 2019 +0300
+++ b/njs/njs_variable.h Wed May 22 21:01:39 2019 +0300
@@ -50,6 +50,7 @@ typedef struct {
njs_variable_t *variable;
njs_parser_scope_t *scope;
nxt_uint_t scope_index; /* NJS_SCOPE_INDEX_... */
+ nxt_bool_t not_defined;
} njs_variable_reference_t;
diff -r 260d9d4f29ee -r 88c5787352b2 njs/njs_vm.c
--- a/njs/njs_vm.c Tue May 21 21:15:21 2019 +0300
+++ b/njs/njs_vm.c Wed May 22 21:01:39 2019 +0300
@@ -2523,6 +2523,21 @@ njs_vmcode_finally(njs_vm_t *vm, njs_val
}
+njs_ret_t
+njs_vmcode_reference_error(njs_vm_t *vm, njs_value_t *invld1,
+ njs_value_t *invld2)
+{
+ njs_vmcode_reference_error_t *ref_err;
+
+ ref_err = (njs_vmcode_reference_error_t *) vm->current;
+
+ njs_reference_error(vm, "\"%V\" is not defined in %uD", &ref_err->name,
+ ref_err->token_line);
+
+ return NJS_ERROR;
+}
+
+
static const njs_vmcode_1addr_t njs_trap_number[] = {
{ .code = { .operation = njs_vmcode_number_primitive,
.operands = NJS_VMCODE_1OPERAND,
diff -r 260d9d4f29ee -r 88c5787352b2 njs/njs_vm.h
--- a/njs/njs_vm.h Tue May 21 21:15:21 2019 +0300
+++ b/njs/njs_vm.h Wed May 22 21:01:39 2019 +0300
@@ -849,6 +849,13 @@ typedef struct {
} njs_vmcode_finally_t;
+typedef struct {
+ njs_vmcode_t code;
+ nxt_str_t name;
+ uint32_t token_line;
+} njs_vmcode_reference_error_t;
+
+
typedef enum {
NJS_SCOPE_ABSOLUTE = 0,
NJS_SCOPE_GLOBAL = 1,
@@ -1303,6 +1310,8 @@ njs_ret_t njs_vmcode_catch(njs_vm_t *vm,
njs_value_t *exception);
njs_ret_t njs_vmcode_finally(njs_vm_t *vm, njs_value_t *invld,
njs_value_t *retval);
+njs_ret_t njs_vmcode_reference_error(njs_vm_t *vm, njs_value_t *invld1,
+ njs_value_t *invld2);
nxt_bool_t njs_values_strict_equal(const njs_value_t *val1,
const njs_value_t *val2);
diff -r 260d9d4f29ee -r 88c5787352b2 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Tue May 21 21:15:21 2019 +0300
+++ b/njs/test/njs_unit_test.c Wed May 22 21:01:39 2019 +0300
@@ -6294,8 +6294,32 @@ static njs_unit_test_t njs_test[] =
nxt_string("a") },
{ nxt_string("function f() { var a = f2(); }"),
+ nxt_string("undefined") },
+
+ { nxt_string("function f() { var a = f2(); } f();"),
nxt_string("ReferenceError: \"f2\" is not defined in 1") },
+ { nxt_string("typeof Buffer !== 'undefined' ? Buffer : function Buffer(){}"),
+ nxt_string("[object Function]") },
+
+ { nxt_string("1 == 2 ? func() : '123'"),
+ nxt_string("123") },
+
+ { nxt_string("1 == 1 ? func() : '123'"),
+ nxt_string("ReferenceError: \"func\" is not defined in 1") },
+
+ { nxt_string("function f(){ if (1 == 1) { 1 == 2 ? some_var : '123' } }; f()"),
+ nxt_string("undefined") },
+
+ { nxt_string("function f(){ if (1 == 1) { 1 == 1 ? some_var : '123' } }; f()"),
+ nxt_string("ReferenceError: \"some_var\" is not defined in 1") },
+
+ { nxt_string("function f(){ if (1 == 1) { 1 == 2 ? some_func() : '123' } }; f()"),
+ nxt_string("undefined") },
+
+ { nxt_string("function f(){ if (1 == 1) { 1 == 1 ? some_func() : '123' } }; f()"),
+ nxt_string("ReferenceError: \"some_func\" is not defined in 1") },
+
{ nxt_string("(function(){ function f() {return f}; return f()})()"),
nxt_string("[object Function]") },
More information about the nginx-devel
mailing list