Skip to content

Commit

Permalink
Refactor collecting of results
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Dec 31, 2022
1 parent bbe3479 commit 2214b35
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 90 deletions.
12 changes: 7 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export function matches(selector, node) {
const state = createState(node)
state.one = true
state.shallow = true
const result = any(parse(selector), node || undefined, state)
return result.length > 0
any(parse(selector), node || undefined, state)
return state.results.length > 0
}

/**
Expand All @@ -50,9 +50,9 @@ export function matches(selector, node) {
export function select(selector, tree) {
const state = createState(tree)
state.one = true
const result = any(parse(selector), tree || undefined, state)
any(parse(selector), tree || undefined, state)
// To do next major: return `undefined`.
return result[0] || null
return state.results[0] || null
}

/**
Expand All @@ -71,7 +71,8 @@ export function select(selector, tree) {
*/
export function selectAll(selector, tree) {
const state = createState(tree)
return any(parse(selector), tree || undefined, state)
any(parse(selector), tree || undefined, state)
return state.results
}

/**
Expand All @@ -80,6 +81,7 @@ export function selectAll(selector, tree) {
*/
function createState(tree) {
return {
results: [],
any,
iterator: undefined,
scopeNodes: tree ? (root(tree) ? tree.children : [tree]) : [],
Expand Down
87 changes: 9 additions & 78 deletions lib/any.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ const type = zwitch('type', {
* Tree.
* @param {SelectState} state
* State.
* @returns {Array<Node>}
* Results.
* @returns {void}
*/
export function any(query, node, state) {
return query && node ? type(query, node, state) : []
if (query && node) {
type(query, node, state)
}
}

/**
Expand All @@ -44,19 +45,15 @@ export function any(query, node, state) {
* Tree.
* @param {SelectState} state
* State.
* @returns {Array<Node>}
* Results.
* @returns {void}
*/
function selectors(query, node, state) {
const collector = new Collector(state.one)
let index = -1

while (++index < query.selectors.length) {
const set = query.selectors[index]
collector.collectAll(rule(set.rule, node, state))
rule(set.rule, node, state)
}

return collector.result
}

/**
Expand All @@ -68,8 +65,7 @@ function selectors(query, node, state) {
* Tree.
* @param {SelectState} state
* State.
* @returns {Array<Node>}
* Results.
* @returns {void}
*/
function ruleSet(query, node, state) {
return rule(query.rule, node, state)
Expand All @@ -84,12 +80,9 @@ function ruleSet(query, node, state) {
* Tree.
* @param {SelectState} state
* State.
* @returns {Array<Node>}
* Results.
* @returns {void}
*/
function rule(query, tree, state) {
const collector = new Collector(state.one)

if (state.shallow && query.rule) {
throw new Error('Expected selector without nesting')
}
Expand All @@ -106,8 +99,6 @@ function rule(query, tree, state) {
})
)

return collector.result

/** @type {SelectIterator} */
function iterator(query, node, index, parent, state) {
if (test(query, node, index, parent, state)) {
Expand All @@ -118,7 +109,7 @@ function rule(query, tree, state) {
index: needsIndex(query.rule)
})
} else {
collector.collect(node)
if (!state.results.includes(node)) state.results.push(node)
state.found = true
}
}
Expand Down Expand Up @@ -183,63 +174,3 @@ function unknownType(query) {
function invalidType() {
throw new Error('Invalid type')
}

/**
* Collect nodes.
*/
class Collector {
/**
* @param {boolean | undefined} one
*/
constructor(one) {
/**
* Found nodes.
*
* @type {Array<Node>}
*/
this.result = []

/**
* Whether we’re looking for one result.
*
* @type {boolean}
*/
this.one = one || false

/**
* Whether we’ve found something.
*
* @type {boolean}
*/
this.found = false
}

/**
* Add multiple nodes.
*
* @param {Array<Node>} nodes
*/
collectAll(nodes) {
let index = -1

while (++index < nodes.length) {
this.collect(nodes[index])
}
}

/**
* Add one node.
*
* @param {Node} node
*/
collect(node) {
if (this.one) {
// Shouldn’t happen, safeguards performance problems.
/* c8 ignore next */
if (this.found) return
this.found = true
}

if (!this.result.includes(node)) this.result.push(node)
}
}
18 changes: 12 additions & 6 deletions lib/pseudo.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,20 @@ export function pseudo(query, node, index, parent, state) {
* @returns {boolean}
*/
function matches(query, node, _1, _2, state) {
const {shallow, one} = state
const {shallow, one, results, any} = state

state.shallow = false
state.one = true
state.results = []

const result = state.any(query.value, node, state)[0] === node
any(query.value, node, state)
const matches = state.results[0] === node

state.shallow = shallow
state.one = one
state.results = results

return result
return matches
}

/**
Expand Down Expand Up @@ -340,19 +343,22 @@ function assertDeep(state, query) {
*/
function hasSelector(query, node, _1, _2, state) {
const fragment = {type: 'root', children: parent(node) ? node.children : []}
const {shallow, one, scopeNodes, any} = state
const {shallow, one, scopeNodes, results, any} = state

state.shallow = false
state.one = true
state.scopeNodes = [node]
state.results = []

const result = any(query.value, fragment, state).length > 0
any(query.value, fragment, state)
const has = state.results.length > 0

state.shallow = shallow
state.one = one
state.scopeNodes = scopeNodes
state.results = results

return result
return has
}

/**
Expand Down
4 changes: 3 additions & 1 deletion lib/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
*
* @typedef SelectState
* Current state.
* @property {(query: Selectors | RuleSet | Rule, node: Node | undefined, state: SelectState) => Array<Node>} any
* @property {Array<Node>} results
* Matches.
* @property {(query: Selectors | RuleSet | Rule, node: Node | undefined, state: SelectState) => void} any
* To do: Remove.
* @property {SelectIterator | undefined} iterator
* Current iterator.
Expand Down

0 comments on commit 2214b35

Please sign in to comment.