summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin (Kun) "Kassimo" Qian <kevinkassimo@gmail.com>2018-09-26 09:44:59 -0700
committerRyan Dahl <ry@tinyclouds.org>2018-09-26 19:30:43 -0400
commit1e390e69cd45aeb4570fe821ef0ea866b71433e6 (patch)
tree4c8037a9b3a9aa16d4689cb5ec72285ef8ab345b
parent32806b18719f09ec3c1f5b41f3a8f98321328884 (diff)
Error pretty print (print stack)
-rw-r--r--js/console.ts112
-rw-r--r--js/console_test.ts14
2 files changed, 79 insertions, 47 deletions
diff --git a/js/console.ts b/js/console.ts
index 00a24e83c..d3bd5bb6b 100644
--- a/js/console.ts
+++ b/js/console.ts
@@ -6,12 +6,68 @@ function getClassInstanceName(instance: any): string {
if (typeof instance !== "object") {
return "";
}
- if (instance && instance.__proto__ && instance.__proto__.constructor) {
- return instance.__proto__.constructor.name; // could be "Object" or "Array"
+ if (instance) {
+ const proto = Object.getPrototypeOf(instance);
+ if (proto && proto.constructor) {
+ return proto.constructor.name; // could be "Object" or "Array"
+ }
}
return "";
}
+function createFunctionString(value: Function, ctx: ConsoleContext): string {
+ // Might be Function/AsyncFunction/GeneratorFunction
+ const cstrName = Object.getPrototypeOf(value).constructor.name;
+ if (value.name && value.name !== "anonymous") {
+ // from MDN spec
+ return `[${cstrName}: ${value.name}]`;
+ }
+ return `[${cstrName}]`;
+}
+
+// tslint:disable-next-line:no-any
+function createArrayString(value: any[], ctx: ConsoleContext): string {
+ const entries: string[] = [];
+ for (const el of value) {
+ entries.push(stringifyWithQuotes(ctx, el));
+ }
+ ctx.delete(value);
+ if (entries.length === 0) {
+ return "[]";
+ }
+ return `[ ${entries.join(", ")} ]`;
+}
+
+// tslint:disable-next-line:no-any
+function createObjectString(value: any, ctx: ConsoleContext): string {
+ const entries: string[] = [];
+ let baseString = "";
+
+ const className = getClassInstanceName(value);
+ let shouldShowClassName = false;
+ if (className && className !== "Object" && className !== "anonymous") {
+ shouldShowClassName = true;
+ }
+
+ for (const key of Object.keys(value)) {
+ entries.push(`${key}: ${stringifyWithQuotes(ctx, value[key])}`);
+ }
+
+ ctx.delete(value);
+
+ if (entries.length === 0) {
+ baseString = "{}";
+ } else {
+ baseString = `{ ${entries.join(", ")} }`;
+ }
+
+ if (shouldShowClassName) {
+ baseString = `${className} ${baseString}`;
+ }
+
+ return baseString;
+}
+
// tslint:disable-next-line:no-any
function stringify(ctx: ConsoleContext, value: any): string {
switch (typeof value) {
@@ -23,13 +79,7 @@ function stringify(ctx: ConsoleContext, value: any): string {
case "symbol":
return String(value);
case "function":
- // Might be Function/AsyncFunction/GeneratorFunction
- const cstrName = value.__proto__.constructor.name;
- if (value.name && value.name !== "anonymous") {
- // from MDN spec
- return `[${cstrName}: ${value.name}]`;
- }
- return `[${cstrName}]`;
+ return createFunctionString(value as Function, ctx);
case "object":
if (value === null) {
return "null";
@@ -38,47 +88,15 @@ function stringify(ctx: ConsoleContext, value: any): string {
if (ctx.has(value)) {
return "[Circular]";
}
-
ctx.add(value);
- const entries: string[] = [];
-
- if (Array.isArray(value)) {
- for (const el of value) {
- entries.push(stringifyWithQuotes(ctx, el));
- }
- ctx.delete(value);
-
- if (entries.length === 0) {
- return "[]";
- }
- return `[ ${entries.join(", ")} ]`;
+ if (value instanceof Error) {
+ return value.stack! || "";
+ } else if (Array.isArray(value)) {
+ // tslint:disable-next-line:no-any
+ return createArrayString(value as any[], ctx);
} else {
- let baseString = "";
-
- const className = getClassInstanceName(value);
- let shouldShowClassName = false;
- if (className && className !== "Object" && className !== "anonymous") {
- shouldShowClassName = true;
- }
-
- for (const key of Object.keys(value)) {
- entries.push(`${key}: ${stringifyWithQuotes(ctx, value[key])}`);
- }
-
- ctx.delete(value);
-
- if (entries.length === 0) {
- baseString = "{}";
- } else {
- baseString = `{ ${entries.join(", ")} }`;
- }
-
- if (shouldShowClassName) {
- baseString = `${className} ${baseString}`;
- }
-
- return baseString;
+ return createObjectString(value, ctx);
}
default:
return "[Not Implemented]";
diff --git a/js/console_test.ts b/js/console_test.ts
index cfe75dafe..94a627a5f 100644
--- a/js/console_test.ts
+++ b/js/console_test.ts
@@ -91,3 +91,17 @@ test(function consoleTestStringifyCircular() {
"Console { printFunc: [Function], debug: [Function: log], info: [Function: log], error: [Function: warn] }"
);
});
+
+test(function consoleTestError() {
+ class MyError extends Error {
+ constructor(msg: string) {
+ super(msg);
+ this.name = "MyError";
+ }
+ }
+ try {
+ throw new MyError("This is an error");
+ } catch (e) {
+ assertEqual(stringify(e).split("\n")[0], "MyError: This is an error");
+ }
+});