Skip to content

Commit f763600

Browse files
committed
Refactor collecting of results
1 parent 3142384 commit f763600

File tree

4 files changed

+34
-92
lines changed

4 files changed

+34
-92
lines changed

index.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* @typedef {import('./lib/types.js').Element} Element
33
* @typedef {import('./lib/types.js').Node} Node
44
* @typedef {import('./lib/types.js').Space} Space
5+
* @typedef {import('./lib/types.js').SelectState} SelectState
56
*/
67

78
import {html, svg} from 'property-information'
@@ -29,7 +30,8 @@ export function matches(selector, node, space) {
2930
const state = createState(node, space)
3031
state.one = true
3132
state.shallow = true
32-
return Boolean(any(parse(selector), node || undefined, state)[0])
33+
any(parse(selector), node || undefined, state)
34+
return state.results.length > 0
3335
}
3436

3537
/**
@@ -50,8 +52,9 @@ export function matches(selector, node, space) {
5052
export function select(selector, tree, space) {
5153
const state = createState(tree, space)
5254
state.one = true
55+
any(parse(selector), tree || undefined, state)
5356
// To do in major: return `undefined` instead.
54-
return any(parse(selector), tree || undefined, state)[0] || null
57+
return state.results[0] || null
5558
}
5659

5760
/**
@@ -70,18 +73,20 @@ export function select(selector, tree, space) {
7073
*/
7174
export function selectAll(selector, tree, space) {
7275
const state = createState(tree, space)
73-
return any(parse(selector), tree || undefined, state)
76+
any(parse(selector), tree || undefined, state)
77+
return state.results
7478
}
7579

