Skip to content

Commit

Permalink
Support custom inspection of objects (#2791)
Browse files Browse the repository at this point in the history
  • Loading branch information
kitsonk authored and ry committed Aug 19, 2019
1 parent 4faab6a commit f0a2355
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 7 deletions.
9 changes: 8 additions & 1 deletion js/console.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,9 @@ function createObjectString(
value: {},
...args: [ConsoleContext, number, number]
): string {
if (value instanceof Error) {
if (customInspect in value && typeof value[customInspect] === "function") {
return String(value[customInspect]!());
} else if (value instanceof Error) {
return String(value.stack);
} else if (Array.isArray(value)) {
return createArrayString(value, ...args);
Expand Down Expand Up @@ -752,6 +754,11 @@ export class Console {
}
}

/** A symbol which can be used as a key for a custom method which will be called
* when `Deno.inspect()` is called, or when the object is logged to the console.
*/
export const customInspect = Symbol.for("Deno.customInspect");

/**
* `inspect()` converts input into string that has the same format
* as printed by `console.log(...)`;
Expand Down
21 changes: 19 additions & 2 deletions js/console_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@ import { assert, assertEquals, test } from "./test_util.ts";

// Some of these APIs aren't exposed in the types and so we have to cast to any
// in order to "trick" TypeScript.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { Console, stringifyArgs, inspect, write, stdout } = Deno as any;
const {
Console,
customInspect,
stringifyArgs,
inspect,
write,
stdout
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} = Deno as any;

function stringify(...args: unknown[]): string {
return stringifyArgs(args).replace(/\n$/, "");
Expand Down Expand Up @@ -173,6 +180,16 @@ test(function consoleTestStringifyWithDepth(): void {
);
});

test(function consoleTestWithCustomInspector(): void {
class A {
[customInspect](): string {
return "b";
}
}

assertEquals(stringify(new A()), "b");
});

test(function consoleTestWithIntegerFormatSpecifier(): void {
assertEquals(stringify("%i"), "%i");
assertEquals(stringify("%i", 42.0), "42");
Expand Down
2 changes: 1 addition & 1 deletion js/deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export {
ProcessStatus,
Signal
} from "./process";
export { inspect } from "./console";
export { inspect, customInspect } from "./console";
export { build, platform, OperatingSystem, Arch } from "./build";
export { version } from "./version";
export const args: string[] = [];
Expand Down
10 changes: 7 additions & 3 deletions js/globals.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
// This is a "special" module, in that it define the global runtime scope of
// Deno, and therefore it defines a lot of the runtime environemnt that code
// Deno, and therefore it defines a lot of the runtime environment that code
// is evaluated in. We use this file to automatically build the runtime type
// library.

Expand All @@ -12,7 +12,7 @@ import * as blob from "./blob";
import * as consoleTypes from "./console";
import * as csprng from "./get_random_values";
import * as customEvent from "./custom_event";
import * as deno from "./deno";
import * as Deno from "./deno";
import * as domTypes from "./dom_types";
import * as domFile from "./dom_file";
import * as event from "./event";
Expand Down Expand Up @@ -62,6 +62,10 @@ declare global {
interface ErrorConstructor {
prepareStackTrace(error: Error, structuredStackTrace: CallSite[]): string;
}

interface Object {
[consoleTypes.customInspect]?(): string;
}
}

// A self reference to the global object.
Expand All @@ -70,7 +74,7 @@ window.window = window;
// This is the Deno namespace, it is handled differently from other window
// properties when building the runtime type library, as the whole module
// is flattened into a single namespace.
window.Deno = deno;
window.Deno = Deno;
Object.freeze(window.Deno);

// Globally available functions and object instances.
Expand Down

0 comments on commit f0a2355

Please sign in to comment.