summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/console.ts5
-rw-r--r--js/console_test.ts5
-rw-r--r--js/format_error.ts21
-rw-r--r--js/libdeno.ts47
-rw-r--r--js/repl.ts19
5 files changed, 63 insertions, 34 deletions
diff --git a/js/console.ts b/js/console.ts
index 0797ab8e9..e5dafceee 100644
--- a/js/console.ts
+++ b/js/console.ts
@@ -3,6 +3,8 @@ import { isTypedArray } from "./util";
import { TextEncoder } from "./text_encoding";
import { File, stdout } from "./files";
import { cliTable } from "./console_table";
+import { formatError } from "./format_error";
+import { libdeno } from "./libdeno";
// tslint:disable-next-line:no-any
type ConsoleContext = Set<any>;
@@ -263,7 +265,8 @@ function createObjectString(
...args: [ConsoleContext, number, number]
): string {
if (value instanceof Error) {
- return value.stack! || "";
+ const errorJSON = libdeno.errorToJSON(value);
+ return formatError(errorJSON);
} else if (Array.isArray(value)) {
return createArrayString(value, ...args);
} else if (value instanceof Number) {
diff --git a/js/console_test.ts b/js/console_test.ts
index 577c8bf5d..f84dc247a 100644
--- a/js/console_test.ts
+++ b/js/console_test.ts
@@ -1,6 +1,6 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { Console, libdeno, stringifyArgs, inspect, write, stdout } from "deno";
-import { test, assertEqual } from "./test_util.ts";
+import { test, assertEqual, assert } from "./test_util.ts";
const console = new Console(libdeno.print);
@@ -245,7 +245,8 @@ test(function consoleTestError() {
try {
throw new MyError("This is an error");
} catch (e) {
- assertEqual(stringify(e).split("\n")[0], "MyError: This is an error");
+ assert(stringify(e).split("\n")[3]
+ .includes("MyError: This is an error"));
}
});
diff --git a/js/format_error.ts b/js/format_error.ts
new file mode 100644
index 000000000..ebc579355
--- /dev/null
+++ b/js/format_error.ts
@@ -0,0 +1,21 @@
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+import * as msg from "gen/msg_generated";
+import * as flatbuffers from "./flatbuffers";
+import { sendSync } from "./dispatch";
+import { assert } from "./util";
+
+export function formatError(errString: string): string {
+ const builder = flatbuffers.createBuilder();
+ const errString_ = builder.createString(errString);
+ msg.FormatError.startFormatError(builder);
+ msg.FormatError.addError(builder, errString_);
+ const offset = msg.FormatError.endFormatError(builder);
+ const baseRes = sendSync(builder, msg.Any.FormatError, offset);
+ assert(baseRes != null);
+ assert(msg.Any.FormatErrorRes === baseRes!.innerType());
+ const formatErrorResMsg = new msg.FormatErrorRes();
+ assert(baseRes!.inner(formatErrorResMsg) != null);
+ const formattedError = formatErrorResMsg.error();
+ assert(formatError != null);
+ return formattedError!;
+}
diff --git a/js/libdeno.ts b/js/libdeno.ts
index 401ffae40..7d2bc3ede 100644
--- a/js/libdeno.ts
+++ b/js/libdeno.ts
@@ -3,11 +3,17 @@ import { globalEval } from "./global_eval";
// The libdeno functions are moved so that users can't access them.
type MessageCallback = (msg: Uint8Array) => void;
-export type PromiseRejectEvent =
- | "RejectWithNoHandler"
- | "HandlerAddedAfterReject"
- | "ResolveAfterResolved"
- | "RejectAfterResolved";
+
+interface EvalErrorInfo {
+ // Is the object thrown a native Error?
+ isNativeError: boolean;
+ // Was the error happened during compilation?
+ isCompileError: boolean;
+ // The actual thrown entity
+ // (might be an Error or anything else thrown by the user)
+ // If isNativeError is true, this is an Error
+ thrown: any; // tslint:disable-line:no-any
+}
interface Libdeno {
recv(cb: MessageCallback): void;
@@ -20,26 +26,17 @@ interface Libdeno {
builtinModules: { [s: string]: object };
- setGlobalErrorHandler: (
- handler: (
- message: string,
- source: string,
- line: number,
- col: number,
- error: Error
- ) => void
- ) => void;
-
- setPromiseRejectHandler: (
- handler: (
- error: Error | string,
- event: PromiseRejectEvent,
- /* tslint:disable-next-line:no-any */
- promise: Promise<any>
- ) => void
- ) => void;
-
- setPromiseErrorExaminer: (handler: () => boolean) => void;
+ /** Evaluate provided code in the current context.
+ * It differs from eval(...) in that it does not create a new context.
+ * Returns an array: [output, errInfo].
+ * If an error occurs, `output` becomes null and `errInfo` is non-null.
+ */
+ evalContext(
+ code: string
+ ): [any, EvalErrorInfo | null] /* tslint:disable-line:no-any */;
+
+ // tslint:disable-next-line:no-any
+ errorToJSON: (e: Error) => string;
}
const window = globalEval("this");
diff --git a/js/repl.ts b/js/repl.ts
index 6fb395e1b..6676721fc 100644
--- a/js/repl.ts
+++ b/js/repl.ts
@@ -7,6 +7,8 @@ import { close } from "./files";
import * as dispatch from "./dispatch";
import { exit } from "./os";
import { globalEval } from "./global_eval";
+import { libdeno } from "./libdeno";
+import { formatError } from "./format_error";
const window = globalEval("this");
@@ -96,14 +98,19 @@ export async function replLoop(): Promise<void> {
}
function evaluate(code: string): void {
- try {
- const result = eval.call(window, code); // FIXME use a new scope.
+ if (code.trim() === "") {
+ return;
+ }
+ const [result, errInfo] = libdeno.evalContext(code);
+ if (!errInfo) {
console.log(result);
- } catch (err) {
- if (err instanceof Error) {
- console.error(`${err.constructor.name}: ${err.message}`);
+ } else {
+ if (errInfo.isNativeError) {
+ const formattedError = formatError(
+ libdeno.errorToJSON(errInfo.thrown as Error));
+ console.error(formattedError);
} else {
- console.error("Thrown:", err);
+ console.error("Thrown:", errInfo.thrown);
}
}
}