import { WorkerPoolContext, useWorkerPool } from "@pierre/diffs/react"; import { WorkerPoolManager } from "@pierre/diffs/worker"; import DiffsWorker from "@pierre/diffs/worker/worker.js?worker"; import * as Schema from "effect/Schema"; import { useCallback, useEffect, useMemo, useState, useSyncExternalStore, type ReactNode, } from "react"; import { useTheme } from "../hooks/useTheme"; import { resolveDiffThemeName, type DiffThemeName } from "../lib/diffRendering"; import { PREFERRED_HIGHLIGHTER } from "../lib/syntaxHighlighting"; export class DiffWorkerError extends Schema.TaggedError()("DiffWorkerError", { operation: Schema.Literals(["create-worker", "get-render-options", "set-render-options"]), themeName: Schema.Literals(["pierre-light", "pierre-dark"]), cause: Schema.Defect(), }) { override get message(): string { return `Diff worker operation ${this.operation} failed for theme ${this.themeName}.`; } } const DIFF_WORKER_IDLE_TTL_MS = 30_000; let sharedWorkerPool: | { readonly pool: WorkerPoolManager; consumers: number; idleTimer: ReturnType | undefined; } | undefined; /** Create workers after a viewer commits, then reuse them across short panel closures. */ function acquireDiffWorkerPool(themeName: DiffThemeName, poolSize: number) { const entry = (sharedWorkerPool ??= { pool: new WorkerPoolManager( { workerFactory: () => { try { return new DiffsWorker(); } catch (cause) { throw new DiffWorkerError({ operation: "create-worker", themeName, cause }); } }, poolSize, totalASTLRUCacheSize: 240, }, { theme: themeName, preferredHighlighter: PREFERRED_HIGHLIGHTER, tokenizeMaxLineLength: 1_000, useTokenTransformer: true, }, ), consumers: 0, idleTimer: undefined, }); clearTimeout(entry.idleTimer); entry.idleTimer = undefined; entry.consumers += 1; return entry; } function DiffWorkerThemeSync({ themeName }: { themeName: DiffThemeName }) { const workerPool = useWorkerPool(); useEffect(() => { if (!workerPool) { return; } let operation: DiffWorkerError["operation"] = "get-render-options"; void (async () => { try { const current = workerPool.getDiffRenderOptions(); if (current.theme === themeName) { return; } operation = "set-render-options"; await workerPool.setRenderOptions({ ...current, theme: themeName, }); } catch (cause) { console.error(new DiffWorkerError({ operation, themeName, cause })); } })(); }, [themeName, workerPool]); return null; } // Plain-text views do not queue a highlight task that could retry a blank first render. function DiffWorkerReady({ children }: { children?: ReactNode }) { const workerPool = useWorkerPool(); const [readyPool, setReadyPool] = useState(); const ready = workerPool ? readyPool === workerPool || workerPool.isInitialized() || !workerPool.isWorkingPool() : typeof window === "undefined"; useEffect(() => { if (ready || !workerPool) return; let mounted = true; const finish = () => { if (mounted) setReadyPool(workerPool); }; // Failed pools use Pierre's existing main-thread highlighter. void workerPool.initialize().then(finish, finish); return () => { mounted = false; }; }, [ready, workerPool]); return ready ? ( children ) : (
Loading code...
); } export function DiffWorkerPoolProvider({ children }: { children?: ReactNode }) { const { resolvedTheme } = useTheme(); const diffThemeName = resolveDiffThemeName(resolvedTheme); const workerPoolSize = useMemo(() => { const cores = typeof navigator === "undefined" ? 4 : Math.max(1, navigator.hardwareConcurrency || 4); return Math.max(2, Math.min(6, Math.floor(cores / 2))); }, []); const workerPool = useSyncExternalStore( useCallback( (onStoreChange) => { if (typeof window === "undefined") return () => {}; const entry = acquireDiffWorkerPool(diffThemeName, workerPoolSize); onStoreChange(); return () => { entry.consumers -= 1; if (entry.consumers !== 0) return; entry.idleTimer = setTimeout(() => { entry.idleTimer = undefined; entry.pool.terminate(); if (sharedWorkerPool === entry) sharedWorkerPool = undefined; }, DIFF_WORKER_IDLE_TTL_MS); }; }, [diffThemeName, workerPoolSize], ), () => sharedWorkerPool?.pool, () => undefined, ); return ( {children} ); }