undici 7.9.0 → 7.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -0
- package/docs/docs/api/CacheStore.md +23 -3
- package/docs/docs/api/Debug.md +13 -13
- package/docs/docs/api/DiagnosticsChannel.md +25 -0
- package/docs/docs/api/Dispatcher.md +20 -1
- package/docs/docs/api/GlobalInstallation.md +91 -0
- package/docs/docs/api/MockClient.md +4 -0
- package/docs/docs/api/MockPool.md +6 -0
- package/docs/docs/api/Pool.md +1 -0
- package/docs/docs/api/ProxyAgent.md +3 -0
- package/docs/docs/api/RetryAgent.md +6 -1
- package/docs/docs/api/RetryHandler.md +1 -0
- package/index.js +15 -0
- package/lib/api/api-stream.js +1 -1
- package/lib/cache/memory-cache-store.js +42 -4
- package/lib/cache/sqlite-cache-store.js +1 -1
- package/lib/core/connect.js +21 -51
- package/lib/core/diagnostics.js +6 -4
- package/lib/core/request.js +6 -0
- package/lib/core/util.js +0 -45
- package/lib/dispatcher/agent.js +25 -15
- package/lib/dispatcher/client-h1.js +1 -1
- package/lib/dispatcher/pool.js +17 -3
- package/lib/dispatcher/proxy-agent.js +90 -3
- package/lib/handler/retry-handler.js +110 -56
- package/lib/mock/mock-agent.js +8 -8
- package/lib/mock/mock-client.js +4 -0
- package/lib/mock/mock-pool.js +4 -0
- package/lib/util/cache.js +11 -1
- package/lib/util/timers.js +11 -9
- package/lib/web/cache/cache.js +1 -1
- package/lib/web/cache/cachestorage.js +1 -1
- package/lib/web/cookies/index.js +1 -1
- package/lib/web/eventsource/eventsource.js +3 -6
- package/lib/web/eventsource/util.js +1 -1
- package/lib/web/fetch/body.js +2 -2
- package/lib/web/fetch/dispatcher-weakref.js +0 -41
- package/lib/web/fetch/formdata-parser.js +4 -4
- package/lib/web/fetch/formdata.js +1 -1
- package/lib/web/fetch/headers.js +1 -1
- package/lib/web/fetch/index.js +7 -1
- package/lib/web/fetch/request.js +1 -1
- package/lib/web/fetch/response.js +1 -1
- package/lib/web/fetch/util.js +2 -2
- package/lib/web/{fetch/webidl.js → webidl/index.js} +57 -9
- package/lib/web/websocket/connection.js +4 -3
- package/lib/web/websocket/events.js +1 -1
- package/lib/web/websocket/frame.js +2 -1
- package/lib/web/websocket/stream/websocketerror.js +1 -1
- package/lib/web/websocket/stream/websocketstream.js +1 -1
- package/lib/web/websocket/websocket.js +4 -4
- package/package.json +4 -4
- package/types/diagnostics-channel.d.ts +9 -0
- package/types/dispatcher.d.ts +3 -2
- package/types/env-http-proxy-agent.d.ts +2 -1
- package/types/eventsource.d.ts +3 -3
- package/types/fetch.d.ts +1 -0
- package/types/handlers.d.ts +1 -1
- package/types/mock-client.d.ts +2 -0
- package/types/mock-interceptor.d.ts +2 -0
- package/types/mock-pool.d.ts +2 -0
- package/types/pool.d.ts +2 -0
- package/types/proxy-agent.d.ts +1 -0
- package/types/retry-handler.d.ts +9 -0
- package/types/webidl.d.ts +19 -15
- package/types/websocket.d.ts +1 -1
|
@@ -29,13 +29,16 @@ class RetryHandler {
|
|
|
29
29
|
methods,
|
|
30
30
|
errorCodes,
|
|
31
31
|
retryAfter,
|
|
32
|
-
statusCodes
|
|
32
|
+
statusCodes,
|
|
33
|
+
throwOnError
|
|
33
34
|
} = retryOptions ?? {}
|
|
34
35
|
|
|
36
|
+
this.error = null
|
|
35
37
|
this.dispatch = dispatch
|
|
36
38
|
this.handler = WrapHandler.wrap(handler)
|
|
37
39
|
this.opts = { ...dispatchOpts, body: wrapRequestBody(opts.body) }
|
|
38
40
|
this.retryOpts = {
|
|
41
|
+
throwOnError: throwOnError ?? true,
|
|
39
42
|
retry: retryFn ?? RetryHandler[kRetryHandlerDefaultRetry],
|
|
40
43
|
retryAfter: retryAfter ?? true,
|
|
41
44
|
maxTimeout: maxTimeout ?? 30 * 1000, // 30s,
|
|
@@ -68,6 +71,50 @@ class RetryHandler {
|
|
|
68
71
|
this.etag = null
|
|
69
72
|
}
|
|
70
73
|
|
|
74
|
+
onResponseStartWithRetry (controller, statusCode, headers, statusMessage, err) {
|
|
75
|
+
if (this.retryOpts.throwOnError) {
|
|
76
|
+
// Preserve old behavior for status codes that are not eligible for retry
|
|
77
|
+
if (this.retryOpts.statusCodes.includes(statusCode) === false) {
|
|
78
|
+
this.headersSent = true
|
|
79
|
+
this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage)
|
|
80
|
+
} else {
|
|
81
|
+
this.error = err
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (isDisturbed(this.opts.body)) {
|
|
88
|
+
this.headersSent = true
|
|
89
|
+
this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage)
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function shouldRetry (passedErr) {
|
|
94
|
+
if (passedErr) {
|
|
95
|
+
this.headersSent = true
|
|
96
|
+
|
|
97
|
+
this.headersSent = true
|
|
98
|
+
this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage)
|
|
99
|
+
controller.resume()
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
this.error = err
|
|
104
|
+
controller.resume()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
controller.pause()
|
|
108
|
+
this.retryOpts.retry(
|
|
109
|
+
err,
|
|
110
|
+
{
|
|
111
|
+
state: { counter: this.retryCount },
|
|
112
|
+
opts: { retryOptions: this.retryOpts, ...this.opts }
|
|
113
|
+
},
|
|
114
|
+
shouldRetry.bind(this)
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
71
118
|
onRequestStart (controller, context) {
|
|
72
119
|
if (!this.headersSent) {
|
|
73
120
|
this.handler.onRequestStart?.(controller, context)
|
|
@@ -137,26 +184,19 @@ class RetryHandler {
|
|
|
137
184
|
}
|
|
138
185
|
|
|
139
186
|
onResponseStart (controller, statusCode, headers, statusMessage) {
|
|
187
|
+
this.error = null
|
|
140
188
|
this.retryCount += 1
|
|
141
189
|
|
|
142
190
|
if (statusCode >= 300) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
} else {
|
|
153
|
-
throw new RequestRetryError('Request failed', statusCode, {
|
|
154
|
-
headers,
|
|
155
|
-
data: {
|
|
156
|
-
count: this.retryCount
|
|
157
|
-
}
|
|
158
|
-
})
|
|
159
|
-
}
|
|
191
|
+
const err = new RequestRetryError('Request failed', statusCode, {
|
|
192
|
+
headers,
|
|
193
|
+
data: {
|
|
194
|
+
count: this.retryCount
|
|
195
|
+
}
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
this.onResponseStartWithRetry(controller, statusCode, headers, statusMessage, err)
|
|
199
|
+
return
|
|
160
200
|
}
|
|
161
201
|
|
|
162
202
|
// Checkpoint for resume from where we left it
|
|
@@ -175,6 +215,7 @@ class RetryHandler {
|
|
|
175
215
|
const contentRange = parseRangeHeader(headers['content-range'])
|
|
176
216
|
// If no content range
|
|
177
217
|
if (!contentRange) {
|
|
218
|
+
// We always throw here as we want to indicate that we entred unexpected path
|
|
178
219
|
throw new RequestRetryError('Content-Range mismatch', statusCode, {
|
|
179
220
|
headers,
|
|
180
221
|
data: { count: this.retryCount }
|
|
@@ -183,6 +224,7 @@ class RetryHandler {
|
|
|
183
224
|
|
|
184
225
|
// Let's start with a weak etag check
|
|
185
226
|
if (this.etag != null && this.etag !== headers.etag) {
|
|
227
|
+
// We always throw here as we want to indicate that we entred unexpected path
|
|
186
228
|
throw new RequestRetryError('ETag mismatch', statusCode, {
|
|
187
229
|
headers,
|
|
188
230
|
data: { count: this.retryCount }
|
|
@@ -266,14 +308,52 @@ class RetryHandler {
|
|
|
266
308
|
}
|
|
267
309
|
|
|
268
310
|
onResponseData (controller, chunk) {
|
|
311
|
+
if (this.error) {
|
|
312
|
+
return
|
|
313
|
+
}
|
|
314
|
+
|
|
269
315
|
this.start += chunk.length
|
|
270
316
|
|
|
271
317
|
this.handler.onResponseData?.(controller, chunk)
|
|
272
318
|
}
|
|
273
319
|
|
|
274
320
|
onResponseEnd (controller, trailers) {
|
|
275
|
-
this.
|
|
276
|
-
|
|
321
|
+
if (this.error && this.retryOpts.throwOnError) {
|
|
322
|
+
throw this.error
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (!this.error) {
|
|
326
|
+
this.retryCount = 0
|
|
327
|
+
return this.handler.onResponseEnd?.(controller, trailers)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
this.retry(controller)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
retry (controller) {
|
|
334
|
+
if (this.start !== 0) {
|
|
335
|
+
const headers = { range: `bytes=${this.start}-${this.end ?? ''}` }
|
|
336
|
+
|
|
337
|
+
// Weak etag check - weak etags will make comparison algorithms never match
|
|
338
|
+
if (this.etag != null) {
|
|
339
|
+
headers['if-match'] = this.etag
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
this.opts = {
|
|
343
|
+
...this.opts,
|
|
344
|
+
headers: {
|
|
345
|
+
...this.opts.headers,
|
|
346
|
+
...headers
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
try {
|
|
352
|
+
this.retryCountCheckpoint = this.retryCount
|
|
353
|
+
this.dispatch(this.opts, this)
|
|
354
|
+
} catch (err) {
|
|
355
|
+
this.handler.onResponseError?.(controller, err)
|
|
356
|
+
}
|
|
277
357
|
}
|
|
278
358
|
|
|
279
359
|
onResponseError (controller, err) {
|
|
@@ -282,6 +362,15 @@ class RetryHandler {
|
|
|
282
362
|
return
|
|
283
363
|
}
|
|
284
364
|
|
|
365
|
+
function shouldRetry (returnedErr) {
|
|
366
|
+
if (!returnedErr) {
|
|
367
|
+
this.retry(controller)
|
|
368
|
+
return
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
this.handler?.onResponseError?.(controller, returnedErr)
|
|
372
|
+
}
|
|
373
|
+
|
|
285
374
|
// We reconcile in case of a mix between network errors
|
|
286
375
|
// and server error response
|
|
287
376
|
if (this.retryCount - this.retryCountCheckpoint > 0) {
|
|
@@ -299,43 +388,8 @@ class RetryHandler {
|
|
|
299
388
|
state: { counter: this.retryCount },
|
|
300
389
|
opts: { retryOptions: this.retryOpts, ...this.opts }
|
|
301
390
|
},
|
|
302
|
-
|
|
391
|
+
shouldRetry.bind(this)
|
|
303
392
|
)
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* @this {RetryHandler}
|
|
307
|
-
* @param {Error} [err]
|
|
308
|
-
* @returns
|
|
309
|
-
*/
|
|
310
|
-
function onRetry (err) {
|
|
311
|
-
if (err != null || controller?.aborted || isDisturbed(this.opts.body)) {
|
|
312
|
-
return this.handler.onResponseError?.(controller, err)
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
if (this.start !== 0) {
|
|
316
|
-
const headers = { range: `bytes=${this.start}-${this.end ?? ''}` }
|
|
317
|
-
|
|
318
|
-
// Weak etag check - weak etags will make comparison algorithms never match
|
|
319
|
-
if (this.etag != null) {
|
|
320
|
-
headers['if-match'] = this.etag
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
this.opts = {
|
|
324
|
-
...this.opts,
|
|
325
|
-
headers: {
|
|
326
|
-
...this.opts.headers,
|
|
327
|
-
...headers
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
try {
|
|
333
|
-
this.retryCountCheckpoint = this.retryCount
|
|
334
|
-
this.dispatch(this.opts, this)
|
|
335
|
-
} catch (err) {
|
|
336
|
-
this.handler.onResponseError?.(controller, err)
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
393
|
}
|
|
340
394
|
}
|
|
341
395
|
|
package/lib/mock/mock-agent.js
CHANGED
|
@@ -159,7 +159,7 @@ class MockAgent extends Dispatcher {
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
[kMockAgentSet] (origin, dispatcher) {
|
|
162
|
-
this[kClients].set(origin, dispatcher)
|
|
162
|
+
this[kClients].set(origin, { count: 0, dispatcher })
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
[kFactory] (origin) {
|
|
@@ -171,9 +171,9 @@ class MockAgent extends Dispatcher {
|
|
|
171
171
|
|
|
172
172
|
[kMockAgentGet] (origin) {
|
|
173
173
|
// First check if we can immediately find it
|
|
174
|
-
const
|
|
175
|
-
if (
|
|
176
|
-
return
|
|
174
|
+
const result = this[kClients].get(origin)
|
|
175
|
+
if (result?.dispatcher) {
|
|
176
|
+
return result.dispatcher
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
// If the origin is not a string create a dummy parent pool and return to user
|
|
@@ -184,11 +184,11 @@ class MockAgent extends Dispatcher {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
// If we match, create a pool and assign the same dispatches
|
|
187
|
-
for (const [keyMatcher,
|
|
188
|
-
if (
|
|
187
|
+
for (const [keyMatcher, result] of Array.from(this[kClients])) {
|
|
188
|
+
if (result && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) {
|
|
189
189
|
const dispatcher = this[kFactory](origin)
|
|
190
190
|
this[kMockAgentSet](origin, dispatcher)
|
|
191
|
-
dispatcher[kDispatches] =
|
|
191
|
+
dispatcher[kDispatches] = result.dispatcher[kDispatches]
|
|
192
192
|
return dispatcher
|
|
193
193
|
}
|
|
194
194
|
}
|
|
@@ -202,7 +202,7 @@ class MockAgent extends Dispatcher {
|
|
|
202
202
|
const mockAgentClients = this[kClients]
|
|
203
203
|
|
|
204
204
|
return Array.from(mockAgentClients.entries())
|
|
205
|
-
.flatMap(([origin,
|
|
205
|
+
.flatMap(([origin, result]) => result.dispatcher[kDispatches].map(dispatch => ({ ...dispatch, origin })))
|
|
206
206
|
.filter(({ pending }) => pending)
|
|
207
207
|
}
|
|
208
208
|
|
package/lib/mock/mock-client.js
CHANGED
package/lib/mock/mock-pool.js
CHANGED
package/lib/util/cache.js
CHANGED
|
@@ -4,6 +4,8 @@ const {
|
|
|
4
4
|
safeHTTPMethods
|
|
5
5
|
} = require('../core/util')
|
|
6
6
|
|
|
7
|
+
const { serializePathWithQuery } = require('../core/util')
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* @param {import('../../types/dispatcher.d.ts').default.DispatchOptions} opts
|
|
9
11
|
*/
|
|
@@ -12,10 +14,18 @@ function makeCacheKey (opts) {
|
|
|
12
14
|
throw new Error('opts.origin is undefined')
|
|
13
15
|
}
|
|
14
16
|
|
|
17
|
+
let fullPath
|
|
18
|
+
try {
|
|
19
|
+
fullPath = serializePathWithQuery(opts.path || '/', opts.query)
|
|
20
|
+
} catch (error) {
|
|
21
|
+
// If fails (path already has query params), use as-is
|
|
22
|
+
fullPath = opts.path || '/'
|
|
23
|
+
}
|
|
24
|
+
|
|
15
25
|
return {
|
|
16
26
|
origin: opts.origin.toString(),
|
|
17
27
|
method: opts.method,
|
|
18
|
-
path:
|
|
28
|
+
path: fullPath,
|
|
19
29
|
headers: opts.headers
|
|
20
30
|
}
|
|
21
31
|
}
|
package/lib/util/timers.js
CHANGED
|
@@ -188,19 +188,21 @@ function onTick () {
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
function refreshTimeout () {
|
|
191
|
-
// If the fastNowTimeout is already set
|
|
192
|
-
|
|
191
|
+
// If the fastNowTimeout is already set and the Timer has the refresh()-
|
|
192
|
+
// method available, call it to refresh the timer.
|
|
193
|
+
// Some timer objects returned by setTimeout may not have a .refresh()
|
|
194
|
+
// method (e.g. mocked timers in tests).
|
|
195
|
+
if (fastNowTimeout?.refresh) {
|
|
193
196
|
fastNowTimeout.refresh()
|
|
194
|
-
|
|
197
|
+
// fastNowTimeout is not instantiated yet or refresh is not availabe,
|
|
198
|
+
// create a new Timer.
|
|
195
199
|
} else {
|
|
196
200
|
clearTimeout(fastNowTimeout)
|
|
197
201
|
fastNowTimeout = setTimeout(onTick, TICK_MS)
|
|
198
|
-
|
|
199
|
-
//
|
|
200
|
-
//
|
|
201
|
-
|
|
202
|
-
fastNowTimeout.unref()
|
|
203
|
-
}
|
|
202
|
+
// If the Timer has an unref method, call it to allow the process to exit,
|
|
203
|
+
// if there are no other active handles. When using fake timers or mocked
|
|
204
|
+
// environments (like Jest), .unref() may not be defined,
|
|
205
|
+
fastNowTimeout?.unref()
|
|
204
206
|
}
|
|
205
207
|
}
|
|
206
208
|
|
package/lib/web/cache/cache.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const { kConstruct } = require('../../core/symbols')
|
|
4
4
|
const { urlEquals, getFieldValues } = require('./util')
|
|
5
5
|
const { kEnumerableProperty, isDisturbed } = require('../../core/util')
|
|
6
|
-
const { webidl } = require('../
|
|
6
|
+
const { webidl } = require('../webidl')
|
|
7
7
|
const { cloneResponse, fromInnerResponse, getResponseState } = require('../fetch/response')
|
|
8
8
|
const { Request, fromInnerRequest, getRequestState } = require('../fetch/request')
|
|
9
9
|
const { fetching } = require('../fetch/index')
|
package/lib/web/cookies/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { parseSetCookie } = require('./parse')
|
|
4
4
|
const { stringify } = require('./util')
|
|
5
|
-
const { webidl } = require('../
|
|
5
|
+
const { webidl } = require('../webidl')
|
|
6
6
|
const { Headers } = require('../fetch/headers')
|
|
7
7
|
|
|
8
8
|
const brandChecks = webidl.brandCheckMultiple([Headers, globalThis.Headers].filter(Boolean))
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const { pipeline } = require('node:stream')
|
|
4
4
|
const { fetching } = require('../fetch')
|
|
5
5
|
const { makeRequest } = require('../fetch/request')
|
|
6
|
-
const { webidl } = require('../
|
|
6
|
+
const { webidl } = require('../webidl')
|
|
7
7
|
const { EventSourceStream } = require('./eventsource-stream')
|
|
8
8
|
const { parseMIMEType } = require('../fetch/data-url')
|
|
9
9
|
const { createFastMessageEvent } = require('../websocket/events')
|
|
@@ -231,12 +231,9 @@ class EventSource extends EventTarget {
|
|
|
231
231
|
|
|
232
232
|
// 14. Let processEventSourceEndOfBody given response res be the following step: if res is not a network error, then reestablish the connection.
|
|
233
233
|
const processEventSourceEndOfBody = (response) => {
|
|
234
|
-
if (isNetworkError(response)) {
|
|
235
|
-
this
|
|
236
|
-
this.close()
|
|
234
|
+
if (!isNetworkError(response)) {
|
|
235
|
+
return this.#reconnect()
|
|
237
236
|
}
|
|
238
|
-
|
|
239
|
-
this.#reconnect()
|
|
240
237
|
}
|
|
241
238
|
|
|
242
239
|
// 15. Fetch request, with processResponseEndOfBody set to processEventSourceEndOfBody...
|
package/lib/web/fetch/body.js
CHANGED
|
@@ -10,7 +10,7 @@ const {
|
|
|
10
10
|
utf8DecodeBytes
|
|
11
11
|
} = require('./util')
|
|
12
12
|
const { FormData, setFormDataState } = require('./formdata')
|
|
13
|
-
const { webidl } = require('
|
|
13
|
+
const { webidl } = require('../webidl')
|
|
14
14
|
const { Blob } = require('node:buffer')
|
|
15
15
|
const assert = require('node:assert')
|
|
16
16
|
const { isErrored, isDisturbed } = require('node:stream')
|
|
@@ -29,7 +29,7 @@ try {
|
|
|
29
29
|
const textEncoder = new TextEncoder()
|
|
30
30
|
function noop () {}
|
|
31
31
|
|
|
32
|
-
const hasFinalizationRegistry = globalThis.FinalizationRegistry
|
|
32
|
+
const hasFinalizationRegistry = globalThis.FinalizationRegistry
|
|
33
33
|
let streamRegistry
|
|
34
34
|
|
|
35
35
|
if (hasFinalizationRegistry) {
|
|
@@ -1,46 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { kConnected, kSize } = require('../../core/symbols')
|
|
4
|
-
|
|
5
|
-
class CompatWeakRef {
|
|
6
|
-
constructor (value) {
|
|
7
|
-
this.value = value
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
deref () {
|
|
11
|
-
return this.value[kConnected] === 0 && this.value[kSize] === 0
|
|
12
|
-
? undefined
|
|
13
|
-
: this.value
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
class CompatFinalizer {
|
|
18
|
-
constructor (finalizer) {
|
|
19
|
-
this.finalizer = finalizer
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
register (dispatcher, key) {
|
|
23
|
-
if (dispatcher.on) {
|
|
24
|
-
dispatcher.on('disconnect', () => {
|
|
25
|
-
if (dispatcher[kConnected] === 0 && dispatcher[kSize] === 0) {
|
|
26
|
-
this.finalizer(key)
|
|
27
|
-
}
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
unregister (key) {}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
3
|
module.exports = function () {
|
|
36
|
-
// FIXME: remove workaround when the Node bug is backported to v18
|
|
37
|
-
// https://github.com/nodejs/node/issues/49344#issuecomment-1741776308
|
|
38
|
-
if (process.env.NODE_V8_COVERAGE && process.version.startsWith('v18')) {
|
|
39
|
-
process._rawDebug('Using compatibility WeakRef and FinalizationRegistry')
|
|
40
|
-
return {
|
|
41
|
-
WeakRef: CompatWeakRef,
|
|
42
|
-
FinalizationRegistry: CompatFinalizer
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
4
|
return { WeakRef, FinalizationRegistry }
|
|
46
5
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const { bufferToLowerCasedHeaderName } = require('../../core/util')
|
|
4
4
|
const { utf8DecodeBytes } = require('./util')
|
|
5
5
|
const { HTTP_TOKEN_CODEPOINTS, isomorphicDecode } = require('./data-url')
|
|
6
6
|
const { makeEntry } = require('./formdata')
|
|
7
|
-
const { webidl } = require('
|
|
7
|
+
const { webidl } = require('../webidl')
|
|
8
8
|
const assert = require('node:assert')
|
|
9
9
|
const { File: NodeFile } = require('node:buffer')
|
|
10
10
|
|
|
@@ -200,8 +200,8 @@ function multipartFormDataParser (input, mimeType) {
|
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
// 5.12. Assert: name is a scalar value string and value is either a scalar value string or a File object.
|
|
203
|
-
assert(
|
|
204
|
-
assert((typeof value === 'string' &&
|
|
203
|
+
assert(webidl.is.USVString(name))
|
|
204
|
+
assert((typeof value === 'string' && webidl.is.USVString(value)) || webidl.is.File(value))
|
|
205
205
|
|
|
206
206
|
// 5.13. Create an entry with name and value, and append it to entry list.
|
|
207
207
|
entryList.push(makeEntry(name, value, filename))
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { iteratorMixin } = require('./util')
|
|
4
4
|
const { kEnumerableProperty } = require('../../core/util')
|
|
5
|
-
const { webidl } = require('
|
|
5
|
+
const { webidl } = require('../webidl')
|
|
6
6
|
const { File: NativeFile } = require('node:buffer')
|
|
7
7
|
const nodeUtil = require('node:util')
|
|
8
8
|
|
package/lib/web/fetch/headers.js
CHANGED
package/lib/web/fetch/index.js
CHANGED
|
@@ -61,7 +61,7 @@ const { Readable, pipeline, finished, isErrored, isReadable } = require('node:st
|
|
|
61
61
|
const { addAbortListener, bufferToLowerCasedHeaderName } = require('../../core/util')
|
|
62
62
|
const { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = require('./data-url')
|
|
63
63
|
const { getGlobalDispatcher } = require('../../global')
|
|
64
|
-
const { webidl } = require('
|
|
64
|
+
const { webidl } = require('../webidl')
|
|
65
65
|
const { STATUS_CODES } = require('node:http')
|
|
66
66
|
const GET_OR_HEAD = ['GET', 'HEAD']
|
|
67
67
|
|
|
@@ -2155,6 +2155,12 @@ async function httpNetworkFetch (
|
|
|
2155
2155
|
flush: zlib.constants.BROTLI_OPERATION_FLUSH,
|
|
2156
2156
|
finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH
|
|
2157
2157
|
}))
|
|
2158
|
+
} else if (coding === 'zstd' && typeof zlib.createZstdDecompress === 'function') {
|
|
2159
|
+
// Node.js v23.8.0+ and v22.15.0+ supports Zstandard
|
|
2160
|
+
decoders.push(zlib.createZstdDecompress({
|
|
2161
|
+
flush: zlib.constants.ZSTD_e_continue,
|
|
2162
|
+
finishFlush: zlib.constants.ZSTD_e_end
|
|
2163
|
+
}))
|
|
2158
2164
|
} else {
|
|
2159
2165
|
decoders.length = 0
|
|
2160
2166
|
break
|
package/lib/web/fetch/request.js
CHANGED
|
@@ -23,7 +23,7 @@ const {
|
|
|
23
23
|
requestDuplex
|
|
24
24
|
} = require('./constants')
|
|
25
25
|
const { kEnumerableProperty, normalizedMethodRecordsBase, normalizedMethodRecords } = util
|
|
26
|
-
const { webidl } = require('
|
|
26
|
+
const { webidl } = require('../webidl')
|
|
27
27
|
const { URLSerializer } = require('./data-url')
|
|
28
28
|
const { kConstruct } = require('../../core/symbols')
|
|
29
29
|
const assert = require('node:assert')
|
|
@@ -18,7 +18,7 @@ const {
|
|
|
18
18
|
redirectStatusSet,
|
|
19
19
|
nullBodyStatus
|
|
20
20
|
} = require('./constants')
|
|
21
|
-
const { webidl } = require('
|
|
21
|
+
const { webidl } = require('../webidl')
|
|
22
22
|
const { URLSerializer } = require('./data-url')
|
|
23
23
|
const { kConstruct } = require('../../core/symbols')
|
|
24
24
|
const assert = require('node:assert')
|
package/lib/web/fetch/util.js
CHANGED
|
@@ -9,7 +9,7 @@ const { performance } = require('node:perf_hooks')
|
|
|
9
9
|
const { ReadableStreamFrom, isValidHTTPToken, normalizedMethodRecordsBase } = require('../../core/util')
|
|
10
10
|
const assert = require('node:assert')
|
|
11
11
|
const { isUint8Array } = require('node:util/types')
|
|
12
|
-
const { webidl } = require('
|
|
12
|
+
const { webidl } = require('../webidl')
|
|
13
13
|
|
|
14
14
|
let supportedHashes = []
|
|
15
15
|
|
|
@@ -1262,7 +1262,7 @@ async function readAllBytes (reader, successSteps, failureSteps) {
|
|
|
1262
1262
|
// 1. If chunk is not a Uint8Array object, call failureSteps
|
|
1263
1263
|
// with a TypeError and abort these steps.
|
|
1264
1264
|
if (!isUint8Array(chunk)) {
|
|
1265
|
-
failureSteps(TypeError('Received non-Uint8Array chunk'))
|
|
1265
|
+
failureSteps(new TypeError('Received non-Uint8Array chunk'))
|
|
1266
1266
|
return
|
|
1267
1267
|
}
|
|
1268
1268
|
|