@asamuzakjp/dom-selector 8.1.3 → 8.1.5
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 +5 -5
- package/src/index.js +12 -32
- package/src/js/finder.js +2 -3
- package/src/js/selector.js +11 -3
package/package.json
CHANGED
|
@@ -25,20 +25,20 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@asamuzakjp/generational-cache": "^
|
|
28
|
+
"@asamuzakjp/generational-cache": "^3.0.1",
|
|
29
29
|
"bidi-js": "^1.0.3",
|
|
30
30
|
"css-tree": "^3.2.1",
|
|
31
31
|
"is-potential-custom-element-name": "^1.0.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/css-tree": "^2.3.11",
|
|
35
|
-
"@types/node": "^
|
|
35
|
+
"@types/node": "^26.0.0",
|
|
36
36
|
"c8": "^11.0.0",
|
|
37
37
|
"chai": "^6.2.2",
|
|
38
38
|
"commander": "^15.0.0",
|
|
39
39
|
"eslint": "^9.39.4",
|
|
40
40
|
"eslint-config-prettier": "^10.1.8",
|
|
41
|
-
"eslint-plugin-jsdoc": "^63.0.
|
|
41
|
+
"eslint-plugin-jsdoc": "^63.0.6",
|
|
42
42
|
"eslint-plugin-prettier": "^5.5.6",
|
|
43
43
|
"eslint-plugin-regexp": "^3.1.0",
|
|
44
44
|
"eslint-plugin-unicorn": "^65.0.1",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"bench:ps-has": "node --expose-gc benchmark/bench-has.js",
|
|
77
77
|
"bench:ps-nth": "node --expose-gc benchmark/bench-nth-child.js && node --expose-gc benchmark/bench-nth-of-type.js",
|
|
78
78
|
"bench:ps-traverse": "node --expose-gc benchmark/bench-dir.js && node --expose-gc benchmark/bench-lang.js",
|
|
79
|
-
"bench:
|
|
79
|
+
"bench:tl": "node --expose-gc benchmark/bench-testing-library.js",
|
|
80
80
|
"bench:universal": "node --expose-gc benchmark/bench-universal.js",
|
|
81
81
|
"build": "npm run tsc && npm run lint && npm test",
|
|
82
82
|
"lint": "eslint --fix .",
|
|
@@ -88,5 +88,5 @@
|
|
|
88
88
|
"engines": {
|
|
89
89
|
"node": "^22.13.0 || >=24.0.0"
|
|
90
90
|
},
|
|
91
|
-
"version": "8.1.
|
|
91
|
+
"version": "8.1.5"
|
|
92
92
|
}
|
package/src/index.js
CHANGED
|
@@ -19,11 +19,8 @@ import { collectAllDescendants, getType } from './js/utility.js';
|
|
|
19
19
|
|
|
20
20
|
/* constants */
|
|
21
21
|
import {
|
|
22
|
-
ATTR_TYPE,
|
|
23
|
-
COMBO,
|
|
24
22
|
DOCUMENT_NODE,
|
|
25
23
|
ELEMENT_NODE,
|
|
26
|
-
TAG_TYPE_WO_UNIVERSAL,
|
|
27
24
|
TARGET_ALL,
|
|
28
25
|
TARGET_FIRST,
|
|
29
26
|
TARGET_LINEAL,
|
|
@@ -33,9 +30,6 @@ const CACHE_SIZE = 2048;
|
|
|
33
30
|
|
|
34
31
|
/* regexp */
|
|
35
32
|
const REG_SELECTOR = /[[\]():\\"'`]/;
|
|
36
|
-
const REG_TEST_LIB = new RegExp(
|
|
37
|
-
`^(?:${TAG_TYPE_WO_UNIVERSAL}|[*]?${ATTR_TYPE}(?:\\s*,\\s*${TAG_TYPE_WO_UNIVERSAL}${COMBO}${TAG_TYPE_WO_UNIVERSAL})?)$`
|
|
38
|
-
);
|
|
39
33
|
const REG_UNIVERSAL = /^(?:\*\|)?\*$/;
|
|
40
34
|
|
|
41
35
|
/**
|
|
@@ -351,13 +345,11 @@ export class DOMSelector {
|
|
|
351
345
|
if (REG_UNIVERSAL.test(selector)) {
|
|
352
346
|
return node.firstElementChild;
|
|
353
347
|
}
|
|
348
|
+
// Only enabled when debugging.
|
|
354
349
|
/*
|
|
355
350
|
const document =
|
|
356
351
|
node.nodeType === DOCUMENT_NODE ? node : node.ownerDocument;
|
|
357
|
-
if (
|
|
358
|
-
(node === this.#document || REG_TEST_LIB.test(selector)) &&
|
|
359
|
-
this.#canUseNwsapi(document)
|
|
360
|
-
) {
|
|
352
|
+
if (node === this.#document && this.#canUseNwsapi(document)) {
|
|
361
353
|
const cacheKey = `querySelector_${selector}`;
|
|
362
354
|
let filterMatches = this.#cache.get(cacheKey);
|
|
363
355
|
if (filterMatches === undefined) {
|
|
@@ -405,29 +397,17 @@ export class DOMSelector {
|
|
|
405
397
|
return collectAllDescendants(node, document);
|
|
406
398
|
}
|
|
407
399
|
if (this.#canUseNwsapi(document)) {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
isTestLib = REG_TEST_LIB.test(selector);
|
|
414
|
-
this.#cache.set(testCacheKey, isTestLib);
|
|
415
|
-
}
|
|
416
|
-
routeToNwsapi = isTestLib;
|
|
400
|
+
const cacheKey = `querySelectorAll_${selector}`;
|
|
401
|
+
let filterMatches = this.#cache.get(cacheKey);
|
|
402
|
+
if (filterMatches === undefined) {
|
|
403
|
+
filterMatches = filterSelector(selector, TARGET_ALL);
|
|
404
|
+
this.#cache.set(cacheKey, filterMatches);
|
|
417
405
|
}
|
|
418
|
-
if (
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
this.#cache.set(cacheKey, filterMatches);
|
|
424
|
-
}
|
|
425
|
-
if (filterMatches) {
|
|
426
|
-
try {
|
|
427
|
-
return this.#nwsapi.select(selector, this.#wrapNode(node));
|
|
428
|
-
} catch (e) {
|
|
429
|
-
// fall through
|
|
430
|
-
}
|
|
406
|
+
if (filterMatches) {
|
|
407
|
+
try {
|
|
408
|
+
return this.#nwsapi.select(selector, this.#wrapNode(node));
|
|
409
|
+
} catch (e) {
|
|
410
|
+
// fall through
|
|
431
411
|
}
|
|
432
412
|
}
|
|
433
413
|
}
|
package/src/js/finder.js
CHANGED
|
@@ -3123,8 +3123,7 @@ export class Finder {
|
|
|
3123
3123
|
}
|
|
3124
3124
|
const [[...branches], collectedNodes] = collection;
|
|
3125
3125
|
const l = branches.length;
|
|
3126
|
-
let sort =
|
|
3127
|
-
l > 1 && targetType === TARGET_ALL && this.#selector.includes(':scope');
|
|
3126
|
+
let sort = l > 1 && targetType === TARGET_ALL;
|
|
3128
3127
|
let nodes = new Set();
|
|
3129
3128
|
for (let i = 0; i < l; i++) {
|
|
3130
3129
|
const { branch, dir, find } = branches[i];
|
|
@@ -3161,8 +3160,8 @@ export class Finder {
|
|
|
3161
3160
|
nodes.add(entryNodes[0]);
|
|
3162
3161
|
}
|
|
3163
3162
|
}
|
|
3164
|
-
// Handle complex selectors.
|
|
3165
3163
|
} else {
|
|
3164
|
+
// Handle complex selectors.
|
|
3166
3165
|
if (targetType === TARGET_ALL) {
|
|
3167
3166
|
const newNodes = this._processComplexBranchAll(
|
|
3168
3167
|
branch,
|
package/src/js/selector.js
CHANGED
|
@@ -8,6 +8,7 @@ import { generateException } from './utility.js';
|
|
|
8
8
|
|
|
9
9
|
/* constants */
|
|
10
10
|
import {
|
|
11
|
+
ATTR_TYPE,
|
|
11
12
|
COMBINATOR,
|
|
12
13
|
COMBO,
|
|
13
14
|
COMPOUND_I,
|
|
@@ -21,8 +22,8 @@ import {
|
|
|
21
22
|
PS_CLASS_SELECTOR,
|
|
22
23
|
PS_ELEMENT_SELECTOR,
|
|
23
24
|
SELECTOR,
|
|
24
|
-
SUB_TYPE,
|
|
25
25
|
SYNTAX_ERR,
|
|
26
|
+
TAG_TYPE_WO_UNIVERSAL,
|
|
26
27
|
TARGET_ALL
|
|
27
28
|
} from './constant.js';
|
|
28
29
|
|
|
@@ -30,7 +31,7 @@ import {
|
|
|
30
31
|
const REG_EXCLUDE_BASIC =
|
|
31
32
|
/[|\\]|::|[^\u0021-\u007F\s]|\[\s*[\w$*=^|~-]+(?:(?:"[\w$*=^|~\s'-]+"|'[\w$*=^|~\s"-]+')?(?:\s+[\w$*=^|~-]+)+|"[^"\]]{1,255}|'[^'\]]{1,255})\s*\]|:(?:is|where)\(\s*\)/;
|
|
32
33
|
const REG_EXCLUDE_QSA = new RegExp(
|
|
33
|
-
`(?:^(?:[A-Z]|\\.)[\\w-]
|
|
34
|
+
`(?:^(?:[A-Z]|\\.)[\\w-]*$|${COMPOUND_I}${COMBO}${COMPOUND_I})`,
|
|
34
35
|
'i'
|
|
35
36
|
);
|
|
36
37
|
const REG_COMPLEX = new RegExp(`${COMPOUND_I}${COMBO}${COMPOUND_I}`, 'i');
|
|
@@ -51,6 +52,9 @@ const REG_CLASS = /\.(\D[^#.*]+)/g;
|
|
|
51
52
|
const REG_TAG = /^([^#.]+)/;
|
|
52
53
|
const REG_INVALID_SYNTAX =
|
|
53
54
|
/[+~>]\s*[+~>]|^\s*[+~>]|[+~>]\s*$|^\s*,|,\s*,|,\s*$/;
|
|
55
|
+
const REG_TEST_LIB = new RegExp(
|
|
56
|
+
`^(?:[*]?${ATTR_TYPE}(?:\\s*,\\s*${TAG_TYPE_WO_UNIVERSAL}${COMBO}${TAG_TYPE_WO_UNIVERSAL})?)$`
|
|
57
|
+
);
|
|
54
58
|
|
|
55
59
|
/**
|
|
56
60
|
* Find a nested :has() pseudo-class.
|
|
@@ -278,7 +282,11 @@ export const filterSelector = (selector, target) => {
|
|
|
278
282
|
return false;
|
|
279
283
|
}
|
|
280
284
|
// Target-specific early exits.
|
|
281
|
-
if (
|
|
285
|
+
if (
|
|
286
|
+
target === TARGET_ALL &&
|
|
287
|
+
REG_EXCLUDE_QSA.test(selector) &&
|
|
288
|
+
!REG_TEST_LIB.test(selector)
|
|
289
|
+
) {
|
|
282
290
|
return false;
|
|
283
291
|
}
|
|
284
292
|
// Exclude various complex or unsupported selectors early.
|