happy-dom 8.9.0 → 9.0.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.

Potentially problematic release.


This version of happy-dom might be problematic. Click here for more details.

Files changed (360) hide show
  1. package/README.md +2 -2
  2. package/lib/cookie/CookieJar.js +1 -1
  3. package/lib/cookie/CookieJar.js.map +1 -1
  4. package/lib/dom-token-list/DOMTokenList.js +24 -20
  5. package/lib/dom-token-list/DOMTokenList.js.map +1 -1
  6. package/lib/event/EventTarget.js +6 -3
  7. package/lib/event/EventTarget.js.map +1 -1
  8. package/lib/exception/DOMExceptionNameEnum.d.ts +5 -1
  9. package/lib/exception/DOMExceptionNameEnum.js +4 -0
  10. package/lib/exception/DOMExceptionNameEnum.js.map +1 -1
  11. package/lib/fetch/AbortController.d.ts +19 -0
  12. package/lib/fetch/AbortController.js +30 -0
  13. package/lib/fetch/AbortController.js.map +1 -0
  14. package/lib/fetch/AbortSignal.d.ts +25 -0
  15. package/lib/fetch/AbortSignal.js +51 -0
  16. package/lib/fetch/AbortSignal.js.map +1 -0
  17. package/lib/fetch/Fetch.d.ts +117 -0
  18. package/lib/fetch/Fetch.js +530 -0
  19. package/lib/fetch/Fetch.js.map +1 -0
  20. package/lib/fetch/Headers.d.ts +81 -3
  21. package/lib/fetch/Headers.js +139 -24
  22. package/lib/fetch/Headers.js.map +1 -1
  23. package/lib/fetch/Request.d.ts +56 -32
  24. package/lib/fetch/Request.js +165 -110
  25. package/lib/fetch/Request.js.map +1 -1
  26. package/lib/fetch/{ResourceFetchHandler.d.ts → ResourceFetch.d.ts} +1 -1
  27. package/lib/fetch/{ResourceFetchHandler.js → ResourceFetch.js} +5 -5
  28. package/lib/fetch/ResourceFetch.js.map +1 -0
  29. package/lib/fetch/Response.d.ts +60 -26
  30. package/lib/fetch/Response.js +196 -104
  31. package/lib/fetch/Response.js.map +1 -1
  32. package/lib/fetch/data-uri/DataURIParser.d.ts +20 -0
  33. package/lib/fetch/data-uri/DataURIParser.js +60 -0
  34. package/lib/fetch/data-uri/DataURIParser.js.map +1 -0
  35. package/lib/fetch/multipart/MultipartFormDataParser.d.ts +40 -0
  36. package/lib/fetch/multipart/MultipartFormDataParser.js +81 -0
  37. package/lib/fetch/multipart/MultipartFormDataParser.js.map +1 -0
  38. package/lib/fetch/multipart/MultipartReader.d.ts +49 -0
  39. package/lib/fetch/multipart/MultipartReader.js +178 -0
  40. package/lib/fetch/multipart/MultipartReader.js.map +1 -0
  41. package/lib/fetch/types/IHeaders.d.ts +71 -0
  42. package/lib/fetch/{IHeaders.js.map → types/IHeaders.js.map} +1 -1
  43. package/lib/fetch/types/IHeadersInit.js.map +1 -0
  44. package/lib/fetch/types/IRequest.d.ts +60 -0
  45. package/lib/fetch/{IRequest.js.map → types/IRequest.js.map} +1 -1
  46. package/lib/fetch/types/IRequestBody.d.ts +7 -0
  47. package/lib/fetch/{IBody.js → types/IRequestBody.js} +1 -1
  48. package/lib/fetch/types/IRequestBody.js.map +1 -0
  49. package/lib/fetch/types/IRequestCredentials.d.ts +2 -0
  50. package/lib/fetch/types/IRequestCredentials.js +3 -0
  51. package/lib/fetch/types/IRequestCredentials.js.map +1 -0
  52. package/lib/fetch/{RequestInfo.d.ts → types/IRequestInfo.d.ts} +2 -2
  53. package/lib/fetch/types/IRequestInfo.js +3 -0
  54. package/lib/fetch/types/IRequestInfo.js.map +1 -0
  55. package/lib/fetch/types/IRequestInit.d.ts +21 -0
  56. package/lib/fetch/types/IRequestInit.js.map +1 -0
  57. package/lib/fetch/types/IRequestRedirect.d.ts +2 -0
  58. package/lib/fetch/types/IRequestRedirect.js +3 -0
  59. package/lib/fetch/types/IRequestRedirect.js.map +1 -0
  60. package/lib/fetch/types/IRequestReferrerPolicy.d.ts +2 -0
  61. package/lib/fetch/types/IRequestReferrerPolicy.js +3 -0
  62. package/lib/fetch/types/IRequestReferrerPolicy.js.map +1 -0
  63. package/lib/fetch/types/IResponse.d.ts +27 -0
  64. package/lib/fetch/{IResponse.js.map → types/IResponse.js.map} +1 -1
  65. package/lib/fetch/types/IResponseBody.d.ts +7 -0
  66. package/lib/fetch/types/IResponseBody.js +3 -0
  67. package/lib/fetch/types/IResponseBody.js.map +1 -0
  68. package/lib/fetch/types/IResponseInit.d.ts +9 -0
  69. package/lib/fetch/types/IResponseInit.js.map +1 -0
  70. package/lib/fetch/utilities/FetchBodyUtility.d.ts +44 -0
  71. package/lib/fetch/utilities/FetchBodyUtility.js +156 -0
  72. package/lib/fetch/utilities/FetchBodyUtility.js.map +1 -0
  73. package/lib/fetch/utilities/FetchCORSUtility.d.ts +12 -0
  74. package/lib/fetch/utilities/FetchCORSUtility.js +20 -0
  75. package/lib/fetch/utilities/FetchCORSUtility.js.map +1 -0
  76. package/lib/fetch/utilities/FetchRequestHeaderUtility.d.ts +12 -0
  77. package/lib/fetch/utilities/FetchRequestHeaderUtility.js +45 -0
  78. package/lib/fetch/utilities/FetchRequestHeaderUtility.js.map +1 -0
  79. package/lib/fetch/utilities/FetchRequestReferrerUtility.d.ts +55 -0
  80. package/lib/fetch/utilities/FetchRequestReferrerUtility.js +194 -0
  81. package/lib/fetch/utilities/FetchRequestReferrerUtility.js.map +1 -0
  82. package/lib/fetch/utilities/FetchRequestValidationUtility.d.ts +38 -0
  83. package/lib/fetch/utilities/FetchRequestValidationUtility.js +70 -0
  84. package/lib/fetch/utilities/FetchRequestValidationUtility.js.map +1 -0
  85. package/lib/file/Blob.d.ts +2 -2
  86. package/lib/file/Blob.js +1 -1
  87. package/lib/file/Blob.js.map +1 -1
  88. package/lib/file/File.d.ts +2 -1
  89. package/lib/file/File.js.map +1 -1
  90. package/lib/form-data/FormData.d.ts +98 -0
  91. package/lib/form-data/FormData.js +212 -0
  92. package/lib/form-data/FormData.js.map +1 -0
  93. package/lib/index.d.ts +14 -1
  94. package/lib/index.js +20 -2
  95. package/lib/index.js.map +1 -1
  96. package/lib/nodes/document/Document.d.ts +5 -17
  97. package/lib/nodes/document/Document.js +11 -54
  98. package/lib/nodes/document/Document.js.map +1 -1
  99. package/lib/nodes/document/IDocument.d.ts +1 -1
  100. package/lib/nodes/document-fragment/DocumentFragment.d.ts +3 -14
  101. package/lib/nodes/document-fragment/DocumentFragment.js +7 -51
  102. package/lib/nodes/document-fragment/DocumentFragment.js.map +1 -1
  103. package/lib/nodes/document-fragment/IDocumentFragment.d.ts +2 -1
  104. package/lib/nodes/element/Element.d.ts +8 -8
  105. package/lib/nodes/element/Element.js +28 -45
  106. package/lib/nodes/element/Element.js.map +1 -1
  107. package/lib/nodes/element/ElementUtility.d.ts +32 -0
  108. package/lib/nodes/element/ElementUtility.js +105 -0
  109. package/lib/nodes/element/ElementUtility.js.map +1 -0
  110. package/lib/nodes/element/HTMLCollection.d.ts +26 -3
  111. package/lib/nodes/element/HTMLCollection.js +51 -0
  112. package/lib/nodes/element/HTMLCollection.js.map +1 -1
  113. package/lib/nodes/element/IHTMLCollection.d.ts +9 -2
  114. package/lib/nodes/html-anchor-element/HTMLAnchorElement.js +24 -24
  115. package/lib/nodes/html-anchor-element/HTMLAnchorElement.js.map +1 -1
  116. package/lib/nodes/html-base-element/HTMLBaseElement.js +4 -4
  117. package/lib/nodes/html-base-element/HTMLBaseElement.js.map +1 -1
  118. package/lib/nodes/html-button-element/HTMLButtonElement.d.ts +84 -3
  119. package/lib/nodes/html-button-element/HTMLButtonElement.js +183 -10
  120. package/lib/nodes/html-button-element/HTMLButtonElement.js.map +1 -1
  121. package/lib/nodes/html-button-element/IHTMLButtonElement.d.ts +28 -2
  122. package/lib/nodes/html-dialog-element/HTMLDialogElement.js +3 -3
  123. package/lib/nodes/html-dialog-element/HTMLDialogElement.js.map +1 -1
  124. package/lib/nodes/html-element/HTMLElement.js +12 -12
  125. package/lib/nodes/html-element/HTMLElement.js.map +1 -1
  126. package/lib/nodes/html-form-element/HTMLFormControlsCollection.d.ts +32 -0
  127. package/lib/nodes/html-form-element/HTMLFormControlsCollection.js +58 -0
  128. package/lib/nodes/html-form-element/HTMLFormControlsCollection.js.map +1 -0
  129. package/lib/nodes/html-form-element/HTMLFormElement.d.ts +37 -17
  130. package/lib/nodes/html-form-element/HTMLFormElement.js +128 -37
  131. package/lib/nodes/html-form-element/HTMLFormElement.js.map +1 -1
  132. package/lib/nodes/html-form-element/IHTMLFormControlsCollection.d.ts +25 -0
  133. package/lib/nodes/html-form-element/IHTMLFormControlsCollection.js +3 -0
  134. package/lib/nodes/html-form-element/IHTMLFormControlsCollection.js.map +1 -0
  135. package/lib/nodes/html-form-element/IHTMLFormElement.d.ts +16 -6
  136. package/lib/nodes/html-form-element/IRadioNodeList.d.ts +15 -0
  137. package/lib/nodes/html-form-element/IRadioNodeList.js +3 -0
  138. package/lib/nodes/html-form-element/IRadioNodeList.js.map +1 -0
  139. package/lib/nodes/html-form-element/RadioNodeList.d.ts +16 -0
  140. package/lib/nodes/html-form-element/RadioNodeList.js +28 -0
  141. package/lib/nodes/html-form-element/RadioNodeList.js.map +1 -0
  142. package/lib/nodes/html-image-element/HTMLImageElement.js +19 -19
  143. package/lib/nodes/html-image-element/HTMLImageElement.js.map +1 -1
  144. package/lib/nodes/html-input-element/HTMLInputElement.d.ts +43 -19
  145. package/lib/nodes/html-input-element/HTMLInputElement.js +206 -111
  146. package/lib/nodes/html-input-element/HTMLInputElement.js.map +1 -1
  147. package/lib/nodes/html-input-element/IHTMLInputElement.d.ts +14 -1
  148. package/lib/nodes/html-label-element/HTMLLabelElement.js +3 -7
  149. package/lib/nodes/html-label-element/HTMLLabelElement.js.map +1 -1
  150. package/lib/nodes/html-link-element/HTMLLinkElement.js +21 -21
  151. package/lib/nodes/html-link-element/HTMLLinkElement.js.map +1 -1
  152. package/lib/nodes/html-media-element/HTMLMediaElement.js +21 -21
  153. package/lib/nodes/html-media-element/HTMLMediaElement.js.map +1 -1
  154. package/lib/nodes/html-meta-element/HTMLMetaElement.js +8 -8
  155. package/lib/nodes/html-meta-element/HTMLMetaElement.js.map +1 -1
  156. package/lib/nodes/html-opt-group-element/HTMLOptGroupElement.js +6 -6
  157. package/lib/nodes/html-opt-group-element/HTMLOptGroupElement.js.map +1 -1
  158. package/lib/nodes/html-option-element/HTMLOptionElement.d.ts +3 -4
  159. package/lib/nodes/html-option-element/HTMLOptionElement.js +26 -29
  160. package/lib/nodes/html-option-element/HTMLOptionElement.js.map +1 -1
  161. package/lib/nodes/html-script-element/HTMLScriptElement.js +16 -16
  162. package/lib/nodes/html-script-element/HTMLScriptElement.js.map +1 -1
  163. package/lib/nodes/html-script-element/ScriptUtility.js +5 -5
  164. package/lib/nodes/html-script-element/ScriptUtility.js.map +1 -1
  165. package/lib/nodes/{html-option-element → html-select-element}/HTMLOptionsCollection.d.ts +5 -6
  166. package/lib/nodes/{html-option-element → html-select-element}/HTMLOptionsCollection.js.map +1 -1
  167. package/lib/nodes/html-select-element/HTMLSelectElement.d.ts +42 -41
  168. package/lib/nodes/html-select-element/HTMLSelectElement.js +134 -138
  169. package/lib/nodes/html-select-element/HTMLSelectElement.js.map +1 -1
  170. package/lib/nodes/{html-option-element → html-select-element}/IHTMLOptionsCollection.d.ts +4 -5
  171. package/lib/nodes/html-select-element/IHTMLOptionsCollection.js.map +1 -0
  172. package/lib/nodes/html-select-element/IHTMLSelectElement.d.ts +22 -2
  173. package/lib/nodes/html-slot-element/HTMLSlotElement.js +2 -2
  174. package/lib/nodes/html-slot-element/HTMLSlotElement.js.map +1 -1
  175. package/lib/nodes/html-style-element/HTMLStyleElement.js +7 -7
  176. package/lib/nodes/html-style-element/HTMLStyleElement.js.map +1 -1
  177. package/lib/nodes/html-text-area-element/HTMLTextAreaElement.d.ts +55 -2
  178. package/lib/nodes/html-text-area-element/HTMLTextAreaElement.js +150 -40
  179. package/lib/nodes/html-text-area-element/HTMLTextAreaElement.js.map +1 -1
  180. package/lib/nodes/html-text-area-element/IHTMLTextAreaElement.d.ts +16 -0
  181. package/lib/nodes/node/Node.d.ts +12 -1
  182. package/lib/nodes/node/Node.js +50 -4
  183. package/lib/nodes/node/Node.js.map +1 -1
  184. package/lib/nodes/node/NodeList.d.ts +2 -3
  185. package/lib/nodes/node/NodeList.js.map +1 -1
  186. package/lib/nodes/parent-node/IParentNode.d.ts +4 -4
  187. package/lib/nodes/parent-node/ParentNodeUtility.d.ts +3 -3
  188. package/lib/nodes/parent-node/ParentNodeUtility.js +13 -11
  189. package/lib/nodes/parent-node/ParentNodeUtility.js.map +1 -1
  190. package/lib/nodes/text/Text.d.ts +13 -0
  191. package/lib/nodes/text/Text.js +30 -0
  192. package/lib/nodes/text/Text.js.map +1 -1
  193. package/lib/query-selector/QuerySelector.js +2 -2
  194. package/lib/query-selector/QuerySelector.js.map +1 -1
  195. package/lib/query-selector/SelectorItem.js +2 -0
  196. package/lib/query-selector/SelectorItem.js.map +1 -1
  197. package/lib/validity-state/ValidityState.d.ts +87 -0
  198. package/lib/validity-state/ValidityState.js +171 -0
  199. package/lib/validity-state/ValidityState.js.map +1 -0
  200. package/lib/window/GlobalWindow.d.ts +0 -8
  201. package/lib/window/GlobalWindow.js +0 -2
  202. package/lib/window/GlobalWindow.js.map +1 -1
  203. package/lib/window/INodeJSGlobal.d.ts +71 -0
  204. package/lib/window/INodeJSGlobal.js +2 -0
  205. package/lib/window/INodeJSGlobal.js.map +1 -0
  206. package/lib/window/IWindow.d.ts +30 -10
  207. package/lib/window/Window.d.ts +36 -20
  208. package/lib/window/Window.js +16 -9
  209. package/lib/window/Window.js.map +1 -1
  210. package/lib/xml-http-request/XMLHttpRequest.js +20 -12
  211. package/lib/xml-http-request/XMLHttpRequest.js.map +1 -1
  212. package/lib/xml-parser/XMLParser.js +1 -1
  213. package/lib/xml-parser/XMLParser.js.map +1 -1
  214. package/package.json +2 -3
  215. package/src/cookie/CookieJar.ts +1 -1
  216. package/src/dom-token-list/DOMTokenList.ts +24 -20
  217. package/src/event/EventTarget.ts +7 -3
  218. package/src/exception/DOMExceptionNameEnum.ts +5 -1
  219. package/src/fetch/AbortController.ts +26 -0
  220. package/src/fetch/AbortSignal.ts +44 -0
  221. package/src/fetch/Fetch.ts +666 -0
  222. package/src/fetch/Headers.ts +151 -3
  223. package/src/fetch/Request.ts +226 -94
  224. package/src/fetch/{ResourceFetchHandler.ts → ResourceFetch.ts} +3 -3
  225. package/src/fetch/Response.ts +252 -89
  226. package/src/fetch/data-uri/DataURIParser.ts +66 -0
  227. package/src/fetch/multipart/MultipartFormDataParser.ts +113 -0
  228. package/src/fetch/multipart/MultipartReader.ts +217 -0
  229. package/src/fetch/types/IHeaders.ts +80 -0
  230. package/src/fetch/types/IRequest.ts +65 -0
  231. package/src/fetch/types/IRequestBody.ts +15 -0
  232. package/src/fetch/types/IRequestCredentials.ts +2 -0
  233. package/src/fetch/types/IRequestInfo.ts +6 -0
  234. package/src/fetch/types/IRequestInit.ts +21 -0
  235. package/src/fetch/types/IRequestRedirect.ts +3 -0
  236. package/src/fetch/types/IRequestReferrerPolicy.ts +11 -0
  237. package/src/fetch/types/IResponse.ts +27 -0
  238. package/src/fetch/types/IResponseBody.ts +15 -0
  239. package/src/fetch/types/IResponseInit.ts +10 -0
  240. package/src/fetch/utilities/FetchBodyUtility.ts +175 -0
  241. package/src/fetch/utilities/FetchCORSUtility.ts +18 -0
  242. package/src/fetch/utilities/FetchRequestHeaderUtility.ts +47 -0
  243. package/src/fetch/utilities/FetchRequestReferrerUtility.ts +241 -0
  244. package/src/fetch/utilities/FetchRequestValidationUtility.ts +82 -0
  245. package/src/file/Blob.ts +2 -2
  246. package/src/file/File.ts +5 -1
  247. package/src/form-data/FormData.ts +237 -0
  248. package/src/index.ts +27 -1
  249. package/src/nodes/document/Document.ts +23 -64
  250. package/src/nodes/document/IDocument.ts +1 -1
  251. package/src/nodes/document-fragment/DocumentFragment.ts +9 -59
  252. package/src/nodes/document-fragment/IDocumentFragment.ts +2 -1
  253. package/src/nodes/element/Element.ts +43 -56
  254. package/src/nodes/element/ElementUtility.ts +137 -0
  255. package/src/nodes/element/HTMLCollection.ts +60 -3
  256. package/src/nodes/element/IHTMLCollection.ts +10 -2
  257. package/src/nodes/html-anchor-element/HTMLAnchorElement.ts +24 -24
  258. package/src/nodes/html-base-element/HTMLBaseElement.ts +4 -4
  259. package/src/nodes/html-button-element/HTMLButtonElement.ts +213 -10
  260. package/src/nodes/html-button-element/IHTMLButtonElement.ts +31 -2
  261. package/src/nodes/html-dialog-element/HTMLDialogElement.ts +3 -3
  262. package/src/nodes/html-element/HTMLElement.ts +12 -12
  263. package/src/nodes/html-form-element/HTMLFormControlsCollection.ts +76 -0
  264. package/src/nodes/html-form-element/HTMLFormElement.ts +147 -41
  265. package/src/nodes/html-form-element/IHTMLFormControlsCollection.ts +45 -0
  266. package/src/nodes/html-form-element/IHTMLFormElement.ts +17 -6
  267. package/src/nodes/html-form-element/IRadioNodeList.ts +16 -0
  268. package/src/nodes/html-form-element/RadioNodeList.ts +24 -0
  269. package/src/nodes/html-image-element/HTMLImageElement.ts +19 -19
  270. package/src/nodes/html-input-element/HTMLInputElement.ts +232 -113
  271. package/src/nodes/html-input-element/IHTMLInputElement.ts +20 -1
  272. package/src/nodes/html-label-element/HTMLLabelElement.ts +3 -7
  273. package/src/nodes/html-link-element/HTMLLinkElement.ts +21 -21
  274. package/src/nodes/html-media-element/HTMLMediaElement.ts +21 -21
  275. package/src/nodes/html-meta-element/HTMLMetaElement.ts +8 -8
  276. package/src/nodes/html-opt-group-element/HTMLOptGroupElement.ts +6 -6
  277. package/src/nodes/html-option-element/HTMLOptionElement.ts +29 -30
  278. package/src/nodes/html-script-element/HTMLScriptElement.ts +16 -16
  279. package/src/nodes/html-script-element/ScriptUtility.ts +5 -5
  280. package/src/nodes/{html-option-element → html-select-element}/HTMLOptionsCollection.ts +5 -9
  281. package/src/nodes/html-select-element/HTMLSelectElement.ts +159 -170
  282. package/src/nodes/{html-option-element → html-select-element}/IHTMLOptionsCollection.ts +4 -8
  283. package/src/nodes/html-select-element/IHTMLSelectElement.ts +25 -2
  284. package/src/nodes/html-slot-element/HTMLSlotElement.ts +2 -2
  285. package/src/nodes/html-style-element/HTMLStyleElement.ts +7 -7
  286. package/src/nodes/html-text-area-element/HTMLTextAreaElement.ts +174 -41
  287. package/src/nodes/html-text-area-element/IHTMLTextAreaElement.ts +18 -0
  288. package/src/nodes/node/Node.ts +61 -6
  289. package/src/nodes/node/NodeList.ts +2 -3
  290. package/src/nodes/parent-node/IParentNode.ts +7 -4
  291. package/src/nodes/parent-node/ParentNodeUtility.ts +25 -15
  292. package/src/nodes/text/Text.ts +38 -0
  293. package/src/query-selector/QuerySelector.ts +2 -2
  294. package/src/query-selector/SelectorItem.ts +3 -0
  295. package/src/validity-state/ValidityState.ts +211 -0
  296. package/src/window/GlobalWindow.ts +0 -2
  297. package/src/window/INodeJSGlobal.ts +70 -0
  298. package/src/window/IWindow.ts +32 -10
  299. package/src/window/Window.ts +37 -20
  300. package/src/xml-http-request/XMLHttpRequest.ts +27 -26
  301. package/src/xml-parser/XMLParser.ts +1 -1
  302. package/lib/fetch/FetchHandler.d.ts +0 -18
  303. package/lib/fetch/FetchHandler.js +0 -83
  304. package/lib/fetch/FetchHandler.js.map +0 -1
  305. package/lib/fetch/IAbortSignal.d.ts +0 -16
  306. package/lib/fetch/IAbortSignal.js +0 -4
  307. package/lib/fetch/IAbortSignal.js.map +0 -1
  308. package/lib/fetch/IBody.d.ts +0 -17
  309. package/lib/fetch/IBody.js.map +0 -1
  310. package/lib/fetch/IHeaders.d.ts +0 -18
  311. package/lib/fetch/IHeadersInit.js.map +0 -1
  312. package/lib/fetch/IRequest.d.ts +0 -18
  313. package/lib/fetch/IRequestInit.d.ts +0 -16
  314. package/lib/fetch/IRequestInit.js.map +0 -1
  315. package/lib/fetch/IResponse.d.ts +0 -20
  316. package/lib/fetch/IResponseInit.d.ts +0 -9
  317. package/lib/fetch/IResponseInit.js.map +0 -1
  318. package/lib/fetch/RequestInfo.js +0 -3
  319. package/lib/fetch/RequestInfo.js.map +0 -1
  320. package/lib/fetch/ResourceFetchHandler.js.map +0 -1
  321. package/lib/form-data/IFormData.d.ts +0 -32
  322. package/lib/form-data/IFormData.js +0 -3
  323. package/lib/form-data/IFormData.js.map +0 -1
  324. package/lib/location/RelativeURL.d.ts +0 -15
  325. package/lib/location/RelativeURL.js +0 -19
  326. package/lib/location/RelativeURL.js.map +0 -1
  327. package/lib/nodes/element/HTMLCollectionFactory.d.ts +0 -21
  328. package/lib/nodes/element/HTMLCollectionFactory.js +0 -31
  329. package/lib/nodes/element/HTMLCollectionFactory.js.map +0 -1
  330. package/lib/nodes/html-option-element/IHTMLOptionsCollection.js.map +0 -1
  331. package/lib/nodes/node/NodeListFactory.d.ts +0 -21
  332. package/lib/nodes/node/NodeListFactory.js +0 -31
  333. package/lib/nodes/node/NodeListFactory.js.map +0 -1
  334. package/lib/nodes/validity-state/ValidityState.d.ts +0 -52
  335. package/lib/nodes/validity-state/ValidityState.js +0 -81
  336. package/lib/nodes/validity-state/ValidityState.js.map +0 -1
  337. package/src/fetch/FetchHandler.ts +0 -90
  338. package/src/fetch/IAbortSignal.ts +0 -34
  339. package/src/fetch/IBody.ts +0 -18
  340. package/src/fetch/IHeaders.ts +0 -18
  341. package/src/fetch/IRequest.ts +0 -59
  342. package/src/fetch/IRequestInit.ts +0 -41
  343. package/src/fetch/IResponse.ts +0 -22
  344. package/src/fetch/IResponseInit.ts +0 -10
  345. package/src/fetch/RequestInfo.ts +0 -6
  346. package/src/form-data/IFormData.ts +0 -33
  347. package/src/location/RelativeURL.ts +0 -17
  348. package/src/nodes/element/HTMLCollectionFactory.ts +0 -31
  349. package/src/nodes/node/NodeListFactory.ts +0 -31
  350. package/src/nodes/validity-state/ValidityState.ts +0 -84
  351. /package/lib/fetch/{IHeaders.js → types/IHeaders.js} +0 -0
  352. /package/lib/fetch/{IHeadersInit.d.ts → types/IHeadersInit.d.ts} +0 -0
  353. /package/lib/fetch/{IHeadersInit.js → types/IHeadersInit.js} +0 -0
  354. /package/lib/fetch/{IRequest.js → types/IRequest.js} +0 -0
  355. /package/lib/fetch/{IRequestInit.js → types/IRequestInit.js} +0 -0
  356. /package/lib/fetch/{IResponse.js → types/IResponse.js} +0 -0
  357. /package/lib/fetch/{IResponseInit.js → types/IResponseInit.js} +0 -0
  358. /package/lib/nodes/{html-option-element → html-select-element}/HTMLOptionsCollection.js +0 -0
  359. /package/lib/nodes/{html-option-element → html-select-element}/IHTMLOptionsCollection.js +0 -0
  360. /package/src/fetch/{IHeadersInit.ts → types/IHeadersInit.ts} +0 -0
