From ffb0318e4a2427abd0ab9c77ab48ef57357b0dc0 Mon Sep 17 00:00:00 2001 From: Nayeem Rahman Date: Thu, 11 May 2023 14:08:17 +0100 Subject: [PATCH] fix(console): handle error when inspecting promise-like (#19083) Fixes https://discord.com/channels/684898665143206084/684911491035430919/1105900195406958672. This was caused by: - A `TypeError` from `core.getPromiseDetails()` for promise-likes which also lead to that code path. - Swallowing internal formatting errors by returning `undefined`. I've made it so that a special message is formatted in that case instead (note that this case is fixed now): ![image](https://github.com/denoland/deno/assets/29990554/65bb9612-60b2-4e31-bf5e-e20976601593) --- cli/tests/unit/console_test.ts | 7 ++++++ ext/console/01_console.js | 43 +++++++++++----------------------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/cli/tests/unit/console_test.ts b/cli/tests/unit/console_test.ts index 0bd53dc779..c4f2f64a4b 100644 --- a/cli/tests/unit/console_test.ts +++ b/cli/tests/unit/console_test.ts @@ -2235,6 +2235,13 @@ Deno.test(function inspectWithPrototypePollution() { } }); +Deno.test(function inspectPromiseLike() { + assertEquals( + Deno.inspect(Object.create(Promise.prototype)), + "Promise { }", + ); +}); + Deno.test(function inspectorMethods() { console.timeStamp("test"); console.profile("test"); diff --git a/ext/console/01_console.js b/ext/console/01_console.js index 31431f120a..dbbc549cad 100644 --- a/ext/console/01_console.js +++ b/ext/console/01_console.js @@ -161,6 +161,7 @@ const styles = { // TODO(BridgeAR): Highlight regular expressions properly. regexp: "red", module: "underline", + internalError: "red", }; const defaultFG = 39; @@ -1022,7 +1023,6 @@ function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) { ArrayPrototypePush(ctx.seen, value); ctx.currentDepth = recurseTimes; let output; - const indentationLvl = ctx.indentationLvl; try { output = formatter(ctx, value, recurseTimes); for (i = 0; i < keys.length; i++) { @@ -1034,13 +1034,12 @@ function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) { if (protoProps !== undefined) { ArrayPrototypePushApply(output, protoProps); } - } catch (err) { - const constructorName = StringPrototypeSlice( - getCtxStyle(value, constructor, tag), - 0, - -1, + } catch (error) { + // TODO(wafuwafu13): Implement stack overflow check + return ctx.stylize( + `[Internal Formatting Error] ${error.stack}`, + "internalError", ); - return handleMaxCallStackSize(ctx, err, constructorName, indentationLvl); } if (ctx.circular !== undefined) { @@ -1658,8 +1657,14 @@ const PromiseState = { function formatPromise(ctx, value, recurseTimes) { let output; - // TODO(wafuwafu13): Implement - const { 0: state, 1: result } = core.getPromiseDetails(value); + let opResult; + // This op will fail for non-promises, but we get here for some promise-likes. + try { + opResult = core.getPromiseDetails(value); + } catch { + return [ctx.stylize("", "special")]; + } + const { 0: state, 1: result } = opResult; if (state === PromiseState.Pending) { output = [ctx.stylize("", "special")]; } else { @@ -1770,26 +1775,6 @@ function formatProperty( return `${name}:${extra}${str}`; } -function handleMaxCallStackSize( - _ctx, - _err, - _constructorName, - _indentationLvl, -) { - // TODO(wafuwafu13): Implement - // if (isStackOverflowError(err)) { - // ctx.seen.pop(); - // ctx.indentationLvl = indentationLvl; - // return ctx.stylize( - // `[${constructorName}: Inspection interrupted ` + - // 'prematurely. Maximum call stack size exceeded.]', - // 'special' - // ); - // } - // /* c8 ignore next */ - // assert.fail(err.stack); -} - const colorRegExp = new SafeRegExp("\u001b\\[\\d\\d?m", "g"); function removeColors(str) { return StringPrototypeReplace(str, colorRegExp, "");