diff --git a/js/console.ts b/js/console.ts index e709de39d85745..02a95c7267c7bb 100644 --- a/js/console.ts +++ b/js/console.ts @@ -7,6 +7,8 @@ type ConsoleOptions = Partial<{ showHidden: boolean; depth: number; colors: boolean; + indentLevel: number; + collapsedAt: number | null; }>; // Default depth of logging nested objects @@ -322,6 +324,18 @@ function stringifyWithQuotes( } } +// Returns true when the console is collapsed. +function isCollapsed( + collapsedAt: number | null | undefined, + indentLevel: number | null | undefined +) { + if (collapsedAt == null || indentLevel == null) { + return false; + } + + return collapsedAt <= indentLevel; +} + /** TODO Do not expose this from "deno" namespace. */ export function stringifyArgs( // tslint:disable-next-line:no-any @@ -329,6 +343,7 @@ export function stringifyArgs( options: ConsoleOptions = {} ): string { const out: string[] = []; + const { collapsedAt, indentLevel } = options; for (const a of args) { if (typeof a === "string") { out.push(a); @@ -347,7 +362,12 @@ export function stringifyArgs( } } let outstr = out.join(" "); - if (groupIndent.length !== 0) { + if ( + !isCollapsed(collapsedAt, indentLevel) && + indentLevel != null && + indentLevel > 0 + ) { + const groupIndent = " ".repeat(indentLevel); if (outstr.indexOf("\n") !== -1) { outstr = outstr.replace(/\n/g, `\n${groupIndent}`); } @@ -356,20 +376,30 @@ export function stringifyArgs( return outstr; } -type PrintFunc = (x: string, isErr?: boolean) => void; +type PrintFunc = (x: string, isErr?: boolean, printsNewline?: boolean) => void; const countMap = new Map(); const timerMap = new Map(); -let groupIndent = ""; - export class Console { - constructor(private printFunc: PrintFunc) {} + indentLevel: number; + collapsedAt: number | null; + constructor(private printFunc: PrintFunc) { + this.indentLevel = 0; + this.collapsedAt = null; + } /** Writes the arguments to stdout */ // tslint:disable-next-line:no-any log = (...args: any[]): void => { - this.printFunc(stringifyArgs(args)); + this.printFunc( + stringifyArgs(args, { + indentLevel: this.indentLevel, + collapsedAt: this.collapsedAt + }), + false, + !isCollapsed(this.collapsedAt, this.indentLevel) + ); }; /** Writes the arguments to stdout */ @@ -380,13 +410,20 @@ export class Console { /** Writes the properties of the supplied `obj` to stdout */ // tslint:disable-next-line:no-any dir = (obj: any, options: ConsoleOptions = {}) => { - this.printFunc(stringifyArgs([obj], options)); + this.log(stringifyArgs([obj], options)); }; /** Writes the arguments to stdout */ // tslint:disable-next-line:no-any warn = (...args: any[]): void => { - this.printFunc(stringifyArgs(args), true); + this.printFunc( + stringifyArgs(args, { + indentLevel: this.indentLevel, + collapsedAt: this.collapsedAt + }), + true, + !isCollapsed(this.collapsedAt, this.indentLevel) + ); }; /** Writes the arguments to stdout */ @@ -484,14 +521,26 @@ export class Console { // tslint:disable-next-line:no-any group = (...label: any[]): void => { - groupIndent += " "; if (label.length > 0) { this.log(...label); } + this.indentLevel += 2; + }; + + groupCollapsed = (...label: unknown[]): void => { + if (this.collapsedAt == null) { + this.collapsedAt = this.indentLevel; + } + this.group(...label); }; groupEnd = (): void => { - groupIndent = groupIndent.slice(0, groupIndent.length - 2); + if (this.indentLevel > 0) { + this.indentLevel -= 2; + } + if (this.collapsedAt != null && this.collapsedAt <= this.indentLevel) { + this.collapsedAt = null; + } }; } diff --git a/js/console_test.ts b/js/console_test.ts index db8e5d47710674..6b6411ae803c4b 100644 --- a/js/console_test.ts +++ b/js/console_test.ts @@ -116,7 +116,7 @@ test(function consoleTestStringifyCircular() { assertEqual( stringify(console), // tslint:disable-next-line:max-line-length - "Console { printFunc: [Function], log: [Function], debug: [Function], info: [Function], dir: [Function], warn: [Function], error: [Function], assert: [Function], count: [Function], countReset: [Function], time: [Function], timeLog: [Function], timeEnd: [Function], group: [Function], groupEnd: [Function] }" + "Console { printFunc: [Function], log: [Function], debug: [Function], info: [Function], dir: [Function], warn: [Function], error: [Function], assert: [Function], count: [Function], countReset: [Function], time: [Function], timeLog: [Function], timeEnd: [Function], group: [Function], groupCollapsed: [Function], groupEnd: [Function], indentLevel: 0, collapsedAt: null }" ); // test inspect is working the same assertEqual(inspect(nestedObj), nestedObjExpected); @@ -145,39 +145,6 @@ test(function consoleTestStringifyWithDepth() { ); }); -test(function consoleStringifyWithGroup() { - const outstrs = [ - "This is the outer level", - "Level 2", - "Level 3", - "More of level 3", - "Back to level 2", - "Back to the outer level", - "Still at the outer level" - ]; - const expectedOut = `${outstrs[0]} ${outstrs[1]} ${outstrs[2]} ${ - outstrs[3] - }${outstrs[4]}${outstrs[5]}`; - - const expectedErr = ` More of level 3`; - let out = ""; - let outErr = ""; - out += stringifyArgs([outstrs[0]]); - console.group(); - out += stringifyArgs([outstrs[1]]); - console.group(); - out += stringifyArgs([outstrs[2]]); - outErr += stringifyArgs([outstrs[3]]); - console.groupEnd(); - out += stringifyArgs([outstrs[3]]); - console.groupEnd(); - out += stringifyArgs([outstrs[4]]); - console.groupEnd(); - out += stringifyArgs([outstrs[5]]); - assertEqual(out, expectedOut); - assertEqual(outErr, expectedErr); -}); - test(function consoleTestCallToStringOnLabel() { const methods = ["count", "countReset", "time", "timeLog", "timeEnd"]; diff --git a/libdeno/binding.cc b/libdeno/binding.cc index eb83d2363d73bd..c126e41b39d340 100644 --- a/libdeno/binding.cc +++ b/libdeno/binding.cc @@ -197,7 +197,7 @@ void PromiseRejectCallback(v8::PromiseRejectMessage promise_reject_message) { void Print(const v8::FunctionCallbackInfo& args) { CHECK_GE(args.Length(), 1); - CHECK_LE(args.Length(), 2); + CHECK_LE(args.Length(), 3); auto* isolate = args.GetIsolate(); DenoIsolate* d = FromIsolate(isolate); auto context = d->context_.Get(d->isolate_); @@ -205,9 +205,13 @@ void Print(const v8::FunctionCallbackInfo& args) { v8::String::Utf8Value str(isolate, args[0]); bool is_err = args.Length() >= 2 ? args[1]->BooleanValue(context).ToChecked() : false; + bool prints_newline = + args.Length() >= 3 ? args[2]->BooleanValue(context).ToChecked() : true; FILE* file = is_err ? stderr : stdout; fwrite(*str, sizeof(**str), str.length(), file); - fprintf(file, "\n"); + if (prints_newline) { + fprintf(file, "\n"); + } fflush(file); } diff --git a/tests/console_group.test b/tests/console_group.test new file mode 100644 index 00000000000000..9b9a0c7bd2bcca --- /dev/null +++ b/tests/console_group.test @@ -0,0 +1,2 @@ +args: tests/console_group.ts --reload +output: tests/console_group.ts.out diff --git a/tests/console_group.ts b/tests/console_group.ts new file mode 100644 index 00000000000000..a0b7caf094910e --- /dev/null +++ b/tests/console_group.ts @@ -0,0 +1,13 @@ +console.group("1"); +console.log("2"); +console.group("3"); +console.log("4"); +console.groupEnd(); +console.groupEnd(); + +console.groupCollapsed("5"); +console.log("6"); +console.group("7"); +console.log("8"); +console.groupEnd(); +console.groupEnd(); diff --git a/tests/console_group.ts.out b/tests/console_group.ts.out new file mode 100644 index 00000000000000..d2502002efb830 --- /dev/null +++ b/tests/console_group.ts.out @@ -0,0 +1,5 @@ +1 + 2 + 3 + 4 +5678 \ No newline at end of file