summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorYingbo (Max) Wang <maxwyb@gmail.com>2018-09-30 15:10:20 -0700
committerRyan Dahl <ry@tinyclouds.org>2018-09-30 18:10:20 -0400
commitbcdbfc00f01a94fed1d3f1d11f8aacc627c5ca36 (patch)
tree0c57bd747dd6fc742f81a0f3d77fc16e94f59601 /js
parent50a9c2b575b383e72f64e16e83e540c215482e73 (diff)
Limit depth of output in console.log for nested objects, and add console.dir (#826)
Diffstat (limited to 'js')
-rw-r--r--js/console.ts86
-rw-r--r--js/console_test.ts19
2 files changed, 87 insertions, 18 deletions
diff --git a/js/console.ts b/js/console.ts
index d3bd5bb6b..51798d79d 100644
--- a/js/console.ts
+++ b/js/console.ts
@@ -1,5 +1,13 @@
// tslint:disable-next-line:no-any
type ConsoleContext = Set<any>;
+type ConsoleOptions = Partial<{
+ showHidden: boolean;
+ depth: number;
+ colors: boolean;
+}>;
+
+// Default depth of logging nested objects
+const DEFAULT_MAX_DEPTH = 2;
// tslint:disable-next-line:no-any
function getClassInstanceName(instance: any): string {
@@ -25,11 +33,16 @@ function createFunctionString(value: Function, ctx: ConsoleContext): string {
return `[${cstrName}]`;
}
-// tslint:disable-next-line:no-any
-function createArrayString(value: any[], ctx: ConsoleContext): string {
+function createArrayString(
+ // tslint:disable-next-line:no-any
+ value: any[],
+ ctx: ConsoleContext,
+ level: number,
+ maxLevel: number
+): string {
const entries: string[] = [];
for (const el of value) {
- entries.push(stringifyWithQuotes(ctx, el));
+ entries.push(stringifyWithQuotes(ctx, el, level + 1, maxLevel));
}
ctx.delete(value);
if (entries.length === 0) {
@@ -38,8 +51,13 @@ function createArrayString(value: any[], ctx: ConsoleContext): string {
return `[ ${entries.join(", ")} ]`;
}
-// tslint:disable-next-line:no-any
-function createObjectString(value: any, ctx: ConsoleContext): string {
+function createObjectString(
+ // tslint:disable-next-line:no-any
+ value: any,
+ ctx: ConsoleContext,
+ level: number,
+ maxLevel: number
+): string {
const entries: string[] = [];
let baseString = "";
@@ -50,7 +68,9 @@ function createObjectString(value: any, ctx: ConsoleContext): string {
}
for (const key of Object.keys(value)) {
- entries.push(`${key}: ${stringifyWithQuotes(ctx, value[key])}`);
+ entries.push(
+ `${key}: ${stringifyWithQuotes(ctx, value[key], level + 1, maxLevel)}`
+ );
}
ctx.delete(value);
@@ -68,8 +88,13 @@ function createObjectString(value: any, ctx: ConsoleContext): string {
return baseString;
}
-// tslint:disable-next-line:no-any
-function stringify(ctx: ConsoleContext, value: any): string {
+function stringify(
+ ctx: ConsoleContext,
+ // tslint:disable-next-line:no-any
+ value: any,
+ level: number,
+ maxLevel: number
+): string {
switch (typeof value) {
case "string":
return value;
@@ -88,15 +113,20 @@ function stringify(ctx: ConsoleContext, value: any): string {
if (ctx.has(value)) {
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);
+ return createArrayString(value as any[], ctx, level, maxLevel);
} else {
- return createObjectString(value, ctx);
+ return createObjectString(value, ctx, level, maxLevel);
}
default:
return "[Not Implemented]";
@@ -104,25 +134,42 @@ function stringify(ctx: ConsoleContext, value: any): string {
}
// Print strings when they are inside of arrays or objects with quotes
-// tslint:disable-next-line:no-any
-function stringifyWithQuotes(ctx: ConsoleContext, value: any): string {
+function stringifyWithQuotes(
+ ctx: ConsoleContext,
+ // tslint:disable-next-line:no-any
+ value: any,
+ level: number,
+ maxLevel: number
+): string {
switch (typeof value) {
case "string":
return `"${value}"`;
default:
- return stringify(ctx, value);
+ return stringify(ctx, value, level, maxLevel);
}
}
-// tslint:disable-next-line:no-any
-export function stringifyArgs(args: any[]): string {
+export function stringifyArgs(
+ // tslint:disable-next-line:no-any
+ args: any[],
+ options: ConsoleOptions = {}
+): string {
const out: string[] = [];
for (const a of args) {
if (typeof a === "string") {
out.push(a);
} else {
- // tslint:disable-next-line:no-any
- out.push(stringify(new Set<any>(), a));
+ out.push(
+ // use default maximum depth for null or undefined argument
+ stringify(
+ // 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
+ )
+ );
}
}
return out.join(" ");
@@ -142,6 +189,11 @@ export class Console {
info = this.log;
// tslint:disable-next-line:no-any
+ dir(obj: any, options: ConsoleOptions = {}) {
+ this.printFunc(stringifyArgs([obj], options));
+ }
+
+ // tslint:disable-next-line:no-any
warn(...args: any[]): void {
this.printFunc(stringifyArgs(args), true);
}
diff --git a/js/console_test.ts b/js/console_test.ts
index 94a627a5f..9e6a37256 100644
--- a/js/console_test.ts
+++ b/js/console_test.ts
@@ -68,7 +68,7 @@ test(function consoleTestStringifyCircular() {
nestedObj.o = circularObj;
- const nestedObjExpected = `{ num: 1, bool: true, str: "a", method: [Function: method], asyncMethod: [AsyncFunction: asyncMethod], generatorMethod: [GeneratorFunction: generatorMethod], un: undefined, nu: null, arrowFunc: [Function: arrowFunc], extendedClass: Extended { a: 1, b: 2 }, nFunc: [Function], extendedCstr: [Function: Extended], o: { num: 2, bool: false, str: "b", method: [Function: method], un: undefined, nu: null, nested: [Circular], emptyObj: {}, arr: [ 1, "s", false, null, [Circular] ], baseClass: Base { a: 1 } } }`;
+ const nestedObjExpected = `{ num: 1, bool: true, str: "a", method: [Function: method], asyncMethod: [AsyncFunction: asyncMethod], generatorMethod: [GeneratorFunction: generatorMethod], un: undefined, nu: null, arrowFunc: [Function: arrowFunc], extendedClass: Extended { a: 1, b: 2 }, nFunc: [Function], extendedCstr: [Function: Extended], o: { num: 2, bool: false, str: "b", method: [Function: method], un: undefined, nu: null, nested: [Circular], emptyObj: [object], arr: [object], baseClass: [object] } }`;
assertEqual(stringify(1), "1");
assertEqual(stringify("s"), "s");
@@ -92,6 +92,23 @@ test(function consoleTestStringifyCircular() {
);
});
+test(function consoleTestStringifyWithDepth() {
+ const nestedObj: any = { a: { b: { c: { d: { e: { f: 42 } } } } } };
+ assertEqual(
+ stringifyArgs([nestedObj], { depth: 3 }),
+ "{ a: { b: { c: [object] } } }"
+ );
+ assertEqual(
+ stringifyArgs([nestedObj], { depth: 4 }),
+ "{ a: { b: { c: { d: [object] } } } }"
+ );
+ assertEqual(stringifyArgs([nestedObj], { depth: 0 }), "[object]");
+ assertEqual(
+ stringifyArgs([nestedObj], { depth: null }),
+ "{ a: { b: [object] } }"
+ );
+});
+
test(function consoleTestError() {
class MyError extends Error {
constructor(msg: string) {