@asamuzakjp/dom-selector 7.0.8 → 7.0.10
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/package.json +10 -6
- package/src/index.js +4 -48
- package/src/js/matcher.js +7 -4
- package/src/js/parser.js +7 -0
- package/types/index.d.ts +0 -11
package/package.json
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"./package.json": "./package.json"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
+
"@asamuzakjp/generational-cache": "^1.0.1",
|
|
27
28
|
"@asamuzakjp/nwsapi": "^2.3.9",
|
|
28
29
|
"bidi-js": "^1.0.3",
|
|
29
30
|
"css-tree": "^3.2.1",
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@types/css-tree": "^2.3.11",
|
|
34
|
-
"@types/node": "^25.
|
|
35
|
+
"@types/node": "^25.6.0",
|
|
35
36
|
"benchmark": "^2.1.4",
|
|
36
37
|
"c8": "^11.0.0",
|
|
37
38
|
"chai": "^6.2.2",
|
|
@@ -42,12 +43,13 @@
|
|
|
42
43
|
"eslint-plugin-prettier": "^5.5.5",
|
|
43
44
|
"eslint-plugin-regexp": "^3.1.0",
|
|
44
45
|
"eslint-plugin-unicorn": "^64.0.0",
|
|
45
|
-
"globals": "^17.
|
|
46
|
-
"jsdom": "^29.0.
|
|
46
|
+
"globals": "^17.5.0",
|
|
47
|
+
"jsdom": "^29.0.2",
|
|
48
|
+
"mitata": "^1.0.34",
|
|
47
49
|
"mocha": "^11.7.5",
|
|
48
50
|
"neostandard": "^0.13.0",
|
|
49
|
-
"prettier": "^3.8.
|
|
50
|
-
"sinon": "^21.
|
|
51
|
+
"prettier": "^3.8.3",
|
|
52
|
+
"sinon": "^21.1.2",
|
|
51
53
|
"typescript": "^6.0.2",
|
|
52
54
|
"wpt-runner": "^7.0.0"
|
|
53
55
|
},
|
|
@@ -60,6 +62,8 @@
|
|
|
60
62
|
},
|
|
61
63
|
"scripts": {
|
|
62
64
|
"bench": "node benchmark/bench.js",
|
|
65
|
+
"bench:cache": "node benchmark/bench-cache.js",
|
|
66
|
+
"bench:cacheMonster": "node benchmark/bench-cache-monster.js",
|
|
63
67
|
"bench:sizzle": "node benchmark/bench-sizzle.js",
|
|
64
68
|
"build": "npm run tsc && npm run lint && npm test",
|
|
65
69
|
"lint": "eslint --fix .",
|
|
@@ -71,5 +75,5 @@
|
|
|
71
75
|
"engines": {
|
|
72
76
|
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
|
73
77
|
},
|
|
74
|
-
"version": "7.0.
|
|
78
|
+
"version": "7.0.10"
|
|
75
79
|
}
|
package/src/index.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/* import */
|
|
9
|
+
import { GenerationalCache } from '@asamuzakjp/generational-cache';
|
|
9
10
|
import { Finder } from './js/finder.js';
|
|
10
11
|
import { filterSelector, getType, initNwsapi } from './js/utility.js';
|
|
11
12
|
|
|
@@ -19,51 +20,7 @@ import {
|
|
|
19
20
|
TARGET_LINEAL,
|
|
20
21
|
TARGET_SELF
|
|
21
22
|
} from './js/constant.js';
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
/* Generational Cache */
|
|
25
|
-
export class GenerationalCache {
|
|
26
|
-
constructor(max) {
|
|
27
|
-
this.max = Math.ceil(max / 2);
|
|
28
|
-
this.current = new Map();
|
|
29
|
-
this.old = new Map();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
get(key) {
|
|
33
|
-
let value = this.current.get(key);
|
|
34
|
-
if (value !== undefined) {
|
|
35
|
-
return value;
|
|
36
|
-
}
|
|
37
|
-
value = this.old.get(key);
|
|
38
|
-
if (value !== undefined) {
|
|
39
|
-
this.set(key, value);
|
|
40
|
-
return value;
|
|
41
|
-
}
|
|
42
|
-
return undefined;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
set(key, value) {
|
|
46
|
-
this.current.set(key, value);
|
|
47
|
-
if (this.current.size >= this.max) {
|
|
48
|
-
this.old = this.current;
|
|
49
|
-
this.current = new Map();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
has(key) {
|
|
54
|
-
return this.current.has(key) || this.old.has(key);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
delete(key) {
|
|
58
|
-
this.current.delete(key);
|
|
59
|
-
this.old.delete(key);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
clear() {
|
|
63
|
-
this.current.clear();
|
|
64
|
-
this.old.clear();
|
|
65
|
-
}
|
|
66
|
-
}
|
|
23
|
+
const CACHE_SIZE = 1024;
|
|
67
24
|
|
|
68
25
|
/**
|
|
69
26
|
* @typedef {object} CheckResult
|
|
@@ -89,13 +46,13 @@ export class DOMSelector {
|
|
|
89
46
|
* @param {object} [opt] - Options.
|
|
90
47
|
*/
|
|
91
48
|
constructor(window, document, opt = {}) {
|
|
92
|
-
const { idlUtils } = opt;
|
|
49
|
+
const { cacheSize, idlUtils } = opt;
|
|
93
50
|
this.#window = window;
|
|
94
51
|
this.#document = document ?? window.document;
|
|
95
52
|
this.#finder = new Finder(window);
|
|
96
53
|
this.#idlUtils = idlUtils;
|
|
97
54
|
this.#nwsapi = initNwsapi(window, document);
|
|
98
|
-
this.#cache = new GenerationalCache(
|
|
55
|
+
this.#cache = new GenerationalCache(cacheSize ?? CACHE_SIZE);
|
|
99
56
|
}
|
|
100
57
|
|
|
101
58
|
/**
|
|
@@ -104,7 +61,6 @@ export class DOMSelector {
|
|
|
104
61
|
*/
|
|
105
62
|
clear = () => {
|
|
106
63
|
this.#finder.clearResults(true);
|
|
107
|
-
// this.#cache.clear();
|
|
108
64
|
};
|
|
109
65
|
|
|
110
66
|
/**
|
package/src/js/matcher.js
CHANGED
|
@@ -443,16 +443,19 @@ export const matchAttributeSelector = (ast, node, opt = {}) => {
|
|
|
443
443
|
const { name: astIdentValue, value: astStringValue } = astValue ?? {};
|
|
444
444
|
let attrValue;
|
|
445
445
|
if (astIdentValue) {
|
|
446
|
+
// Ident values are not unescaped by css-tree, so we must unescape them
|
|
447
|
+
// (e.g. `\5c` hex escapes, `\n` character escapes).
|
|
446
448
|
if (caseInsensitive) {
|
|
447
|
-
attrValue = astIdentValue.toLowerCase()
|
|
449
|
+
attrValue = unescapeSelector(astIdentValue).toLowerCase();
|
|
448
450
|
} else {
|
|
449
|
-
attrValue = astIdentValue
|
|
451
|
+
attrValue = unescapeSelector(astIdentValue);
|
|
450
452
|
}
|
|
451
453
|
} else if (astStringValue) {
|
|
454
|
+
// String values (quoted) are already unescaped by css-tree, so use as-is.
|
|
452
455
|
if (caseInsensitive) {
|
|
453
|
-
attrValue = astStringValue.toLowerCase()
|
|
456
|
+
attrValue = astStringValue.toLowerCase();
|
|
454
457
|
} else {
|
|
455
|
-
attrValue = astStringValue
|
|
458
|
+
attrValue = astStringValue;
|
|
456
459
|
}
|
|
457
460
|
} else if (astStringValue === '') {
|
|
458
461
|
attrValue = astStringValue;
|
package/src/js/parser.js
CHANGED
|
@@ -72,6 +72,13 @@ export const unescapeSelector = (selector = '') => {
|
|
|
72
72
|
const item = arr[i];
|
|
73
73
|
if (item === '' && i === l - 1) {
|
|
74
74
|
selectorItems.push(U_FFFD);
|
|
75
|
+
} else if (item === '') {
|
|
76
|
+
// Empty segment at non-last position means \\ (escaped backslash)
|
|
77
|
+
selectorItems.push('\\');
|
|
78
|
+
i++; // skip the next segment which is the remainder after \\
|
|
79
|
+
if (i < l) {
|
|
80
|
+
selectorItems.push(arr[i]);
|
|
81
|
+
}
|
|
75
82
|
} else {
|
|
76
83
|
const hexExists = /^([\da-f]{1,6}\s?)/i.exec(item);
|
|
77
84
|
if (hexExists) {
|
package/types/index.d.ts
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
export class GenerationalCache {
|
|
2
|
-
constructor(max: any);
|
|
3
|
-
max: number;
|
|
4
|
-
current: Map<any, any>;
|
|
5
|
-
old: Map<any, any>;
|
|
6
|
-
get(key: any): any;
|
|
7
|
-
set(key: any, value: any): void;
|
|
8
|
-
has(key: any): boolean;
|
|
9
|
-
delete(key: any): void;
|
|
10
|
-
clear(): void;
|
|
11
|
-
}
|
|
12
1
|
export class DOMSelector {
|
|
13
2
|
constructor(window: Window, document: Document, opt?: object);
|
|
14
3
|
clear: () => void;
|