Skip to content

perf: migrate find highlights to CSS Highlight API#751

Open
lukecotter wants to merge 10 commits intocertinia:mainfrom
lukecotter:feat-highlights-api
Open

perf: migrate find highlights to CSS Highlight API#751
lukecotter wants to merge 10 commits intocertinia:mainfrom
lukecotter:feat-highlights-api

Conversation

@lukecotter
Copy link
Copy Markdown
Contributor

📝 PR Overview

Migrates the Find module's text highlighting from DOM-manipulating <span> elements to the CSS Custom Highlight API. This eliminates DOM mutations during search, enabling up to 10x faster search on large logs and fixing scroll-to-row centering issues caused by extra DOM elements.

🛠️ Changes made

  • Rewrote Find module to use CSS Custom Highlight API instead of injecting <span> elements for matches
  • Introduced headless formatter rendering so search operates on plain text without DOM side-effects
  • Extracted and optimised the call tree name column formatter for reuse
  • Converted progress formatter from HTML string concatenation to HTMLElement construction
  • Fixed scroll-to-row centering broken by virtual DOM bottom-pad miscalculation
  • Refactored RowNavigation with promise-based scroll flow replacing setTimeout deferrals
  • Added CSS compositor hints (contain, will-change) for smoother tabulator scrolling
  • Disabled scroll anchoring on the virtual scroll container to prevent browser interference

🧩 Type of change (check all applicable)

  • 🐛 Bug fix - something not working as expected
  • ✨ New feature – adds new functionality
  • ♻️ Refactor - internal changes with no user impact
  • ⚡ Performance Improvement
  • 📝 Documentation - README or documentation site changes
  • 🔧 Chore - dev tooling, CI, config
  • 💥 Breaking change

🔗 Related Issues

resolves #627

✅ Tests added?

  • 👍 yes
  • 🙅 no, not needed

📚 Docs updated?

  • 🔖 CHANGELOG.md
  • 🙅 not needed

Prevents Chrome's scroll anchoring from double-compensating
when the virtual DOM renderer adjusts padding during scroll-up,
which caused visible content drift.
will-change: transform promotes the scroll container to a compositor
layer for GPU-accelerated scrolling.
content-visibility: auto skips rendering off-screen table content.
Replace DOM-based find/match highlighting (span insertion with
.findMatch/.currentFindMatch classes) with the CSS Highlight API.
Uses shared Highlight objects with per-instance Range tracking,
rAF-throttled scroll listener for virtual scroll, and
::highlight() pseudo-elements for styling.
Return a Promise from goToRow for async coordination. Use
scrollIntoView as fallback after tabulator's scrollToRow to handle
edge cases near the bottom of the grid. Check element connectivity
in _isVisible and compare against tableholder bounds instead of
window.
The two setTimeout wrappers in goToRow and _scrollToRow were deferring
 execution unnecessarily — goToRow now calls _scrollToRow directly, and
_scrollToRow resolves synchronously after scrollIntoView rather than deferring
to the next tick.
Extracts the inline name formatter into CalltreeNameFormatter.ts using a
factory/closure pattern. Key hot-path improvements: replaces
createElement('span') with document.createTextNode() (no element allocation
for plain text rows), eliminates private row._row.modules.dataTree access by
computing treeLevel once in _toCallTree and storing it in row data, and reads
dataTreeChildIndent via this.table on first render only.
Replace scrollIntoView with \_centerRow that restores vDomBottomPad
before setting scrollTop via offsetTop. Tabulator's \_addBottomRow
zeroes vDomBottomPad when vDomBottom reaches the last row index —
even for mid-table rows — shrinking scrollHeight and preventing
center alignment. Also refactor \_scrollToRow to async/await.
… API

Replace per-cell DOM-based highlighting with CSS Highlight API ranges,
eliminating row.reformat() calls during search. Extract searchable text
via headless formatter execution with a reusable mock cell and per-row
cache, bypassing getCells() and its O(rows × cols) DOM element creation.
Skip innerHTML parsing for non-HTML formatter results. Highlight ranges
now span across adjacent text nodes for cross-element match support.
Eliminates innerHTML parsing in Find search by returning DOM elements directly.
_runFormatterForColumn now reads .textContent instead of parsing HTML via
innerHTML for every progress column cell.
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.

🔧 chore: use custom highlights api for text highlighting

1 participant