@nitpicker/core 0.22.0 → 0.22.1

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.
@@ -7,13 +7,21 @@
7
7
  * 1. Dynamically imports the configured plugin via {@link importModules}
8
8
  * (cached after the first task on the same worker)
9
9
  * 2. If the plugin implements `eachPage`:
10
- * - Creates a JSDOM instance from the raw HTML
10
+ * - Creates a JSDOM instance from the raw HTML, with `runScripts:
11
+ * 'outside-only'` so that plugins can use `window.eval` to run
12
+ * DOM-scoped scripts (e.g. injecting a browser-oriented library that
13
+ * needs to bind to that specific window — see
14
+ * `@nitpicker/analyze-axe`'s `injectAxe`)
11
15
  * - Calls the plugin's `eachPage` hook with the DOM window
12
16
  * - Closes the JSDOM window to free memory
13
17
  * 3. Returns the plugin result as {@link ReportPage} or `null`
14
18
  *
15
19
  * One invocation processes exactly one plugin × one page, even though
16
20
  * the worker hosting this module handles many tasks over its lifetime.
21
+ * `eachPage` plugins must not rely on `dom.window` being reachable from
22
+ * `globalThis` — nothing exposes it there — and must not cache state that
23
+ * outlives a single call, since the window backing it is closed once the
24
+ * call returns.
17
25
  * @module
18
26
  */
19
27
  import type { Plugin, ReportPage } from './types.js';
@@ -7,35 +7,25 @@
7
7
  * 1. Dynamically imports the configured plugin via {@link importModules}
8
8
  * (cached after the first task on the same worker)
9
9
  * 2. If the plugin implements `eachPage`:
10
- * - Creates a JSDOM instance from the raw HTML
10
+ * - Creates a JSDOM instance from the raw HTML, with `runScripts:
11
+ * 'outside-only'` so that plugins can use `window.eval` to run
12
+ * DOM-scoped scripts (e.g. injecting a browser-oriented library that
13
+ * needs to bind to that specific window — see
14
+ * `@nitpicker/analyze-axe`'s `injectAxe`)
11
15
  * - Calls the plugin's `eachPage` hook with the DOM window
12
16
  * - Closes the JSDOM window to free memory
13
17
  * 3. Returns the plugin result as {@link ReportPage} or `null`
14
18
  *
15
19
  * One invocation processes exactly one plugin × one page, even though
16
20
  * the worker hosting this module handles many tasks over its lifetime.
21
+ * `eachPage` plugins must not rely on `dom.window` being reachable from
22
+ * `globalThis` — nothing exposes it there — and must not cache state that
23
+ * outlives a single call, since the window backing it is closed once the
24
+ * call returns.
17
25
  * @module
18
26
  */
19
27
  import { JSDOM } from 'jsdom';
20
28
  import { importModules } from './import-modules.js';
21
- /**
22
- * Set of critical Node.js global properties that must never be overwritten
23
- * by JSDOM window properties.
24
- */
25
- const PROTECTED_GLOBALS = new Set([
26
- 'process',
27
- 'global',
28
- 'globalThis',
29
- 'console',
30
- 'Buffer',
31
- 'setTimeout',
32
- 'setInterval',
33
- 'clearTimeout',
34
- 'clearInterval',
35
- 'setImmediate',
36
- 'clearImmediate',
37
- 'queueMicrotask',
38
- ]);
39
29
  /**
40
30
  * Executes a single plugin's `eachPage` hook against a single page.
41
31
  * @template T - Column key union from the plugin's headers.
@@ -58,23 +48,6 @@ export default async function (data, urlEventBus, num, total) {
58
48
  url: url.href,
59
49
  runScripts: 'outside-only',
60
50
  });
61
- // Expose JSDOM globals so that browser-oriented libraries
62
- // (axe-core, @medv/finder, etc.) that inspect the global scope
63
- // can find `window`, `document`, `Node`, and other DOM APIs.
64
- const g = globalThis;
65
- const domGlobalKeys = [];
66
- for (const key of Object.getOwnPropertyNames(dom.window)) {
67
- if (key in g || PROTECTED_GLOBALS.has(key)) {
68
- continue;
69
- }
70
- try {
71
- g[key] = dom.window[key];
72
- domGlobalKeys.push(key);
73
- }
74
- catch {
75
- // Some window properties throw on access — skip them
76
- }
77
- }
78
51
  try {
79
52
  const report = await analyzeMod.eachPage({
80
53
  url,
@@ -90,9 +63,6 @@ export default async function (data, urlEventBus, num, total) {
90
63
  throw new Error(`[${plugin.name}] ${message}`);
91
64
  }
92
65
  finally {
93
- for (const key of domGlobalKeys) {
94
- delete g[key];
95
- }
96
66
  dom.window.close();
97
67
  }
98
68
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitpicker/core",
3
- "version": "0.22.0",
3
+ "version": "0.22.1",
4
4
  "description": "Plugin-based page analysis engine for Nitpicker",
5
5
  "author": "D-ZERO",
6
6
  "license": "Apache-2.0",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@d-zero/dealer": "1.14.0",
34
- "@d-zero/page-cluster": "0.6.3",
34
+ "@d-zero/page-cluster": "0.6.4",
35
35
  "@d-zero/shared": "0.23.0",
36
36
  "@nitpicker/crawler": "0.22.0",
37
37
  "@nitpicker/types": "0.22.0",
@@ -39,5 +39,5 @@
39
39
  "cosmiconfig": "10.0.1",
40
40
  "jsdom": "30.0.1"
41
41
  },
42
- "gitHead": "934b1714f4394effb3865d84bf8348ed74f45840"
42
+ "gitHead": "ec937f6442b1aa0ed06e68cfde2abaa21a66358c"
43
43
  }