diff --git a/cli/tests/unit/console_test.ts b/cli/tests/unit/console_test.ts index b5dcf2f053..4201a2a467 100644 --- a/cli/tests/unit/console_test.ts +++ b/cli/tests/unit/console_test.ts @@ -1823,6 +1823,48 @@ unitTest(function inspectProxy() { ); }); +unitTest(function inspectError() { + const error1 = new Error("This is an error"); + const error2 = new Error("This is an error", { + cause: new Error("This is a cause error"), + }); + + assertStringIncludes( + stripColor(Deno.inspect(error1)), + "Error: This is an error", + ); + assertStringIncludes( + stripColor(Deno.inspect(error2)), + "Error: This is an error", + ); + assertStringIncludes( + stripColor(Deno.inspect(error2)), + "Caused by Error: This is a cause error", + ); +}); + +unitTest(function inspectErrorCircular() { + const error1 = new Error("This is an error"); + const error2 = new Error("This is an error", { + cause: new Error("This is a cause error"), + }); + error1.cause = error1; + error2.cause.cause = error2; + + assertStringIncludes( + stripColor(Deno.inspect(error1)), + "Error: This is an error", + ); + assertStringIncludes( + stripColor(Deno.inspect(error2)), + "Error: This is an error", + ); + assertStringIncludes( + stripColor(Deno.inspect(error2)), + "Caused by Error: This is a cause error", + ); +}); + unitTest(function inspectColors() { assertEquals(Deno.inspect(1), "1"); assertStringIncludes(Deno.inspect(1, { colors: true }), "\x1b["); diff --git a/ext/console/02_console.js b/ext/console/02_console.js index 09d96fc091..8d650d8ecb 100644 --- a/ext/console/02_console.js +++ b/ext/console/02_console.js @@ -883,6 +883,26 @@ return red(RegExpPrototypeToString(value)); // RegExps are red } + function inspectError(value) { + const causes = []; + + let err = value; + while ( + err.cause instanceof Error && err.cause !== value && + !ArrayPrototypeIncludes(causes, err.cause) // circular check + ) { + ArrayPrototypePush(causes, err.cause); + err = err.cause; + } + + return `${value.stack}${ + ArrayPrototypeJoin( + ArrayPrototypeMap(causes, (cause) => `\nCaused by ${cause.stack}`), + "", + ) + }`; + } + function inspectStringObject(value, inspectOptions) { const cyan = maybeColor(colors.cyan, inspectOptions); return cyan(`[String: "${StringPrototypeToString(value)}"]`); // wrappers are in cyan @@ -1141,7 +1161,7 @@ return String(value[privateCustomInspect](inspect)); } if (value instanceof Error) { - return String(value.stack); + return inspectError(value); } else if (ArrayIsArray(value)) { return inspectArray(value, level, inspectOptions); } else if (value instanceof Number) {