From 8d59cc8c5523587ab71b07d01241f6cfc6c8610b Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Fri, 11 Jun 2021 15:15:48 +0000 Subject: [PATCH] Fixed dumping of objects with circular references. This closes #395 issue on Github. --- src/njs_json.c | 65 +++++----------------------------------- src/test/njs_unit_test.c | 9 ++++++ 2 files changed, 17 insertions(+), 57 deletions(-) diff --git a/src/njs_json.c b/src/njs_json.c index dd886425..56df4e77 100644 --- a/src/njs_json.c +++ b/src/njs_json.c @@ -2036,40 +2036,15 @@ njs_dump_is_recursive(const njs_value_t *value) njs_inline njs_int_t -njs_dump_visit(njs_arr_t *list, 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_dump_visited(njs_vm_t *vm, njs_json_stringify_t *stringify, + const njs_value_t *value) { - njs_uint_t items, n; - njs_object_t **start, *obj; + njs_int_t depth; - if (!njs_is_object(value)) { - /* External. */ - return 0; - } - - start = list->start; - items = list->items; - obj = njs_object(value); + depth = stringify->depth - 1; - for (n = 0; n < items; n++) { - if (start[n] == obj) { + 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_t *retval, njs_value_t *value, 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_t *retval, njs_value_t *value, 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_t *retval, njs_value_t *value, 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_t *retval, njs_value_t *value, } 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_t *retval, njs_value_t *value, 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_t *retval, njs_value_t *value, done: - njs_arr_destroy(&visited); - ret = njs_chb_join(&chain, &str); if (njs_slow_path(ret != NJS_OK)) { goto memory_error; diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 5bb3f1cb..f26a4bd2 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -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]]]") }, -- 2.47.3