@asamuzakjp/dom-selector 0.19.4 → 0.19.6

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 CHANGED
@@ -21,26 +21,26 @@
21
21
  "dependencies": {
22
22
  "css-tree": "^2.3.1",
23
23
  "is-potential-custom-element-name": "^1.0.1",
24
- "xpath": "^0.0.32"
24
+ "xpath": "^0.0.33"
25
25
  },
26
26
  "devDependencies": {
27
- "@types/css-tree": "^2.3.1",
27
+ "@types/css-tree": "^2.3.2",
28
28
  "benchmark": "^2.1.4",
29
- "c8": "^8.0.0",
30
- "chai": "^4.3.7",
29
+ "c8": "^8.0.1",
30
+ "chai": "^4.3.8",
31
31
  "css2xpath": "^0.0.3",
32
- "eslint": "^8.44.0",
32
+ "eslint": "^8.50.0",
33
33
  "eslint-config-standard": "^17.1.0",
34
- "eslint-plugin-import": "^2.27.5",
35
- "eslint-plugin-jsdoc": "^46.4.3",
34
+ "eslint-plugin-import": "^2.28.1",
35
+ "eslint-plugin-jsdoc": "^46.8.2",
36
36
  "eslint-plugin-regexp": "^1.15.0",
37
- "eslint-plugin-unicorn": "^47.0.0",
37
+ "eslint-plugin-unicorn": "^48.0.1",
38
38
  "jsdom": "^22.1.0",
39
- "linkedom": "^0.14.26",
39
+ "linkedom": "^0.15.3",
40
40
  "mocha": "^10.2.0",
41
41
  "nwsapi": "^2.2.7",
42
- "sinon": "^15.2.0",
43
- "typescript": "^5.1.6"
42
+ "sinon": "^16.0.0",
43
+ "typescript": "^5.2.2"
44
44
  },
45
45
  "scripts": {
46
46
  "bench": "node benchmark/benchmark.js",
@@ -49,5 +49,5 @@
49
49
  "test": "c8 --reporter=text mocha --exit test/**/*.test.js",
50
50
  "tsc": "npx tsc"
51
51
  },
52
- "version": "0.19.4"
52
+ "version": "0.19.6"
53
53
  }
@@ -8,6 +8,7 @@ export const CLASS_SELECTOR = 'ClassSelector';
8
8
  export const COMBINATOR = 'Combinator';
9
9
  export const ID_SELECTOR = 'IdSelector';
10
10
  export const IDENTIFIER = 'Identifier';
11
+ export const NOT_SUPPORTED_ERR = 'NotSupportedError';
11
12
  export const NTH = 'Nth';
12
13
  export const PSEUDO_CLASS_SELECTOR = 'PseudoClassSelector';
13
14
  export const PSEUDO_ELEMENT_SELECTOR = 'PseudoElementSelector';
@@ -15,4 +16,5 @@ export const RAW = 'Raw';
15
16
  export const SELECTOR = 'Selector';
16
17
  export const SELECTOR_LIST = 'SelectorList';
17
18
  export const STRING = 'String';
19
+ export const SYNTAX_ERR = 'SyntaxError';
18
20
  export const TYPE_SELECTOR = 'TypeSelector';
package/src/js/matcher.js CHANGED
@@ -10,7 +10,8 @@ import { generateCSS, parseSelector, walkAST } from './parser.js';
10
10
  /* constants */
11
11
  import {
12
12
  ATTRIBUTE_SELECTOR, CLASS_SELECTOR, COMBINATOR, ID_SELECTOR,
13
- PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, TYPE_SELECTOR
13
+ NOT_SUPPORTED_ERR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR,
14
+ SYNTAX_ERR, TYPE_SELECTOR
14
15
  } from './constant.js';
15
16
  const BIT_ATTRIBUTE_SELECTOR = 16;
16
17
  const BIT_CLASS_SELECTOR = 2;
@@ -26,6 +27,10 @@ const DOCUMENT_POSITION_PRECEDING = 2;
26
27
  const ELEMENT_NODE = 1;
27
28
  const FILTER_SHOW_ELEMENT = 1;
28
29
  const TEXT_NODE = 3;
30
+ const TYPE_ALL = 'all';
31
+ const TYPE_FIRST = 'first';
32
+ const TYPE_LINEAL = 'lineal';
33
+ const TYPE_SELF = 'self';
29
34
 
