Skip to content

Commit

Permalink
deps: update undici adding code from nodejs/undici#2701
Browse files Browse the repository at this point in the history
  • Loading branch information
santigimeno committed Nov 12, 2024
1 parent 624dde8 commit 947e4f1
Show file tree
Hide file tree
Showing 3 changed files with 254 additions and 133 deletions.
10 changes: 9 additions & 1 deletion deps/undici/src/lib/core/diagnostics.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ const undiciDebugLog = util.debuglog('undici')
const fetchDebuglog = util.debuglog('fetch')
const websocketDebuglog = util.debuglog('websocket')
let isClientSet = false
let tracingChannel

if (diagnosticsChannel.tracingChannel) {
tracingChannel = diagnosticsChannel.tracingChannel('undici:fetch')
}

const channels = {
// Client
beforeConnect: diagnosticsChannel.channel('undici:client:beforeConnect'),
Expand All @@ -23,7 +29,9 @@ const channels = {
close: diagnosticsChannel.channel('undici:websocket:close'),
socketError: diagnosticsChannel.channel('undici:websocket:socket_error'),
ping: diagnosticsChannel.channel('undici:websocket:ping'),
pong: diagnosticsChannel.channel('undici:websocket:pong')
pong: diagnosticsChannel.channel('undici:websocket:pong'),
// Fetch channels
tracingChannel
}

if (undiciDebugLog.enabled || fetchDebuglog.enabled) {
Expand Down
227 changes: 143 additions & 84 deletions deps/undici/src/lib/web/fetch/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const defaultUserAgent = typeof __UNDICI_IS_NODE__ !== 'undefined' || typeof esb
? 'node'
: 'undici'

const channels = require('../../core/diagnostics.js').channels.tracingChannel
/** @type {import('buffer').resolveObjectURL} */
let resolveObjectURL

Expand Down Expand Up @@ -124,12 +125,68 @@ function handleFetchDone (response) {
finalizeAndReportTiming(response, 'fetch')
}

// This will publish all diagnostic events only when we have subscribers.
function ifSubscribersRunStores (req, input, init, callback) {
const hasSubscribers = subscribersCheck()

if (hasSubscribers) {
const context = { req, input, init, result: null, error: null }

return channels.start.runStores(context, () => {
try {
return callback(createInstrumentedDeferredPromise(context))
} catch (e) {
context.error = e
channels.error.publish(context)
throw e
} finally {
channels.end.publish(context)
}
})
} else {
return callback(createDeferredPromise())
}
}

// subscribersCheck will be called at the beginning of the fetch call
// and will check if we have subscribers
function subscribersCheck () {
return channels && (channels.start.hasSubscribers ||
channels.end.hasSubscribers ||
channels.asyncStart.hasSubscribers ||
channels.asyncEnd.hasSubscribers ||
channels.error.hasSubscribers)
}

function createInstrumentedDeferredPromise (context) {
let res
let rej
const promise = new Promise((resolve, reject) => {
res = function (result) {
context.result = result
channels.asyncStart.runStores(context, () => {
resolve(result)
channels.asyncEnd.publish(context)
})
}
rej = function (error) {
context.error = error
channels.error.publish(context)
channels.asyncStart.runStores(context, () => {
reject(error)
channels.asyncEnd.publish(context)
})
}
})

return { promise, resolve: res, reject: rej }
}

// https://fetch.spec.whatwg.org/#fetch-method
function fetch (input, init = undefined) {
webidl.argumentLengthCheck(arguments, 1, 'globalThis.fetch')

// 1. Let p be a new promise.
let p = createDeferredPromise()

// 2. Let requestObject be the result of invoking the initial value of
// Request as constructor with input and init as arguments. If this throws
Expand All @@ -139,116 +196,117 @@ function fetch (input, init = undefined) {
try {
requestObject = new Request(input, init)
} catch (e) {
p.reject(e)
return p.promise
return Promise.reject(e)
}

// 3. Let request be requestObject’s request.
const request = requestObject[kState]
return ifSubscribersRunStores(requestObject, input, init, p => {
// 3. Let request be requestObject’s request.
const request = requestObject[kState]

// 4. If requestObject’s signal’s aborted flag is set, then:
if (requestObject.signal.aborted) {
// 4. If requestObject’s signal’s aborted flag is set, then:
if (requestObject.signal.aborted) {
// 1. Abort the fetch() call with p, request, null, and
// requestObject’s signal’s abort reason.
abortFetch(p, request, null, requestObject.signal.reason)
abortFetch(p, request, null, requestObject.signal.reason)

// 2. Return p.
return p.promise
}
// 2. Return p.
return p.promise
}

// 5. Let globalObject be request’s client’s global object.
const globalObject = request.client.globalObject
// 5. Let globalObject be request’s client’s global object.
const globalObject = request.client.globalObject

// 6. If globalObject is a ServiceWorkerGlobalScope object, then set
// request’s service-workers mode to "none".
if (globalObject?.constructor?.name === 'ServiceWorkerGlobalScope') {
request.serviceWorkers = 'none'
}
// 6. If globalObject is a ServiceWorkerGlobalScope object, then set
// request’s service-workers mode to "none".
if (globalObject?.constructor?.name === 'ServiceWorkerGlobalScope') {
request.serviceWorkers = 'none'
}

// 7. Let responseObject be null.
let responseObject = null
// 7. Let responseObject be null.
let responseObject = null

// 8. Let relevantRealm be this’s relevant Realm.
// 8. Let relevantRealm be this’s relevant Realm.

// 9. Let locallyAborted be false.
let locallyAborted = false
// 9. Let locallyAborted be false.
let locallyAborted = false

// 10. Let controller be null.
let controller = null
// 10. Let controller be null.
let controller = null

// 11. Add the following abort steps to requestObject’s signal:
addAbortListener(
requestObject.signal,
() => {
// 1. Set locallyAborted to true.
locallyAborted = true
// 11. Add the following abort steps to requestObject’s signal:
addAbortListener(
requestObject.signal,
() => {
// 1. Set locallyAborted to true.
locallyAborted = true

// 2. Assert: controller is non-null.
assert(controller != null)
// 2. Assert: controller is non-null.
assert(controller != null)

// 3. Abort controller with requestObject’s signal’s abort reason.
controller.abort(requestObject.signal.reason)
// 3. Abort controller with requestObject’s signal’s abort reason.
controller.abort(requestObject.signal.reason)

const realResponse = responseObject?.deref()
const realResponse = responseObject?.deref()

// 4. Abort the fetch() call with p, request, responseObject,
// and requestObject’s signal’s abort reason.
abortFetch(p, request, realResponse, requestObject.signal.reason)
}
)
// 4. Abort the fetch() call with p, request, responseObject,
// and requestObject’s signal’s abort reason.
abortFetch(p, request, realResponse, requestObject.signal.reason)
}
)

// 12. Let handleFetchDone given response response be to finalize and
// report timing with response, globalObject, and "fetch".
// see function handleFetchDone
// 12. Let handleFetchDone given response response be to finalize and
// report timing with response, globalObject, and "fetch".
// see function handleFetchDone

// 13. Set controller to the result of calling fetch given request,
// with processResponseEndOfBody set to handleFetchDone, and processResponse
// given response being these substeps:
// 13. Set controller to the result of calling fetch given request,
// with processResponseEndOfBody set to handleFetchDone, and processResponse
// given response being these substeps:

const processResponse = (response) => {
// 1. If locallyAborted is true, terminate these substeps.
if (locallyAborted) {
return
}
const processResponse = (response) => {
// 1. If locallyAborted is true, terminate these substeps.
if (locallyAborted) {
return
}

// 2. If response’s aborted flag is set, then:
if (response.aborted) {
// 1. Let deserializedError be the result of deserialize a serialized
// abort reason given controller’s serialized abort reason and
// relevantRealm.
// 2. If response’s aborted flag is set, then:
if (response.aborted) {
// 1. Let deserializedError be the result of deserialize a serialized
// abort reason given controller’s serialized abort reason and
// relevantRealm.

// 2. Abort the fetch() call with p, request, responseObject, and
// deserializedError.
// 2. Abort the fetch() call with p, request, responseObject, and
// deserializedError.

abortFetch(p, request, responseObject, controller.serializedAbortReason)
return
}
abortFetch(p, request, responseObject, controller.serializedAbortReason)
return
}

// 3. If response is a network error, then reject p with a TypeError
// and terminate these substeps.
if (response.type === 'error') {
p.reject(new TypeError('fetch failed', { cause: response.error }))
return
}
// 3. If response is a network error, then reject p with a TypeError
// and terminate these substeps.
if (response.type === 'error') {
p.reject(new TypeError('fetch failed', { cause: response.error }))
return
}

// 4. Set responseObject to the result of creating a Response object,
// given response, "immutable", and relevantRealm.
responseObject = new WeakRef(fromInnerResponse(response, 'immutable'))
// 4. Set responseObject to the result of creating a Response object,
// given response, "immutable", and relevantRealm.
responseObject = new WeakRef(fromInnerResponse(response, 'immutable'))

// 5. Resolve p with responseObject.
p.resolve(responseObject.deref())
p = null
}
// 5. Resolve p with responseObject.
p.resolve(responseObject.deref())
p = null
}

controller = fetching({
request,
processResponseEndOfBody: handleFetchDone,
processResponse,
dispatcher: requestObject[kDispatcher] // undici
})
controller = fetching({
request,
processResponseEndOfBody: handleFetchDone,
processResponse,
dispatcher: requestObject[kDispatcher] // undici
})

// 14. Return p.
return p.promise
// 14. Return p.
return p.promise
})
}

// https://fetch.spec.whatwg.org/#finalize-and-report-timing
Expand Down Expand Up @@ -444,7 +502,8 @@ function fetching ({
// 9. If request’s origin is "client", then set request’s origin to request’s
// client’s origin.
if (request.origin === 'client') {
request.origin = request.client.origin
// TODO: What if request.client is null?
request.origin = request.client?.origin
}

// 10. If all of the following conditions are true:
Expand Down
Loading

0 comments on commit 947e4f1

Please sign in to comment.