happy-dom 2.50.0 → 2.51.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.
- package/lib/async-task-manager/AsyncTaskManager.d.ts +65 -0
- package/lib/{window → async-task-manager}/AsyncTaskManager.js +52 -55
- package/lib/async-task-manager/AsyncTaskManager.js.map +1 -0
- package/lib/fetch/FetchHandler.d.ts +17 -0
- package/lib/fetch/FetchHandler.js +59 -0
- package/lib/fetch/FetchHandler.js.map +1 -0
- package/lib/fetch/Headers.d.ts +7 -0
- package/lib/fetch/Headers.js +53 -0
- package/lib/fetch/Headers.js.map +1 -0
- package/lib/fetch/IAbortSignal.d.ts +16 -0
- package/lib/fetch/IAbortSignal.js +4 -0
- package/lib/fetch/IAbortSignal.js.map +1 -0
- package/lib/fetch/IBody.d.ts +17 -0
- package/lib/{window/IFetchOptions.js → fetch/IBody.js} +1 -1
- package/lib/fetch/IBody.js.map +1 -0
- package/lib/fetch/IHeaders.d.ts +18 -0
- package/lib/fetch/IHeaders.js +3 -0
- package/lib/fetch/IHeaders.js.map +1 -0
- package/lib/fetch/IHeadersInit.d.ts +5 -0
- package/lib/fetch/IHeadersInit.js +3 -0
- package/lib/fetch/IHeadersInit.js.map +1 -0
- package/lib/fetch/IRequest.d.ts +18 -0
- package/lib/fetch/IRequest.js +3 -0
- package/lib/fetch/IRequest.js.map +1 -0
- package/lib/fetch/IRequestInit.d.ts +15 -0
- package/lib/fetch/IRequestInit.js +3 -0
- package/lib/fetch/IRequestInit.js.map +1 -0
- package/lib/fetch/IResponse.d.ts +20 -0
- package/lib/{window → fetch}/IResponse.js +0 -0
- package/lib/{window → fetch}/IResponse.js.map +1 -1
- package/lib/fetch/IResponseInit.d.ts +9 -0
- package/lib/fetch/IResponseInit.js +3 -0
- package/lib/fetch/IResponseInit.js.map +1 -0
- package/lib/fetch/Request.d.ts +69 -0
- package/lib/fetch/Request.js +179 -0
- package/lib/fetch/Request.js.map +1 -0
- package/lib/fetch/ResourceFetchHandler.d.ts +22 -0
- package/lib/fetch/{ResourceFetcher.js → ResourceFetchHandler.js} +19 -26
- package/lib/fetch/ResourceFetchHandler.js.map +1 -0
- package/lib/fetch/Response.d.ts +69 -0
- package/lib/fetch/Response.js +179 -0
- package/lib/fetch/Response.js.map +1 -0
- package/lib/file/Blob.d.ts +8 -1
- package/lib/file/Blob.js +48 -0
- package/lib/file/Blob.js.map +1 -1
- package/lib/file/IBlob.d.ts +10 -0
- package/lib/file/IBlob.js +3 -0
- package/lib/file/IBlob.js.map +1 -0
- package/lib/form-data/IFormData.d.ts +30 -0
- package/lib/form-data/IFormData.js +3 -0
- package/lib/form-data/IFormData.js.map +1 -0
- package/lib/index.d.ts +3 -5
- package/lib/index.js +3 -3
- package/lib/index.js.map +1 -1
- package/lib/nodes/html-link-element/HTMLLinkElement.js +3 -3
- package/lib/nodes/html-link-element/HTMLLinkElement.js.map +1 -1
- package/lib/nodes/html-script-element/ScriptUtility.js +3 -9
- package/lib/nodes/html-script-element/ScriptUtility.js.map +1 -1
- package/lib/window/IWindow.d.ts +20 -16
- package/lib/window/Window.d.ts +45 -10
- package/lib/window/Window.js +72 -66
- package/lib/window/Window.js.map +1 -1
- package/package.json +3 -2
- package/src/async-task-manager/AsyncTaskManager.ts +128 -0
- package/src/fetch/FetchHandler.ts +54 -0
- package/src/fetch/Headers.ts +7 -0
- package/src/fetch/IAbortSignal.ts +34 -0
- package/src/fetch/IBody.ts +18 -0
- package/src/fetch/IHeaders.ts +18 -0
- package/src/fetch/IHeadersInit.ts +5 -0
- package/src/fetch/IRequest.ts +59 -0
- package/src/fetch/IRequestInit.ts +41 -0
- package/src/fetch/IResponse.ts +22 -0
- package/src/fetch/IResponseInit.ts +10 -0
- package/src/fetch/Request.ts +149 -0
- package/src/fetch/ResourceFetchHandler.ts +47 -0
- package/src/fetch/Response.ts +149 -0
- package/src/file/Blob.ts +12 -1
- package/src/file/IBlob.ts +10 -0
- package/src/form-data/IFormData.ts +33 -0
- package/src/index.ts +2 -6
- package/src/nodes/html-link-element/HTMLLinkElement.ts +3 -3
- package/src/nodes/html-script-element/ScriptUtility.ts +3 -9
- package/src/window/IWindow.ts +14 -16
- package/src/window/Window.ts +68 -67
- package/lib/fetch/ResourceFetcher.d.ts +0 -30
- package/lib/fetch/ResourceFetcher.js.map +0 -1
- package/lib/url-search-params/URLSearchParams.d.ts +0 -87
- package/lib/url-search-params/URLSearchParams.js +0 -196
- package/lib/url-search-params/URLSearchParams.js.map +0 -1
- package/lib/window/AsyncTaskManager.d.ts +0 -54
- package/lib/window/AsyncTaskManager.js.map +0 -1
- package/lib/window/AsyncTaskTypeEnum.d.ts +0 -5
- package/lib/window/AsyncTaskTypeEnum.js +0 -9
- package/lib/window/AsyncTaskTypeEnum.js.map +0 -1
- package/lib/window/IFetchOptions.d.ts +0 -13
- package/lib/window/IFetchOptions.js.map +0 -1
- package/lib/window/IResponse.d.ts +0 -32
- package/src/fetch/ResourceFetcher.ts +0 -55
- package/src/url-search-params/URLSearchParams.ts +0 -198
- package/src/window/AsyncTaskManager.ts +0 -127
- package/src/window/AsyncTaskTypeEnum.ts +0 -5
- package/src/window/IFetchOptions.ts +0 -11
- package/src/window/IResponse.ts +0 -34
@@ -0,0 +1,47 @@
|
|
1
|
+
import RelativeURL from '../location/RelativeURL';
|
2
|
+
import DOMException from '../exception/DOMException';
|
3
|
+
import IDocument from '../nodes/document/IDocument';
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Helper class for performing fetch of resources.
|
7
|
+
*/
|
8
|
+
export default class ResourceFetchHandler {
|
9
|
+
/**
|
10
|
+
* Returns resource data asynchonously.
|
11
|
+
*
|
12
|
+
* @param document Document.
|
13
|
+
* @param url URL.
|
14
|
+
* @returns Response.
|
15
|
+
*/
|
16
|
+
public static async fetch(document: IDocument, url: string): Promise<string> {
|
17
|
+
const response = await document.defaultView.fetch(url);
|
18
|
+
if (!response.ok) {
|
19
|
+
throw new DOMException(
|
20
|
+
`Failed to perform request to "${url}". Status code: ${response.status}`
|
21
|
+
);
|
22
|
+
}
|
23
|
+
return await response.text();
|
24
|
+
}
|
25
|
+
|
26
|
+
/**
|
27
|
+
* Returns resource data synchonously.
|
28
|
+
*
|
29
|
+
* @param document Document.
|
30
|
+
* @param url URL.
|
31
|
+
* @returns Response.
|
32
|
+
*/
|
33
|
+
public static fetchSync(document: IDocument, url: string): string {
|
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 syncRequest = require('sync-request');
|
36
|
+
const absoluteURL = RelativeURL.getAbsoluteURL(document.defaultView.location, url);
|
37
|
+
const response = syncRequest('GET', absoluteURL);
|
38
|
+
|
39
|
+
if (response.isError()) {
|
40
|
+
throw new DOMException(
|
41
|
+
`Failed to perform request to "${absoluteURL}". Status code: ${response.statusCode}`
|
42
|
+
);
|
43
|
+
}
|
44
|
+
|
45
|
+
return response.getBody();
|
46
|
+
}
|
47
|
+
}
|
@@ -0,0 +1,149 @@
|
|
1
|
+
import IResponse from './IResponse';
|
2
|
+
import IBlob from '../file/IBlob';
|
3
|
+
import IDocument from '../nodes/document/IDocument';
|
4
|
+
import * as NodeFetch from 'node-fetch';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Fetch response.
|
8
|
+
*/
|
9
|
+
export default class Response extends NodeFetch.Response implements IResponse {
|
10
|
+
public static _ownerDocument: IDocument = null;
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Returns array buffer.
|
14
|
+
*
|
15
|
+
* @returns Array buffer.
|
16
|
+
*/
|
17
|
+
public arrayBuffer(): Promise<ArrayBuffer> {
|
18
|
+
return new Promise((resolve, reject) => {
|
19
|
+
const taskID = this._handlePromiseStart();
|
20
|
+
super
|
21
|
+
.arrayBuffer()
|
22
|
+
.then(this._handlePromiseEnd.bind(this, resolve, reject, taskID))
|
23
|
+
.catch(this._handlePromiseError.bind(this, reject));
|
24
|
+
});
|
25
|
+
}
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Returns blob.
|
29
|
+
*
|
30
|
+
* @returns Blob.
|
31
|
+
*/
|
32
|
+
public blob(): Promise<IBlob> {
|
33
|
+
return new Promise((resolve, reject) => {
|
34
|
+
const taskID = this._handlePromiseStart();
|
35
|
+
super
|
36
|
+
.blob()
|
37
|
+
.then(this._handlePromiseEnd.bind(this, resolve, reject, taskID))
|
38
|
+
.catch(this._handlePromiseError.bind(this, reject));
|
39
|
+
});
|
40
|
+
}
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Returns buffer.
|
44
|
+
*
|
45
|
+
* @returns Buffer.
|
46
|
+
*/
|
47
|
+
public buffer(): Promise<Buffer> {
|
48
|
+
return new Promise((resolve, reject) => {
|
49
|
+
const taskID = this._handlePromiseStart();
|
50
|
+
super
|
51
|
+
.buffer()
|
52
|
+
.then(this._handlePromiseEnd.bind(this, resolve, reject, taskID))
|
53
|
+
.catch(this._handlePromiseError.bind(this, reject));
|
54
|
+
});
|
55
|
+
}
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Returns json.
|
59
|
+
*
|
60
|
+
* @returns JSON.
|
61
|
+
*/
|
62
|
+
public json(): Promise<unknown> {
|
63
|
+
return new Promise((resolve, reject) => {
|
64
|
+
const taskID = this._handlePromiseStart();
|
65
|
+
super
|
66
|
+
.json()
|
67
|
+
.then(this._handlePromiseEnd.bind(this, resolve, reject, taskID))
|
68
|
+
.catch(this._handlePromiseError.bind(this, reject));
|
69
|
+
});
|
70
|
+
}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* Returns json.
|
74
|
+
*
|
75
|
+
* @returns JSON.
|
76
|
+
*/
|
77
|
+
public text(): Promise<string> {
|
78
|
+
return new Promise((resolve, reject) => {
|
79
|
+
const taskID = this._handlePromiseStart();
|
80
|
+
super
|
81
|
+
.text()
|
82
|
+
.then(this._handlePromiseEnd.bind(this, resolve, reject, taskID))
|
83
|
+
.catch(this._handlePromiseError.bind(this, reject));
|
84
|
+
});
|
85
|
+
}
|
86
|
+
|
87
|
+
/**
|
88
|
+
* Returns json.
|
89
|
+
*
|
90
|
+
* @returns JSON.
|
91
|
+
*/
|
92
|
+
public textConverted(): Promise<string> {
|
93
|
+
return new Promise((resolve, reject) => {
|
94
|
+
const taskID = this._handlePromiseStart();
|
95
|
+
super
|
96
|
+
.textConverted()
|
97
|
+
.then(this._handlePromiseEnd.bind(this, resolve, reject, taskID))
|
98
|
+
.catch(this._handlePromiseError.bind(this, reject));
|
99
|
+
});
|
100
|
+
}
|
101
|
+
|
102
|
+
/**
|
103
|
+
* Handles promise start.
|
104
|
+
*
|
105
|
+
* @returns Task ID.
|
106
|
+
*/
|
107
|
+
private _handlePromiseStart(): number {
|
108
|
+
const taskManager = (<typeof Response>this.constructor)._ownerDocument.defaultView.happyDOM
|
109
|
+
.asyncTaskManager;
|
110
|
+
return taskManager.startTask();
|
111
|
+
}
|
112
|
+
|
113
|
+
/**
|
114
|
+
* Handles promise end.
|
115
|
+
*
|
116
|
+
* @param resolve Resolve.
|
117
|
+
* @param reject Reject.
|
118
|
+
* @param taskID Task ID.
|
119
|
+
* @param response Response.
|
120
|
+
*/
|
121
|
+
private _handlePromiseEnd(
|
122
|
+
resolve: (response: unknown) => void,
|
123
|
+
reject: (error: Error) => void,
|
124
|
+
taskID: number,
|
125
|
+
response: unknown
|
126
|
+
): void {
|
127
|
+
const taskManager = (<typeof Response>this.constructor)._ownerDocument.defaultView.happyDOM
|
128
|
+
.asyncTaskManager;
|
129
|
+
if (taskManager.getTaskCount() === 0) {
|
130
|
+
reject(new Error('Failed to complete fetch request. Task was canceled.'));
|
131
|
+
} else {
|
132
|
+
resolve(response);
|
133
|
+
taskManager.endTask(taskID);
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
/**
|
138
|
+
* Handles promise error.
|
139
|
+
*
|
140
|
+
* @param error
|
141
|
+
* @param reject
|
142
|
+
*/
|
143
|
+
private _handlePromiseError(reject: (error: Error) => void, error: Error): void {
|
144
|
+
const taskManager = (<typeof Response>this.constructor)._ownerDocument.defaultView.happyDOM
|
145
|
+
.asyncTaskManager;
|
146
|
+
reject(error);
|
147
|
+
taskManager.cancelAll(error);
|
148
|
+
}
|
149
|
+
}
|
package/src/file/Blob.ts
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import IBlob from './IBlob';
|
2
|
+
|
1
3
|
/**
|
2
4
|
* Reference:
|
3
5
|
* https://developer.mozilla.org/en-US/docs/Web/API/Blob.
|
@@ -5,7 +7,7 @@
|
|
5
7
|
* Based on:
|
6
8
|
* https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/file-api/Blob-impl.js (MIT licensed).
|
7
9
|
*/
|
8
|
-
export default class Blob {
|
10
|
+
export default class Blob implements IBlob {
|
9
11
|
public readonly _buffer: Buffer = null;
|
10
12
|
public readonly type: string = '';
|
11
13
|
|
@@ -108,6 +110,15 @@ export default class Blob {
|
|
108
110
|
return blob;
|
109
111
|
}
|
110
112
|
|
113
|
+
/**
|
114
|
+
* Returns a Promise that resolves to a text.
|
115
|
+
*
|
116
|
+
* @returns Text.
|
117
|
+
*/
|
118
|
+
public async text(): Promise<string> {
|
119
|
+
return this._buffer.toString();
|
120
|
+
}
|
121
|
+
|
111
122
|
/**
|
112
123
|
* Closes the blob.
|
113
124
|
*
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import Stream from 'stream';
|
2
|
+
import HTTP from 'http';
|
3
|
+
|
4
|
+
interface IHeaders {
|
5
|
+
[key: string]: unknown;
|
6
|
+
}
|
7
|
+
|
8
|
+
interface IAppendOptions {
|
9
|
+
header?: string | IHeaders;
|
10
|
+
knownLength?: number;
|
11
|
+
filename?: string;
|
12
|
+
filepath?: string;
|
13
|
+
contentType?: string;
|
14
|
+
}
|
15
|
+
|
16
|
+
interface ISubmitOptions extends HTTP.RequestOptions {
|
17
|
+
protocol?: 'https:' | 'http:';
|
18
|
+
}
|
19
|
+
|
20
|
+
export default interface IFormData extends Stream.Readable {
|
21
|
+
append(key: string, value: unknown, options?: IAppendOptions | string): void;
|
22
|
+
getHeaders(userHeaders?: IHeaders): { [key: string]: IHeaders };
|
23
|
+
submit(
|
24
|
+
params: string | ISubmitOptions,
|
25
|
+
callback?: (error: Error | null, response: HTTP.IncomingMessage) => void
|
26
|
+
): HTTP.ClientRequest;
|
27
|
+
getBuffer(): Buffer;
|
28
|
+
setBoundary(boundary: string): void;
|
29
|
+
getBoundary(): string;
|
30
|
+
getLength(callback: (err: Error | null, length: number) => void): void;
|
31
|
+
getLengthSync(): number;
|
32
|
+
hasKnownLength(): boolean;
|
33
|
+
}
|
package/src/index.ts
CHANGED
@@ -14,9 +14,7 @@ import DOMException from './exception/DOMException';
|
|
14
14
|
import History from './history/History';
|
15
15
|
import CSSStyleDeclaration from './css/CSSStyleDeclaration';
|
16
16
|
import Screen from './screen/Screen';
|
17
|
-
import AsyncTaskManager from './
|
18
|
-
import IResponse from './window/IResponse';
|
19
|
-
import IFetchOptions from './window/IFetchOptions';
|
17
|
+
import AsyncTaskManager from './async-task-manager/AsyncTaskManager';
|
20
18
|
import NodeFilter from './tree-walker/NodeFilter';
|
21
19
|
import Event from './event/Event';
|
22
20
|
import EventTarget from './event/EventTarget';
|
@@ -101,7 +99,7 @@ import XMLParser from './xml-parser/XMLParser';
|
|
101
99
|
import XMLSerializer from './xml-serializer/XMLSerializer';
|
102
100
|
import CSSStyleSheet from './css/CSSStyleSheet';
|
103
101
|
import Storage from './storage/Storage';
|
104
|
-
import URLSearchParams from '
|
102
|
+
import { URLSearchParams } from 'url';
|
105
103
|
import Selection from './selection/Selection';
|
106
104
|
|
107
105
|
export {
|
@@ -123,8 +121,6 @@ export {
|
|
123
121
|
CSSStyleDeclaration,
|
124
122
|
Screen,
|
125
123
|
AsyncTaskManager,
|
126
|
-
IResponse,
|
127
|
-
IFetchOptions,
|
128
124
|
NodeFilter,
|
129
125
|
Event,
|
130
126
|
EventTarget,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import Attr from '../../attribute/Attr';
|
2
2
|
import CSSStyleSheet from '../../css/CSSStyleSheet';
|
3
|
-
import
|
3
|
+
import ResourceFetchHandler from '../../fetch/ResourceFetchHandler';
|
4
4
|
import HTMLElement from '../html-element/HTMLElement';
|
5
5
|
import Document from '../document/Document';
|
6
6
|
import IHTMLLinkElement from './IHTMLLinkElement';
|
@@ -199,7 +199,7 @@ export default class HTMLLinkElement extends HTMLElement implements IHTMLLinkEle
|
|
199
199
|
this.isConnected
|
200
200
|
) {
|
201
201
|
(<Document>this.ownerDocument)._readyStateManager.startTask();
|
202
|
-
|
202
|
+
ResourceFetchHandler.fetch(this.ownerDocument, href)
|
203
203
|
.then((code) => {
|
204
204
|
const styleSheet = new CSSStyleSheet();
|
205
205
|
styleSheet.replaceSync(code);
|
@@ -245,7 +245,7 @@ export default class HTMLLinkElement extends HTMLElement implements IHTMLLinkEle
|
|
245
245
|
|
246
246
|
if (href !== null && rel && rel.toLowerCase() === 'stylesheet') {
|
247
247
|
(<Document>this.ownerDocument)._readyStateManager.startTask();
|
248
|
-
|
248
|
+
ResourceFetchHandler.fetch(this.ownerDocument, href)
|
249
249
|
.then((code) => {
|
250
250
|
const styleSheet = new CSSStyleSheet();
|
251
251
|
styleSheet.replaceSync(code);
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { Document } from '../..';
|
2
2
|
import Event from '../../event/Event';
|
3
3
|
import ErrorEvent from '../../event/events/ErrorEvent';
|
4
|
-
import
|
4
|
+
import ResourceFetchHandler from '../../fetch/ResourceFetchHandler';
|
5
5
|
import HTMLScriptElement from './HTMLScriptElement';
|
6
6
|
|
7
7
|
/**
|
@@ -22,10 +22,7 @@ export default class ScriptUtility {
|
|
22
22
|
let code = null;
|
23
23
|
(<Document>element.ownerDocument)._readyStateManager.startTask();
|
24
24
|
try {
|
25
|
-
code = await
|
26
|
-
window: element.ownerDocument.defaultView,
|
27
|
-
url: src
|
28
|
-
});
|
25
|
+
code = await ResourceFetchHandler.fetch(element.ownerDocument, src);
|
29
26
|
} catch (error) {
|
30
27
|
element.dispatchEvent(
|
31
28
|
new ErrorEvent('error', {
|
@@ -54,10 +51,7 @@ export default class ScriptUtility {
|
|
54
51
|
} else {
|
55
52
|
let code = null;
|
56
53
|
try {
|
57
|
-
code =
|
58
|
-
window: element.ownerDocument.defaultView,
|
59
|
-
url: src
|
60
|
-
});
|
54
|
+
code = ResourceFetchHandler.fetchSync(element.ownerDocument, src);
|
61
55
|
} catch (error) {
|
62
56
|
element.dispatchEvent(
|
63
57
|
new ErrorEvent('error', {
|
package/src/window/IWindow.ts
CHANGED
@@ -60,13 +60,15 @@ import UIEvent from '../event/UIEvent';
|
|
60
60
|
import ErrorEvent from '../event/events/ErrorEvent';
|
61
61
|
import StorageEvent from '../event/events/StorageEvent';
|
62
62
|
import Screen from '../screen/Screen';
|
63
|
-
import AsyncTaskManager from '
|
64
|
-
import IResponse from '
|
63
|
+
import AsyncTaskManager from '../async-task-manager/AsyncTaskManager';
|
64
|
+
import IResponse from '../fetch/IResponse';
|
65
|
+
import IResponseInit from '../fetch/IResponseInit';
|
66
|
+
import IRequest from '../fetch/IRequest';
|
67
|
+
import IRequestInit from '../fetch/IRequestInit';
|
68
|
+
import IHeaders from '../fetch/IHeaders';
|
65
69
|
import Storage from '../storage/Storage';
|
66
|
-
import IFetchOptions from './IFetchOptions';
|
67
70
|
import NodeFilter from '../tree-walker/NodeFilter';
|
68
71
|
import Window from './Window';
|
69
|
-
import URLSearchParams from '../url-search-params/URLSearchParams';
|
70
72
|
import HTMLCollection from '../nodes/element/HTMLCollection';
|
71
73
|
import NodeList from '../nodes/node/NodeList';
|
72
74
|
import Selection from '../selection/Selection';
|
@@ -76,6 +78,7 @@ import MimeType from '../navigator/MimeType';
|
|
76
78
|
import MimeTypeArray from '../navigator/MimeTypeArray';
|
77
79
|
import Plugin from '../navigator/Plugin';
|
78
80
|
import PluginArray from '../navigator/PluginArray';
|
81
|
+
import { URLSearchParams } from 'url';
|
79
82
|
|
80
83
|
/**
|
81
84
|
* Window.
|
@@ -141,7 +144,9 @@ export default interface IWindow extends IEventTarget {
|
|
141
144
|
readonly Location: typeof Location;
|
142
145
|
readonly CustomElementRegistry: typeof CustomElementRegistry;
|
143
146
|
readonly Window: typeof Window;
|
144
|
-
readonly Headers:
|
147
|
+
readonly Headers: { new (init?: string[][] | Record<string, string> | IHeaders): IHeaders };
|
148
|
+
readonly Request: { new (input: string | IRequest, init?: IRequestInit): IRequest };
|
149
|
+
readonly Response: { new (body?: unknown | null, init?: IResponseInit): IResponse };
|
145
150
|
readonly XMLSerializer: typeof XMLSerializer;
|
146
151
|
readonly ResizeObserver: typeof ResizeObserver;
|
147
152
|
readonly CSSStyleSheet: typeof CSSStyleSheet;
|
@@ -221,7 +226,6 @@ export default interface IWindow extends IEventTarget {
|
|
221
226
|
/**
|
222
227
|
* Sets a timer which executes a function once the timer expires.
|
223
228
|
*
|
224
|
-
* @override
|
225
229
|
* @param callback Function to be executed.
|
226
230
|
* @param [delay=0] Delay in ms.
|
227
231
|
* @returns Timeout ID.
|
@@ -231,7 +235,6 @@ export default interface IWindow extends IEventTarget {
|
|
231
235
|
/**
|
232
236
|
* Cancels a timeout previously established by calling setTimeout().
|
233
237
|
*
|
234
|
-
* @override
|
235
238
|
* @param id ID of the timeout.
|
236
239
|
*/
|
237
240
|
clearTimeout(id: NodeJS.Timeout): void;
|
@@ -239,7 +242,6 @@ export default interface IWindow extends IEventTarget {
|
|
239
242
|
/**
|
240
243
|
* Calls a function with a fixed time delay between each call.
|
241
244
|
*
|
242
|
-
* @override
|
243
245
|
* @param callback Function to be executed.
|
244
246
|
* @param [delay=0] Delay in ms.
|
245
247
|
* @returns Interval ID.
|
@@ -249,7 +251,6 @@ export default interface IWindow extends IEventTarget {
|
|
249
251
|
/**
|
250
252
|
* Cancels a timed repeating action which was previously established by a call to setInterval().
|
251
253
|
*
|
252
|
-
* @override
|
253
254
|
* @param id ID of the interval.
|
254
255
|
*/
|
255
256
|
clearInterval(id: NodeJS.Timeout): void;
|
@@ -257,7 +258,6 @@ export default interface IWindow extends IEventTarget {
|
|
257
258
|
/**
|
258
259
|
* Mock animation frames with timeouts.
|
259
260
|
*
|
260
|
-
* @override
|
261
261
|
* @param {Function} callback Callback.
|
262
262
|
* @returns {NodeJS.Timeout} Timeout ID.
|
263
263
|
*/
|
@@ -266,18 +266,16 @@ export default interface IWindow extends IEventTarget {
|
|
266
266
|
/**
|
267
267
|
* Mock animation frames with timeouts.
|
268
268
|
*
|
269
|
-
* @override
|
270
269
|
* @param {NodeJS.Timeout} id Timeout ID.
|
271
270
|
*/
|
272
271
|
cancelAnimationFrame(id: NodeJS.Timeout): void;
|
273
272
|
|
274
273
|
/**
|
275
|
-
*
|
274
|
+
* This method provides an easy, logical way to fetch resources asynchronously across the network.
|
276
275
|
*
|
277
|
-
* @
|
278
|
-
* @param
|
279
|
-
* @param [options] Options.
|
276
|
+
* @param url URL.
|
277
|
+
* @param [init] Init.
|
280
278
|
* @returns Promise.
|
281
279
|
*/
|
282
|
-
fetch(url: string,
|
280
|
+
fetch(url: string, init?: IRequestInit): Promise<IResponse>;
|
283
281
|
}
|
package/src/window/Window.ts
CHANGED
@@ -63,14 +63,15 @@ import UIEvent from '../event/UIEvent';
|
|
63
63
|
import ErrorEvent from '../event/events/ErrorEvent';
|
64
64
|
import StorageEvent from '../event/events/StorageEvent';
|
65
65
|
import Screen from '../screen/Screen';
|
66
|
-
import AsyncTaskManager from '
|
67
|
-
import IResponse from '
|
68
|
-
import
|
69
|
-
import
|
66
|
+
import AsyncTaskManager from '../async-task-manager/AsyncTaskManager';
|
67
|
+
import IResponse from '../fetch/IResponse';
|
68
|
+
import IResponseInit from '../fetch/IResponseInit';
|
69
|
+
import IRequest from '../fetch/IRequest';
|
70
|
+
import IRequestInit from '../fetch/IRequestInit';
|
71
|
+
import IHeaders from '../fetch/IHeaders';
|
72
|
+
import IHeadersInit from '../fetch/IHeadersInit';
|
70
73
|
import Storage from '../storage/Storage';
|
71
|
-
import IFetchOptions from './IFetchOptions';
|
72
74
|
import IWindow from './IWindow';
|
73
|
-
import URLSearchParams from '../url-search-params/URLSearchParams';
|
74
75
|
import HTMLCollection from '../nodes/element/HTMLCollection';
|
75
76
|
import NodeList from '../nodes/node/NodeList';
|
76
77
|
import MediaQueryList from '../match-media/MediaQueryList';
|
@@ -81,8 +82,8 @@ import MimeType from '../navigator/MimeType';
|
|
81
82
|
import MimeTypeArray from '../navigator/MimeTypeArray';
|
82
83
|
import Plugin from '../navigator/Plugin';
|
83
84
|
import PluginArray from '../navigator/PluginArray';
|
84
|
-
|
85
|
-
|
85
|
+
import FetchHandler from '../fetch/FetchHandler';
|
86
|
+
import { URLSearchParams } from 'url';
|
86
87
|
|
87
88
|
/**
|
88
89
|
* Handles the Window.
|
@@ -94,7 +95,7 @@ export default class Window extends EventTarget implements IWindow, NodeJS.Globa
|
|
94
95
|
return await this.happyDOM.asyncTaskManager.whenComplete();
|
95
96
|
},
|
96
97
|
cancelAsync: (): void => {
|
97
|
-
this.happyDOM.asyncTaskManager.
|
98
|
+
this.happyDOM.asyncTaskManager.cancelAll();
|
98
99
|
},
|
99
100
|
asyncTaskManager: new AsyncTaskManager()
|
100
101
|
};
|
@@ -152,7 +153,6 @@ export default class Window extends EventTarget implements IWindow, NodeJS.Globa
|
|
152
153
|
public readonly Location = Location;
|
153
154
|
public readonly CustomElementRegistry = CustomElementRegistry;
|
154
155
|
public readonly Window = Window;
|
155
|
-
public readonly Headers = Map;
|
156
156
|
public readonly XMLSerializer = XMLSerializer;
|
157
157
|
public readonly ResizeObserver = ResizeObserver;
|
158
158
|
public readonly CSSStyleSheet = CSSStyleSheet;
|
@@ -200,7 +200,6 @@ export default class Window extends EventTarget implements IWindow, NodeJS.Globa
|
|
200
200
|
public readonly performance = PerfHooks.performance;
|
201
201
|
|
202
202
|
// Node.js Globals
|
203
|
-
public Array = global ? global.Array : null;
|
204
203
|
public ArrayBuffer = global ? global.ArrayBuffer : null;
|
205
204
|
public Boolean = global ? global.Boolean : null;
|
206
205
|
public Buffer = null;
|
@@ -262,6 +261,7 @@ export default class Window extends EventTarget implements IWindow, NodeJS.Globa
|
|
262
261
|
|
263
262
|
// Private properties
|
264
263
|
private _objectClass: typeof globalThis.Object = null;
|
264
|
+
private _arrayClass: typeof globalThis.Array = null;
|
265
265
|
private _functionClass: typeof globalThis.Function = null;
|
266
266
|
|
267
267
|
/**
|
@@ -315,6 +315,21 @@ export default class Window extends EventTarget implements IWindow, NodeJS.Globa
|
|
315
315
|
return this._objectClass;
|
316
316
|
}
|
317
317
|
|
318
|
+
/**
|
319
|
+
* Returns Array class.
|
320
|
+
*
|
321
|
+
* @returns Array class.
|
322
|
+
*/
|
323
|
+
public get Array(): typeof globalThis.Array {
|
324
|
+
if (this._arrayClass) {
|
325
|
+
return this._arrayClass;
|
326
|
+
}
|
327
|
+
// When inside a VM global.Object is not the same as [].constructor
|
328
|
+
// We will therefore run the code inside the VM to get the real constructor
|
329
|
+
this._arrayClass = <typeof globalThis.Array>this.eval('[].constructor');
|
330
|
+
return this._arrayClass;
|
331
|
+
}
|
332
|
+
|
318
333
|
/**
|
319
334
|
* Returns Function class.
|
320
335
|
*
|
@@ -339,6 +354,43 @@ export default class Window extends EventTarget implements IWindow, NodeJS.Globa
|
|
339
354
|
return new CSS();
|
340
355
|
}
|
341
356
|
|
357
|
+
/**
|
358
|
+
* Returns Headers class.
|
359
|
+
*
|
360
|
+
* @returns Headers.
|
361
|
+
*/
|
362
|
+
public get Headers(): {
|
363
|
+
new (init?: IHeadersInit): IHeaders;
|
364
|
+
} {
|
365
|
+
return require('../fetch/Headers').default;
|
366
|
+
}
|
367
|
+
|
368
|
+
/**
|
369
|
+
* Returns Request class.
|
370
|
+
*
|
371
|
+
* @returns Request.
|
372
|
+
*/
|
373
|
+
public get Request(): {
|
374
|
+
new (input: string | { href: string } | IRequest, init?: IRequestInit): IRequest;
|
375
|
+
} {
|
376
|
+
const Request = require('../fetch/Request').default;
|
377
|
+
Request._ownerDocument = Request._ownerDocument || this.document;
|
378
|
+
return Request;
|
379
|
+
}
|
380
|
+
|
381
|
+
/**
|
382
|
+
* Returns Response class.
|
383
|
+
*
|
384
|
+
* @returns Response.
|
385
|
+
*/
|
386
|
+
public get Response(): {
|
387
|
+
new (body?: NodeJS.ReadableStream | null, init?: IResponseInit): IResponse;
|
388
|
+
} {
|
389
|
+
const Response = require('../fetch/Response').default;
|
390
|
+
Response._ownerDocument = Response._ownerDocument || this.document;
|
391
|
+
return Response;
|
392
|
+
}
|
393
|
+
|
342
394
|
/**
|
343
395
|
* Evaluates code.
|
344
396
|
*
|
@@ -509,65 +561,14 @@ export default class Window extends EventTarget implements IWindow, NodeJS.Globa
|
|
509
561
|
}
|
510
562
|
|
511
563
|
/**
|
512
|
-
*
|
564
|
+
* This method provides an easy, logical way to fetch resources asynchronously across the network.
|
513
565
|
*
|
514
566
|
* @override
|
515
|
-
* @param url URL
|
516
|
-
* @param [
|
567
|
+
* @param url URL.
|
568
|
+
* @param [init] Init.
|
517
569
|
* @returns Promise.
|
518
570
|
*/
|
519
|
-
public async fetch(url: string,
|
520
|
-
return
|
521
|
-
let fetch = null;
|
522
|
-
|
523
|
-
try {
|
524
|
-
fetch = require('node-fetch');
|
525
|
-
} catch (error) {
|
526
|
-
throw new Error('Failed to perform fetch. "node-fetch" could not be loaded.');
|
527
|
-
}
|
528
|
-
|
529
|
-
this.happyDOM.asyncTaskManager.startTask(AsyncTaskTypeEnum.fetch);
|
530
|
-
|
531
|
-
fetch(RelativeURL.getAbsoluteURL(this.location, url), options)
|
532
|
-
.then((response) => {
|
533
|
-
if (this.happyDOM.asyncTaskManager.getRunningCount(AsyncTaskTypeEnum.fetch) === 0) {
|
534
|
-
reject(new Error('Failed to complete fetch request. Task was canceled.'));
|
535
|
-
} else {
|
536
|
-
for (const methodName of FETCH_RESPONSE_TYPE_METHODS) {
|
537
|
-
const asyncMethod = response[methodName];
|
538
|
-
response[methodName] = () => {
|
539
|
-
return new Promise((resolve, reject) => {
|
540
|
-
this.happyDOM.asyncTaskManager.startTask(AsyncTaskTypeEnum.fetch);
|
541
|
-
|
542
|
-
asyncMethod
|
543
|
-
.call(response)
|
544
|
-
.then((response) => {
|
545
|
-
if (
|
546
|
-
this.happyDOM.asyncTaskManager.getRunningCount(AsyncTaskTypeEnum.fetch) ===
|
547
|
-
0
|
548
|
-
) {
|
549
|
-
reject(new Error('Failed to complete fetch request. Task was canceled.'));
|
550
|
-
} else {
|
551
|
-
resolve(response);
|
552
|
-
this.happyDOM.asyncTaskManager.endTask(AsyncTaskTypeEnum.fetch);
|
553
|
-
}
|
554
|
-
})
|
555
|
-
.catch((error) => {
|
556
|
-
reject(error);
|
557
|
-
this.happyDOM.asyncTaskManager.endTask(AsyncTaskTypeEnum.fetch, error);
|
558
|
-
});
|
559
|
-
});
|
560
|
-
};
|
561
|
-
}
|
562
|
-
|
563
|
-
resolve(response);
|
564
|
-
this.happyDOM.asyncTaskManager.endTask(AsyncTaskTypeEnum.fetch);
|
565
|
-
}
|
566
|
-
})
|
567
|
-
.catch((error) => {
|
568
|
-
reject(error);
|
569
|
-
this.happyDOM.asyncTaskManager.endTask(AsyncTaskTypeEnum.fetch, error);
|
570
|
-
});
|
571
|
-
});
|
571
|
+
public async fetch(url: string, init?: IRequestInit): Promise<IResponse> {
|
572
|
+
return await FetchHandler.fetch(this.document, url, init);
|
572
573
|
}
|
573
574
|
}
|
@@ -1,30 +0,0 @@
|
|
1
|
-
import Window from '../window/Window';
|
2
|
-
/**
|
3
|
-
* Helper class for performing an asynchonous or synchrounous request to a resource.
|
4
|
-
*/
|
5
|
-
export default class ResourceFetcher {
|
6
|
-
/**
|
7
|
-
* Returns resource data asynchonously.
|
8
|
-
*
|
9
|
-
* @param options Options.
|
10
|
-
* @param options.window Location.
|
11
|
-
* @param options.url URL.
|
12
|
-
* @returns Response.
|
13
|
-
*/
|
14
|
-
static fetch(options: {
|
15
|
-
window: Window;
|
16
|
-
url: string;
|
17
|
-
}): Promise<string>;
|
18
|
-
/**
|
19
|
-
* Returns resource data synchonously.
|
20
|
-
*
|
21
|
-
* @param options Options.
|
22
|
-
* @param options.window Location.
|
23
|
-
* @param options.url URL.
|
24
|
-
* @returns Response.
|
25
|
-
*/
|
26
|
-
static fetchSync(options: {
|
27
|
-
window: Window;
|
28
|
-
url: string;
|
29
|
-
}): string;
|
30
|
-
}
|