happy-dom 7.7.2 → 7.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (97) hide show
  1. package/README.md +62 -27
  2. package/lib/async-task-manager/AsyncTaskManager.d.ts +3 -8
  3. package/lib/async-task-manager/AsyncTaskManager.js +21 -24
  4. package/lib/async-task-manager/AsyncTaskManager.js.map +1 -1
  5. package/lib/event/IEventListener.d.ts +1 -1
  6. package/lib/exception/DOMExceptionNameEnum.d.ts +4 -1
  7. package/lib/exception/DOMExceptionNameEnum.js +3 -0
  8. package/lib/exception/DOMExceptionNameEnum.js.map +1 -1
  9. package/lib/fetch/FetchHandler.d.ts +3 -2
  10. package/lib/fetch/FetchHandler.js +31 -3
  11. package/lib/fetch/FetchHandler.js.map +1 -1
  12. package/lib/fetch/RequestInfo.d.ts +5 -0
  13. package/lib/fetch/RequestInfo.js +3 -0
  14. package/lib/fetch/RequestInfo.js.map +1 -0
  15. package/lib/fetch/ResourceFetchHandler.d.ts +2 -2
  16. package/lib/fetch/ResourceFetchHandler.js +9 -8
  17. package/lib/fetch/ResourceFetchHandler.js.map +1 -1
  18. package/lib/index.d.ts +1 -2
  19. package/lib/index.js +3 -4
  20. package/lib/index.js.map +1 -1
  21. package/lib/location/Location.d.ts +2 -1
  22. package/lib/location/Location.js +4 -7
  23. package/lib/location/Location.js.map +1 -1
  24. package/lib/location/RelativeURL.d.ts +3 -1
  25. package/lib/location/RelativeURL.js +2 -11
  26. package/lib/location/RelativeURL.js.map +1 -1
  27. package/lib/nodes/document/Document.d.ts +12 -2
  28. package/lib/nodes/document/Document.js +16 -2
  29. package/lib/nodes/document/Document.js.map +1 -1
  30. package/lib/nodes/document/IDocument.d.ts +2 -0
  31. package/lib/nodes/html-link-element/HTMLLinkElement.js +5 -2
  32. package/lib/nodes/html-link-element/HTMLLinkElement.js.map +1 -1
  33. package/lib/nodes/html-script-element/HTMLScriptElement.js +1 -1
  34. package/lib/nodes/html-script-element/HTMLScriptElement.js.map +1 -1
  35. package/lib/nodes/html-script-element/ScriptUtility.js +4 -0
  36. package/lib/nodes/html-script-element/ScriptUtility.js.map +1 -1
  37. package/lib/window/IHappyDOMSettings.d.ts +9 -0
  38. package/lib/window/IHappyDOMSettings.js +3 -0
  39. package/lib/window/IHappyDOMSettings.js.map +1 -0
  40. package/lib/window/IWindow.d.ts +15 -6
  41. package/lib/window/Window.d.ts +18 -3
  42. package/lib/window/Window.js +26 -4
  43. package/lib/window/Window.js.map +1 -1
  44. package/lib/xml-http-request/XMLHttpRequest.d.ts +196 -0
  45. package/lib/xml-http-request/XMLHttpRequest.js +777 -0
  46. package/lib/xml-http-request/XMLHttpRequest.js.map +1 -0
  47. package/lib/xml-http-request/XMLHttpRequestCertificate.d.ts +5 -0
  48. package/lib/xml-http-request/XMLHttpRequestCertificate.js +55 -0
  49. package/lib/xml-http-request/XMLHttpRequestCertificate.js.map +1 -0
  50. package/lib/xml-http-request/XMLHttpRequestEventTarget.d.ts +15 -0
  51. package/lib/xml-http-request/XMLHttpRequestEventTarget.js +23 -0
  52. package/lib/xml-http-request/XMLHttpRequestEventTarget.js.map +1 -0
  53. package/lib/xml-http-request/XMLHttpRequestReadyStateEnum.d.ts +8 -0
  54. package/lib/xml-http-request/XMLHttpRequestReadyStateEnum.js +12 -0
  55. package/lib/xml-http-request/XMLHttpRequestReadyStateEnum.js.map +1 -0
  56. package/lib/xml-http-request/XMLHttpRequestUpload.d.ts +6 -0
  57. package/lib/xml-http-request/XMLHttpRequestUpload.js +13 -0
  58. package/lib/xml-http-request/XMLHttpRequestUpload.js.map +1 -0
  59. package/lib/xml-http-request/XMLHttpResponseTypeEnum.d.ts +8 -0
  60. package/lib/xml-http-request/XMLHttpResponseTypeEnum.js +12 -0
  61. package/lib/xml-http-request/XMLHttpResponseTypeEnum.js.map +1 -0
  62. package/lib/xml-http-request/utilities/XMLHttpRequestSyncRequestScriptBuilder.d.ts +15 -0
  63. package/lib/xml-http-request/utilities/XMLHttpRequestSyncRequestScriptBuilder.js +55 -0
  64. package/lib/xml-http-request/utilities/XMLHttpRequestSyncRequestScriptBuilder.js.map +1 -0
  65. package/lib/xml-http-request/utilities/XMLHttpRequestURLUtility.d.ts +35 -0
  66. package/lib/xml-http-request/utilities/XMLHttpRequestURLUtility.js +62 -0
  67. package/lib/xml-http-request/utilities/XMLHttpRequestURLUtility.js.map +1 -0
  68. package/package.json +2 -2
  69. package/src/async-task-manager/AsyncTaskManager.ts +24 -26
  70. package/src/event/IEventListener.ts +1 -1
  71. package/src/exception/DOMExceptionNameEnum.ts +4 -1
  72. package/src/fetch/FetchHandler.ts +40 -4
  73. package/src/fetch/RequestInfo.ts +6 -0
  74. package/src/fetch/ResourceFetchHandler.ts +10 -8
  75. package/src/index.ts +1 -2
  76. package/src/location/Location.ts +3 -3
  77. package/src/location/RelativeURL.ts +3 -14
  78. package/src/nodes/document/Document.ts +18 -2
  79. package/src/nodes/document/IDocument.ts +2 -0
  80. package/src/nodes/html-link-element/HTMLLinkElement.ts +7 -2
  81. package/src/nodes/html-script-element/HTMLScriptElement.ts +1 -1
  82. package/src/nodes/html-script-element/ScriptUtility.ts +8 -0
  83. package/src/window/IHappyDOMSettings.ts +9 -0
  84. package/src/window/IWindow.ts +15 -6
  85. package/src/window/Window.ts +36 -5
  86. package/src/xml-http-request/XMLHttpRequest.ts +998 -0
  87. package/src/xml-http-request/XMLHttpRequestCertificate.ts +52 -0
  88. package/src/xml-http-request/XMLHttpRequestEventTarget.ts +17 -0
  89. package/src/xml-http-request/XMLHttpRequestReadyStateEnum.ts +9 -0
  90. package/src/xml-http-request/XMLHttpRequestUpload.ts +6 -0
  91. package/src/xml-http-request/XMLHttpResponseTypeEnum.ts +9 -0
  92. package/src/xml-http-request/utilities/XMLHttpRequestSyncRequestScriptBuilder.ts +53 -0
  93. package/src/xml-http-request/utilities/XMLHttpRequestURLUtility.ts +64 -0
  94. package/lib/location/URL.d.ts +0 -53
  95. package/lib/location/URL.js +0 -96
  96. package/lib/location/URL.js.map +0 -1
  97. package/src/location/URL.ts +0 -102
