From a04fd162fc1919ebfc22ddf8d506abbac9e066b1 Mon Sep 17 00:00:00 2001 From: withgit-contributor Date: Fri, 1 Sep 2017 16:32:09 +0900 Subject: [PATCH] util: use proper circular reference checking Circular references are conceptually nothing that should be checked for objects (or Sets or Maps) only, but applies to recursive structures in general, so move the `seen` checks into a position where it is part of the recursion itself. Fixes: https://github.com/with-git/node/issues/1 PR-URL: https://github.com/with-git/node/pull/2 --- lib/util.js | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/lib/util.js b/lib/util.js index 8fe811f812..0664f94cd2 100644 --- a/lib/util.js +++ b/lib/util.js @@ -612,10 +612,13 @@ function formatValue(ctx, value, recurseTimes) { } } - ctx.seen.push(value); - - var output = formatter(ctx, value, recurseTimes, visibleKeys, keys); + // TODO(addaleax): Make `seen` a Set to avoid linear-time lookup. + if (ctx.seen.includes(value)) { + return ctx.stylize('[Circular]', 'special'); + } + ctx.seen.push(value); + const output = formatter(ctx, value, recurseTimes, visibleKeys, keys); ctx.seen.pop(); return reduceToSingleString(output, base, braces, ctx.breakLength); @@ -835,21 +838,17 @@ function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { } } if (!str) { - if (ctx.seen.indexOf(desc.value) < 0) { - if (recurseTimes === null) { - str = formatValue(ctx, desc.value, null); + if (recurseTimes === null) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.replace(/\n/g, '\n '); } else { - str = formatValue(ctx, desc.value, recurseTimes - 1); - } - if (str.indexOf('\n') > -1) { - if (array) { - str = str.replace(/\n/g, '\n '); - } else { - str = str.replace(/^|\n/g, '\n '); - } + str = str.replace(/^|\n/g, '\n '); } - } else { - str = ctx.stylize('[Circular]', 'special'); } } if (name === undefined) {