undici 7.10.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 +3 -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/ProxyAgent.md +2 -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 +3 -3
- 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/client-h1.js +1 -1
- package/lib/dispatcher/proxy-agent.js +2 -1
- package/lib/handler/retry-handler.js +110 -56
- 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/retry-handler.d.ts +9 -0
- package/types/webidl.d.ts +19 -15
- package/types/websocket.d.ts +1 -1
package/lib/core/util.js
CHANGED
|
@@ -6,7 +6,6 @@ const { IncomingMessage } = require('node:http')
|
|
|
6
6
|
const stream = require('node:stream')
|
|
7
7
|
const net = require('node:net')
|
|
8
8
|
const { Blob } = require('node:buffer')
|
|
9
|
-
const nodeUtil = require('node:util')
|
|
10
9
|
const { stringify } = require('node:querystring')
|
|
11
10
|
const { EventEmitter: EE } = require('node:events')
|
|
12
11
|
const timers = require('../util/timers')
|
|
@@ -660,48 +659,6 @@ function addAbortListener (signal, listener) {
|
|
|
660
659
|
return () => signal.removeListener('abort', listener)
|
|
661
660
|
}
|
|
662
661
|
|
|
663
|
-
/**
|
|
664
|
-
* @function
|
|
665
|
-
* @param {string} value
|
|
666
|
-
* @returns {string}
|
|
667
|
-
*/
|
|
668
|
-
const toUSVString = (() => {
|
|
669
|
-
if (typeof String.prototype.toWellFormed === 'function') {
|
|
670
|
-
/**
|
|
671
|
-
* @param {string} value
|
|
672
|
-
* @returns {string}
|
|
673
|
-
*/
|
|
674
|
-
return (value) => `${value}`.toWellFormed()
|
|
675
|
-
} else {
|
|
676
|
-
/**
|
|
677
|
-
* @param {string} value
|
|
678
|
-
* @returns {string}
|
|
679
|
-
*/
|
|
680
|
-
return nodeUtil.toUSVString
|
|
681
|
-
}
|
|
682
|
-
})()
|
|
683
|
-
|
|
684
|
-
/**
|
|
685
|
-
* @param {*} value
|
|
686
|
-
* @returns {boolean}
|
|
687
|
-
*/
|
|
688
|
-
// TODO: move this to webidl
|
|
689
|
-
const isUSVString = (() => {
|
|
690
|
-
if (typeof String.prototype.isWellFormed === 'function') {
|
|
691
|
-
/**
|
|
692
|
-
* @param {*} value
|
|
693
|
-
* @returns {boolean}
|
|
694
|
-
*/
|
|
695
|
-
return (value) => `${value}`.isWellFormed()
|
|
696
|
-
} else {
|
|
697
|
-
/**
|
|
698
|
-
* @param {*} value
|
|
699
|
-
* @returns {boolean}
|
|
700
|
-
*/
|
|
701
|
-
return (value) => toUSVString(value) === `${value}`
|
|
702
|
-
}
|
|
703
|
-
})()
|
|
704
|
-
|
|
705
662
|
/**
|
|
706
663
|
* @see https://tools.ietf.org/html/rfc7230#section-3.2.6
|
|
707
664
|
* @param {number} c
|
|
@@ -943,8 +900,6 @@ Object.setPrototypeOf(normalizedMethodRecords, null)
|
|
|
943
900
|
module.exports = {
|
|
944
901
|
kEnumerableProperty,
|
|
945
902
|
isDisturbed,
|
|
946
|
-
toUSVString,
|
|
947
|
-
isUSVString,
|
|
948
903
|
isBlobLike,
|
|
949
904
|
parseOrigin,
|
|
950
905
|
parseURL,
|
|
@@ -144,7 +144,8 @@ class ProxyAgent extends DispatcherBase {
|
|
|
144
144
|
signal: opts.signal,
|
|
145
145
|
headers: {
|
|
146
146
|
...this[kProxyHeaders],
|
|
147
|
-
host: opts.host
|
|
147
|
+
host: opts.host,
|
|
148
|
+
...(opts.connections == null || opts.connections > 0 ? { 'proxy-connection': 'keep-alive' } : {})
|
|
148
149
|
},
|
|
149
150
|
servername: this[kProxyTls]?.servername || proxyHostname
|
|
150
151
|
})
|
|
@@ -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-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
|
|