happy-dom 7.7.1 → 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.
- package/README.md +62 -27
- package/lib/async-task-manager/AsyncTaskManager.d.ts +3 -8
- package/lib/async-task-manager/AsyncTaskManager.js +21 -24
- package/lib/async-task-manager/AsyncTaskManager.js.map +1 -1
- package/lib/cookie/Cookie.d.ts +53 -0
- package/lib/cookie/Cookie.js +146 -0
- package/lib/cookie/Cookie.js.map +1 -0
- package/lib/cookie/CookieJar.d.ts +30 -0
- package/lib/cookie/CookieJar.js +84 -0
- package/lib/cookie/CookieJar.js.map +1 -0
- package/lib/event/IEventListener.d.ts +1 -1
- package/lib/exception/DOMExceptionNameEnum.d.ts +4 -1
- package/lib/exception/DOMExceptionNameEnum.js +3 -0
- package/lib/exception/DOMExceptionNameEnum.js.map +1 -1
- package/lib/fetch/FetchHandler.d.ts +3 -2
- package/lib/fetch/FetchHandler.js +31 -3
- package/lib/fetch/FetchHandler.js.map +1 -1
- package/lib/fetch/RequestInfo.d.ts +5 -0
- package/lib/fetch/RequestInfo.js +3 -0
- package/lib/fetch/RequestInfo.js.map +1 -0
- package/lib/fetch/ResourceFetchHandler.d.ts +2 -2
- package/lib/fetch/ResourceFetchHandler.js +9 -8
- package/lib/fetch/ResourceFetchHandler.js.map +1 -1
- package/lib/index.d.ts +1 -2
- package/lib/index.js +3 -4
- package/lib/index.js.map +1 -1
- package/lib/location/Location.d.ts +2 -1
- package/lib/location/Location.js +4 -7
- package/lib/location/Location.js.map +1 -1
- package/lib/location/RelativeURL.d.ts +3 -1
- package/lib/location/RelativeURL.js +2 -11
- package/lib/location/RelativeURL.js.map +1 -1
- package/lib/nodes/document/Document.d.ts +14 -3
- package/lib/nodes/document/Document.js +21 -6
- package/lib/nodes/document/Document.js.map +1 -1
- package/lib/nodes/document/IDocument.d.ts +2 -0
- package/lib/nodes/html-link-element/HTMLLinkElement.js +5 -2
- package/lib/nodes/html-link-element/HTMLLinkElement.js.map +1 -1
- package/lib/nodes/html-script-element/HTMLScriptElement.js +1 -1
- package/lib/nodes/html-script-element/HTMLScriptElement.js.map +1 -1
- package/lib/nodes/html-script-element/ScriptUtility.js +4 -0
- package/lib/nodes/html-script-element/ScriptUtility.js.map +1 -1
- package/lib/window/IHappyDOMSettings.d.ts +9 -0
- package/lib/window/IHappyDOMSettings.js +3 -0
- package/lib/window/IHappyDOMSettings.js.map +1 -0
- package/lib/window/IWindow.d.ts +15 -6
- package/lib/window/Window.d.ts +18 -3
- package/lib/window/Window.js +26 -4
- package/lib/window/Window.js.map +1 -1
- package/lib/xml-http-request/XMLHttpRequest.d.ts +196 -0
- package/lib/xml-http-request/XMLHttpRequest.js +777 -0
- package/lib/xml-http-request/XMLHttpRequest.js.map +1 -0
- package/lib/xml-http-request/XMLHttpRequestCertificate.d.ts +5 -0
- package/lib/xml-http-request/XMLHttpRequestCertificate.js +55 -0
- package/lib/xml-http-request/XMLHttpRequestCertificate.js.map +1 -0
- package/lib/xml-http-request/XMLHttpRequestEventTarget.d.ts +15 -0
- package/lib/xml-http-request/XMLHttpRequestEventTarget.js +23 -0
- package/lib/xml-http-request/XMLHttpRequestEventTarget.js.map +1 -0
- package/lib/xml-http-request/XMLHttpRequestReadyStateEnum.d.ts +8 -0
- package/lib/xml-http-request/XMLHttpRequestReadyStateEnum.js +12 -0
- package/lib/xml-http-request/XMLHttpRequestReadyStateEnum.js.map +1 -0
- package/lib/xml-http-request/XMLHttpRequestUpload.d.ts +6 -0
- package/lib/xml-http-request/XMLHttpRequestUpload.js +13 -0
- package/lib/xml-http-request/XMLHttpRequestUpload.js.map +1 -0
- package/lib/xml-http-request/XMLHttpResponseTypeEnum.d.ts +8 -0
- package/lib/xml-http-request/XMLHttpResponseTypeEnum.js +12 -0
- package/lib/xml-http-request/XMLHttpResponseTypeEnum.js.map +1 -0
- package/lib/xml-http-request/utilities/XMLHttpRequestSyncRequestScriptBuilder.d.ts +15 -0
- package/lib/xml-http-request/utilities/XMLHttpRequestSyncRequestScriptBuilder.js +55 -0
- package/lib/xml-http-request/utilities/XMLHttpRequestSyncRequestScriptBuilder.js.map +1 -0
- package/lib/xml-http-request/utilities/XMLHttpRequestURLUtility.d.ts +35 -0
- package/lib/xml-http-request/utilities/XMLHttpRequestURLUtility.js +62 -0
- package/lib/xml-http-request/utilities/XMLHttpRequestURLUtility.js.map +1 -0
- package/package.json +2 -2
- package/src/async-task-manager/AsyncTaskManager.ts +24 -26
- package/src/cookie/Cookie.ts +158 -0
- package/src/cookie/CookieJar.ts +82 -0
- package/src/event/IEventListener.ts +1 -1
- package/src/exception/DOMExceptionNameEnum.ts +4 -1
- package/src/fetch/FetchHandler.ts +40 -4
- package/src/fetch/RequestInfo.ts +6 -0
- package/src/fetch/ResourceFetchHandler.ts +10 -8
- package/src/index.ts +1 -2
- package/src/location/Location.ts +3 -3
- package/src/location/RelativeURL.ts +3 -14
- package/src/nodes/document/Document.ts +24 -6
- package/src/nodes/document/IDocument.ts +2 -0
- package/src/nodes/html-link-element/HTMLLinkElement.ts +7 -2
- package/src/nodes/html-script-element/HTMLScriptElement.ts +1 -1
- package/src/nodes/html-script-element/ScriptUtility.ts +8 -0
- package/src/window/IHappyDOMSettings.ts +9 -0
- package/src/window/IWindow.ts +15 -6
- package/src/window/Window.ts +36 -5
- package/src/xml-http-request/XMLHttpRequest.ts +998 -0
- package/src/xml-http-request/XMLHttpRequestCertificate.ts +52 -0
- package/src/xml-http-request/XMLHttpRequestEventTarget.ts +17 -0
- package/src/xml-http-request/XMLHttpRequestReadyStateEnum.ts +9 -0
- package/src/xml-http-request/XMLHttpRequestUpload.ts +6 -0
- package/src/xml-http-request/XMLHttpResponseTypeEnum.ts +9 -0
- package/src/xml-http-request/utilities/XMLHttpRequestSyncRequestScriptBuilder.ts +53 -0
- package/src/xml-http-request/utilities/XMLHttpRequestURLUtility.ts +64 -0
- package/lib/cookie/CookieUtility.d.ts +0 -15
- package/lib/cookie/CookieUtility.js +0 -83
- package/lib/cookie/CookieUtility.js.map +0 -1
- package/lib/location/URL.d.ts +0 -53
- package/lib/location/URL.js +0 -96
- package/lib/location/URL.js.map +0 -1
- package/src/cookie/CookieUtility.ts +0 -87
- package/src/location/URL.ts +0 -102
@@ -0,0 +1,158 @@
|
|
1
|
+
const CookiePairRegex = /([^=]+)(?:=([\s\S]*))?/;
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Cookie.
|
5
|
+
*/
|
6
|
+
export default class Cookie {
|
7
|
+
private pairs: { [key: string]: string } = {};
|
8
|
+
//
|
9
|
+
public key = '';
|
10
|
+
public value = '';
|
11
|
+
public size = 0;
|
12
|
+
// Optional
|
13
|
+
public domain = '';
|
14
|
+
public path = '';
|
15
|
+
public expriesOrMaxAge: Date = null;
|
16
|
+
public httpOnly = false;
|
17
|
+
public secure = false;
|
18
|
+
public sameSite = '';
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Constructor.
|
22
|
+
*
|
23
|
+
* @param cookie Cookie.
|
24
|
+
*/
|
25
|
+
constructor(cookie: string) {
|
26
|
+
let match: RegExpExecArray | null;
|
27
|
+
|
28
|
+
const parts = cookie.split(';').filter(Boolean);
|
29
|
+
|
30
|
+
// Part[0] is the key-value pair.
|
31
|
+
match = new RegExp(CookiePairRegex).exec(parts[0]);
|
32
|
+
if (!match) {
|
33
|
+
throw new Error(`Invalid cookie: ${cookie}`);
|
34
|
+
}
|
35
|
+
this.key = match[1].trim();
|
36
|
+
this.value = match[2];
|
37
|
+
// Set key is empty if match[2] is undefined.
|
38
|
+
if (!match[2]) {
|
39
|
+
this.value = this.key;
|
40
|
+
this.key = '';
|
41
|
+
}
|
42
|
+
this.pairs[this.key] = this.value;
|
43
|
+
this.size = this.key.length + this.value.length;
|
44
|
+
// Attribute.
|
45
|
+
for (const part of parts.slice(1)) {
|
46
|
+
match = new RegExp(CookiePairRegex).exec(part);
|
47
|
+
if (!match) {
|
48
|
+
throw new Error(`Invalid cookie: ${part}`);
|
49
|
+
}
|
50
|
+
const key = match[1].trim();
|
51
|
+
const value = match[2];
|
52
|
+
|
53
|
+
switch (key.toLowerCase()) {
|
54
|
+
case 'expires':
|
55
|
+
this.expriesOrMaxAge = new Date(value);
|
56
|
+
break;
|
57
|
+
case 'max-age':
|
58
|
+
this.expriesOrMaxAge = new Date(parseInt(value, 10) * 1000 + Date.now());
|
59
|
+
break;
|
60
|
+
case 'domain':
|
61
|
+
this.domain = value;
|
62
|
+
break;
|
63
|
+
case 'path':
|
64
|
+
this.path = value.startsWith('/') ? value : `/${value}`;
|
65
|
+
break;
|
66
|
+
case 'httponly':
|
67
|
+
this.httpOnly = true;
|
68
|
+
break;
|
69
|
+
case 'secure':
|
70
|
+
this.secure = true;
|
71
|
+
break;
|
72
|
+
case 'samesite':
|
73
|
+
this.sameSite = value;
|
74
|
+
break;
|
75
|
+
default:
|
76
|
+
continue; // Skip.
|
77
|
+
}
|
78
|
+
// Skip unknown key-value pair.
|
79
|
+
if (
|
80
|
+
['expires', 'max-age', 'domain', 'path', 'httponly', 'secure', 'samesite'].indexOf(
|
81
|
+
key.toLowerCase()
|
82
|
+
) === -1
|
83
|
+
) {
|
84
|
+
continue;
|
85
|
+
}
|
86
|
+
this.pairs[key] = value;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
/**
|
91
|
+
* Returns a raw string of the cookie.
|
92
|
+
*/
|
93
|
+
public rawString(): string {
|
94
|
+
return Object.keys(this.pairs)
|
95
|
+
.map((key) => {
|
96
|
+
if (key) {
|
97
|
+
return `${key}=${this.pairs[key]}`;
|
98
|
+
}
|
99
|
+
return this.pairs[key];
|
100
|
+
})
|
101
|
+
.join('; ');
|
102
|
+
}
|
103
|
+
|
104
|
+
/**
|
105
|
+
*
|
106
|
+
*/
|
107
|
+
public cookieString(): string {
|
108
|
+
if (this.key) {
|
109
|
+
return `${this.key}=${this.value}`;
|
110
|
+
}
|
111
|
+
return this.value;
|
112
|
+
}
|
113
|
+
|
114
|
+
/**
|
115
|
+
*
|
116
|
+
*/
|
117
|
+
public isExpired(): boolean {
|
118
|
+
// If the expries/maxage is set, then determine whether it is expired.
|
119
|
+
if (this.expriesOrMaxAge && this.expriesOrMaxAge.getTime() < Date.now()) {
|
120
|
+
return true;
|
121
|
+
}
|
122
|
+
// If the expries/maxage is not set, it's a session-level cookie that will expire when the browser is closed.
|
123
|
+
// (it's never expired in happy-dom)
|
124
|
+
return false;
|
125
|
+
}
|
126
|
+
|
127
|
+
/**
|
128
|
+
*
|
129
|
+
*/
|
130
|
+
public isHttpOnly(): boolean {
|
131
|
+
return this.httpOnly;
|
132
|
+
}
|
133
|
+
|
134
|
+
/**
|
135
|
+
*
|
136
|
+
*/
|
137
|
+
public isSecure(): boolean {
|
138
|
+
return this.secure;
|
139
|
+
}
|
140
|
+
|
141
|
+
/**
|
142
|
+
* Parse a cookie string.
|
143
|
+
*
|
144
|
+
* @param cookieString
|
145
|
+
*/
|
146
|
+
public static parse(cookieString: string): Cookie {
|
147
|
+
return new Cookie(cookieString);
|
148
|
+
}
|
149
|
+
|
150
|
+
/**
|
151
|
+
* Stringify a Cookie object.
|
152
|
+
*
|
153
|
+
* @param cookie
|
154
|
+
*/
|
155
|
+
public static stringify(cookie: Cookie): string {
|
156
|
+
return cookie.toString();
|
157
|
+
}
|
158
|
+
}
|
@@ -0,0 +1,82 @@
|
|
1
|
+
import Location from 'src/location/Location';
|
2
|
+
import Cookie from './Cookie';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* CookieJar.
|
6
|
+
*
|
7
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cookie.
|
8
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie.
|
9
|
+
*/
|
10
|
+
export default class CookieJar {
|
11
|
+
private cookies: Cookie[] = [];
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Validate cookie.
|
15
|
+
*
|
16
|
+
* @param cookie
|
17
|
+
*/
|
18
|
+
private validateCookie(cookie: Cookie): boolean {
|
19
|
+
if (cookie.key.toLowerCase().startsWith('__secure-') && !cookie.isSecure()) {
|
20
|
+
return false;
|
21
|
+
}
|
22
|
+
if (
|
23
|
+
cookie.key.toLowerCase().startsWith('__host-') &&
|
24
|
+
(!cookie.isSecure() || cookie.path !== '/' || cookie.domain)
|
25
|
+
) {
|
26
|
+
return false;
|
27
|
+
}
|
28
|
+
return true;
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Set cookie.
|
33
|
+
*
|
34
|
+
* @param cookieString
|
35
|
+
*/
|
36
|
+
public setCookiesString(cookieString: string): void {
|
37
|
+
if (!cookieString) {
|
38
|
+
return;
|
39
|
+
}
|
40
|
+
const newCookie = new Cookie(cookieString);
|
41
|
+
if (!this.validateCookie(newCookie)) {
|
42
|
+
return;
|
43
|
+
}
|
44
|
+
this.cookies
|
45
|
+
.filter((cookie) => cookie.key === newCookie.key)
|
46
|
+
.forEach((cookie) => {
|
47
|
+
this.cookies.splice(this.cookies.indexOf(cookie), 1);
|
48
|
+
});
|
49
|
+
this.cookies.push(newCookie);
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Get cookie.
|
54
|
+
*
|
55
|
+
* @param location Location.
|
56
|
+
* @param fromDocument If true, the caller is a document.
|
57
|
+
* @returns Cookie string.
|
58
|
+
*/
|
59
|
+
public getCookiesString(location: Location, fromDocument: boolean): string {
|
60
|
+
const cookies = this.cookies.filter((cookie) => {
|
61
|
+
// Skip when use document.cookie and the cookie is httponly.
|
62
|
+
if (fromDocument && cookie.isHttpOnly()) {
|
63
|
+
return false;
|
64
|
+
}
|
65
|
+
if (cookie.isExpired()) {
|
66
|
+
return false;
|
67
|
+
}
|
68
|
+
if (cookie.isSecure() && location.protocol !== 'https:') {
|
69
|
+
return false;
|
70
|
+
}
|
71
|
+
if (cookie.domain && !location.hostname.endsWith(cookie.domain)) {
|
72
|
+
return false;
|
73
|
+
}
|
74
|
+
if (cookie.path && !location.pathname.startsWith(cookie.path)) {
|
75
|
+
return false;
|
76
|
+
}
|
77
|
+
// TODO: check SameSite.
|
78
|
+
return true;
|
79
|
+
});
|
80
|
+
return cookies.map((cookie) => cookie.cookieString()).join('; ');
|
81
|
+
}
|
82
|
+
}
|
@@ -8,6 +8,9 @@ enum DOMExceptionNameEnum {
|
|
8
8
|
invalidNodeTypeError = 'InvalidNodeTypeError',
|
9
9
|
invalidCharacterError = 'InvalidCharacterError',
|
10
10
|
notFoundError = 'NotFoundError',
|
11
|
-
|
11
|
+
securityError = 'SecurityError',
|
12
|
+
networkError = 'NetworkError',
|
13
|
+
domException = 'DOMException',
|
14
|
+
invalidAccessError = 'InvalidAccessError'
|
12
15
|
}
|
13
16
|
export default DOMExceptionNameEnum;
|
@@ -4,27 +4,63 @@ import IDocument from '../nodes/document/IDocument';
|
|
4
4
|
import IResponse from './IResponse';
|
5
5
|
import Response from './Response';
|
6
6
|
import NodeFetch from 'node-fetch';
|
7
|
+
import Request from './Request';
|
8
|
+
import RequestInfo from './RequestInfo';
|
9
|
+
import { URL } from 'url';
|
7
10
|
|
8
11
|
/**
|
9
12
|
* Helper class for performing fetch.
|
10
13
|
*/
|
11
14
|
export default class FetchHandler {
|
12
15
|
/**
|
13
|
-
* Returns resource data
|
16
|
+
* Returns resource data asynchronously.
|
14
17
|
*
|
15
18
|
* @param document Document.
|
16
19
|
* @param url URL to resource.
|
17
20
|
* @param [init] Init.
|
18
21
|
* @returns Response.
|
19
22
|
*/
|
20
|
-
public static fetch(
|
21
|
-
|
23
|
+
public static fetch(
|
24
|
+
document: IDocument,
|
25
|
+
url: RequestInfo,
|
26
|
+
init?: IRequestInit
|
27
|
+
): Promise<IResponse> {
|
22
28
|
const taskManager = document.defaultView.happyDOM.asyncTaskManager;
|
29
|
+
const requestInit = { ...init, headers: { ...init?.headers } };
|
30
|
+
const cookie = document.defaultView.document.cookie;
|
31
|
+
const referer = document.defaultView.location.origin;
|
32
|
+
|
33
|
+
requestInit.headers['user-agent'] = document.defaultView.navigator.userAgent;
|
34
|
+
|
35
|
+
// We need set referer to solve anti-hotlinking.
|
36
|
+
// And the browser will set the referer to the origin of the page.
|
37
|
+
// Referer is "null" when the URL is set to "about:blank".
|
38
|
+
// This is also how the browser behaves.
|
39
|
+
if (referer !== 'null') {
|
40
|
+
requestInit.headers['referer'] = referer;
|
41
|
+
}
|
42
|
+
|
43
|
+
if (cookie) {
|
44
|
+
requestInit.headers['set-cookie'] = cookie;
|
45
|
+
}
|
46
|
+
|
47
|
+
let request;
|
48
|
+
|
49
|
+
if (typeof url === 'string') {
|
50
|
+
request = new Request(RelativeURL.getAbsoluteURL(document.defaultView.location, url));
|
51
|
+
} else if (url instanceof URL) {
|
52
|
+
// URLs are always absolute, no need for getAbsoluteURL.
|
53
|
+
request = new Request(url);
|
54
|
+
} else {
|
55
|
+
request = new Request(RelativeURL.getAbsoluteURL(document.defaultView.location, url.url), {
|
56
|
+
...url
|
57
|
+
});
|
58
|
+
}
|
23
59
|
|
24
60
|
return new Promise((resolve, reject) => {
|
25
61
|
const taskID = taskManager.startTask();
|
26
62
|
|
27
|
-
NodeFetch(
|
63
|
+
NodeFetch(request, requestInit)
|
28
64
|
.then((response) => {
|
29
65
|
if (taskManager.getTaskCount() === 0) {
|
30
66
|
reject(new Error('Failed to complete fetch request. Task was canceled.'));
|
@@ -7,7 +7,7 @@ import IDocument from '../nodes/document/IDocument';
|
|
7
7
|
*/
|
8
8
|
export default class ResourceFetchHandler {
|
9
9
|
/**
|
10
|
-
* Returns resource data
|
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
|
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
|
-
|
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: ${
|
43
|
+
`Failed to perform request to "${absoluteURL}". Status code: ${xhr.status}`
|
42
44
|
);
|
43
45
|
}
|
44
46
|
|
45
|
-
return
|
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 '
|
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';
|
package/src/location/Location.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import URL from '
|
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.
|
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):
|
14
|
-
|
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
|
}
|
@@ -19,7 +19,7 @@ import QuerySelector from '../../query-selector/QuerySelector';
|
|
19
19
|
import IDocument from './IDocument';
|
20
20
|
import CSSStyleSheet from '../../css/CSSStyleSheet';
|
21
21
|
import DOMException from '../../exception/DOMException';
|
22
|
-
import
|
22
|
+
import CookieJar from '../../cookie/CookieJar';
|
23
23
|
import IElement from '../element/IElement';
|
24
24
|
import IHTMLScriptElement from '../html-script-element/IHTMLScriptElement';
|
25
25
|
import IHTMLElement from '../html-element/IHTMLElement';
|
@@ -63,10 +63,12 @@ export default class Document extends Node implements IDocument {
|
|
63
63
|
|
64
64
|
// Used as an unique identifier which is updated whenever the DOM gets modified.
|
65
65
|
public _cacheID = 0;
|
66
|
+
// Public in order to be accessible by the fetch and xhr.
|
67
|
+
public _cookie = new CookieJar();
|
66
68
|
|
67
69
|
protected _isFirstWrite = true;
|
68
70
|
protected _isFirstWriteAfterOpen = false;
|
69
|
-
|
71
|
+
|
70
72
|
private _selection: Selection = null;
|
71
73
|
|
72
74
|
// Events
|
@@ -183,7 +185,6 @@ export default class Document extends Node implements IDocument {
|
|
183
185
|
/**
|
184
186
|
* Creates an instance of Document.
|
185
187
|
*
|
186
|
-
* @param defaultView Default view.
|
187
188
|
*/
|
188
189
|
constructor() {
|
189
190
|
super();
|
@@ -258,7 +259,7 @@ export default class Document extends Node implements IDocument {
|
|
258
259
|
* @returns Cookie.
|
259
260
|
*/
|
260
261
|
public get cookie(): string {
|
261
|
-
return this._cookie;
|
262
|
+
return this._cookie.getCookiesString(this.defaultView.location, true);
|
262
263
|
}
|
263
264
|
|
264
265
|
/**
|
@@ -267,7 +268,7 @@ export default class Document extends Node implements IDocument {
|
|
267
268
|
* @param cookie Cookie string.
|
268
269
|
*/
|
269
270
|
public set cookie(cookie: string) {
|
270
|
-
this._cookie
|
271
|
+
this._cookie.setCookiesString(cookie);
|
271
272
|
}
|
272
273
|
|
273
274
|
/**
|
@@ -404,6 +405,24 @@ export default class Document extends Node implements IDocument {
|
|
404
405
|
return this.defaultView.location.href;
|
405
406
|
}
|
406
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
|
+
|
407
426
|
/**
|
408
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.
|
409
428
|
*
|
@@ -866,7 +885,6 @@ export default class Document extends Node implements IDocument {
|
|
866
885
|
*
|
867
886
|
* @param node Node to import.
|
868
887
|
* @param [deep=false] Set to "true" if the clone should be deep.
|
869
|
-
* @param Imported Node.
|
870
888
|
*/
|
871
889
|
public importNode(node: INode, deep = false): INode {
|
872
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 (
|
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();
|