From 06741c74b4ca0cdaea47f06f9efc997a37d0ed2e Mon Sep 17 00:00:00 2001 From: Ben Vinegar Date: Sun, 29 Mar 2026 22:03:03 -0400 Subject: [PATCH] perf: cache highlighter promises by key --- src/ui/diff/pierre.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/ui/diff/pierre.ts b/src/ui/diff/pierre.ts index 1fa7b4d..348f094 100644 --- a/src/ui/diff/pierre.ts +++ b/src/ui/diff/pierre.ts @@ -38,8 +38,10 @@ function pierreRenderOptions(appearance: AppTheme["appearance"]) { } type HighlightOptions = ReturnType; +type Highlighter = Awaited>; const highlighterOptionsByKey = new Map(); +const highlighterPromiseCache = new Map>(); let queuedHighlightWork = Promise.resolve(); type HastNode = HastTextNode | HastElementNode; @@ -352,6 +354,11 @@ async function prepareHighlighter( ) { const resolvedLanguage = language ?? "text"; const cacheKey = `${appearance}:${resolvedLanguage}`; + const cached = highlighterPromiseCache.get(cacheKey); + if (cached) { + return cached; + } + const options = highlighterOptionsByKey.get(cacheKey) ?? getHighlighterOptions(resolvedLanguage, { @@ -362,10 +369,16 @@ async function prepareHighlighter( highlighterOptionsByKey.set(cacheKey, options); } - return getSharedHighlighter({ + const highlighterPromise = getSharedHighlighter({ ...options, preferredHighlighter: "shiki-wasm", + }).catch((error) => { + highlighterPromiseCache.delete(cacheKey); + throw error; }); + + highlighterPromiseCache.set(cacheKey, highlighterPromise); + return highlighterPromise; } /** Queue highlight rendering so startup work stays serialized in request order. */