summaryrefslogtreecommitdiff
path: root/lib/internal/util/inspect.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/internal/util/inspect.js')
-rw-r--r--lib/internal/util/inspect.js27
1 files changed, 25 insertions, 2 deletions
diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js
index e46a18633c..8735c40ac0 100644
--- a/lib/internal/util/inspect.js
+++ b/lib/internal/util/inspect.js
@@ -563,8 +563,19 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
// Using an array here is actually better for the average case than using
// a Set. `seen` will only check for the depth and will never grow too large.
- if (ctx.seen.includes(value))
- return ctx.stylize('[Circular]', 'special');
+ if (ctx.seen.includes(value)) {
+ let index = 1;
+ if (ctx.circular === undefined) {
+ ctx.circular = new Map([[value, index]]);
+ } else {
+ index = ctx.circular.get(value);
+ if (index === undefined) {
+ index = ctx.circular.size + 1;
+ ctx.circular.set(value, index);
+ }
+ }
+ return ctx.stylize(`[Circular *${index}]`, 'special');
+ }
return formatRaw(ctx, value, recurseTimes, typedArray);
}
@@ -766,6 +777,18 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
const constructorName = getCtxStyle(value, constructor, tag).slice(0, -1);
return handleMaxCallStackSize(ctx, err, constructorName, indentationLvl);
}
+ if (ctx.circular !== undefined) {
+ const index = ctx.circular.get(value);
+ if (index !== undefined) {
+ const reference = ctx.stylize(`<ref *${index}>`, 'special');
+ // Add reference always to the very beginning of the output.
+ if (ctx.compact !== true) {
+ base = base === '' ? reference : `${reference} ${base}`;
+ } else {
+ braces[0] = `${reference} ${braces[0]}`;
+ }
+ }
+ }
ctx.seen.pop();
if (ctx.sorted) {