30
35
  /* regexp */
31
36
  const DIR_VALUE = /^(?:auto|ltr|rtl)$/;
@@ -48,7 +53,9 @@ const WHITESPACE = /^[\n\r\f]/;
48
53
  export const isContentEditable = (node = {}) => {
49
54
  let res;
50
55
  if (node.nodeType === ELEMENT_NODE) {
51
- if (node.ownerDocument.designMode === 'on') {
56
+ if (typeof node.isContentEditable === 'boolean') {
57
+ res = node.isContentEditable;
58
+ } else if (node.ownerDocument.designMode === 'on') {
52
59
  res = true;
53
60
  } else if (node.hasAttribute('contenteditable')) {
54
61
  const attr = node.getAttribute('contenteditable');
@@ -176,14 +183,14 @@ export const parseASTName = (name, node) => {
176
183
  [astPrefix, astNodeName] = name.split('|');
177
184
  if (astPrefix && astPrefix !== '*' &&
178
185
  node && !isNamespaceDeclared(astPrefix, node)) {
179
- throw new DOMException(`invalid selector ${name}`, 'SyntaxError');
186
+ throw new DOMException(`invalid selector ${name}`, SYNTAX_ERR);
180
187
  }
181
188
  } else {
182
189
  astPrefix = '*';
183
190
  astNodeName = name;
184
191
  }
185
192
  } else {
186
- throw new DOMException(`invalid selector ${name}`, 'SyntaxError');
193
+ throw new DOMException(`invalid selector ${name}`, SYNTAX_ERR);
187
194
  }
188
195
  return {
189
196
  astNodeName,
@@ -249,7 +256,7 @@ export class Matcher {
249
256
  this.#selector = selector;
250
257
  this.#sort = !!sort;
251
258
  this.#warn = !!warn;
252
- this._prepare(selector);
259
+ [this.#list, this.#matrix] = this._prepare(selector);
253
260
  }
254
261
 
255
262
  /**
@@ -259,7 +266,7 @@ export class Matcher {
259
266
  * @returns {void}
260
267
  */
261
268
  _onError(e) {
262
- if (e instanceof DOMException && e.name === 'NotSupportedError') {
269
+ if (e instanceof DOMException && e.name === NOT_SUPPORTED_ERR) {
263
270
  if (this.#warn) {
264
271
  console.warn(e.message);
265
272
  }
@@ -354,8 +361,8 @@ export class Matcher {
354
361
  _prepare(selector = this.#selector) {
355
362
  const ast = parseSelector(selector);
356
363
  const branches = walkAST(ast).values();
357
- this.#list = [];
358
- this.#matrix = [];
364
+ const list = [];
365
+ const matrix = [];
359
366
  let i = 0;
360
367
  for (const branchItem of branches) {
361
368
  const [...items] = branchItem;
@@ -368,7 +375,7 @@ export class Matcher {
368
375
  const [nextItem] = items;
369
376
  if (nextItem.type === COMBINATOR) {
370
377
  const msg = `invalid combinator, ${item.name}${nextItem.name}`;
371
- throw new DOMException(msg, 'SyntaxError');
378
+ throw new DOMException(msg, SYNTAX_ERR);
372
379
  }
373
380
  branch.push({
374
381
  combo: item,
@@ -391,19 +398,19 @@ export class Matcher {
391
398
  }
392
399
  }
393
400
  const branchLen = branch.length;
394
- this.#matrix[i] = [];
401
+ matrix[i] = [];
395
402
  for (let j = 0; j < branchLen; j++) {
396
- this.#matrix[i][j] = new Set();
403
+ matrix[i][j] = new Set();
397
404
  }
398
- this.#list.push({
405
+ list.push({
399
406
  branch,
400
407
  skip: false
401
408
  });
402
409
  i++;
403
410
  }
404
411
  return [
405
- this.#list,
406
- this.#matrix
412
+ list,
413
+ matrix
407
414
  ];
408
415
  }
409
416
 
@@ -655,11 +662,11 @@ export class Matcher {
655
662
  (!inputType ||
656
663
  /^(?:(?:emai|te|ur)l|search|text)$/.test(inputType))))) {
657
664
  throw new DOMException('Unsupported pseudo-class :dir()',
658
- 'NotSupportedError');
665
+ NOT_SUPPORTED_ERR);
659
666
  // FIXME:
660
667
  } else if (nodeDir === 'auto' || (localName === 'bdi' && !nodeDir)) {
661
668
  throw new DOMException('Unsupported pseudo-class :dir()',
662
- 'NotSupportedError');
669
+ NOT_SUPPORTED_ERR);
663
670
  } else if (!nodeDir) {
664
671
  let parent = node.parentNode;
665
672
  while (parent) {
@@ -863,10 +870,10 @@ export class Matcher {
863
870
  case 'nth-col':
864
871
  case 'nth-last-col':
865
872
  throw new DOMException(`Unsupported pseudo-class :${astName}()`,
866
- 'NotSupportedError');
873
+ NOT_SUPPORTED_ERR);
867
874
  default:
868
875
  throw new DOMException(`Unknown pseudo-class :${astName}()`,
869
- 'SyntaxError');
876
+ SYNTAX_ERR);
870
877
  }
871
878
  }
872
879
  } else {
@@ -1172,7 +1179,7 @@ export class Matcher {
1172
1179
  // FIXME:
1173
1180
  if (isMultiple) {
1174
1181
  throw new DOMException(`Unsupported pseudo-class :${astName}`,
1175
- 'NotSupportedError');
1182
+ NOT_SUPPORTED_ERR);
1176
1183
  } else {
1177
1184
  const firstOpt = parentNode.firstElementChild;
1178
1185
  const defaultOpt = new Set();
@@ -1382,7 +1389,7 @@ export class Matcher {
1382
1389
  case 'first-letter':
1383
1390
  case 'first-line': {
1384
1391
  throw new DOMException(`Unsupported pseudo-element ::${astName}`,
1385
- 'NotSupportedError');
1392
+ NOT_SUPPORTED_ERR);
1386
1393
  }
1387
1394
  case 'active':
1388
1395
  case 'autofill':
@@ -1406,11 +1413,11 @@ export class Matcher {
1406
1413
  case 'volume-locked':
1407
1414
  case '-webkit-autofill': {
1408
1415
  throw new DOMException(`Unsupported pseudo-class :${astName}`,
1409
- 'NotSupportedError');
1416
+ NOT_SUPPORTED_ERR);
1410
1417
  }
1411
1418
  default: {
1412
1419
  throw new DOMException(`Unknown pseudo-class :${astName}`,
1413
- 'SyntaxError');
1420
+ SYNTAX_ERR);
1414
1421
  }
1415
1422
  }
1416
1423
  }
@@ -1428,7 +1435,7 @@ export class Matcher {
1428
1435
  flags: astFlags, matcher: astMatcher, name: astName, value: astValue
1429
1436
  } = ast;
1430
1437
  if (typeof astFlags === 'string' && !/^[is]$/i.test(astFlags)) {
1431
- throw new DOMException('invalid attribute selector', 'SyntaxError');
1438
+ throw new DOMException('invalid attribute selector', SYNTAX_ERR);
1432
1439
  }
1433
1440
  const { attributes } = node;
1434
1441
  let res;
@@ -1650,13 +1657,15 @@ export class Matcher {
1650
1657
 
1651
1658
  /**
1652
1659
  * match pseudo-element selector
1653
- * NOTE: throws DOMException
1654
1660
  * @param {object} ast - AST
1655
1661
  * @param {object} node - Element node
1662
+ * @throws {DOMException}
1656
1663
  * @returns {void}
1657
1664
  */
1658
1665
  _matchPseudoElementSelector(ast, node) {
1659
1666
  const astName = unescapeSelector(ast.name);
1667
+ let msg;
1668
+ let type;
1660
1669
  switch (astName) {
1661
1670
  case 'after':
1662
1671
  case 'backdrop':
@@ -1672,14 +1681,16 @@ export class Matcher {
1672
1681
  case 'selection':
1673
1682
  case 'slotted':
1674
1683
  case 'target-text': {
1675
- throw new DOMException(`Unsupported pseudo-element ::${astName}`,
1676
- 'NotSupportedError');
1684
+ msg = `Unsupported pseudo-element ::${astName}`;
1685
+ type = NOT_SUPPORTED_ERR;
1686
+ break;
1677
1687
  }
1678
1688
  default: {
1679
- throw new DOMException(`Unknown pseudo-element ::${astName}`,
1680
- 'SyntaxError');
1689
+ msg = `Unknown pseudo-element ::${astName}`;
1690
+ type = SYNTAX_ERR;
1681
1691
  }
1682
1692
  }
1693
+ throw new DOMException(msg, type);
1683
1694
  }
1684
1695
 
1685
1696
  /**
@@ -1972,10 +1983,10 @@ export class Matcher {
1972
1983
  /**
1973
1984
  * find nodes
1974
1985
  * @param {object} twig - twig
1975
- * @param {string} range - target range
1986
+ * @param {string} targetType - target type
1976
1987
  * @returns {object} - result
1977
1988
  */
1978
- _findNodes(twig, range) {
1989
+ _findNodes(twig, targetType) {
1979
1990
  const { leaves: [leaf, ...items] } = twig;
1980
1991
  const len = items.length;
1981
1992
  const { type: leafType } = leaf;
@@ -1986,12 +1997,12 @@ export class Matcher {
1986
1997
  switch (leafType) {
1987
1998
  case ID_SELECTOR: {
1988
1999
  let node;
1989
- if (range === 'self') {
2000
+ if (targetType === TYPE_SELF) {
1990
2001
  const bool = this._matchLeaves([leaf], this.#node);
1991
2002
  if (bool) {
1992
2003
  node = this.#node;
1993
2004
  }
1994
- } else if (range === 'lineal') {
2005
+ } else if (targetType === TYPE_LINEAL) {
1995
2006
  let refNode = this.#node;
1996
2007
  while (refNode) {
1997
2008
  const bool = this._matchLeaves([leaf], refNode);
@@ -2020,12 +2031,12 @@ export class Matcher {
2020
2031
  }
2021
2032
  case CLASS_SELECTOR: {
2022
2033
  const arr = [];
2023
- if (range === 'self') {
2034
+ if (targetType === TYPE_SELF) {
2024
2035
  if (this.#node.nodeType === ELEMENT_NODE &&
2025
2036
  this.#node.classList.contains(leafName)) {
2026
2037
  arr.push(this.#node);
2027
2038
  }
2028
- } else if (range === 'lineal') {
2039
+ } else if (targetType === TYPE_LINEAL) {
2029
2040
  let refNode = this.#node;
2030
2041
  while (refNode) {
2031
2042
  if (refNode.nodeType === ELEMENT_NODE) {
@@ -2038,15 +2049,13 @@ export class Matcher {
2038
2049
  }
2039
2050
  }
2040
2051
  } else if (root.nodeType === DOCUMENT_FRAGMENT_NODE) {
2041
- const walker = document.createTreeWalker(root, FILTER_SHOW_ELEMENT);
2042
- let nextNode = walker.firstChild();
2043
- while (nextNode) {
2044
- if (nextNode.classList.contains(leafName)) {
2045
- arr.push(nextNode);
2052
+ const iterator = [...root.children].values();
2053
+ for (const node of iterator) {
2054
+ if (node.classList.contains(leafName)) {
2055
+ arr.push(node);
2046
2056
  }
2047
- const a = [...nextNode.getElementsByClassName(leafName)];
2057
+ const a = [...node.getElementsByClassName(leafName)];
2048
2058
  arr.push(...a);
2049
- nextNode = walker.nextSibling();
2050
2059
  }
2051
2060
  } else {
2052
2061
  if (root.nodeType === ELEMENT_NODE &&
@@ -2072,64 +2081,62 @@ export class Matcher {
2072
2081
  break;
2073
2082
  }
2074
2083
  case TYPE_SELECTOR: {
2075
- if (document.contentType !== 'text/html' || /[*|]/.test(leafName)) {
2084
+ const arr = [];
2085
+ if (targetType === TYPE_SELF) {
2086
+ const bool = this.#node.nodeType === ELEMENT_NODE &&
2087
+ this._matchLeaves([leaf], this.#node);
2088
+ if (bool) {
2089
+ arr.push(this.#node);
2090
+ }
2091
+ } else if (targetType === TYPE_LINEAL) {
2092
+ let refNode = this.#node;
2093
+ while (refNode) {
2094
+ if (refNode.nodeType === ELEMENT_NODE) {
2095
+ const bool = this._matchLeaves([leaf], refNode);
2096
+ if (bool) {
2097
+ arr.push(refNode);
2098
+ }
2099
+ refNode = refNode.parentNode;
2100
+ } else {
2101
+ break;
2102
+ }
2103
+ }
2104
+ } else if (document.contentType !== 'text/html' ||
2105
+ /[*|]/.test(leafName)) {
2076
2106
  pending = true;
2077
2107
  } else {
2078
2108
  const tagName = leafName.toLowerCase();
2079
- const arr = [];
2080
- if (range === 'self') {
2081
- const bool = this.#node.nodeType === ELEMENT_NODE &&
2082
- this._matchLeaves([leaf], this.#node);
2083
- if (bool) {
2084
- arr.push(this.#node);
2085
- }
2086
- } else if (range === 'lineal') {
2087
- let refNode = this.#node;
2088
- while (refNode) {
2089
- if (refNode.nodeType === ELEMENT_NODE) {
2090
- const bool = this._matchLeaves([leaf], refNode);
2091
- if (bool) {
2092
- arr.push(refNode);
2093
- }
2094
- refNode = refNode.parentNode;
2095
- } else {
2096
- break;
2097
- }
2098
- }
2099
- } else if (root.nodeType === DOCUMENT_NODE) {
2109
+ if (root.nodeType === DOCUMENT_NODE) {
2100
2110
  const a = xpath.select(`//*[local-name()='${tagName}']`, root);
2101
2111
  arr.push(...a);
2102
2112
  } else if (root.nodeType === DOCUMENT_FRAGMENT_NODE) {
2103
- const walker = document.createTreeWalker(root, FILTER_SHOW_ELEMENT);
2104
- let nextNode = walker.firstChild();
2105
- while (nextNode) {
2106
- if (nextNode.localName === tagName) {
2107
- arr.push(nextNode);
2113
+ const iterator = [...root.children].values();
2114
+ for (const node of iterator) {
2115
+ if (node.localName === tagName) {
2116
+ arr.push(node);
2108
2117
  }
2109
- const a = [...nextNode.getElementsByTagName(leafName)];
2118
+ const a = [...node.getElementsByTagName(leafName)];
2110
2119
  arr.push(...a);
2111
- nextNode = walker.nextSibling();
2112
2120
  }
2113
- } else {
2114
- if (root.nodeType === ELEMENT_NODE &&
2115
- root.localName === tagName) {
2121
+ } else if (root.nodeType === ELEMENT_NODE) {
2122
+ if (root.localName === tagName) {
2116
2123
  arr.push(root);
2117
2124
  }
2118
2125
  const a = [...root.getElementsByTagName(leafName)];
2119
2126
  arr.push(...a);
2120
2127
  }
2121
- if (arr.length) {
2122
- if (len) {
2123
- const iterator = arr.values();
2124
- for (const node of iterator) {
2125
- const bool = this._matchLeaves(items, node);
2126
- if (bool) {
2127
- nodes.add(node);
2128
- }
2128
+ }
2129
+ if (arr.length) {
2130
+ if (len) {
2131
+ const iterator = arr.values();
2132
+ for (const node of iterator) {
2133
+ const bool = this._matchLeaves(items, node);
2134
+ if (bool) {
2135
+ nodes.add(node);
2129
2136
  }
2130
- } else {
2131
- nodes = new Set(arr);
2132
2137
  }
2138
+ } else {
2139
+ nodes = new Set(arr);
2133
2140
  }
2134
2141
  }
2135
2142
  break;
@@ -2139,12 +2146,12 @@ export class Matcher {
2139
2146
  }
2140
2147
  default: {
2141
2148
  const arr = [];
2142
- if (range === 'self') {
2149
+ if (targetType === TYPE_SELF) {
2143
2150
  const bool = this._matchLeaves([leaf], this.#node);
2144
2151
  if (bool) {
2145
2152
  arr.push(this.#node);
2146
2153
  }
2147
- } else if (range === 'lineal') {
2154
+ } else if (targetType === TYPE_LINEAL) {
2148
2155
  let refNode = this.#node;
2149
2156
  while (refNode) {
2150
2157
  const bool = this._matchLeaves([leaf], refNode); ;
@@ -2179,10 +2186,10 @@ export class Matcher {
2179
2186
 
2180
2187
  /**
2181
2188
  * collect nodes
2182
- * @param {string} range - target range
2189
+ * @param {string} targetType - target type
2183
2190
  * @returns {Array} - matrix
2184
2191
  */
2185
- _collectNodes(range) {
2192
+ _collectNodes(targetType) {
2186
2193
  const pendingItems = new Set();
2187
2194
  const listIterator = this.#list.values();
2188
2195
  let i = 0;
@@ -2190,11 +2197,11 @@ export class Matcher {
2190
2197
  const { branch } = list;
2191
2198
  const branchLen = branch.length;
2192
2199
  const lastIndex = branchLen - 1;
2193
- if (range === 'all') {
2200
+ if (targetType === TYPE_ALL) {
2194
2201
  for (let j = 0; j < branchLen; j++) {
2195
2202
  const twig = branch[j];
2196
2203
  const { nodes, pending } =
2197
- this._findNodes(twig, j === lastIndex ? range : null);
2204
+ this._findNodes(twig, j === lastIndex ? targetType : null);
2198
2205
  if (nodes.size) {
2199
2206
  this.#matrix[i][j] = nodes;
2200
2207
  } else if (pending) {
@@ -2209,7 +2216,7 @@ export class Matcher {
2209
2216
  }
2210
2217
  } else {
2211
2218
  const twig = branch[lastIndex];
2212
- const { nodes, pending } = this._findNodes(twig, range);
2219
+ const { nodes, pending } = this._findNodes(twig, targetType);
2213
2220
  if (nodes.size) {
2214
2221
  this.#matrix[i][lastIndex] = nodes;
2215
2222
  } else if (pending) {
@@ -2230,18 +2237,7 @@ export class Matcher {
2230
2237
  let nextNode = iterator.nextNode();
2231
2238
  while (nextNode) {
2232
2239
  let bool;
2233
- if (range === 'self') {
2234
- bool = nextNode === this.#node;
2235
- } else if (range === 'lineal') {
2236
- let refNode = this.#node;
2237
- while (refNode) {
2238
- bool = nextNode === refNode;
2239
- if (bool) {
2240
- break;
2241
- }
2242
- refNode = refNode.parentNode;
2243
- }
2244
- } else if (/^(?:all|first)$/.test(range)) {
2240
+ if (targetType === TYPE_ALL || targetType === TYPE_FIRST) {
2245
2241
  if (this.#node.nodeType === ELEMENT_NODE) {
2246
2242
  bool = isDescendant(nextNode, this.#node);
2247
2243
  } else {
@@ -2270,10 +2266,10 @@ export class Matcher {
2270
2266
 
2271
2267
  /**
2272
2268
  * match nodes
2273
- * @param {string} range - target range
2269
+ * @param {string} targetType - target type
2274
2270
  * @returns {object} - collection of matched nodes
2275
2271
  */
2276
- _matchNodes(range) {
2272
+ _matchNodes(targetType) {
2277
2273
  const [...branches] = this.#list;
2278
2274
  const l = branches.length;
2279
2275
  let nodes = new Set();
@@ -2286,7 +2282,7 @@ export class Matcher {
2286
2282
  const lastIndex = branchLen - 1;
2287
2283
  if (lastIndex === 0) {
2288
2284
  const matched = this.#matrix[i][0];
2289
- if (/^(?:all|first)$/.test(range) &&
2285
+ if ((targetType === TYPE_ALL || targetType === TYPE_FIRST) &&
2290
2286
  this.#node.nodeType === ELEMENT_NODE) {
2291
2287
  for (const node of matched) {
2292
2288
  if (isDescendant(node, this.#node)) {
@@ -2296,7 +2292,7 @@ export class Matcher {
2296
2292
  } else {
2297
2293
  nodes = matched;
2298
2294
  }
2299
- } else if (range === 'all') {
2295
+ } else if (targetType === TYPE_ALL) {
2300
2296
  let { combo } = branch[0];
2301
2297
  let prevNodes = this.#matrix[i][0];
2302
2298
  for (let j = 1; j < branchLen; j++) {
@@ -2339,7 +2335,7 @@ export class Matcher {
2339
2335
  }
2340
2336
  if (matched.size) {
2341
2337
  if (j === 0) {
2342
- if (range === 'first' &&
2338
+ if (targetType === TYPE_FIRST &&
2343
2339
  this.#node.nodeType === ELEMENT_NODE) {
2344
2340
  if (isDescendant(node, this.#node)) {
2345
2341
  nodes.add(node);
@@ -2368,12 +2364,12 @@ export class Matcher {
2368
2364
 
2369
2365
  /**
2370
2366
  * find matched nodes
2371
- * @param {string} range - target range
2367
+ * @param {string} targetType - target type
2372
2368
  * @returns {object} - collection of matched nodes
2373
2369
  */
2374
- _find(range) {
2375
- this._collectNodes(range);
2376
- const nodes = this._matchNodes(range);
2370
+ _find(targetType) {
2371
+ this._collectNodes(targetType);
2372
+ const nodes = this._matchNodes(targetType);
2377
2373
  return nodes;
2378
2374
  }
2379
2375
 
@@ -2407,7 +2403,7 @@ export class Matcher {
2407
2403
  matches() {
2408
2404
  let res;
2409
2405
  try {
2410
- const nodes = this._find('self');
2406
+ const nodes = this._find(TYPE_SELF);
2411
2407
  res = nodes.has(this.#node);
2412
2408
  } catch (e) {
2413
2409
  this._onError(e);
@@ -2422,7 +2418,7 @@ export class Matcher {
2422
2418
  closest() {
2423
2419
  let res;
2424
2420
  try {
2425
- const nodes = this._find('lineal');
2421
+ const nodes = this._find(TYPE_LINEAL);
2426
2422
  let node = this.#node;
2427
2423
  while (node) {
2428
2424
  if (nodes.has(node)) {
@@ -2444,7 +2440,7 @@ export class Matcher {
2444
2440
  querySelector() {
2445
2441
  let res;
2446
2442
  try {
2447
- const nodes = this._find('first');
2443
+ const nodes = this._find(TYPE_FIRST);
2448
2444
  nodes.delete(this.#node);
2449
2445
  if (nodes.size) {
2450
2446
  [res] = this._sortNodes(nodes);
@@ -2463,7 +2459,7 @@ export class Matcher {
2463
2459
  querySelectorAll() {
2464
2460
  const res = [];
2465
2461
  try {
2466
- const nodes = this._find('all');
2462
+ const nodes = this._find(TYPE_ALL);
2467
2463
  nodes.delete(this.#node);
2468
2464
  if (nodes.size > 1 && this.#sort) {
2469
2465
  res.push(...this._sortNodes(nodes));
package/src/js/parser.js CHANGED
@@ -6,7 +6,7 @@
6
6
  import { findAll, parse, toPlainObject, walk } from 'css-tree';
7
7
 
8
8
  /* constants */
9
- import { PSEUDO_CLASS_SELECTOR, SELECTOR } from './constant.js';
9
+ import { PSEUDO_CLASS_SELECTOR, SELECTOR, SYNTAX_ERR } from './constant.js';
10
10
  const CODE_POINT_UNIT = parseInt('10000', 16);
11
11
  const HEX = 16;
12
12
  const PAIR = 2;
@@ -54,7 +54,7 @@ export const preprocess = (...args) => {
54
54
  selector = Object.prototype.toString.call(selector)
55
55
  .slice(TYPE_FROM, TYPE_TO).toLowerCase();
56
56
  } else {
57
- throw new DOMException(`invalid selector ${selector}`, 'SyntaxError');
57
+ throw new DOMException(`invalid selector ${selector}`, SYNTAX_ERR);
58
58
  }
59
59
  return selector;
60
60
  };
@@ -68,7 +68,7 @@ export const parseSelector = selector => {
68
68
  selector = preprocess(selector);
69
69
  // invalid selectors
70
70
  if (selector === '' || /^\s*>/.test(selector) || /,\s*$/.test(selector)) {
71
- throw new DOMException(`invalid selector ${selector}`, 'SyntaxError');
71
+ throw new DOMException(`invalid selector ${selector}`, SYNTAX_ERR);
72
72
  }
73
73
  let res;
74
74
  try {
@@ -83,7 +83,7 @@ export const parseSelector = selector => {
83
83
  } else if (e.message === '")" is expected' && !selector.endsWith(')')) {
84
84
  res = parseSelector(`${selector})`);
85
85
  } else {
86
- throw new DOMException(e.message, 'SyntaxError');
86
+ throw new DOMException(e.message, SYNTAX_ERR);
87
87
  }
88
88
  }
89
89
  return res;