@depup/jsdom 28.1.0-depup.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 (538) hide show
  1. package/LICENSE.txt +22 -0
  2. package/README.md +38 -0
  3. package/changes.json +38 -0
  4. package/lib/api.js +373 -0
  5. package/lib/generated/event-sets.js +115 -0
  6. package/lib/generated/idl/AbortController.js +143 -0
  7. package/lib/generated/idl/AbortSignal.js +249 -0
  8. package/lib/generated/idl/AbstractRange.js +171 -0
  9. package/lib/generated/idl/AddEventListenerOptions.js +53 -0
  10. package/lib/generated/idl/AssignedNodesOptions.js +28 -0
  11. package/lib/generated/idl/Attr.js +219 -0
  12. package/lib/generated/idl/BarProp.js +117 -0
  13. package/lib/generated/idl/BeforeUnloadEvent.js +139 -0
  14. package/lib/generated/idl/BinaryType.js +12 -0
  15. package/lib/generated/idl/Blob.js +253 -0
  16. package/lib/generated/idl/BlobCallback.js +30 -0
  17. package/lib/generated/idl/BlobEvent.js +157 -0
  18. package/lib/generated/idl/BlobEventInit.js +43 -0
  19. package/lib/generated/idl/BlobPropertyBag.js +42 -0
  20. package/lib/generated/idl/CDATASection.js +109 -0
  21. package/lib/generated/idl/CanPlayTypeResult.js +12 -0
  22. package/lib/generated/idl/CharacterData.js +455 -0
  23. package/lib/generated/idl/CloseEvent.js +168 -0
  24. package/lib/generated/idl/CloseEventInit.js +65 -0
  25. package/lib/generated/idl/Comment.js +120 -0
  26. package/lib/generated/idl/CompositionEvent.js +219 -0
  27. package/lib/generated/idl/CompositionEventInit.js +32 -0
  28. package/lib/generated/idl/Crypto.js +148 -0
  29. package/lib/generated/idl/CustomElementConstructor.js +34 -0
  30. package/lib/generated/idl/CustomElementRegistry.js +269 -0
  31. package/lib/generated/idl/CustomEvent.js +206 -0
  32. package/lib/generated/idl/CustomEventInit.js +32 -0
  33. package/lib/generated/idl/DOMException.js +222 -0
  34. package/lib/generated/idl/DOMImplementation.js +237 -0
  35. package/lib/generated/idl/DOMParser.js +140 -0
  36. package/lib/generated/idl/DOMRect.js +276 -0
  37. package/lib/generated/idl/DOMRectInit.js +76 -0
  38. package/lib/generated/idl/DOMRectReadOnly.js +285 -0
  39. package/lib/generated/idl/DOMStringMap.js +299 -0
  40. package/lib/generated/idl/DOMTokenList.js +539 -0
  41. package/lib/generated/idl/DeviceMotionEvent.js +183 -0
  42. package/lib/generated/idl/DeviceMotionEventAcceleration.js +145 -0
  43. package/lib/generated/idl/DeviceMotionEventAccelerationInit.js +61 -0
  44. package/lib/generated/idl/DeviceMotionEventInit.js +70 -0
  45. package/lib/generated/idl/DeviceMotionEventRotationRate.js +145 -0
  46. package/lib/generated/idl/DeviceMotionEventRotationRateInit.js +61 -0
  47. package/lib/generated/idl/DeviceOrientationEvent.js +183 -0
  48. package/lib/generated/idl/DeviceOrientationEventInit.js +80 -0
  49. package/lib/generated/idl/Document.js +4511 -0
  50. package/lib/generated/idl/DocumentFragment.js +336 -0
  51. package/lib/generated/idl/DocumentReadyState.js +12 -0
  52. package/lib/generated/idl/DocumentType.js +254 -0
  53. package/lib/generated/idl/Element.js +3720 -0
  54. package/lib/generated/idl/ElementCreationOptions.js +26 -0
  55. package/lib/generated/idl/ElementDefinitionOptions.js +29 -0
  56. package/lib/generated/idl/ElementInternals.js +2152 -0
  57. package/lib/generated/idl/EndingType.js +12 -0
  58. package/lib/generated/idl/ErrorEvent.js +192 -0
  59. package/lib/generated/idl/ErrorEventInit.js +92 -0
  60. package/lib/generated/idl/Event.js +430 -0
  61. package/lib/generated/idl/EventHandlerNonNull.js +36 -0
  62. package/lib/generated/idl/EventInit.js +58 -0
  63. package/lib/generated/idl/EventListener.js +35 -0
  64. package/lib/generated/idl/EventListenerOptions.js +28 -0
  65. package/lib/generated/idl/EventModifierInit.js +221 -0
  66. package/lib/generated/idl/EventTarget.js +259 -0
  67. package/lib/generated/idl/External.js +130 -0
  68. package/lib/generated/idl/File.js +185 -0
  69. package/lib/generated/idl/FileList.js +298 -0
  70. package/lib/generated/idl/FilePropertyBag.js +33 -0
  71. package/lib/generated/idl/FileReader.js +468 -0
  72. package/lib/generated/idl/FocusEvent.js +144 -0
  73. package/lib/generated/idl/FocusEventInit.js +36 -0
  74. package/lib/generated/idl/FormData.js +468 -0
  75. package/lib/generated/idl/Function.js +42 -0
  76. package/lib/generated/idl/GetRootNodeOptions.js +31 -0
  77. package/lib/generated/idl/HTMLAnchorElement.js +1026 -0
  78. package/lib/generated/idl/HTMLAreaElement.js +825 -0
  79. package/lib/generated/idl/HTMLAudioElement.js +111 -0
  80. package/lib/generated/idl/HTMLBRElement.js +156 -0
  81. package/lib/generated/idl/HTMLBaseElement.js +196 -0
  82. package/lib/generated/idl/HTMLBodyElement.js +880 -0
  83. package/lib/generated/idl/HTMLButtonElement.js +525 -0
  84. package/lib/generated/idl/HTMLCanvasElement.js +307 -0
  85. package/lib/generated/idl/HTMLCollection.js +352 -0
  86. package/lib/generated/idl/HTMLDListElement.js +159 -0
  87. package/lib/generated/idl/HTMLDataElement.js +156 -0
  88. package/lib/generated/idl/HTMLDataListElement.js +126 -0
  89. package/lib/generated/idl/HTMLDetailsElement.js +159 -0
  90. package/lib/generated/idl/HTMLDialogElement.js +159 -0
  91. package/lib/generated/idl/HTMLDirectoryElement.js +159 -0
  92. package/lib/generated/idl/HTMLDivElement.js +156 -0
  93. package/lib/generated/idl/HTMLElement.js +3492 -0
  94. package/lib/generated/idl/HTMLEmbedElement.js +381 -0
  95. package/lib/generated/idl/HTMLFieldSetElement.js +332 -0
  96. package/lib/generated/idl/HTMLFontElement.js +239 -0
  97. package/lib/generated/idl/HTMLFormControlsCollection.js +318 -0
  98. package/lib/generated/idl/HTMLFormElement.js +661 -0
  99. package/lib/generated/idl/HTMLFrameElement.js +513 -0
  100. package/lib/generated/idl/HTMLFrameSetElement.js +711 -0
  101. package/lib/generated/idl/HTMLHRElement.js +323 -0
  102. package/lib/generated/idl/HTMLHeadElement.js +111 -0
  103. package/lib/generated/idl/HTMLHeadingElement.js +156 -0
  104. package/lib/generated/idl/HTMLHtmlElement.js +156 -0
  105. package/lib/generated/idl/HTMLIFrameElement.js +689 -0
  106. package/lib/generated/idl/HTMLImageElement.js +906 -0
  107. package/lib/generated/idl/HTMLInputElement.js +1931 -0
  108. package/lib/generated/idl/HTMLLIElement.js +204 -0
  109. package/lib/generated/idl/HTMLLabelElement.js +182 -0
  110. package/lib/generated/idl/HTMLLegendElement.js +169 -0
  111. package/lib/generated/idl/HTMLLinkElement.js +555 -0
  112. package/lib/generated/idl/HTMLMapElement.js +171 -0
  113. package/lib/generated/idl/HTMLMarqueeElement.js +558 -0
  114. package/lib/generated/idl/HTMLMediaElement.js +900 -0
  115. package/lib/generated/idl/HTMLMenuElement.js +159 -0
  116. package/lib/generated/idl/HTMLMetaElement.js +279 -0
  117. package/lib/generated/idl/HTMLMeterElement.js +368 -0
  118. package/lib/generated/idl/HTMLModElement.js +217 -0
  119. package/lib/generated/idl/HTMLOListElement.js +284 -0
  120. package/lib/generated/idl/HTMLObjectElement.js +945 -0
  121. package/lib/generated/idl/HTMLOptGroupElement.js +200 -0
  122. package/lib/generated/idl/HTMLOptionElement.js +379 -0
  123. package/lib/generated/idl/HTMLOptionsCollection.js +513 -0
  124. package/lib/generated/idl/HTMLOutputElement.js +395 -0
  125. package/lib/generated/idl/HTMLParagraphElement.js +156 -0
  126. package/lib/generated/idl/HTMLParamElement.js +279 -0
  127. package/lib/generated/idl/HTMLPictureElement.js +111 -0
  128. package/lib/generated/idl/HTMLPreElement.js +163 -0
  129. package/lib/generated/idl/HTMLProgressElement.js +232 -0
  130. package/lib/generated/idl/HTMLQuoteElement.js +176 -0
  131. package/lib/generated/idl/HTMLScriptElement.js +472 -0
  132. package/lib/generated/idl/HTMLSelectElement.js +993 -0
  133. package/lib/generated/idl/HTMLSlotElement.js +195 -0
  134. package/lib/generated/idl/HTMLSourceElement.js +340 -0
  135. package/lib/generated/idl/HTMLSpanElement.js +111 -0
  136. package/lib/generated/idl/HTMLStyleElement.js +210 -0
  137. package/lib/generated/idl/HTMLTableCaptionElement.js +156 -0
  138. package/lib/generated/idl/HTMLTableCellElement.js +733 -0
  139. package/lib/generated/idl/HTMLTableColElement.js +376 -0
  140. package/lib/generated/idl/HTMLTableElement.js +802 -0
  141. package/lib/generated/idl/HTMLTableRowElement.js +417 -0
  142. package/lib/generated/idl/HTMLTableSectionElement.js +349 -0
  143. package/lib/generated/idl/HTMLTemplateElement.js +124 -0
  144. package/lib/generated/idl/HTMLTextAreaElement.js +1210 -0
  145. package/lib/generated/idl/HTMLTimeElement.js +156 -0
  146. package/lib/generated/idl/HTMLTitleElement.js +155 -0
  147. package/lib/generated/idl/HTMLTrackElement.js +366 -0
  148. package/lib/generated/idl/HTMLUListElement.js +200 -0
  149. package/lib/generated/idl/HTMLUnknownElement.js +109 -0
  150. package/lib/generated/idl/HTMLVideoElement.js +344 -0
  151. package/lib/generated/idl/HashChangeEvent.js +157 -0
  152. package/lib/generated/idl/HashChangeEventInit.js +50 -0
  153. package/lib/generated/idl/Headers.js +418 -0
  154. package/lib/generated/idl/History.js +266 -0
  155. package/lib/generated/idl/InputEvent.js +168 -0
  156. package/lib/generated/idl/InputEventInit.js +68 -0
  157. package/lib/generated/idl/KeyboardEvent.js +445 -0
  158. package/lib/generated/idl/KeyboardEventInit.js +116 -0
  159. package/lib/generated/idl/Location.js +404 -0
  160. package/lib/generated/idl/MessageEvent.js +317 -0
  161. package/lib/generated/idl/MessageEventInit.js +100 -0
  162. package/lib/generated/idl/MimeType.js +156 -0
  163. package/lib/generated/idl/MimeTypeArray.js +326 -0
  164. package/lib/generated/idl/MouseEvent.js +595 -0
  165. package/lib/generated/idl/MouseEventInit.js +189 -0
  166. package/lib/generated/idl/MutationCallback.js +34 -0
  167. package/lib/generated/idl/MutationObserver.js +178 -0
  168. package/lib/generated/idl/MutationObserverInit.js +121 -0
  169. package/lib/generated/idl/MutationRecord.js +229 -0
  170. package/lib/generated/idl/NamedNodeMap.js +529 -0
  171. package/lib/generated/idl/Navigator.js +326 -0
  172. package/lib/generated/idl/Node.js +765 -0
  173. package/lib/generated/idl/NodeFilter.js +75 -0
  174. package/lib/generated/idl/NodeIterator.js +207 -0
  175. package/lib/generated/idl/NodeList.js +302 -0
  176. package/lib/generated/idl/OnBeforeUnloadEventHandlerNonNull.js +42 -0
  177. package/lib/generated/idl/OnErrorEventHandlerNonNull.js +56 -0
  178. package/lib/generated/idl/PageTransitionEvent.js +144 -0
  179. package/lib/generated/idl/PageTransitionEventInit.js +35 -0
  180. package/lib/generated/idl/Performance.js +142 -0
  181. package/lib/generated/idl/Plugin.js +359 -0
  182. package/lib/generated/idl/PluginArray.js +336 -0
  183. package/lib/generated/idl/PointerEvent.js +324 -0
  184. package/lib/generated/idl/PointerEventInit.js +241 -0
  185. package/lib/generated/idl/PopStateEvent.js +144 -0
  186. package/lib/generated/idl/PopStateEventInit.js +32 -0
  187. package/lib/generated/idl/ProcessingInstruction.js +122 -0
  188. package/lib/generated/idl/ProgressEvent.js +170 -0
  189. package/lib/generated/idl/ProgressEventInit.js +65 -0
  190. package/lib/generated/idl/PromiseRejectionEvent.js +157 -0
  191. package/lib/generated/idl/PromiseRejectionEventInit.js +42 -0
  192. package/lib/generated/idl/RadioNodeList.js +296 -0
  193. package/lib/generated/idl/Range.js +643 -0
  194. package/lib/generated/idl/SVGAnimatedPreserveAspectRatio.js +136 -0
  195. package/lib/generated/idl/SVGAnimatedRect.js +136 -0
  196. package/lib/generated/idl/SVGAnimatedString.js +149 -0
  197. package/lib/generated/idl/SVGBoundingBoxOptions.js +64 -0
  198. package/lib/generated/idl/SVGDefsElement.js +109 -0
  199. package/lib/generated/idl/SVGDescElement.js +109 -0
  200. package/lib/generated/idl/SVGElement.js +3157 -0
  201. package/lib/generated/idl/SVGGElement.js +109 -0
  202. package/lib/generated/idl/SVGGraphicsElement.js +139 -0
  203. package/lib/generated/idl/SVGMetadataElement.js +109 -0
  204. package/lib/generated/idl/SVGNumber.js +132 -0
  205. package/lib/generated/idl/SVGPreserveAspectRatio.js +196 -0
  206. package/lib/generated/idl/SVGRect.js +210 -0
  207. package/lib/generated/idl/SVGSVGElement.js +786 -0
  208. package/lib/generated/idl/SVGStringList.js +511 -0
  209. package/lib/generated/idl/SVGSwitchElement.js +109 -0
  210. package/lib/generated/idl/SVGSymbolElement.js +146 -0
  211. package/lib/generated/idl/SVGTitleElement.js +109 -0
  212. package/lib/generated/idl/Screen.js +180 -0
  213. package/lib/generated/idl/ScrollBehavior.js +12 -0
  214. package/lib/generated/idl/ScrollIntoViewOptions.js +45 -0
  215. package/lib/generated/idl/ScrollLogicalPosition.js +14 -0
  216. package/lib/generated/idl/ScrollOptions.js +30 -0
  217. package/lib/generated/idl/ScrollRestoration.js +12 -0
  218. package/lib/generated/idl/Selection.js +571 -0
  219. package/lib/generated/idl/SelectionMode.js +12 -0
  220. package/lib/generated/idl/ShadowRoot.js +189 -0
  221. package/lib/generated/idl/ShadowRootInit.js +30 -0
  222. package/lib/generated/idl/ShadowRootMode.js +12 -0
  223. package/lib/generated/idl/StaticRange.js +123 -0
  224. package/lib/generated/idl/StaticRangeInit.js +72 -0
  225. package/lib/generated/idl/Storage.js +397 -0
  226. package/lib/generated/idl/StorageEvent.js +318 -0
  227. package/lib/generated/idl/StorageEventInit.js +99 -0
  228. package/lib/generated/idl/StyleSheetList.js +300 -0
  229. package/lib/generated/idl/SubmitEvent.js +144 -0
  230. package/lib/generated/idl/SubmitEventInit.js +36 -0
  231. package/lib/generated/idl/SupportedType.js +18 -0
  232. package/lib/generated/idl/Text.js +170 -0
  233. package/lib/generated/idl/TextDecodeOptions.js +28 -0
  234. package/lib/generated/idl/TextDecoder.js +211 -0
  235. package/lib/generated/idl/TextDecoderOptions.js +43 -0
  236. package/lib/generated/idl/TextEncoder.js +176 -0
  237. package/lib/generated/idl/TextEncoderEncodeIntoResult.js +42 -0
  238. package/lib/generated/idl/TextTrackKind.js +12 -0
  239. package/lib/generated/idl/TouchEvent.js +222 -0
  240. package/lib/generated/idl/TouchEventInit.js +89 -0
  241. package/lib/generated/idl/TransitionEvent.js +170 -0
  242. package/lib/generated/idl/TransitionEventInit.js +65 -0
  243. package/lib/generated/idl/TreeWalker.js +255 -0
  244. package/lib/generated/idl/UIEvent.js +235 -0
  245. package/lib/generated/idl/UIEventInit.js +62 -0
  246. package/lib/generated/idl/ValidityState.js +249 -0
  247. package/lib/generated/idl/VisibilityState.js +12 -0
  248. package/lib/generated/idl/VoidFunction.js +26 -0
  249. package/lib/generated/idl/WebSocket.js +480 -0
  250. package/lib/generated/idl/WheelEvent.js +191 -0
  251. package/lib/generated/idl/WheelEventInit.js +71 -0
  252. package/lib/generated/idl/XMLDocument.js +109 -0
  253. package/lib/generated/idl/XMLHttpRequest.js +663 -0
  254. package/lib/generated/idl/XMLHttpRequestEventTarget.js +334 -0
  255. package/lib/generated/idl/XMLHttpRequestResponseType.js +14 -0
  256. package/lib/generated/idl/XMLHttpRequestUpload.js +109 -0
  257. package/lib/generated/idl/XMLSerializer.js +132 -0
  258. package/lib/generated/idl/utils.js +252 -0
  259. package/lib/generated/js-globals.json +332 -0
  260. package/lib/jsdom/browser/Window.js +952 -0
  261. package/lib/jsdom/browser/default-stylesheet.css +415 -0
  262. package/lib/jsdom/browser/not-implemented.js +20 -0
  263. package/lib/jsdom/browser/parser/html.js +208 -0
  264. package/lib/jsdom/browser/parser/index.js +37 -0
  265. package/lib/jsdom/browser/parser/xml.js +202 -0
  266. package/lib/jsdom/browser/resources/async-resource-queue.js +114 -0
  267. package/lib/jsdom/browser/resources/decompress-interceptor.js +184 -0
  268. package/lib/jsdom/browser/resources/jsdom-dispatcher.js +756 -0
  269. package/lib/jsdom/browser/resources/per-document-resource-loader.js +116 -0
  270. package/lib/jsdom/browser/resources/request-interceptor.js +171 -0
  271. package/lib/jsdom/browser/resources/request-manager.js +33 -0
  272. package/lib/jsdom/browser/resources/resource-queue.js +142 -0
  273. package/lib/jsdom/browser/resources/stream-handler.js +89 -0
  274. package/lib/jsdom/level2/style.js +65 -0
  275. package/lib/jsdom/level3/xpath.js +1875 -0
  276. package/lib/jsdom/living/aborting/AbortController-impl.js +17 -0
  277. package/lib/jsdom/living/aborting/AbortSignal-impl.js +131 -0
  278. package/lib/jsdom/living/attributes/Attr-impl.js +60 -0
  279. package/lib/jsdom/living/attributes/NamedNodeMap-impl.js +78 -0
  280. package/lib/jsdom/living/attributes.js +312 -0
  281. package/lib/jsdom/living/constraint-validation/DefaultConstraintValidation-impl.js +75 -0
  282. package/lib/jsdom/living/constraint-validation/ValidityState-impl.js +66 -0
  283. package/lib/jsdom/living/crypto/Crypto-impl.js +68 -0
  284. package/lib/jsdom/living/cssom/StyleSheetList-impl.js +38 -0
  285. package/lib/jsdom/living/custom-elements/CustomElementRegistry-impl.js +279 -0
  286. package/lib/jsdom/living/custom-elements/ElementInternals-impl.js +56 -0
  287. package/lib/jsdom/living/deviceorientation/DeviceMotionEventAcceleration-impl.js +7 -0
  288. package/lib/jsdom/living/deviceorientation/DeviceMotionEventRotationRate-impl.js +7 -0
  289. package/lib/jsdom/living/documents.js +15 -0
  290. package/lib/jsdom/living/domparsing/DOMParser-impl.js +59 -0
  291. package/lib/jsdom/living/domparsing/InnerHTML-impl.js +30 -0
  292. package/lib/jsdom/living/domparsing/XMLSerializer-impl.js +18 -0
  293. package/lib/jsdom/living/domparsing/parse5-adapter-serialization.js +63 -0
  294. package/lib/jsdom/living/domparsing/serialization.js +36 -0
  295. package/lib/jsdom/living/encoding/TextDecoder-impl.js +25 -0
  296. package/lib/jsdom/living/encoding/TextEncoder-impl.js +26 -0
  297. package/lib/jsdom/living/events/BeforeUnloadEvent-impl.js +12 -0
  298. package/lib/jsdom/living/events/BlobEvent-impl.js +14 -0
  299. package/lib/jsdom/living/events/CloseEvent-impl.js +10 -0
  300. package/lib/jsdom/living/events/CompositionEvent-impl.js +20 -0
  301. package/lib/jsdom/living/events/CustomEvent-impl.js +21 -0
  302. package/lib/jsdom/living/events/DeviceMotionEvent-impl.js +49 -0
  303. package/lib/jsdom/living/events/DeviceOrientationEvent-impl.js +10 -0
  304. package/lib/jsdom/living/events/ErrorEvent-impl.js +14 -0
  305. package/lib/jsdom/living/events/Event-impl.js +195 -0
  306. package/lib/jsdom/living/events/EventModifierMixin-impl.js +24 -0
  307. package/lib/jsdom/living/events/EventTarget-impl.js +438 -0
  308. package/lib/jsdom/living/events/FocusEvent-impl.js +9 -0
  309. package/lib/jsdom/living/events/HashChangeEvent-impl.js +14 -0
  310. package/lib/jsdom/living/events/InputEvent-impl.js +11 -0
  311. package/lib/jsdom/living/events/KeyboardEvent-impl.js +29 -0
  312. package/lib/jsdom/living/events/MessageEvent-impl.js +25 -0
  313. package/lib/jsdom/living/events/MouseEvent-impl.js +72 -0
  314. package/lib/jsdom/living/events/PageTransitionEvent-impl.js +20 -0
  315. package/lib/jsdom/living/events/PointerEvent-impl.js +21 -0
  316. package/lib/jsdom/living/events/PopStateEvent-impl.js +9 -0
  317. package/lib/jsdom/living/events/ProgressEvent-impl.js +14 -0
  318. package/lib/jsdom/living/events/PromiseRejectionEvent-impl.js +14 -0
  319. package/lib/jsdom/living/events/StorageEvent-impl.js +26 -0
  320. package/lib/jsdom/living/events/SubmitEvent-impl.js +13 -0
  321. package/lib/jsdom/living/events/TouchEvent-impl.js +14 -0
  322. package/lib/jsdom/living/events/TransitionEvent-impl.js +10 -0
  323. package/lib/jsdom/living/events/UIEvent-impl.js +43 -0
  324. package/lib/jsdom/living/events/WheelEvent-impl.js +12 -0
  325. package/lib/jsdom/living/fetch/Headers-impl.js +173 -0
  326. package/lib/jsdom/living/fetch/header-list.js +158 -0
  327. package/lib/jsdom/living/fetch/header-types.js +205 -0
  328. package/lib/jsdom/living/fetch/header-utils.js +26 -0
  329. package/lib/jsdom/living/file-api/Blob-impl.js +125 -0
  330. package/lib/jsdom/living/file-api/File-impl.js +12 -0
  331. package/lib/jsdom/living/file-api/FileList-impl.js +15 -0
  332. package/lib/jsdom/living/file-api/FileReader-impl.js +148 -0
  333. package/lib/jsdom/living/geometry/DOMRect-impl.js +39 -0
  334. package/lib/jsdom/living/geometry/DOMRectReadOnly-impl.js +72 -0
  335. package/lib/jsdom/living/helpers/binary-data.js +63 -0
  336. package/lib/jsdom/living/helpers/by-id-cache.js +67 -0
  337. package/lib/jsdom/living/helpers/colors.js +245 -0
  338. package/lib/jsdom/living/helpers/create-element.js +329 -0
  339. package/lib/jsdom/living/helpers/create-event-accessor.js +209 -0
  340. package/lib/jsdom/living/helpers/custom-elements.js +272 -0
  341. package/lib/jsdom/living/helpers/dates-and-times.js +270 -0
  342. package/lib/jsdom/living/helpers/details.js +15 -0
  343. package/lib/jsdom/living/helpers/encoding.js +60 -0
  344. package/lib/jsdom/living/helpers/events.js +24 -0
  345. package/lib/jsdom/living/helpers/focusing.js +104 -0
  346. package/lib/jsdom/living/helpers/form-controls.js +309 -0
  347. package/lib/jsdom/living/helpers/html-constructor.js +78 -0
  348. package/lib/jsdom/living/helpers/internal-constants.js +12 -0
  349. package/lib/jsdom/living/helpers/is-window.js +18 -0
  350. package/lib/jsdom/living/helpers/iterable-weak-set.js +48 -0
  351. package/lib/jsdom/living/helpers/json.js +7 -0
  352. package/lib/jsdom/living/helpers/mutation-observers.js +198 -0
  353. package/lib/jsdom/living/helpers/namespaces.js +16 -0
  354. package/lib/jsdom/living/helpers/node.js +108 -0
  355. package/lib/jsdom/living/helpers/number-and-date-inputs.js +195 -0
  356. package/lib/jsdom/living/helpers/ordered-set.js +104 -0
  357. package/lib/jsdom/living/helpers/page-transition-event.js +9 -0
  358. package/lib/jsdom/living/helpers/runtime-script-errors.js +75 -0
  359. package/lib/jsdom/living/helpers/shadow-dom.js +285 -0
  360. package/lib/jsdom/living/helpers/strings.js +168 -0
  361. package/lib/jsdom/living/helpers/style-rules.js +404 -0
  362. package/lib/jsdom/living/helpers/stylesheets.js +148 -0
  363. package/lib/jsdom/living/helpers/svg/basic-types.js +41 -0
  364. package/lib/jsdom/living/helpers/svg/render.js +46 -0
  365. package/lib/jsdom/living/helpers/system-colors.js +147 -0
  366. package/lib/jsdom/living/helpers/text.js +19 -0
  367. package/lib/jsdom/living/helpers/traversal.js +72 -0
  368. package/lib/jsdom/living/helpers/validate-names.js +65 -0
  369. package/lib/jsdom/living/hr-time/Performance-impl.js +22 -0
  370. package/lib/jsdom/living/interfaces.js +252 -0
  371. package/lib/jsdom/living/mutation-observer/MutationObserver-impl.js +95 -0
  372. package/lib/jsdom/living/mutation-observer/MutationRecord-impl.js +37 -0
  373. package/lib/jsdom/living/navigator/MimeType-impl.js +3 -0
  374. package/lib/jsdom/living/navigator/MimeTypeArray-impl.js +21 -0
  375. package/lib/jsdom/living/navigator/Navigator-impl.js +29 -0
  376. package/lib/jsdom/living/navigator/NavigatorConcurrentHardware-impl.js +8 -0
  377. package/lib/jsdom/living/navigator/NavigatorCookies-impl.js +7 -0
  378. package/lib/jsdom/living/navigator/NavigatorID-impl.js +37 -0
  379. package/lib/jsdom/living/navigator/NavigatorLanguage-impl.js +9 -0
  380. package/lib/jsdom/living/navigator/NavigatorOnLine-impl.js +7 -0
  381. package/lib/jsdom/living/navigator/NavigatorPlugins-impl.js +8 -0
  382. package/lib/jsdom/living/navigator/Plugin-impl.js +3 -0
  383. package/lib/jsdom/living/navigator/PluginArray-impl.js +23 -0
  384. package/lib/jsdom/living/node-document-position.js +10 -0
  385. package/lib/jsdom/living/node-type.js +16 -0
  386. package/lib/jsdom/living/node.js +331 -0
  387. package/lib/jsdom/living/nodes/CDATASection-impl.js +16 -0
  388. package/lib/jsdom/living/nodes/CharacterData-impl.js +118 -0
  389. package/lib/jsdom/living/nodes/ChildNode-impl.js +80 -0
  390. package/lib/jsdom/living/nodes/Comment-impl.js +20 -0
  391. package/lib/jsdom/living/nodes/DOMImplementation-impl.js +120 -0
  392. package/lib/jsdom/living/nodes/DOMStringMap-impl.js +64 -0
  393. package/lib/jsdom/living/nodes/DOMTokenList-impl.js +171 -0
  394. package/lib/jsdom/living/nodes/Document-impl.js +1000 -0
  395. package/lib/jsdom/living/nodes/DocumentFragment-impl.js +44 -0
  396. package/lib/jsdom/living/nodes/DocumentOrShadowRoot-impl.js +28 -0
  397. package/lib/jsdom/living/nodes/DocumentType-impl.js +24 -0
  398. package/lib/jsdom/living/nodes/Element-impl.js +584 -0
  399. package/lib/jsdom/living/nodes/ElementCSSInlineStyle-impl.js +22 -0
  400. package/lib/jsdom/living/nodes/ElementContentEditable-impl.js +7 -0
  401. package/lib/jsdom/living/nodes/GlobalEventHandlers-impl.js +81 -0
  402. package/lib/jsdom/living/nodes/HTMLAnchorElement-impl.js +50 -0
  403. package/lib/jsdom/living/nodes/HTMLAreaElement-impl.js +43 -0
  404. package/lib/jsdom/living/nodes/HTMLAudioElement-impl.js +9 -0
  405. package/lib/jsdom/living/nodes/HTMLBRElement-impl.js +9 -0
  406. package/lib/jsdom/living/nodes/HTMLBaseElement-impl.js +44 -0
  407. package/lib/jsdom/living/nodes/HTMLBodyElement-impl.js +12 -0
  408. package/lib/jsdom/living/nodes/HTMLButtonElement-impl.js +79 -0
  409. package/lib/jsdom/living/nodes/HTMLCanvasElement-impl.js +136 -0
  410. package/lib/jsdom/living/nodes/HTMLCollection-impl.js +96 -0
  411. package/lib/jsdom/living/nodes/HTMLDListElement-impl.js +9 -0
  412. package/lib/jsdom/living/nodes/HTMLDataElement-impl.js +9 -0
  413. package/lib/jsdom/living/nodes/HTMLDataListElement-impl.js +20 -0
  414. package/lib/jsdom/living/nodes/HTMLDetailsElement-impl.js +35 -0
  415. package/lib/jsdom/living/nodes/HTMLDialogElement-impl.js +9 -0
  416. package/lib/jsdom/living/nodes/HTMLDirectoryElement-impl.js +9 -0
  417. package/lib/jsdom/living/nodes/HTMLDivElement-impl.js +9 -0
  418. package/lib/jsdom/living/nodes/HTMLElement-impl.js +211 -0
  419. package/lib/jsdom/living/nodes/HTMLEmbedElement-impl.js +8 -0
  420. package/lib/jsdom/living/nodes/HTMLFieldSetElement-impl.js +43 -0
  421. package/lib/jsdom/living/nodes/HTMLFontElement-impl.js +9 -0
  422. package/lib/jsdom/living/nodes/HTMLFormControlsCollection-impl.js +33 -0
  423. package/lib/jsdom/living/nodes/HTMLFormElement-impl.js +248 -0
  424. package/lib/jsdom/living/nodes/HTMLFrameElement-impl.js +266 -0
  425. package/lib/jsdom/living/nodes/HTMLFrameSetElement-impl.js +12 -0
  426. package/lib/jsdom/living/nodes/HTMLHRElement-impl.js +9 -0
  427. package/lib/jsdom/living/nodes/HTMLHeadElement-impl.js +9 -0
  428. package/lib/jsdom/living/nodes/HTMLHeadingElement-impl.js +9 -0
  429. package/lib/jsdom/living/nodes/HTMLHtmlElement-impl.js +9 -0
  430. package/lib/jsdom/living/nodes/HTMLHyperlinkElementUtils-impl.js +368 -0
  431. package/lib/jsdom/living/nodes/HTMLIFrameElement-impl.js +9 -0
  432. package/lib/jsdom/living/nodes/HTMLImageElement-impl.js +127 -0
  433. package/lib/jsdom/living/nodes/HTMLInputElement-impl.js +1097 -0
  434. package/lib/jsdom/living/nodes/HTMLLIElement-impl.js +9 -0
  435. package/lib/jsdom/living/nodes/HTMLLabelElement-impl.js +94 -0
  436. package/lib/jsdom/living/nodes/HTMLLegendElement-impl.js +18 -0
  437. package/lib/jsdom/living/nodes/HTMLLinkElement-impl.js +107 -0
  438. package/lib/jsdom/living/nodes/HTMLMapElement-impl.js +13 -0
  439. package/lib/jsdom/living/nodes/HTMLMarqueeElement-impl.js +9 -0
  440. package/lib/jsdom/living/nodes/HTMLMediaElement-impl.js +138 -0
  441. package/lib/jsdom/living/nodes/HTMLMenuElement-impl.js +9 -0
  442. package/lib/jsdom/living/nodes/HTMLMetaElement-impl.js +9 -0
  443. package/lib/jsdom/living/nodes/HTMLMeterElement-impl.js +180 -0
  444. package/lib/jsdom/living/nodes/HTMLModElement-impl.js +9 -0
  445. package/lib/jsdom/living/nodes/HTMLOListElement-impl.js +22 -0
  446. package/lib/jsdom/living/nodes/HTMLObjectElement-impl.js +26 -0
  447. package/lib/jsdom/living/nodes/HTMLOptGroupElement-impl.js +9 -0
  448. package/lib/jsdom/living/nodes/HTMLOptionElement-impl.js +146 -0
  449. package/lib/jsdom/living/nodes/HTMLOptionsCollection-impl.js +110 -0
  450. package/lib/jsdom/living/nodes/HTMLOrSVGElement-impl.js +88 -0
  451. package/lib/jsdom/living/nodes/HTMLOutputElement-impl.js +88 -0
  452. package/lib/jsdom/living/nodes/HTMLParagraphElement-impl.js +9 -0
  453. package/lib/jsdom/living/nodes/HTMLParamElement-impl.js +9 -0
  454. package/lib/jsdom/living/nodes/HTMLPictureElement-impl.js +9 -0
  455. package/lib/jsdom/living/nodes/HTMLPreElement-impl.js +9 -0
  456. package/lib/jsdom/living/nodes/HTMLProgressElement-impl.js +72 -0
  457. package/lib/jsdom/living/nodes/HTMLQuoteElement-impl.js +9 -0
  458. package/lib/jsdom/living/nodes/HTMLScriptElement-impl.js +255 -0
  459. package/lib/jsdom/living/nodes/HTMLSelectElement-impl.js +283 -0
  460. package/lib/jsdom/living/nodes/HTMLSlotElement-impl.js +59 -0
  461. package/lib/jsdom/living/nodes/HTMLSourceElement-impl.js +8 -0
  462. package/lib/jsdom/living/nodes/HTMLSpanElement-impl.js +9 -0
  463. package/lib/jsdom/living/nodes/HTMLStyleElement-impl.js +76 -0
  464. package/lib/jsdom/living/nodes/HTMLTableCaptionElement-impl.js +9 -0
  465. package/lib/jsdom/living/nodes/HTMLTableCellElement-impl.js +73 -0
  466. package/lib/jsdom/living/nodes/HTMLTableColElement-impl.js +9 -0
  467. package/lib/jsdom/living/nodes/HTMLTableElement-impl.js +236 -0
  468. package/lib/jsdom/living/nodes/HTMLTableRowElement-impl.js +88 -0
  469. package/lib/jsdom/living/nodes/HTMLTableSectionElement-impl.js +61 -0
  470. package/lib/jsdom/living/nodes/HTMLTemplateElement-impl.js +67 -0
  471. package/lib/jsdom/living/nodes/HTMLTextAreaElement-impl.js +244 -0
  472. package/lib/jsdom/living/nodes/HTMLTimeElement-impl.js +9 -0
  473. package/lib/jsdom/living/nodes/HTMLTitleElement-impl.js +18 -0
  474. package/lib/jsdom/living/nodes/HTMLTrackElement-impl.js +13 -0
  475. package/lib/jsdom/living/nodes/HTMLUListElement-impl.js +9 -0
  476. package/lib/jsdom/living/nodes/HTMLUnknownElement-impl.js +9 -0
  477. package/lib/jsdom/living/nodes/HTMLVideoElement-impl.js +17 -0
  478. package/lib/jsdom/living/nodes/LinkStyle-impl.js +2 -0
  479. package/lib/jsdom/living/nodes/Node-impl.js +1179 -0
  480. package/lib/jsdom/living/nodes/NodeList-impl.js +43 -0
  481. package/lib/jsdom/living/nodes/NonDocumentTypeChildNode-impl.js +28 -0
  482. package/lib/jsdom/living/nodes/NonElementParentNode-impl.js +11 -0
  483. package/lib/jsdom/living/nodes/ParentNode-impl.js +90 -0
  484. package/lib/jsdom/living/nodes/ProcessingInstruction-impl.js +22 -0
  485. package/lib/jsdom/living/nodes/RadioNodeList-impl.js +49 -0
  486. package/lib/jsdom/living/nodes/SVGDefsElement-impl.js +9 -0
  487. package/lib/jsdom/living/nodes/SVGDescElement-impl.js +9 -0
  488. package/lib/jsdom/living/nodes/SVGElement-impl.js +64 -0
  489. package/lib/jsdom/living/nodes/SVGGElement-impl.js +9 -0
  490. package/lib/jsdom/living/nodes/SVGGraphicsElement-impl.js +16 -0
  491. package/lib/jsdom/living/nodes/SVGMetadataElement-impl.js +9 -0
  492. package/lib/jsdom/living/nodes/SVGSVGElement-impl.js +40 -0
  493. package/lib/jsdom/living/nodes/SVGSwitchElement-impl.js +9 -0
  494. package/lib/jsdom/living/nodes/SVGSymbolElement-impl.js +9 -0
  495. package/lib/jsdom/living/nodes/SVGTests-impl.js +42 -0
  496. package/lib/jsdom/living/nodes/SVGTitleElement-impl.js +9 -0
  497. package/lib/jsdom/living/nodes/ShadowRoot-impl.js +41 -0
  498. package/lib/jsdom/living/nodes/Slotable-impl.js +48 -0
  499. package/lib/jsdom/living/nodes/Text-impl.js +96 -0
  500. package/lib/jsdom/living/nodes/WindowEventHandlers-impl.js +14 -0
  501. package/lib/jsdom/living/nodes/XMLDocument-impl.js +4 -0
  502. package/lib/jsdom/living/range/AbstractRange-impl.js +43 -0
  503. package/lib/jsdom/living/range/Range-impl.js +902 -0
  504. package/lib/jsdom/living/range/StaticRange-impl.js +39 -0
  505. package/lib/jsdom/living/range/boundary-point.js +47 -0
  506. package/lib/jsdom/living/selection/Selection-impl.js +358 -0
  507. package/lib/jsdom/living/svg/SVGAnimatedPreserveAspectRatio-impl.js +24 -0
  508. package/lib/jsdom/living/svg/SVGAnimatedRect-impl.js +122 -0
  509. package/lib/jsdom/living/svg/SVGAnimatedString-impl.js +42 -0
  510. package/lib/jsdom/living/svg/SVGListBase.js +195 -0
  511. package/lib/jsdom/living/svg/SVGNumber-impl.js +48 -0
  512. package/lib/jsdom/living/svg/SVGPreserveAspectRatio-impl.js +100 -0
  513. package/lib/jsdom/living/svg/SVGRect-impl.js +143 -0
  514. package/lib/jsdom/living/svg/SVGStringList-impl.js +16 -0
  515. package/lib/jsdom/living/traversal/NodeIterator-impl.js +107 -0
  516. package/lib/jsdom/living/traversal/TreeWalker-impl.js +217 -0
  517. package/lib/jsdom/living/traversal/helpers.js +44 -0
  518. package/lib/jsdom/living/webidl/DOMException-impl.js +46 -0
  519. package/lib/jsdom/living/websockets/WebSocket-impl.js +211 -0
  520. package/lib/jsdom/living/webstorage/Storage-impl.js +102 -0
  521. package/lib/jsdom/living/window/BarProp-impl.js +10 -0
  522. package/lib/jsdom/living/window/External-impl.js +9 -0
  523. package/lib/jsdom/living/window/History-impl.js +148 -0
  524. package/lib/jsdom/living/window/Location-impl.js +227 -0
  525. package/lib/jsdom/living/window/Screen-impl.js +13 -0
  526. package/lib/jsdom/living/window/SessionHistory.js +163 -0
  527. package/lib/jsdom/living/window/navigation.js +87 -0
  528. package/lib/jsdom/living/window-properties.js +241 -0
  529. package/lib/jsdom/living/xhr/FormData-impl.js +191 -0
  530. package/lib/jsdom/living/xhr/XMLHttpRequest-impl.js +1057 -0
  531. package/lib/jsdom/living/xhr/XMLHttpRequestEventTarget-impl.js +17 -0
  532. package/lib/jsdom/living/xhr/XMLHttpRequestUpload-impl.js +4 -0
  533. package/lib/jsdom/living/xhr/multipart-form-data.js +99 -0
  534. package/lib/jsdom/living/xhr/xhr-sync-worker.js +51 -0
  535. package/lib/jsdom/living/xhr/xhr-utils.js +206 -0
  536. package/lib/jsdom/utils.js +105 -0
  537. package/lib/jsdom/virtual-console.js +46 -0
  538. package/package.json +143 -0