@@ -0,0 +1,666 @@
1
+ import IRequestInit from './types/IRequestInit';
2
+ import IDocument from '../nodes/document/IDocument';
3
+ import IResponse from './types/IResponse';
4
+ import Request from './Request';
5
+ import IRequestInfo from './types/IRequestInfo';
6
+ import Headers from './Headers';
7
+ import FetchRequestReferrerUtility from './utilities/FetchRequestReferrerUtility';
8
+ import DOMException from '../exception/DOMException';
9
+ import DOMExceptionNameEnum from '../exception/DOMExceptionNameEnum';
10
+ import Response from './Response';
11
+ import HTTP, { IncomingMessage } from 'http';
12
+ import HTTPS from 'https';
13
+ import Zlib from 'zlib';
14
+ import { URL } from 'url';
15
+ import { Socket } from 'net';
16
+ import Stream from 'stream';
17
+ import DataURIParser from './data-uri/DataURIParser';
18
+ import FetchCORSUtility from './utilities/FetchCORSUtility';
19
+
20
+ const SUPPORTED_SCHEMAS = ['data:', 'http:', 'https:'];
21
+ const REDIRECT_STATUS_CODES = [301, 302, 303, 307, 308];
22
+ const LAST_CHUNK = Buffer.from('0\r\n\r\n');
23
+ const MAX_REDIRECT_COUNT = 20;
24
+
25
+ /**
26
+ * Handles fetch requests.
27
+ *
28
+ * Based on:
29
+ * https://github.com/node-fetch/node-fetch/blob/main/src/index.js
30
+ *
31
+ * @see https://fetch.spec.whatwg.org/#http-network-fetch
32
+ */
33
+ export default class Fetch {
34
+ private reject: (reason: Error) => void | null = null;
35
+ private resolve: (value: IResponse | Promise<IResponse>) => void | null = null;
36
+ private listeners = {
37
+ onSignalAbort: this.onSignalAbort.bind(this)
38
+ };
39
+ private isChunkedTransfer = false;
40
+ private isProperLastChunkReceived = false;
41
+ private previousChunk: Buffer | null = null;
42
+ private nodeRequest: HTTP.ClientRequest | null = null;
43
+ private response: Response | null = null;
44
+ private ownerDocument: IDocument;
45
+ private request: Request;
46
+ private redirectCount = 0;
47
+
48
+ /**
49
+ * Constructor.
50
+ *
51
+ * @param options Options.
52
+ * @param options.document
53
+ * @param options.url URL.
54
+ * @param [options.init] Init.
55
+ * @param [options.ownerDocument] Owner document.
56
+ * @param [options.redirectCount] Redirect count.
57
+ * @param [options.contentType] Content Type.
58
+ */
59
+ constructor(options: {
60
+ ownerDocument: IDocument;
61
+ url: IRequestInfo;
62
+ init?: IRequestInit;
63
+ redirectCount?: number;
64
+ contentType?: string;
65
+ }) {
66
+ const url = options.url;
67
+
68
+ this.ownerDocument = options.ownerDocument;
69
+ this.request =
70
+ typeof options.url === 'string' || options.url instanceof URL
71
+ ? new Request(options.url, options.init)
72
+ : <Request>url;
73
+ if (options.contentType) {
74
+ (<string>this.request._contentType) = options.contentType;
75
+ }
76
+ this.redirectCount = options.redirectCount || 0;
77
+ }
78
+
79
+ /**
80
+ * Sends request.
81
+ *
82
+ * @returns Response.
83
+ */
84
+ public send(): Promise<IResponse> {
85
+ return new Promise((resolve, reject) => {
86
+ const taskManager = this.ownerDocument.defaultView.happyDOM.asyncTaskManager;
87
+ const taskID = taskManager.startTask(() => this.abort());
88
+
89
+ if (this.resolve) {
90
+ throw new Error('Fetch already sent.');
91
+ }
92
+
93
+ this.resolve = (response: IResponse | Promise<IResponse>): void => {
94
+ resolve(response);
95
+ taskManager.endTask(taskID);
96
+ };
97
+ this.reject = (error: Error): void => {
98
+ reject(error);
99
+ taskManager.endTask(taskID);
100
+ };
101
+
102
+ this.prepareRequest();
103
+ this.validateRequest();
104
+
105
+ if (this.request._url.protocol === 'data:') {
106
+ const result = DataURIParser.parse(this.request.url);
107
+ this.response = new Response(result.buffer, {
108
+ headers: { 'Content-Type': result.type }
109
+ });
110
+ resolve(this.response);
111
+ return;
112
+ }
113
+
114
+ if (this.request.signal.aborted) {
115
+ this.abort();
116
+ return;
117
+ }
118
+
119
+ this.request.signal.addEventListener('abort', this.listeners.onSignalAbort);
120
+
121
+ const send = (this.request._url.protocol === 'https:' ? HTTPS : HTTP).request;
122
+
123
+ this.nodeRequest = send(this.request._url.href, {
124
+ method: this.request.method,
125
+ headers: this.getRequestHeaders()
126
+ });
127
+
128
+ this.nodeRequest.on('error', this.onError.bind(this));
129
+ this.nodeRequest.on('socket', this.onSocket.bind(this));
130
+ this.nodeRequest.on('response', this.onResponse.bind(this));
131
+
132
+ if (this.request.body === null) {
133
+ this.nodeRequest.end();
134
+ } else {
135
+ Stream.pipeline(this.request.body, this.nodeRequest, (error) => {
136
+ if (error) {
137
+ this.onError(error);
138
+ }
139
+ });
140
+ }
141
+ });
142
+ }
143
+
144
+ /**
145
+ * Event listener for "socket" event.
146
+ *
147
+ * @param socket Socket.
148
+ */
149
+ private onSocket(socket: Socket): void {
150
+ const onSocketClose = (): void => {
151
+ if (this.isChunkedTransfer && !this.isProperLastChunkReceived) {
152
+ const error = new DOMException('Premature close.', DOMExceptionNameEnum.networkError);
153
+
154
+ if (this.response && this.response.body) {
155
+ this.response.body.destroy(error);
156
+ }
157
+ }
158
+ };
159
+
160
+ const onData = (buffer: Buffer): void => {
161
+ this.isProperLastChunkReceived = Buffer.compare(buffer.slice(-5), LAST_CHUNK) === 0;
162
+
163
+ // Sometimes final 0-length chunk and end of message code are in separate packets.
164
+ if (!this.isProperLastChunkReceived && this.previousChunk) {
165
+ this.isProperLastChunkReceived =
166
+ Buffer.compare(this.previousChunk.slice(-3), LAST_CHUNK.slice(0, 3)) === 0 &&
167
+ Buffer.compare(buffer.slice(-2), LAST_CHUNK.slice(3)) === 0;
168
+ }
169
+
170
+ this.previousChunk = buffer;
171
+ };
172
+
173
+ socket.prependListener('close', onSocketClose);
174
+ socket.on('data', onData);
175
+
176
+ this.nodeRequest.on('close', () => {
177
+ socket.removeListener('close', onSocketClose);
178
+ socket.removeListener('data', onData);
179
+ });
180
+ }
181
+
182
+ /**
183
+ * Event listener for signal "abort" event.
184
+ */
185
+ private onSignalAbort(): void {
186
+ this.finalizeRequest();
187
+ this.abort();
188
+ }
189
+
190
+ /**
191
+ * Event listener for request "error" event.
192
+ *
193
+ * @param error Error.
194
+ */
195
+ private onError(error: Error): void {
196
+ this.finalizeRequest();
197
+ this.reject(
198
+ new DOMException(
199
+ `Fetch to "${this.request.url}" failed. Error: ${error.message}`,
200
+ DOMExceptionNameEnum.networkError
201
+ )
202
+ );
203
+ }
204
+
205
+ /**
206
+ * Event listener for request "response" event.
207
+ *
208
+ * @param nodeResponse Node response.
209
+ */
210
+ private onResponse(nodeResponse: IncomingMessage): void {
211
+ // Needed for handling bad endings of chunked transfer.
212
+ this.isChunkedTransfer =
213
+ nodeResponse.headers['transfer-encoding'] === 'chunked' &&
214
+ !nodeResponse.headers['content-length'];
215
+
216
+ this.nodeRequest.setTimeout(0);
217
+
218
+ const headers = this.getResponseHeaders(nodeResponse);
219
+
220
+ if (this.handleRedirectResponse(nodeResponse, headers)) {
221
+ return;
222
+ }
223
+
224
+ nodeResponse.once('end', () =>
225
+ this.request.signal.removeEventListener('abort', this.listeners.onSignalAbort)
226
+ );
227
+
228
+ let body = Stream.pipeline(nodeResponse, new Stream.PassThrough(), (error: Error) => {
229
+ if (error) {
230
+ // Ignore error as it is forwarded to the response body.
231
+ }
232
+ });
233
+
234
+ const responseOptions = {
235
+ status: nodeResponse.statusCode,
236
+ statusText: nodeResponse.statusMessage,
237
+ headers
238
+ };
239
+
240
+ const contentEncodingHeader = headers.get('Content-Encoding');
241
+
242
+ if (
243
+ this.request.method === 'HEAD' ||
244
+ contentEncodingHeader === null ||
245
+ nodeResponse.statusCode === 204 ||
246
+ nodeResponse.statusCode === 304
247
+ ) {
248
+ this.response = new Response(body, responseOptions);
249
+ (<boolean>this.response.redirected) = this.redirectCount > 0;
250
+ (<string>this.response.url) = this.request.url;
251
+ this.resolve(this.response);
252
+ return;
253
+ }
254
+
255
+ // Be less strict when decoding compressed responses.
256
+ // Sometimes servers send slightly invalid responses that are still accepted by common browsers.
257
+ // "cURL" always uses Z_SYNC_FLUSH.
258
+ const zlibOptions = {
259
+ flush: Zlib.constants.Z_SYNC_FLUSH,
260
+ finishFlush: Zlib.constants.Z_SYNC_FLUSH
261
+ };
262
+
263
+ // For GZip
264
+ if (contentEncodingHeader === 'gzip' || contentEncodingHeader === 'x-gzip') {
265
+ body = Stream.pipeline(body, Zlib.createGunzip(zlibOptions), (error: Error) => {
266
+ if (error) {
267
+ // Ignore error as it is forwarded to the response body.
268
+ }
269
+ });
270
+ this.response = new Response(body, responseOptions);
271
+ (<boolean>this.response.redirected) = this.redirectCount > 0;
272
+ (<string>this.response.url) = this.request.url;
273
+ this.resolve(this.response);
274
+ return;
275
+ }
276
+
277
+ // For Deflate
278
+ if (contentEncodingHeader === 'deflate' || contentEncodingHeader === 'x-deflate') {
279
+ // Handle the infamous raw deflate response from old servers
280
+ // A hack for old IIS and Apache servers
281
+ const raw = Stream.pipeline(nodeResponse, new Stream.PassThrough(), (error) => {
282
+ if (error) {
283
+ // Ignore error as it is forwarded to the response body.
284
+ }
285
+ });
286
+ raw.on('data', (chunk) => {
287
+ // See http://stackoverflow.com/questions/37519828
288
+ if ((chunk[0] & 0x0f) === 0x08) {
289
+ body = Stream.pipeline(body, Zlib.createInflate(), (error) => {
290
+ if (error) {
291
+ // Ignore error as the fetch() promise has already been resolved.
292
+ }
293
+ });
294
+ } else {
295
+ body = Stream.pipeline(body, Zlib.createInflateRaw(), (error) => {
296
+ if (error) {
297
+ // Ignore error as it is forwarded to the response body.
298
+ }
299
+ });
300
+ }
301
+
302
+ this.response = new Response(body, responseOptions);
303
+ (<boolean>this.response.redirected) = this.redirectCount > 0;
304
+ (<string>this.response.url) = this.request.url;
305
+ this.resolve(this.response);
306
+ });
307
+ raw.on('end', () => {
308
+ // Some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted.
309
+ if (!this.response) {
310
+ this.response = new Response(body, responseOptions);
311
+ (<boolean>this.response.redirected) = this.redirectCount > 0;
312
+ (<string>this.response.url) = this.request.url;
313
+ this.resolve(this.response);
314
+ }
315
+ });
316
+ return;
317
+ }
318
+
319
+ // For BR
320
+ if (contentEncodingHeader === 'br') {
321
+ body = Stream.pipeline(body, Zlib.createBrotliDecompress(), (error) => {
322
+ if (error) {
323
+ // Ignore error as it is forwarded to the response body.
324
+ }
325
+ });
326
+ this.response = new Response(body, responseOptions);
327
+ (<boolean>this.response.redirected) = this.redirectCount > 0;
328
+ (<string>this.response.url) = this.request.url;
329
+ this.resolve(this.response);
330
+ return;
331
+ }
332
+
333
+ // Otherwise, use response as is
334
+ this.response = new Response(body, responseOptions);
335
+ (<boolean>this.response.redirected) = this.redirectCount > 0;
336
+ (<string>this.response.url) = this.request.url;
337
+ this.resolve(this.response);
338
+ }
339
+
340
+ /**
341
+ * Handles redirect response.
342
+ *
343
+ * @param nodeResponse Node response.
344
+ * @param responseHeaders Headers.
345
+ * @returns True if redirect response was handled, false otherwise.
346
+ */
347
+ private handleRedirectResponse(nodeResponse: IncomingMessage, responseHeaders: Headers): boolean {
348
+ if (!this.isRedirect(nodeResponse.statusCode)) {
349
+ return false;
350
+ }
351
+
352
+ switch (this.request.redirect) {
353
+ case 'error':
354
+ this.finalizeRequest();
355
+ this.reject(
356
+ new DOMException(
357
+ `URI requested responds with a redirect, redirect mode is set to "error": ${this.request.url}`,
358
+ DOMExceptionNameEnum.abortError
359
+ )
360
+ );
361
+ return true;
362
+ case 'manual':
363
+ // Nothing to do
364
+ return false;
365
+ case 'follow':
366
+ const locationHeader = responseHeaders.get('Location');
367
+ const shouldBecomeGetRequest =
368
+ nodeResponse.statusCode === 303 ||
369
+ ((nodeResponse.statusCode === 301 || nodeResponse.statusCode === 302) &&
370
+ this.request.method === 'POST');
371
+ let locationURL: URL = null;
372
+
373
+ if (locationHeader !== null) {
374
+ try {
375
+ locationURL = new URL(locationHeader, this.request.url);
376
+ } catch {
377
+ this.finalizeRequest();
378
+ this.reject(
379
+ new DOMException(
380
+ `URI requested responds with an invalid redirect URL: ${locationHeader}`,
381
+ DOMExceptionNameEnum.uriMismatchError
382
+ )
383
+ );
384
+ return true;
385
+ }
386
+ }
387
+
388
+ if (locationURL === null) {
389
+ return false;
390
+ }
391
+
392
+ if (this.redirectCount >= MAX_REDIRECT_COUNT) {
393
+ this.finalizeRequest();
394
+ this.reject(
395
+ new DOMException(
396
+ `Maximum redirects reached at: ${this.request.url}`,
397
+ DOMExceptionNameEnum.networkError
398
+ )
399
+ );
400
+ return true;
401
+ }
402
+
403
+ const headers = new Headers(this.request.headers);
404
+ let body: Stream.Readable | Buffer | null = this.request._bodyBuffer;
405
+
406
+ if (!body && this.request.body) {
407
+ // Piping a used request body is not possible.
408
+ if (this.request.bodyUsed) {
409
+ throw new DOMException(
410
+ 'It is not possible to pipe a body after it is used.',
411
+ DOMExceptionNameEnum.networkError
412
+ );
413
+ }
414
+
415
+ body = new Stream.PassThrough();
416
+ this.request.body.pipe(<Stream.PassThrough>body);
417
+ }
418
+
419
+ const requestInit: IRequestInit = {
420
+ method: this.request.method,
421
+ signal: this.request.signal,
422
+ referrer: this.request.referrer,
423
+ referrerPolicy: this.request.referrerPolicy,
424
+ credentials: this.request.credentials,
425
+ headers,
426
+ body
427
+ };
428
+
429
+ // TODO: Maybe we need to add support for OPTIONS request with 'Access-Control-Allow-*' headers?
430
+ if (
431
+ this.request.credentials === 'omit' ||
432
+ (this.request.credentials === 'same-origin' &&
433
+ FetchCORSUtility.isCORS(this.ownerDocument.location, locationURL))
434
+ ) {
435
+ headers.delete('authorization');
436
+ headers.delete('www-authenticate');
437
+ headers.delete('cookie');
438
+ headers.delete('cookie2');
439
+ }
440
+
441
+ if (nodeResponse.statusCode !== 303 && this.request.body && !this.request._bodyBuffer) {
442
+ this.finalizeRequest();
443
+ this.reject(
444
+ new DOMException(
445
+ 'Cannot follow redirect with body being a readable stream.',
446
+ DOMExceptionNameEnum.networkError
447
+ )
448
+ );
449
+ return true;
450
+ }
451
+
452
+ if (this.request.signal.aborted) {
453
+ this.abort();
454
+ return true;
455
+ }
456
+
457
+ if (shouldBecomeGetRequest) {
458
+ requestInit.method = 'GET';
459
+ requestInit.body = undefined;
460
+ headers.delete('Content-Length');
461
+ headers.delete('Content-Type');
462
+ }
463
+
464
+ const responseReferrerPolicy =
465
+ FetchRequestReferrerUtility.getReferrerPolicyFromHeader(headers);
466
+ if (responseReferrerPolicy) {
467
+ requestInit.referrerPolicy = responseReferrerPolicy;
468
+ }
469
+
470
+ const fetch = new (<typeof Fetch>this.constructor)({
471
+ ownerDocument: this.ownerDocument,
472
+ url: locationURL,
473
+ init: requestInit,
474
+ redirectCount: this.redirectCount + 1,
475
+ contentType: !shouldBecomeGetRequest ? this.request._contentType : undefined
476
+ });
477
+
478
+ this.finalizeRequest();
479
+ this.resolve(fetch.send());
480
+ return true;
481
+ default:
482
+ this.finalizeRequest();
483
+ this.reject(
484
+ new DOMException(
485
+ `Redirect option '${this.request.redirect}' is not a valid value of RequestRedirect`
486
+ )
487
+ );
488
+ return true;
489
+ }
490
+ }
491
+
492
+ /**
493
+ * Prepares the request before being sent.
494
+ */
495
+ private prepareRequest(): void {
496
+ if (!this.request.referrerPolicy) {
497
+ (<string>this.request.referrerPolicy) = 'strict-origin-when-cross-origin';
498
+ }
499
+
500
+ if (this.request.referrer && this.request.referrer !== 'no-referrer') {
501
+ this.request._referrer = FetchRequestReferrerUtility.getSentReferrer(
502
+ this.ownerDocument,
503
+ this.request
504
+ );
505
+ } else {
506
+ this.request._referrer = 'no-referrer';
507
+ }
508
+ }
509
+
510
+ /**
511
+ * Validates the request.
512
+ *
513
+ * @throws {Error} Throws an error if the request is invalid.
514
+ */
515
+ private validateRequest(): void {
516
+ if (!SUPPORTED_SCHEMAS.includes(this.request._url.protocol)) {
517
+ throw new DOMException(
518
+ `Failed to fetch from "${
519
+ this.request.url
520
+ }": URL scheme "${this.request._url.protocol.replace(/:$/, '')}" is not supported.`,
521
+ DOMExceptionNameEnum.notSupportedError
522
+ );
523
+ }
524
+ }
525
+
526
+ /**
527
+ * Returns request headers.
528
+ *
529
+ * @returns Headers.
530
+ */
531
+ private getRequestHeaders(): { [key: string]: string } {
532
+ const headers = new Headers(this.request.headers);
533
+ const document = this.ownerDocument;
534
+ const isCORS = FetchCORSUtility.isCORS(document.location, this.request._url);
535
+
536
+ // TODO: Maybe we need to add support for OPTIONS request with 'Access-Control-Allow-*' headers?
537
+ if (
538
+ this.request.credentials === 'omit' ||
539
+ (this.request.credentials === 'same-origin' && isCORS)
540
+ ) {
541
+ headers.delete('authorization');
542
+ headers.delete('www-authenticate');
543
+ }
544
+
545
+ headers.set('Accept-Encoding', 'gzip, deflate, br');
546
+ headers.set('Connection', 'close');
547
+
548
+ if (!headers.has('User-Agent')) {
549
+ headers.set('User-Agent', document.defaultView.navigator.userAgent);
550
+ }
551
+
552
+ if (this.request._referrer instanceof URL) {
553
+ headers.set('Referer', this.request._referrer.href);
554
+ }
555
+
556
+ if (
557
+ this.request.credentials === 'include' ||
558
+ (this.request.credentials === 'same-origin' && !isCORS)
559
+ ) {
560
+ const cookie = document.defaultView.document.cookie;
561
+ if (cookie) {
562
+ headers.set('Cookie', cookie);
563
+ }
564
+ }
565
+
566
+ if (!headers.has('Accept')) {
567
+ headers.set('Accept', '*/*');
568
+ }
569
+
570
+ if (!headers.has('Content-Length') && this.request._contentLength !== null) {
571
+ headers.set('Content-Length', String(this.request._contentLength));
572
+ }
573
+
574
+ if (!headers.has('Content-Type') && this.request._contentType) {
575
+ headers.set('Content-Type', this.request._contentType);
576
+ }
577
+
578
+ // We need to convert the headers to Node request headers.
579
+ const httpRequestHeaders = {};
580
+
581
+ for (const header of Object.values(headers._entries)) {
582
+ httpRequestHeaders[header.name] = header.value;
583
+ }
584
+
585
+ return httpRequestHeaders;
586
+ }
587
+
588
+ /**
589
+ * Returns "true" if redirect.
590
+ *
591
+ * @param statusCode Status code.
592
+ * @returns "true" if redirect.
593
+ */
594
+ private isRedirect(statusCode: number): boolean {
595
+ return REDIRECT_STATUS_CODES.includes(statusCode);
596
+ }
597
+
598
+ /**
599
+ * Appends headers to response.
600
+ *
601
+ * @param nodeResponse HTTP request.
602
+ * @returns Headers.
603
+ */
604
+ private getResponseHeaders(nodeResponse: IncomingMessage): Headers {
605
+ const headers = new Headers();
606
+ let key = null;
607
+
608
+ for (const header of nodeResponse.rawHeaders) {
609
+ if (!key) {
610
+ key = header;
611
+ } else {
612
+ const lowerKey = key.toLowerCase();
613
+
614
+ // Handles setting cookie headers to the document.
615
+ // "set-cookie" and "set-cookie2" are not allowed in response headers according to spec.
616
+ if (lowerKey === 'set-cookie' || lowerKey === 'set-cookie2') {
617
+ const isCORS = FetchCORSUtility.isCORS(this.ownerDocument.location, this.request._url);
618
+ if (
619
+ this.request.credentials === 'include' ||
620
+ (this.request.credentials === 'same-origin' && !isCORS)
621
+ ) {
622
+ this.ownerDocument.cookie = header;
623
+ }
624
+ } else {
625
+ headers.append(key, header);
626
+ }
627
+
628
+ key = null;
629
+ }
630
+ }
631
+
632
+ return headers;
633
+ }
634
+
635
+ /**
636
+ * Finalizes the request.
637
+ */
638
+ private finalizeRequest(): void {
639
+ this.request.signal.removeEventListener('abort', this.listeners.onSignalAbort);
640
+ this.nodeRequest.destroy();
641
+ }
642
+
643
+ /**
644
+ * Aborts the request.
645
+ */
646
+ private abort(): void {
647
+ const error = new DOMException('The operation was aborted.', DOMExceptionNameEnum.abortError);
648
+
649
+ if (this.request.body) {
650
+ this.request.body.destroy(error);
651
+ }
652
+
653
+ if (!this.response || !this.response.body) {
654
+ if (this.reject) {
655
+ this.reject(error);
656
+ }
657
+ return;
658
+ }
659
+
660
+ this.response.body.emit('error', error);
661
+
662
+ if (this.reject) {
663
+ this.reject(error);
664
+ }
665
+ }
666
+ }