summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/libdeno.ts17
-rw-r--r--js/main.ts3
-rw-r--r--js/promise_util.ts46
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;
+}