@@ -0,0 +1,756 @@
1
+ "use strict";
2
+ const fs = require("fs");
3
+ const { Readable } = require("stream");
4
+ const { fileURLToPath } = require("url");
5
+ const { parseURL, serializeURL, serializeURLOrigin, serializePath } = require("whatwg-url");
6
+ const dataURLFromRecord = require("data-urls").fromURLRecord;
7
+ const { Dispatcher } = require("undici");
8
+ const WrapHandler = require("undici/lib/handler/wrap-handler.js");
9
+ const UnwrapHandler = require("undici/lib/handler/unwrap-handler.js");
10
+ const { toBase64 } = require("@exodus/bytes/base64.js");
11
+ const { utf8Encode } = require("../../living/helpers/encoding");
12
+ const { sendStreamResponse } = require("./stream-handler");
13
+
14
+ const packageVersion = require("../../../../package.json").version;
15
+
16
+ const DEFAULT_USER_AGENT = `Mozilla/5.0 (${process.platform || "unknown OS"}) AppleWebKit/537.36 ` +
17
+ `(KHTML, like Gecko) jsdom/${packageVersion}`;
18
+ const MAX_REDIRECTS = 20;
19
+
20
+ /**
21
+ * JSDOMDispatcher - Full undici Dispatcher implementation for jsdom.
22
+ *
23
+ * Handles:
24
+ * - data: URLs (decode and return)
25
+ * - file: URLs (read from filesystem)
26
+ * - HTTP(S) and web sockets: follows redirects manually, capturing cookies at each hop
27
+ *
28
+ * Callers should provide the expected opaque fields when possible, to ensure that various parts of the jsdom pipeline
29
+ * have enough information. See the `dispatch()` JSDoc for details.
30
+ */
31
+ class JSDOMDispatcher extends Dispatcher {
32
+ #baseDispatcher;
33
+ #cookieJar;
34
+ #userAgent;
35
+ #userInterceptors;
36
+
37
+ constructor({ baseDispatcher, cookieJar, userAgent, userInterceptors = [] }) {
38
+ super();
39
+ this.#baseDispatcher = baseDispatcher;
40
+ this.#cookieJar = cookieJar;
41
+ this.#userAgent = userAgent || DEFAULT_USER_AGENT;
42
+ this.#userInterceptors = userInterceptors;
43
+ }
44
+
45
+ /**
46
+ * Dispatch a request through the jsdom resource loading pipeline.
47
+ *
48
+ * Vaguely corresponds to:
49
+ * - https://fetch.spec.whatwg.org/#concept-fetch: in theory, all jsdom fetches should go through here, like all web
50
+ * platform fetches go through #concept-fetch.
51
+ * - https://fetch.spec.whatwg.org/#concept-scheme-fetch: the code is more like skipping straight to scheme fetch.
52
+ *
53
+ * @param {object} opts - undici dispatch options
54
+ * @param {object} [opts.opaque] - jsdom-specific request context (may be undefined for WebSocket upgrades)
55
+ * @param {Element|null} opts.opaque.element - DOM element that triggered the request
56
+ * @param {string} opts.opaque.url - Full request URL (since we cannot reconstruct it from `opts.origin + opts.path`
57
+ * for `file:` URLs). If given, `opts.origin`, `opts.path`, and `opts.query` are ignored.
58
+ * @param {string} [opts.opaque.origin] - Request origin for CORS (used by XHR)
59
+ * @param {boolean} [opts.opaque.corsMode] - Enable CORS validation during redirects (used by XHR)
60
+ * @param {boolean} [opts.opaque.withCredentials] - Include cookies cross-origin (used by XHR)
61
+ * @param {Object} [opts.opaque.auth] - Auth credentials {user, pass} for 401 Basic auth handling
62
+ * @param {Object} [opts.opaque.preflight] - If present, do CORS preflight before main request
63
+ * @param {string[]} [opts.opaque.preflight.unsafeHeaders] - Non-simple headers that need to be allowed
64
+ * @param {object} handler - undici handler
65
+ */
66
+ dispatch(opts, handler) {
67
+ // Wrap handler to normalize OLD API (onConnect/onHeaders/onData/onComplete/onError) to NEW API
68
+ // (onRequestStart/onResponseStart/onResponseData/onResponseEnd/onResponseError). This is necessary because undici's
69
+ // internals call the old API a lot, despite it being undocumented:
70
+ // * https://github.com/nodejs/undici/issues/4771
71
+ // * https://github.com/nodejs/undici/issues/4780
72
+ const wrappedHandler = WrapHandler.wrap(handler);
73
+
74
+ // Get URL from opaque if present (required for file: URLs since they have origin "null"),
75
+ // otherwise reconstruct from opts.origin + opts.path (works for http/https/ws/wss)
76
+ const urlString = opts.opaque?.url || (opts.origin + opts.path);
77
+ const urlRecord = parseURL(urlString);
78
+
79
+ if (urlRecord === null) {
80
+ wrappedHandler.onResponseError?.(null, new TypeError(`Invalid URL: ${urlString}`));
81
+ return false;
82
+ }
83
+
84
+ if (urlRecord.scheme === "data") {
85
+ return this.#dispatchDataURL(urlRecord, wrappedHandler);
86
+ }
87
+
88
+ if (urlRecord.scheme === "file") {
89
+ return this.#dispatchFileURL(urlRecord, wrappedHandler);
90
+ }
91
+
92
+ // HTTP(S) - handles redirects, CORS, preflight, and WebSocket upgrades.
93
+ // #dispatchHTTP is async but we can't await it here (dispatch() must be sync per the undici Dispatcher API).
94
+ // Catch rejections so that errors (e.g. from the undici dispatch chain throwing) are forwarded to the handler
95
+ // instead of becoming unhandled rejections that silently prevent the response promise from ever resolving.
96
+ this.#dispatchHTTP(urlRecord, wrappedHandler, opts).catch(err => {
97
+ wrappedHandler.onResponseError?.(null, err);
98
+ });
99
+ return true;
100
+ }
101
+
102
+ /**
103
+ * Handle `data:` URLs by decoding them and returning the body.
104
+ *
105
+ * Corresponds fairly directly to https://fetch.spec.whatwg.org/#concept-scheme-fetch's "data" scheme case.
106
+ */
107
+ #dispatchDataURL(urlRecord, handler) {
108
+ const dataURL = dataURLFromRecord(urlRecord);
109
+ if (dataURL === null) {
110
+ const error = new TypeError("Invalid data: URL");
111
+ handler.onResponseError?.(null, error);
112
+ return false;
113
+ }
114
+
115
+ const stream = Readable.from([dataURL.body]);
116
+
117
+ sendStreamResponse(handler, stream, {
118
+ status: 200,
119
+ statusText: "OK",
120
+ headers: { "content-type": dataURL.mimeType.toString() },
121
+ context: { finalURL: urlRecord }
122
+ });
123
+
124
+ return true;
125
+ }
126
+
127
+ /**
128
+ * Handle `file:` URLs by reading from the filesystem.
129
+ *
130
+ * Corresponds fairly directly to https://fetch.spec.whatwg.org/#concept-scheme-fetch's "file" scheme case.
131
+ */
132
+ #dispatchFileURL(urlRecord, handler) {
133
+ const filePath = fileURLToPath(serializeURL(urlRecord));
134
+ const stream = fs.createReadStream(filePath);
135
+
136
+ sendStreamResponse(handler, stream, {
137
+ status: 200,
138
+ statusText: "OK",
139
+ context: { finalURL: urlRecord }
140
+ });
141
+
142
+ return true;
143
+ }
144
+
145
+ /**
146
+ * High-level HTTP(S) fetch with redirect handling, CORS validation, and preflight.
147
+ *
148
+ * Corresponds roughly to https://fetch.spec.whatwg.org/#concept-http-fetch, although some parts of
149
+ * https://fetch.spec.whatwg.org/#concept-fetch also live here.
150
+ */
151
+ async #dispatchHTTP(urlRecord, handler, opts) {
152
+ const { corsMode, origin, withCredentials, auth, preflight } = opts.opaque || {};
153
+ const requestFragment = urlRecord.fragment;
154
+ let currentURL = urlRecord;
155
+ let currentMethod = opts.method || "GET";
156
+ let currentBody = opts.body ?? null;
157
+ const currentHeaders = { ...this.#normalizeHeadersToObject(opts.headers) };
158
+ let effectiveOrigin = origin; // CORS tracking - may become "null" after cross-origin redirects
159
+ let receivedAuthChallenge = false;
160
+ const ctx = { finalURL: null };
161
+
162
+ // Create a proxy controller that forwards to the current underlying controller.
163
+ // This provides a stable reference across redirect hops.
164
+ let currentController;
165
+ let onRequestStartCalled = false;
166
+ const proxyController = {
167
+ abort(reason) {
168
+ currentController.abort(reason);
169
+ },
170
+ pause() {
171
+ currentController.pause();
172
+ },
173
+ resume() {
174
+ currentController.resume();
175
+ },
176
+ get paused() {
177
+ return currentController.paused;
178
+ },
179
+ get aborted() {
180
+ return currentController.aborted;
181
+ },
182
+ get reason() {
183
+ return currentController.reason;
184
+ }
185
+ };
186
+
187
+ // Callback for #doSingleRequest to invoke when a controller becomes available
188
+ function onControllerReady(controller) {
189
+ currentController = controller;
190
+ if (!onRequestStartCalled) {
191
+ onRequestStartCalled = true;
192
+ handler.onRequestStart?.(proxyController, ctx);
193
+ }
194
+ }
195
+
196
+ // Handle CORS preflight if needed
197
+ if (preflight) {
198
+ const preflightHeaders = {
199
+ Origin: origin
200
+ };
201
+ preflightHeaders["Access-Control-Request-Method"] = currentMethod;
202
+ if (preflight.unsafeHeaders?.length > 0) {
203
+ preflightHeaders["Access-Control-Request-Headers"] = preflight.unsafeHeaders.join(", ");
204
+ }
205
+
206
+ const preflightResult = await this.#doSingleRequest(
207
+ currentURL,
208
+ "OPTIONS",
209
+ preflightHeaders,
210
+ null,
211
+ { ...opts.opaque, origin, withCredentials },
212
+ undefined, // no upgrade for preflight
213
+ opts,
214
+ onControllerReady
215
+ );
216
+
217
+ if (preflightResult.error) {
218
+ handler.onResponseError?.(null, preflightResult.error);
219
+ return;
220
+ }
221
+
222
+ // Validate preflight response status
223
+ if (preflightResult.status < 200 || preflightResult.status > 299) {
224
+ handler.onResponseError?.(null, new Error(
225
+ "Response for preflight has invalid HTTP status code " + preflightResult.status
226
+ ));
227
+ return;
228
+ }
229
+
230
+ // CORS validation on preflight response
231
+ const acao = preflightResult.headers["access-control-allow-origin"];
232
+ if (acao !== "*" && acao !== origin) {
233
+ handler.onResponseError?.(null, new Error("Cross origin " + origin + " forbidden"));
234
+ return;
235
+ }
236
+ if (withCredentials) {
237
+ const acac = preflightResult.headers["access-control-allow-credentials"];
238
+ if (acac !== "true") {
239
+ handler.onResponseError?.(null, new Error("Credentials forbidden"));
240
+ return;
241
+ }
242
+ }
243
+
244
+ // Validate allowed headers
245
+ const acahStr = preflightResult.headers["access-control-allow-headers"];
246
+ const acah = new Set(acahStr ? acahStr.toLowerCase().split(/,\s*/) : []);
247
+ if (!acah.has("*")) {
248
+ for (const unsafeHeader of preflight.unsafeHeaders || []) {
249
+ if (!acah.has(unsafeHeader.toLowerCase())) {
250
+ handler.onResponseError?.(null, new Error("Header " + unsafeHeader + " forbidden"));
251
+ return;
252
+ }
253
+ }
254
+ }
255
+ }
256
+
257
+ // Redirect loop
258
+ for (let redirectCount = 0; redirectCount <= MAX_REDIRECTS; redirectCount++) {
259
+ ctx.finalURL = currentURL;
260
+ const currentOrigin = serializeURLOrigin(currentURL);
261
+
262
+ // Clone headers for this request
263
+ const requestHeaders = { ...currentHeaders };
264
+
265
+ // Add auth header if needed
266
+ if (receivedAuthChallenge && auth) {
267
+ const authString = `${auth.user || ""}:${auth.pass || ""}`;
268
+ requestHeaders.Authorization = "Basic " + toBase64(utf8Encode(authString));
269
+ }
270
+
271
+ const result = await this.#doSingleRequest(
272
+ currentURL,
273
+ currentMethod,
274
+ requestHeaders,
275
+ currentBody,
276
+ { ...opts.opaque, origin, withCredentials },
277
+ opts.upgrade,
278
+ opts,
279
+ onControllerReady
280
+ );
281
+
282
+ // WebSocket upgrade
283
+ if (result.upgraded) {
284
+ handler.onRequestUpgrade?.(proxyController, result.statusCode, result.headers, result.socket);
285
+ return;
286
+ }
287
+
288
+ if (result.error) {
289
+ handler.onResponseError?.(null, result.error);
290
+ return;
291
+ }
292
+
293
+ // Handle 401 auth challenge
294
+ if (result.status === 401 && auth && !receivedAuthChallenge) {
295
+ const wwwAuth = result.headers["www-authenticate"] || "";
296
+ if (/^Basic /i.test(wwwAuth)) {
297
+ receivedAuthChallenge = true;
298
+ continue;
299
+ }
300
+ }
301
+
302
+ // Handle redirect
303
+ const { location } = result.headers;
304
+ if (result.status >= 300 && result.status < 400 && location) {
305
+ const targetURL = parseURL(location, { baseURL: currentURL });
306
+ if (!targetURL) {
307
+ handler.onResponseError?.(null, new TypeError("Invalid redirect URL"));
308
+ return;
309
+ }
310
+
311
+ // Per fetch spec: if location's fragment is null, inherit from request
312
+ if (targetURL.fragment === null) {
313
+ targetURL.fragment = requestFragment;
314
+ }
315
+
316
+ // Per fetch spec: if locationURL's scheme is not HTTP(S), return a network error
317
+ if (targetURL.scheme !== "http" && targetURL.scheme !== "https") {
318
+ handler.onResponseError?.(null, new Error("Cannot redirect to non-HTTP(S) URL"));
319
+ return;
320
+ }
321
+
322
+ // Method change per fetch spec "HTTP-redirect fetch"
323
+ // 301/302 + POST → GET, 303 + non-GET/HEAD → GET
324
+ if (((result.status === 301 || result.status === 302) && currentMethod === "POST") ||
325
+ (result.status === 303 && !["GET", "HEAD"].includes(currentMethod))) {
326
+ currentMethod = "GET";
327
+ currentBody = null;
328
+ this.#deleteRequestHeader(currentHeaders, "content-encoding");
329
+ this.#deleteRequestHeader(currentHeaders, "content-language");
330
+ this.#deleteRequestHeader(currentHeaders, "content-location");
331
+ this.#deleteRequestHeader(currentHeaders, "content-type");
332
+ }
333
+
334
+ const targetOrigin = serializeURLOrigin(targetURL);
335
+
336
+ // Authorization header removal on cross-origin redirect
337
+ if (currentOrigin !== targetOrigin) {
338
+ this.#deleteRequestHeader(currentHeaders, "authorization");
339
+ }
340
+
341
+ // CORS handling for cross-origin redirects (only if origin is set, indicating XHR/fetch)
342
+ const targetIsCrossOrigin = origin !== undefined && origin !== targetOrigin;
343
+ if (corsMode || targetIsCrossOrigin) {
344
+ // CORS validation on redirect response (if source was cross-origin)
345
+ if (origin !== currentOrigin) {
346
+ const acao = result.headers["access-control-allow-origin"];
347
+ if (acao !== "*" && acao !== origin) {
348
+ handler.onResponseError?.(null, new Error("Cross origin " + origin + " forbidden"));
349
+ return;
350
+ }
351
+ if (withCredentials) {
352
+ const acac = result.headers["access-control-allow-credentials"];
353
+ if (acac !== "true") {
354
+ handler.onResponseError?.(null, new Error("Credentials forbidden"));
355
+ return;
356
+ }
357
+ }
358
+ // Userinfo check - forbid redirects to URLs with username/password
359
+ if (targetURL.username || targetURL.password) {
360
+ handler.onResponseError?.(null, new Error("Userinfo forbidden in cors redirect"));
361
+ return;
362
+ }
363
+ // Update effective origin - becomes "null" after cross-origin→cross-origin redirect
364
+ if (currentOrigin !== targetOrigin) {
365
+ effectiveOrigin = "null";
366
+ }
367
+ }
368
+
369
+ // Add Origin header for cross-origin target or if effective origin became "null"
370
+ if (targetIsCrossOrigin || effectiveOrigin === "null") {
371
+ currentHeaders.Origin = effectiveOrigin;
372
+ }
373
+ }
374
+
375
+ currentURL = targetURL;
376
+ continue;
377
+ }
378
+
379
+ // Final response - CORS validation (if destination is cross-origin or effective origin is "null")
380
+ if (origin !== undefined && (origin !== currentOrigin || effectiveOrigin === "null")) {
381
+ const acao = result.headers["access-control-allow-origin"];
382
+ if (acao !== "*" && acao !== effectiveOrigin) {
383
+ handler.onResponseError?.(null, new Error("Cross origin " + effectiveOrigin + " forbidden"));
384
+ return;
385
+ }
386
+ if (withCredentials) {
387
+ const acac = result.headers["access-control-allow-credentials"];
388
+ if (acac !== "true") {
389
+ handler.onResponseError?.(null, new Error("Credentials forbidden"));
390
+ return;
391
+ }
392
+ }
393
+ }
394
+
395
+ // Stream response to handler
396
+ handler.onResponseStart?.(proxyController, result.status, result.headers, result.statusText);
397
+
398
+ // Forward body chunks to handler
399
+ result.forwardBodyTo(handler);
400
+ return;
401
+ }
402
+
403
+ handler.onResponseError?.(null, new Error(`Too many redirects (max ${MAX_REDIRECTS})`));
404
+ }
405
+
406
+ /**
407
+ * Perform a single HTTP request (no redirects).
408
+ * Handles cookies based on cross-origin/credentials settings.
409
+ * Returns response metadata immediately, with a forwardBodyTo() method to stream the body later.
410
+ *
411
+ * For WebSocket upgrades, returns { upgraded: true, controller, statusCode, headers, socket }.
412
+ *
413
+ * Mostly corresponds to https://fetch.spec.whatwg.org/#concept-http-network-fetch.
414
+ *
415
+ * @param {object} url - URL record to request
416
+ * @param {string} method - HTTP method
417
+ * @param {object} headers - Request headers
418
+ * @param {*} body - Request body
419
+ * @param {object} opaque - jsdom opaque options
420
+ * @param {string} upgrade - Upgrade protocol (e.g., "websocket")
421
+ * @param {object} originalOpts - Original dispatch options to preserve extra undici options
422
+ * @param {function} onControllerReady - Callback invoked when controller is available
423
+ */
424
+ async #doSingleRequest(url, method, headers, body, opaque, upgrade, originalOpts, onControllerReady) {
425
+ const { origin: requestOrigin, withCredentials } = opaque || {};
426
+
427
+ // Build headers with defaults
428
+ const requestHeaders = { ...headers };
429
+ this.#setDefaultHeaders(requestHeaders);
430
+
431
+ if (body === null && (method === "POST" || method === "PUT")) {
432
+ requestHeaders["Content-Length"] = "0";
433
+ } else if (body !== null && body.byteLength !== undefined) {
434
+ // The `body.byteLength !== undefined` check is equivalent to the spec case where httpRequest's body's length is
435
+ // null, because body is a stream.
436
+ requestHeaders["Content-Length"] = String(body.byteLength);
437
+ }
438
+
439
+ // Determine if this is cross-origin (for cookie handling)
440
+ const urlOrigin = serializeURLOrigin(url);
441
+ const crossOrigin = requestOrigin !== undefined && requestOrigin !== urlOrigin;
442
+
443
+ // Only handle cookies for same-origin requests, or cross-origin with credentials
444
+ // Don't send cookies for preflight requests
445
+ const isPreflight = method === "OPTIONS" &&
446
+ this.#hasRequestHeader(headers, "Access-Control-Request-Method");
447
+ const shouldHandleCookies = (!crossOrigin || withCredentials) && !isPreflight;
448
+
449
+ const urlSerialized = serializeURL(url);
450
+
451
+ if (shouldHandleCookies) {
452
+ const cookieString = this.#cookieJar.getCookieStringSync(urlSerialized);
453
+ if (cookieString) {
454
+ requestHeaders.Cookie = cookieString;
455
+ }
456
+ }
457
+
458
+ // Spread original opts to preserve extra undici options (e.g., idempotent, bodyTimeout),
459
+ // then override with our specific values.
460
+ // If opaque.url was provided, derive origin/path from it and null out query.
461
+ // Otherwise, pass through origin/path/query unchanged.
462
+ const hasOpaqueURL = opaque?.url !== undefined;
463
+ const dispatchOpts = {
464
+ ...originalOpts,
465
+ origin: hasOpaqueURL ? urlOrigin : originalOpts.origin,
466
+ path: hasOpaqueURL ? serializePathForUndici(url) : originalOpts.path,
467
+ query: hasOpaqueURL ? null : originalOpts.query,
468
+ method,
469
+ headers: requestHeaders,
470
+ body,
471
+ upgrade,
472
+ opaque: { ...opaque, url: urlSerialized }
473
+ };
474
+
475
+ const innerDispatch = this.#buildDispatchChain();
476
+
477
+ return new Promise(resolve => {
478
+ let responseHeaders, streamError;
479
+ let bodyHandler = null;
480
+ let pendingChunks = [];
481
+ let ended = false;
482
+ let responseStarted = false;
483
+
484
+ innerDispatch(dispatchOpts, {
485
+ onRequestStart: controller => {
486
+ onControllerReady(controller);
487
+ },
488
+ onRequestUpgrade: (controller, statusCode, headersObj, socket) => {
489
+ if (controller.aborted) {
490
+ resolve({ error: controller.reason });
491
+ return;
492
+ }
493
+ if (shouldHandleCookies) {
494
+ this.#storeCookiesFromHeaders(headersObj, urlSerialized);
495
+ }
496
+ resolve({ upgraded: true, controller, statusCode, headers: headersObj, socket });
497
+ },
498
+ onResponseStart: (controller, statusCode, headersObj, statusText) => {
499
+ if (controller.aborted) {
500
+ resolve({ error: controller.reason });
501
+ return;
502
+ }
503
+
504
+ responseHeaders = headersObj;
505
+ responseStarted = true;
506
+
507
+ // Create a mechanism to forward body to handler later
508
+ function forwardBodyTo(fwdHandler) {
509
+ bodyHandler = fwdHandler;
510
+ // Forward any chunks that arrived before forwardBodyTo was called
511
+ for (const chunk of pendingChunks) {
512
+ fwdHandler.onResponseData?.(controller, chunk);
513
+ }
514
+ pendingChunks = null;
515
+ if (streamError) {
516
+ fwdHandler.onResponseError?.(controller, streamError);
517
+ } else if (ended) {
518
+ fwdHandler.onResponseEnd?.(controller, {});
519
+ }
520
+ }
521
+
522
+ resolve({
523
+ status: statusCode,
524
+ statusText: statusText || "",
525
+ headers: responseHeaders,
526
+ url,
527
+ forwardBodyTo
528
+ });
529
+ },
530
+ onResponseData: (controller, chunk) => {
531
+ if (controller.aborted) {
532
+ return;
533
+ }
534
+ if (bodyHandler) {
535
+ bodyHandler.onResponseData?.(controller, chunk);
536
+ } else {
537
+ pendingChunks.push(chunk);
538
+ }
539
+ },
540
+ onResponseEnd: (controller, trailers) => {
541
+ if (controller.aborted) {
542
+ if (bodyHandler) {
543
+ bodyHandler.onResponseError?.(controller, controller.reason);
544
+ } else {
545
+ streamError = controller.reason;
546
+ }
547
+ return;
548
+ }
549
+ if (shouldHandleCookies) {
550
+ this.#storeCookiesFromHeaders(responseHeaders, urlSerialized);
551
+ }
552
+ if (bodyHandler) {
553
+ bodyHandler.onResponseEnd?.(controller, trailers);
554
+ } else {
555
+ ended = true;
556
+ }
557
+ },
558
+ onResponseError: (controller, err) => {
559
+ if (responseStarted) {
560
+ // Error occurred mid-stream - forward to body handler
561
+ if (bodyHandler) {
562
+ bodyHandler.onResponseError?.(controller, err);
563
+ } else {
564
+ streamError = err;
565
+ }
566
+ } else {
567
+ resolve({ error: err });
568
+ }
569
+ }
570
+ });
571
+ });
572
+ }
573
+
574
+ /**
575
+ * Build the dispatch chain with user interceptors applied.
576
+ */
577
+ #buildDispatchChain() {
578
+ // Convert handlers to old-style before passing to the base dispatcher. When Node's built-in fetch() has run,
579
+ // it registers a v6 undici Agent as the global dispatcher via the shared Symbol.for('undici.globalDispatcher.1').
580
+ // Our v7 code passes new-style handlers, which v6 rejects. Old-style handlers are accepted by both v6 and v7.
581
+ // See https://github.com/jsdom/jsdom/issues/4047
582
+ let innerDispatch = (opts, h) => {
583
+ return this.#baseDispatcher.dispatch(opts, UnwrapHandler.unwrap(h));
584
+ };
585
+
586
+ // Apply user interceptors from innermost to outermost
587
+ for (let i = this.#userInterceptors.length - 1; i >= 0; i--) {
588
+ const interceptor = this.#userInterceptors[i];
589
+ const nextDispatch = innerDispatch;
590
+ innerDispatch = (opts, h) => interceptor(nextDispatch)(opts, h);
591
+ }
592
+
593
+ return innerDispatch;
594
+ }
595
+
596
+ /**
597
+ * Normalize headers to an object format.
598
+ * Callers pass either HeaderList (iterable) or plain objects.
599
+ */
600
+ #normalizeHeadersToObject(headers) {
601
+ if (!headers) {
602
+ return {};
603
+ }
604
+
605
+ // HeaderList has Symbol.iterator; plain objects don't
606
+ if (typeof headers[Symbol.iterator] === "function") {
607
+ const obj = {};
608
+ for (const [name, value] of headers) {
609
+ obj[name] = value;
610
+ }
611
+ return obj;
612
+ }
613
+
614
+ return { ...headers };
615
+ }
616
+
617
+ /**
618
+ * Check if a request header exists (case-insensitive).
619
+ * Request headers may have user-controlled casing.
620
+ */
621
+ #hasRequestHeader(requestHeaders, name) {
622
+ const lowerName = name.toLowerCase();
623
+ return Object.keys(requestHeaders).some(key => key.toLowerCase() === lowerName);
624
+ }
625
+
626
+ /**
627
+ * Delete a request header (case-insensitive).
628
+ * Request headers may have user-controlled casing. Mutates the object in place.
629
+ */
630
+ #deleteRequestHeader(requestHeaders, name) {
631
+ const lowerName = name.toLowerCase();
632
+ for (const key of Object.keys(requestHeaders)) {
633
+ if (key.toLowerCase() === lowerName) {
634
+ delete requestHeaders[key];
635
+ }
636
+ }
637
+ }
638
+
639
+ /**
640
+ * Set default request headers if not already present.
641
+ * Mutates the headers object in place.
642
+ */
643
+ #setDefaultHeaders(requestHeaders) {
644
+ if (!this.#hasRequestHeader(requestHeaders, "User-Agent")) {
645
+ requestHeaders["User-Agent"] = this.#userAgent;
646
+ }
647
+ if (!this.#hasRequestHeader(requestHeaders, "Accept-Language")) {
648
+ requestHeaders["Accept-Language"] = "en";
649
+ }
650
+ if (!this.#hasRequestHeader(requestHeaders, "Accept")) {
651
+ requestHeaders.Accept = "*/*";
652
+ }
653
+ if (!this.#hasRequestHeader(requestHeaders, "Accept-Encoding")) {
654
+ requestHeaders["Accept-Encoding"] = "gzip, deflate";
655
+ }
656
+ }
657
+
658
+ /**
659
+ * Extract and store cookies from response headers.
660
+ */
661
+ #storeCookiesFromHeaders(headers, url) {
662
+ if (!headers["set-cookie"]) {
663
+ return;
664
+ }
665
+ const cookies = Array.isArray(headers["set-cookie"]) ?
666
+ headers["set-cookie"] :
667
+ [headers["set-cookie"]];
668
+ for (const cookie of cookies) {
669
+ this.#cookieJar.setCookieSync(cookie, url, { ignoreError: true });
670
+ }
671
+ }
672
+
673
+ // Dispatcher API methods - forward close/destroy to base dispatcher
674
+
675
+ close(...args) {
676
+ return this.#baseDispatcher.close(...args);
677
+ }
678
+
679
+ destroy(...args) {
680
+ return this.#baseDispatcher.destroy(...args);
681
+ }
682
+
683
+ /**
684
+ * Create a new JSDOMDispatcher with additional interceptors.
685
+ * The new interceptors are added as the outermost (first to see requests, last to see responses).
686
+ */
687
+ compose(...additionalInterceptors) {
688
+ return new JSDOMDispatcher({
689
+ baseDispatcher: this.#baseDispatcher,
690
+ cookieJar: this.#cookieJar,
691
+ userAgent: this.#userAgent,
692
+ userInterceptors: [...additionalInterceptors, ...this.#userInterceptors]
693
+ });
694
+ }
695
+
696
+ get closed() {
697
+ return this.#baseDispatcher.closed;
698
+ }
699
+
700
+ get destroyed() {
701
+ return this.#baseDispatcher.destroyed;
702
+ }
703
+ }
704
+
705
+ /**
706
+ * High-level GET fetch that collects the full response body. Used for subresources and `JSDOM.fromURL()`.
707
+ *
708
+ * @param {Dispatcher} dispatcher - The undici dispatcher to use
709
+ * @param {object} opts - Request options
710
+ * @param {string} opts.url - The URL to fetch
711
+ * @param {object} [opts.headers] - Request headers (include Referer if needed)
712
+ * @param {AbortSignal} [opts.signal] - Abort signal
713
+ * @param {Element} [opts.element] - The element initiating the request (default: null)
714
+ * @returns {Promise<{status: number, headers: object, body: Uint8Array, url: string, ok: boolean}>}
715
+ */
716
+ async function fetchCollected(dispatcher, { url, headers, signal, element = null }) {
717
+ const urlRecord = parseURL(url);
718
+ if (!urlRecord) {
719
+ throw new TypeError(`Invalid URL: ${url}`);
720
+ }
721
+
722
+ const response = await dispatcher.request({
723
+ origin: serializeURLOrigin(urlRecord),
724
+ path: serializePathForUndici(urlRecord),
725
+ method: "GET",
726
+ headers,
727
+ signal,
728
+ opaque: { element, url }
729
+ });
730
+
731
+ const body = await response.body.bytes();
732
+
733
+ // Get final URL from context (set by dispatcher after handling redirects)
734
+ const finalURL = serializeURL(response.context.finalURL);
735
+
736
+ return {
737
+ status: response.statusCode,
738
+ headers: response.headers,
739
+ body,
740
+ url: finalURL,
741
+ ok: response.statusCode >= 200 && response.statusCode < 300
742
+ };
743
+ }
744
+
745
+ /**
746
+ * Serialize a URL record's path and query for undici's `path` option.
747
+ */
748
+ function serializePathForUndici(urlRecord) {
749
+ return serializePath(urlRecord) + (urlRecord.query ? "?" + urlRecord.query : "");
750
+ }
751
+
752
+ module.exports = {
753
+ JSDOMDispatcher,
754
+ DEFAULT_USER_AGENT,
755
+ fetchCollected
756
+ };