@depup/jsdom 30.1.0-depup.3 → 30.1.1-depup.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.
- package/README.md +4 -6
- package/changes.json +5 -13
- package/lib/api.js +79 -146
- package/lib/jsdom/browser/Window.js +18 -31
- package/lib/jsdom/browser/not-implemented.js +1 -1
- package/lib/jsdom/browser/resources/decompress-interceptor.js +2 -2
- package/lib/jsdom/browser/resources/jsdom-dispatcher.js +3 -3
- package/lib/jsdom/browser/resources/per-document-resource-loader.js +4 -6
- package/lib/jsdom/browser/resources/request-interceptor.js +1 -1
- package/lib/jsdom/living/crypto/Crypto-impl.js +1 -1
- package/lib/jsdom/living/css/CSSStyleDeclaration-impl.js +4 -21
- package/lib/jsdom/living/css/helpers/generic-property-descriptor.js +2 -3
- package/lib/jsdom/living/css/helpers/stylesheets.js +3 -3
- package/lib/jsdom/living/css/properties/background.js +4 -5
- package/lib/jsdom/living/css/properties/backgroundAttachment.js +2 -4
- package/lib/jsdom/living/css/properties/backgroundClip.js +2 -4
- package/lib/jsdom/living/css/properties/backgroundColor.js +2 -4
- package/lib/jsdom/living/css/properties/backgroundImage.js +2 -4
- package/lib/jsdom/living/css/properties/backgroundOrigin.js +2 -4
- package/lib/jsdom/living/css/properties/backgroundPosition.js +2 -6
- package/lib/jsdom/living/css/properties/backgroundPositionX.js +2 -4
- package/lib/jsdom/living/css/properties/backgroundPositionY.js +2 -4
- package/lib/jsdom/living/css/properties/backgroundRepeat.js +2 -4
- package/lib/jsdom/living/css/properties/backgroundSize.js +2 -4
- package/lib/jsdom/living/css/properties/border.js +2 -3
- package/lib/jsdom/living/css/properties/borderBottom.js +2 -5
- package/lib/jsdom/living/css/properties/borderBottomColor.js +2 -12
- package/lib/jsdom/living/css/properties/borderBottomStyle.js +2 -12
- package/lib/jsdom/living/css/properties/borderBottomWidth.js +2 -12
- package/lib/jsdom/living/css/properties/borderColor.js +2 -5
- package/lib/jsdom/living/css/properties/borderLeft.js +2 -5
- package/lib/jsdom/living/css/properties/borderLeftColor.js +2 -12
- package/lib/jsdom/living/css/properties/borderLeftStyle.js +2 -12
- package/lib/jsdom/living/css/properties/borderLeftWidth.js +2 -12
- package/lib/jsdom/living/css/properties/borderRight.js +2 -5
- package/lib/jsdom/living/css/properties/borderRightColor.js +2 -12
- package/lib/jsdom/living/css/properties/borderRightStyle.js +2 -12
- package/lib/jsdom/living/css/properties/borderRightWidth.js +2 -12
- package/lib/jsdom/living/css/properties/borderSpacing.js +2 -3
- package/lib/jsdom/living/css/properties/borderStyle.js +2 -5
- package/lib/jsdom/living/css/properties/borderTop.js +2 -5
- package/lib/jsdom/living/css/properties/borderTopColor.js +2 -12
- package/lib/jsdom/living/css/properties/borderTopStyle.js +2 -12
- package/lib/jsdom/living/css/properties/borderTopWidth.js +2 -12
- package/lib/jsdom/living/css/properties/borderWidth.js +2 -5
- package/lib/jsdom/living/css/properties/bottom.js +2 -3
- package/lib/jsdom/living/css/properties/clip.js +2 -3
- package/lib/jsdom/living/css/properties/display.js +2 -3
- package/lib/jsdom/living/css/properties/flex.js +2 -3
- package/lib/jsdom/living/css/properties/flexBasis.js +2 -4
- package/lib/jsdom/living/css/properties/flexGrow.js +2 -4
- package/lib/jsdom/living/css/properties/flexShrink.js +2 -4
- package/lib/jsdom/living/css/properties/font.js +2 -3
- package/lib/jsdom/living/css/properties/fontFamily.js +2 -4
- package/lib/jsdom/living/css/properties/fontSize.js +2 -4
- package/lib/jsdom/living/css/properties/fontStyle.js +2 -4
- package/lib/jsdom/living/css/properties/fontVariant.js +2 -4
- package/lib/jsdom/living/css/properties/fontWeight.js +2 -4
- package/lib/jsdom/living/css/properties/height.js +2 -3
- package/lib/jsdom/living/css/properties/left.js +2 -3
- package/lib/jsdom/living/css/properties/lineHeight.js +2 -4
- package/lib/jsdom/living/css/properties/margin.js +2 -3
- package/lib/jsdom/living/css/properties/marginBottom.js +2 -4
- package/lib/jsdom/living/css/properties/marginLeft.js +2 -4
- package/lib/jsdom/living/css/properties/marginRight.js +2 -4
- package/lib/jsdom/living/css/properties/marginTop.js +2 -4
- package/lib/jsdom/living/css/properties/opacity.js +2 -3
- package/lib/jsdom/living/css/properties/padding.js +2 -3
- package/lib/jsdom/living/css/properties/paddingBottom.js +2 -4
- package/lib/jsdom/living/css/properties/paddingLeft.js +2 -4
- package/lib/jsdom/living/css/properties/paddingRight.js +2 -4
- package/lib/jsdom/living/css/properties/paddingTop.js +2 -4
- package/lib/jsdom/living/css/properties/right.js +2 -3
- package/lib/jsdom/living/css/properties/top.js +2 -3
- package/lib/jsdom/living/css/properties/width.js +2 -3
- package/lib/jsdom/living/helpers/focusing.js +213 -10
- package/lib/jsdom/living/helpers/runtime-script-errors.js +2 -2
- package/lib/jsdom/living/mutation-observer/MutationObserver-impl.js +1 -1
- package/lib/jsdom/living/navigator/Navigator-impl.js +1 -1
- package/lib/jsdom/living/navigator/NavigatorConcurrentHardware-impl.js +1 -1
- package/lib/jsdom/living/nodes/Document-impl.js +31 -33
- package/lib/jsdom/living/nodes/GlobalEventHandlers-impl.js +3 -2
- package/lib/jsdom/living/nodes/HTMLFrameElement-impl.js +10 -15
- package/lib/jsdom/living/nodes/HTMLOrSVGElement-impl.js +5 -39
- package/lib/jsdom/living/nodes/HTMLScriptElement-impl.js +5 -4
- package/lib/jsdom/living/websockets/WebSocket-impl.js +1 -1
- package/lib/jsdom/living/window/navigation.js +1 -1
- package/lib/jsdom/living/xhr/XMLHttpRequest-impl.js +2 -2
- package/lib/jsdom/virtual-console.js +1 -1
- package/package.json +8 -17
package/README.md
CHANGED
|
@@ -13,22 +13,20 @@ npm install @depup/jsdom
|
|
|
13
13
|
|
|
14
14
|
| Field | Value |
|
|
15
15
|
|-------|-------|
|
|
16
|
-
| Original | [jsdom](https://www.npmjs.com/package/jsdom) @ 30.1.
|
|
17
|
-
| Processed | 2026-09-
|
|
16
|
+
| Original | [jsdom](https://www.npmjs.com/package/jsdom) @ 30.1.1 |
|
|
17
|
+
| Processed | 2026-09-22 |
|
|
18
18
|
| Smoke test | passed |
|
|
19
|
-
| Deps updated |
|
|
19
|
+
| Deps updated | 6 |
|
|
20
20
|
|
|
21
21
|
## Dependency Changes
|
|
22
22
|
|
|
23
23
|
| Dependency | From | To |
|
|
24
24
|
|------------|------|-----|
|
|
25
25
|
| @asamuzakjp/css-color | ^7.0.0 | ^7.0.1 |
|
|
26
|
-
| @asamuzakjp/dom-selector | ^9.1.2 | ^9.2.1 |
|
|
27
26
|
| @csstools/css-syntax-patches-for-csstree | ^1.1.13 | ^1.1.14 |
|
|
28
27
|
| @exodus/bytes | ^1.15.1 | ^1.15.2 |
|
|
29
|
-
| html-encoding-sniffer | ^6.0.0 | ^7.0.0 |
|
|
30
28
|
| lru-cache | ^11.5.2 | ^11.5.3 |
|
|
31
|
-
|
|
|
29
|
+
| undici | ^8.10.2 | ^8.11.0 |
|
|
32
30
|
| whatwg-url | ^17.1.1 | ^17.1.2 |
|
|
33
31
|
|
|
34
32
|
---
|
package/changes.json
CHANGED
|
@@ -4,10 +4,6 @@
|
|
|
4
4
|
"from": "^7.0.0",
|
|
5
5
|
"to": "^7.0.1"
|
|
6
6
|
},
|
|
7
|
-
"@asamuzakjp/dom-selector": {
|
|
8
|
-
"from": "^9.1.2",
|
|
9
|
-
"to": "^9.2.1"
|
|
10
|
-
},
|
|
11
7
|
"@csstools/css-syntax-patches-for-csstree": {
|
|
12
8
|
"from": "^1.1.13",
|
|
13
9
|
"to": "^1.1.14"
|
|
@@ -16,23 +12,19 @@
|
|
|
16
12
|
"from": "^1.15.1",
|
|
17
13
|
"to": "^1.15.2"
|
|
18
14
|
},
|
|
19
|
-
"html-encoding-sniffer": {
|
|
20
|
-
"from": "^6.0.0",
|
|
21
|
-
"to": "^7.0.0"
|
|
22
|
-
},
|
|
23
15
|
"lru-cache": {
|
|
24
16
|
"from": "^11.5.2",
|
|
25
17
|
"to": "^11.5.3"
|
|
26
18
|
},
|
|
27
|
-
"
|
|
28
|
-
"from": "^
|
|
29
|
-
"to": "^
|
|
19
|
+
"undici": {
|
|
20
|
+
"from": "^8.10.2",
|
|
21
|
+
"to": "^8.11.0"
|
|
30
22
|
},
|
|
31
23
|
"whatwg-url": {
|
|
32
24
|
"from": "^17.1.1",
|
|
33
25
|
"to": "^17.1.2"
|
|
34
26
|
}
|
|
35
27
|
},
|
|
36
|
-
"timestamp": "2026-09-
|
|
37
|
-
"totalUpdated":
|
|
28
|
+
"timestamp": "2026-09-22T08:13:15.738Z",
|
|
29
|
+
"totalUpdated": 6
|
|
38
30
|
}
|
package/lib/api.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const vm = require("vm");
|
|
2
|
+
const fs = require("node:fs").promises;
|
|
3
|
+
const path = require("node:path");
|
|
4
|
+
const { pathToFileURL } = require("node:url");
|
|
5
|
+
const vm = require("node:vm");
|
|
6
6
|
const toughCookie = require("tough-cookie");
|
|
7
7
|
const sniffHTMLEncoding = require("html-encoding-sniffer");
|
|
8
8
|
const whatwgURL = require("whatwg-url");
|
|
@@ -36,13 +36,13 @@ class JSDOM {
|
|
|
36
36
|
const mimeType = new MIMEType(options.contentType === undefined ? "text/html" : options.contentType);
|
|
37
37
|
const { html, encoding } = normalizeHTML(input, mimeType);
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
const normalized = normalizeOptions(options, encoding, mimeType);
|
|
40
40
|
|
|
41
|
-
this[window] = createWindow(
|
|
41
|
+
this[window] = createWindow(normalized.windowOptions);
|
|
42
42
|
|
|
43
43
|
const documentImpl = this[window]._document;
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
normalized.beforeParse(this[window]._globalProxy);
|
|
46
46
|
|
|
47
47
|
parseIntoDocument(html, documentImpl);
|
|
48
48
|
|
|
@@ -56,12 +56,11 @@ class JSDOM {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
get virtualConsole() {
|
|
59
|
-
return this[window].
|
|
59
|
+
return this[window]._settings.virtualConsole;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
get cookieJar() {
|
|
63
|
-
|
|
64
|
-
return this[window]._document._cookieJar;
|
|
63
|
+
return this[window]._settings.cookieJar;
|
|
65
64
|
}
|
|
66
65
|
|
|
67
66
|
serialize() {
|
|
@@ -122,14 +121,14 @@ class JSDOM {
|
|
|
122
121
|
// For the initial fetch, we default to "usable" instead of no resource loading, since fromURL() implicitly requests
|
|
123
122
|
// fetching the initial resource. This does not impact further resource fetching, which uses options.resources.
|
|
124
123
|
const resourcesForInitialFetch = options.resources !== undefined ? options.resources : "usable";
|
|
125
|
-
const {
|
|
124
|
+
const { dispatcher } = createResourceSettings(resourcesForInitialFetch, options.cookieJar);
|
|
126
125
|
|
|
127
126
|
const headers = { Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" };
|
|
128
127
|
if (options.referrer) {
|
|
129
128
|
headers.Referer = options.referrer;
|
|
130
129
|
}
|
|
131
130
|
|
|
132
|
-
const response = await fetchCollected(
|
|
131
|
+
const response = await fetchCollected(dispatcher, {
|
|
133
132
|
url,
|
|
134
133
|
headers
|
|
135
134
|
});
|
|
@@ -138,14 +137,11 @@ class JSDOM {
|
|
|
138
137
|
throw new Error(`Resource was not loaded. Status: ${response.status}`);
|
|
139
138
|
}
|
|
140
139
|
|
|
141
|
-
|
|
140
|
+
return new JSDOM(response.body, {
|
|
141
|
+
...options,
|
|
142
142
|
url: response.url,
|
|
143
|
-
contentType: response.headers["content-type"] || undefined
|
|
144
|
-
referrer: options.referrer,
|
|
145
|
-
resources: options.resources
|
|
143
|
+
contentType: response.headers["content-type"] || undefined
|
|
146
144
|
});
|
|
147
|
-
|
|
148
|
-
return new JSDOM(response.body, options);
|
|
149
145
|
}
|
|
150
146
|
|
|
151
147
|
static async fromFile(filename, options = {}) {
|
|
@@ -165,8 +161,7 @@ function normalizeFromURLOptions(options) {
|
|
|
165
161
|
throw new TypeError("Cannot supply a contentType option when using fromURL");
|
|
166
162
|
}
|
|
167
163
|
|
|
168
|
-
//
|
|
169
|
-
// given to request()
|
|
164
|
+
// Normalize fields needed for the initial request. The constructor handles the remaining options after fetching.
|
|
170
165
|
const normalized = { ...options };
|
|
171
166
|
|
|
172
167
|
if (options.referrer !== undefined) {
|
|
@@ -178,54 +173,6 @@ function normalizeFromURLOptions(options) {
|
|
|
178
173
|
}
|
|
179
174
|
|
|
180
175
|
return normalized;
|
|
181
|
-
|
|
182
|
-
// All other options don't need to be processed yet, and can be taken care of in the normal course of things when
|
|
183
|
-
// `fromURL` calls `new JSDOM(html, options)`.
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function extractResourcesOptions(resources, cookieJar) {
|
|
187
|
-
// loadSubresources controls whether PerDocumentResourceLoader fetches scripts, stylesheets, etc.
|
|
188
|
-
// XHR always works regardless of this flag.
|
|
189
|
-
let userAgent, baseDispatcher, userInterceptors, loadSubresources;
|
|
190
|
-
|
|
191
|
-
if (resources === undefined) {
|
|
192
|
-
// resources: undefined means no automatic subresource fetching, but XHR still works
|
|
193
|
-
userAgent = DEFAULT_USER_AGENT;
|
|
194
|
-
baseDispatcher = getGlobalDispatcher();
|
|
195
|
-
userInterceptors = [];
|
|
196
|
-
loadSubresources = false;
|
|
197
|
-
} else if (resources === "usable") {
|
|
198
|
-
// resources: "usable" means use all defaults
|
|
199
|
-
userAgent = DEFAULT_USER_AGENT;
|
|
200
|
-
baseDispatcher = getGlobalDispatcher();
|
|
201
|
-
userInterceptors = [];
|
|
202
|
-
loadSubresources = true;
|
|
203
|
-
} else if (typeof resources === "object" && resources !== null) {
|
|
204
|
-
// resources: { userAgent?, dispatcher?, interceptors? }
|
|
205
|
-
userAgent = resources.userAgent !== undefined ? resources.userAgent : DEFAULT_USER_AGENT;
|
|
206
|
-
baseDispatcher = resources.dispatcher !== undefined ? resources.dispatcher : getGlobalDispatcher();
|
|
207
|
-
userInterceptors = resources.interceptors !== undefined ? resources.interceptors : [];
|
|
208
|
-
loadSubresources = true;
|
|
209
|
-
} else {
|
|
210
|
-
throw new TypeError(`resources must be undefined, "usable", or an object`);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// User interceptors come first (outermost), then decompress interceptor
|
|
214
|
-
const allUserInterceptors = [
|
|
215
|
-
...userInterceptors,
|
|
216
|
-
createDecompressInterceptor()
|
|
217
|
-
];
|
|
218
|
-
|
|
219
|
-
return {
|
|
220
|
-
userAgent,
|
|
221
|
-
effectiveDispatcher: new JSDOMDispatcher({
|
|
222
|
-
baseDispatcher,
|
|
223
|
-
cookieJar,
|
|
224
|
-
userAgent,
|
|
225
|
-
userInterceptors: allUserInterceptors
|
|
226
|
-
}),
|
|
227
|
-
loadSubresources
|
|
228
|
-
};
|
|
229
176
|
}
|
|
230
177
|
|
|
231
178
|
function normalizeFromFileOptions(filename, options) {
|
|
@@ -245,99 +192,85 @@ function normalizeFromFileOptions(filename, options) {
|
|
|
245
192
|
return normalized;
|
|
246
193
|
}
|
|
247
194
|
|
|
248
|
-
function
|
|
249
|
-
|
|
250
|
-
windowOptions: {
|
|
251
|
-
// Defaults
|
|
252
|
-
url: "about:blank",
|
|
253
|
-
referrer: "",
|
|
254
|
-
contentType: "text/html",
|
|
255
|
-
parsingMode: "html",
|
|
256
|
-
parseOptions: {
|
|
257
|
-
sourceCodeLocationInfo: false,
|
|
258
|
-
scriptingEnabled: false
|
|
259
|
-
},
|
|
260
|
-
runScripts: undefined,
|
|
261
|
-
encoding,
|
|
262
|
-
pretendToBeVisual: false,
|
|
263
|
-
storageQuota: 5000000,
|
|
264
|
-
|
|
265
|
-
// Defaults filled in later
|
|
266
|
-
dispatcher: undefined,
|
|
267
|
-
loadSubresources: undefined,
|
|
268
|
-
userAgent: undefined,
|
|
269
|
-
virtualConsole: undefined,
|
|
270
|
-
cookieJar: undefined
|
|
271
|
-
},
|
|
272
|
-
|
|
273
|
-
// Defaults
|
|
274
|
-
beforeParse() { }
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
// options.contentType was parsed into mimeType by the caller.
|
|
195
|
+
function normalizeOptions(options, encoding, mimeType) {
|
|
196
|
+
// `options.contentType` was parsed into `mimeType` by the caller.
|
|
278
197
|
if (!mimeType.isHTML() && !mimeType.isXML()) {
|
|
279
198
|
throw new RangeError(`The given content type of "${options.contentType}" was not a HTML or XML content type`);
|
|
280
199
|
}
|
|
281
200
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
if (options.referrer !== undefined) {
|
|
290
|
-
transformed.windowOptions.referrer = (new URL(options.referrer)).href;
|
|
201
|
+
const parsingMode = mimeType.isHTML() ? "html" : "xml";
|
|
202
|
+
const url = options.url === undefined ? "about:blank" : (new URL(options.url)).href;
|
|
203
|
+
const referrer = options.referrer === undefined ? "" : (new URL(options.referrer)).href;
|
|
204
|
+
const sourceCodeLocationInfo = Boolean(options.includeNodeLocations);
|
|
205
|
+
if (sourceCodeLocationInfo && parsingMode === "xml") {
|
|
206
|
+
throw new TypeError("Cannot set includeNodeLocations to true with an XML content type");
|
|
291
207
|
}
|
|
292
208
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
transformed.windowOptions.parseOptions = { sourceCodeLocationInfo: true };
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
transformed.windowOptions.cookieJar = options.cookieJar === undefined ?
|
|
302
|
-
new CookieJar() :
|
|
303
|
-
options.cookieJar;
|
|
304
|
-
|
|
305
|
-
transformed.windowOptions.virtualConsole = options.virtualConsole === undefined ?
|
|
306
|
-
(new VirtualConsole()).forwardTo(console) :
|
|
307
|
-
options.virtualConsole;
|
|
308
|
-
|
|
309
|
-
if (!(transformed.windowOptions.virtualConsole instanceof VirtualConsole)) {
|
|
209
|
+
const cookieJar = options.cookieJar === undefined ? new CookieJar() : options.cookieJar;
|
|
210
|
+
const virtualConsole = options.virtualConsole === undefined ?
|
|
211
|
+
(new VirtualConsole()).forwardTo(console) :
|
|
212
|
+
options.virtualConsole;
|
|
213
|
+
if (!(virtualConsole instanceof VirtualConsole)) {
|
|
310
214
|
throw new TypeError("virtualConsole must be an instance of VirtualConsole");
|
|
311
215
|
}
|
|
312
216
|
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
transformed.windowOptions.loadSubresources = loadSubresources;
|
|
318
|
-
|
|
319
|
-
if (options.runScripts !== undefined) {
|
|
320
|
-
transformed.windowOptions.runScripts = String(options.runScripts);
|
|
321
|
-
if (transformed.windowOptions.runScripts === "dangerously") {
|
|
322
|
-
transformed.windowOptions.parseOptions.scriptingEnabled = true;
|
|
323
|
-
} else if (transformed.windowOptions.runScripts !== "outside-only") {
|
|
324
|
-
throw new RangeError(`runScripts must be undefined, "dangerously", or "outside-only"`);
|
|
325
|
-
}
|
|
217
|
+
const resourceSettings = createResourceSettings(options.resources, cookieJar);
|
|
218
|
+
const runScripts = options.runScripts === undefined ? undefined : String(options.runScripts);
|
|
219
|
+
if (runScripts !== undefined && runScripts !== "dangerously" && runScripts !== "outside-only") {
|
|
220
|
+
throw new RangeError(`runScripts must be undefined, "dangerously", or "outside-only"`);
|
|
326
221
|
}
|
|
327
222
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
223
|
+
const { beforeParse = () => {} } = options;
|
|
224
|
+
const pretendToBeVisual = Boolean(options.pretendToBeVisual);
|
|
225
|
+
const storageQuota = options.storageQuota === undefined ? 5000000 : Number(options.storageQuota);
|
|
331
226
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
227
|
+
return {
|
|
228
|
+
windowOptions: {
|
|
229
|
+
settings: {
|
|
230
|
+
runScripts,
|
|
231
|
+
pretendToBeVisual,
|
|
232
|
+
storageQuota,
|
|
233
|
+
cookieJar,
|
|
234
|
+
virtualConsole,
|
|
235
|
+
...resourceSettings
|
|
236
|
+
},
|
|
237
|
+
documentOptions: {
|
|
238
|
+
url,
|
|
239
|
+
referrer,
|
|
240
|
+
contentType: mimeType.essence,
|
|
241
|
+
parsingMode,
|
|
242
|
+
encoding,
|
|
243
|
+
parseOptions: { sourceCodeLocationInfo }
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
beforeParse
|
|
247
|
+
};
|
|
248
|
+
}
|
|
335
249
|
|
|
336
|
-
|
|
337
|
-
|
|
250
|
+
function createResourceSettings(resources, cookieJar) {
|
|
251
|
+
const resourceOptions = resources === undefined || resources === "usable" ? {} : resources;
|
|
252
|
+
if (typeof resourceOptions !== "object" || resourceOptions === null) {
|
|
253
|
+
throw new TypeError(`resources must be undefined, "usable", or an object`);
|
|
338
254
|
}
|
|
339
255
|
|
|
340
|
-
|
|
256
|
+
const {
|
|
257
|
+
userAgent = DEFAULT_USER_AGENT,
|
|
258
|
+
dispatcher = getGlobalDispatcher(),
|
|
259
|
+
interceptors = []
|
|
260
|
+
} = resourceOptions;
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
userAgent,
|
|
264
|
+
dispatcher: new JSDOMDispatcher({
|
|
265
|
+
baseDispatcher: dispatcher,
|
|
266
|
+
cookieJar,
|
|
267
|
+
userAgent,
|
|
268
|
+
// User interceptors come first (outermost), then the decompression interceptor.
|
|
269
|
+
userInterceptors: [...interceptors, createDecompressInterceptor()]
|
|
270
|
+
}),
|
|
271
|
+
// This controls automatic subresource fetching; XHR works regardless.
|
|
272
|
+
loadSubresources: resources !== undefined
|
|
273
|
+
};
|
|
341
274
|
}
|
|
342
275
|
|
|
343
276
|
function normalizeHTML(html, mimeType) {
|
|
@@ -40,7 +40,7 @@ const { globalEventHandlersEvents, windowEventHandlersEvents } = require("../../
|
|
|
40
40
|
const jsGlobalEntriesToInstall = Object.entries(jsGlobals).filter(([name]) => name in global);
|
|
41
41
|
|
|
42
42
|
exports.createWindow = options => {
|
|
43
|
-
const makeVMContext = options.runScripts === "outside-only" || options.runScripts === "dangerously";
|
|
43
|
+
const makeVMContext = options.settings.runScripts === "outside-only" || options.settings.runScripts === "dangerously";
|
|
44
44
|
|
|
45
45
|
// Bootstrap with an empty object from the Node.js realm. We'll muck with its prototype chain shortly.
|
|
46
46
|
let window = {};
|
|
@@ -185,29 +185,23 @@ function installEventHandlerAccessors(window, events) {
|
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
function installOwnProperties(window,
|
|
188
|
+
function installOwnProperties(window, { settings, documentOptions, commonForOrigin }) {
|
|
189
189
|
const windowInitialized = performance.now();
|
|
190
190
|
|
|
191
191
|
// ### PRIVATE DATA PROPERTIES
|
|
192
192
|
|
|
193
|
-
window
|
|
194
|
-
window.
|
|
195
|
-
window._userAgent = options.userAgent;
|
|
193
|
+
// These jsdom settings are shared by every window created for this `JSDOM` instance.
|
|
194
|
+
window._settings = settings;
|
|
196
195
|
|
|
197
|
-
// List options explicitly to be clear which are passed through
|
|
198
196
|
window._document = documents.createImpl(window, {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
referrer: options.referrer,
|
|
206
|
-
parseOptions: options.parseOptions,
|
|
197
|
+
...documentOptions,
|
|
198
|
+
cookieJar: settings.cookieJar,
|
|
199
|
+
parseOptions: {
|
|
200
|
+
...documentOptions.parseOptions,
|
|
201
|
+
scriptingEnabled: settings.runScripts === "dangerously"
|
|
202
|
+
},
|
|
207
203
|
readyState: "loading",
|
|
208
|
-
defaultView: window._globalProxy
|
|
209
|
-
global: window,
|
|
210
|
-
parentOrigin: options.parentOrigin
|
|
204
|
+
defaultView: window._globalProxy
|
|
211
205
|
}, { alwaysUseDocumentClass: true });
|
|
212
206
|
|
|
213
207
|
const documentOrigin = window._document._origin;
|
|
@@ -220,10 +214,6 @@ function installOwnProperties(window, options) {
|
|
|
220
214
|
stateObject: null
|
|
221
215
|
}, window);
|
|
222
216
|
|
|
223
|
-
window._virtualConsole = options.virtualConsole;
|
|
224
|
-
|
|
225
|
-
window._runScripts = options.runScripts;
|
|
226
|
-
|
|
227
217
|
// Set up the window as if it's a top level window.
|
|
228
218
|
// If it's not, then references will be corrected by frame/iframe code.
|
|
229
219
|
window._parent = window._top = window._globalProxy;
|
|
@@ -237,14 +227,11 @@ function installOwnProperties(window, options) {
|
|
|
237
227
|
// https://dom.spec.whatwg.org/#window-current-event
|
|
238
228
|
window._currentEvent = undefined;
|
|
239
229
|
|
|
240
|
-
window._pretendToBeVisual = options.pretendToBeVisual;
|
|
241
|
-
window._storageQuota = options.storageQuota;
|
|
242
|
-
|
|
243
230
|
// Some properties (such as localStorage and sessionStorage) share data
|
|
244
231
|
// between windows in the same origin. This object is intended
|
|
245
232
|
// to contain such data.
|
|
246
|
-
if (
|
|
247
|
-
window._commonForOrigin =
|
|
233
|
+
if (commonForOrigin && commonForOrigin[documentOrigin]) {
|
|
234
|
+
window._commonForOrigin = commonForOrigin;
|
|
248
235
|
} else {
|
|
249
236
|
window._commonForOrigin = {
|
|
250
237
|
[documentOrigin]: {
|
|
@@ -264,14 +251,14 @@ function installOwnProperties(window, options) {
|
|
|
264
251
|
storageArea: window._currentOriginData.localStorageArea,
|
|
265
252
|
type: "localStorage",
|
|
266
253
|
url: window._document.documentURI,
|
|
267
|
-
storageQuota: window.
|
|
254
|
+
storageQuota: window._settings.storageQuota
|
|
268
255
|
});
|
|
269
256
|
window._sessionStorage = Storage.create(window, [], {
|
|
270
257
|
associatedWindow: window,
|
|
271
258
|
storageArea: window._currentOriginData.sessionStorageArea,
|
|
272
259
|
type: "sessionStorage",
|
|
273
260
|
url: window._document.documentURI,
|
|
274
|
-
storageQuota: window.
|
|
261
|
+
storageQuota: window._settings.storageQuota
|
|
275
262
|
});
|
|
276
263
|
|
|
277
264
|
// ### SELECTION
|
|
@@ -552,7 +539,7 @@ function installOwnProperties(window, options) {
|
|
|
552
539
|
try {
|
|
553
540
|
if (typeof handler === "function") {
|
|
554
541
|
handler.apply(methodContextProxy, args);
|
|
555
|
-
} else if (window.
|
|
542
|
+
} else if (window._settings.runScripts === "dangerously") {
|
|
556
543
|
vm.runInContext(handler, window, { filename: window.location.href, displayErrors: false });
|
|
557
544
|
}
|
|
558
545
|
} catch (e) {
|
|
@@ -602,7 +589,7 @@ function installOwnProperties(window, options) {
|
|
|
602
589
|
// requestAnimationFrame() calls outstanding, we don't fire the timer. This helps us track that.
|
|
603
590
|
let numberOfOngoingAnimationFrameCallbacks = 0;
|
|
604
591
|
|
|
605
|
-
if (window.
|
|
592
|
+
if (window._settings.pretendToBeVisual) {
|
|
606
593
|
window.requestAnimationFrame = function (callback) {
|
|
607
594
|
callback = IDLFunction.convert(window, callback);
|
|
608
595
|
if (window._document._isDestroyed) {
|
|
@@ -892,7 +879,7 @@ function installOwnProperties(window, options) {
|
|
|
892
879
|
|
|
893
880
|
function wrapConsoleMethod(method) {
|
|
894
881
|
return (...args) => {
|
|
895
|
-
window.
|
|
882
|
+
window._settings.virtualConsole.emit(method, ...args);
|
|
896
883
|
};
|
|
897
884
|
}
|
|
898
885
|
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
// - Removed experimental warning
|
|
8
8
|
// - Use undici's exported DecoratorHandler
|
|
9
9
|
|
|
10
|
-
const {
|
|
11
|
-
const {
|
|
10
|
+
const { pipeline } = require("node:stream");
|
|
11
|
+
const { createInflate, createGunzip, createBrotliDecompress } = require("node:zlib");
|
|
12
12
|
const { DecoratorHandler } = require("undici");
|
|
13
13
|
|
|
14
14
|
const supportedEncodings = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const fs = require("fs");
|
|
3
|
-
const { Readable } = require("stream");
|
|
4
|
-
const { fileURLToPath } = require("url");
|
|
2
|
+
const fs = require("node:fs");
|
|
3
|
+
const { Readable } = require("node:stream");
|
|
4
|
+
const { fileURLToPath } = require("node:url");
|
|
5
5
|
const { parseURL, serializeURL, serializeURLOrigin, serializePath } = require("whatwg-url");
|
|
6
6
|
const dataURLFromRecord = require("data-urls").fromURLRecord;
|
|
7
7
|
const { Dispatcher } = require("undici");
|
|
@@ -6,10 +6,8 @@ const { fetchCollected } = require("./jsdom-dispatcher");
|
|
|
6
6
|
module.exports = class PerDocumentResourceLoader {
|
|
7
7
|
constructor(document) {
|
|
8
8
|
this._document = document;
|
|
9
|
-
this._defaultEncoding = document._encoding;
|
|
10
9
|
const defaultView = document._defaultView;
|
|
11
|
-
this.
|
|
12
|
-
this._loadSubresources = defaultView ? defaultView._loadSubresources : false;
|
|
10
|
+
this._settings = defaultView ? defaultView._settings : null;
|
|
13
11
|
this._requestManager = document._requestManager;
|
|
14
12
|
this._queue = document._queue;
|
|
15
13
|
this._deferQueue = document._deferQueue;
|
|
@@ -17,7 +15,7 @@ module.exports = class PerDocumentResourceLoader {
|
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
fetch(url, { element, onLoad, onError }) {
|
|
20
|
-
if (!this.
|
|
18
|
+
if (!this._settings?.loadSubresources || this._document._isDestroyed) {
|
|
21
19
|
return null;
|
|
22
20
|
}
|
|
23
21
|
|
|
@@ -33,7 +31,7 @@ module.exports = class PerDocumentResourceLoader {
|
|
|
33
31
|
// calls `window.close()`, the abort controller is already registered and will see the abort.
|
|
34
32
|
this._requestManager.add(abortController);
|
|
35
33
|
|
|
36
|
-
const fetchPromise = fetchCollected(this.
|
|
34
|
+
const fetchPromise = fetchCollected(this._settings.dispatcher, {
|
|
37
35
|
url,
|
|
38
36
|
headers: { Referer: this._document.URL },
|
|
39
37
|
signal: abortController.signal,
|
|
@@ -58,7 +56,7 @@ module.exports = class PerDocumentResourceLoader {
|
|
|
58
56
|
jsomError.type = "resource-loading";
|
|
59
57
|
jsomError.url = url;
|
|
60
58
|
|
|
61
|
-
this.
|
|
59
|
+
this._settings.virtualConsole.emit("jsdomError", jsomError);
|
|
62
60
|
|
|
63
61
|
return Promise.resolve();
|
|
64
62
|
};
|
|
@@ -166,7 +166,6 @@ class CSSStyleDeclarationImpl {
|
|
|
166
166
|
const parsedProperties = prepareProperties(properties);
|
|
167
167
|
for (const [property, item] of parsedProperties) {
|
|
168
168
|
const { priority, value } = item;
|
|
169
|
-
this._priorities.set(property, priority);
|
|
170
169
|
this.setProperty(property, value, priority);
|
|
171
170
|
}
|
|
172
171
|
}
|
|
@@ -327,13 +326,7 @@ class CSSStyleDeclarationImpl {
|
|
|
327
326
|
if (!Object.hasOwn(propertyDescriptors, property)) {
|
|
328
327
|
return;
|
|
329
328
|
}
|
|
330
|
-
this
|
|
331
|
-
if (priority) {
|
|
332
|
-
this._priorities.set(property, priority);
|
|
333
|
-
} else {
|
|
334
|
-
this._priorities.delete(property);
|
|
335
|
-
}
|
|
336
|
-
propertyDescriptors[property].set.call(this, value);
|
|
329
|
+
propertyDescriptors[property].set.call(this, value, priority);
|
|
337
330
|
}
|
|
338
331
|
|
|
339
332
|
get [idlUtils.supportedPropertyIndices]() {
|
|
@@ -760,17 +753,12 @@ class CSSStyleDeclarationImpl {
|
|
|
760
753
|
if (!shorthandProperty || !shorthandProperties.has(shorthandProperty)) {
|
|
761
754
|
return;
|
|
762
755
|
}
|
|
763
|
-
const shorthandPriority = this._priorities.get(shorthandProperty);
|
|
764
756
|
this.removeProperty(shorthandProperty);
|
|
765
757
|
if (typeof priority !== "string") {
|
|
766
758
|
priority = this._priorities.get(property) ?? "";
|
|
767
759
|
}
|
|
768
760
|
this.removeProperty(property);
|
|
769
|
-
|
|
770
|
-
this._setProperty(property, value);
|
|
771
|
-
} else {
|
|
772
|
-
this._setProperty(property, value, priority);
|
|
773
|
-
}
|
|
761
|
+
this._setProperty(property, value, priority);
|
|
774
762
|
if (value && !cssValues.hasVarFunc(value)) {
|
|
775
763
|
const longhandValues = [];
|
|
776
764
|
const shorthandItem = shorthandProperties.get(shorthandProperty);
|
|
@@ -868,17 +856,12 @@ class CSSStyleDeclarationImpl {
|
|
|
868
856
|
if (!shorthandProperty || !shorthandProperties.has(shorthandProperty)) {
|
|
869
857
|
return;
|
|
870
858
|
}
|
|
871
|
-
const shorthandPriority = this._priorities.get(shorthandProperty);
|
|
872
859
|
this.removeProperty(shorthandProperty);
|
|
873
860
|
if (typeof priority !== "string") {
|
|
874
861
|
priority = this._priorities.get(property) ?? "";
|
|
875
862
|
}
|
|
876
863
|
this.removeProperty(property);
|
|
877
|
-
|
|
878
|
-
this._setProperty(property, value);
|
|
879
|
-
} else {
|
|
880
|
-
this._setProperty(property, value, priority);
|
|
881
|
-
}
|
|
864
|
+
this._setProperty(property, value, priority);
|
|
882
865
|
if (value && !cssValues.hasVarFunc(value)) {
|
|
883
866
|
const longhandValues = [];
|
|
884
867
|
const { shorthandFor, position: shorthandPosition } = shorthandProperties.get(shorthandProperty);
|
|
@@ -892,7 +875,7 @@ class CSSStyleDeclarationImpl {
|
|
|
892
875
|
}
|
|
893
876
|
if (longhandValues.length === shorthandFor.size) {
|
|
894
877
|
const replacedValue = getPositionValue(longhandValues, shorthandPosition);
|
|
895
|
-
this._setProperty(shorthandProperty, replacedValue);
|
|
878
|
+
this._setProperty(shorthandProperty, replacedValue, priority);
|
|
896
879
|
}
|
|
897
880
|
}
|
|
898
881
|
}
|
|
@@ -22,15 +22,14 @@ const { AST_TYPES } = parsers;
|
|
|
22
22
|
*/
|
|
23
23
|
function createGenericPropertyDescriptor(property, { caseSensitive, dimensionTypes = {}, functionTypes = {} }) {
|
|
24
24
|
return {
|
|
25
|
-
set(v) {
|
|
25
|
+
set(v, priority = "") {
|
|
26
26
|
v = v.trim();
|
|
27
27
|
if (parsers.hasVarFunc(v)) {
|
|
28
|
-
this._setProperty(property, v);
|
|
28
|
+
this._setProperty(property, v, priority);
|
|
29
29
|
} else {
|
|
30
30
|
const parsedValue = parsers.parsePropertyValue(property, v, {
|
|
31
31
|
caseSensitive
|
|
32
32
|
});
|
|
33
|
-
const priority = this._priorities.get(property) ?? "";
|
|
34
33
|
if (Array.isArray(parsedValue)) {
|
|
35
34
|
if (parsedValue.length === 1) {
|
|
36
35
|
const {
|