[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