From 0d019faf217ee69583e5694c5dcd1ae8c61e267f Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sat, 12 Aug 2017 14:37:12 +0200 Subject: [PATCH] util: use proper circular reference checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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/nodejs/node/issues/14758 PR-URL: https://github.com/nodejs/node/pull/14790 Reviewed-By: Refael Ackermann Reviewed-By: James M Snell Reviewed-By: Evan Lucas Reviewed-By: Timothy Gu Reviewed-By: Colin Ihrig Reviewed-By: Tobias Nießen Reviewed-By: Yuta Hiroto Reviewed-By: Alexey Orlenko Reviewed-By: Ruben Bridgewater --- lib/util.js | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/lib/util.js b/lib/util.js index 8fe811f8121fce..0664f94cd200da 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) {