undici 6.5.0 → 6.6.1

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.
Files changed (54) hide show
  1. package/docs/best-practices/client-certificate.md +3 -3
  2. package/lib/agent.js +5 -7
  3. package/lib/api/api-connect.js +2 -2
  4. package/lib/api/api-pipeline.js +4 -4
  5. package/lib/api/api-request.js +2 -2
  6. package/lib/api/api-stream.js +4 -4
  7. package/lib/api/api-upgrade.js +3 -3
  8. package/lib/api/readable.js +2 -2
  9. package/lib/api/util.js +1 -1
  10. package/lib/balanced-pool.js +1 -1
  11. package/lib/cache/cache.js +4 -10
  12. package/lib/cache/util.js +1 -1
  13. package/lib/client.js +14 -14
  14. package/lib/cookies/parse.js +1 -1
  15. package/lib/cookies/util.js +1 -1
  16. package/lib/core/connect.js +3 -3
  17. package/lib/core/diagnostics.js +2 -2
  18. package/lib/core/request.js +18 -13
  19. package/lib/core/tree.js +3 -5
  20. package/lib/core/util.js +15 -15
  21. package/lib/dispatcher.js +1 -1
  22. package/lib/eventsource/eventsource-stream.js +1 -1
  23. package/lib/eventsource/eventsource.js +2 -2
  24. package/lib/eventsource/util.js +9 -1
  25. package/lib/fetch/body.js +29 -21
  26. package/lib/fetch/dataURL.js +97 -17
  27. package/lib/fetch/file.js +5 -5
  28. package/lib/fetch/formdata.js +24 -9
  29. package/lib/fetch/headers.js +11 -26
  30. package/lib/fetch/index.js +37 -40
  31. package/lib/fetch/request.js +3 -2
  32. package/lib/fetch/response.js +31 -39
  33. package/lib/fetch/util.js +258 -96
  34. package/lib/fetch/webidl.js +1 -1
  35. package/lib/fileapi/util.js +2 -2
  36. package/lib/handler/RedirectHandler.js +2 -2
  37. package/lib/handler/RetryHandler.js +3 -3
  38. package/lib/llhttp/llhttp-wasm.js +3 -1
  39. package/lib/llhttp/llhttp_simd-wasm.js +3 -1
  40. package/lib/mock/mock-agent.js +2 -2
  41. package/lib/mock/mock-client.js +1 -1
  42. package/lib/mock/mock-pool.js +1 -1
  43. package/lib/mock/mock-utils.js +2 -2
  44. package/lib/mock/pending-interceptors-formatter.js +2 -2
  45. package/lib/pool.js +7 -8
  46. package/lib/proxy-agent.js +2 -2
  47. package/lib/timers.js +1 -1
  48. package/lib/websocket/connection.js +1 -1
  49. package/lib/websocket/events.js +1 -1
  50. package/lib/websocket/frame.js +1 -1
  51. package/lib/websocket/receiver.js +7 -6
  52. package/lib/websocket/util.js +1 -1
  53. package/lib/websocket/websocket.js +1 -1
  54. package/package.json +5 -8
@@ -23,8 +23,8 @@ const { FormData } = require('./formdata')
23
23
  const { getGlobalOrigin } = require('./global')
24
24
  const { URLSerializer } = require('./dataURL')
25
25
  const { kHeadersList, kConstruct } = require('../core/symbols')
26
- const assert = require('assert')
27
- const { types } = require('util')
26
+ const assert = require('node:assert')
27
+ const { types } = require('node:util')
28
28
 
29
29
  const textEncoder = new TextEncoder('utf-8')
30
30
 
