@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.
Files changed (90) hide show
  1. package/README.md +4 -6
  2. package/changes.json +5 -13
  3. package/lib/api.js +79 -146
  4. package/lib/jsdom/browser/Window.js +18 -31
  5. package/lib/jsdom/browser/not-implemented.js +1 -1
  6. package/lib/jsdom/browser/resources/decompress-interceptor.js +2 -2
  7. package/lib/jsdom/browser/resources/jsdom-dispatcher.js +3 -3
  8. package/lib/jsdom/browser/resources/per-document-resource-loader.js +4 -6
  9. package/lib/jsdom/browser/resources/request-interceptor.js +1 -1
  10. package/lib/jsdom/living/crypto/Crypto-impl.js +1 -1
  11. package/lib/jsdom/living/css/CSSStyleDeclaration-impl.js +4 -21
  12. package/lib/jsdom/living/css/helpers/generic-property-descriptor.js +2 -3
  13. package/lib/jsdom/living/css/helpers/stylesheets.js +3 -3
  14. package/lib/jsdom/living/css/properties/background.js +4 -5
  15. package/lib/jsdom/living/css/properties/backgroundAttachment.js +2 -4
  16. package/lib/jsdom/living/css/properties/backgroundClip.js +2 -4
  17. package/lib/jsdom/living/css/properties/backgroundColor.js +2 -4
  18. package/lib/jsdom/living/css/properties/backgroundImage.js +2 -4
  19. package/lib/jsdom/living/css/properties/backgroundOrigin.js +2 -4
  20. package/lib/jsdom/living/css/properties/backgroundPosition.js +2 -6
  21. package/lib/jsdom/living/css/properties/backgroundPositionX.js +2 -4
  22. package/lib/jsdom/living/css/properties/backgroundPositionY.js +2 -4
  23. package/lib/jsdom/living/css/properties/backgroundRepeat.js +2 -4
  24. package/lib/jsdom/living/css/properties/backgroundSize.js +2 -4
  25. package/lib/jsdom/living/css/properties/border.js +2 -3
  26. package/lib/jsdom/living/css/properties/borderBottom.js +2 -5
  27. package/lib/jsdom/living/css/properties/borderBottomColor.js +2 -12
  28. package/lib/jsdom/living/css/properties/borderBottomStyle.js +2 -12
  29. package/lib/jsdom/living/css/properties/borderBottomWidth.js +2 -12
  30. package/lib/jsdom/living/css/properties/borderColor.js +2 -5
  31. package/lib/jsdom/living/css/properties/borderLeft.js +2 -5
  32. package/lib/jsdom/living/css/properties/borderLeftColor.js +2 -12
  33. package/lib/jsdom/living/css/properties/borderLeftStyle.js +2 -12
  34. package/lib/jsdom/living/css/properties/borderLeftWidth.js +2 -12
  35. package/lib/jsdom/living/css/properties/borderRight.js +2 -5
  36. package/lib/jsdom/living/css/properties/borderRightColor.js +2 -12
  37. package/lib/jsdom/living/css/properties/borderRightStyle.js +2 -12
  38. package/lib/jsdom/living/css/properties/borderRightWidth.js +2 -12
  39. package/lib/jsdom/living/css/properties/borderSpacing.js +2 -3
  40. package/lib/jsdom/living/css/properties/borderStyle.js +2 -5
  41. package/lib/jsdom/living/css/properties/borderTop.js +2 -5
  42. package/lib/jsdom/living/css/properties/borderTopColor.js +2 -12
  43. package/lib/jsdom/living/css/properties/borderTopStyle.js +2 -12
  44. package/lib/jsdom/living/css/properties/borderTopWidth.js +2 -12
  45. package/lib/jsdom/living/css/properties/borderWidth.js +2 -5
  46. package/lib/jsdom/living/css/properties/bottom.js +2 -3
  47. package/lib/jsdom/living/css/properties/clip.js +2 -3
  48. package/lib/jsdom/living/css/properties/display.js +2 -3
  49. package/lib/jsdom/living/css/properties/flex.js +2 -3
  50. package/lib/jsdom/living/css/properties/flexBasis.js +2 -4
  51. package/lib/jsdom/living/css/properties/flexGrow.js +2 -4
  52. package/lib/jsdom/living/css/properties/flexShrink.js +2 -4
  53. package/lib/jsdom/living/css/properties/font.js +2 -3
  54. package/lib/jsdom/living/css/properties/fontFamily.js +2 -4
  55. package/lib/jsdom/living/css/properties/fontSize.js +2 -4
  56. package/lib/jsdom/living/css/properties/fontStyle.js +2 -4
  57. package/lib/jsdom/living/css/properties/fontVariant.js +2 -4
  58. package/lib/jsdom/living/css/properties/fontWeight.js +2 -4
  59. package/lib/jsdom/living/css/properties/height.js +2 -3
  60. package/lib/jsdom/living/css/properties/left.js +2 -3
  61. package/lib/jsdom/living/css/properties/lineHeight.js +2 -4
  62. package/lib/jsdom/living/css/properties/margin.js +2 -3
  63. package/lib/jsdom/living/css/properties/marginBottom.js +2 -4
  64. package/lib/jsdom/living/css/properties/marginLeft.js +2 -4
  65. package/lib/jsdom/living/css/properties/marginRight.js +2 -4
  66. package/lib/jsdom/living/css/properties/marginTop.js +2 -4
  67. package/lib/jsdom/living/css/properties/opacity.js +2 -3
  68. package/lib/jsdom/living/css/properties/padding.js +2 -3
  69. package/lib/jsdom/living/css/properties/paddingBottom.js +2 -4
  70. package/lib/jsdom/living/css/properties/paddingLeft.js +2 -4
  71. package/lib/jsdom/living/css/properties/paddingRight.js +2 -4
  72. package/lib/jsdom/living/css/properties/paddingTop.js +2 -4
  73. package/lib/jsdom/living/css/properties/right.js +2 -3
  74. package/lib/jsdom/living/css/properties/top.js +2 -3
  75. package/lib/jsdom/living/css/properties/width.js +2 -3
  76. package/lib/jsdom/living/helpers/focusing.js +213 -10
  77. package/lib/jsdom/living/helpers/runtime-script-errors.js +2 -2
  78. package/lib/jsdom/living/mutation-observer/MutationObserver-impl.js +1 -1
  79. package/lib/jsdom/living/navigator/Navigator-impl.js +1 -1
  80. package/lib/jsdom/living/navigator/NavigatorConcurrentHardware-impl.js +1 -1
  81. package/lib/jsdom/living/nodes/Document-impl.js +31 -33
  82. package/lib/jsdom/living/nodes/GlobalEventHandlers-impl.js +3 -2
  83. package/lib/jsdom/living/nodes/HTMLFrameElement-impl.js +10 -15
  84. package/lib/jsdom/living/nodes/HTMLOrSVGElement-impl.js +5 -39
  85. package/lib/jsdom/living/nodes/HTMLScriptElement-impl.js +5 -4
  86. package/lib/jsdom/living/websockets/WebSocket-impl.js +1 -1
  87. package/lib/jsdom/living/window/navigation.js +1 -1
  88. package/lib/jsdom/living/xhr/XMLHttpRequest-impl.js +2 -2
  89. package/lib/jsdom/virtual-console.js +1 -1
  90. 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.0 |
