[njs] Fixed the names of global functions in backtraces.
Dmitry Volyntsev
xeioex at nginx.com
Tue Feb 20 16:19:28 UTC 2018
details: http://hg.nginx.org/njs/rev/757271547b56
branches:
changeset: 450:757271547b56
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Tue Feb 20 19:12:55 2018 +0300
description:
Fixed the names of global functions in backtraces.
Previously, they were reported as 'native (native)'.
diffstat:
njs/njs_builtin.c | 92 ++++++++++++++++++++---------------
njs/njs_extern.c | 102 ++++++++++++++++++++++++++++++++++++++++
njs/njs_extern.h | 4 +
njs/njs_function.c | 2 +-
njs/njs_module.c | 7 ++
njs/njs_module.h | 1 +
njs/njs_number.c | 28 ++++++++++
njs/njs_number.h | 5 +
njs/njs_string.c | 35 +++++++++++++
njs/njs_string.h | 6 ++
njs/njs_vm.c | 12 +++-
njs/test/njs_expect_test.exp | 6 ++
njs/test/njs_interactive_test.c | 10 +++
13 files changed, 268 insertions(+), 42 deletions(-)
diffs (463 lines):
diff -r 18e0275576a3 -r 757271547b56 njs/njs_builtin.c
--- a/njs/njs_builtin.c Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/njs_builtin.c Tue Feb 20 19:12:55 2018 +0300
@@ -102,6 +102,38 @@ const njs_object_init_t *njs_construc
};
+const njs_object_init_t *njs_function_init[] = {
+ &njs_eval_function_init,
+ &njs_to_string_function_init,
+ &njs_is_nan_function_init,
+ &njs_is_finite_function_init,
+ &njs_parse_int_function_init,
+ &njs_parse_float_function_init,
+ &njs_encode_uri_function_init,
+ &njs_encode_uri_component_function_init,
+ &njs_decode_uri_function_init,
+ &njs_decode_uri_component_function_init,
+ &njs_require_function_init
+};
+
+
+const njs_function_init_t njs_native_functions[] = {
+ /* SunC does not allow empty array initialization. */
+ { njs_eval_function, { 0 } },
+ { njs_object_prototype_to_string, { 0 } },
+ { njs_number_global_is_nan, { NJS_SKIP_ARG, NJS_NUMBER_ARG } },
+ { njs_number_is_finite, { NJS_SKIP_ARG, NJS_NUMBER_ARG } },
+ { njs_number_parse_int,
+ { NJS_SKIP_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG } },
+ { njs_number_parse_float, { NJS_SKIP_ARG, NJS_STRING_ARG } },
+ { njs_string_encode_uri, { NJS_SKIP_ARG, NJS_STRING_ARG } },
+ { njs_string_encode_uri_component, { NJS_SKIP_ARG, NJS_STRING_ARG } },
+ { njs_string_decode_uri, { NJS_SKIP_ARG, NJS_STRING_ARG } },
+ { njs_string_decode_uri_component, { NJS_SKIP_ARG, NJS_STRING_ARG } },
+ { njs_module_require, { NJS_SKIP_ARG, NJS_STRING_ARG } },
+};
+
+
static njs_ret_t
njs_prototype_function(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
@@ -190,36 +222,6 @@ njs_builtin_objects_create(njs_vm_t *vm)
{ njs_memory_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } },
};
- static const njs_object_init_t *function_init[] = {
- &njs_eval_function_init, /* eval */
- NULL, /* toString */
- NULL, /* isNaN */
- NULL, /* isFinite */
- NULL, /* parseInt */
- NULL, /* parseFloat */
- NULL, /* encodeURI */
- NULL, /* encodeURIComponent */
- NULL, /* decodeURI */
- NULL, /* decodeURIComponent */
- NULL, /* require */
- };
-
- static const njs_function_init_t native_functions[] = {
- /* SunC does not allow empty array initialization. */
- { njs_eval_function, { 0 } },
- { njs_object_prototype_to_string, { 0 } },
- { njs_number_global_is_nan, { NJS_SKIP_ARG, NJS_NUMBER_ARG } },
- { njs_number_is_finite, { NJS_SKIP_ARG, NJS_NUMBER_ARG } },
- { njs_number_parse_int,
- { NJS_SKIP_ARG, NJS_STRING_ARG, NJS_INTEGER_ARG } },
- { njs_number_parse_float, { NJS_SKIP_ARG, NJS_STRING_ARG } },
- { njs_string_encode_uri, { NJS_SKIP_ARG, NJS_STRING_ARG } },
- { njs_string_encode_uri_component, { NJS_SKIP_ARG, NJS_STRING_ARG } },
- { njs_string_decode_uri, { NJS_SKIP_ARG, NJS_STRING_ARG } },
- { njs_string_decode_uri_component, { NJS_SKIP_ARG, NJS_STRING_ARG } },
- { njs_module_require, { NJS_SKIP_ARG, NJS_STRING_ARG } },
- };
-
static const njs_object_prop_t null_proto_property = {
.type = NJS_WHITEOUT,
.name = njs_string("__proto__"),
@@ -293,10 +295,10 @@ njs_builtin_objects_create(njs_vm_t *vm)
functions = vm->shared->functions;
for (i = NJS_FUNCTION_EVAL; i < NJS_FUNCTION_MAX; i++) {
- if (function_init[i] != NULL) {
+ if (njs_function_init[i]->items != 0) {
ret = njs_object_hash_create(vm, &functions[i].object.shared_hash,
- function_init[i]->properties,
- function_init[i]->items);
+ njs_function_init[i]->properties,
+ njs_function_init[i]->items);
if (nxt_slow_path(ret != NXT_OK)) {
return NXT_ERROR;
}
@@ -306,12 +308,12 @@ njs_builtin_objects_create(njs_vm_t *vm)
functions[i].object.extensible = 1;
functions[i].native = 1;
functions[i].args_offset = 1;
- functions[i].u.native = native_functions[i].native;
- functions[i].args_types[0] = native_functions[i].args_types[0];
- functions[i].args_types[1] = native_functions[i].args_types[1];
- functions[i].args_types[2] = native_functions[i].args_types[2];
- functions[i].args_types[3] = native_functions[i].args_types[3];
- functions[i].args_types[4] = native_functions[i].args_types[4];
+ functions[i].u.native = njs_native_functions[i].native;
+ functions[i].args_types[0] = njs_native_functions[i].args_types[0];
+ functions[i].args_types[1] = njs_native_functions[i].args_types[1];
+ functions[i].args_types[2] = njs_native_functions[i].args_types[2];
+ functions[i].args_types[3] = njs_native_functions[i].args_types[3];
+ functions[i].args_types[4] = njs_native_functions[i].args_types[4];
}
prototypes = vm->shared->prototypes;
@@ -1022,6 +1024,18 @@ njs_builtin_match_native_function(njs_vm
}
}
+ for (i = NJS_FUNCTION_EVAL; i < NJS_FUNCTION_MAX; i++) {
+ if (njs_function_init[i] == NULL) {
+ continue;
+ }
+
+ if (function->u.native == njs_native_functions[i].native) {
+ *name = njs_function_init[i]->name;
+
+ return NXT_OK;
+ }
+ }
+
nxt_lvlhsh_each_init(&lhe, &njs_modules_hash_proto);
for ( ;; ) {
diff -r 18e0275576a3 -r 757271547b56 njs/njs_extern.c
--- a/njs/njs_extern.c Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/njs_extern.c Tue Feb 20 19:12:55 2018 +0300
@@ -22,6 +22,15 @@
#include <njs_variable.h>
#include <njs_parser.h>
#include <string.h>
+#include <stdio.h>
+
+
+typedef struct njs_extern_part_s njs_extern_part_t;
+
+struct njs_extern_part_s {
+ njs_extern_part_t *next;
+ nxt_str_t str;
+};
static nxt_int_t
@@ -242,3 +251,96 @@ njs_parser_external(njs_vm_t *vm, njs_pa
return NULL;
}
+
+
+static nxt_int_t
+njs_external_match(njs_vm_t *vm, njs_function_native_t func, njs_extern_t *ext,
+ nxt_str_t *name, njs_extern_part_t *head, njs_extern_part_t *ppart)
+{
+ char *buf, *p;
+ size_t len;
+ nxt_int_t ret;
+ njs_extern_t *prop;
+ njs_extern_part_t part, *pr;
+ nxt_lvlhsh_each_t lhe;
+
+ ppart->next = ∂
+
+ nxt_lvlhsh_each_init(&lhe, &njs_extern_hash_proto);
+
+ for ( ;; ) {
+ prop = nxt_lvlhsh_each(&ext->hash, &lhe);
+ if (prop == NULL) {
+ break;
+ }
+
+ part.next = NULL;
+ part.str = prop->name;
+
+ if (prop->function && prop->function->u.native == func) {
+ goto found;
+ }
+
+ ret = njs_external_match(vm, func, prop, name, head, &part);
+ if (ret != NXT_DECLINED) {
+ return ret;
+ }
+ }
+
+ return NXT_DECLINED;
+
+found:
+
+ len = 0;
+
+ for (pr = head; pr != NULL; pr = pr->next) {
+ len += pr->str.length + sizeof(".") - 1;
+ }
+
+ buf = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
+ if (buf == NULL) {
+ return NXT_ERROR;
+ }
+
+ p = buf;
+
+ for (pr = head; pr != NULL; pr = pr->next) {
+ p += snprintf(p, buf + len - p, "%.*s.", (int) pr->str.length,
+ pr->str.start);
+ }
+
+ name->start = (u_char *) buf;
+ name->length = len;
+
+ return NXT_OK;
+}
+
+
+nxt_int_t
+njs_external_match_native_function(njs_vm_t *vm, njs_function_native_t func,
+ nxt_str_t *name)
+{
+ nxt_int_t ret;
+ njs_extern_t *ext;
+ njs_extern_part_t part;
+ nxt_lvlhsh_each_t lhe;
+
+ nxt_lvlhsh_each_init(&lhe, &njs_extern_hash_proto);
+
+ for ( ;; ) {
+ ext = nxt_lvlhsh_each(&vm->external_prototypes_hash, &lhe);
+ if (ext == NULL) {
+ break;
+ }
+
+ part.next = NULL;
+ part.str = ext->name;
+
+ ret = njs_external_match(vm, func, ext, name, &part, &part);
+ if (ret != NXT_DECLINED) {
+ return ret;
+ }
+ }
+
+ return NXT_DECLINED;
+}
diff -r 18e0275576a3 -r 757271547b56 njs/njs_extern.h
--- a/njs/njs_extern.h Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/njs_extern.h Tue Feb 20 19:12:55 2018 +0300
@@ -38,6 +38,10 @@ typedef struct {
} njs_extern_value_t;
+nxt_int_t njs_external_match_native_function(njs_vm_t *vm,
+ njs_function_native_t func, nxt_str_t *name);
+
+
extern const nxt_lvlhsh_proto_t njs_extern_hash_proto;
extern const nxt_lvlhsh_proto_t njs_extern_value_hash_proto;
diff -r 18e0275576a3 -r 757271547b56 njs/njs_function.c
--- a/njs/njs_function.c Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/njs_function.c Tue Feb 20 19:12:55 2018 +0300
@@ -723,7 +723,7 @@ static const njs_object_prop_t njs_eval
const njs_object_init_t njs_eval_function_init = {
- nxt_string("Function"),
+ nxt_string("eval"),
njs_eval_function_properties,
nxt_nitems(njs_eval_function_properties),
};
diff -r 18e0275576a3 -r 757271547b56 njs/njs_module.c
--- a/njs/njs_module.c Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/njs_module.c Tue Feb 20 19:12:55 2018 +0300
@@ -83,3 +83,10 @@ njs_ret_t njs_module_require(njs_vm_t *v
return NJS_ERROR;
}
+
+
+const njs_object_init_t njs_require_function_init = {
+ nxt_string("require"),
+ NULL,
+ 0,
+};
diff -r 18e0275576a3 -r 757271547b56 njs/njs_module.h
--- a/njs/njs_module.h Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/njs_module.h Tue Feb 20 19:12:55 2018 +0300
@@ -18,5 +18,6 @@ njs_ret_t njs_module_require(njs_vm_t *v
extern const nxt_lvlhsh_proto_t njs_modules_hash_proto;
+extern const njs_object_init_t njs_require_function_init;
#endif /* _NJS_MODULE_H_INCLUDED_ */
diff -r 18e0275576a3 -r 757271547b56 njs/njs_number.c
--- a/njs/njs_number.c Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/njs_number.c Tue Feb 20 19:12:55 2018 +0300
@@ -896,3 +896,31 @@ njs_number_to_integer(double num)
return (uint32_t) i64;
}
+
+
+const njs_object_init_t njs_is_nan_function_init = {
+ nxt_string("isNaN"),
+ NULL,
+ 0,
+};
+
+
+const njs_object_init_t njs_is_finite_function_init = {
+ nxt_string("isFinite"),
+ NULL,
+ 0,
+};
+
+
+const njs_object_init_t njs_parse_int_function_init = {
+ nxt_string("parseInt"),
+ NULL,
+ 0,
+};
+
+
+const njs_object_init_t njs_parse_float_function_init = {
+ nxt_string("parseFloat"),
+ NULL,
+ 0,
+};
diff -r 18e0275576a3 -r 757271547b56 njs/njs_number.h
--- a/njs/njs_number.h Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/njs_number.h Tue Feb 20 19:12:55 2018 +0300
@@ -35,5 +35,10 @@ nxt_noinline uint32_t njs_number_to_inte
extern const njs_object_init_t njs_number_constructor_init;
extern const njs_object_init_t njs_number_prototype_init;
+extern const njs_object_init_t njs_is_nan_function_init;
+extern const njs_object_init_t njs_is_finite_function_init;
+extern const njs_object_init_t njs_parse_int_function_init;
+extern const njs_object_init_t njs_parse_float_function_init;
+
#endif /* _NJS_NUMBER_H_INCLUDED_ */
diff -r 18e0275576a3 -r 757271547b56 njs/njs_string.c
--- a/njs/njs_string.c Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/njs_string.c Tue Feb 20 19:12:55 2018 +0300
@@ -3791,3 +3791,38 @@ njs_value_index(njs_vm_t *vm, njs_parser
return (njs_index_t) value;
}
+
+
+const njs_object_init_t njs_to_string_function_init = {
+ nxt_string("toString"),
+ NULL,
+ 0,
+};
+
+
+const njs_object_init_t njs_encode_uri_function_init = {
+ nxt_string("encodeURI"),
+ NULL,
+ 0,
+};
+
+
+const njs_object_init_t njs_encode_uri_component_function_init = {
+ nxt_string("encodeURIComponent"),
+ NULL,
+ 0,
+};
+
+
+const njs_object_init_t njs_decode_uri_function_init = {
+ nxt_string("decodeURI"),
+ NULL,
+ 0,
+};
+
+
+const njs_object_init_t njs_decode_uri_component_function_init = {
+ nxt_string("decodeURIComponent"),
+ NULL,
+ 0,
+};
diff -r 18e0275576a3 -r 757271547b56 njs/njs_string.h
--- a/njs/njs_string.h Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/njs_string.h Tue Feb 20 19:12:55 2018 +0300
@@ -158,5 +158,11 @@ njs_index_t njs_value_index(njs_vm_t *vm
extern const njs_object_init_t njs_string_constructor_init;
extern const njs_object_init_t njs_string_prototype_init;
+extern const njs_object_init_t njs_to_string_function_init;
+extern const njs_object_init_t njs_encode_uri_function_init;
+extern const njs_object_init_t njs_encode_uri_component_function_init;
+extern const njs_object_init_t njs_decode_uri_function_init;
+extern const njs_object_init_t njs_decode_uri_component_function_init;
+
#endif /* _NJS_STRING_H_INCLUDED_ */
diff -r 18e0275576a3 -r 757271547b56 njs/njs_vm.c
--- a/njs/njs_vm.c Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/njs_vm.c Tue Feb 20 19:12:55 2018 +0300
@@ -3744,10 +3744,18 @@ njs_vm_add_backtrace_entry(njs_vm_t *vm,
if (function->native) {
ret = njs_builtin_match_native_function(vm, function, &be->name);
- if (ret != NXT_OK) {
- be->name = entry_native;
+ if (ret == NXT_OK) {
+ return NXT_OK;
}
+ ret = njs_external_match_native_function(vm, function->u.native,
+ &be->name);
+ if (ret == NXT_OK) {
+ return NXT_OK;
+ }
+
+ be->name = entry_native;
+
return NXT_OK;
}
diff -r 18e0275576a3 -r 757271547b56 njs/test/njs_expect_test.exp
--- a/njs/test/njs_expect_test.exp Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/test/njs_expect_test.exp Tue Feb 20 19:12:55 2018 +0300
@@ -171,6 +171,12 @@ njs_test {
"console.ll()\r\nTypeError: cannot find property 'll' of an external object"}
}
+# Backtraces for external objects
+njs_test {
+ {"console.log(console)\r\n"
+ "console.log(console)\r\nTypeError:*at console.log (native)"}
+}
+
# Exception in njs_vm_retval_to_ext_string()
njs_test {
{"var o = { toString: function() { return [1] } }\r\n"
diff -r 18e0275576a3 -r 757271547b56 njs/test/njs_interactive_test.c
--- a/njs/test/njs_interactive_test.c Tue Feb 20 19:12:53 2018 +0300
+++ b/njs/test/njs_interactive_test.c Tue Feb 20 19:12:55 2018 +0300
@@ -162,6 +162,16 @@ static njs_interactive_test_t njs_test[
" at Math.log (native)\n"
" at main (native)\n") },
+ { nxt_string("eval()" ENTER),
+ nxt_string("InternalError: Not implemented\n"
+ " at eval (native)\n"
+ " at main (native)\n") },
+
+ { nxt_string("require()" ENTER),
+ nxt_string("TypeError: missing path\n"
+ " at require (native)\n"
+ " at main (native)\n") },
+
{ nxt_string("function f(o) {function f_in(o) {return o.a.a};"
" return f_in(o)}; f({})" ENTER),
nxt_string("TypeError: cannot get property 'a' of undefined\n"
More information about the nginx-devel
mailing list