mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-04 14:39:42 +02:00
When the data-pacing path (chunkedTerminalWrite + deferred path of flushPendingWrites) schedules its next chunk via requestAnimationFrame alone, terminal output stalls indefinitely if rAF is starved. Three real-world scenarios reproduce this in Chromium: 1. Window is occluded (fully covered by another window, or on a monitor that has gone to sleep). rAF drops to ~0Hz. 2. Tab is idle-throttled (no user interaction for ~5 min). Chromium intensive-throttling clamps setTimeout to 1Hz too. 3. Tab is in a background window. Both rAF and setTimeout slow to a crawl. Replace the rAF-only scheduling with a _safeYield helper that races three primitives in parallel: - requestAnimationFrame (primary, fires at compositor rate). - setTimeout(50) (fallback for visible-but-occluded windows). - Worker postMessage tick (fallback for idle-throttled and background tabs; Workers are not subject to main-thread throttling — this is the React Scheduler trick). The first one to fire wins via a `done` guard; the others become no-ops. The Worker is built lazily on first call (4 lines of inline JS via Blob URL); if Worker construction throws we silently fall back to the other two primitives. Replaces 6 requestAnimationFrame callsites that participate in data pacing: - 3 flushPendingWrites scheduling sites (live + deferred paths). - 3 chunkedTerminalWrite sites (initial chunk, next-chunk loop, final finish-callback). True animation use cases (scroll loop in scrollToBottom, fit-addon reflow) stay on plain requestAnimationFrame — they are correctly throttled when the user is not looking, by design. File: src/web/public/terminal-ui.js (+70/-8). Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>