[njs] Fixed dumping of objects with circular references.

Dmitry Volyntsev xeioex at nginx.com
Fri Jun 11 15:21:32 UTC 2021


details:   https://hg.nginx.org/njs/rev/1c066436ec55
branches:  
changeset: 1657:1c066436ec55
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Fri Jun 11 15:15:48 2021 +0000
description:
Fixed dumping of objects with circular references.

This closes #395 issue on Github.

diffstat:

 src/njs_json.c           |  69 ++++++-----------------------------------------
 src/test/njs_unit_test.c |   9 ++++++
 2 files changed, 19 insertions(+), 59 deletions(-)

diffs (150 lines):

diff -r f2d02c3b5f8a -r 1c066436ec55 src/njs_json.c
--- a/src/njs_json.c	Wed Jun 09 17:14:10 2021 +0000
+++ b/src/njs_json.c	Fri Jun 11 15:15:48 2021 +0000
@@ -2036,40 +2036,15 @@ njs_dump_is_recursive(const njs_value_t 
 
 
 njs_inline njs_int_t
-njs_dump_visit(njs_arr_t *list, const njs_value_t *value)
+njs_dump_visited(njs_vm_t *vm, njs_json_stringify_t *stringify,
+    const njs_value_t *value)
 {
-    njs_object_t  **p;
-
-    if (njs_is_object(value)) {
-        p = njs_arr_add(list);
-        if (njs_slow_path(p == NULL)) {
-            return NJS_ERROR;
-        }
-
-        *p = njs_object(value);
-    }
-
-    return NJS_OK;
-}
-
-
-njs_inline njs_int_t
-njs_dump_visited(njs_arr_t *list, const njs_value_t *value)
-{
-    njs_uint_t    items, n;
-    njs_object_t  **start, *obj;
-
-    if (!njs_is_object(value)) {
-        /* External. */
-        return 0;
-    }
-
-    start = list->start;
-    items = list->items;
-    obj = njs_object(value);
-
-    for (n = 0; n < items; n++) {
-        if (start[n] == obj) {
+    njs_int_t  depth;
+
+    depth = stringify->depth - 1;
+
+    for (; depth >= 0; depth--) {
+        if (njs_values_same(&stringify->states[depth].value, value)) {
             return 1;
         }
     }
@@ -2125,9 +2100,7 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_
     njs_int_t             ret;
     njs_chb_t             chain;
     njs_str_t             str;
-    njs_arr_t             visited;
     njs_value_t           *key, *val, tag;
-    njs_object_t          **start;
     njs_json_state_t      *state;
     njs_string_prop_t     string;
     njs_object_prop_t     *prop;
@@ -2147,9 +2120,6 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_
             goto memory_error;
         }
 
-        visited.separate = 0;
-        visited.pointer = 0;
-
         goto done;
     }
 
@@ -2166,13 +2136,6 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_
         goto memory_error;
     }
 
-    start = njs_arr_init(vm->mem_pool, &visited, NULL, 8, sizeof(void *));
-    if (njs_slow_path(start == NULL)) {
-        goto memory_error;
-    }
-
-    (void) njs_dump_visit(&visited, value);
-
     for ( ;; ) {
         switch (state->type) {
         case NJS_JSON_OBJECT:
@@ -2276,16 +2239,11 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_
             }
 
             if (njs_dump_is_recursive(val)) {
-                if (njs_slow_path(njs_dump_visited(&visited, val))) {
+                if (njs_slow_path(njs_dump_visited(vm, stringify, val))) {
                     njs_chb_append_literal(&chain, "[Circular]");
                     break;
                 }
 
-                ret = njs_dump_visit(&visited, val);
-                if (njs_slow_path(ret != NJS_OK)) {
-                    goto memory_error;
-                }
-
                 state = njs_json_push_stringify_state(vm, stringify, val);
                 if (njs_slow_path(state == NULL)) {
                     goto exception;
@@ -2342,16 +2300,11 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_
             val = &njs_array_start(&state->value)[state->index++];
 
             if (njs_dump_is_recursive(val)) {
-                if (njs_slow_path(njs_dump_visited(&visited, val))) {
+                if (njs_slow_path(njs_dump_visited(vm, stringify, val))) {
                     njs_chb_append_literal(&chain, "[Circular]");
                     break;
                 }
 
-                ret = njs_dump_visit(&visited, val);
-                if (njs_slow_path(ret != NJS_OK)) {
-                    goto memory_error;
-                }
-
                 state = njs_json_push_stringify_state(vm, stringify, val);
                 if (njs_slow_path(state == NULL)) {
                     goto exception;
@@ -2377,8 +2330,6 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_
 
 done:
 
-    njs_arr_destroy(&visited);
-
     ret = njs_chb_join(&chain, &str);
     if (njs_slow_path(ret != NJS_OK)) {
         goto memory_error;
diff -r f2d02c3b5f8a -r 1c066436ec55 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Wed Jun 09 17:14:10 2021 +0000
+++ b/src/test/njs_unit_test.c	Fri Jun 11 15:15:48 2021 +0000
@@ -17422,6 +17422,15 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("var a = []; a[0] = a; njs.dump(a)"),
       njs_str("[[Circular]]") },
 
+    { njs_str("var a = []; njs.dump([a,a])"),
+      njs_str("[[],[]]") },
+
+    { njs_str("var O = {}; O.x = O; njs.dump(O)"),
+      njs_str("{x:[Circular]}") },
+
+    { njs_str("var O = {}; njs.dump({x:O, y:O})"),
+      njs_str("{x:{},y:{}}") },
+
     { njs_str("var a = [], b = [a];  a[0] = b; njs.dump(a)"),
       njs_str("[[[Circular]]]") },
 


More information about the nginx-devel mailing list