@@ -38,13 +38,8 @@ class Response {
38
38
  // The static error() method steps are to return the result of creating a
39
39
  // Response object, given a new network error, "immutable", and this’s
40
40
  // relevant Realm.
41
- const responseObject = new Response(kConstruct)
42
- responseObject[kState] = makeNetworkError()
43
- responseObject[kRealm] = relevantRealm
44
- responseObject[kHeaders] = new Headers(kConstruct)
45
- responseObject[kHeaders][kHeadersList] = responseObject[kState].headersList
46
- responseObject[kHeaders][kGuard] = 'immutable'
47
- responseObject[kHeaders][kRealm] = relevantRealm
41
+ const responseObject = fromInnerResponse(makeNetworkError(), 'immutable', relevantRealm)
42
+
48
43
  return responseObject
49
44
  }
50
45
 
@@ -67,13 +62,7 @@ class Response {
67
62
  // 3. Let responseObject be the result of creating a Response object, given a new response,
68
63
  // "response", and this’s relevant Realm.
69
64
  const relevantRealm = { settingsObject: {} }
70
- const responseObject = new Response(kConstruct)
71
- responseObject[kState] = makeResponse({})
72
- responseObject[kRealm] = relevantRealm
73
- responseObject[kHeaders] = new Headers(kConstruct)
74
- responseObject[kHeaders][kHeadersList] = responseObject[kState].headersList
75
- responseObject[kHeaders][kGuard] = 'response'
76
- responseObject[kHeaders][kRealm] = relevantRealm
65
+ const responseObject = fromInnerResponse(makeResponse({}), 'response', relevantRealm)
77
66
 
78
67
  // 4. Perform initialize a response given responseObject, init, and (body, "application/json").
79
68
  initializeResponse(responseObject, init, { body: body[0], type: 'application/json' })
@@ -99,25 +88,17 @@ class Response {
99
88
  try {
100
89
  parsedURL = new URL(url, getGlobalOrigin())
101
90
  } catch (err) {
102
- throw Object.assign(new TypeError('Failed to parse URL from ' + url), {
103
- cause: err
104
- })
91
+ throw new TypeError(`Failed to parse URL from ${url}`, { cause: err })
105
92
  }
106
93
 
107
94
  // 3. If status is not a redirect status, then throw a RangeError.
108
95
  if (!redirectStatusSet.has(status)) {
109
- throw new RangeError('Invalid status code ' + status)
96
+ throw new RangeError(`Invalid status code ${status}`)
110
97
  }
111
98
 
112
99
  // 4. Let responseObject be the result of creating a Response object,
113
100
  // given a new response, "immutable", and this’s relevant Realm.
114
- const responseObject = new Response(kConstruct)
115
- responseObject[kState] = makeResponse({})
116
- responseObject[kRealm] = relevantRealm
117
- responseObject[kHeaders] = new Headers(kConstruct)
118
- responseObject[kHeaders][kHeadersList] = responseObject[kState].headersList
119
- responseObject[kHeaders][kGuard] = 'immutable'
120
- responseObject[kHeaders][kRealm] = relevantRealm
101
+ const responseObject = fromInnerResponse(makeResponse({}), 'immutable', relevantRealm)
121
102
 
122
103
  // 5. Set responseObject’s response’s status to status.
123
104
  responseObject[kState].status = status
@@ -257,7 +238,7 @@ class Response {
257
238
  webidl.brandCheck(this, Response)
258
239
 
259
240
  // 1. If this is unusable, then throw a TypeError.
260
- if (this.bodyUsed || (this.body && this.body.locked)) {
241
+ if (this.bodyUsed || this.body?.locked) {
261
242
  throw webidl.errors.exception({
262
243
  header: 'Response.clone',
263
244
  message: 'Body has already been consumed.'
@@ -269,15 +250,7 @@ class Response {
269
250
 
270
251
  // 3. Return the result of creating a Response object, given
271
252
  // clonedResponse, this’s headers’s guard, and this’s relevant Realm.
272
- const clonedResponseObject = new Response(kConstruct)
273
- clonedResponseObject[kState] = clonedResponse
274
- clonedResponseObject[kRealm] = this[kRealm]
275
- clonedResponseObject[kHeaders] = new Headers(kConstruct)
276
- clonedResponseObject[kHeaders][kHeadersList] = clonedResponse.headersList
277
- clonedResponseObject[kHeaders][kGuard] = this[kHeaders][kGuard]
278
- clonedResponseObject[kHeaders][kRealm] = this[kHeaders][kRealm]
279
-
280
- return clonedResponseObject
253
+ return fromInnerResponse(clonedResponse, this[kHeaders][kGuard], this[kRealm])
281
254
  }
282
255
  }
283
256
 
@@ -497,7 +470,7 @@ function initializeResponse (response, init, body) {
497
470
  if (nullBodyStatus.includes(response.status)) {
498
471
  throw webidl.errors.exception({
499
472
  header: 'Response constructor',
500
- message: 'Invalid response status code ' + response.status
473
+ message: `Invalid response status code ${response.status}`
501
474
  })
502
475
  }
503
476
 
@@ -512,6 +485,24 @@ function initializeResponse (response, init, body) {
512
485
  }
513
486
  }
514
487
 
488
+ /**
489
+ * @see https://fetch.spec.whatwg.org/#response-create
490
+ * @param {any} innerResponse
491
+ * @param {'request' | 'immutable' | 'request-no-cors' | 'response' | 'none'} guard
492
+ * @param {any} [realm]
493
+ * @returns {Response}
494
+ */
495
+ function fromInnerResponse (innerResponse, guard, realm) {
496
+ const response = new Response(kConstruct)
497
+ response[kState] = innerResponse
498
+ response[kRealm] = realm
499
+ response[kHeaders] = new Headers(kConstruct)
500
+ response[kHeaders][kHeadersList] = innerResponse.headersList
501
+ response[kHeaders][kGuard] = guard
502
+ response[kHeaders][kRealm] = realm
503
+ return response
504
+ }
505
+
515
506
  webidl.converters.ReadableStream = webidl.interfaceConverter(
516
507
  ReadableStream
517
508
  )
@@ -588,5 +579,6 @@ module.exports = {
588
579
  makeAppropriateNetworkError,
589
580
  filterResponse,
590
581
  Response,
591
- cloneResponse
582
+ cloneResponse,
583
+ fromInnerResponse
592
584
  }
package/lib/fetch/util.js CHANGED
@@ -1,10 +1,13 @@
1
1
  'use strict'
2
2
 
3
+ const { Transform } = require('node:stream')
4
+ const zlib = require('node:zlib')
3
5
  const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = require('./constants')
4
6
  const { getGlobalOrigin } = require('./global')
5
- const { performance } = require('perf_hooks')
7
+ const { collectASequenceOfCodePoints, collectAnHTTPQuotedString, removeChars, parseMIMEType } = require('./dataURL')
8
+ const { performance } = require('node:perf_hooks')
6
9
  const { isBlobLike, toUSVString, ReadableStreamFrom, isValidHTTPToken } = require('../core/util')
7
- const assert = require('assert')
10
+ const assert = require('node:assert')
8
11
  const { isUint8Array } = require('util/types')
9
12
 
10
13
  // https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable
@@ -12,7 +15,7 @@ const { isUint8Array } = require('util/types')
12
15
  let crypto
13
16
 
14
17
  try {
15
- crypto = require('crypto')
18
+ crypto = require('node:crypto')
16
19
  } catch {
17
20
 
18
21
  }
@@ -272,7 +275,7 @@ function coarsenTime (timestamp, crossOriginIsolatedCapability) {
272
275
  }
273
276
 
274
277
  // https://fetch.spec.whatwg.org/#clamp-and-coarsen-connection-timing-info
275
- function clampAndCoursenConnectionTimingInfo (connectionTimingInfo, defaultStartTime, crossOriginIsolatedCapability) {
278
+ function clampAndCoarsenConnectionTimingInfo (connectionTimingInfo, defaultStartTime, crossOriginIsolatedCapability) {
276
279
  if (!connectionTimingInfo?.startTime || connectionTimingInfo.startTime < defaultStartTime) {
277
280
  return {
278
281
  domainLookupStartTime: defaultStartTime,
@@ -736,19 +739,23 @@ const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbo
736
739
 
737
740
  /**
738
741
  * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object
739
- * @param {() => unknown[]} iterator
742
+ * @param {() => unknown} iterator
740
743
  * @param {string} name name of the instance
741
744
  * @param {'key'|'value'|'key+value'} kind
745
+ * @param {string | number} [keyIndex]
746
+ * @param {string | number} [valueIndex]
742
747
  */
743
- function makeIterator (iterator, name, kind) {
748
+ function makeIterator (iterator, name, kind, keyIndex = 0, valueIndex = 1) {
744
749
  const object = {
745
750
  index: 0,
746
751
  kind,
747
752
  target: iterator
748
753
  }
754
+ // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%.
755
+ const iteratorObject = Object.create(esIteratorPrototype)
749
756
 
750
- const i = {
751
- next () {
757
+ Object.defineProperty(iteratorObject, 'next', {
758
+ value: function next () {
752
759
  // 1. Let interface be the interface for which the iterator prototype object exists.
753
760
 
754
761
  // 2. Let thisValue be the this value.
@@ -760,7 +767,7 @@ function makeIterator (iterator, name, kind) {
760
767
 
761
768
  // 5. If object is not a default iterator object for interface,
762
769
  // then throw a TypeError.
763
- if (Object.getPrototypeOf(this) !== i) {
770
+ if (Object.getPrototypeOf(this) !== iteratorObject) {
764
771
  throw new TypeError(
765
772
  `'next' called on an object that does not implement interface ${name} Iterator.`
766
773
  )
@@ -780,68 +787,66 @@ function makeIterator (iterator, name, kind) {
780
787
  if (index >= len) {
781
788
  return { value: undefined, done: true }
782
789
  }
783
-
784
790
  // 11. Let pair be the entry in values at index index.
785
- const pair = values[index]
786
-
791
+ const { [keyIndex]: key, [valueIndex]: value } = values[index]
787
792
  // 12. Set object’s index to index + 1.
788
793
  object.index = index + 1
789
-
790
794
  // 13. Return the iterator result for pair and kind.
791
- return iteratorResult(pair, kind)
795
+ // https://webidl.spec.whatwg.org/#iterator-result
796
+ // 1. Let result be a value determined by the value of kind:
797
+ let result
798
+ switch (kind) {
799
+ case 'key':
800
+ // 1. Let idlKey be pair’s key.
801
+ // 2. Let key be the result of converting idlKey to an
802
+ // ECMAScript value.
803
+ // 3. result is key.
804
+ result = key
805
+ break
806
+ case 'value':
807
+ // 1. Let idlValue be pair’s value.
808
+ // 2. Let value be the result of converting idlValue to
809
+ // an ECMAScript value.
810
+ // 3. result is value.
811
+ result = value
812
+ break
813
+ case 'key+value':
814
+ // 1. Let idlKey be pair’s key.
815
+ // 2. Let idlValue be pair’s value.
816
+ // 3. Let key be the result of converting idlKey to an
817
+ // ECMAScript value.
818
+ // 4. Let value be the result of converting idlValue to
819
+ // an ECMAScript value.
820
+ // 5. Let array be ! ArrayCreate(2).
821
+ // 6. Call ! CreateDataProperty(array, "0", key).
822
+ // 7. Call ! CreateDataProperty(array, "1", value).
823
+ // 8. result is array.
824
+ result = [key, value]
825
+ break
826
+ }
827
+ // 2. Return CreateIterResultObject(result, false).
828
+ return {
829
+ value: result,
830
+ done: false
831
+ }
792
832
  },
793
- // The class string of an iterator prototype object for a given interface is the
794
- // result of concatenating the identifier of the interface and the string " Iterator".
795
- [Symbol.toStringTag]: `${name} Iterator`
796
- }
797
-
798
- // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%.
799
- Object.setPrototypeOf(i, esIteratorPrototype)
800
- // esIteratorPrototype needs to be the prototype of i
801
- // which is the prototype of an empty object. Yes, it's confusing.
802
- return Object.setPrototypeOf({}, i)
803
- }
833
+ writable: true,
834
+ enumerable: true,
835
+ configurable: true
836
+ })
804
837
 
805
- // https://webidl.spec.whatwg.org/#iterator-result
806
- function iteratorResult (pair, kind) {
807
- let result
808
-
809
- // 1. Let result be a value determined by the value of kind:
810
- switch (kind) {
811
- case 'key': {
812
- // 1. Let idlKey be pair’s key.
813
- // 2. Let key be the result of converting idlKey to an
814
- // ECMAScript value.
815
- // 3. result is key.
816
- result = pair[0]
817
- break
818
- }
819
- case 'value': {
820
- // 1. Let idlValue be pair’s value.
821
- // 2. Let value be the result of converting idlValue to
822
- // an ECMAScript value.
823
- // 3. result is value.
824
- result = pair[1]
825
- break
826
- }
827
- case 'key+value': {
828
- // 1. Let idlKey be pair’s key.
829
- // 2. Let idlValue be pair’s value.
830
- // 3. Let key be the result of converting idlKey to an
831
- // ECMAScript value.
832
- // 4. Let value be the result of converting idlValue to
833
- // an ECMAScript value.
834
- // 5. Let array be ! ArrayCreate(2).
835
- // 6. Call ! CreateDataProperty(array, "0", key).
836
- // 7. Call ! CreateDataProperty(array, "1", value).
837
- // 8. result is array.
838
- result = pair
839
- break
840
- }
841
- }
838
+ // The class string of an iterator prototype object for a given interface is the
839
+ // result of concatenating the identifier of the interface and the string " Iterator".
840
+ Object.defineProperty(iteratorObject, Symbol.toStringTag, {
841
+ value: `${name} Iterator`,
842
+ writable: false,
843
+ enumerable: false,
844
+ configurable: true
845
+ })
842
846
 
843
- // 2. Return CreateIterResultObject(result, false).
844
- return { value: result, done: false }
847
+ // esIteratorPrototype needs to be the prototype of iteratorObject
848
+ // which is the prototype of an empty object. Yes, it's confusing.
849
+ return Object.create(iteratorObject)
845
850
  }
846
851
 
847
852
  /**
@@ -887,29 +892,6 @@ function isReadableStreamLike (stream) {
887
892
  )
888
893
  }
889
894
 
890
- /**
891
- * @see https://infra.spec.whatwg.org/#isomorphic-decode
892
- * @param {Uint8Array} input
893
- */
894
- function isomorphicDecode (input) {
895
- // 1. To isomorphic decode a byte sequence input, return a string whose code point
896
- // length is equal to input’s length and whose code points have the same values
897
- // as the values of input’s bytes, in the same order.
898
- const length = input.length
899
- if ((2 << 15) - 1 > length) {
900
- return String.fromCharCode.apply(null, input)
901
- }
902
- let result = ''; let i = 0
903
- let addition = (2 << 15) - 1
904
- while (i < length) {
905
- if (i + addition > length) {
906
- addition = length - i
907
- }
908
- result += String.fromCharCode.apply(null, input.subarray(i, i += addition))
909
- }
910
- return result
911
- }
912
-
913
895
  /**
914
896
  * @param {ReadableStreamController<Uint8Array>} controller
915
897
  */
@@ -1007,18 +989,12 @@ function urlIsHttpHttpsScheme (url) {
1007
989
  return protocol === 'http:' || protocol === 'https:'
1008
990
  }
1009
991
 
1010
- /** @type {import('./dataURL')['collectASequenceOfCodePoints']} */
1011
- let collectASequenceOfCodePoints
1012
-
1013
992
  /**
1014
993
  * @see https://fetch.spec.whatwg.org/#simple-range-header-value
1015
994
  * @param {string} value
1016
995
  * @param {boolean} allowWhitespace
1017
996
  */
1018
997
  function simpleRangeHeaderValue (value, allowWhitespace) {
1019
- // Note: avoid circular require
1020
- collectASequenceOfCodePoints ??= require('./dataURL').collectASequenceOfCodePoints
1021
-
1022
998
  // 1. Let data be the isomorphic decoding of value.
1023
999
  // Note: isomorphic decoding takes a sequence of bytes (ie. a Uint8Array) and turns it into a string,
1024
1000
  // nothing more. We obviously don't need to do that if value is a string already.
@@ -1174,6 +1150,191 @@ function buildContentRange (rangeStart, rangeEnd, fullLength) {
1174
1150
  return contentRange
1175
1151
  }
1176
1152
 
1153
+ // A Stream, which pipes the response to zlib.createInflate() or
1154
+ // zlib.createInflateRaw() depending on the first byte of the Buffer.
1155
+ // If the lower byte of the first byte is 0x08, then the stream is
1156
+ // interpreted as a zlib stream, otherwise it's interpreted as a
1157
+ // raw deflate stream.
1158
+ class InflateStream extends Transform {
1159
+ _transform (chunk, encoding, callback) {
1160
+ if (!this._inflateStream) {
1161
+ if (chunk.length === 0) {
1162
+ callback()
1163
+ return
1164
+ }
1165
+ this._inflateStream = (chunk[0] & 0x0F) === 0x08
1166
+ ? zlib.createInflate()
1167
+ : zlib.createInflateRaw()
1168
+
1169
+ this._inflateStream.on('data', this.push.bind(this))
1170
+ this._inflateStream.on('end', () => this.push(null))
1171
+ this._inflateStream.on('error', (err) => this.destroy(err))
1172
+ }
1173
+
1174
+ this._inflateStream.write(chunk, encoding, callback)
1175
+ }
1176
+
1177
+ _final (callback) {
1178
+ if (this._inflateStream) {
1179
+ this._inflateStream.end()
1180
+ this._inflateStream = null
1181
+ }
1182
+ callback()
1183
+ }
1184
+ }
1185
+
1186
+ function createInflate () {
1187
+ return new InflateStream()
1188
+ }
1189
+
1190
+ /**
1191
+ * @see https://fetch.spec.whatwg.org/#concept-header-extract-mime-type
1192
+ * @param {import('./headers').HeadersList} headers
1193
+ */
1194
+ function extractMimeType (headers) {
1195
+ // 1. Let charset be null.
1196
+ let charset = null
1197
+
1198
+ // 2. Let essence be null.
1199
+ let essence = null
1200
+
1201
+ // 3. Let mimeType be null.
1202
+ let mimeType = null
1203
+
1204
+ // 4. Let values be the result of getting, decoding, and splitting `Content-Type` from headers.
1205
+ const values = getDecodeSplit('content-type', headers)
1206
+
1207
+ // 5. If values is null, then return failure.
1208
+ if (values === null) {
1209
+ return 'failure'
1210
+ }
1211
+
1212
+ // 6. For each value of values:
1213
+ for (const value of values) {
1214
+ // 6.1. Let temporaryMimeType be the result of parsing value.
1215
+ const temporaryMimeType = parseMIMEType(value)
1216
+
1217
+ // 6.2. If temporaryMimeType is failure or its essence is "*/*", then continue.
1218
+ if (temporaryMimeType === 'failure' || temporaryMimeType.essence === '*/*') {
1219
+ continue
1220
+ }
1221
+
1222
+ // 6.3. Set mimeType to temporaryMimeType.
1223
+ mimeType = temporaryMimeType
1224
+
1225
+ // 6.4. If mimeType’s essence is not essence, then:
1226
+ if (mimeType.essence !== essence) {
1227
+ // 6.4.1. Set charset to null.
1228
+ charset = null
1229
+
1230
+ // 6.4.2. If mimeType’s parameters["charset"] exists, then set charset to
1231
+ // mimeType’s parameters["charset"].
1232
+ if (mimeType.parameters.has('charset')) {
1233
+ charset = mimeType.parameters.get('charset')
1234
+ }
1235
+
1236
+ // 6.4.3. Set essence to mimeType’s essence.
1237
+ essence = mimeType.essence
1238
+ } else if (!mimeType.parameters.has('charset') && charset !== null) {
1239
+ // 6.5. Otherwise, if mimeType’s parameters["charset"] does not exist, and
1240
+ // charset is non-null, set mimeType’s parameters["charset"] to charset.
1241
+ mimeType.parameters.set('charset', charset)
1242
+ }
1243
+ }
1244
+
1245
+ // 7. If mimeType is null, then return failure.
1246
+ if (mimeType == null) {
1247
+ return 'failure'
1248
+ }
1249
+
1250
+ // 8. Return mimeType.
1251
+ return mimeType
1252
+ }
1253
+
1254
+ /**
1255
+ * @see https://fetch.spec.whatwg.org/#header-value-get-decode-and-split
1256
+ * @param {string|null} value
1257
+ */
1258
+ function gettingDecodingSplitting (value) {
1259
+ // 1. Let input be the result of isomorphic decoding value.
1260
+ const input = value
1261
+
1262
+ // 2. Let position be a position variable for input, initially pointing at the start of input.
1263
+ const position = { position: 0 }
1264
+
1265
+ // 3. Let values be a list of strings, initially empty.
1266
+ const values = []
1267
+
1268
+ // 4. Let temporaryValue be the empty string.
1269
+ let temporaryValue = ''
1270
+
1271
+ // 5. While position is not past the end of input:
1272
+ while (position.position < input.length) {
1273
+ // 5.1. Append the result of collecting a sequence of code points that are not U+0022 (")
1274
+ // or U+002C (,) from input, given position, to temporaryValue.
1275
+ temporaryValue += collectASequenceOfCodePoints(
1276
+ (char) => char !== '"' && char !== ',',
1277
+ input,
1278
+ position
1279
+ )
1280
+
1281
+ // 5.2. If position is not past the end of input, then:
1282
+ if (position.position < input.length) {
1283
+ // 5.2.1. If the code point at position within input is U+0022 ("), then:
1284
+ if (input.charCodeAt(position.position) === 0x22) {
1285
+ // 5.2.1.1. Append the result of collecting an HTTP quoted string from input, given position, to temporaryValue.
1286
+ temporaryValue += collectAnHTTPQuotedString(
1287
+ input,
1288
+ position
1289
+ )
1290
+
1291
+ // 5.2.1.2. If position is not past the end of input, then continue.
1292
+ if (position.position < input.length) {
1293
+ continue
1294
+ }
1295
+ } else {
1296
+ // 5.2.2. Otherwise:
1297
+
1298
+ // 5.2.2.1. Assert: the code point at position within input is U+002C (,).
1299
+ assert(input.charCodeAt(position.position) === 0x2C)
1300
+
1301
+ // 5.2.2.2. Advance position by 1.
1302
+ position.position++
1303
+ }
1304
+ }
1305
+
1306
+ // 5.3. Remove all HTTP tab or space from the start and end of temporaryValue.
1307
+ temporaryValue = removeChars(temporaryValue, true, true, (char) => char === 0x9 || char === 0x20)
1308
+
1309
+ // 5.4. Append temporaryValue to values.
1310
+ values.push(temporaryValue)
1311
+
1312
+ // 5.6. Set temporaryValue to the empty string.
1313
+ temporaryValue = ''
1314
+ }
1315
+
1316
+ // 6. Return values.
1317
+ return values
1318
+ }
1319
+
1320
+ /**
1321
+ * @see https://fetch.spec.whatwg.org/#concept-header-list-get-decode-split
1322
+ * @param {string} name lowercase header name
1323
+ * @param {import('./headers').HeadersList} list
1324
+ */
1325
+ function getDecodeSplit (name, list) {
1326
+ // 1. Let value be the result of getting name from list.
1327
+ const value = list.get(name, true)
1328
+
1329
+ // 2. If value is null, then return null.
1330
+ if (value === null) {
1331
+ return null
1332
+ }
1333
+
1334
+ // 3. Return the result of getting, decoding, and splitting value.
1335
+ return gettingDecodingSplitting(value)
1336
+ }
1337
+
1177
1338
  module.exports = {
1178
1339
  isAborted,
1179
1340
  isCancelled,
@@ -1181,7 +1342,7 @@ module.exports = {
1181
1342
  ReadableStreamFrom,
1182
1343
  toUSVString,
1183
1344
  tryUpgradeRequestToAPotentiallyTrustworthyURL,
1184
- clampAndCoursenConnectionTimingInfo,
1345
+ clampAndCoarsenConnectionTimingInfo,
1185
1346
  coarsenedSharedCurrentTime,
1186
1347
  determineRequestsReferrer,
1187
1348
  makePolicyContainer,
@@ -1213,7 +1374,6 @@ module.exports = {
1213
1374
  isReadableStreamLike,
1214
1375
  readableStreamClose,
1215
1376
  isomorphicEncode,
1216
- isomorphicDecode,
1217
1377
  urlIsLocal,
1218
1378
  urlHasHttpsScheme,
1219
1379
  urlIsHttpHttpsScheme,
@@ -1221,5 +1381,7 @@ module.exports = {
1221
1381
  normalizeMethodRecord,
1222
1382
  simpleRangeHeaderValue,
1223
1383
  buildContentRange,
1224
- parseMetadata
1384
+ parseMetadata,
1385
+ createInflate,
1386
+ extractMimeType
1225
1387
  }
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { types } = require('util')
3
+ const { types } = require('node:util')
4
4
  const { toUSVString } = require('./util')
5
5
 
6
6
  /** @type {import('../../types/webidl').Webidl} */
@@ -10,9 +10,9 @@ const {
10
10
  const { ProgressEvent } = require('./progressevent')
11
11
  const { getEncoding } = require('./encoding')
12
12
  const { serializeAMimeType, parseMIMEType } = require('../fetch/dataURL')
13
- const { types } = require('util')
13
+ const { types } = require('node:util')
14
14
  const { StringDecoder } = require('string_decoder')
15
- const { btoa } = require('buffer')
15
+ const { btoa } = require('node:buffer')
16
16
 
17
17
  /** @type {PropertyDescriptor} */
18
18
  const staticPropertyDescriptors = {
@@ -2,9 +2,9 @@
2
2
 
3
3
  const util = require('../core/util')
4
4
  const { kBodyUsed } = require('../core/symbols')
5
- const assert = require('assert')
5
+ const assert = require('node:assert')
6
6
  const { InvalidArgumentError } = require('../core/errors')
7
- const EE = require('events')
7
+ const EE = require('node:events')
8
8
 
9
9
  const redirectableStatusCodes = [300, 301, 302, 303, 307, 308]
10
10
 
@@ -1,4 +1,4 @@
1
- const assert = require('assert')
1
+ const assert = require('node:assert')
2
2
 
3
3
  const { kRetryHandlerDefaultRetry } = require('../core/symbols')
4
4
  const { RequestRetryError } = require('../core/errors')
@@ -148,10 +148,10 @@ class RetryHandler {
148
148
  return
149
149
  }
150
150
 
151
- let retryAfterHeader = headers != null && headers['retry-after']
151
+ let retryAfterHeader = headers?.['retry-after']
152
152
  if (retryAfterHeader) {
153
153
  retryAfterHeader = Number(retryAfterHeader)
154
- retryAfterHeader = isNaN(retryAfterHeader)
154
+ retryAfterHeader = Number.isNaN(retryAfterHeader)
155
155
  ? calculateRetryAfterHeader(retryAfterHeader)
156
156
  : retryAfterHeader * 1e3 // Retry-After is in seconds
157
157
  }