Skip to content

perf: fix O(n*m) dedup in querySelectorAll#12

Merged
borgar merged 1 commit intoborgar:masterfrom
gthb:optimize-domquery-dedup
Feb 16, 2026
Merged

perf: fix O(n*m) dedup in querySelectorAll#12
borgar merged 1 commit intoborgar:masterfrom
gthb:optimize-domquery-dedup

Conversation

@gthb
Copy link
Contributor

@gthb gthb commented Feb 13, 2026

What

Fix O(n*m) performance in domQuery

How

The deduplication step after selector matching did this:

  contextNode.getElementsByTagName('*')
    .filter(elm => elements.includes(elm))

This traverses the entire tree and does a linear .includes() scan per element. That makes it O(n*m) where n is the tree size and m is the number of matched elements. For large documents with many matches (e.g. querySelectorAll on a sheet with thousands of cells), this can get quite bad.

For single-group selectors (no commas), the filter chain already produces results in document order, so skip the tree walk entirely and just deduplicate seen elements in-place with a Set.

For multi-group selectors (i.e. with commas), keep the tree walk for document order but collect matched elements into a Set up front and use Set.has() for O(1) lookups.

The deduplication step after selector matching did this:

```ts
  contextNode.getElementsByTagName('*')
    .filter(elm => elements.includes(elm))
```

This traverses the entire tree and does a linear .includes() scan per element.
That makes it O(n*m) where n is the tree size and m is the number of matched
elements. For large documents with many matches (e.g. querySelectorAll on a
sheet with thousands of cells), this can get quite bad.

For single-group selectors (no commas), the filter chain already produces
results in document order, so skip the tree walk entirely and just deduplicate
seen elements in-place with a Set.

For multi-group (comma) selectors, keep the tree walk for document order but
collect matched elements into a `Set` up front and use `Set.has()` for O(1)
lookups.
@borgar borgar merged commit 764f5a5 into borgar:master Feb 16, 2026
@borgar
Copy link
Owner

borgar commented Feb 16, 2026

Awesome!

@gthb gthb deleted the optimize-domquery-dedup branch February 16, 2026 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants