undici 7.14.0 → 7.16.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.
Files changed (63) hide show
  1. package/README.md +1 -1
  2. package/docs/docs/api/Agent.md +1 -0
  3. package/docs/docs/api/Dispatcher.md +59 -0
  4. package/docs/docs/api/Errors.md +0 -1
  5. package/index-fetch.js +2 -2
  6. package/index.js +6 -9
  7. package/lib/api/api-request.js +22 -8
  8. package/lib/api/readable.js +7 -5
  9. package/lib/core/errors.js +217 -13
  10. package/lib/core/request.js +5 -1
  11. package/lib/core/util.js +45 -11
  12. package/lib/dispatcher/agent.js +44 -23
  13. package/lib/dispatcher/client-h1.js +20 -9
  14. package/lib/dispatcher/client-h2.js +13 -3
  15. package/lib/dispatcher/client.js +57 -57
  16. package/lib/dispatcher/dispatcher-base.js +12 -7
  17. package/lib/dispatcher/env-http-proxy-agent.js +12 -16
  18. package/lib/dispatcher/fixed-queue.js +15 -39
  19. package/lib/dispatcher/h2c-client.js +6 -6
  20. package/lib/dispatcher/pool-base.js +60 -43
  21. package/lib/dispatcher/pool.js +2 -2
  22. package/lib/dispatcher/proxy-agent.js +14 -9
  23. package/lib/global.js +19 -1
  24. package/lib/interceptor/cache.js +61 -0
  25. package/lib/interceptor/decompress.js +253 -0
  26. package/lib/llhttp/constants.d.ts +99 -1
  27. package/lib/llhttp/constants.js +34 -1
  28. package/lib/llhttp/llhttp-wasm.js +1 -1
  29. package/lib/llhttp/llhttp_simd-wasm.js +1 -1
  30. package/lib/llhttp/utils.d.ts +2 -2
  31. package/lib/llhttp/utils.js +3 -6
  32. package/lib/mock/mock-agent.js +4 -4
  33. package/lib/mock/mock-errors.js +10 -0
  34. package/lib/mock/mock-utils.js +12 -10
  35. package/lib/util/cache.js +6 -7
  36. package/lib/util/date.js +534 -140
  37. package/lib/web/cookies/index.js +1 -1
  38. package/lib/web/cookies/parse.js +2 -2
  39. package/lib/web/eventsource/eventsource-stream.js +2 -2
  40. package/lib/web/eventsource/eventsource.js +34 -29
  41. package/lib/web/eventsource/util.js +1 -9
  42. package/lib/web/fetch/body.js +20 -26
  43. package/lib/web/fetch/index.js +15 -16
  44. package/lib/web/fetch/response.js +2 -4
  45. package/lib/web/fetch/util.js +8 -230
  46. package/lib/web/subresource-integrity/Readme.md +9 -0
  47. package/lib/web/subresource-integrity/subresource-integrity.js +306 -0
  48. package/lib/web/webidl/index.js +203 -42
  49. package/lib/web/websocket/connection.js +4 -3
  50. package/lib/web/websocket/events.js +1 -1
  51. package/lib/web/websocket/stream/websocketerror.js +22 -1
  52. package/lib/web/websocket/stream/websocketstream.js +16 -7
  53. package/lib/web/websocket/websocket.js +32 -42
  54. package/package.json +9 -7
  55. package/types/agent.d.ts +1 -0
  56. package/types/diagnostics-channel.d.ts +0 -1
  57. package/types/errors.d.ts +5 -15
  58. package/types/interceptors.d.ts +5 -0
  59. package/types/snapshot-agent.d.ts +5 -3
  60. package/types/webidl.d.ts +82 -21
  61. package/lib/api/util.js +0 -95
  62. package/lib/llhttp/constants.js.map +0 -1
  63. package/lib/llhttp/utils.js.map +0 -1
@@ -160,7 +160,7 @@ webidl.util.TypeValueToString = function (o) {
160
160
  webidl.util.markAsUncloneable = markAsUncloneable || (() => {})
161
161
 
162
162
  // https://webidl.spec.whatwg.org/#abstract-opdef-converttoint
163
- webidl.util.ConvertToInt = function (V, bitLength, signedness, opts) {
163
+ webidl.util.ConvertToInt = function (V, bitLength, signedness, flags) {
164
164
  let upperBound
165
165
  let lowerBound
166
166
 
@@ -204,7 +204,7 @@ webidl.util.ConvertToInt = function (V, bitLength, signedness, opts) {
204
204
 
205
205
  // 6. If the conversion is to an IDL type associated
206
206
  // with the [EnforceRange] extended attribute, then:
207
- if (opts?.enforceRange === true) {
207
+ if (webidl.util.HasFlag(flags, webidl.attributes.EnforceRange)) {
208
208
  // 1. If x is NaN, +∞, or −∞, then throw a TypeError.
209
209
  if (
210
210
  Number.isNaN(x) ||
@@ -236,7 +236,7 @@ webidl.util.ConvertToInt = function (V, bitLength, signedness, opts) {
236
236
  // 7. If x is not NaN and the conversion is to an IDL
237
237
  // type associated with the [Clamp] extended
238
238
  // attribute, then:
239
- if (!Number.isNaN(x) && opts?.clamp === true) {
239
+ if (!Number.isNaN(x) && webidl.util.HasFlag(flags, webidl.attributes.Clamp)) {
240
240
  // 1. Set x to min(max(x, lowerBound), upperBound).
241
241
  x = Math.min(Math.max(x, lowerBound), upperBound)
242
242
 
@@ -310,6 +310,25 @@ webidl.util.Stringify = function (V) {
310
310
  }
311
311
  }
312
312
 
313
+ webidl.util.IsResizableArrayBuffer = function (V) {
314
+ if (types.isArrayBuffer(V)) {
315
+ return V.resizable
316
+ }
317
+
318
+ if (types.isSharedArrayBuffer(V)) {
319
+ return V.growable
320
+ }
321
+
322
+ throw webidl.errors.exception({
323
+ header: 'IsResizableArrayBuffer',
324
+ message: `"${webidl.util.Stringify(V)}" is not an array buffer.`
325
+ })
326
+ }
327
+
328
+ webidl.util.HasFlag = function (flags, attributes) {
329
+ return typeof flags === 'number' && (flags & attributes) === attributes
330
+ }
331
+
313
332
  // https://webidl.spec.whatwg.org/#es-sequence
314
333
  webidl.sequenceConverter = function (converter) {
315
334
  return (V, prefix, argument, Iterable) => {
@@ -514,13 +533,20 @@ webidl.is.URL = webidl.util.MakeTypeAssertion(URL)
514
533
  webidl.is.AbortSignal = webidl.util.MakeTypeAssertion(AbortSignal)
515
534
  webidl.is.MessagePort = webidl.util.MakeTypeAssertion(MessagePort)
516
535
 
536
+ webidl.is.BufferSource = function (V) {
537
+ return types.isArrayBuffer(V) || (
538
+ ArrayBuffer.isView(V) &&
539
+ types.isArrayBuffer(V.buffer)
540
+ )
541
+ }
542
+
517
543
  // https://webidl.spec.whatwg.org/#es-DOMString
518
- webidl.converters.DOMString = function (V, prefix, argument, opts) {
544
+ webidl.converters.DOMString = function (V, prefix, argument, flags) {
519
545
  // 1. If V is null and the conversion is to an IDL type
520
546
  // associated with the [LegacyNullToEmptyString]
521
547
  // extended attribute, then return the DOMString value
522
548
  // that represents the empty string.
523
- if (V === null && opts?.legacyNullToEmptyString) {
549
+ if (V === null && webidl.util.HasFlag(flags, webidl.attributes.LegacyNullToEmptyString)) {
524
550
  return ''
525
551
  }
526
552
 
@@ -599,7 +625,7 @@ webidl.converters.any = function (V) {
599
625
  // https://webidl.spec.whatwg.org/#es-long-long
600
626
  webidl.converters['long long'] = function (V, prefix, argument) {
601
627
  // 1. Let x be ? ConvertToInt(V, 64, "signed").
602
- const x = webidl.util.ConvertToInt(V, 64, 'signed', undefined, prefix, argument)
628
+ const x = webidl.util.ConvertToInt(V, 64, 'signed', 0, prefix, argument)
603
629
 
604
630
  // 2. Return the IDL long long value that represents
605
631
  // the same numeric value as x.
@@ -609,7 +635,7 @@ webidl.converters['long long'] = function (V, prefix, argument) {
609
635
  // https://webidl.spec.whatwg.org/#es-unsigned-long-long
610
636
  webidl.converters['unsigned long long'] = function (V, prefix, argument) {
611
637
  // 1. Let x be ? ConvertToInt(V, 64, "unsigned").
612
- const x = webidl.util.ConvertToInt(V, 64, 'unsigned', undefined, prefix, argument)
638
+ const x = webidl.util.ConvertToInt(V, 64, 'unsigned', 0, prefix, argument)
613
639
 
614
640
  // 2. Return the IDL unsigned long long value that
615
641
  // represents the same numeric value as x.
@@ -619,7 +645,7 @@ webidl.converters['unsigned long long'] = function (V, prefix, argument) {
619
645
  // https://webidl.spec.whatwg.org/#es-unsigned-long
620
646
  webidl.converters['unsigned long'] = function (V, prefix, argument) {
621
647
  // 1. Let x be ? ConvertToInt(V, 32, "unsigned").
622
- const x = webidl.util.ConvertToInt(V, 32, 'unsigned', undefined, prefix, argument)
648
+ const x = webidl.util.ConvertToInt(V, 32, 'unsigned', 0, prefix, argument)
623
649
 
624
650
  // 2. Return the IDL unsigned long value that
625
651
  // represents the same numeric value as x.
@@ -627,9 +653,9 @@ webidl.converters['unsigned long'] = function (V, prefix, argument) {
627
653
  }
628
654
 
629
655
  // https://webidl.spec.whatwg.org/#es-unsigned-short
630
- webidl.converters['unsigned short'] = function (V, prefix, argument, opts) {
656
+ webidl.converters['unsigned short'] = function (V, prefix, argument, flags) {
631
657
  // 1. Let x be ? ConvertToInt(V, 16, "unsigned").
632
- const x = webidl.util.ConvertToInt(V, 16, 'unsigned', opts, prefix, argument)
658
+ const x = webidl.util.ConvertToInt(V, 16, 'unsigned', flags, prefix, argument)
633
659
 
634
660
  // 2. Return the IDL unsigned short value that represents
635
661
  // the same numeric value as x.
@@ -637,15 +663,16 @@ webidl.converters['unsigned short'] = function (V, prefix, argument, opts) {
637
663
  }
638
664
 
639
665
  // https://webidl.spec.whatwg.org/#idl-ArrayBuffer
640
- webidl.converters.ArrayBuffer = function (V, prefix, argument, opts) {
641
- // 1. If Type(V) is not Object, or V does not have an
666
+ webidl.converters.ArrayBuffer = function (V, prefix, argument, flags) {
667
+ // 1. If V is not an Object, or V does not have an
642
668
  // [[ArrayBufferData]] internal slot, then throw a
643
669
  // TypeError.
670
+ // 2. If IsSharedArrayBuffer(V) is true, then throw a
671
+ // TypeError.
644
672
  // see: https://tc39.es/ecma262/#sec-properties-of-the-arraybuffer-instances
645
- // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances
646
673
  if (
647
674
  webidl.util.Type(V) !== OBJECT ||
648
- !types.isAnyArrayBuffer(V)
675
+ !types.isArrayBuffer(V)
649
676
  ) {
650
677
  throw webidl.errors.conversionFailed({
651
678
  prefix,
@@ -654,14 +681,38 @@ webidl.converters.ArrayBuffer = function (V, prefix, argument, opts) {
654
681
  })
655
682
  }
656
683
 
657
- // 2. If the conversion is not to an IDL type associated
658
- // with the [AllowShared] extended attribute, and
659
- // IsSharedArrayBuffer(V) is true, then throw a
684
+ // 3. If the conversion is not to an IDL type associated
685
+ // with the [AllowResizable] extended attribute, and
686
+ // IsResizableArrayBuffer(V) is true, then throw a
660
687
  // TypeError.
661
- if (opts?.allowShared === false && types.isSharedArrayBuffer(V)) {
688
+ if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) {
662
689
  throw webidl.errors.exception({
663
- header: 'ArrayBuffer',
664
- message: 'SharedArrayBuffer is not allowed.'
690
+ header: prefix,
691
+ message: `${argument} cannot be a resizable ArrayBuffer.`
692
+ })
693
+ }
694
+
695
+ // 4. Return the IDL ArrayBuffer value that is a
696
+ // reference to the same object as V.
697
+ return V
698
+ }
699
+
700
+ // https://webidl.spec.whatwg.org/#idl-SharedArrayBuffer
701
+ webidl.converters.SharedArrayBuffer = function (V, prefix, argument, flags) {
702
+ // 1. If V is not an Object, or V does not have an
703
+ // [[ArrayBufferData]] internal slot, then throw a
704
+ // TypeError.
705
+ // 2. If IsSharedArrayBuffer(V) is false, then throw a
706
+ // TypeError.
707
+ // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances
708
+ if (
709
+ webidl.util.Type(V) !== OBJECT ||
710
+ !types.isSharedArrayBuffer(V)
711
+ ) {
712
+ throw webidl.errors.conversionFailed({
713
+ prefix,
714
+ argument: `${argument} ("${webidl.util.Stringify(V)}")`,
715
+ types: ['SharedArrayBuffer']
665
716
  })
666
717
  }
667
718
 
@@ -669,19 +720,20 @@ webidl.converters.ArrayBuffer = function (V, prefix, argument, opts) {
669
720
  // with the [AllowResizable] extended attribute, and
670
721
  // IsResizableArrayBuffer(V) is true, then throw a
671
722
  // TypeError.
672
- if (V.resizable || V.growable) {
723
+ if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V)) {
673
724
  throw webidl.errors.exception({
674
- header: 'ArrayBuffer',
675
- message: 'Received a resizable ArrayBuffer.'
725
+ header: prefix,
726
+ message: `${argument} cannot be a resizable SharedArrayBuffer.`
676
727
  })
677
728
  }
678
729
 
679
- // 4. Return the IDL ArrayBuffer value that is a
730
+ // 4. Return the IDL SharedArrayBuffer value that is a
680
731
  // reference to the same object as V.
681
732
  return V
682
733
  }
683
734
 
684
- webidl.converters.TypedArray = function (V, T, prefix, name, opts) {
735
+ // https://webidl.spec.whatwg.org/#dfn-typed-array-type
736
+ webidl.converters.TypedArray = function (V, T, prefix, argument, flags) {
685
737
  // 1. Let T be the IDL type V is being converted to.
686
738
 
687
739
  // 2. If Type(V) is not Object, or V does not have a
@@ -694,7 +746,7 @@ webidl.converters.TypedArray = function (V, T, prefix, name, opts) {
694
746
  ) {
695
747
  throw webidl.errors.conversionFailed({
696
748
  prefix,
697
- argument: `${name} ("${webidl.util.Stringify(V)}")`,
749
+ argument: `${argument} ("${webidl.util.Stringify(V)}")`,
698
750
  types: [T.name]
699
751
  })
700
752
  }
@@ -703,10 +755,10 @@ webidl.converters.TypedArray = function (V, T, prefix, name, opts) {
703
755
  // with the [AllowShared] extended attribute, and
704
756
  // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is
705
757
  // true, then throw a TypeError.
706
- if (opts?.allowShared === false && types.isSharedArrayBuffer(V.buffer)) {
758
+ if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) {
707
759
  throw webidl.errors.exception({
708
- header: 'ArrayBuffer',
709
- message: 'SharedArrayBuffer is not allowed.'
760
+ header: prefix,
761
+ message: `${argument} cannot be a view on a shared array buffer.`
710
762
  })
711
763
  }
712
764
 
@@ -714,10 +766,10 @@ webidl.converters.TypedArray = function (V, T, prefix, name, opts) {
714
766
  // with the [AllowResizable] extended attribute, and
715
767
  // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is
716
768
  // true, then throw a TypeError.
717
- if (V.buffer.resizable || V.buffer.growable) {
769
+ if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) {
718
770
  throw webidl.errors.exception({
719
- header: 'ArrayBuffer',
720
- message: 'Received a resizable ArrayBuffer.'
771
+ header: prefix,
772
+ message: `${argument} cannot be a view on a resizable array buffer.`
721
773
  })
722
774
  }
723
775
 
@@ -726,13 +778,15 @@ webidl.converters.TypedArray = function (V, T, prefix, name, opts) {
726
778
  return V
727
779
  }
728
780
 
729
- webidl.converters.DataView = function (V, prefix, name, opts) {
781
+ // https://webidl.spec.whatwg.org/#idl-DataView
782
+ webidl.converters.DataView = function (V, prefix, argument, flags) {
730
783
  // 1. If Type(V) is not Object, or V does not have a
731
784
  // [[DataView]] internal slot, then throw a TypeError.
732
785
  if (webidl.util.Type(V) !== OBJECT || !types.isDataView(V)) {
733
- throw webidl.errors.exception({
734
- header: prefix,
735
- message: `${name} is not a DataView.`
786
+ throw webidl.errors.conversionFailed({
787
+ prefix,
788
+ argument: `${argument} ("${webidl.util.Stringify(V)}")`,
789
+ types: ['DataView']
736
790
  })
737
791
  }
738
792
 
@@ -740,10 +794,10 @@ webidl.converters.DataView = function (V, prefix, name, opts) {
740
794
  // with the [AllowShared] extended attribute, and
741
795
  // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true,
742
796
  // then throw a TypeError.
743
- if (opts?.allowShared === false && types.isSharedArrayBuffer(V.buffer)) {
797
+ if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) {
744
798
  throw webidl.errors.exception({
745
- header: 'ArrayBuffer',
746
- message: 'SharedArrayBuffer is not allowed.'
799
+ header: prefix,
800
+ message: `${argument} cannot be a view on a shared array buffer.`
747
801
  })
748
802
  }
749
803
 
@@ -751,10 +805,10 @@ webidl.converters.DataView = function (V, prefix, name, opts) {
751
805
  // with the [AllowResizable] extended attribute, and
752
806
  // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is
753
807
  // true, then throw a TypeError.
754
- if (V.buffer.resizable || V.buffer.growable) {
808
+ if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) {
755
809
  throw webidl.errors.exception({
756
- header: 'ArrayBuffer',
757
- message: 'Received a resizable ArrayBuffer.'
810
+ header: prefix,
811
+ message: `${argument} cannot be a view on a resizable array buffer.`
758
812
  })
759
813
  }
760
814
 
@@ -763,6 +817,85 @@ webidl.converters.DataView = function (V, prefix, name, opts) {
763
817
  return V
764
818
  }
765
819
 
820
+ // https://webidl.spec.whatwg.org/#ArrayBufferView
821
+ webidl.converters.ArrayBufferView = function (V, prefix, argument, flags) {
822
+ if (
823
+ webidl.util.Type(V) !== OBJECT ||
824
+ !types.isArrayBufferView(V)
825
+ ) {
826
+ throw webidl.errors.conversionFailed({
827
+ prefix,
828
+ argument: `${argument} ("${webidl.util.Stringify(V)}")`,
829
+ types: ['ArrayBufferView']
830
+ })
831
+ }
832
+
833
+ if (!webidl.util.HasFlag(flags, webidl.attributes.AllowShared) && types.isSharedArrayBuffer(V.buffer)) {
834
+ throw webidl.errors.exception({
835
+ header: prefix,
836
+ message: `${argument} cannot be a view on a shared array buffer.`
837
+ })
838
+ }
839
+
840
+ if (!webidl.util.HasFlag(flags, webidl.attributes.AllowResizable) && webidl.util.IsResizableArrayBuffer(V.buffer)) {
841
+ throw webidl.errors.exception({
842
+ header: prefix,
843
+ message: `${argument} cannot be a view on a resizable array buffer.`
844
+ })
845
+ }
846
+
847
+ return V
848
+ }
849
+
850
+ // https://webidl.spec.whatwg.org/#BufferSource
851
+ webidl.converters.BufferSource = function (V, prefix, argument, flags) {
852
+ if (types.isArrayBuffer(V)) {
853
+ return webidl.converters.ArrayBuffer(V, prefix, argument, flags)
854
+ }
855
+
856
+ if (types.isArrayBufferView(V)) {
857
+ flags &= ~webidl.attributes.AllowShared
858
+
859
+ return webidl.converters.ArrayBufferView(V, prefix, argument, flags)
860
+ }
861
+
862
+ // Make this explicit for easier debugging
863
+ if (types.isSharedArrayBuffer(V)) {
864
+ throw webidl.errors.exception({
865
+ header: prefix,
866
+ message: `${argument} cannot be a SharedArrayBuffer.`
867
+ })
868
+ }
869
+
870
+ throw webidl.errors.conversionFailed({
871
+ prefix,
872
+ argument: `${argument} ("${webidl.util.Stringify(V)}")`,
873
+ types: ['ArrayBuffer', 'ArrayBufferView']
874
+ })
875
+ }
876
+
877
+ // https://webidl.spec.whatwg.org/#AllowSharedBufferSource
878
+ webidl.converters.AllowSharedBufferSource = function (V, prefix, argument, flags) {
879
+ if (types.isArrayBuffer(V)) {
880
+ return webidl.converters.ArrayBuffer(V, prefix, argument, flags)
881
+ }
882
+
883
+ if (types.isSharedArrayBuffer(V)) {
884
+ return webidl.converters.SharedArrayBuffer(V, prefix, argument, flags)
885
+ }
886
+
887
+ if (types.isArrayBufferView(V)) {
888
+ flags |= webidl.attributes.AllowShared
889
+ return webidl.converters.ArrayBufferView(V, prefix, argument, flags)
890
+ }
891
+
892
+ throw webidl.errors.conversionFailed({
893
+ prefix,
894
+ argument: `${argument} ("${webidl.util.Stringify(V)}")`,
895
+ types: ['ArrayBuffer', 'SharedArrayBuffer', 'ArrayBufferView']
896
+ })
897
+ }
898
+
766
899
  webidl.converters['sequence<ByteString>'] = webidl.sequenceConverter(
767
900
  webidl.converters.ByteString
768
901
  )
@@ -783,6 +916,34 @@ webidl.converters.AbortSignal = webidl.interfaceConverter(
783
916
  'AbortSignal'
784
917
  )
785
918
 
919
+ /**
920
+ * [LegacyTreatNonObjectAsNull]
921
+ * callback EventHandlerNonNull = any (Event event);
922
+ * typedef EventHandlerNonNull? EventHandler;
923
+ * @param {*} V
924
+ */
925
+ webidl.converters.EventHandlerNonNull = function (V) {
926
+ if (webidl.util.Type(V) !== OBJECT) {
927
+ return null
928
+ }
929
+
930
+ // [I]f the value is not an object, it will be converted to null, and if the value is not callable,
931
+ // it will be converted to a callback function value that does nothing when called.
932
+ if (typeof V === 'function') {
933
+ return V
934
+ }
935
+
936
+ return () => {}
937
+ }
938
+
939
+ webidl.attributes = {
940
+ Clamp: 1 << 0,
941
+ EnforceRange: 1 << 1,
942
+ AllowShared: 1 << 2,
943
+ AllowResizable: 1 << 3,
944
+ LegacyNullToEmptyString: 1 << 4
945
+ }
946
+
786
947
  module.exports = {
787
948
  webidl
788
949
  }
@@ -303,11 +303,12 @@ function failWebsocketConnection (handler, code, reason, cause) {
303
303
 
304
304
  handler.controller.abort()
305
305
 
306
- if (handler.socket?.destroyed === false) {
306
+ if (!handler.socket) {
307
+ // If the connection was not established, we must still emit an 'error' and 'close' events
308
+ handler.onSocketClose()
309
+ } else if (handler.socket.destroyed === false) {
307
310
  handler.socket.destroy()
308
311
  }
309
-
310
- handler.onFail(code, reason, cause)
311
312
  }
312
313
 
313
314
  module.exports = {
@@ -272,7 +272,7 @@ webidl.converters.MessageEventInit = webidl.dictionaryConverter([
272
272
  {
273
273
  key: 'ports',
274
274
  converter: webidl.converters['sequence<MessagePort>'],
275
- defaultValue: () => new Array(0)
275
+ defaultValue: () => []
276
276
  }
277
277
  ])
278
278
 
@@ -5,7 +5,28 @@ const { validateCloseCodeAndReason } = require('../util')
5
5
  const { kConstruct } = require('../../../core/symbols')
6
6
  const { kEnumerableProperty } = require('../../../core/util')
7
7
 
8
- class WebSocketError extends DOMException {
8
+ function createInheritableDOMException () {
9
+ // https://github.com/nodejs/node/issues/59677
10
+ class Test extends DOMException {
11
+ get reason () {
12
+ return ''
13
+ }
14
+ }
15
+
16
+ if (new Test().reason !== undefined) {
17
+ return DOMException
18
+ }
19
+
20
+ return new Proxy(DOMException, {
21
+ construct (target, args, newTarget) {
22
+ const instance = Reflect.construct(target, args, target)
23
+ Object.setPrototypeOf(instance, newTarget.prototype)
24
+ return instance
25
+ }
26
+ })
27
+ }
28
+
29
+ class WebSocketError extends createInheritableDOMException() {
9
30
  #closeCode
10
31
  #reason
11
32
 
@@ -6,7 +6,6 @@ const { states, opcodes, sentCloseFrameState } = require('../constants')
6
6
  const { webidl } = require('../../webidl')
7
7
  const { getURLRecord, isValidSubprotocol, isEstablished, utf8Decode } = require('../util')
8
8
  const { establishWebSocketConnection, failWebsocketConnection, closeWebSocketConnection } = require('../connection')
9
- const { isArrayBuffer } = require('node:util/types')
10
9
  const { channels } = require('../../../core/diagnostics')
11
10
  const { WebsocketFrameSend } = require('../frame')
12
11
  const { ByteParser } = require('../receiver')
@@ -46,7 +45,6 @@ class WebSocketStream {
46
45
  #handler = {
47
46
  // https://whatpr.org/websockets/48/7b748d3...d5570f3.html#feedback-to-websocket-stream-from-the-protocol
48
47
  onConnectionEstablished: (response, extensions) => this.#onConnectionEstablished(response, extensions),
49
- onFail: (_code, _reason) => {},
50
48
  onMessage: (opcode, data) => this.#onMessage(opcode, data),
51
49
  onParserError: (err) => failWebsocketConnection(this.#handler, null, err.message),
52
50
  onParserDrain: () => this.#handler.socket.resume(),
@@ -200,6 +198,9 @@ class WebSocketStream {
200
198
  }
201
199
 
202
200
  #write (chunk) {
201
+ // See /websockets/stream/tentative/write.any.html
202
+ chunk = webidl.converters.WebSocketStreamWrite(chunk)
203
+
203
204
  // 1. Let promise be a new promise created in stream ’s relevant realm .
204
205
  const promise = createDeferredPromise()
205
206
 
@@ -210,9 +211,9 @@ class WebSocketStream {
210
211
  let opcode = null
211
212
 
212
213
  // 4. If chunk is a BufferSource ,
213
- if (ArrayBuffer.isView(chunk) || isArrayBuffer(chunk)) {
214
+ if (webidl.is.BufferSource(chunk)) {
214
215
  // 4.1. Set data to a copy of the bytes given chunk .
215
- data = new Uint8Array(ArrayBuffer.isView(chunk) ? new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength) : chunk)
216
+ data = new Uint8Array(ArrayBuffer.isView(chunk) ? new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength) : chunk.slice())
216
217
 
217
218
  // 4.2. Set opcode to a binary frame opcode.
218
219
  opcode = opcodes.BINARY
@@ -227,7 +228,7 @@ class WebSocketStream {
227
228
  string = webidl.converters.DOMString(chunk)
228
229
  } catch (e) {
229
230
  promise.reject(e)
230
- return
231
+ return promise.promise
231
232
  }
232
233
 
233
234
  // 5.2. Set data to the result of UTF-8 encoding string .
@@ -250,7 +251,7 @@ class WebSocketStream {
250
251
  }
251
252
 
252
253
  // 6.3. Queue a global task on the WebSocket task source given stream ’s relevant global object to resolve promise with undefined.
253
- return promise
254
+ return promise.promise
254
255
  }
255
256
 
256
257
  /** @type {import('../websocket').Handler['onConnectionEstablished']} */
@@ -476,7 +477,7 @@ webidl.converters.WebSocketStreamOptions = webidl.dictionaryConverter([
476
477
  webidl.converters.WebSocketCloseInfo = webidl.dictionaryConverter([
477
478
  {
478
479
  key: 'closeCode',
479
- converter: (V) => webidl.converters['unsigned short'](V, { enforceRange: true })
480
+ converter: (V) => webidl.converters['unsigned short'](V, webidl.attributes.EnforceRange)
480
481
  },
481
482
  {
482
483
  key: 'reason',
@@ -485,4 +486,12 @@ webidl.converters.WebSocketCloseInfo = webidl.dictionaryConverter([
485
486
  }
486
487
  ])
487
488
 
489
+ webidl.converters.WebSocketStreamWrite = function (V) {
490
+ if (typeof V === 'string') {
491
+ return webidl.converters.USVString(V)
492
+ }
493
+
494
+ return webidl.converters.BufferSource(V)
495
+ }
496
+
488
497
  module.exports = { WebSocketStream }