undici 6.14.1 → 6.15.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.
@@ -259,6 +259,24 @@ class HeadersList {
259
259
  return headers
260
260
  }
261
261
 
262
+ get entriesList () {
263
+ const headers = []
264
+
265
+ if (this[kHeadersMap].size !== 0) {
266
+ for (const { 0: lowerName, 1: { name, value } } of this[kHeadersMap]) {
267
+ if (lowerName === 'set-cookie') {
268
+ for (const cookie of this.cookies) {
269
+ headers.push([name, cookie])
270
+ }
271
+ } else {
272
+ headers.push([name, value])
273
+ }
274
+ }
275
+ }
276
+
277
+ return headers
278
+ }
279
+
262
280
  // https://fetch.spec.whatwg.org/#convert-header-names-to-a-sorted-lowercase-set
263
281
  toSortedArray () {
264
282
  const size = this[kHeadersMap].size
@@ -348,7 +366,7 @@ class Headers {
348
366
 
349
367
  // 2. If init is given, then fill this with init.
350
368
  if (init !== undefined) {
351
- init = webidl.converters.HeadersInit(init)
369
+ init = webidl.converters.HeadersInit(init, 'Headers contructor', 'init')
352
370
  fill(this, init)
353
371
  }
354
372
  }
@@ -357,10 +375,11 @@ class Headers {
357
375
  append (name, value) {
358
376
  webidl.brandCheck(this, Headers)
359
377
 
360
- webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.append' })
378
+ webidl.argumentLengthCheck(arguments, 2, 'Headers.append')
361
379
 
362
- name = webidl.converters.ByteString(name)
363
- value = webidl.converters.ByteString(value)
380
+ const prefix = 'Headers.append'
381
+ name = webidl.converters.ByteString(name, prefix, 'name')
382
+ value = webidl.converters.ByteString(value, prefix, 'value')
364
383
 
365
384
  return appendHeader(this, name, value)
366
385
  }
@@ -369,9 +388,10 @@ class Headers {
369
388
  delete (name) {
370
389
  webidl.brandCheck(this, Headers)
371
390
 
372
- webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.delete' })
391
+ webidl.argumentLengthCheck(arguments, 1, 'Headers.delete')
373
392
 
374
- name = webidl.converters.ByteString(name)
393
+ const prefix = 'Headers.delete'
394
+ name = webidl.converters.ByteString(name, prefix, 'name')
375
395
 
376
396
  // 1. If name is not a header name, then throw a TypeError.
377
397
  if (!isValidHeaderName(name)) {
@@ -414,14 +434,15 @@ class Headers {
414
434
  get (name) {
415
435
  webidl.brandCheck(this, Headers)
416
436
 
417
- webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.get' })
437
+ webidl.argumentLengthCheck(arguments, 1, 'Headers.get')
418
438
 
419
- name = webidl.converters.ByteString(name)
439
+ const prefix = 'Headers.get'
440
+ name = webidl.converters.ByteString(name, prefix, 'name')
420
441
 
421
442
  // 1. If name is not a header name, then throw a TypeError.
422
443
  if (!isValidHeaderName(name)) {
423
444
  throw webidl.errors.invalidArgument({
424
- prefix: 'Headers.get',
445
+ prefix,
425
446
  value: name,
426
447
  type: 'header name'
427
448
  })
@@ -436,14 +457,15 @@ class Headers {
436
457
  has (name) {
437
458
  webidl.brandCheck(this, Headers)
438
459
 
439
- webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.has' })
460
+ webidl.argumentLengthCheck(arguments, 1, 'Headers.has')
440
461
 
441
- name = webidl.converters.ByteString(name)
462
+ const prefix = 'Headers.has'
463
+ name = webidl.converters.ByteString(name, prefix, 'name')
442
464
 
443
465
  // 1. If name is not a header name, then throw a TypeError.
444
466
  if (!isValidHeaderName(name)) {
445
467
  throw webidl.errors.invalidArgument({
446
- prefix: 'Headers.has',
468
+ prefix,
447
469
  value: name,
448
470
  type: 'header name'
449
471
  })
@@ -458,10 +480,11 @@ class Headers {
458
480
  set (name, value) {
459
481
  webidl.brandCheck(this, Headers)
460
482
 
461
- webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.set' })
483
+ webidl.argumentLengthCheck(arguments, 2, 'Headers.set')
462
484
 
463
- name = webidl.converters.ByteString(name)
464
- value = webidl.converters.ByteString(value)
485
+ const prefix = 'Headers.set'
486
+ name = webidl.converters.ByteString(name, prefix, 'name')
487
+ value = webidl.converters.ByteString(value, prefix, 'value')
465
488
 
466
489
  // 1. Normalize value.
467
490
  value = headerValueNormalize(value)
@@ -470,13 +493,13 @@ class Headers {
470
493
  // header value, then throw a TypeError.
471
494
  if (!isValidHeaderName(name)) {
472
495
  throw webidl.errors.invalidArgument({
473
- prefix: 'Headers.set',
496
+ prefix,
474
497
  value: name,
475
498
  type: 'header name'
476
499
  })
477
500
  } else if (!isValidHeaderValue(value)) {
478
501
  throw webidl.errors.invalidArgument({
479
- prefix: 'Headers.set',
502
+ prefix,
480
503
  value,
481
504
  type: 'header value'
482
505
  })
@@ -598,15 +621,21 @@ Object.defineProperties(Headers.prototype, {
598
621
  }
599
622
  })
600
623
 
601
- webidl.converters.HeadersInit = function (V) {
624
+ webidl.converters.HeadersInit = function (V, prefix, argument) {
602
625
  if (webidl.util.Type(V) === 'Object') {
603
626
  const iterator = Reflect.get(V, Symbol.iterator)
604
627
 
628
+ // A work-around to ensure we send the properly-cased Headers when V is a Headers object.
629
+ // Read https://github.com/nodejs/undici/pull/3159#issuecomment-2075537226 before touching, please.
630
+ if (!util.types.isProxy(V) && kHeadersList in V && iterator === Headers.prototype.entries) { // Headers object
631
+ return V[kHeadersList].entriesList
632
+ }
633
+
605
634
  if (typeof iterator === 'function') {
606
- return webidl.converters['sequence<sequence<ByteString>>'](V, iterator.bind(V))
635
+ return webidl.converters['sequence<sequence<ByteString>>'](V, prefix, argument, iterator.bind(V))
607
636
  }
608
637
 
609
- return webidl.converters['record<ByteString, ByteString>'](V)
638
+ return webidl.converters['record<ByteString, ByteString>'](V, prefix, argument)
610
639
  }
611
640
 
612
641
  throw webidl.errors.conversionFailed({
@@ -122,7 +122,7 @@ class Fetch extends EE {
122
122
 
123
123
  // https://fetch.spec.whatwg.org/#fetch-method
124
124
  function fetch (input, init = undefined) {
125
- webidl.argumentLengthCheck(arguments, 1, { header: 'globalThis.fetch' })
125
+ webidl.argumentLengthCheck(arguments, 1, 'globalThis.fetch')
126
126
 
127
127
  // 1. Let p be a new promise.
128
128
  const p = createDeferredPromise()
@@ -1537,7 +1537,7 @@ async function httpNetworkOrCacheFetch (
1537
1537
 
1538
1538
  // 24. If httpRequest’s cache mode is neither "no-store" nor "reload",
1539
1539
  // then:
1540
- if (httpRequest.mode !== 'no-store' && httpRequest.mode !== 'reload') {
1540
+ if (httpRequest.cache !== 'no-store' && httpRequest.cache !== 'reload') {
1541
1541
  // TODO: cache
1542
1542
  }
1543
1543
 
@@ -1548,7 +1548,7 @@ async function httpNetworkOrCacheFetch (
1548
1548
  if (response == null) {
1549
1549
  // 1. If httpRequest’s cache mode is "only-if-cached", then return a
1550
1550
  // network error.
1551
- if (httpRequest.mode === 'only-if-cached') {
1551
+ if (httpRequest.cache === 'only-if-cached') {
1552
1552
  return makeNetworkError('only if cached')
1553
1553
  }
1554
1554
 
@@ -38,6 +38,46 @@ const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => {
38
38
  signal.removeEventListener('abort', abort)
39
39
  })
40
40
 
41
+ const dependentControllerMap = new WeakMap()
42
+
43
+ function buildAbort (acRef) {
44
+ return abort
45
+
46
+ function abort () {
47
+ const ac = acRef.deref()
48
+ if (ac !== undefined) {
49
+ // Currently, there is a problem with FinalizationRegistry.
50
+ // https://github.com/nodejs/node/issues/49344
51
+ // https://github.com/nodejs/node/issues/47748
52
+ // In the case of abort, the first step is to unregister from it.
53
+ // If the controller can refer to it, it is still registered.
54
+ // It will be removed in the future.
55
+ requestFinalizer.unregister(abort)
56
+
57
+ // Unsubscribe a listener.
58
+ // FinalizationRegistry will no longer be called, so this must be done.
59
+ this.removeEventListener('abort', abort)
60
+
61
+ ac.abort(this.reason)
62
+
63
+ const controllerList = dependentControllerMap.get(ac.signal)
64
+
65
+ if (controllerList !== undefined) {
66
+ if (controllerList.size !== 0) {
67
+ for (const ref of controllerList) {
68
+ const ctrl = ref.deref()
69
+ if (ctrl !== undefined) {
70
+ ctrl.abort(this.reason)
71
+ }
72
+ }
73
+ controllerList.clear()
74
+ }
75
+ dependentControllerMap.delete(ac.signal)
76
+ }
77
+ }
78
+ }
79
+ }
80
+
41
81
  let patchMethodWarning = false
42
82
 
43
83
  // https://fetch.spec.whatwg.org/#request-class
@@ -48,10 +88,11 @@ class Request {
48
88
  return
49
89
  }
50
90
 
51
- webidl.argumentLengthCheck(arguments, 1, { header: 'Request constructor' })
91
+ const prefix = 'Request constructor'
92
+ webidl.argumentLengthCheck(arguments, 1, prefix)
52
93
 
53
- input = webidl.converters.RequestInfo(input)
54
- init = webidl.converters.RequestInit(init)
94
+ input = webidl.converters.RequestInfo(input, prefix, 'input')
95
+ init = webidl.converters.RequestInit(init, prefix, 'init')
55
96
 
56
97
  // 1. Let request be null.
57
98
  let request = null
@@ -377,24 +418,7 @@ class Request {
377
418
  this[kAbortController] = ac
378
419
 
379
420
  const acRef = new WeakRef(ac)
380
- const abort = function () {
381
- const ac = acRef.deref()
382
- if (ac !== undefined) {
383
- // Currently, there is a problem with FinalizationRegistry.
384
- // https://github.com/nodejs/node/issues/49344
385
- // https://github.com/nodejs/node/issues/47748
386
- // In the case of abort, the first step is to unregister from it.
387
- // If the controller can refer to it, it is still registered.
388
- // It will be removed in the future.
389
- requestFinalizer.unregister(abort)
390
-
391
- // Unsubscribe a listener.
392
- // FinalizationRegistry will no longer be called, so this must be done.
393
- this.removeEventListener('abort', abort)
394
-
395
- ac.abort(this.reason)
396
- }
397
- }
421
+ const abort = buildAbort(acRef)
398
422
 
399
423
  // Third-party AbortControllers may not work with these.
400
424
  // See, https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619.
@@ -402,9 +426,9 @@ class Request {
402
426
  // If the max amount of listeners is equal to the default, increase it
403
427
  // This is only available in node >= v19.9.0
404
428
  if (typeof getMaxListeners === 'function' && getMaxListeners(signal) === defaultMaxListeners) {
405
- setMaxListeners(100, signal)
429
+ setMaxListeners(1500, signal)
406
430
  } else if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) {
407
- setMaxListeners(100, signal)
431
+ setMaxListeners(1500, signal)
408
432
  }
409
433
  } catch {}
410
434
 
@@ -453,8 +477,9 @@ class Request {
453
477
  // 4. If headers is a Headers object, then for each header in its header
454
478
  // list, append header’s name/header’s value to this’s headers.
455
479
  if (headers instanceof HeadersList) {
456
- for (const [key, val] of headers) {
457
- headersList.append(key, val)
480
+ for (const { 0: key, 1: val } of headers) {
481
+ // Note: The header names are already in lowercase.
482
+ headersList.append(key, val, true)
458
483
  }
459
484
  // Note: Copy the `set-cookie` meta-data.
460
485
  headersList.cookies = headers.cookies
@@ -747,11 +772,16 @@ class Request {
747
772
  if (this.signal.aborted) {
748
773
  ac.abort(this.signal.reason)
749
774
  } else {
775
+ let list = dependentControllerMap.get(this.signal)
776
+ if (list === undefined) {
777
+ list = new Set()
778
+ dependentControllerMap.set(this.signal, list)
779
+ }
780
+ const acRef = new WeakRef(ac)
781
+ list.add(acRef)
750
782
  util.addAbortListener(
751
- this.signal,
752
- () => {
753
- ac.abort(this.signal.reason)
754
- }
783
+ ac.signal,
784
+ buildAbort(acRef)
755
785
  )
756
786
  }
757
787
 
@@ -903,16 +933,16 @@ webidl.converters.Request = webidl.interfaceConverter(
903
933
  )
904
934
 
905
935
  // https://fetch.spec.whatwg.org/#requestinfo
906
- webidl.converters.RequestInfo = function (V) {
936
+ webidl.converters.RequestInfo = function (V, prefix, argument) {
907
937
  if (typeof V === 'string') {
908
- return webidl.converters.USVString(V)
938
+ return webidl.converters.USVString(V, prefix, argument)
909
939
  }
910
940
 
911
941
  if (V instanceof Request) {
912
- return webidl.converters.Request(V)
942
+ return webidl.converters.Request(V, prefix, argument)
913
943
  }
914
944
 
915
- return webidl.converters.USVString(V)
945
+ return webidl.converters.USVString(V, prefix, argument)
916
946
  }
917
947
 
918
948
  webidl.converters.AbortSignal = webidl.interfaceConverter(
@@ -982,6 +1012,8 @@ webidl.converters.RequestInit = webidl.dictionaryConverter([
982
1012
  converter: webidl.nullableConverter(
983
1013
  (signal) => webidl.converters.AbortSignal(
984
1014
  signal,
1015
+ 'RequestInit',
1016
+ 'signal',
985
1017
  { strict: false }
986
1018
  )
987
1019
  )
@@ -43,7 +43,7 @@ class Response {
43
43
 
44
44
  // https://fetch.spec.whatwg.org/#dom-response-json
45
45
  static json (data, init = {}) {
46
- webidl.argumentLengthCheck(arguments, 1, { header: 'Response.json' })
46
+ webidl.argumentLengthCheck(arguments, 1, 'Response.json')
47
47
 
48
48
  if (init !== null) {
49
49
  init = webidl.converters.ResponseInit(init)
@@ -70,7 +70,7 @@ class Response {
70
70
 
71
71
  // Creates a redirect Response that redirects to url with status status.
72
72
  static redirect (url, status = 302) {
73
- webidl.argumentLengthCheck(arguments, 1, { header: 'Response.redirect' })
73
+ webidl.argumentLengthCheck(arguments, 1, 'Response.redirect')
74
74
 
75
75
  url = webidl.converters.USVString(url)
76
76
  status = webidl.converters['unsigned short'](status)
@@ -526,34 +526,34 @@ webidl.converters.URLSearchParams = webidl.interfaceConverter(
526
526
  )
527
527
 
528
528
  // https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit
529
- webidl.converters.XMLHttpRequestBodyInit = function (V) {
529
+ webidl.converters.XMLHttpRequestBodyInit = function (V, prefix, name) {
530
530
  if (typeof V === 'string') {
531
- return webidl.converters.USVString(V)
531
+ return webidl.converters.USVString(V, prefix, name)
532
532
  }
533
533
 
534
534
  if (isBlobLike(V)) {
535
- return webidl.converters.Blob(V, { strict: false })
535
+ return webidl.converters.Blob(V, prefix, name, { strict: false })
536
536
  }
537
537
 
538
538
  if (ArrayBuffer.isView(V) || types.isArrayBuffer(V)) {
539
- return webidl.converters.BufferSource(V)
539
+ return webidl.converters.BufferSource(V, prefix, name)
540
540
  }
541
541
 
542
542
  if (util.isFormDataLike(V)) {
543
- return webidl.converters.FormData(V, { strict: false })
543
+ return webidl.converters.FormData(V, prefix, name, { strict: false })
544
544
  }
545
545
 
546
546
  if (V instanceof URLSearchParams) {
547
- return webidl.converters.URLSearchParams(V)
547
+ return webidl.converters.URLSearchParams(V, prefix, name)
548
548
  }
549
549
 
550
- return webidl.converters.DOMString(V)
550
+ return webidl.converters.DOMString(V, prefix, name)
551
551
  }
552
552
 
553
553
  // https://fetch.spec.whatwg.org/#bodyinit
554
- webidl.converters.BodyInit = function (V) {
554
+ webidl.converters.BodyInit = function (V, prefix, argument) {
555
555
  if (V instanceof ReadableStream) {
556
- return webidl.converters.ReadableStream(V)
556
+ return webidl.converters.ReadableStream(V, prefix, argument)
557
557
  }
558
558
 
559
559
  // Note: the spec doesn't include async iterables,
@@ -562,19 +562,19 @@ webidl.converters.BodyInit = function (V) {
562
562
  return V
563
563
  }
564
564
 
565
- return webidl.converters.XMLHttpRequestBodyInit(V)
565
+ return webidl.converters.XMLHttpRequestBodyInit(V, prefix, argument)
566
566
  }
567
567
 
568
568
  webidl.converters.ResponseInit = webidl.dictionaryConverter([
569
569
  {
570
570
  key: 'status',
571
571
  converter: webidl.converters['unsigned short'],
572
- defaultValue: 200
572
+ defaultValue: () => 200
573
573
  },
574
574
  {
575
575
  key: 'statusText',
576
576
  converter: webidl.converters.ByteString,
577
- defaultValue: ''
577
+ defaultValue: () => ''
578
578
  },
579
579
  {
580
580
  key: 'headers',
@@ -1016,7 +1016,7 @@ function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueInde
1016
1016
  configurable: true,
1017
1017
  value: function forEach (callbackfn, thisArg = globalThis) {
1018
1018
  webidl.brandCheck(this, object)
1019
- webidl.argumentLengthCheck(arguments, 1, { header: `${name}.forEach` })
1019
+ webidl.argumentLengthCheck(arguments, 1, `${name}.forEach`)
1020
1020
  if (typeof callbackfn !== 'function') {
1021
1021
  throw new TypeError(
1022
1022
  `Failed to execute 'forEach' on '${name}': parameter 1 is not of type 'Function'.`