summaryrefslogtreecommitdiff
path: root/ext/console/02_console.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/console/02_console.js')
-rw-r--r--ext/console/02_console.js98
1 files changed, 75 insertions, 23 deletions
diff --git a/ext/console/02_console.js b/ext/console/02_console.js
index 4dab799b9..d3734b6a4 100644
--- a/ext/console/02_console.js
+++ b/ext/console/02_console.js
@@ -72,6 +72,7 @@
ArrayPrototypePop,
ArrayPrototypeSort,
ArrayPrototypeSlice,
+ ArrayPrototypeShift,
ArrayPrototypeIncludes,
ArrayPrototypeFill,
ArrayPrototypeFilter,
@@ -340,11 +341,17 @@
// If we didn't find any properties, we will just append an
// empty suffix.
let suffix = ``;
+ let refStr = "";
if (
ObjectKeys(value).length > 0 ||
ObjectGetOwnPropertySymbols(value).length > 0
) {
- const propString = inspectRawObject(value, level, inspectOptions);
+ const [propString, refIndex] = inspectRawObject(
+ value,
+ level,
+ inspectOptions,
+ );
+ refStr = refIndex;
// Filter out the empty string for the case we only have
// non-enumerable symbols.
if (
@@ -357,9 +364,9 @@
if (value.name && value.name !== "anonymous") {
// from MDN spec
- return cyan(`[${cstrName}: ${value.name}]`) + suffix;
+ return cyan(`${refStr}[${cstrName}: ${value.name}]`) + suffix;
}
- return cyan(`[${cstrName}]`) + suffix;
+ return cyan(`${refStr}[${cstrName}]`) + suffix;
}
function inspectIterable(
@@ -589,6 +596,23 @@
return entries;
}
+ let circular;
+ function handleCircular(value, cyan) {
+ let index = 1;
+ if (circular === undefined) {
+ circular = new Map();
+ MapPrototypeSet(circular, value, index);
+ } else {
+ index = MapPrototypeGet(circular, value);
+ if (index === undefined) {
+ index = circular.size + 1;
+ MapPrototypeSet(circular, value, index);
+ }
+ }
+ // Circular string is cyan
+ return cyan(`[Circular *${index}]`);
+ }
+
function _inspectValue(
value,
level,
@@ -623,7 +647,7 @@
case "function": // Function string is cyan
if (ctxHas(value)) {
// Circular string is cyan
- return cyan("[Circular]");
+ return handleCircular(value, cyan);
}
return inspectFunction(value, level, inspectOptions);
@@ -633,8 +657,7 @@
}
if (ctxHas(value)) {
- // Circular string is cyan
- return cyan("[Circular]");
+ return handleCircular(value, cyan);
}
return inspectObject(value, level, inspectOptions);
default:
@@ -892,25 +915,41 @@
return red(RegExpPrototypeToString(value)); // RegExps are red
}
- function inspectError(value) {
- const causes = [];
+ function inspectError(value, cyan) {
+ const causes = [value];
let err = value;
- while (
- ObjectPrototypeIsPrototypeOf(ErrorPrototype, err.cause) &&
- err.cause !== value &&
- !ArrayPrototypeIncludes(causes, err.cause) // circular check
- ) {
- ArrayPrototypePush(causes, err.cause);
- err = err.cause;
+ while (err.cause) {
+ if (ArrayPrototypeIncludes(causes, err.cause)) {
+ ArrayPrototypePush(causes, handleCircular(err.cause, cyan));
+ break;
+ } else {
+ ArrayPrototypePush(causes, err.cause);
+ err = err.cause;
+ }
}
- return `${value.stack}${
+ const refMap = new Map();
+ for (const cause of causes) {
+ if (circular !== undefined) {
+ const index = MapPrototypeGet(circular, cause);
+ if (index !== undefined) {
+ MapPrototypeSet(refMap, cause, cyan(`<ref *${index}> `));
+ }
+ }
+ }
+ ArrayPrototypeShift(causes);
+
+ return (MapPrototypeGet(refMap, value) ?? "") + value.stack +
ArrayPrototypeJoin(
- ArrayPrototypeMap(causes, (cause) => `\nCaused by ${cause.stack}`),
+ ArrayPrototypeMap(
+ causes,
+ (cause) =>
+ "\nCaused by " + (MapPrototypeGet(refMap, cause) ?? "") +
+ (cause?.stack ?? cause),
+ ),
"",
- )
- }`;
+ );
}
function inspectStringObject(value, inspectOptions) {
@@ -1002,7 +1041,7 @@
const cyan = maybeColor(colors.cyan, inspectOptions);
if (level >= inspectOptions.depth) {
- return cyan("[Object]"); // wrappers are in cyan
+ return [cyan("[Object]"), ""]; // wrappers are in cyan
}
let baseString;
@@ -1144,7 +1183,15 @@
baseString = `${displayName} ${baseString}`;
}
- return baseString;
+ let refIndex = "";
+ if (circular !== undefined) {
+ const index = MapPrototypeGet(circular, value);
+ if (index !== undefined) {
+ refIndex = `<ref *${index}> `;
+ }
+ }
+
+ return [baseString, refIndex];
}
function inspectObject(
@@ -1171,7 +1218,7 @@
return String(value[privateCustomInspect](inspect));
}
if (ObjectPrototypeIsPrototypeOf(ErrorPrototype, value)) {
- return inspectError(value);
+ return inspectError(value, maybeColor(colors.cyan, inspectOptions));
} else if (ArrayIsArray(value)) {
return inspectArray(value, level, inspectOptions);
} else if (ObjectPrototypeIsPrototypeOf(NumberPrototype, value)) {
@@ -1207,7 +1254,9 @@
);
} else {
// Otherwise, default object formatting
- return inspectRawObject(value, level, inspectOptions);
+ let [insp, refIndex] = inspectRawObject(value, level, inspectOptions);
+ insp = refIndex + insp;
+ return insp;
}
}
@@ -1660,6 +1709,8 @@
}
function inspectArgs(args, inspectOptions = {}) {
+ circular = undefined;
+
const noColor = colors.getNoColor();
const rInspectOptions = { ...DEFAULT_INSPECT_OPTIONS, ...inspectOptions };
const first = args[0];
@@ -2076,6 +2127,7 @@
value,
inspectOptions = {},
) {
+ circular = undefined;
return inspectValue(value, 0, {
...DEFAULT_INSPECT_OPTIONS,
...inspectOptions,