From 7bafb60ac08886386db3a76e72b3b37174071eac Mon Sep 17 00:00:00 2001 From: "Kamat, Trivikram" <16024985+trivikr@users.noreply.github.com> Date: Sun, 5 Apr 2026 13:41:03 -0700 Subject: [PATCH 1/3] chore: use Promise.withResolvers for async helpers - Replace manual promise wrappers across API and dispatcher paths - Keep error and timeout handling intact while simplifying control flow Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> --- lib/api/api-connect.js | 8 +- lib/api/api-request.js | 8 +- lib/api/api-stream.js | 8 +- lib/api/api-upgrade.js | 8 +- lib/api/readable.js | 20 ++++- lib/dispatcher/client-h1.js | 6 +- lib/dispatcher/client-h2.js | 6 +- lib/dispatcher/client.js | 56 ++++++------ lib/dispatcher/dispatcher-base.js | 16 ++-- lib/dispatcher/pool-base.js | 6 +- lib/dispatcher/socks5-proxy-agent.js | 130 ++++++++++++++------------- lib/web/fetch/index.js | 8 +- 12 files changed, 153 insertions(+), 127 deletions(-) diff --git a/lib/api/api-connect.js b/lib/api/api-connect.js index b545a3eb5c1..b2e15e25f24 100644 --- a/lib/api/api-connect.js +++ b/lib/api/api-connect.js @@ -89,11 +89,11 @@ class ConnectHandler extends AsyncResource { function connect (opts, callback) { if (callback === undefined) { - return new Promise((resolve, reject) => { - connect.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data) - }) + const { promise, resolve, reject } = Promise.withResolvers() + connect.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) }) + return promise } try { diff --git a/lib/api/api-request.js b/lib/api/api-request.js index 1d56fb0c9ad..48dc90fb659 100644 --- a/lib/api/api-request.js +++ b/lib/api/api-request.js @@ -214,11 +214,11 @@ class RequestHandler extends AsyncResource { function request (opts, callback) { if (callback === undefined) { - return new Promise((resolve, reject) => { - request.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data) - }) + const { promise, resolve, reject } = Promise.withResolvers() + request.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) }) + return promise } try { diff --git a/lib/api/api-stream.js b/lib/api/api-stream.js index daee5681223..1e9cc51fcc3 100644 --- a/lib/api/api-stream.js +++ b/lib/api/api-stream.js @@ -201,11 +201,11 @@ class StreamHandler extends AsyncResource { function stream (opts, factory, callback) { if (callback === undefined) { - return new Promise((resolve, reject) => { - stream.call(this, opts, factory, (err, data) => { - return err ? reject(err) : resolve(data) - }) + const { promise, resolve, reject } = Promise.withResolvers() + stream.call(this, opts, factory, (err, data) => { + return err ? reject(err) : resolve(data) }) + return promise } try { diff --git a/lib/api/api-upgrade.js b/lib/api/api-upgrade.js index 9f1d80c62dc..eed763e025a 100644 --- a/lib/api/api-upgrade.js +++ b/lib/api/api-upgrade.js @@ -88,11 +88,11 @@ class UpgradeHandler extends AsyncResource { function upgrade (opts, callback) { if (callback === undefined) { - return new Promise((resolve, reject) => { - upgrade.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data) - }) + const { promise, resolve, reject } = Promise.withResolvers() + upgrade.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) }) + return promise } try { diff --git a/lib/api/readable.js b/lib/api/readable.js index cdede959980..243e409690d 100644 --- a/lib/api/readable.js +++ b/lib/api/readable.js @@ -281,7 +281,9 @@ class BodyReadable extends Readable { return Promise.resolve(null) } - return new Promise((resolve, reject) => { + const { promise, resolve, reject } = Promise.withResolvers() + + try { if ( (this[kContentLength] && (this[kContentLength] > limit)) || this[kBytesRead] > limit @@ -315,7 +317,11 @@ class BodyReadable extends Readable { } }) .resume() - }) + } catch (err) { + reject(err) + } + + return promise } /** @@ -382,7 +388,9 @@ function isUnusable (bodyReadable) { function consume (stream, type) { assert(!stream[kConsume]) - return new Promise((resolve, reject) => { + const { promise, resolve, reject } = Promise.withResolvers() + + try { if (isUnusable(stream)) { const rState = stream._readableState if (rState.destroyed && rState.closeEmitted === false) { @@ -418,7 +426,11 @@ function consume (stream, type) { consumeStart(stream[kConsume]) }) } - }) + } catch (err) { + reject(err) + } + + return promise } /** diff --git a/lib/dispatcher/client-h1.js b/lib/dispatcher/client-h1.js index 887b0fb029f..4fc41d6e3d2 100644 --- a/lib/dispatcher/client-h1.js +++ b/lib/dispatcher/client-h1.js @@ -1414,7 +1414,8 @@ async function writeIterable (abort, body, client, request, socket, contentLengt } } - const waitForDrain = () => new Promise((resolve, reject) => { + const waitForDrain = () => { + const { promise, resolve, reject } = Promise.withResolvers() assert(callback === null) if (socket[kError]) { @@ -1422,7 +1423,8 @@ async function writeIterable (abort, body, client, request, socket, contentLengt } else { callback = resolve } - }) + return promise + } socket .on('close', onDrain) diff --git a/lib/dispatcher/client-h2.js b/lib/dispatcher/client-h2.js index 58ccdfb75ec..9570f57cb43 100644 --- a/lib/dispatcher/client-h2.js +++ b/lib/dispatcher/client-h2.js @@ -945,7 +945,8 @@ async function writeIterable (abort, h2stream, body, client, request, socket, co } } - const waitForDrain = () => new Promise((resolve, reject) => { + const waitForDrain = () => { + const { promise, resolve, reject } = Promise.withResolvers() assert(callback === null) if (socket[kError]) { @@ -953,7 +954,8 @@ async function writeIterable (abort, h2stream, body, client, request, socket, co } else { callback = resolve } - }) + return promise + } h2stream .on('close', onDrain) diff --git a/lib/dispatcher/client.js b/lib/dispatcher/client.js index f40fbb2c75b..ae9fb9a2431 100644 --- a/lib/dispatcher/client.js +++ b/lib/dispatcher/client.js @@ -359,41 +359,41 @@ class Client extends DispatcherBase { [kClose] () { // TODO: for H2 we need to gracefully flush the remaining enqueued // request and close each stream. - return new Promise((resolve) => { - if (this[kSize]) { - this[kClosedResolve] = resolve - } else { - resolve(null) - } - }) + const { promise, resolve } = Promise.withResolvers() + if (this[kSize]) { + this[kClosedResolve] = resolve + } else { + resolve(null) + } + return promise } [kDestroy] (err) { - return new Promise((resolve) => { - const requests = this[kQueue].splice(this[kPendingIdx]) - for (let i = 0; i < requests.length; i++) { - const request = requests[i] - util.errorRequest(this, request, err) - } + const { promise, resolve } = Promise.withResolvers() + const requests = this[kQueue].splice(this[kPendingIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + util.errorRequest(this, request, err) + } - const callback = () => { - if (this[kClosedResolve]) { - // TODO (fix): Should we error here with ClientDestroyedError? - this[kClosedResolve]() - this[kClosedResolve] = null - } - resolve(null) + const callback = () => { + if (this[kClosedResolve]) { + // TODO (fix): Should we error here with ClientDestroyedError? + this[kClosedResolve]() + this[kClosedResolve] = null } + resolve(null) + } - if (this[kHTTPContext]) { - this[kHTTPContext].destroy(err, callback) - this[kHTTPContext] = null - } else { - queueMicrotask(callback) - } + if (this[kHTTPContext]) { + this[kHTTPContext].destroy(err, callback) + this[kHTTPContext] = null + } else { + queueMicrotask(callback) + } - this[kResume]() - }) + this[kResume]() + return promise } } diff --git a/lib/dispatcher/dispatcher-base.js b/lib/dispatcher/dispatcher-base.js index 59ad3abd046..735bd920161 100644 --- a/lib/dispatcher/dispatcher-base.js +++ b/lib/dispatcher/dispatcher-base.js @@ -36,11 +36,11 @@ class DispatcherBase extends Dispatcher { close (callback) { if (callback === undefined) { - return new Promise((resolve, reject) => { - this.close((err, data) => { - return err ? reject(err) : resolve(data) - }) + const { promise, resolve, reject } = Promise.withResolvers() + this.close((err, data) => { + return err ? reject(err) : resolve(data) }) + return promise } if (typeof callback !== 'function') { @@ -87,11 +87,11 @@ class DispatcherBase extends Dispatcher { } if (callback === undefined) { - return new Promise((resolve, reject) => { - this.destroy(err, (err, data) => { - return err ? reject(err) : resolve(data) - }) + const { promise, resolve, reject } = Promise.withResolvers() + this.destroy(err, (err, data) => { + return err ? reject(err) : resolve(data) }) + return promise } if (typeof callback !== 'function') { diff --git a/lib/dispatcher/pool-base.js b/lib/dispatcher/pool-base.js index daa19cb812e..d0703597ac2 100644 --- a/lib/dispatcher/pool-base.js +++ b/lib/dispatcher/pool-base.js @@ -131,9 +131,9 @@ class PoolBase extends DispatcherBase { } return Promise.all(closeAll) } else { - return new Promise((resolve) => { - this[kClosedResolve] = resolve - }) + const { promise, resolve } = Promise.withResolvers() + this[kClosedResolve] = resolve + return promise } } diff --git a/lib/dispatcher/socks5-proxy-agent.js b/lib/dispatcher/socks5-proxy-agent.js index a2dd2f428c7..4a2f65e6eed 100644 --- a/lib/dispatcher/socks5-proxy-agent.js +++ b/lib/dispatcher/socks5-proxy-agent.js @@ -79,26 +79,28 @@ class Socks5ProxyAgent extends DispatcherBase { debug('creating SOCKS5 connection to', proxyHost, proxyPort) // Connect to the SOCKS5 proxy - const socket = await new Promise((resolve, reject) => { - const onConnect = () => { - socket.removeListener('error', onError) - resolve(socket) - } + const socketReady = Promise.withResolvers() - const onError = (err) => { - socket.removeListener('connect', onConnect) - reject(err) - } + const onSocketConnect = () => { + socket.removeListener('error', onSocketError) + socketReady.resolve(socket) + } - const socket = net.connect({ - host: proxyHost, - port: proxyPort - }) + const onSocketError = (err) => { + socket.removeListener('connect', onSocketConnect) + socketReady.reject(err) + } - socket.once('connect', onConnect) - socket.once('error', onError) + const socket = net.connect({ + host: proxyHost, + port: proxyPort }) + socket.once('connect', onSocketConnect) + socket.once('error', onSocketError) + + await socketReady.promise + // Create SOCKS5 client const socks5Client = new Socks5Client(socket, this[kProxyAuth]) @@ -112,58 +114,62 @@ class Socks5ProxyAgent extends DispatcherBase { await socks5Client.handshake() // Wait for authentication (if required) - await new Promise((resolve, reject) => { - const timeout = setTimeout(() => { - reject(new Error('SOCKS5 authentication timeout')) - }, 5000) - - const onAuthenticated = () => { - clearTimeout(timeout) - socks5Client.removeListener('error', onError) - resolve() - } + const authenticationReady = Promise.withResolvers() - const onError = (err) => { - clearTimeout(timeout) - socks5Client.removeListener('authenticated', onAuthenticated) - reject(err) - } + const authenticationTimeout = setTimeout(() => { + authenticationReady.reject(new Error('SOCKS5 authentication timeout')) + }, 5000) - // Check if already authenticated (for NO_AUTH method) - if (socks5Client.state === 'authenticated') { - clearTimeout(timeout) - resolve() - } else { - socks5Client.once('authenticated', onAuthenticated) - socks5Client.once('error', onError) - } - }) + const onAuthenticated = () => { + clearTimeout(authenticationTimeout) + socks5Client.removeListener('error', onAuthenticationError) + authenticationReady.resolve() + } + + const onAuthenticationError = (err) => { + clearTimeout(authenticationTimeout) + socks5Client.removeListener('authenticated', onAuthenticated) + authenticationReady.reject(err) + } + + // Check if already authenticated (for NO_AUTH method) + if (socks5Client.state === 'authenticated') { + clearTimeout(authenticationTimeout) + authenticationReady.resolve() + } else { + socks5Client.once('authenticated', onAuthenticated) + socks5Client.once('error', onAuthenticationError) + } + + await authenticationReady.promise // Send CONNECT command await socks5Client.connect(targetHost, targetPort) // Wait for connection - await new Promise((resolve, reject) => { - const timeout = setTimeout(() => { - reject(new Error('SOCKS5 connection timeout')) - }, 5000) - - const onConnected = (info) => { - debug('SOCKS5 tunnel established to', targetHost, targetPort, 'via', info) - clearTimeout(timeout) - socks5Client.removeListener('error', onError) - resolve() - } + const connectionReady = Promise.withResolvers() - const onError = (err) => { - clearTimeout(timeout) - socks5Client.removeListener('connected', onConnected) - reject(err) - } + const connectionTimeout = setTimeout(() => { + connectionReady.reject(new Error('SOCKS5 connection timeout')) + }, 5000) - socks5Client.once('connected', onConnected) - socks5Client.once('error', onError) - }) + const onConnected = (info) => { + debug('SOCKS5 tunnel established to', targetHost, targetPort, 'via', info) + clearTimeout(connectionTimeout) + socks5Client.removeListener('error', onConnectionError) + connectionReady.resolve() + } + + const onConnectionError = (err) => { + clearTimeout(connectionTimeout) + socks5Client.removeListener('connected', onConnected) + connectionReady.reject(err) + } + + socks5Client.once('connected', onConnected) + socks5Client.once('error', onConnectionError) + + await connectionReady.promise return socket } @@ -206,10 +212,10 @@ class Socks5ProxyAgent extends DispatcherBase { ...connectOpts.tls || {} }) - await new Promise((resolve, reject) => { - finalSocket.once('secureConnect', resolve) - finalSocket.once('error', reject) - }) + const tlsReady = Promise.withResolvers() + finalSocket.once('secureConnect', tlsReady.resolve) + finalSocket.once('error', tlsReady.reject) + await tlsReady.promise } callback(null, finalSocket) diff --git a/lib/web/fetch/index.js b/lib/web/fetch/index.js index 982a0301951..e097ab36cb9 100644 --- a/lib/web/fetch/index.js +++ b/lib/web/fetch/index.js @@ -2133,7 +2133,9 @@ async function httpNetworkFetch ( return dispatchWithProtocolPreference(body) function dispatchWithProtocolPreference (body, allowH2) { - return new Promise((resolve, reject) => agent.dispatch( + const { promise, resolve, reject } = Promise.withResolvers() + + agent.dispatch( { path: hasTrailingQuestionMark ? `${path}?` : path, origin: url.origin, @@ -2365,7 +2367,9 @@ async function httpNetworkFetch ( return true } } - )) + ) + + return promise } } } From bd0f9bd1181cb221e54f71dece54888c73ed2aff Mon Sep 17 00:00:00 2001 From: "Kamat, Trivikram" <16024985+trivikr@users.noreply.github.com> Date: Sun, 5 Apr 2026 14:06:38 -0700 Subject: [PATCH 2/3] chore: re-introduce 'new Promise(...)' with 1-2 LoC in body --- lib/api/api-connect.js | 8 ++++---- lib/api/api-request.js | 8 ++++---- lib/api/api-stream.js | 8 ++++---- lib/api/api-upgrade.js | 8 ++++---- lib/dispatcher/dispatcher-base.js | 16 ++++++++-------- lib/dispatcher/pool-base.js | 6 +++--- 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/lib/api/api-connect.js b/lib/api/api-connect.js index b2e15e25f24..b545a3eb5c1 100644 --- a/lib/api/api-connect.js +++ b/lib/api/api-connect.js @@ -89,11 +89,11 @@ class ConnectHandler extends AsyncResource { function connect (opts, callback) { if (callback === undefined) { - const { promise, resolve, reject } = Promise.withResolvers() - connect.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data) + return new Promise((resolve, reject) => { + connect.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) }) - return promise } try { diff --git a/lib/api/api-request.js b/lib/api/api-request.js index 48dc90fb659..1d56fb0c9ad 100644 --- a/lib/api/api-request.js +++ b/lib/api/api-request.js @@ -214,11 +214,11 @@ class RequestHandler extends AsyncResource { function request (opts, callback) { if (callback === undefined) { - const { promise, resolve, reject } = Promise.withResolvers() - request.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data) + return new Promise((resolve, reject) => { + request.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) }) - return promise } try { diff --git a/lib/api/api-stream.js b/lib/api/api-stream.js index 1e9cc51fcc3..daee5681223 100644 --- a/lib/api/api-stream.js +++ b/lib/api/api-stream.js @@ -201,11 +201,11 @@ class StreamHandler extends AsyncResource { function stream (opts, factory, callback) { if (callback === undefined) { - const { promise, resolve, reject } = Promise.withResolvers() - stream.call(this, opts, factory, (err, data) => { - return err ? reject(err) : resolve(data) + return new Promise((resolve, reject) => { + stream.call(this, opts, factory, (err, data) => { + return err ? reject(err) : resolve(data) + }) }) - return promise } try { diff --git a/lib/api/api-upgrade.js b/lib/api/api-upgrade.js index eed763e025a..9f1d80c62dc 100644 --- a/lib/api/api-upgrade.js +++ b/lib/api/api-upgrade.js @@ -88,11 +88,11 @@ class UpgradeHandler extends AsyncResource { function upgrade (opts, callback) { if (callback === undefined) { - const { promise, resolve, reject } = Promise.withResolvers() - upgrade.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data) + return new Promise((resolve, reject) => { + upgrade.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) }) - return promise } try { diff --git a/lib/dispatcher/dispatcher-base.js b/lib/dispatcher/dispatcher-base.js index 735bd920161..59ad3abd046 100644 --- a/lib/dispatcher/dispatcher-base.js +++ b/lib/dispatcher/dispatcher-base.js @@ -36,11 +36,11 @@ class DispatcherBase extends Dispatcher { close (callback) { if (callback === undefined) { - const { promise, resolve, reject } = Promise.withResolvers() - this.close((err, data) => { - return err ? reject(err) : resolve(data) + return new Promise((resolve, reject) => { + this.close((err, data) => { + return err ? reject(err) : resolve(data) + }) }) - return promise } if (typeof callback !== 'function') { @@ -87,11 +87,11 @@ class DispatcherBase extends Dispatcher { } if (callback === undefined) { - const { promise, resolve, reject } = Promise.withResolvers() - this.destroy(err, (err, data) => { - return err ? reject(err) : resolve(data) + return new Promise((resolve, reject) => { + this.destroy(err, (err, data) => { + return err ? reject(err) : resolve(data) + }) }) - return promise } if (typeof callback !== 'function') { diff --git a/lib/dispatcher/pool-base.js b/lib/dispatcher/pool-base.js index d0703597ac2..daa19cb812e 100644 --- a/lib/dispatcher/pool-base.js +++ b/lib/dispatcher/pool-base.js @@ -131,9 +131,9 @@ class PoolBase extends DispatcherBase { } return Promise.all(closeAll) } else { - const { promise, resolve } = Promise.withResolvers() - this[kClosedResolve] = resolve - return promise + return new Promise((resolve) => { + this[kClosedResolve] = resolve + }) } } From 25d35dcd4357627b811503db5751326c796763f7 Mon Sep 17 00:00:00 2001 From: "Kamat, Trivikram" <16024985+trivikr@users.noreply.github.com> Date: Sun, 5 Apr 2026 15:12:48 -0700 Subject: [PATCH 3/3] chore: re-introduce 'new Promise(...)' with single proimse in block --- lib/api/readable.js | 20 +++---------- lib/dispatcher/client-h1.js | 6 ++-- lib/dispatcher/client-h2.js | 6 ++-- lib/dispatcher/client.js | 56 ++++++++++++++++++------------------- lib/web/fetch/index.js | 8 ++---- 5 files changed, 38 insertions(+), 58 deletions(-) diff --git a/lib/api/readable.js b/lib/api/readable.js index 243e409690d..cdede959980 100644 --- a/lib/api/readable.js +++ b/lib/api/readable.js @@ -281,9 +281,7 @@ class BodyReadable extends Readable { return Promise.resolve(null) } - const { promise, resolve, reject } = Promise.withResolvers() - - try { + return new Promise((resolve, reject) => { if ( (this[kContentLength] && (this[kContentLength] > limit)) || this[kBytesRead] > limit @@ -317,11 +315,7 @@ class BodyReadable extends Readable { } }) .resume() - } catch (err) { - reject(err) - } - - return promise + }) } /** @@ -388,9 +382,7 @@ function isUnusable (bodyReadable) { function consume (stream, type) { assert(!stream[kConsume]) - const { promise, resolve, reject } = Promise.withResolvers() - - try { + return new Promise((resolve, reject) => { if (isUnusable(stream)) { const rState = stream._readableState if (rState.destroyed && rState.closeEmitted === false) { @@ -426,11 +418,7 @@ function consume (stream, type) { consumeStart(stream[kConsume]) }) } - } catch (err) { - reject(err) - } - - return promise + }) } /** diff --git a/lib/dispatcher/client-h1.js b/lib/dispatcher/client-h1.js index 4fc41d6e3d2..887b0fb029f 100644 --- a/lib/dispatcher/client-h1.js +++ b/lib/dispatcher/client-h1.js @@ -1414,8 +1414,7 @@ async function writeIterable (abort, body, client, request, socket, contentLengt } } - const waitForDrain = () => { - const { promise, resolve, reject } = Promise.withResolvers() + const waitForDrain = () => new Promise((resolve, reject) => { assert(callback === null) if (socket[kError]) { @@ -1423,8 +1422,7 @@ async function writeIterable (abort, body, client, request, socket, contentLengt } else { callback = resolve } - return promise - } + }) socket .on('close', onDrain) diff --git a/lib/dispatcher/client-h2.js b/lib/dispatcher/client-h2.js index 9570f57cb43..58ccdfb75ec 100644 --- a/lib/dispatcher/client-h2.js +++ b/lib/dispatcher/client-h2.js @@ -945,8 +945,7 @@ async function writeIterable (abort, h2stream, body, client, request, socket, co } } - const waitForDrain = () => { - const { promise, resolve, reject } = Promise.withResolvers() + const waitForDrain = () => new Promise((resolve, reject) => { assert(callback === null) if (socket[kError]) { @@ -954,8 +953,7 @@ async function writeIterable (abort, h2stream, body, client, request, socket, co } else { callback = resolve } - return promise - } + }) h2stream .on('close', onDrain) diff --git a/lib/dispatcher/client.js b/lib/dispatcher/client.js index ae9fb9a2431..f40fbb2c75b 100644 --- a/lib/dispatcher/client.js +++ b/lib/dispatcher/client.js @@ -359,41 +359,41 @@ class Client extends DispatcherBase { [kClose] () { // TODO: for H2 we need to gracefully flush the remaining enqueued // request and close each stream. - const { promise, resolve } = Promise.withResolvers() - if (this[kSize]) { - this[kClosedResolve] = resolve - } else { - resolve(null) - } - return promise + return new Promise((resolve) => { + if (this[kSize]) { + this[kClosedResolve] = resolve + } else { + resolve(null) + } + }) } [kDestroy] (err) { - const { promise, resolve } = Promise.withResolvers() - const requests = this[kQueue].splice(this[kPendingIdx]) - for (let i = 0; i < requests.length; i++) { - const request = requests[i] - util.errorRequest(this, request, err) - } + return new Promise((resolve) => { + const requests = this[kQueue].splice(this[kPendingIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + util.errorRequest(this, request, err) + } - const callback = () => { - if (this[kClosedResolve]) { - // TODO (fix): Should we error here with ClientDestroyedError? - this[kClosedResolve]() - this[kClosedResolve] = null + const callback = () => { + if (this[kClosedResolve]) { + // TODO (fix): Should we error here with ClientDestroyedError? + this[kClosedResolve]() + this[kClosedResolve] = null + } + resolve(null) } - resolve(null) - } - if (this[kHTTPContext]) { - this[kHTTPContext].destroy(err, callback) - this[kHTTPContext] = null - } else { - queueMicrotask(callback) - } + if (this[kHTTPContext]) { + this[kHTTPContext].destroy(err, callback) + this[kHTTPContext] = null + } else { + queueMicrotask(callback) + } - this[kResume]() - return promise + this[kResume]() + }) } } diff --git a/lib/web/fetch/index.js b/lib/web/fetch/index.js index e097ab36cb9..982a0301951 100644 --- a/lib/web/fetch/index.js +++ b/lib/web/fetch/index.js @@ -2133,9 +2133,7 @@ async function httpNetworkFetch ( return dispatchWithProtocolPreference(body) function dispatchWithProtocolPreference (body, allowH2) { - const { promise, resolve, reject } = Promise.withResolvers() - - agent.dispatch( + return new Promise((resolve, reject) => agent.dispatch( { path: hasTrailingQuestionMark ? `${path}?` : path, origin: url.origin, @@ -2367,9 +2365,7 @@ async function httpNetworkFetch ( return true } } - ) - - return promise + )) } } }