Skip to content

v7.16.1

Choose a tag to compare

@metonym metonym released this 27 Jul 15:47
· 20 commits to master since this release
v7.16.1
7bd5716

Performance

  • make the Typewriter fallback split incremental (00d2c11)
  • read HighlightEditable caret offsets from line lengths (2a75907)
  • cache reopen tags across line breaks in extendLines (d97c520)
  • binary-search ranges for single-line HighlightEditable repaints (de6d955)
  • resolve preprocessor match line numbers lazily (e939ce1)
  • memoize missing closing tags in the JSX guard (f7cab7e)
  • use a Set for LineNumbers highlighted-line lookups (016d350)
  • defer guard closure allocation to cache misses (eddc39e)
  • repaint css-highlights in one linear sweep (ce2856e)

Performance

This release is a performance-only patch focused on the new highlight engine, HighlightEditable, Typewriter, LineNumbers, and the static preprocessor. No API changes.

Typewriter

The fallback unit split re-walked the highlighted HTML from index 0 on every tick. Since revealed only grows by one unit per tick, a full animation was O(n²). A stateful splitter now advances forward across calls, and head/tail are built with a single slice. A 30k-unit animation drops from ~4.3s to ~2.6ms.

HighlightEditable

Several hot paths around caret tracking and token painting are cheaper:

  • Caret offsets are read from cached line lengths instead of serializing the whole document per keystroke.
  • Single-line repaints binary-search the sorted token ranges instead of scanning every token in the document.
  • Full css-highlights repaints advance a single cursor over sorted ranges (O(lines + tokens)) instead of rescanning all ranges per line (O(lines × tokens)), which could freeze large files on mount, paste, or undo/redo.

Highlight engine

  • extendLines caches close/reopen tag strings across newlines instead of rebuilding them from the scope stack on every line break.
  • The JSX tag guard memoizes missing closing tags per name, so generic-dense TypeScript no longer pays a full tail scan for every <T> occurrence. Highlighting ~441 KB of that style drops from ~339ms to ~196ms.
  • Guard closures are allocated only on cache misses, not on every token boundary.

LineNumbers and static preprocessor

  • Highlighted-line membership uses a Set so each rendered line is O(1) instead of an array scan.
  • The static preprocessor resolves match line numbers only on warn paths, so the happy path no longer scans the file for newlines on every <Highlight> match.