17
- | Processed | 2026-09-21 |
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 | 8 |
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
- | w3c-xmlserializer | ^5.0.0 | ^6.0.0 |
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
- "w3c-xmlserializer": {
28
- "from": "^5.0.0",
29
- "to": "^6.0.0"
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-21T16:11:35.161Z",
37
- "totalUpdated": 8
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 path = require("path");
3
- const { pathToFileURL } = require("url");
4
- const fs = require("fs").promises;
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
- options = transformOptions(options, encoding, mimeType);
39
+ const normalized = normalizeOptions(options, encoding, mimeType);
40
40
 
41
- this[window] = createWindow(options.windowOptions);
41
+ this[window] = createWindow(normalized.windowOptions);
42
42
 
43
43
  const documentImpl = this[window]._document;
44
44
 
45
- options.beforeParse(this[window]._globalProxy);
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]._virtualConsole;
59
+ return this[window]._settings.virtualConsole;
60
60
  }
61
61
 
62
62
  get cookieJar() {
63
- // TODO NEWAPI move _cookieJar to window probably
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 { effectiveDispatcher } = extractResourcesOptions(resourcesForInitialFetch, options.cookieJar);
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(effectiveDispatcher, {
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
- options = Object.assign(options, {
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
- // Normalization of options which must be done before the rest of the fromURL code can use them, because they are
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 transformOptions(options, encoding, mimeType) {
249
- const transformed = {
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
- transformed.windowOptions.contentType = mimeType.essence;
283
- transformed.windowOptions.parsingMode = mimeType.isHTML() ? "html" : "xml";
284
-
285
- if (options.url !== undefined) {
286
- transformed.windowOptions.url = (new URL(options.url)).href;
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
- if (options.includeNodeLocations) {
294
- if (transformed.windowOptions.parsingMode === "xml") {
295
- throw new TypeError("Cannot set includeNodeLocations to true with an XML content type");
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 { userAgent, effectiveDispatcher, loadSubresources } =
314
- extractResourcesOptions(options.resources, transformed.windowOptions.cookieJar);
315
- transformed.windowOptions.userAgent = userAgent;
316
- transformed.windowOptions.dispatcher = effectiveDispatcher;
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
- if (options.beforeParse !== undefined) {
329
- transformed.beforeParse = options.beforeParse;
330
- }
223
+ const { beforeParse = () => {} } = options;
224
+ const pretendToBeVisual = Boolean(options.pretendToBeVisual);
225
+ const storageQuota = options.storageQuota === undefined ? 5000000 : Number(options.storageQuota);
331
226
 
332
- if (options.pretendToBeVisual !== undefined) {
333
- transformed.windowOptions.pretendToBeVisual = Boolean(options.pretendToBeVisual);
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
- if (options.storageQuota !== undefined) {
337
- transformed.windowOptions.storageQuota = Number(options.storageQuota);
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
- return transformed;
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, options) {
188
+ function installOwnProperties(window, { settings, documentOptions, commonForOrigin }) {
189
189
  const windowInitialized = performance.now();
190
190
 
191
191
  // ### PRIVATE DATA PROPERTIES
192
192
 
193
- window._dispatcher = options.dispatcher;
194
- window._loadSubresources = options.loadSubresources;
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
- parsingMode: options.parsingMode,
200
- contentType: options.contentType,
201
- encoding: options.encoding,
202
- cookieJar: options.cookieJar,
203
- url: options.url,
204
- lastModified: options.lastModified,
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 (options.commonForOrigin && options.commonForOrigin[documentOrigin]) {
247
- window._commonForOrigin = options.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._storageQuota
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._storageQuota
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._runScripts === "dangerously") {
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._pretendToBeVisual) {
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._virtualConsole.emit(method, ...args);
882
+ window._settings.virtualConsole.emit(method, ...args);
896
883
  };
897
884
  }
898
885
 
@@ -16,5 +16,5 @@ exports.notImplemented = (window, message) => {
16
16
  const error = new Error(`Not implemented: ${message}`);
17
17
  error.type = "not-implemented";
18
18
 
19
- window._virtualConsole.emit("jsdomError", error);
19
+ window._settings.virtualConsole.emit("jsdomError", error);
20
20
  };
@@ -7,8 +7,8 @@
7
7
  // - Removed experimental warning
8
8
  // - Use undici's exported DecoratorHandler
9
9
 
10
- const { createInflate, createGunzip, createBrotliDecompress } = require("zlib");
11
- const { pipeline } = require("stream");
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._dispatcher = defaultView ? defaultView._dispatcher : null;
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._loadSubresources || this._document._isDestroyed) {
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._dispatcher, {
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._document._defaultView._virtualConsole.emit("jsdomError", jsomError);
59
+ this._settings.virtualConsole.emit("jsdomError", jsomError);
62
60
 
63
61
  return Promise.resolve();
64
62
  };
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const { Readable } = require("stream");
2
+ const { Readable } = require("node:stream");
3
3
  const { sendStreamResponse } = require("./stream-handler");
4
4
 
5
5
  /**
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- const nodeCrypto = require("crypto");
3
+ const nodeCrypto = require("node:crypto");
4
4
  const DOMException = require("../../../generated/idl/DOMException");
5
5
  const QuotaExceededError = require("../../../generated/idl/QuotaExceededError");
6
6
 
@@ -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.#cachedCssText = null;
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
- if (shorthandPriority && priority) {
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
- if (shorthandPriority && priority) {
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 {