diff options
Diffstat (limited to 'js/console.ts')
-rw-r--r-- | js/console.ts | 224 |
1 files changed, 195 insertions, 29 deletions
diff --git a/js/console.ts b/js/console.ts index ccfcf007b..3d2d65909 100644 --- a/js/console.ts +++ b/js/console.ts @@ -1,4 +1,5 @@ // Copyright 2018 the Deno authors. All rights reserved. MIT license. +import { isTypedArray } from "./util"; // tslint:disable-next-line:no-any type ConsoleContext = Set<any>; @@ -9,7 +10,7 @@ type ConsoleOptions = Partial<{ }>; // Default depth of logging nested objects -const DEFAULT_MAX_DEPTH = 2; +const DEFAULT_MAX_DEPTH = 4; // tslint:disable-next-line:no-any function getClassInstanceName(instance: any): string { @@ -35,31 +36,165 @@ function createFunctionString(value: Function, ctx: ConsoleContext): string { return `[${cstrName}]`; } -function createArrayString( +interface IterablePrintConfig { + typeName: string; + displayName: string; + delims: [string, string]; + entryHandler: ( + // tslint:disable-next-line:no-any + entry: any, + ctx: ConsoleContext, + level: number, + maxLevel: number + ) => string; +} + +function createIterableString( // tslint:disable-next-line:no-any - value: any[], + value: any, ctx: ConsoleContext, level: number, - maxLevel: number + maxLevel: number, + config: IterablePrintConfig ): string { + if (level >= maxLevel) { + return `[${config.typeName}]`; + } + ctx.add(value); + const entries: string[] = []; for (const el of value) { - entries.push(stringifyWithQuotes(ctx, el, level + 1, maxLevel)); + entries.push(config.entryHandler(el, ctx, level + 1, maxLevel)); } ctx.delete(value); - if (entries.length === 0) { - return "[]"; - } - return `[ ${entries.join(", ")} ]`; + const iPrefix = `${config.displayName ? config.displayName + " " : ""}`; + const iContent = entries.length === 0 ? "" : ` ${entries.join(", ")} `; + return `${iPrefix}${config.delims[0]}${iContent}${config.delims[1]}`; } -function createObjectString( +function createArrayString( + // tslint:disable-next-line:no-any + value: any[], + ctx: ConsoleContext, + level: number, + maxLevel: number +): string { + const printConfig: IterablePrintConfig = { + typeName: "Array", + displayName: "", + delims: ["[", "]"], + entryHandler: (el, ctx, level, maxLevel) => + stringifyWithQuotes(el, ctx, level + 1, maxLevel) + }; + return createIterableString(value, ctx, level, maxLevel, printConfig); +} + +function createTypedArrayString( + typedArrayName: string, // tslint:disable-next-line:no-any value: any, ctx: ConsoleContext, level: number, maxLevel: number ): string { + const printConfig: IterablePrintConfig = { + typeName: typedArrayName, + displayName: typedArrayName, + delims: ["[", "]"], + entryHandler: (el, ctx, level, maxLevel) => + stringifyWithQuotes(el, ctx, level + 1, maxLevel) + }; + return createIterableString(value, ctx, level, maxLevel, printConfig); +} + +function createSetString( + // tslint:disable-next-line:no-any + value: Set<any>, + ctx: ConsoleContext, + level: number, + maxLevel: number +): string { + const printConfig: IterablePrintConfig = { + typeName: "Set", + displayName: "Set", + delims: ["{", "}"], + entryHandler: (el, ctx, level, maxLevel) => + stringifyWithQuotes(el, ctx, level + 1, maxLevel) + }; + return createIterableString(value, ctx, level, maxLevel, printConfig); +} + +function createMapString( + // tslint:disable-next-line:no-any + value: Map<any, any>, + ctx: ConsoleContext, + level: number, + maxLevel: number +): string { + const printConfig: IterablePrintConfig = { + typeName: "Map", + displayName: "Map", + delims: ["{", "}"], + entryHandler: (el, ctx, level, maxLevel) => { + const [key, val] = el; + return `${stringifyWithQuotes( + key, + ctx, + level + 1, + maxLevel + )} => ${stringifyWithQuotes(val, ctx, level + 1, maxLevel)}`; + } + }; + return createIterableString(value, ctx, level, maxLevel, printConfig); +} + +function createWeakSetString(): string { + return "WeakSet { [items unknown] }"; // as seen in Node +} + +function createWeakMapString(): string { + return "WeakMap { [items unknown] }"; // as seen in Node +} + +function createDateString(value: Date) { + // without quotes, ISO format + return value.toISOString(); +} + +function createRegExpString(value: RegExp) { + return value.toString(); +} + +// tslint:disable-next-line:ban-types +function createStringWrapperString(value: String) { + return `[String: "${value.toString()}"]`; +} + +// tslint:disable-next-line:ban-types +function createBooleanWrapperString(value: Boolean) { + return `[Boolean: ${value.toString()}]`; +} + +// tslint:disable-next-line:ban-types +function createNumberWrapperString(value: Number) { + return `[Number: ${value.toString()}]`; +} + +// TODO: Promise, requires v8 bindings to get info +// TODO: Proxy + +function createRawObjectString( + // tslint:disable-next-line:no-any + value: any, + ctx: ConsoleContext, + level: number, + maxLevel: number +): string { + if (level >= maxLevel) { + return "[Object]"; + } + ctx.add(value); + const entries: string[] = []; let baseString = ""; @@ -71,7 +206,7 @@ function createObjectString( for (const key of Object.keys(value)) { entries.push( - `${key}: ${stringifyWithQuotes(ctx, value[key], level + 1, maxLevel)}` + `${key}: ${stringifyWithQuotes(value[key], ctx, level + 1, maxLevel)}` ); } @@ -90,10 +225,54 @@ function createObjectString( return baseString; } +function createObjectString( + // tslint:disable-next-line:no-any + value: any, + ...args: [ConsoleContext, number, number] +): string { + if (value instanceof Error) { + return value.stack! || ""; + } else if (Array.isArray(value)) { + return createArrayString(value, ...args); + } else if (value instanceof Number) { + // tslint:disable-next-line:ban-types + return createNumberWrapperString(value as Number); + } else if (value instanceof Boolean) { + // tslint:disable-next-line:ban-types + return createBooleanWrapperString(value as Boolean); + } else if (value instanceof String) { + // tslint:disable-next-line:ban-types + return createStringWrapperString(value as String); + } else if (value instanceof RegExp) { + return createRegExpString(value as RegExp); + } else if (value instanceof Date) { + return createDateString(value as Date); + } else if (value instanceof Set) { + // tslint:disable-next-line:no-any + return createSetString(value as Set<any>, ...args); + } else if (value instanceof Map) { + // tslint:disable-next-line:no-any + return createMapString(value as Map<any, any>, ...args); + } else if (value instanceof WeakSet) { + return createWeakSetString(); + } else if (value instanceof WeakMap) { + return createWeakMapString(); + } else if (isTypedArray(value)) { + return createTypedArrayString( + Object.getPrototypeOf(value).constructor.name, + value, + ...args + ); + } else { + // Otherwise, default object formatting + return createRawObjectString(value, ...args); + } +} + function stringify( - ctx: ConsoleContext, // tslint:disable-next-line:no-any value: any, + ctx: ConsoleContext, level: number, maxLevel: number ): string { @@ -118,20 +297,7 @@ function stringify( return "[Circular]"; } - if (level >= maxLevel) { - return `[object]`; - } - - ctx.add(value); - - if (value instanceof Error) { - return value.stack! || ""; - } else if (Array.isArray(value)) { - // tslint:disable-next-line:no-any - return createArrayString(value as any[], ctx, level, maxLevel); - } else { - return createObjectString(value, ctx, level, maxLevel); - } + return createObjectString(value, ctx, level, maxLevel); default: return "[Not Implemented]"; } @@ -139,9 +305,9 @@ function stringify( // Print strings when they are inside of arrays or objects with quotes function stringifyWithQuotes( - ctx: ConsoleContext, // tslint:disable-next-line:no-any value: any, + ctx: ConsoleContext, level: number, maxLevel: number ): string { @@ -149,7 +315,7 @@ function stringifyWithQuotes( case "string": return `"${value}"`; default: - return stringify(ctx, value, level, maxLevel); + return stringify(value, ctx, level, maxLevel); } } @@ -167,9 +333,9 @@ export function stringifyArgs( out.push( // use default maximum depth for null or undefined argument stringify( + a, // tslint:disable-next-line:no-any new Set<any>(), - a, 0, // tslint:disable-next-line:triple-equals options.depth != undefined ? options.depth : DEFAULT_MAX_DEPTH |