diff options
author | MichaĆ Sabiniarz <31597105+mhvsa@users.noreply.github.com> | 2020-03-31 01:01:19 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-30 19:01:19 -0400 |
commit | 30fdf6dc83d3a9d44436528959c39d3eab14cbbb (patch) | |
tree | 8f9cd11b1ae96333158b7a4be7d3d982dfde1688 /cli/js | |
parent | 3892d49165f00b2ce078825c204ba8ceaa21f386 (diff) |
console: print promise details (#4524)
Diffstat (limited to 'cli/js')
-rw-r--r-- | cli/js/globals.ts | 13 | ||||
-rw-r--r-- | cli/js/tests/console_test.ts | 21 | ||||
-rw-r--r-- | cli/js/web/console.ts | 34 | ||||
-rw-r--r-- | cli/js/web/promise.ts | 7 |
4 files changed, 74 insertions, 1 deletions
diff --git a/cli/js/globals.ts b/cli/js/globals.ts index 87ff13b22..e5b7ff85a 100644 --- a/cli/js/globals.ts +++ b/cli/js/globals.ts @@ -2,6 +2,7 @@ import * as blob from "./web/blob.ts"; import * as consoleTypes from "./web/console.ts"; +import * as promiseTypes from "./web/promise.ts"; import * as customEvent from "./web/custom_event.ts"; import * as domTypes from "./web/dom_types.ts"; import * as domFile from "./web/dom_file.ts"; @@ -102,6 +103,18 @@ declare global { formatError: (e: Error) => string; + /** + * Get promise details as two elements array. + * + * First element is the `PromiseState`. + * If promise isn't pending, second element would be the result of the promise. + * Otherwise, second element would be undefined. + * + * Throws `TypeError` if argument isn't a promise + * + */ + getPromiseDetails<T>(promise: Promise<T>): promiseTypes.PromiseDetails<T>; + decode(bytes: Uint8Array): string; encode(text: string): Uint8Array; } diff --git a/cli/js/tests/console_test.ts b/cli/js/tests/console_test.ts index c49c941f4..88902f84b 100644 --- a/cli/js/tests/console_test.ts +++ b/cli/js/tests/console_test.ts @@ -580,6 +580,27 @@ unitTest(function consoleTestStringifyIterable() { ); }); +unitTest(async function consoleTestStringifyPromises(): Promise<void> { + const pendingPromise = new Promise((_res, _rej) => {}); + assertEquals(stringify(pendingPromise), "Promise { <pending> }"); + + const resolvedPromise = new Promise((res, _rej) => { + res("Resolved!"); + }); + assertEquals(stringify(resolvedPromise), `Promise { "Resolved!" }`); + + let rejectedPromise; + try { + rejectedPromise = new Promise((_, rej) => { + rej(Error("Whoops")); + }); + await rejectedPromise; + } catch (err) {} + const strLines = stringify(rejectedPromise).split("\n"); + assertEquals(strLines[0], "Promise {"); + assertEquals(strLines[1], " <rejected> Error: Whoops"); +}); + unitTest(function consoleTestWithCustomInspector(): void { class A { [customInspect](): string { diff --git a/cli/js/web/console.ts b/cli/js/web/console.ts index a9b4d53be..3a274e086 100644 --- a/cli/js/web/console.ts +++ b/cli/js/web/console.ts @@ -4,6 +4,7 @@ import { TextEncoder } from "./text_encoding.ts"; import { File, stdout } from "../files.ts"; import { cliTable } from "./console_table.ts"; import { exposeForTest } from "../internals.ts"; +import { PromiseState } from "./promise.ts"; type ConsoleContext = Set<unknown>; type InspectOptions = Partial<{ @@ -28,6 +29,8 @@ const CHAR_LOWERCASE_O = 111; /* o */ const CHAR_UPPERCASE_O = 79; /* O */ const CHAR_LOWERCASE_C = 99; /* c */ +const PROMISE_STRING_BASE_LENGTH = 12; + export class CSI { static kClear = "\x1b[1;1H"; static kClearScreenDown = "\x1b[0J"; @@ -442,7 +445,34 @@ function createNumberWrapperString(value: Number): string { /* eslint-enable @typescript-eslint/ban-types */ -// TODO: Promise, requires v8 bindings to get info +function createPromiseString( + value: Promise<unknown>, + ctx: ConsoleContext, + level: number, + maxLevel: number +): string { + const [state, result] = Deno.core.getPromiseDetails(value); + + if (state === PromiseState.Pending) { + return "Promise { <pending> }"; + } + + const prefix = state === PromiseState.Fulfilled ? "" : "<rejected> "; + + const str = `${prefix}${stringifyWithQuotes( + result, + ctx, + level + 1, + maxLevel + )}`; + + if (str.length + PROMISE_STRING_BASE_LENGTH > LINE_BREAKING_LENGTH) { + return `Promise {\n${" ".repeat(level + 1)}${str}\n}`; + } + + return `Promise { ${str} }`; +} + // TODO: Proxy function createRawObjectString( @@ -531,6 +561,8 @@ function createObjectString( return createBooleanWrapperString(value); } else if (value instanceof String) { return createStringWrapperString(value); + } else if (value instanceof Promise) { + return createPromiseString(value, ...args); } else if (value instanceof RegExp) { return createRegExpString(value); } else if (value instanceof Date) { diff --git a/cli/js/web/promise.ts b/cli/js/web/promise.ts new file mode 100644 index 000000000..b00c0786f --- /dev/null +++ b/cli/js/web/promise.ts @@ -0,0 +1,7 @@ +export enum PromiseState { + Pending = 0, + Fulfilled = 1, + Rejected = 2, +} + +export type PromiseDetails<T> = [PromiseState, T | undefined]; |