summaryrefslogtreecommitdiff
path: root/runtime/js
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/js')
-rw-r--r--runtime/js/99_main.js120
1 files changed, 27 insertions, 93 deletions
diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js
index 6e43da085..050cd3bf8 100644
--- a/runtime/js/99_main.js
+++ b/runtime/js/99_main.js
@@ -9,12 +9,8 @@ const internals = globalThis.__bootstrap.internals;
const primordials = globalThis.__bootstrap.primordials;
const {
ArrayPrototypeFilter,
- ArrayPrototypeIndexOf,
ArrayPrototypeIncludes,
ArrayPrototypeMap,
- ArrayPrototypePush,
- ArrayPrototypeShift,
- ArrayPrototypeSplice,
DateNow,
Error,
ErrorPrototype,
@@ -27,13 +23,9 @@ const {
ObjectSetPrototypeOf,
PromisePrototypeThen,
PromiseResolve,
- SafeWeakMap,
Symbol,
SymbolIterator,
TypeError,
- WeakMapPrototypeDelete,
- WeakMapPrototypeGet,
- WeakMapPrototypeSet,
} = primordials;
import * as util from "ext:runtime/06_util.js";
import * as event from "ext:deno_web/02_event.js";
@@ -328,7 +320,6 @@ function runtimeStart(
target,
) {
core.setMacrotaskCallback(timers.handleTimerMacrotask);
- core.setMacrotaskCallback(promiseRejectMacrotaskCallback);
core.setWasmStreamingCallback(fetch.handleWasmStreaming);
core.setReportExceptionCallback(event.reportException);
ops.op_set_format_exception_callback(formatException);
@@ -340,91 +331,38 @@ function runtimeStart(
core.setBuildInfo(target);
}
-const pendingRejections = [];
-const pendingRejectionsReasons = new SafeWeakMap();
-
-function promiseRejectCallback(type, promise, reason) {
- switch (type) {
- case 0: {
- ops.op_store_pending_promise_rejection(promise, reason);
- ArrayPrototypePush(pendingRejections, promise);
- WeakMapPrototypeSet(pendingRejectionsReasons, promise, reason);
- break;
- }
- case 1: {
- ops.op_remove_pending_promise_rejection(promise);
- const index = ArrayPrototypeIndexOf(pendingRejections, promise);
- if (index > -1) {
- ArrayPrototypeSplice(pendingRejections, index, 1);
- WeakMapPrototypeDelete(pendingRejectionsReasons, promise);
- }
- break;
- }
- default:
- return false;
- }
-
- return !!globalThis_.onunhandledrejection ||
- event.listenerCount(globalThis_, "unhandledrejection") > 0 ||
- typeof internals.nodeProcessUnhandledRejectionCallback !== "undefined";
-}
-
-function promiseRejectMacrotaskCallback() {
- // We have no work to do, tell the runtime that we don't
- // need to perform microtask checkpoint.
- if (pendingRejections.length === 0) {
- return undefined;
- }
-
- while (pendingRejections.length > 0) {
- const promise = ArrayPrototypeShift(pendingRejections);
- const hasPendingException = ops.op_has_pending_promise_rejection(
+core.setUnhandledPromiseRejectionHandler(processUnhandledPromiseRejection);
+// Notification that the core received an unhandled promise rejection that is about to
+// terminate the runtime. If we can handle it, attempt to do so.
+function processUnhandledPromiseRejection(promise, reason) {
+ const rejectionEvent = new event.PromiseRejectionEvent(
+ "unhandledrejection",
+ {
+ cancelable: true,
promise,
- );
- const reason = WeakMapPrototypeGet(pendingRejectionsReasons, promise);
- WeakMapPrototypeDelete(pendingRejectionsReasons, promise);
+ reason,
+ },
+ );
- if (!hasPendingException) {
- continue;
- }
+ // Note that the handler may throw, causing a recursive "error" event
+ globalThis_.dispatchEvent(rejectionEvent);
- const rejectionEvent = new event.PromiseRejectionEvent(
- "unhandledrejection",
- {
- cancelable: true,
- promise,
- reason,
- },
- );
-
- const errorEventCb = (event) => {
- if (event.error === reason) {
- ops.op_remove_pending_promise_rejection(promise);
- }
- };
- // Add a callback for "error" event - it will be dispatched
- // if error is thrown during dispatch of "unhandledrejection"
- // event.
- globalThis_.addEventListener("error", errorEventCb);
- globalThis_.dispatchEvent(rejectionEvent);
- globalThis_.removeEventListener("error", errorEventCb);
-
- // If event was not yet prevented, try handing it off to Node compat layer
- // (if it was initialized)
- if (
- !rejectionEvent.defaultPrevented &&
- typeof internals.nodeProcessUnhandledRejectionCallback !== "undefined"
- ) {
- internals.nodeProcessUnhandledRejectionCallback(rejectionEvent);
- }
+ // If event was not yet prevented, try handing it off to Node compat layer
+ // (if it was initialized)
+ if (
+ !rejectionEvent.defaultPrevented &&
+ typeof internals.nodeProcessUnhandledRejectionCallback !== "undefined"
+ ) {
+ internals.nodeProcessUnhandledRejectionCallback(rejectionEvent);
+ }
- // If event was not prevented (or "unhandledrejection" listeners didn't
- // throw) we will let Rust side handle it.
- if (rejectionEvent.defaultPrevented) {
- ops.op_remove_pending_promise_rejection(promise);
- }
+ // If event was not prevented (or "unhandledrejection" listeners didn't
+ // throw) we will let Rust side handle it.
+ if (rejectionEvent.defaultPrevented) {
+ return true;
}
- return true;
+
+ return false;
}
let hasBootstrapped = false;
@@ -523,8 +461,6 @@ function bootstrapMainRuntime(runtimeOptions) {
event.defineEventHandler(globalThis, "unload");
event.defineEventHandler(globalThis, "unhandledrejection");
- core.setPromiseRejectCallback(promiseRejectCallback);
-
runtimeStart(
denoVersion,
v8Version,
@@ -642,8 +578,6 @@ function bootstrapWorkerRuntime(
event.defineEventHandler(self, "error", undefined, true);
event.defineEventHandler(self, "unhandledrejection");
- core.setPromiseRejectCallback(promiseRejectCallback);
-
// `Deno.exit()` is an alias to `self.close()`. Setting and exit
// code using an op in worker context is a no-op.
os.setExitHandler((_exitCode) => {