Repository navigation
fix(web): keep chat typing fast beside open PDFs and LaTeX - #801
Merged
Merged
Conversation
PDF.js's TextLayerBuilder re-appended each text layer's endOfContent on every keyup and selectionchange in the app, even when it was already the last child. DrawLayer observes that move and reads Selection.isCollapsed, which forces a full synchronous layout, so chat typing beside a long PDF paid for a whole-document layout per key (about 160 ms per key at 4x CPU throttle with a 320-page PDF; 16 ms after this change). Patch the legacy viewer Scient imports to skip the move when the node is already last. Two Scient selectionchange handlers also read Selection.isCollapsed; they now read the range's collapsed flag, which does not force layout. Co-authored-by: nattikahana <93278659+nattikahana@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
React copies a controlled textarea's value into defaultValue after every change, which replaces the textarea's text node. With the app's :has() rules, Chromium then invalidates every element under body, so each key in Ask in chat, the LaTeX source fields and other textareas restyled the whole document (256 ms per key at 4x with a LaTeX document open; 24 ms after this change). Skip a defaultValue write that equals the value the textarea already shows. Nothing visible changes, and a different default still applies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The previous commit patched HTMLTextAreaElement.prototype, so every textarea in the renderer, including library and form textareas, stopped honouring `defaultValue = value` as a new reset baseline. Scope it: textareas that never use their native default or form reset spread SKIP_MIRRORED_DEFAULT, and a focusin listener gives only those elements the skipping setter. Ask in chat and the Visual LaTeX fields opt in. Line endings are normalised before comparing, so CRLF drafts are covered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reading HTMLTextAreaElement at module load failed every Node unit test that imports Ask in chat or the LaTeX fields. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
yaacovcorcos
enabled auto-merge
November 9, 2026 13:28
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Nov 9, 2026
Contributor
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
This was referenced Nov 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Platforms: measured and tested on macOS (Apple Silicon) only. The causes are in Chromium, PDF.js and React, which Electron 44 shares on Windows and Linux, but neither was run there. Windows is where #777's author saw the stall.
What Changed
Typing in chat no longer slows down while a document is open. Two root causes are fixed:
keyupandselectionchangeanywhere in the app, PDF.js's TextLayerBuilder re-appended each text layer'sendOfContent, even when it was already last. PDF.js's DrawLayer observes that move and readsSelection.isCollapsed, which forces a synchronous layout.pnpm patchto the legacy viewer Scient imports skips the no-op move. PDF.js main still has the bug.selectionchangehandlers now readRange.collapsedinstead ofSelection.isCollapsed.defaultValueafter each change, which replaces its text node. With the app's:has()rules, Chromium then invalidated every element under<body>, about 13,000 with a Visual LaTeX document open.SKIP_MIRRORED_DEFAULT, and only those skip a default equal to their shown text. That covers Ask in chat (inside a SCIENT-FORK seam) and the six Visual LaTeX textareas. Every other textarea keeps the native behaviour.Why
This replaces #777. Its PDF.js finding was right and is credited. Measuring showed that the two causes above account for the stalls, so #777's 500 ms input-priority scheduler is not needed. It only deferred the work, and it delayed PDF drawing, panes, previews and clocks with no limit while someone types.
Typing latency per key at 4× CPU throttle. Production build, headless Chromium, 149 keys, Event Timing key-to-paint, p50 / p90 in ms:
Without throttling on an M-series Mac, main reached 24–64 ms in the PDF and Ask cases, and this PR is 16 ms in all of them.
Still slow, and not part of this PR:
Both deserve their own follow-ups.
Verification
pdfTextLayerReset.browser.test.tsfails against unpatched PDF.js and passes with the patch.textareaDefaultValue.browser.test.tsx's first test fails without the installer. Its second test fails if the skip leaks to unmarked textareas.SCIENT_TEST_CPU_THROTTLE=6.vp run check:changed f3354849afpasses:alignment:seams:check,latex:seams:check,upstream:provenance:check, andpnpm run test:desktop-smokein an isolated home.defaultValue/form-reset semantics for every textarea. That's fixed by the opt-in.Documentation Impact
Documentation impact: Updated —
UPSTREAM.md(PDF.js patch and its removal check) anddocs/internals/performance-regressions.md(typing beside documents).Checklist
Implementation: Claude Code (Claude Opus 5.5). Review: Codex (gpt-6.1-sol). Diagnosis credit for the PDF.js listener: nattikahana in #777.
🤖 Generated with Claude Code