[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