Lazily store a lowercased line variant in the line cache entry to avoid
repeated toLowerCase calls during case-insensitive searches.
Co-authored-by: Cursor <cursoragent@cursor.com>
Compile the line search RegExp once per find/findNext/findPrevious call
and pass it into _findInLine to avoid per-line recompilation.
Co-authored-by: Cursor <cursoragent@cursor.com>
Skip empty regex matches in the reverse path to match forward behavior and
avoid unstable result selection.
Co-authored-by: Cursor <cursoragent@cursor.com>
Scan for additional matches when the first candidate fails whole-word
checks instead of returning early.
Co-authored-by: Cursor <cursoragent@cursor.com>
Pass isActiveResult through to _applyStyles in onRender so active matches
receive xterm-find-active-result-decoration.
Co-authored-by: Cursor <cursoragent@cursor.com>
Compare decoration style fields in didOptionsChange so same-term searches
with updated colors or rulers trigger highlight recomputation.
Co-authored-by: Cursor <cursoragent@cursor.com>
Evaluate shouldUpdateHighlighting before updating lastSearchOptions so
option-only changes trigger highlight refresh for the same term.
Co-authored-by: Cursor <cursoragent@cursor.com>
Three related disposable-registration gaps that leak xterm Terminal
instances when the host application unmounts a Terminal. Evidence +
full writeup at juspay/kolu#606.
1. addon-webgl/WebglRenderer._cursorBlinkStateManager was declared
`= new MutableDisposable()` without the `this._register(...)`
wrapper that every sibling MutableDisposable in the class uses.
CursorBlinkStateManager runs a setInterval for the cursor blink
and its `dispose()` correctly clears it — but dispose() was never
called because the disposable wasn't registered. The live timer
kept the renderer (and thus the Terminal) alive past host
unmount.
2. common/TaskQueue.DebouncedIdleTask had no `dispose()` method.
Added one that clears the internal IdleTaskQueue (cancelling any
pending idle callback).
3. browser/services/RenderService._pausedResizeTask (a
DebouncedIdleTask) was not registered. Wrapped with
`this._register(...)` so RenderService.dispose propagates.
Verified in a downstream app (kolu) with a repro that toggles Focus
vs Canvas layout modes:
- Pre-fix: 24/28 disposed xterm Terminals retained past host unmount
+ forced GC.
- Post-fix: 0/28 retained.
Retention chain (before fix):
DOMTimer → ScheduledAction → V8Function
→ CursorBlinkStateManager._renderCallback → WebglRenderer
→ Terminal
Terminal.resize() already no-ops internally when dimensions haven't
changed. The addon's guard prevented resize() from being called at all,
forcing callers using ResizeObserver-based layouts to use perturbation
workarounds (resize to rows-1, then fit) that race with the observer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>