@@ -7,7 +7,7 @@ import IDocument from '../nodes/document/IDocument';
7
7
  */
8
8
  export default class ResourceFetchHandler {
9
9
  /**
10
- * Returns resource data asynchonously.
10
+ * Returns resource data asynchronously.
11
11
  *
12
12
  * @param document Document.
13
13
  * @param url URL.
@@ -24,7 +24,7 @@ export default class ResourceFetchHandler {
24
24
  }
25
25
 
26
26
  /**
27
- * Returns resource data synchonously.
27
+ * Returns resource data synchronously.
28
28
  *
29
29
  * @param document Document.
30
30
  * @param url URL.
@@ -32,16 +32,18 @@ export default class ResourceFetchHandler {
32
32
  */
33
33
  public static fetchSync(document: IDocument, url: string): string {
34
34
  // We want to only load SyncRequest when it is needed to improve performance and not have direct dependencies to server side packages.
35
- const absoluteURL = RelativeURL.getAbsoluteURL(document.defaultView.location, url);
36
- const syncRequest = require('sync-request');
37
- const response = syncRequest('GET', absoluteURL);
35
+ const absoluteURL = RelativeURL.getAbsoluteURL(document.defaultView.location, url).href;
38
36
 
39
- if (response.isError()) {
37
+ const xhr = new document.defaultView.XMLHttpRequest();
38
+ xhr.open('GET', absoluteURL, false);
39
+ xhr.send();
40
+
41
+ if (xhr.status !== 200) {
40
42
  throw new DOMException(
41
- `Failed to perform request to "${absoluteURL}". Status code: ${response.statusCode}`
43
+ `Failed to perform request to "${absoluteURL}". Status code: ${xhr.status}`
42
44
  );
43
45
  }
44
46
 
45
- return response.getBody().toString();
47
+ return xhr.responseText;
46
48
  }
47
49
  }
package/src/index.ts CHANGED
@@ -4,7 +4,7 @@ import Window from './window/Window';
4
4
  import DataTransfer from './event/DataTransfer';
5
5
  import DataTransferItem from './event/DataTransferItem';
6
6
  import DataTransferItemList from './event/DataTransferItemList';
7
- import URL from './location/URL';
7
+ import { URL, URLSearchParams } from 'url';
8
8
  import Location from './location/Location';
9
9
  import MutationObserver from './mutation-observer/MutationObserver';
10
10
  import ResizeObserver from './resize-observer/ResizeObserver';
@@ -115,7 +115,6 @@ import CSSMediaRule from './css/rules/CSSMediaRule';
115
115
  import CSSStyleRule from './css/rules/CSSStyleRule';
116
116
  import Storage from './storage/Storage';
117
117
  import DOMRect from './nodes/element/DOMRect';
118
- import { URLSearchParams } from 'url';
119
118
  import Selection from './selection/Selection';
120
119
  import Range from './range/Range';
121
120
  import HTMLDialogElement from './nodes/html-dialog-element/HTMLDialogElement';
@@ -1,4 +1,4 @@
1
- import URL from './URL';
1
+ import { URL } from 'url';
2
2
 
3
3
  /**
4
4
  *
@@ -8,7 +8,7 @@ export default class Location extends URL {
8
8
  * Constructor.
9
9
  */
10
10
  constructor() {
11
- super('');
11
+ super('about:blank');
12
12
  }
13
13
 
14
14
  /**
@@ -17,7 +17,7 @@ export default class Location extends URL {
17
17
  * @param url URL.
18
18
  */
19
19
  public replace(url: string): void {
20
- this.parse(url);
20
+ this.href = url;
21
21
  }
22
22
 
23
23
  /**
@@ -1,4 +1,5 @@
1
1
  import Location from './Location';
2
+ import { URL } from 'url';
2
3
 
3
4
  /**
4
5
  * Helper class for getting the URL relative to a Location object.
@@ -10,19 +11,7 @@ export default class RelativeURL {
10
11
  * @param location Location.
11
12
  * @param url URL.
12
13
  */
13
- public static getAbsoluteURL(location: Location, url: string): string {
14
- if (url.startsWith('/')) {
15
- return location.origin + url;
16
- }
17
-
18
- if (!url.startsWith('https://') && !url.startsWith('http://')) {
19
- let pathname = location.pathname;
20
- if (pathname.endsWith('/')) {
21
- pathname = pathname.slice(0, -1);
22
- }
23
- return location.origin + pathname + '/' + url;
24
- }
25
-
26
- return url;
14
+ public static getAbsoluteURL(location: Location, url: string): URL {
15
+ return new URL(url, location.href);
27
16
  }
28
17
  }
@@ -185,7 +185,6 @@ export default class Document extends Node implements IDocument {
185
185
  /**
186
186
  * Creates an instance of Document.
187
187
  *
188
- * @param defaultView Default view.
189
188
  */
190
189
  constructor() {
191
190
  super();
@@ -406,6 +405,24 @@ export default class Document extends Node implements IDocument {
406
405
  return this.defaultView.location.href;
407
406
  }
408
407
 
408
+ /**
409
+ * Returns URL.
410
+ *
411
+ * @returns the URL of the current document.
412
+ * */
413
+ public get URL(): string {
414
+ return this.defaultView.location.href;
415
+ }
416
+
417
+ /**
418
+ * Returns document URI.
419
+ *
420
+ * @returns the URL of the current document.
421
+ * */
422
+ public get documentURI(): string {
423
+ return this.URL;
424
+ }
425
+
409
426
  /**
410
427
  * Inserts a set of Node objects or DOMString objects after the last child of the ParentNode. DOMString objects are inserted as equivalent Text nodes.
411
428
  *
@@ -868,7 +885,6 @@ export default class Document extends Node implements IDocument {
868
885
  *
869
886
  * @param node Node to import.
870
887
  * @param [deep=false] Set to "true" if the clone should be deep.
871
- * @param Imported Node.
872
888
  */
873
889
  public importNode(node: INode, deep = false): INode {
874
890
  if (!(node instanceof Node)) {
@@ -39,6 +39,8 @@ export default interface IDocument extends IParentNode {
39
39
  readonly readyState: DocumentReadyStateEnum;
40
40
  readonly charset: string;
41
41
  readonly characterSet: string;
42
+ readonly URL: string;
43
+ readonly documentURI: string;
42
44
  cookie: string;
43
45
 
44
46
  // Events
@@ -196,7 +196,8 @@ export default class HTMLLinkElement extends HTMLElement implements IHTMLLinkEle
196
196
  href !== null &&
197
197
  rel &&
198
198
  rel.toLowerCase() === 'stylesheet' &&
199
- this.isConnected
199
+ this.isConnected &&
200
+ !this.ownerDocument.defaultView.happyDOM.settings.disableCSSFileLoading
200
201
  ) {
201
202
  (<Document>this.ownerDocument)._readyStateManager.startTask();
202
203
  ResourceFetchHandler.fetch(this.ownerDocument, href)
@@ -255,7 +256,11 @@ export default class HTMLLinkElement extends HTMLElement implements IHTMLLinkEle
255
256
 
256
257
  super._connectToNode(parentNode);
257
258
 
258
- if (isConnected !== isParentConnected && this._evaluateCSS) {
259
+ if (
260
+ isConnected !== isParentConnected &&
261
+ this._evaluateCSS &&
262
+ !this.ownerDocument.defaultView.happyDOM.settings.disableCSSFileLoading
263
+ ) {
259
264
  const href = this.getAttributeNS(null, 'href');
260
265
  const rel = this.getAttributeNS(null, 'rel');
261
266
 
@@ -193,7 +193,7 @@ export default class HTMLScriptElement extends HTMLElement implements IHTMLScrip
193
193
 
194
194
  if (src !== null) {
195
195
  ScriptUtility.loadExternalScript(this);
196
- } else {
196
+ } else if (!this.ownerDocument.defaultView.happyDOM.settings.disableJavaScriptEvaluation) {
197
197
  const textContent = this.textContent;
198
198
  const type = this.getAttributeNS(null, 'type');
199
199
  if (
@@ -18,6 +18,14 @@ export default class ScriptUtility {
18
18
  public static async loadExternalScript(element: HTMLScriptElement): Promise<void> {
19
19
  const src = element.getAttributeNS(null, 'src');
20
20
  const async = element.getAttributeNS(null, 'async') !== null;
21
+
22
+ if (
23
+ element.ownerDocument.defaultView.happyDOM.settings.disableJavaScriptFileLoading ||
24
+ element.ownerDocument.defaultView.happyDOM.settings.disableJavaScriptEvaluation
25
+ ) {
26
+ return;
27
+ }
28
+
21
29
  if (async) {
22
30
  let code = null;
23
31
  (<Document>element.ownerDocument)._readyStateManager.startTask();
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Happy DOM settings.
3
+ */
4
+ export default interface IHappyDOMSettings {
5
+ disableJavaScriptEvaluation: boolean;
6
+ disableJavaScriptFileLoading: boolean;
7
+ disableCSSFileLoading: boolean;
8
+ enableFileSystemHttpRequests: boolean;
9
+ }
@@ -39,7 +39,7 @@ import KeyboardEvent from '../event/events/KeyboardEvent';
39
39
  import ProgressEvent from '../event/events/ProgressEvent';
40
40
  import MediaQueryListEvent from '../event/events/MediaQueryListEvent';
41
41
  import EventTarget from '../event/EventTarget';
42
- import URL from '../location/URL';
42
+ import { URL, URLSearchParams } from 'url';
43
43
  import Location from '../location/Location';
44
44
  import MutationObserver from '../mutation-observer/MutationObserver';
45
45
  import DOMParser from '../dom-parser/DOMParser';
@@ -92,14 +92,18 @@ import IRequestInit from '../fetch/IRequestInit';
92
92
  import IResponse from '../fetch/IResponse';
93
93
  import Range from '../range/Range';
94
94
  import MediaQueryList from '../match-media/MediaQueryList';
95
+ import XMLHttpRequest from '../xml-http-request/XMLHttpRequest';
96
+ import XMLHttpRequestUpload from '../xml-http-request/XMLHttpRequestUpload';
97
+ import XMLHttpRequestEventTarget from '../xml-http-request/XMLHttpRequestEventTarget';
95
98
  import DOMRect from '../nodes/element/DOMRect';
96
99
  import Window from './Window';
97
100
  import Attr from '../nodes/attr/Attr';
98
101
  import NamedNodeMap from '../named-node-map/NamedNodeMap';
99
- import { URLSearchParams } from 'url';
100
102
  import { Performance } from 'perf_hooks';
101
103
  import IElement from '../nodes/element/IElement';
102
104
  import ProcessingInstruction from '../nodes/processing-instruction/ProcessingInstruction';
105
+ import IHappyDOMSettings from './IHappyDOMSettings';
106
+ import RequestInfo from '../fetch/RequestInfo';
103
107
 
104
108
  /**
105
109
  * Window without dependencies to server side specific packages.
@@ -112,6 +116,8 @@ export default interface IWindow extends IEventTarget, NodeJS.Global {
112
116
  asyncTaskManager: AsyncTaskManager;
113
117
  setInnerWidth: (width: number) => void;
114
118
  setInnerHeight: (height: number) => void;
119
+ setURL: (url: string) => void;
120
+ settings: IHappyDOMSettings;
115
121
  };
116
122
 
117
123
  // Global classes
@@ -173,6 +179,7 @@ export default interface IWindow extends IEventTarget, NodeJS.Global {
173
179
  readonly DataTransferItem: typeof DataTransferItem;
174
180
  readonly DataTransferItemList: typeof DataTransferItemList;
175
181
  readonly URL: typeof URL;
182
+ readonly URLSearchParams: typeof URLSearchParams;
176
183
  readonly Location: typeof Location;
177
184
  readonly CustomElementRegistry: typeof CustomElementRegistry;
178
185
  readonly Window: typeof Window;
@@ -186,7 +193,6 @@ export default interface IWindow extends IEventTarget, NodeJS.Global {
186
193
  readonly History: typeof History;
187
194
  readonly Screen: typeof Screen;
188
195
  readonly Storage: typeof Storage;
189
- readonly URLSearchParams: typeof URLSearchParams;
190
196
  readonly HTMLCollection: typeof HTMLCollection;
191
197
  readonly NodeList: typeof NodeList;
192
198
  readonly CSSUnitValue: typeof CSSUnitValue;
@@ -209,6 +215,9 @@ export default interface IWindow extends IEventTarget, NodeJS.Global {
209
215
  readonly Response: { new (body?: unknown | null, init?: IResponseInit): IResponse };
210
216
  readonly Range: typeof Range;
211
217
  readonly DOMRect: typeof DOMRect;
218
+ readonly XMLHttpRequest: typeof XMLHttpRequest;
219
+ readonly XMLHttpRequestUpload: typeof XMLHttpRequestUpload;
220
+ readonly XMLHttpRequestEventTarget: typeof XMLHttpRequestEventTarget;
212
221
 
213
222
  // Events
214
223
  onload: (event: Event) => void;
@@ -334,13 +343,13 @@ export default interface IWindow extends IEventTarget, NodeJS.Global {
334
343
  * @param [init] Init.
335
344
  * @returns Promise.
336
345
  */
337
- fetch(url: string, init?: IRequestInit): Promise<IResponse>;
346
+ fetch(url: RequestInfo, init?: IRequestInit): Promise<IResponse>;
338
347
 
339
348
  /**
340
349
  * Creates a Base64-encoded ASCII string from a binary string (i.e., a string in which each character in the string is treated as a byte of binary data).
341
350
  *
342
351
  * @see https://developer.mozilla.org/en-US/docs/Web/API/btoa
343
- * @param data Binay data.
352
+ * @param data Binary data.
344
353
  * @returns Base64-encoded string.
345
354
  */
346
355
  btoa(data: unknown): string;
@@ -351,7 +360,7 @@ export default interface IWindow extends IEventTarget, NodeJS.Global {
351
360
  * @see https://developer.mozilla.org/en-US/docs/Web/API/atob
352
361
  * @see https://infra.spec.whatwg.org/#forgiving-base64-encode.
353
362
  * @see Https://html.spec.whatwg.org/multipage/webappapis.html#btoa.
354
- * @param data Binay string.
363
+ * @param data Binary string.
355
364
  * @returns An ASCII string containing decoded data from encodedData.
356
365
  */
357
366
  atob(data: unknown): string;
@@ -40,7 +40,7 @@ import KeyboardEvent from '../event/events/KeyboardEvent';
40
40
  import ProgressEvent from '../event/events/ProgressEvent';
41
41
  import MediaQueryListEvent from '../event/events/MediaQueryListEvent';
42
42
  import EventTarget from '../event/EventTarget';
43
- import URL from '../location/URL';
43
+ import { URL, URLSearchParams } from 'url';
44
44
  import Location from '../location/Location';
45
45
  import NonImplementedEventTypes from '../event/NonImplementedEventTypes';
46
46
  import MutationObserver from '../mutation-observer/MutationObserver';
@@ -97,7 +97,6 @@ import MimeType from '../navigator/MimeType';
97
97
  import MimeTypeArray from '../navigator/MimeTypeArray';
98
98
  import Plugin from '../navigator/Plugin';
99
99
  import PluginArray from '../navigator/PluginArray';
100
- import { URLSearchParams } from 'url';
101
100
  import FetchHandler from '../fetch/FetchHandler';
102
101
  import { default as RangeImplementation } from '../range/Range';
103
102
  import DOMRect from '../nodes/element/DOMRect';
@@ -105,12 +104,17 @@ import VMGlobalPropertyScript from './VMGlobalPropertyScript';
105
104
  import * as PerfHooks from 'perf_hooks';
106
105
  import VM from 'vm';
107
106
  import { Buffer } from 'buffer';
107
+ import XMLHttpRequestImplementation from '../xml-http-request/XMLHttpRequest';
108
+ import XMLHttpRequestUpload from '../xml-http-request/XMLHttpRequestUpload';
109
+ import XMLHttpRequestEventTarget from '../xml-http-request/XMLHttpRequestEventTarget';
108
110
  import Base64 from '../base64/Base64';
109
111
  import IDocument from '../nodes/document/IDocument';
110
112
  import Attr from '../nodes/attr/Attr';
111
113
  import NamedNodeMap from '../named-node-map/NamedNodeMap';
112
114
  import IElement from '../nodes/element/IElement';
113
115
  import ProcessingInstruction from '../nodes/processing-instruction/ProcessingInstruction';
116
+ import IHappyDOMSettings from './IHappyDOMSettings';
117
+ import RequestInfo from '../fetch/RequestInfo';
114
118
 
115
119
  const ORIGINAL_SET_TIMEOUT = setTimeout;
116
120
  const ORIGINAL_CLEAR_TIMEOUT = clearTimeout;
@@ -144,6 +148,15 @@ export default class Window extends EventTarget implements IWindow {
144
148
  (<number>this.innerHeight) = height;
145
149
  this.dispatchEvent(new Event('resize'));
146
150
  }
151
+ },
152
+ setURL: (url: string) => {
153
+ this.location.href = url;
154
+ },
155
+ settings: {
156
+ disableJavaScriptEvaluation: false,
157
+ disableJavaScriptFileLoading: false,
158
+ disableCSSFileLoading: false,
159
+ enableFileSystemHttpRequests: false
147
160
  }
148
161
  };
149
162
 
@@ -241,6 +254,9 @@ export default class Window extends EventTarget implements IWindow {
241
254
  public readonly Response: {
242
255
  new (body?: NodeJS.ReadableStream | null, init?: IResponseInit): IResponse;
243
256
  };
257
+ public readonly XMLHttpRequestUpload = XMLHttpRequestUpload;
258
+ public readonly XMLHttpRequestEventTarget = XMLHttpRequestEventTarget;
259
+ public readonly XMLHttpRequest;
244
260
  public readonly DOMParser;
245
261
  public readonly Range;
246
262
  public readonly FileReader;
@@ -346,8 +362,14 @@ export default class Window extends EventTarget implements IWindow {
346
362
  * @param [options.innerWidth] Inner width.
347
363
  * @param [options.innerHeight] Inner height.
348
364
  * @param [options.url] URL.
365
+ * @param [options.settings] Settings.
349
366
  */
350
- constructor(options?: { innerWidth?: number; innerHeight?: number; url?: string }) {
367
+ constructor(options?: {
368
+ innerWidth?: number;
369
+ innerHeight?: number;
370
+ url?: string;
371
+ settings?: IHappyDOMSettings;
372
+ }) {
351
373
  super();
352
374
 
353
375
  this.customElements = new CustomElementRegistry();
@@ -365,6 +387,10 @@ export default class Window extends EventTarget implements IWindow {
365
387
  this.location.href = options.url;
366
388
  }
367
389
 
390
+ if (options?.settings) {
391
+ this.happyDOM.settings = Object.assign(this.happyDOM.settings, options.settings);
392
+ }
393
+
368
394
  this._setTimeout = ORIGINAL_SET_TIMEOUT;
369
395
  this._clearTimeout = ORIGINAL_CLEAR_TIMEOUT;
370
396
  this._setInterval = ORIGINAL_SET_INTERVAL;
@@ -413,6 +439,7 @@ export default class Window extends EventTarget implements IWindow {
413
439
  FileReaderImplementation._ownerDocument = document;
414
440
  DOMParserImplementation._ownerDocument = document;
415
441
  RangeImplementation._ownerDocument = document;
442
+ XMLHttpRequestImplementation._ownerDocument = document;
416
443
 
417
444
  /* eslint-disable jsdoc/require-jsdoc */
418
445
  class Response extends ResponseImplementation {
@@ -430,10 +457,13 @@ export default class Window extends EventTarget implements IWindow {
430
457
  class DOMParser extends DOMParserImplementation {
431
458
  public static _ownerDocument: IDocument = document;
432
459
  }
433
- class Range extends RangeImplementation {
460
+ class XMLHttpRequest extends XMLHttpRequestImplementation {
434
461
  public static _ownerDocument: IDocument = document;
435
462
  }
436
463
 
464
+ class Range extends RangeImplementation {
465
+ public static _ownerDocument: IDocument = document;
466
+ }
437
467
  /* eslint-enable jsdoc/require-jsdoc */
438
468
 
439
469
  this.Response = Response;
@@ -441,6 +471,7 @@ export default class Window extends EventTarget implements IWindow {
441
471
  this.Image = Image;
442
472
  this.FileReader = FileReader;
443
473
  this.DOMParser = DOMParser;
474
+ this.XMLHttpRequest = XMLHttpRequest;
444
475
  this.Range = Range;
445
476
 
446
477
  this._setupVMContext();
@@ -629,7 +660,7 @@ export default class Window extends EventTarget implements IWindow {
629
660
  * @param [init] Init.
630
661
  * @returns Promise.
631
662
  */
632
- public async fetch(url: string, init?: IRequestInit): Promise<IResponse> {
663
+ public async fetch(url: RequestInfo, init?: IRequestInit): Promise<IResponse> {
633
664
  return await FetchHandler.fetch(this.document, url, init);
634
665
  }
635
666