@miaskiewicz/turbo-dom 0.1.3 → 0.1.4
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 +7 -1
- package/package.json +5 -3
- package/src/environment/install.mjs +37 -10
- package/src/environment/jest.cjs +1 -1
- package/src/environment/vitest.mjs +16 -11
- package/src/runtime/dom.mjs +12 -0
- package/turbo-dom-parser.win32-x64-msvc.node +0 -0
package/README.md
CHANGED
|
@@ -25,14 +25,20 @@ npm install -D @miaskiewicz/turbo-dom
|
|
|
25
25
|
```ts
|
|
26
26
|
// vitest.config.ts
|
|
27
27
|
import { defineConfig } from 'vitest/config';
|
|
28
|
+
import { createRequire } from 'node:module';
|
|
29
|
+
|
|
30
|
+
const envPath = createRequire(import.meta.url).resolve('@miaskiewicz/turbo-dom/environment/vitest');
|
|
28
31
|
|
|
29
32
|
export default defineConfig({
|
|
30
33
|
test: {
|
|
31
|
-
environment:
|
|
34
|
+
environment: envPath, // vitest resolves a bare name only for `vitest-environment-*`
|
|
35
|
+
// packages, so a scoped package is referenced by file path
|
|
32
36
|
},
|
|
33
37
|
});
|
|
34
38
|
```
|
|
35
39
|
|
|
40
|
+
Works on vitest 1–4.
|
|
41
|
+
|
|
36
42
|
### jest
|
|
37
43
|
|
|
38
44
|
```js
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@miaskiewicz/turbo-dom",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Faster, more spec-correct DOM for test runners — native html5ever (Rust/WASM) parser + lazy copy-on-write DOM. A drop-in-style alternative to jsdom/happy-dom for vitest & jest.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -64,7 +64,8 @@
|
|
|
64
64
|
"bench:suite": "node bench/suite.mjs",
|
|
65
65
|
"bench:wasm": "node bench/wasm.mjs",
|
|
66
66
|
"bench:all": "node bench/parse.mjs && node bench/construct.mjs && node bench/suite.mjs && node bench/wasm.mjs",
|
|
67
|
-
"prepublishOnly": "napi build --platform --release"
|
|
67
|
+
"prepublishOnly": "napi build --platform --release",
|
|
68
|
+
"test:vitest": "vitest run -c test-vitest/vitest.config.mjs"
|
|
68
69
|
},
|
|
69
70
|
"keywords": [
|
|
70
71
|
"dom",
|
|
@@ -116,6 +117,7 @@
|
|
|
116
117
|
"jsdom": "^29.1.1",
|
|
117
118
|
"parse5": "^8.0.1",
|
|
118
119
|
"react": "^19.2.7",
|
|
119
|
-
"react-dom": "^19.2.7"
|
|
120
|
+
"react-dom": "^19.2.7",
|
|
121
|
+
"vitest": "^4.1.8"
|
|
120
122
|
}
|
|
121
123
|
}
|
|
@@ -6,29 +6,56 @@ import { createEnvironment } from '../runtime/index.mjs';
|
|
|
6
6
|
|
|
7
7
|
const DEFAULT_HTML = '<!doctype html><html><head></head><body></body></html>';
|
|
8
8
|
|
|
9
|
-
// Globals that point at the window itself.
|
|
10
|
-
|
|
9
|
+
// Globals that point at the window itself. Deliberately NOT `globalThis`/`global`
|
|
10
|
+
// — redefining those breaks test runners (vitest builds its module-runner vm
|
|
11
|
+
// primitives off globalThis; pointing it at our window Proxy hides Symbol et al).
|
|
12
|
+
const SELF_KEYS = ['window', 'self', 'parent', 'top', 'frames'];
|
|
11
13
|
|
|
12
14
|
export function installGlobals(target, { html = DEFAULT_HTML, url } = {}) {
|
|
13
15
|
const env = createEnvironment(html, url ? { url } : {});
|
|
14
16
|
const { window } = env;
|
|
15
17
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
+
const installed = []; // keys we defined
|
|
19
|
+
const originals = new Map(); // prior descriptors to restore on teardown
|
|
20
|
+
|
|
21
|
+
const define = (name, descriptor) => {
|
|
22
|
+
const prior = Object.getOwnPropertyDescriptor(target, name);
|
|
23
|
+
if (prior) originals.set(name, prior);
|
|
24
|
+
Object.defineProperty(target, name, descriptor);
|
|
25
|
+
installed.push(name);
|
|
18
26
|
};
|
|
19
27
|
|
|
20
28
|
// window self-references
|
|
21
|
-
for (const k of SELF_KEYS)
|
|
29
|
+
for (const k of SELF_KEYS) {
|
|
30
|
+
define(k, {
|
|
31
|
+
configurable: true,
|
|
32
|
+
get: () => window,
|
|
33
|
+
set(v) { Object.defineProperty(target, k, { configurable: true, writable: true, value: v }); },
|
|
34
|
+
});
|
|
35
|
+
}
|
|
22
36
|
// document is eager + universal
|
|
23
|
-
|
|
37
|
+
define('document', { configurable: true, writable: true, enumerable: true, value: env.document });
|
|
24
38
|
|
|
25
39
|
// every other window global → lazy getter (materializes + traces on first read)
|
|
26
40
|
for (const name of env.globalKeys) {
|
|
27
41
|
if (name === 'document' || SELF_KEYS.includes(name)) continue;
|
|
28
|
-
define(name,
|
|
42
|
+
define(name, {
|
|
43
|
+
configurable: true,
|
|
44
|
+
get: () => window[name],
|
|
45
|
+
set(v) { Object.defineProperty(target, name, { configurable: true, writable: true, value: v }); },
|
|
46
|
+
});
|
|
29
47
|
}
|
|
30
48
|
|
|
31
|
-
// handy escape
|
|
32
|
-
|
|
33
|
-
|
|
49
|
+
// handy escape hatch
|
|
50
|
+
define('__turboDom', { configurable: true, writable: true, value: env });
|
|
51
|
+
|
|
52
|
+
const teardown = () => {
|
|
53
|
+
for (const name of installed) {
|
|
54
|
+
delete target[name];
|
|
55
|
+
const prior = originals.get(name);
|
|
56
|
+
if (prior) Object.defineProperty(target, name, prior);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return { env, window, teardown };
|
|
34
61
|
}
|
package/src/environment/jest.cjs
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
//
|
|
6
6
|
// or point directly at this file:
|
|
7
7
|
//
|
|
8
|
-
// testEnvironment: './node_modules/@miaskiewicz/turbo-dom/
|
|
8
|
+
// testEnvironment: './node_modules/@miaskiewicz/turbo-dom/src/environment/jest.cjs'
|
|
9
9
|
//
|
|
10
10
|
// Per-file / project options:
|
|
11
11
|
// testEnvironmentOptions: { html: '<!doctype html>...', url: 'http://localhost/' }
|
|
@@ -1,31 +1,36 @@
|
|
|
1
|
-
// Vitest environment adapter. Use in vitest config:
|
|
1
|
+
// Vitest environment adapter (vitest 1–4). Use in vitest config:
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
// export default defineConfig({ test: { environment:
|
|
3
|
+
// import TurboDom from '@miaskiewicz/turbo-dom/environment/vitest';
|
|
4
|
+
// export default defineConfig({ test: { environment: TurboDom } });
|
|
5
5
|
//
|
|
6
|
-
//
|
|
7
|
-
// or point directly at this file:
|
|
6
|
+
// or point at the file path:
|
|
8
7
|
//
|
|
9
|
-
// test: { environment: './node_modules/@miaskiewicz/turbo-dom/
|
|
8
|
+
// test: { environment: './node_modules/@miaskiewicz/turbo-dom/src/environment/vitest.mjs' }
|
|
9
|
+
//
|
|
10
|
+
// (vitest's bare-name `environment: 'name'` only works for a package literally
|
|
11
|
+
// named `vitest-environment-<name>`; use the object or path form for a scoped pkg.)
|
|
10
12
|
//
|
|
11
13
|
// Per-file options via environmentOptions:
|
|
12
14
|
// test: { environmentOptions: { turboDom: { html: '<!doctype html>...', url: 'http://localhost/' } } }
|
|
13
15
|
|
|
14
16
|
import { installGlobals } from './install.mjs';
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
const environment = {
|
|
17
19
|
name: 'turbo-dom',
|
|
18
|
-
//
|
|
20
|
+
// vitest 3/4 read `viteEnvironment`; older versions read `transformMode`.
|
|
21
|
+
viteEnvironment: 'client',
|
|
19
22
|
transformMode: 'web',
|
|
20
23
|
|
|
21
24
|
setup(global, options) {
|
|
22
25
|
const opts = (options && options.turboDom) || {};
|
|
23
|
-
const env = installGlobals(global, opts);
|
|
26
|
+
const { env, teardown } = installGlobals(global, opts);
|
|
24
27
|
return {
|
|
25
|
-
teardown() {
|
|
26
|
-
|
|
28
|
+
teardown(g) {
|
|
29
|
+
teardown();
|
|
27
30
|
env.reset();
|
|
28
31
|
},
|
|
29
32
|
};
|
|
30
33
|
},
|
|
31
34
|
};
|
|
35
|
+
|
|
36
|
+
export default environment;
|
package/src/runtime/dom.mjs
CHANGED
|
@@ -193,6 +193,18 @@ export class Node extends EventTarget {
|
|
|
193
193
|
get __owner() { return null; }
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
// nodeType + document-position constants on the prototype, so `node.TEXT_NODE`
|
|
197
|
+
// works on instances (dom-accessibility-api and others read them off the node).
|
|
198
|
+
Object.assign(Node.prototype, {
|
|
199
|
+
ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4,
|
|
200
|
+
ENTITY_REFERENCE_NODE: 5, ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7,
|
|
201
|
+
COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10,
|
|
202
|
+
DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12,
|
|
203
|
+
DOCUMENT_POSITION_DISCONNECTED: 1, DOCUMENT_POSITION_PRECEDING: 2,
|
|
204
|
+
DOCUMENT_POSITION_FOLLOWING: 4, DOCUMENT_POSITION_CONTAINS: 8,
|
|
205
|
+
DOCUMENT_POSITION_CONTAINED_BY: 16, DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 32,
|
|
206
|
+
});
|
|
207
|
+
|
|
196
208
|
// ----------------------------------------------------- CharacterData ----
|
|
197
209
|
class CharacterData extends Node {
|
|
198
210
|
constructor(ownerDocument, data) { super(ownerDocument); this._data = data ?? ''; }
|
|
Binary file
|