build(deps): bump undici from 7.30.0 to 7.30.1 (#1430)

Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
This commit is contained in:
dependabot[bot]
2026-10-31 10:26:58 +00:00
committed by GitHub
co-authored by Fernandez Ludovic
parent 80a417e615
commit 1eaa2a6e86
3 changed files with 903 additions and 383 deletions
Generated Vendored
+298 -38
View File
@@ -33621,18 +33621,24 @@ const SessionCache = class WeakSessionCache {
if (this._sessionCache.has(sessionKey)) {
this._sessionCache.delete(sessionKey)
} else if (this._sessionCache.size >= this._maxCachedSessions) {
// Make room for the new session: prefer an entry whose session has
// already been collected, otherwise evict the oldest one.
let evicted = false
for (const [key, ref] of this._sessionCache) {
if (ref.deref() === undefined) {
this._sessionCache.delete(key)
return
evicted = true
break
}
}
if (!evicted) {
const oldest = this._sessionCache.keys().next()
if (!oldest.done) {
this._sessionCache.delete(oldest.value)
}
}
}
this._sessionCache.set(sessionKey, new WeakRef(session))
this._sessionRegistry.register(session, sessionKey)
@@ -35760,6 +35766,7 @@ module.exports = {
kDestroy: Symbol('destroy'),
kDispatch: Symbol('dispatch'),
kUrl: Symbol('url'),
kRedirectCacheControl: Symbol('redirect cache control'),
kWriting: Symbol('writing'),
kResuming: Symbol('resuming'),
kQueue: Symbol('queue'),
@@ -37028,7 +37035,7 @@ function defaultFactory (origin, opts) {
}
class Agent extends DispatcherBase {
constructor ({ factory = defaultFactory, maxOrigins = Infinity, connect, ...options } = {}) {
constructor ({ factory = defaultFactory, maxOrigins = Infinity, connect, tls, ...options } = {}) {
if (typeof factory !== 'function') {
throw new InvalidArgumentError('factory must be a function.')
}
@@ -37047,7 +37054,11 @@ class Agent extends DispatcherBase {
connect = { ...connect }
}
this[kOptions] = { ...util.deepClone(options), maxOrigins, connect }
if (tls && typeof tls !== 'function') {
tls = { ...tls }
}
this[kOptions] = { ...util.deepClone(options), maxOrigins, connect, tls }
this[kFactory] = factory
this[kClients] = new Map()
this[kOrigins] = new Set()
@@ -38329,8 +38340,6 @@ function connectH1 (client, socket) {
}
function onHttpSocketError (err) {
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
const parser = this[kParser]
// On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded
@@ -39448,8 +39457,6 @@ function onHttp2SendPing (session) {
}
function onHttp2SessionError (err) {
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
this[kSocket][kError] = err
this[kClient][kOnError](err)
}
@@ -39591,8 +39598,6 @@ function onHttp2SocketClose () {
}
function onHttp2SocketError (err) {
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
this[kError] = err
this[kClient][kOnError](err)
@@ -40338,7 +40343,8 @@ class Client extends DispatcherBase {
initialWindowSize,
connectionWindowSize,
pingInterval,
webSocket
webSocket,
eventSource
} = {}) {
if (keepAlive !== undefined) {
throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead')
@@ -40446,7 +40452,7 @@ class Client extends DispatcherBase {
throw new InvalidArgumentError('pingInterval must be a positive integer, greater or equal to 0')
}
super({ webSocket })
super({ webSocket, eventSource })
if (typeof connect !== 'function') {
connect = buildConnector({
@@ -40899,6 +40905,7 @@ module.exports = Client
"use strict";
const buffer = __nccwpck_require__(4573)
const Dispatcher = __nccwpck_require__(30883)
const UnwrapHandler = __nccwpck_require__(92365)
const {
@@ -40911,6 +40918,7 @@ const { kDestroy, kClose, kClosed, kDestroyed, kDispatch } = __nccwpck_require__
const kOnDestroyed = Symbol('onDestroyed')
const kOnClosed = Symbol('onClosed')
const kWebSocketOptions = Symbol('webSocketOptions')
const kEventSourceOptions = Symbol('eventSourceOptions')
class DispatcherBase extends Dispatcher {
/** @type {boolean} */
@@ -40931,6 +40939,7 @@ class DispatcherBase extends Dispatcher {
constructor (opts) {
super()
this[kWebSocketOptions] = opts?.webSocket ?? {}
this[kEventSourceOptions] = opts?.eventSource ?? {}
}
/**
@@ -40943,6 +40952,15 @@ class DispatcherBase extends Dispatcher {
}
}
/**
* @returns {import('../../types/client').Client.EventSourceOptions}
*/
get eventSourceOptions () {
return {
maxEventSize: this[kEventSourceOptions].maxEventSize ?? buffer.kStringMaxLength
}
}
/** @returns {boolean} */
get destroyed () {
return this[kDestroyed]
@@ -42743,6 +42761,7 @@ module.exports = {
const util = __nccwpck_require__(3440)
const { kRedirectCacheControl } = __nccwpck_require__(36443)
const {
parseCacheControlHeader,
hasInvalidCacheControlDirective,
@@ -42755,6 +42774,19 @@ const { parseHttpDate } = __nccwpck_require__(25453)
function noop () {}
/**
* @param {string | URL} a
* @param {string | URL} b
* @returns {boolean}
*/
function sameOrigin (a, b) {
try {
return new URL(String(a)).origin === new URL(String(b)).origin
} catch {
return String(a) === String(b)
}
}
// Status codes that we can use some heuristics on to cache
const HEURISTICALLY_CACHEABLE_STATUS_CODES = [
200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501
@@ -42893,6 +42925,14 @@ class CacheHandler {
*/
#writeStream
/**
* The URLs visited while following redirects, shared by reference from the
* redirect handler through the request context. Carries the suppressed hops'
* cache-control under {@link kRedirectCacheControl}.
* @type {URL[] | undefined}
*/
#history
/**
* @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} opts
* @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey
@@ -42909,6 +42949,9 @@ class CacheHandler {
onRequestStart (controller, context) {
this.#writeStream?.destroy()
this.#writeStream = undefined
// The redirect handler mutates this shared history as redirects are
// followed, allowing the cache to identify the response's actual origin.
this.#history = context?.history
this.#handler.onRequestStart?.(controller, context)
}
@@ -42948,6 +42991,29 @@ class CacheHandler {
return downstreamOnHeaders()
}
// Never store a response produced by a different origin under the original
// request's cache key.
if (this.#history && this.#history.length > 0) {
const finalUrl = this.#history[this.#history.length - 1]
if (!sameOrigin(finalUrl.origin, this.#cacheKey.origin)) {
return downstreamOnHeaders()
}
}
// Preserve restrictive cache policy from suppressed redirect responses.
const redirectCacheControl = this.#history?.[kRedirectCacheControl]
if (redirectCacheControl) {
for (const hopCacheControl of redirectCacheControl) {
const hopDirectives = hopCacheControl ? parseCacheControlHeader(hopCacheControl) : {}
if (
hopDirectives['no-store'] === true ||
(this.#cacheType === 'shared' && hopDirectives.private === true)
) {
return downstreamOnHeaders()
}
}
}
const cacheControlHeader = resHeaders['cache-control']
const cacheControlDirectives = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {}
@@ -43749,6 +43815,7 @@ const DEFAULT_MAX_BUFFER_SIZE = 5 * 1024 * 1024
* @property {number} bufferedBytes
* @property {object | null} pendingTrailers
* @property {boolean} done
* @property {boolean} [pendingStart] onRequestStart deferred until the primary request's context is known
*/
/**
@@ -43763,6 +43830,20 @@ class DeduplicationHandler {
*/
#primaryHandler
/**
* Whether the primary request has started (onRequestStart received). Until
* then the request context is unknown and cannot be given to waiting handlers.
* @type {boolean}
*/
#requestStarted = false
/**
* The primary request context, replayed to waiting handlers so they observe
* the same redirect history as the primary.
* @type {any}
*/
#context = null
/**
* @type {WaitingHandler[]}
*/
@@ -43845,7 +43926,10 @@ class DeduplicationHandler {
const waitingController = waitingHandler.controller
try {
handler.onRequestStart?.(waitingController, null)
if (this.#requestStarted) {
// The primary request has started, so its context (including the
// redirect history) is known and can be delivered immediately.
handler.onRequestStart?.(waitingController, this.#context)
if (waitingController.aborted) {
waitingHandler.done = true
@@ -43860,6 +43944,13 @@ class DeduplicationHandler {
this.#statusMessage
)
}
} else {
// The primary request has not started yet. Defer onRequestStart until
// its context is known, so the waiting handler observes the same
// redirect history as the primary (a cache handler relies on it to
// reject cross-origin redirect responses).
waitingHandler.pendingStart = true
}
} catch {
// Ignore errors from waiting handlers
waitingHandler.done = true
@@ -43879,6 +43970,24 @@ class DeduplicationHandler {
*/
onRequestStart (controller, context) {
this.#controller = controller
if (!this.#requestStarted) {
this.#requestStarted = true
this.#context = context
// Deliver the now-known context to handlers that joined before the
// primary request started.
for (const waitingHandler of this.#waitingHandlers) {
if (waitingHandler.pendingStart && !waitingHandler.done && !waitingHandler.controller.aborted) {
waitingHandler.pendingStart = false
try {
waitingHandler.handler.onRequestStart?.(waitingHandler.controller, context)
} catch {
// Ignore errors from waiting handlers
waitingHandler.done = true
}
}
}
this.#pruneDoneWaitingHandlers()
}
this.#primaryHandler.onRequestStart?.(controller, context)
}
@@ -44052,7 +44161,8 @@ class DeduplicationHandler {
bufferedChunks: [],
bufferedBytes: 0,
pendingTrailers: null,
done: false
done: false,
pendingStart: false
}
const state = {
@@ -44202,7 +44312,7 @@ module.exports = DeduplicationHandler
const util = __nccwpck_require__(3440)
const { kBodyUsed } = __nccwpck_require__(36443)
const { kBodyUsed, kRedirectCacheControl } = __nccwpck_require__(36443)
const assert = __nccwpck_require__(34589)
const { InvalidArgumentError } = __nccwpck_require__(68707)
const EE = __nccwpck_require__(78474)
@@ -44248,6 +44358,11 @@ class RedirectHandler {
this.maxRedirections = maxRedirections
this.handler = handler
this.history = []
// Retain cache-control from suppressed redirect hops for an outer cache.
Object.defineProperty(this.history, kRedirectCacheControl, {
value: [],
enumerable: false
})
if (util.isStream(this.opts.body)) {
// TODO (fix): Provide some way for the user to cache the file to e.g. /tmp
@@ -44331,6 +44446,8 @@ class RedirectHandler {
return
}
this.history[kRedirectCacheControl].push(headers['cache-control'])
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)))
const path = search ? `${pathname}${search}` : pathname
@@ -46035,10 +46152,15 @@ class DecompressHandler extends DecoratorHandler {
this.#decompressedSize = decompressedSize
}
try {
const result = super.onResponseData(this.#controller, chunk)
if (result === false && !this.#controller.paused) {
this.#controller.pause()
}
} catch (err) {
this.#fail(err)
return
}
}
} while (this.#drainRequested && !this.#terminated && !this.#controller.paused)
} finally {
@@ -46054,9 +46176,14 @@ class DecompressHandler extends DecoratorHandler {
return
}
this.#terminated = true
this.#cleanupDecompressors()
try {
super.onResponseEnd(this.#controller, this.#trailers)
} catch (err) {
this.#fail(err)
return
}
this.#terminated = true
}
#onDecompressionEnd () {
@@ -53701,8 +53828,10 @@ function getCookies (headers) {
const cookie = headers.get('cookie')
// A null prototype keeps a cookie named `__proto__` from hitting the
// Object.prototype setter, which would silently drop it.
/** @type {Record<string, string>} */
const out = {}
const out = { __proto__: null }
if (!cookie) {
return out
@@ -53968,6 +54097,7 @@ function parseSetCookie (header) {
* @param {Object.<string, unknown>} [cookieAttributeList={}]
*/
function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) {
while (true) {
// 1. If the unparsed-attributes string is empty, skip the rest of
// these steps.
if (unparsedAttributes.length === 0) {
@@ -54036,7 +54166,7 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {})
// 6. If the attribute-value is longer than 1024 octets, ignore the
// cookie-av string and return to Step 1 of this algorithm.
if (attributeValue.length > maxAttributeValueSize) {
return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList)
continue
}
// 7. Process the attribute-name and attribute-value according to the
@@ -54066,13 +54196,13 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {})
const charCode = attributeValue.charCodeAt(0)
if ((charCode < 48 || charCode > 57) && attributeValue[0] !== '-') {
return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList)
continue
}
// 2. If the remainder of attribute-value contains a non-DIGIT
// character, ignore the cookie-av.
if (!/^\d+$/.test(attributeValue)) {
return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList)
continue
}
// 3. Let delta-seconds be the attribute-value converted to an integer.
@@ -54181,7 +54311,7 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {})
}
// 8. Return to Step 1 of this algorithm.
return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList)
}
}
module.exports = {
@@ -54513,9 +54643,28 @@ function stringify (cookie) {
out.push(`Path=${cookie.path}`)
}
if (cookie.expires && cookie.expires.toString() !== 'Invalid Date') {
// A numeric 0 is the Unix epoch, not an absent value -- the same reason the
// Max-Age check above tests the type rather than truthiness.
//
// expires is Date | number, so the "Invalid Date" check only guards the Date
// form. A number that is not a valid time value (NaN, +/-Infinity, or outside
// the Date range) would otherwise reach toIMFDate, which splices undefined and
// NaN into the header value instead of failing.
if (cookie.expires != null) {
const expiresMs = cookie.expires instanceof Date
? cookie.expires.getTime()
: cookie.expires
// The largest time value a Date can represent, in milliseconds, i.e.
// 100,000,000 days either side of the epoch (ECMA-262 Date Time Values).
// Anything within it is safe for toIMFDate to format; anything beyond it
// produces an invalid Date and must be ignored instead.
const maxTimeValue = 8640000000000000
if (typeof expiresMs === 'number' && Number.isFinite(expiresMs) && Math.abs(expiresMs) <= maxTimeValue) {
out.push(`Expires=${toIMFDate(cookie.expires)}`)
}
}
if (cookie.sameSite) {
out.push(`SameSite=${cookie.sameSite}`)
@@ -54557,6 +54706,7 @@ module.exports = {
"use strict";
const buffer = __nccwpck_require__(4573)
const { Transform } = __nccwpck_require__(57075)
const { isASCIINumber, isValidLastEventId } = __nccwpck_require__(94811)
@@ -54581,11 +54731,19 @@ const COLON = 0x3A
*/
const SPACE = 0x20
const defaultMaxEventSize = buffer.kStringMaxLength
const DATA = Buffer.from('data')
const EVENT = Buffer.from('event')
const ID = Buffer.from('id')
const RETRY = Buffer.from('retry')
// Each data field creates a string node, and each unconsumed input chunk keeps
// a Buffer wrapper. The absolute ceiling protects the large default byte limit.
const minParserItems = 1024
const maxParserItems = 131072
const bytesPerParserItem = 128
function isASCIINumberBytes (buffer, start) {
if (start >= buffer.length) {
return false
@@ -54624,6 +54782,12 @@ function isFieldName (line, length, field) {
return true
}
function createMaxEventSizeExceededError () {
const error = new Error('EventSource message size exceeded')
error.aborted = false
return error
}
/**
* @typedef {object} EventSourceStreamEvent
* @type {object}
@@ -54672,6 +54836,13 @@ class EventSourceStream extends Transform {
pos = 0
lineChunkIndex = 0
linePos = 0
lineLength = 0
eventSize = 0
eventFieldSizes = { data: 0, event: 0, id: 0, retry: 0 }
dataLineCount = 0
maxEventSize
maxDataLines
maxBufferedChunks
event = {
data: undefined,
@@ -54683,6 +54854,7 @@ class EventSourceStream extends Transform {
/**
* @param {object} options
* @param {boolean} [options.readableObjectMode]
* @param {number} [options.maxEventSize]
* @param {eventSourceSettings} [options.eventSourceSettings]
* @param {(chunk: any, encoding?: BufferEncoding | undefined) => boolean} [options.push]
*/
@@ -54694,6 +54866,12 @@ class EventSourceStream extends Transform {
super(options)
this.state = options.eventSourceSettings || {}
this.maxEventSize = options.maxEventSize ?? defaultMaxEventSize
const parserItemLimit = this.maxEventSize > 0
? Math.min(maxParserItems, Math.max(minParserItems, Math.floor(this.maxEventSize / bytesPerParserItem)))
: 0
this.maxDataLines = parserItemLimit
this.maxBufferedChunks = parserItemLimit
if (options.push) {
this.push = options.push
}
@@ -54711,6 +54889,14 @@ class EventSourceStream extends Transform {
return
}
// A leading line ending can immediately release the currently buffered
// line, even when it uses the final allowed chunk slot.
if (this.maxEventSize > 0 &&
this.chunks.length >= this.maxBufferedChunks &&
chunk[0] !== LF && chunk[0] !== CR) {
callback(createMaxEventSizeExceededError())
return
}
this.chunks.push(chunk)
// Strip leading byte-order-mark if we opened the stream and started
@@ -54789,7 +54975,12 @@ class EventSourceStream extends Transform {
// In any case, we can process the line as we reached an
// end-of-line character
try {
this.parseLine(this.readLine(), this.event)
} catch (error) {
callback(error)
return
}
this.consumeCurrentByte()
// A line was processed and this could be the end of the event. We need
// to check if the next line is empty to determine if the event is
@@ -54798,12 +54989,25 @@ class EventSourceStream extends Transform {
continue
}
// readLine() is only called after CR or LF. Reject an unfinished line
// before it can retain an unbounded number of decoded chunks. The seven
// extra bytes allow the longest field prefix ("event: " or "retry: ").
if (this.maxEventSize > 0 && ++this.lineLength > this.maxEventSize + 7) {
callback(createMaxEventSizeExceededError())
return
}
this.advanceCursor()
}
callback()
}
_destroy (error, callback) {
this.chunks.length = 0
this.clearEvent()
super._destroy(error, callback)
}
/**
* @param {Buffer} line
* @param {EventSourceStreamEvent} event
@@ -54840,6 +55044,13 @@ class EventSourceStream extends Transform {
}
if (isFieldName(line, fieldLength, DATA)) {
if (this.maxEventSize > 0 && this.dataLineCount >= this.maxDataLines) {
throw createMaxEventSizeExceededError()
}
const valueBytes = line.length - valueStart
const dataSize = this.eventFieldSizes.data + (event.data === undefined ? 0 : 1) + valueBytes
this.setEventFieldSize('data', dataSize)
const value = line.toString('utf8', valueStart)
if (event.data === undefined) {
@@ -54847,11 +55058,13 @@ class EventSourceStream extends Transform {
} else {
event.data += `\n${value}`
}
this.dataLineCount++
return
}
if (isFieldName(line, fieldLength, RETRY)) {
if (isASCIINumberBytes(line, valueStart)) {
this.setEventFieldSize('retry', line.length - valueStart)
event.retry = line.toString('utf8', valueStart)
}
return
@@ -54859,18 +55072,27 @@ class EventSourceStream extends Transform {
if (isFieldName(line, fieldLength, ID)) {
if (isValidLastEventIdBytes(line, valueStart)) {
this.setEventFieldSize('id', line.length - valueStart)
event.id = line.toString('utf8', valueStart)
}
return
}
if (isFieldName(line, fieldLength, EVENT)) {
const value = line.toString('utf8', valueStart)
if (valueStart < line.length) {
this.setEventFieldSize('event', line.length - valueStart)
event.event = line.toString('utf8', valueStart)
}
}
}
if (value.length > 0) {
event.event = value
}
setEventFieldSize (field, size) {
const eventSize = this.eventSize - this.eventFieldSizes[field] + size
if (this.maxEventSize > 0 && eventSize > this.maxEventSize) {
throw createMaxEventSizeExceededError()
}
this.eventSize = eventSize
this.eventFieldSizes[field] = size
}
/**
@@ -54903,6 +55125,12 @@ class EventSourceStream extends Transform {
this.event.event = undefined
this.event.id = undefined
this.event.retry = undefined
this.eventSize = 0
this.dataLineCount = 0
this.eventFieldSizes.data = 0
this.eventFieldSizes.event = 0
this.eventFieldSizes.id = 0
this.eventFieldSizes.retry = 0
}
hasPendingEvent () {
@@ -54938,14 +55166,16 @@ class EventSourceStream extends Transform {
syncLineStartToCursor () {
this.lineChunkIndex = this.chunkIndex
this.linePos = this.pos
this.lineLength = 0
this.dropConsumedChunks()
}
dropConsumedChunks () {
while (this.lineChunkIndex > 0) {
this.chunks.shift()
this.lineChunkIndex--
this.chunkIndex--
if (this.lineChunkIndex > 0) {
const consumed = this.lineChunkIndex
this.chunks.splice(0, consumed)
this.lineChunkIndex = 0
this.chunkIndex -= consumed
}
if (this.chunkIndex === this.chunks.length) {
@@ -55070,6 +55300,7 @@ const { createFastMessageEvent } = __nccwpck_require__(15188)
const { isNetworkError } = __nccwpck_require__(99051)
const { kEnumerableProperty } = __nccwpck_require__(3440)
const { environmentSettingsObject } = __nccwpck_require__(73168)
const { getGlobalDispatcher } = __nccwpck_require__(32581)
let experimentalWarned = false
@@ -55352,6 +55583,7 @@ class EventSource extends EventTarget {
const eventSourceStream = new EventSourceStream({
eventSourceSettings: this.#state,
maxEventSize: this.#dispatcher.eventSourceOptions?.maxEventSize,
push: (event) => {
this.dispatchEvent(createFastMessageEvent(
event.type,
@@ -55536,7 +55768,8 @@ webidl.converters.EventSourceInitDict = webidl.dictionaryConverter([
},
{
key: 'dispatcher', // undici only
converter: webidl.converters.any
converter: webidl.converters.any,
defaultValue: () => getGlobalDispatcher()
},
{
key: 'node', // undici only
@@ -60717,8 +60950,6 @@ async function httpNetworkFetch (
}
const location = headersList.get('location', true)
this.body = new Readable({ read: resume })
const willFollow = location && request.redirect === 'follow' &&
redirectStatusSet.has(status)
@@ -60736,7 +60967,7 @@ async function httpNetworkFetch (
// CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206).
const maxContentEncodings = 5
if (codings.length > maxContentEncodings) {
reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`))
this.abort(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`))
return true
}
@@ -60774,6 +61005,8 @@ async function httpNetworkFetch (
}
}
this.body = new Readable({ read: resume })
const onError = this.onError.bind(this)
resolve({
@@ -64277,6 +64510,19 @@ function collectASequenceOfCodePointsFast (char, input, position) {
}
const ASCII_WHITESPACE_REPLACE_REGEX = /[\u0009\u000A\u000C\u000D\u0020]/g // eslint-disable-line no-control-regex
const nonASCIIRegex = /[^\x00-\x7F]/ // eslint-disable-line no-control-regex
/**
* @param {string} str
* @returns {string}
*
* @see https://infra.spec.whatwg.org/#ascii-lowercase
*/
function asciiLowercase (str) {
return nonASCIIRegex.test(str)
? str.replace(/[A-Z]+/g, (upper) => upper.toLowerCase())
: str.toLowerCase()
}
/**
* @param {string} data
@@ -64441,6 +64687,7 @@ function serializeJavascriptValueToJSONString (value) {
}
module.exports = {
asciiLowercase,
collectASequenceOfCodePoints,
collectASequenceOfCodePointsFast,
forgivingBase64,
@@ -64464,6 +64711,7 @@ module.exports = {
const assert = __nccwpck_require__(34589)
const { runtimeFeatures } = __nccwpck_require__(313)
const { asciiLowercase } = __nccwpck_require__(8116)
/**
* @typedef {object} Metadata
@@ -64528,14 +64776,12 @@ const getSRIHashAlgorithmIndex = /** @type {GetSRIHashAlgorithmIndex} */ (Map.pr
/**
* @typedef IsValidSRIHashAlgorithm
* @see https://w3c.github.io/webappsec-subresource-integrity/#valid-sri-hash-algorithm-token
* @type {(algorithm: string) => algorithm is SRIHashAlgorithm}
* @param {*} algorithm
* @returns {algorithm is SRIHashAlgorithm}
*/
const isValidSRIHashAlgorithm = /** @type {IsValidSRIHashAlgorithm} */ (
Map.prototype.has.bind(validSRIHashAlgorithmTokenSet)
)
const isValidSRIHashAlgorithm = (algorithm) => validSRIHashAlgorithmTokenSet.has(asciiLowercase(algorithm))
/**
* @param {Uint8Array} bytes
@@ -64691,7 +64937,8 @@ function parseMetadata (metadata) {
// 8. Let metadata be the ordered map
// «["alg" → algorithm, "val" → base64-value]».
const metadata = {
alg: algorithm,
// Possible spec bug?
alg: asciiLowercase(algorithm),
val: base64Value
}
@@ -67109,6 +67356,19 @@ class ByteParser extends Writable {
if (isControlFrame(this.#info.opcode)) {
this.#loop = this.parseControlFrame(body)
this.#state = parserStates.INFO
// If the automatic PONG/CLOSE reply filled the socket's write buffer,
// stop parsing and resume on drain so a PING flood cannot grow the
// outbound queue without bound.
if (this.#loop && this.#handler.socket.writableNeedDrain) {
this.#loop = false
this.#handler.socket.once('drain', () => {
if (this.destroyed) return
this.#loop = true
this.run(callback)
})
return
}
} else {
if (!this.#info.compressed) {
if (!this.writeFragments(body)) {
Generated Vendored
+298 -38
View File
@@ -33621,18 +33621,24 @@ const SessionCache = class WeakSessionCache {
if (this._sessionCache.has(sessionKey)) {
this._sessionCache.delete(sessionKey)
} else if (this._sessionCache.size >= this._maxCachedSessions) {
// Make room for the new session: prefer an entry whose session has
// already been collected, otherwise evict the oldest one.
let evicted = false
for (const [key, ref] of this._sessionCache) {
if (ref.deref() === undefined) {
this._sessionCache.delete(key)
return
evicted = true
break
}
}
if (!evicted) {
const oldest = this._sessionCache.keys().next()
if (!oldest.done) {
this._sessionCache.delete(oldest.value)
}
}
}
this._sessionCache.set(sessionKey, new WeakRef(session))
this._sessionRegistry.register(session, sessionKey)
@@ -35760,6 +35766,7 @@ module.exports = {
kDestroy: Symbol('destroy'),
kDispatch: Symbol('dispatch'),
kUrl: Symbol('url'),
kRedirectCacheControl: Symbol('redirect cache control'),
kWriting: Symbol('writing'),
kResuming: Symbol('resuming'),
kQueue: Symbol('queue'),
@@ -37028,7 +37035,7 @@ function defaultFactory (origin, opts) {
}
class Agent extends DispatcherBase {
constructor ({ factory = defaultFactory, maxOrigins = Infinity, connect, ...options } = {}) {
constructor ({ factory = defaultFactory, maxOrigins = Infinity, connect, tls, ...options } = {}) {
if (typeof factory !== 'function') {
throw new InvalidArgumentError('factory must be a function.')
}
@@ -37047,7 +37054,11 @@ class Agent extends DispatcherBase {
connect = { ...connect }
}
this[kOptions] = { ...util.deepClone(options), maxOrigins, connect }
if (tls && typeof tls !== 'function') {
tls = { ...tls }
}
this[kOptions] = { ...util.deepClone(options), maxOrigins, connect, tls }
this[kFactory] = factory
this[kClients] = new Map()
this[kOrigins] = new Set()
@@ -38329,8 +38340,6 @@ function connectH1 (client, socket) {
}
function onHttpSocketError (err) {
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
const parser = this[kParser]
// On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded
@@ -39448,8 +39457,6 @@ function onHttp2SendPing (session) {
}
function onHttp2SessionError (err) {
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
this[kSocket][kError] = err
this[kClient][kOnError](err)
}
@@ -39591,8 +39598,6 @@ function onHttp2SocketClose () {
}
function onHttp2SocketError (err) {
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
this[kError] = err
this[kClient][kOnError](err)
@@ -40338,7 +40343,8 @@ class Client extends DispatcherBase {
initialWindowSize,
connectionWindowSize,
pingInterval,
webSocket
webSocket,
eventSource
} = {}) {
if (keepAlive !== undefined) {
throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead')
@@ -40446,7 +40452,7 @@ class Client extends DispatcherBase {
throw new InvalidArgumentError('pingInterval must be a positive integer, greater or equal to 0')
}
super({ webSocket })
super({ webSocket, eventSource })
if (typeof connect !== 'function') {
connect = buildConnector({
@@ -40899,6 +40905,7 @@ module.exports = Client
"use strict";
const buffer = __nccwpck_require__(4573)
const Dispatcher = __nccwpck_require__(30883)
const UnwrapHandler = __nccwpck_require__(92365)
const {
@@ -40911,6 +40918,7 @@ const { kDestroy, kClose, kClosed, kDestroyed, kDispatch } = __nccwpck_require__
const kOnDestroyed = Symbol('onDestroyed')
const kOnClosed = Symbol('onClosed')
const kWebSocketOptions = Symbol('webSocketOptions')
const kEventSourceOptions = Symbol('eventSourceOptions')
class DispatcherBase extends Dispatcher {
/** @type {boolean} */
@@ -40931,6 +40939,7 @@ class DispatcherBase extends Dispatcher {
constructor (opts) {
super()
this[kWebSocketOptions] = opts?.webSocket ?? {}
this[kEventSourceOptions] = opts?.eventSource ?? {}
}
/**
@@ -40943,6 +40952,15 @@ class DispatcherBase extends Dispatcher {
}
}
/**
* @returns {import('../../types/client').Client.EventSourceOptions}
*/
get eventSourceOptions () {
return {
maxEventSize: this[kEventSourceOptions].maxEventSize ?? buffer.kStringMaxLength
}
}
/** @returns {boolean} */
get destroyed () {
return this[kDestroyed]
@@ -42743,6 +42761,7 @@ module.exports = {
const util = __nccwpck_require__(3440)
const { kRedirectCacheControl } = __nccwpck_require__(36443)
const {
parseCacheControlHeader,
hasInvalidCacheControlDirective,
@@ -42755,6 +42774,19 @@ const { parseHttpDate } = __nccwpck_require__(25453)
function noop () {}
/**
* @param {string | URL} a
* @param {string | URL} b
* @returns {boolean}
*/
function sameOrigin (a, b) {
try {
return new URL(String(a)).origin === new URL(String(b)).origin
} catch {
return String(a) === String(b)
}
}
// Status codes that we can use some heuristics on to cache
const HEURISTICALLY_CACHEABLE_STATUS_CODES = [
200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501
@@ -42893,6 +42925,14 @@ class CacheHandler {
*/
#writeStream
/**
* The URLs visited while following redirects, shared by reference from the
* redirect handler through the request context. Carries the suppressed hops'
* cache-control under {@link kRedirectCacheControl}.
* @type {URL[] | undefined}
*/
#history
/**
* @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} opts
* @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey
@@ -42909,6 +42949,9 @@ class CacheHandler {
onRequestStart (controller, context) {
this.#writeStream?.destroy()
this.#writeStream = undefined
// The redirect handler mutates this shared history as redirects are
// followed, allowing the cache to identify the response's actual origin.
this.#history = context?.history
this.#handler.onRequestStart?.(controller, context)
}
@@ -42948,6 +42991,29 @@ class CacheHandler {
return downstreamOnHeaders()
}
// Never store a response produced by a different origin under the original
// request's cache key.
if (this.#history && this.#history.length > 0) {
const finalUrl = this.#history[this.#history.length - 1]
if (!sameOrigin(finalUrl.origin, this.#cacheKey.origin)) {
return downstreamOnHeaders()
}
}
// Preserve restrictive cache policy from suppressed redirect responses.
const redirectCacheControl = this.#history?.[kRedirectCacheControl]
if (redirectCacheControl) {
for (const hopCacheControl of redirectCacheControl) {
const hopDirectives = hopCacheControl ? parseCacheControlHeader(hopCacheControl) : {}
if (
hopDirectives['no-store'] === true ||
(this.#cacheType === 'shared' && hopDirectives.private === true)
) {
return downstreamOnHeaders()
}
}
}
const cacheControlHeader = resHeaders['cache-control']
const cacheControlDirectives = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {}
@@ -43749,6 +43815,7 @@ const DEFAULT_MAX_BUFFER_SIZE = 5 * 1024 * 1024
* @property {number} bufferedBytes
* @property {object | null} pendingTrailers
* @property {boolean} done
* @property {boolean} [pendingStart] onRequestStart deferred until the primary request's context is known
*/
/**
@@ -43763,6 +43830,20 @@ class DeduplicationHandler {
*/
#primaryHandler
/**
* Whether the primary request has started (onRequestStart received). Until
* then the request context is unknown and cannot be given to waiting handlers.
* @type {boolean}
*/
#requestStarted = false
/**
* The primary request context, replayed to waiting handlers so they observe
* the same redirect history as the primary.
* @type {any}
*/
#context = null
/**
* @type {WaitingHandler[]}
*/
@@ -43845,7 +43926,10 @@ class DeduplicationHandler {
const waitingController = waitingHandler.controller
try {
handler.onRequestStart?.(waitingController, null)
if (this.#requestStarted) {
// The primary request has started, so its context (including the
// redirect history) is known and can be delivered immediately.
handler.onRequestStart?.(waitingController, this.#context)
if (waitingController.aborted) {
waitingHandler.done = true
@@ -43860,6 +43944,13 @@ class DeduplicationHandler {
this.#statusMessage
)
}
} else {
// The primary request has not started yet. Defer onRequestStart until
// its context is known, so the waiting handler observes the same
// redirect history as the primary (a cache handler relies on it to
// reject cross-origin redirect responses).
waitingHandler.pendingStart = true
}
} catch {
// Ignore errors from waiting handlers
waitingHandler.done = true
@@ -43879,6 +43970,24 @@ class DeduplicationHandler {
*/
onRequestStart (controller, context) {
this.#controller = controller
if (!this.#requestStarted) {
this.#requestStarted = true
this.#context = context
// Deliver the now-known context to handlers that joined before the
// primary request started.
for (const waitingHandler of this.#waitingHandlers) {
if (waitingHandler.pendingStart && !waitingHandler.done && !waitingHandler.controller.aborted) {
waitingHandler.pendingStart = false
try {
waitingHandler.handler.onRequestStart?.(waitingHandler.controller, context)
} catch {
// Ignore errors from waiting handlers
waitingHandler.done = true
}
}
}
this.#pruneDoneWaitingHandlers()
}
this.#primaryHandler.onRequestStart?.(controller, context)
}
@@ -44052,7 +44161,8 @@ class DeduplicationHandler {
bufferedChunks: [],
bufferedBytes: 0,
pendingTrailers: null,
done: false
done: false,
pendingStart: false
}
const state = {
@@ -44202,7 +44312,7 @@ module.exports = DeduplicationHandler
const util = __nccwpck_require__(3440)
const { kBodyUsed } = __nccwpck_require__(36443)
const { kBodyUsed, kRedirectCacheControl } = __nccwpck_require__(36443)
const assert = __nccwpck_require__(34589)
const { InvalidArgumentError } = __nccwpck_require__(68707)
const EE = __nccwpck_require__(78474)
@@ -44248,6 +44358,11 @@ class RedirectHandler {
this.maxRedirections = maxRedirections
this.handler = handler
this.history = []
// Retain cache-control from suppressed redirect hops for an outer cache.
Object.defineProperty(this.history, kRedirectCacheControl, {
value: [],
enumerable: false
})
if (util.isStream(this.opts.body)) {
// TODO (fix): Provide some way for the user to cache the file to e.g. /tmp
@@ -44331,6 +44446,8 @@ class RedirectHandler {
return
}
this.history[kRedirectCacheControl].push(headers['cache-control'])
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)))
const path = search ? `${pathname}${search}` : pathname
@@ -46035,10 +46152,15 @@ class DecompressHandler extends DecoratorHandler {
this.#decompressedSize = decompressedSize
}
try {
const result = super.onResponseData(this.#controller, chunk)
if (result === false && !this.#controller.paused) {
this.#controller.pause()
}
} catch (err) {
this.#fail(err)
return
}
}
} while (this.#drainRequested && !this.#terminated && !this.#controller.paused)
} finally {
@@ -46054,9 +46176,14 @@ class DecompressHandler extends DecoratorHandler {
return
}
this.#terminated = true
this.#cleanupDecompressors()
try {
super.onResponseEnd(this.#controller, this.#trailers)
} catch (err) {
this.#fail(err)
return
}
this.#terminated = true
}
#onDecompressionEnd () {
@@ -53701,8 +53828,10 @@ function getCookies (headers) {
const cookie = headers.get('cookie')
// A null prototype keeps a cookie named `__proto__` from hitting the
// Object.prototype setter, which would silently drop it.
/** @type {Record<string, string>} */
const out = {}
const out = { __proto__: null }
if (!cookie) {
return out
@@ -53968,6 +54097,7 @@ function parseSetCookie (header) {
* @param {Object.<string, unknown>} [cookieAttributeList={}]
*/
function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) {
while (true) {
// 1. If the unparsed-attributes string is empty, skip the rest of
// these steps.
if (unparsedAttributes.length === 0) {
@@ -54036,7 +54166,7 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {})
// 6. If the attribute-value is longer than 1024 octets, ignore the
// cookie-av string and return to Step 1 of this algorithm.
if (attributeValue.length > maxAttributeValueSize) {
return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList)
continue
}
// 7. Process the attribute-name and attribute-value according to the
@@ -54066,13 +54196,13 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {})
const charCode = attributeValue.charCodeAt(0)
if ((charCode < 48 || charCode > 57) && attributeValue[0] !== '-') {
return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList)
continue
}
// 2. If the remainder of attribute-value contains a non-DIGIT
// character, ignore the cookie-av.
if (!/^\d+$/.test(attributeValue)) {
return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList)
continue
}
// 3. Let delta-seconds be the attribute-value converted to an integer.
@@ -54181,7 +54311,7 @@ function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {})
}
// 8. Return to Step 1 of this algorithm.
return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList)
}
}
module.exports = {
@@ -54513,9 +54643,28 @@ function stringify (cookie) {
out.push(`Path=${cookie.path}`)
}
if (cookie.expires && cookie.expires.toString() !== 'Invalid Date') {
// A numeric 0 is the Unix epoch, not an absent value -- the same reason the
// Max-Age check above tests the type rather than truthiness.
//
// expires is Date | number, so the "Invalid Date" check only guards the Date
// form. A number that is not a valid time value (NaN, +/-Infinity, or outside
// the Date range) would otherwise reach toIMFDate, which splices undefined and
// NaN into the header value instead of failing.
if (cookie.expires != null) {
const expiresMs = cookie.expires instanceof Date
? cookie.expires.getTime()
: cookie.expires
// The largest time value a Date can represent, in milliseconds, i.e.
// 100,000,000 days either side of the epoch (ECMA-262 Date Time Values).
// Anything within it is safe for toIMFDate to format; anything beyond it
// produces an invalid Date and must be ignored instead.
const maxTimeValue = 8640000000000000
if (typeof expiresMs === 'number' && Number.isFinite(expiresMs) && Math.abs(expiresMs) <= maxTimeValue) {
out.push(`Expires=${toIMFDate(cookie.expires)}`)
}
}
if (cookie.sameSite) {
out.push(`SameSite=${cookie.sameSite}`)
@@ -54557,6 +54706,7 @@ module.exports = {
"use strict";
const buffer = __nccwpck_require__(4573)
const { Transform } = __nccwpck_require__(57075)
const { isASCIINumber, isValidLastEventId } = __nccwpck_require__(94811)
@@ -54581,11 +54731,19 @@ const COLON = 0x3A
*/
const SPACE = 0x20
const defaultMaxEventSize = buffer.kStringMaxLength
const DATA = Buffer.from('data')
const EVENT = Buffer.from('event')
const ID = Buffer.from('id')
const RETRY = Buffer.from('retry')
// Each data field creates a string node, and each unconsumed input chunk keeps
// a Buffer wrapper. The absolute ceiling protects the large default byte limit.
const minParserItems = 1024
const maxParserItems = 131072
const bytesPerParserItem = 128
function isASCIINumberBytes (buffer, start) {
if (start >= buffer.length) {
return false
@@ -54624,6 +54782,12 @@ function isFieldName (line, length, field) {
return true
}
function createMaxEventSizeExceededError () {
const error = new Error('EventSource message size exceeded')
error.aborted = false
return error
}
/**
* @typedef {object} EventSourceStreamEvent
* @type {object}
@@ -54672,6 +54836,13 @@ class EventSourceStream extends Transform {
pos = 0
lineChunkIndex = 0
linePos = 0
lineLength = 0
eventSize = 0
eventFieldSizes = { data: 0, event: 0, id: 0, retry: 0 }
dataLineCount = 0
maxEventSize
maxDataLines
maxBufferedChunks
event = {
data: undefined,
@@ -54683,6 +54854,7 @@ class EventSourceStream extends Transform {
/**
* @param {object} options
* @param {boolean} [options.readableObjectMode]
* @param {number} [options.maxEventSize]
* @param {eventSourceSettings} [options.eventSourceSettings]
* @param {(chunk: any, encoding?: BufferEncoding | undefined) => boolean} [options.push]
*/
@@ -54694,6 +54866,12 @@ class EventSourceStream extends Transform {
super(options)
this.state = options.eventSourceSettings || {}
this.maxEventSize = options.maxEventSize ?? defaultMaxEventSize
const parserItemLimit = this.maxEventSize > 0
? Math.min(maxParserItems, Math.max(minParserItems, Math.floor(this.maxEventSize / bytesPerParserItem)))
: 0
this.maxDataLines = parserItemLimit
this.maxBufferedChunks = parserItemLimit
if (options.push) {
this.push = options.push
}
@@ -54711,6 +54889,14 @@ class EventSourceStream extends Transform {
return
}
// A leading line ending can immediately release the currently buffered
// line, even when it uses the final allowed chunk slot.
if (this.maxEventSize > 0 &&
this.chunks.length >= this.maxBufferedChunks &&
chunk[0] !== LF && chunk[0] !== CR) {
callback(createMaxEventSizeExceededError())
return
}
this.chunks.push(chunk)
// Strip leading byte-order-mark if we opened the stream and started
@@ -54789,7 +54975,12 @@ class EventSourceStream extends Transform {
// In any case, we can process the line as we reached an
// end-of-line character
try {
this.parseLine(this.readLine(), this.event)
} catch (error) {
callback(error)
return
}
this.consumeCurrentByte()
// A line was processed and this could be the end of the event. We need
// to check if the next line is empty to determine if the event is
@@ -54798,12 +54989,25 @@ class EventSourceStream extends Transform {
continue
}
// readLine() is only called after CR or LF. Reject an unfinished line
// before it can retain an unbounded number of decoded chunks. The seven
// extra bytes allow the longest field prefix ("event: " or "retry: ").
if (this.maxEventSize > 0 && ++this.lineLength > this.maxEventSize + 7) {
callback(createMaxEventSizeExceededError())
return
}
this.advanceCursor()
}
callback()
}
_destroy (error, callback) {
this.chunks.length = 0
this.clearEvent()
super._destroy(error, callback)
}
/**
* @param {Buffer} line
* @param {EventSourceStreamEvent} event
@@ -54840,6 +55044,13 @@ class EventSourceStream extends Transform {
}
if (isFieldName(line, fieldLength, DATA)) {
if (this.maxEventSize > 0 && this.dataLineCount >= this.maxDataLines) {
throw createMaxEventSizeExceededError()
}
const valueBytes = line.length - valueStart
const dataSize = this.eventFieldSizes.data + (event.data === undefined ? 0 : 1) + valueBytes
this.setEventFieldSize('data', dataSize)
const value = line.toString('utf8', valueStart)
if (event.data === undefined) {
@@ -54847,11 +55058,13 @@ class EventSourceStream extends Transform {
} else {
event.data += `\n${value}`
}
this.dataLineCount++
return
}
if (isFieldName(line, fieldLength, RETRY)) {
if (isASCIINumberBytes(line, valueStart)) {
this.setEventFieldSize('retry', line.length - valueStart)
event.retry = line.toString('utf8', valueStart)
}
return
@@ -54859,18 +55072,27 @@ class EventSourceStream extends Transform {
if (isFieldName(line, fieldLength, ID)) {
if (isValidLastEventIdBytes(line, valueStart)) {
this.setEventFieldSize('id', line.length - valueStart)
event.id = line.toString('utf8', valueStart)
}
return
}
if (isFieldName(line, fieldLength, EVENT)) {
const value = line.toString('utf8', valueStart)
if (valueStart < line.length) {
this.setEventFieldSize('event', line.length - valueStart)
event.event = line.toString('utf8', valueStart)
}
}
}
if (value.length > 0) {
event.event = value
}
setEventFieldSize (field, size) {
const eventSize = this.eventSize - this.eventFieldSizes[field] + size
if (this.maxEventSize > 0 && eventSize > this.maxEventSize) {
throw createMaxEventSizeExceededError()
}
this.eventSize = eventSize
this.eventFieldSizes[field] = size
}
/**
@@ -54903,6 +55125,12 @@ class EventSourceStream extends Transform {
this.event.event = undefined
this.event.id = undefined
this.event.retry = undefined
this.eventSize = 0
this.dataLineCount = 0
this.eventFieldSizes.data = 0
this.eventFieldSizes.event = 0
this.eventFieldSizes.id = 0
this.eventFieldSizes.retry = 0
}
hasPendingEvent () {
@@ -54938,14 +55166,16 @@ class EventSourceStream extends Transform {
syncLineStartToCursor () {
this.lineChunkIndex = this.chunkIndex
this.linePos = this.pos
this.lineLength = 0
this.dropConsumedChunks()
}
dropConsumedChunks () {
while (this.lineChunkIndex > 0) {
this.chunks.shift()
this.lineChunkIndex--
this.chunkIndex--
if (this.lineChunkIndex > 0) {
const consumed = this.lineChunkIndex
this.chunks.splice(0, consumed)
this.lineChunkIndex = 0
this.chunkIndex -= consumed
}
if (this.chunkIndex === this.chunks.length) {
@@ -55070,6 +55300,7 @@ const { createFastMessageEvent } = __nccwpck_require__(15188)
const { isNetworkError } = __nccwpck_require__(99051)
const { kEnumerableProperty } = __nccwpck_require__(3440)
const { environmentSettingsObject } = __nccwpck_require__(73168)
const { getGlobalDispatcher } = __nccwpck_require__(32581)
let experimentalWarned = false
@@ -55352,6 +55583,7 @@ class EventSource extends EventTarget {
const eventSourceStream = new EventSourceStream({
eventSourceSettings: this.#state,
maxEventSize: this.#dispatcher.eventSourceOptions?.maxEventSize,
push: (event) => {
this.dispatchEvent(createFastMessageEvent(
event.type,
@@ -55536,7 +55768,8 @@ webidl.converters.EventSourceInitDict = webidl.dictionaryConverter([
},
{
key: 'dispatcher', // undici only
converter: webidl.converters.any
converter: webidl.converters.any,
defaultValue: () => getGlobalDispatcher()
},
{
key: 'node', // undici only
@@ -60717,8 +60950,6 @@ async function httpNetworkFetch (
}
const location = headersList.get('location', true)
this.body = new Readable({ read: resume })
const willFollow = location && request.redirect === 'follow' &&
redirectStatusSet.has(status)
@@ -60736,7 +60967,7 @@ async function httpNetworkFetch (
// CVE fix similar to urllib3 (GHSA-gm62-xv2j-4w53) and curl (CVE-2022-32206).
const maxContentEncodings = 5
if (codings.length > maxContentEncodings) {
reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`))
this.abort(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`))
return true
}
@@ -60774,6 +61005,8 @@ async function httpNetworkFetch (
}
}
this.body = new Readable({ read: resume })
const onError = this.onError.bind(this)
resolve({
@@ -64277,6 +64510,19 @@ function collectASequenceOfCodePointsFast (char, input, position) {
}
const ASCII_WHITESPACE_REPLACE_REGEX = /[\u0009\u000A\u000C\u000D\u0020]/g // eslint-disable-line no-control-regex
const nonASCIIRegex = /[^\x00-\x7F]/ // eslint-disable-line no-control-regex
/**
* @param {string} str
* @returns {string}
*
* @see https://infra.spec.whatwg.org/#ascii-lowercase
*/
function asciiLowercase (str) {
return nonASCIIRegex.test(str)
? str.replace(/[A-Z]+/g, (upper) => upper.toLowerCase())
: str.toLowerCase()
}
/**
* @param {string} data
@@ -64441,6 +64687,7 @@ function serializeJavascriptValueToJSONString (value) {
}
module.exports = {
asciiLowercase,
collectASequenceOfCodePoints,
collectASequenceOfCodePointsFast,
forgivingBase64,
@@ -64464,6 +64711,7 @@ module.exports = {
const assert = __nccwpck_require__(34589)
const { runtimeFeatures } = __nccwpck_require__(313)
const { asciiLowercase } = __nccwpck_require__(8116)
/**
* @typedef {object} Metadata
@@ -64528,14 +64776,12 @@ const getSRIHashAlgorithmIndex = /** @type {GetSRIHashAlgorithmIndex} */ (Map.pr
/**
* @typedef IsValidSRIHashAlgorithm
* @see https://w3c.github.io/webappsec-subresource-integrity/#valid-sri-hash-algorithm-token
* @type {(algorithm: string) => algorithm is SRIHashAlgorithm}
* @param {*} algorithm
* @returns {algorithm is SRIHashAlgorithm}
*/
const isValidSRIHashAlgorithm = /** @type {IsValidSRIHashAlgorithm} */ (
Map.prototype.has.bind(validSRIHashAlgorithmTokenSet)
)
const isValidSRIHashAlgorithm = (algorithm) => validSRIHashAlgorithmTokenSet.has(asciiLowercase(algorithm))
/**
* @param {Uint8Array} bytes
@@ -64691,7 +64937,8 @@ function parseMetadata (metadata) {
// 8. Let metadata be the ordered map
// «["alg" → algorithm, "val" → base64-value]».
const metadata = {
alg: algorithm,
// Possible spec bug?
alg: asciiLowercase(algorithm),
val: base64Value
}
@@ -67109,6 +67356,19 @@ class ByteParser extends Writable {
if (isControlFrame(this.#info.opcode)) {
this.#loop = this.parseControlFrame(body)
this.#state = parserStates.INFO
// If the automatic PONG/CLOSE reply filled the socket's write buffer,
// stop parsing and resume on drain so a PING flood cannot grow the
// outbound queue without bound.
if (this.#loop && this.#handler.socket.writableNeedDrain) {
this.#loop = false
this.#handler.socket.once('drain', () => {
if (this.destroyed) return
this.#loop = true
this.run(callback)
})
return
}
} else {
if (!this.#info.compressed) {
if (!this.writeFragments(body)) {
+3 -3
View File
@@ -4233,9 +4233,9 @@
}
},
"node_modules/undici": {
"version": "7.30.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.30.0.tgz",
"integrity": "sha512-dkrQXeHSaoamnItlYbmzG0wFYrM0ZwDxCIg0A7aKjTyyhh9svRzCNFEzV+Vm05/yehjCzjDZ31KXfGEjYSztDQ==",
"version": "7.30.1",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.30.1.tgz",
"integrity": "sha512-03KrMbjIFDWQR5RNPrSw3bd1r12JpyFQl9/yxjUbJtqkjmllqC5lFjZh6ujeuJCKr8EOQvRW872Oy/az+nLYxg==",
"license": "MIT",
"engines": {
"node": ">=20.18.1"