Skip to content

fix(elements): dedupe in-flight code block tokenization - #455

Open
ephraimduncan wants to merge 2 commits into
vercel:mainfrom
ephraimduncan:fix/code-block-duplicate-tokenization
Open

fix(elements): dedupe in-flight code block tokenization#455
ephraimduncan wants to merge 2 commits into
vercel:mainfrom
ephraimduncan:fix/code-block-duplicate-tokenization

Conversation

@ephraimduncan

@ephraimduncan ephraimduncan commented Jul 30, 2026

Copy link
Copy Markdown

Problem

The first render of any uncached code/language pair launches two Shiki tokenization jobs for the same input. CodeBlockContent calls highlightCode from two paths in the same render cycle:

  1. the render-time memo (highlightCode(code, language) ?? rawTokens)
  2. the passive effect (highlightCode(code, language, callback))

Before the first job can populate tokensCache, the effect's cache miss starts a second getHighlighter(...).then(codeToTokens). Both execute codeToTokens; the later one overwrites the same cache entry. During streaming, where every chunk is a new uncached string, this doubles the expensive part of the hot path.

Fix

  • Track in-flight work in a pendingHighlights set keyed by the token cache key. A cache miss with a pending job subscribes the callback and returns null instead of starting duplicate tokenization. The set is cleared on both success and failure so a rejected highlight permits a later retry.
  • Found while verifying the retry path: getHighlighter cached rejected createHighlighter promises per language forever, making a language permanently unhighlightable after one transient failure. Rejected promises are now evicted from highlighterCache.

Immediate raw-token rendering while Shiki loads is unchanged, as is the subscriber fan-out.

Verification

Regression test (describe("highlightCode") in code-block.test.tsx, shiki mocked at the module boundary with a counting codeToTokens spy):

  • one tokenization per uncached first mount (fails with "called 2 times" on pre-fix code)
  • two concurrent subscribers receive the same in-flight result from one job
  • a rejected highlight permits a later retry (fails on pre-fix code: rejected highlighter promise was cached forever)

All 3 tests fail against the pre-fix source and pass with the fix; existing code-block and snippet suites pass; ultracite check clean on touched files.

An uncached code/language pair launched two Shiki jobs on first render:
CodeBlockContent calls highlightCode from both its render-time memo and
its passive effect before the token cache is warm. Track in-flight keys
so a cache miss with a pending job only subscribes instead of starting
duplicate tokenization.

Also evict rejected createHighlighter promises from the highlighter
cache so a transient failure no longer makes a language permanently
unhighlightable.
@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

@ephraimduncan is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

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.

1 participant