diff options
Diffstat (limited to 'js')
-rw-r--r-- | js/libdeno.ts | 17 | ||||
-rw-r--r-- | js/main.ts | 3 | ||||
-rw-r--r-- | js/promise_util.ts | 46 |
3 files changed, 66 insertions, 0 deletions
diff --git a/js/libdeno.ts b/js/libdeno.ts index 97269c36c..842b0c8ad 100644 --- a/js/libdeno.ts +++ b/js/libdeno.ts @@ -3,6 +3,12 @@ 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 Libdeno { recv(cb: MessageCallback): void; @@ -20,6 +26,17 @@ interface Libdeno { ) => void ) => void; + setPromiseRejectHandler: ( + handler: ( + error: Error | string, + event: PromiseRejectEvent, + /* tslint:disable-next-line:no-any */ + promise: Promise<any> + ) => void + ) => void; + + setPromiseErrorExaminer: (handler: () => boolean) => void; + mainSource: string; mainSourceMap: RawSourceMap; } diff --git a/js/main.ts b/js/main.ts index 24418b53e..0d33cf063 100644 --- a/js/main.ts +++ b/js/main.ts @@ -7,6 +7,7 @@ import { DenoCompiler } from "./compiler"; import { libdeno } from "./libdeno"; import { args } from "./deno"; import { sendSync, handleAsyncMsgFromRust } from "./dispatch"; +import { promiseErrorExaminer, promiseRejectHandler } from "./promise_util"; function sendStart(): msg.StartRes { const builder = new flatbuffers.Builder(); @@ -39,6 +40,8 @@ function onGlobalError( export default function denoMain() { libdeno.recv(handleAsyncMsgFromRust); libdeno.setGlobalErrorHandler(onGlobalError); + libdeno.setPromiseRejectHandler(promiseRejectHandler); + libdeno.setPromiseErrorExaminer(promiseErrorExaminer); const compiler = DenoCompiler.instance(); // First we send an empty "Start" message to let the privileged side know we diff --git a/js/promise_util.ts b/js/promise_util.ts new file mode 100644 index 000000000..a550bc388 --- /dev/null +++ b/js/promise_util.ts @@ -0,0 +1,46 @@ +import { PromiseRejectEvent } from "./libdeno"; + +/* tslint:disable-next-line:no-any */ +const rejectMap = new Map<Promise<any>, string>(); +// For uncaught promise rejection errors + +/* tslint:disable-next-line:no-any */ +const otherErrorMap = new Map<Promise<any>, string>(); +// For reject after resolve / resolve after resolve errors + +export function promiseRejectHandler( + error: Error | string, + event: PromiseRejectEvent, + /* tslint:disable-next-line:no-any */ + promise: Promise<any> +) { + switch (event) { + case "RejectWithNoHandler": + rejectMap.set(promise, (error as Error).stack || "RejectWithNoHandler"); + break; + case "HandlerAddedAfterReject": + rejectMap.delete(promise); + break; + default: + // error is string here + otherErrorMap.set(promise, `Promise warning: ${error as string}`); + } +} + +// Return true when continue, false to die on uncaught promise reject +export function promiseErrorExaminer(): boolean { + if (otherErrorMap.size > 0) { + for (const msg of otherErrorMap.values()) { + console.log(msg); + } + otherErrorMap.clear(); + } + if (rejectMap.size > 0) { + for (const msg of rejectMap.values()) { + console.log(msg); + } + rejectMap.clear(); + return false; + } + return true; +} |