7680
/**
7781
* @param {Node | null | undefined} [tree]
7882
* Tree to search.
7983
* @param {Space | null | undefined} [space='html']
8084
* Name of namespace (`'svg'` or `'html'`).
81-
* @returns {import('./lib/types.js').SelectState} SelectState
85+
* @returns {SelectState} SelectState
8286
*/
83-
function createState(tree, space) {
87+
export function createState(tree, space) {
8488
return {
89+
results: [],
8590
// @ts-expect-error assume elements.
8691
scopeElements: tree ? (tree.type === 'root' ? tree.children : [tree]) : [],
8792
iterator: undefined,

lib/any.js

Lines changed: 10 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ const type = zwitch('type', {
3030
* Tree.
3131
* @param {SelectState} state
3232
* State.
33-
* @returns {Array<Element>}
34-
* Results.
33+
* @returns {void}
3534
*/
3635
export function any(query, node, state) {
37-
return query && node ? type(query, node, state) : []
36+
if (query && node) {
37+
type(query, node, state)
38+
}
3839
}
3940

4041
/**
@@ -46,19 +47,15 @@ export function any(query, node, state) {
4647
* Tree.
4748
* @param {SelectState} state
4849
* State.
49-
* @returns {Array<Element>}
50-
* Results.
50+
* @returns {void}
5151
*/
5252
function selectors(query, node, state) {
53-
const collector = new Collector(state.one)
5453
let index = -1
5554

5655
while (++index < query.selectors.length) {
5756
const set = query.selectors[index]
58-
collector.collectAll(rule(set.rule, node, state))
57+
rule(set.rule, node, state)
5958
}
60-
61-
return collector.result
6259
}
6360

6461
/**
@@ -70,11 +67,10 @@ function selectors(query, node, state) {
7067
* Tree.
7168
* @param {SelectState} state
7269
* State.
73-
* @returns {Array<Element>}
74-
* Results.
70+
* @returns {void}
7571
*/
7672
function ruleSet(query, node, state) {
77-
return rule(query.rule, node, state)
73+
rule(query.rule, node, state)
7874
}
7975

8076
/**
@@ -86,12 +82,9 @@ function ruleSet(query, node, state) {
8682
* Tree.
8783
* @param {SelectState} state
8884
* State.
89-
* @returns {Array<Element>}
90-
* Results.
85+
* @returns {void}
9186
*/
9287
function rule(query, tree, state) {
93-
const collector = new Collector(state.one)
94-
9588
if (state.shallow && query.rule) {
9689
throw new Error('Expected selector without nesting')
9790
}
@@ -102,8 +95,6 @@ function rule(query, tree, state) {
10295
index: needsIndex(query)
10396
})
10497

105-
return collector.result
106-
10798
/** @type {SelectIterator} */
10899
function iterator(query, node, index, parent, state) {
109100
const exit = enterState(state, node)
@@ -117,7 +108,7 @@ function rule(query, tree, state) {
117108
})
118109
} else {
119110
// @ts-expect-error `test` also asserts `node is Element`
120-
collector.collect(node)
111+
if (!state.results.includes(node)) state.results.push(node)
121112
state.found = true
122113
}
123114
}
@@ -161,63 +152,3 @@ function unknownType(query) {
161152
function invalidType() {
162153
throw new Error('Invalid type')
163154
}
164-
165-
/**
166-
* Collect elements.
167-
*/
168-
class Collector {
169-
/**
170-
* @param {boolean | undefined} one
171-
*/
172-
constructor(one) {
173-
/**
174-
* Found elements.
175-
*
176-
* @type {Array<Element>}
177-
*/
178-
this.result = []
179-
180-
/**
181-
* Whether we’re looking for one result.
182-
*
183-
* @type {boolean}
184-
*/
185-
this.one = one || false
186-
187-
/**
188-
* Whether we’ve found something.
189-
*
190-
* @type {boolean}
191-
*/
192-
this.found = false
193-
}
194-
195-
/**
196-
* Add multiple elements.
197-
*
198-
* @param {Array<Element>} elements
199-
*/
200-
collectAll(elements) {
201-
let index = -1
202-
203-
while (++index < elements.length) {
204-
this.collect(elements[index])
205-
}
206-
}
207-
208-
/**
209-
* Add one element.
210-
*
211-
* @param {Element} element
212-
*/
213-
collect(element) {
214-
if (this.one) {
215-
// Shouldn’t happen, safeguards performance problems.
216-
/* c8 ignore next */
217-
if (this.found) return
218-
this.found = true
219-
}
220-
221-
if (!this.result.includes(element)) this.result.push(element)
222-
}
223-
}

lib/pseudo.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,17 +104,19 @@ export function pseudo(query, element, index, parent, state) {
104104
* @returns {boolean}
105105
*/
106106
function matches(query, element, _, parent, state) {
107-
const {shallow, one} = state
107+
const {shallow, one, results} = state
108108

109109
state.shallow = false
110110
state.one = true
111-
112-
const result = any(query.value, element, state)[0] === element
111+
state.results = []
112+
any(query.value, element, state)
113+
const matches = state.results[0] === element
113114

114115
state.shallow = shallow
115116
state.one = one
117+
state.results = results
116118

117-
return result
119+
return matches
118120
}
119121

120122
/**
@@ -541,19 +543,21 @@ function assertDeep(state, query) {
541543
function has(query, element, _1, _2, state) {
542544
/** @type {Root} */
543545
const fragment = {type: 'root', children: element.children}
544-
const {shallow, one, scopeElements} = state
546+
const {shallow, one, scopeElements, results} = state
545547

546548
state.shallow = false
547549
state.one = true
548550
state.scopeElements = [element]
549-
550-
const result = any(query.value, fragment, state).length > 0
551+
state.results = []
552+
any(query.value, fragment, state)
553+
const has = state.results.length > 0
551554

552555
state.shallow = shallow
553556
state.one = one
554557
state.scopeElements = scopeElements
558+
state.results = results
555559

556-
return result
560+
return has
557561
}
558562

559563
/**

lib/types.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
*
6060
* @typedef SelectState
6161
* Current state.
62+
* @property {Array<Element>} results
63+
* Matches.
6264
* @property {Array<Element>} scopeElements
6365
* Elements in scope.
6466
* @property {SelectIterator | undefined} iterator

0 commit comments

Comments
 (0)