diff options
-rw-r--r-- | ext/node/lib.rs | 10 | ||||
-rw-r--r-- | ext/node/polyfills/async_hooks.ts | 20 |
2 files changed, 19 insertions, 11 deletions
diff --git a/ext/node/lib.rs b/ext/node/lib.rs index 6d496f001..a623eac11 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -138,6 +138,15 @@ fn op_is_any_arraybuffer(value: serde_v8::Value) -> bool { value.v8_value.is_array_buffer() || value.v8_value.is_shared_array_buffer() } +#[op(fast)] +fn op_node_is_promise_rejected(value: serde_v8::Value) -> bool { + let Ok(promise) = v8::Local::<v8::Promise>::try_from(value.v8_value) else { + return false; + }; + + promise.state() == v8::PromiseState::Rejected +} + deno_core::extension!(deno_node, deps = [ deno_io, deno_fs ], parameters = [P: NodePermissions], @@ -233,6 +242,7 @@ deno_core::extension!(deno_node, ops::http::op_node_http_request<P>, op_node_build_os, op_is_any_arraybuffer, + op_node_is_promise_rejected, ops::require::op_require_init_paths, ops::require::op_require_node_module_paths<P>, ops::require::op_require_proxy_path, diff --git a/ext/node/polyfills/async_hooks.ts b/ext/node/polyfills/async_hooks.ts index df42847a2..c97e81ef5 100644 --- a/ext/node/polyfills/async_hooks.ts +++ b/ext/node/polyfills/async_hooks.ts @@ -10,6 +10,7 @@ import { validateFunction } from "ext:deno_node/internal/validators.mjs"; const { core } = globalThis.__bootstrap; +const { ops } = core; function assert(cond: boolean) { if (!cond) throw new Error("Assertion failed"); @@ -29,10 +30,6 @@ let rootAsyncFrame: AsyncContextFrame | undefined = undefined; let promiseHooksSet = false; const asyncContext = Symbol("asyncContext"); -function isRejected(promise: Promise<unknown>) { - const [state] = core.getPromiseDetails(promise); - return state == 2; -} function setPromiseHooks() { if (promiseHooksSet) { @@ -43,12 +40,14 @@ function setPromiseHooks() { const init = (promise: Promise<unknown>) => { const currentFrame = AsyncContextFrame.current(); if (!currentFrame.isRoot()) { - assert(AsyncContextFrame.tryGetContext(promise) == null); + if (typeof promise[asyncContext] !== "undefined") { + throw new Error("Promise already has async context"); + } AsyncContextFrame.attachContext(promise); } }; const before = (promise: Promise<unknown>) => { - const maybeFrame = AsyncContextFrame.tryGetContext(promise); + const maybeFrame = promise[asyncContext]; if (maybeFrame) { pushAsyncFrame(maybeFrame); } else { @@ -57,16 +56,16 @@ function setPromiseHooks() { }; const after = (promise: Promise<unknown>) => { popAsyncFrame(); - if (!isRejected(promise)) { + if (!ops.op_node_is_promise_rejected(promise)) { // @ts-ignore promise async context - delete promise[asyncContext]; + promise[asyncContext] = undefined; } }; const resolve = (promise: Promise<unknown>) => { const currentFrame = AsyncContextFrame.current(); if ( - !currentFrame.isRoot() && isRejected(promise) && - AsyncContextFrame.tryGetContext(promise) == null + !currentFrame.isRoot() && ops.op_node_is_promise_rejected(promise) && + typeof promise[asyncContext] === "undefined" ) { AsyncContextFrame.attachContext(promise); } @@ -117,7 +116,6 @@ class AsyncContextFrame { } static attachContext(promise: Promise<unknown>) { - assert(!(asyncContext in promise)); // @ts-ignore promise async context promise[asyncContext] = AsyncContextFrame.current(); } |