Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
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: #14758
PR-URL: #14790
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Yuta Hiroto <hello@about-hiroppy.com>
Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben.bridgewater@fintura.de>
  • Loading branch information
addaleax committed Aug 17, 2017
commit 0d019faf217ee69583e5694c5dcd1ae8c61e267f
31 changes: 15 additions & 16 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume value can only ever be an object here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Or maybe that depends on what you mean by “object”; at least it’s not a primitive.

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);
Expand Down Expand Up @@ -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) {
Expand Down