undici 7.0.0-alpha.1 → 7.0.0-alpha.2
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 +2 -2
- package/docs/docs/api/Client.md +1 -1
- package/docs/docs/api/Debug.md +1 -1
- package/docs/docs/api/Dispatcher.md +53 -2
- package/docs/docs/api/MockAgent.md +2 -0
- package/docs/docs/api/MockPool.md +2 -1
- package/docs/docs/api/RetryAgent.md +1 -1
- package/docs/docs/api/RetryHandler.md +1 -1
- package/docs/docs/api/WebSocket.md +45 -3
- package/index.js +6 -2
- package/lib/api/abort-signal.js +2 -0
- package/lib/api/api-pipeline.js +4 -2
- package/lib/api/api-request.js +4 -2
- package/lib/api/api-stream.js +3 -1
- package/lib/api/api-upgrade.js +2 -2
- package/lib/api/readable.js +194 -41
- package/lib/api/util.js +2 -0
- package/lib/core/connect.js +49 -22
- package/lib/core/constants.js +11 -9
- package/lib/core/diagnostics.js +122 -128
- package/lib/core/request.js +4 -4
- package/lib/core/symbols.js +2 -0
- package/lib/core/tree.js +4 -2
- package/lib/core/util.js +220 -39
- package/lib/dispatcher/client-h1.js +299 -60
- package/lib/dispatcher/client-h2.js +1 -1
- package/lib/dispatcher/client.js +24 -7
- package/lib/dispatcher/fixed-queue.js +91 -49
- package/lib/dispatcher/pool-stats.js +2 -0
- package/lib/dispatcher/proxy-agent.js +3 -1
- package/lib/handler/redirect-handler.js +2 -2
- package/lib/handler/retry-handler.js +2 -2
- package/lib/interceptor/dns.js +346 -0
- package/lib/mock/mock-agent.js +5 -8
- package/lib/mock/mock-client.js +7 -2
- package/lib/mock/mock-errors.js +3 -1
- package/lib/mock/mock-interceptor.js +8 -6
- package/lib/mock/mock-pool.js +7 -2
- package/lib/mock/mock-symbols.js +2 -1
- package/lib/mock/mock-utils.js +33 -5
- package/lib/util/timers.js +50 -6
- package/lib/web/cache/cache.js +24 -21
- package/lib/web/cache/cachestorage.js +1 -1
- package/lib/web/cookies/index.js +6 -4
- package/lib/web/fetch/body.js +42 -34
- package/lib/web/fetch/constants.js +35 -26
- package/lib/web/fetch/formdata-parser.js +14 -3
- package/lib/web/fetch/formdata.js +40 -20
- package/lib/web/fetch/headers.js +116 -84
- package/lib/web/fetch/index.js +65 -59
- package/lib/web/fetch/request.js +130 -55
- package/lib/web/fetch/response.js +79 -36
- package/lib/web/fetch/util.js +104 -57
- package/lib/web/fetch/webidl.js +38 -14
- package/lib/web/websocket/connection.js +92 -15
- package/lib/web/websocket/constants.js +2 -3
- package/lib/web/websocket/events.js +4 -2
- package/lib/web/websocket/receiver.js +20 -26
- package/lib/web/websocket/stream/websocketerror.js +83 -0
- package/lib/web/websocket/stream/websocketstream.js +485 -0
- package/lib/web/websocket/util.js +115 -10
- package/lib/web/websocket/websocket.js +45 -170
- package/package.json +6 -6
- package/types/interceptors.d.ts +14 -0
- package/types/mock-agent.d.ts +3 -0
- package/types/readable.d.ts +10 -7
- package/types/webidl.d.ts +24 -4
- package/types/websocket.d.ts +33 -0
- package/lib/mock/pluralizer.js +0 -29
- package/lib/web/cache/symbols.js +0 -5
- package/lib/web/fetch/symbols.js +0 -8
|
@@ -18,9 +18,7 @@ const {
|
|
|
18
18
|
redirectStatusSet,
|
|
19
19
|
nullBodyStatus
|
|
20
20
|
} = require('./constants')
|
|
21
|
-
const { kState, kHeaders } = require('./symbols')
|
|
22
21
|
const { webidl } = require('./webidl')
|
|
23
|
-
const { FormData } = require('./formdata')
|
|
24
22
|
const { URLSerializer } = require('./data-url')
|
|
25
23
|
const { kConstruct } = require('../../core/symbols')
|
|
26
24
|
const assert = require('node:assert')
|
|
@@ -30,6 +28,11 @@ const textEncoder = new TextEncoder('utf-8')
|
|
|
30
28
|
|
|
31
29
|
// https://fetch.spec.whatwg.org/#response-class
|
|
32
30
|
class Response {
|
|
31
|
+
/** @type {Headers} */
|
|
32
|
+
#headers
|
|
33
|
+
|
|
34
|
+
#state
|
|
35
|
+
|
|
33
36
|
// Creates network error Response.
|
|
34
37
|
static error () {
|
|
35
38
|
// The static error() method steps are to return the result of creating a
|
|
@@ -95,13 +98,13 @@ class Response {
|
|
|
95
98
|
const responseObject = fromInnerResponse(makeResponse({}), 'immutable')
|
|
96
99
|
|
|
97
100
|
// 5. Set responseObject’s response’s status to status.
|
|
98
|
-
responseObject
|
|
101
|
+
responseObject.#state.status = status
|
|
99
102
|
|
|
100
103
|
// 6. Let value be parsedURL, serialized and isomorphic encoded.
|
|
101
104
|
const value = isomorphicEncode(URLSerializer(parsedURL))
|
|
102
105
|
|
|
103
106
|
// 7. Append `Location`/value to responseObject’s response’s header list.
|
|
104
|
-
responseObject
|
|
107
|
+
responseObject.#state.headersList.append('location', value, true)
|
|
105
108
|
|
|
106
109
|
// 8. Return responseObject.
|
|
107
110
|
return responseObject
|
|
@@ -120,14 +123,14 @@ class Response {
|
|
|
120
123
|
init = webidl.converters.ResponseInit(init)
|
|
121
124
|
|
|
122
125
|
// 1. Set this’s response to a new response.
|
|
123
|
-
this
|
|
126
|
+
this.#state = makeResponse({})
|
|
124
127
|
|
|
125
128
|
// 2. Set this’s headers to a new Headers object with this’s relevant
|
|
126
129
|
// Realm, whose header list is this’s response’s header list and guard
|
|
127
130
|
// is "response".
|
|
128
|
-
this
|
|
129
|
-
setHeadersGuard(this
|
|
130
|
-
setHeadersList(this
|
|
131
|
+
this.#headers = new Headers(kConstruct)
|
|
132
|
+
setHeadersGuard(this.#headers, 'response')
|
|
133
|
+
setHeadersList(this.#headers, this.#state.headersList)
|
|
131
134
|
|
|
132
135
|
// 3. Let bodyWithType be null.
|
|
133
136
|
let bodyWithType = null
|
|
@@ -147,14 +150,14 @@ class Response {
|
|
|
147
150
|
webidl.brandCheck(this, Response)
|
|
148
151
|
|
|
149
152
|
// The type getter steps are to return this’s response’s type.
|
|
150
|
-
return this
|
|
153
|
+
return this.#state.type
|
|
151
154
|
}
|
|
152
155
|
|
|
153
156
|
// Returns response’s URL, if it has one; otherwise the empty string.
|
|
154
157
|
get url () {
|
|
155
158
|
webidl.brandCheck(this, Response)
|
|
156
159
|
|
|
157
|
-
const urlList = this
|
|
160
|
+
const urlList = this.#state.urlList
|
|
158
161
|
|
|
159
162
|
// The url getter steps are to return the empty string if this’s
|
|
160
163
|
// response’s URL is null; otherwise this’s response’s URL,
|
|
@@ -174,7 +177,7 @@ class Response {
|
|
|
174
177
|
|
|
175
178
|
// The redirected getter steps are to return true if this’s response’s URL
|
|
176
179
|
// list has more than one item; otherwise false.
|
|
177
|
-
return this
|
|
180
|
+
return this.#state.urlList.length > 1
|
|
178
181
|
}
|
|
179
182
|
|
|
180
183
|
// Returns response’s status.
|
|
@@ -182,7 +185,7 @@ class Response {
|
|
|
182
185
|
webidl.brandCheck(this, Response)
|
|
183
186
|
|
|
184
187
|
// The status getter steps are to return this’s response’s status.
|
|
185
|
-
return this
|
|
188
|
+
return this.#state.status
|
|
186
189
|
}
|
|
187
190
|
|
|
188
191
|
// Returns whether response’s status is an ok status.
|
|
@@ -191,7 +194,7 @@ class Response {
|
|
|
191
194
|
|
|
192
195
|
// The ok getter steps are to return true if this’s response’s status is an
|
|
193
196
|
// ok status; otherwise false.
|
|
194
|
-
return this
|
|
197
|
+
return this.#state.status >= 200 && this.#state.status <= 299
|
|
195
198
|
}
|
|
196
199
|
|
|
197
200
|
// Returns response’s status message.
|
|
@@ -200,7 +203,7 @@ class Response {
|
|
|
200
203
|
|
|
201
204
|
// The statusText getter steps are to return this’s response’s status
|
|
202
205
|
// message.
|
|
203
|
-
return this
|
|
206
|
+
return this.#state.statusText
|
|
204
207
|
}
|
|
205
208
|
|
|
206
209
|
// Returns response’s headers as Headers.
|
|
@@ -208,19 +211,19 @@ class Response {
|
|
|
208
211
|
webidl.brandCheck(this, Response)
|
|
209
212
|
|
|
210
213
|
// The headers getter steps are to return this’s headers.
|
|
211
|
-
return this
|
|
214
|
+
return this.#headers
|
|
212
215
|
}
|
|
213
216
|
|
|
214
217
|
get body () {
|
|
215
218
|
webidl.brandCheck(this, Response)
|
|
216
219
|
|
|
217
|
-
return this
|
|
220
|
+
return this.#state.body ? this.#state.body.stream : null
|
|
218
221
|
}
|
|
219
222
|
|
|
220
223
|
get bodyUsed () {
|
|
221
224
|
webidl.brandCheck(this, Response)
|
|
222
225
|
|
|
223
|
-
return !!this
|
|
226
|
+
return !!this.#state.body && util.isDisturbed(this.#state.body.stream)
|
|
224
227
|
}
|
|
225
228
|
|
|
226
229
|
// Returns a clone of response.
|
|
@@ -228,7 +231,7 @@ class Response {
|
|
|
228
231
|
webidl.brandCheck(this, Response)
|
|
229
232
|
|
|
230
233
|
// 1. If this is unusable, then throw a TypeError.
|
|
231
|
-
if (bodyUnusable(this)) {
|
|
234
|
+
if (bodyUnusable(this.#state)) {
|
|
232
235
|
throw webidl.errors.exception({
|
|
233
236
|
header: 'Response.clone',
|
|
234
237
|
message: 'Body has already been consumed.'
|
|
@@ -236,11 +239,11 @@ class Response {
|
|
|
236
239
|
}
|
|
237
240
|
|
|
238
241
|
// 2. Let clonedResponse be the result of cloning this’s response.
|
|
239
|
-
const clonedResponse = cloneResponse(this
|
|
242
|
+
const clonedResponse = cloneResponse(this.#state)
|
|
240
243
|
|
|
241
244
|
// 3. Return the result of creating a Response object, given
|
|
242
245
|
// clonedResponse, this’s headers’s guard, and this’s relevant Realm.
|
|
243
|
-
return fromInnerResponse(clonedResponse, getHeadersGuard(this
|
|
246
|
+
return fromInnerResponse(clonedResponse, getHeadersGuard(this.#headers))
|
|
244
247
|
}
|
|
245
248
|
|
|
246
249
|
[nodeUtil.inspect.custom] (depth, options) {
|
|
@@ -264,9 +267,45 @@ class Response {
|
|
|
264
267
|
|
|
265
268
|
return `Response ${nodeUtil.formatWithOptions(options, properties)}`
|
|
266
269
|
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* @param {Response} response
|
|
273
|
+
*/
|
|
274
|
+
static getResponseHeaders (response) {
|
|
275
|
+
return response.#headers
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* @param {Response} response
|
|
280
|
+
* @param {Headers} newHeaders
|
|
281
|
+
*/
|
|
282
|
+
static setResponseHeaders (response, newHeaders) {
|
|
283
|
+
response.#headers = newHeaders
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* @param {Response} response
|
|
288
|
+
*/
|
|
289
|
+
static getResponseState (response) {
|
|
290
|
+
return response.#state
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* @param {Response} response
|
|
295
|
+
* @param {any} newState
|
|
296
|
+
*/
|
|
297
|
+
static setResponseState (response, newState) {
|
|
298
|
+
response.#state = newState
|
|
299
|
+
}
|
|
267
300
|
}
|
|
268
301
|
|
|
269
|
-
|
|
302
|
+
const { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState } = Response
|
|
303
|
+
Reflect.deleteProperty(Response, 'getResponseHeaders')
|
|
304
|
+
Reflect.deleteProperty(Response, 'setResponseHeaders')
|
|
305
|
+
Reflect.deleteProperty(Response, 'getResponseState')
|
|
306
|
+
Reflect.deleteProperty(Response, 'setResponseState')
|
|
307
|
+
|
|
308
|
+
mixinBody(Response, getResponseState)
|
|
270
309
|
|
|
271
310
|
Object.defineProperties(Response.prototype, {
|
|
272
311
|
type: kEnumerableProperty,
|
|
@@ -463,17 +502,17 @@ function initializeResponse (response, init, body) {
|
|
|
463
502
|
|
|
464
503
|
// 3. Set response’s response’s status to init["status"].
|
|
465
504
|
if ('status' in init && init.status != null) {
|
|
466
|
-
response
|
|
505
|
+
getResponseState(response).status = init.status
|
|
467
506
|
}
|
|
468
507
|
|
|
469
508
|
// 4. Set response’s response’s status message to init["statusText"].
|
|
470
509
|
if ('statusText' in init && init.statusText != null) {
|
|
471
|
-
response
|
|
510
|
+
getResponseState(response).statusText = init.statusText
|
|
472
511
|
}
|
|
473
512
|
|
|
474
513
|
// 5. If init["headers"] exists, then fill response’s headers with init["headers"].
|
|
475
514
|
if ('headers' in init && init.headers != null) {
|
|
476
|
-
fill(response
|
|
515
|
+
fill(getResponseHeaders(response), init.headers)
|
|
477
516
|
}
|
|
478
517
|
|
|
479
518
|
// 6. If body was given, then:
|
|
@@ -487,12 +526,12 @@ function initializeResponse (response, init, body) {
|
|
|
487
526
|
}
|
|
488
527
|
|
|
489
528
|
// 2. Set response's body to body's body.
|
|
490
|
-
response
|
|
529
|
+
getResponseState(response).body = body.body
|
|
491
530
|
|
|
492
531
|
// 3. If body's type is non-null and response's header list does not contain
|
|
493
532
|
// `Content-Type`, then append (`Content-Type`, body's type) to response's header list.
|
|
494
|
-
if (body.type != null && !response
|
|
495
|
-
response
|
|
533
|
+
if (body.type != null && !getResponseState(response).headersList.contains('content-type', true)) {
|
|
534
|
+
getResponseState(response).headersList.append('content-type', body.type, true)
|
|
496
535
|
}
|
|
497
536
|
}
|
|
498
537
|
}
|
|
@@ -505,10 +544,11 @@ function initializeResponse (response, init, body) {
|
|
|
505
544
|
*/
|
|
506
545
|
function fromInnerResponse (innerResponse, guard) {
|
|
507
546
|
const response = new Response(kConstruct)
|
|
508
|
-
response
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
547
|
+
setResponseState(response, innerResponse)
|
|
548
|
+
const headers = new Headers(kConstruct)
|
|
549
|
+
setResponseHeaders(response, headers)
|
|
550
|
+
setHeadersList(headers, innerResponse.headersList)
|
|
551
|
+
setHeadersGuard(headers, guard)
|
|
512
552
|
|
|
513
553
|
if (hasFinalizationRegistry && innerResponse.body?.stream) {
|
|
514
554
|
// If the target (response) is reclaimed, the cleanup callback may be called at some point with
|
|
@@ -528,7 +568,7 @@ webidl.converters.XMLHttpRequestBodyInit = function (V, prefix, name) {
|
|
|
528
568
|
return webidl.converters.USVString(V, prefix, name)
|
|
529
569
|
}
|
|
530
570
|
|
|
531
|
-
if (V
|
|
571
|
+
if (webidl.is.Blob(V)) {
|
|
532
572
|
return V
|
|
533
573
|
}
|
|
534
574
|
|
|
@@ -536,11 +576,11 @@ webidl.converters.XMLHttpRequestBodyInit = function (V, prefix, name) {
|
|
|
536
576
|
return V
|
|
537
577
|
}
|
|
538
578
|
|
|
539
|
-
if (V
|
|
579
|
+
if (webidl.is.FormData(V)) {
|
|
540
580
|
return V
|
|
541
581
|
}
|
|
542
582
|
|
|
543
|
-
if (V
|
|
583
|
+
if (webidl.is.URLSearchParams(V)) {
|
|
544
584
|
return V
|
|
545
585
|
}
|
|
546
586
|
|
|
@@ -549,7 +589,7 @@ webidl.converters.XMLHttpRequestBodyInit = function (V, prefix, name) {
|
|
|
549
589
|
|
|
550
590
|
// https://fetch.spec.whatwg.org/#bodyinit
|
|
551
591
|
webidl.converters.BodyInit = function (V, prefix, argument) {
|
|
552
|
-
if (V
|
|
592
|
+
if (webidl.is.ReadableStream(V)) {
|
|
553
593
|
return V
|
|
554
594
|
}
|
|
555
595
|
|
|
@@ -579,6 +619,8 @@ webidl.converters.ResponseInit = webidl.dictionaryConverter([
|
|
|
579
619
|
}
|
|
580
620
|
])
|
|
581
621
|
|
|
622
|
+
webidl.is.Response = webidl.util.MakeTypeAssertion(Response.prototype)
|
|
623
|
+
|
|
582
624
|
module.exports = {
|
|
583
625
|
isNetworkError,
|
|
584
626
|
makeNetworkError,
|
|
@@ -587,5 +629,6 @@ module.exports = {
|
|
|
587
629
|
filterResponse,
|
|
588
630
|
Response,
|
|
589
631
|
cloneResponse,
|
|
590
|
-
fromInnerResponse
|
|
632
|
+
fromInnerResponse,
|
|
633
|
+
getResponseState
|
|
591
634
|
}
|
package/lib/web/fetch/util.js
CHANGED
|
@@ -399,7 +399,7 @@ function determineRequestsReferrer (request) {
|
|
|
399
399
|
|
|
400
400
|
// note: we need to clone it as it's mutated
|
|
401
401
|
referrerSource = new URL(globalOrigin)
|
|
402
|
-
} else if (request.referrer
|
|
402
|
+
} else if (webidl.is.URL(request.referrer)) {
|
|
403
403
|
// Let referrerSource be request’s referrer.
|
|
404
404
|
referrerSource = request.referrer
|
|
405
405
|
}
|
|
@@ -418,18 +418,37 @@ function determineRequestsReferrer (request) {
|
|
|
418
418
|
referrerURL = referrerOrigin
|
|
419
419
|
}
|
|
420
420
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
421
|
+
// 7. The user agent MAY alter referrerURL or referrerOrigin at this point
|
|
422
|
+
// to enforce arbitrary policy considerations in the interests of minimizing
|
|
423
|
+
// data leakage. For example, the user agent could strip the URL down to an
|
|
424
|
+
// origin, modify its host, replace it with an empty string, etc.
|
|
424
425
|
|
|
425
426
|
// 8. Execute the switch statements corresponding to the value of policy:
|
|
426
427
|
switch (policy) {
|
|
427
|
-
case '
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
428
|
+
case 'no-referrer':
|
|
429
|
+
// Return no referrer
|
|
430
|
+
return 'no-referrer'
|
|
431
|
+
case 'origin':
|
|
432
|
+
// Return referrerOrigin
|
|
433
|
+
if (referrerOrigin != null) {
|
|
434
|
+
return referrerOrigin
|
|
435
|
+
}
|
|
436
|
+
return stripURLForReferrer(referrerSource, true)
|
|
437
|
+
case 'unsafe-url':
|
|
438
|
+
// Return referrerURL.
|
|
439
|
+
return referrerURL
|
|
440
|
+
case 'strict-origin': {
|
|
441
|
+
const currentURL = requestCurrentURL(request)
|
|
442
|
+
|
|
443
|
+
// 1. If referrerURL is a potentially trustworthy URL and request’s
|
|
444
|
+
// current URL is not a potentially trustworthy URL, then return no
|
|
445
|
+
// referrer.
|
|
446
|
+
if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) {
|
|
447
|
+
return 'no-referrer'
|
|
448
|
+
}
|
|
449
|
+
// 2. Return referrerOrigin
|
|
450
|
+
return referrerOrigin
|
|
451
|
+
}
|
|
433
452
|
case 'strict-origin-when-cross-origin': {
|
|
434
453
|
const currentURL = requestCurrentURL(request)
|
|
435
454
|
|
|
@@ -449,23 +468,34 @@ function determineRequestsReferrer (request) {
|
|
|
449
468
|
// 3. Return referrerOrigin.
|
|
450
469
|
return referrerOrigin
|
|
451
470
|
}
|
|
452
|
-
case '
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
471
|
+
case 'same-origin':
|
|
472
|
+
// 1. If the origin of referrerURL and the origin of request’s current
|
|
473
|
+
// URL are the same, then return referrerURL.
|
|
474
|
+
if (sameOrigin(request, referrerURL)) {
|
|
475
|
+
return referrerURL
|
|
476
|
+
}
|
|
477
|
+
// 2. Return no referrer.
|
|
478
|
+
return 'no-referrer'
|
|
479
|
+
case 'origin-when-cross-origin':
|
|
480
|
+
// 1. If the origin of referrerURL and the origin of request’s current
|
|
481
|
+
// URL are the same, then return referrerURL.
|
|
482
|
+
if (sameOrigin(request, referrerURL)) {
|
|
483
|
+
return referrerURL
|
|
484
|
+
}
|
|
485
|
+
// 2. Return referrerOrigin.
|
|
486
|
+
return referrerOrigin
|
|
487
|
+
case 'no-referrer-when-downgrade': {
|
|
488
|
+
const currentURL = requestCurrentURL(request)
|
|
489
|
+
|
|
490
|
+
// 1. If referrerURL is a potentially trustworthy URL and request’s
|
|
491
|
+
// current URL is not a potentially trustworthy URL, then return no
|
|
492
|
+
// referrer.
|
|
493
|
+
if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) {
|
|
494
|
+
return 'no-referrer'
|
|
495
|
+
}
|
|
496
|
+
// 2. Return referrerOrigin
|
|
497
|
+
return referrerOrigin
|
|
498
|
+
}
|
|
469
499
|
}
|
|
470
500
|
}
|
|
471
501
|
|
|
@@ -476,7 +506,7 @@ function determineRequestsReferrer (request) {
|
|
|
476
506
|
*/
|
|
477
507
|
function stripURLForReferrer (url, originOnly) {
|
|
478
508
|
// 1. Assert: url is a URL.
|
|
479
|
-
assert(url
|
|
509
|
+
assert(webidl.is.URL(url))
|
|
480
510
|
|
|
481
511
|
url = new URL(url)
|
|
482
512
|
|
|
@@ -508,7 +538,7 @@ function stripURLForReferrer (url, originOnly) {
|
|
|
508
538
|
}
|
|
509
539
|
|
|
510
540
|
function isURLPotentiallyTrustworthy (url) {
|
|
511
|
-
if (!(url
|
|
541
|
+
if (!webidl.is.URL(url)) {
|
|
512
542
|
return false
|
|
513
543
|
}
|
|
514
544
|
|
|
@@ -825,7 +855,7 @@ const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbo
|
|
|
825
855
|
/**
|
|
826
856
|
* @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object
|
|
827
857
|
* @param {string} name name of the instance
|
|
828
|
-
* @param {
|
|
858
|
+
* @param {((target: any) => any)} kInternalIterator
|
|
829
859
|
* @param {string | number} [keyIndex]
|
|
830
860
|
* @param {string | number} [valueIndex]
|
|
831
861
|
*/
|
|
@@ -867,7 +897,7 @@ function createIterator (name, kInternalIterator, keyIndex = 0, valueIndex = 1)
|
|
|
867
897
|
// 7. Let kind be object’s kind.
|
|
868
898
|
// 8. Let values be object’s target's value pairs to iterate over.
|
|
869
899
|
const index = this.#index
|
|
870
|
-
const values = this.#target
|
|
900
|
+
const values = kInternalIterator(this.#target)
|
|
871
901
|
|
|
872
902
|
// 9. Let len be the length of values.
|
|
873
903
|
const len = values.length
|
|
@@ -961,7 +991,7 @@ function createIterator (name, kInternalIterator, keyIndex = 0, valueIndex = 1)
|
|
|
961
991
|
* @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object
|
|
962
992
|
* @param {string} name name of the instance
|
|
963
993
|
* @param {any} object class
|
|
964
|
-
* @param {
|
|
994
|
+
* @param {(target: any) => any} kInternalIterator
|
|
965
995
|
* @param {string | number} [keyIndex]
|
|
966
996
|
* @param {string | number} [valueIndex]
|
|
967
997
|
*/
|
|
@@ -1029,7 +1059,7 @@ function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueInde
|
|
|
1029
1059
|
/**
|
|
1030
1060
|
* @see https://fetch.spec.whatwg.org/#body-fully-read
|
|
1031
1061
|
*/
|
|
1032
|
-
|
|
1062
|
+
function fullyReadBody (body, processBody, processBodyError) {
|
|
1033
1063
|
// 1. If taskDestination is null, then set taskDestination to
|
|
1034
1064
|
// the result of starting a new parallel queue.
|
|
1035
1065
|
|
|
@@ -1054,11 +1084,7 @@ async function fullyReadBody (body, processBody, processBodyError) {
|
|
|
1054
1084
|
}
|
|
1055
1085
|
|
|
1056
1086
|
// 5. Read all bytes from reader, given successSteps and errorSteps.
|
|
1057
|
-
|
|
1058
|
-
successSteps(await readAllBytes(reader))
|
|
1059
|
-
} catch (e) {
|
|
1060
|
-
errorSteps(e)
|
|
1061
|
-
}
|
|
1087
|
+
readAllBytes(reader, successSteps, errorSteps)
|
|
1062
1088
|
}
|
|
1063
1089
|
|
|
1064
1090
|
/**
|
|
@@ -1096,30 +1122,39 @@ function isomorphicEncode (input) {
|
|
|
1096
1122
|
* @see https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes
|
|
1097
1123
|
* @see https://streams.spec.whatwg.org/#read-loop
|
|
1098
1124
|
* @param {ReadableStreamDefaultReader} reader
|
|
1125
|
+
* @param {(bytes: Uint8Array) => void} successSteps
|
|
1126
|
+
* @param {(error: Error) => void} failureSteps
|
|
1099
1127
|
*/
|
|
1100
|
-
async function readAllBytes (reader) {
|
|
1128
|
+
async function readAllBytes (reader, successSteps, failureSteps) {
|
|
1101
1129
|
const bytes = []
|
|
1102
1130
|
let byteLength = 0
|
|
1103
1131
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1132
|
+
try {
|
|
1133
|
+
do {
|
|
1134
|
+
const { done, value: chunk } = await reader.read()
|
|
1106
1135
|
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1136
|
+
if (done) {
|
|
1137
|
+
// 1. Call successSteps with bytes.
|
|
1138
|
+
successSteps(Buffer.concat(bytes, byteLength))
|
|
1139
|
+
return
|
|
1140
|
+
}
|
|
1111
1141
|
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1142
|
+
// 1. If chunk is not a Uint8Array object, call failureSteps
|
|
1143
|
+
// with a TypeError and abort these steps.
|
|
1144
|
+
if (!isUint8Array(chunk)) {
|
|
1145
|
+
failureSteps(TypeError('Received non-Uint8Array chunk'))
|
|
1146
|
+
return
|
|
1147
|
+
}
|
|
1117
1148
|
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1149
|
+
// 2. Append the bytes represented by chunk to bytes.
|
|
1150
|
+
bytes.push(chunk)
|
|
1151
|
+
byteLength += chunk.length
|
|
1121
1152
|
|
|
1122
1153
|
// 3. Read-loop given reader, bytes, successSteps, and failureSteps.
|
|
1154
|
+
} while (true)
|
|
1155
|
+
} catch (e) {
|
|
1156
|
+
// 1. Call failureSteps with e.
|
|
1157
|
+
failureSteps(e)
|
|
1123
1158
|
}
|
|
1124
1159
|
}
|
|
1125
1160
|
|
|
@@ -1333,6 +1368,14 @@ function buildContentRange (rangeStart, rangeEnd, fullLength) {
|
|
|
1333
1368
|
// interpreted as a zlib stream, otherwise it's interpreted as a
|
|
1334
1369
|
// raw deflate stream.
|
|
1335
1370
|
class InflateStream extends Transform {
|
|
1371
|
+
#zlibOptions
|
|
1372
|
+
|
|
1373
|
+
/** @param {zlib.ZlibOptions} [zlibOptions] */
|
|
1374
|
+
constructor (zlibOptions) {
|
|
1375
|
+
super()
|
|
1376
|
+
this.#zlibOptions = zlibOptions
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1336
1379
|
_transform (chunk, encoding, callback) {
|
|
1337
1380
|
if (!this._inflateStream) {
|
|
1338
1381
|
if (chunk.length === 0) {
|
|
@@ -1340,8 +1383,8 @@ class InflateStream extends Transform {
|
|
|
1340
1383
|
return
|
|
1341
1384
|
}
|
|
1342
1385
|
this._inflateStream = (chunk[0] & 0x0F) === 0x08
|
|
1343
|
-
? zlib.createInflate()
|
|
1344
|
-
: zlib.createInflateRaw()
|
|
1386
|
+
? zlib.createInflate(this.#zlibOptions)
|
|
1387
|
+
: zlib.createInflateRaw(this.#zlibOptions)
|
|
1345
1388
|
|
|
1346
1389
|
this._inflateStream.on('data', this.push.bind(this))
|
|
1347
1390
|
this._inflateStream.on('end', () => this.push(null))
|
|
@@ -1360,8 +1403,12 @@ class InflateStream extends Transform {
|
|
|
1360
1403
|
}
|
|
1361
1404
|
}
|
|
1362
1405
|
|
|
1363
|
-
|
|
1364
|
-
|
|
1406
|
+
/**
|
|
1407
|
+
* @param {zlib.ZlibOptions} [zlibOptions]
|
|
1408
|
+
* @returns {InflateStream}
|
|
1409
|
+
*/
|
|
1410
|
+
function createInflate (zlibOptions) {
|
|
1411
|
+
return new InflateStream(zlibOptions)
|
|
1365
1412
|
}
|
|
1366
1413
|
|
|
1367
1414
|
/**
|
package/lib/web/fetch/webidl.js
CHANGED
|
@@ -13,10 +13,12 @@ const NULL = 7
|
|
|
13
13
|
const OBJECT = 8 // function and object
|
|
14
14
|
|
|
15
15
|
/** @type {import('../../../types/webidl').Webidl} */
|
|
16
|
-
const webidl = {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
const webidl = {
|
|
17
|
+
converters: {},
|
|
18
|
+
util: {},
|
|
19
|
+
errors: {},
|
|
20
|
+
is: {}
|
|
21
|
+
}
|
|
20
22
|
|
|
21
23
|
webidl.errors.exception = function (message) {
|
|
22
24
|
return new TypeError(`${message.header}: ${message.message}`)
|
|
@@ -43,18 +45,22 @@ webidl.errors.invalidArgument = function (context) {
|
|
|
43
45
|
|
|
44
46
|
// https://webidl.spec.whatwg.org/#implements
|
|
45
47
|
webidl.brandCheck = function (V, I) {
|
|
46
|
-
if (!(V
|
|
48
|
+
if (!I.prototype.isPrototypeOf(V)) { // eslint-disable-line no-prototype-builtins
|
|
47
49
|
const err = new TypeError('Illegal invocation')
|
|
48
50
|
err.code = 'ERR_INVALID_THIS' // node compat.
|
|
49
51
|
throw err
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
webidl.brandCheckMultiple = function (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
webidl.brandCheckMultiple = function (List) {
|
|
56
|
+
const prototypes = List.map((c) => webidl.util.MakeTypeAssertion(c.prototype))
|
|
57
|
+
|
|
58
|
+
return (V) => {
|
|
59
|
+
if (prototypes.every(typeCheck => !typeCheck(V))) {
|
|
60
|
+
const err = new TypeError('Illegal invocation')
|
|
61
|
+
err.code = 'ERR_INVALID_THIS' // node compat.
|
|
62
|
+
throw err
|
|
63
|
+
}
|
|
58
64
|
}
|
|
59
65
|
}
|
|
60
66
|
|
|
@@ -75,6 +81,11 @@ webidl.illegalConstructor = function () {
|
|
|
75
81
|
})
|
|
76
82
|
}
|
|
77
83
|
|
|
84
|
+
const isPrototypeOf = Object.prototype.isPrototypeOf
|
|
85
|
+
webidl.util.MakeTypeAssertion = function (Prototype) {
|
|
86
|
+
return (O) => isPrototypeOf.call(Prototype, O)
|
|
87
|
+
}
|
|
88
|
+
|
|
78
89
|
// https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values
|
|
79
90
|
webidl.util.Type = function (V) {
|
|
80
91
|
switch (typeof V) {
|
|
@@ -372,12 +383,12 @@ webidl.recordConverter = function (keyConverter, valueConverter) {
|
|
|
372
383
|
}
|
|
373
384
|
}
|
|
374
385
|
|
|
375
|
-
webidl.interfaceConverter = function (
|
|
386
|
+
webidl.interfaceConverter = function (TypeCheck, name) {
|
|
376
387
|
return (V, prefix, argument) => {
|
|
377
|
-
if (!(V
|
|
388
|
+
if (!TypeCheck(V)) {
|
|
378
389
|
throw webidl.errors.exception({
|
|
379
390
|
header: prefix,
|
|
380
|
-
message: `Expected ${argument} ("${webidl.util.Stringify(V)}") to be an instance of ${
|
|
391
|
+
message: `Expected ${argument} ("${webidl.util.Stringify(V)}") to be an instance of ${name}.`
|
|
381
392
|
})
|
|
382
393
|
}
|
|
383
394
|
|
|
@@ -451,6 +462,14 @@ webidl.nullableConverter = function (converter) {
|
|
|
451
462
|
}
|
|
452
463
|
}
|
|
453
464
|
|
|
465
|
+
webidl.is.ReadableStream = webidl.util.MakeTypeAssertion(ReadableStream.prototype)
|
|
466
|
+
webidl.is.Blob = webidl.util.MakeTypeAssertion(Blob.prototype)
|
|
467
|
+
webidl.is.URLSearchParams = webidl.util.MakeTypeAssertion(URLSearchParams.prototype)
|
|
468
|
+
webidl.is.File = webidl.util.MakeTypeAssertion((globalThis.File ?? require('node:buffer').File).prototype)
|
|
469
|
+
webidl.is.URL = webidl.util.MakeTypeAssertion(URL.prototype)
|
|
470
|
+
webidl.is.AbortSignal = webidl.util.MakeTypeAssertion(AbortSignal.prototype)
|
|
471
|
+
webidl.is.MessagePort = webidl.util.MakeTypeAssertion(MessagePort.prototype)
|
|
472
|
+
|
|
454
473
|
// https://webidl.spec.whatwg.org/#es-DOMString
|
|
455
474
|
webidl.converters.DOMString = function (V, prefix, argument, opts) {
|
|
456
475
|
// 1. If V is null and the conversion is to an IDL type
|
|
@@ -697,7 +716,12 @@ webidl.converters['record<ByteString, ByteString>'] = webidl.recordConverter(
|
|
|
697
716
|
webidl.converters.ByteString
|
|
698
717
|
)
|
|
699
718
|
|
|
700
|
-
webidl.converters.Blob = webidl.interfaceConverter(Blob)
|
|
719
|
+
webidl.converters.Blob = webidl.interfaceConverter(webidl.is.Blob, 'Blob')
|
|
720
|
+
|
|
721
|
+
webidl.converters.AbortSignal = webidl.interfaceConverter(
|
|
722
|
+
webidl.is.AbortSignal,
|
|
723
|
+
'AbortSignal'
|
|
724
|
+
)
|
|
701
725
|
|
|
702
726
|
module.exports = {
|
|
703
727
|
webidl
|