Commit Graph
11252 Commits
Author SHA1 Message Date
Graciliano Monteiro PassosandDaniel Imms 576181d93d Add OmnyShell PWA to the list of tools (#6034)
Co-authored-by: Daniel Imms <2193314+Tyriar@users.noreply.github.com>
2026-08-09 05:54:39 -07:00
kkd927andDaniel Imms eef62138a4 Add kmux to real-world uses (#6031)
Co-authored-by: Daniel Imms <2193314+Tyriar@users.noreply.github.com>
2026-08-09 05:54:04 -07:00
dependabot[bot]andPretaSOFT c793c317fd build(deps-dev): Bump fast-uri from 3.1.2 to 3.1.5 (#6091)
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.2 to 3.1.5.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](https://github.com/fastify/fast-uri/compare/v3.1.2...v3.1.5)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-09 05:52:59 -07:00
dependabot[bot]andPretaSOFT a4e4e28f97 build(deps-dev): Bump undici from 7.25.0 to 7.29.0 (#6088)
Bumps [undici](https://github.com/nodejs/undici) from 7.25.0 to 7.29.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v7.25.0...v7.29.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 7.29.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-09 05:52:51 -07:00
Bob LeeandDaniel Imms 4452773563 Add BitFun to real-world uses (#6092)
Co-authored-by: Daniel Imms <2193314+Tyriar@users.noreply.github.com>
2026-08-09 05:52:24 -07:00
Gevik BabakhaniandDaniel Imms 7aea5197d8 Add JSVision to real-world uses (#6085)
Co-authored-by: Daniel Imms <2193314+Tyriar@users.noreply.github.com>
2026-08-09 05:50:48 -07:00
Ark0NandDaniel Imms 9f39dc2bf9 Add Codeman to real-world uses (#6082)
Co-authored-by: Daniel Imms <2193314+Tyriar@users.noreply.github.com>
2026-08-09 05:50:08 -07:00
KindaBrazy 330eaaf205 add "LynxHub" to Real-world uses. (#6077) 2026-08-09 05:49:33 -07:00
Anthony Kim 904ae93526 Merge pull request #6055 from heudev/fix-shared-atlas-clear-invalidation
Fix stale rendering after a shared texture atlas is cleared
2026-07-26 21:24:07 -07:00
Anthony Kim 699f5537b0 Merge pull request #6056 from anthonykim1/anthonykim1/webgl-atlas-tui-stress-dual-coverage
Add WebGL atlas alternate-buffer stress test and refine the manual rendering demo
2026-07-19 16:26:06 -07:00
Anthony Kim abce6f1c62 call scroll output 2026-07-17 11:36:15 -07:00
Anthony Kim 4d93815c36 Improve types in webglatlasstress.test.ts 2026-07-17 11:31:12 -07:00
Anthony Kim 5b00193876 adjust button style 2026-07-17 11:17:30 -07:00
Enes Uysal 0b1c0b5c5a Fix stale rendering after a shared texture atlas is cleared
TextureAtlas.clearTexture() wipes every page and both cache maps but never
bumped _pageLayoutVersion, so it silently broke the invalidation contract that
#6042 introduced for shared atlases.

The atlas is shared by every terminal with an equal config (CharAtlasCache),
but WebglRenderer.clearTextureAtlas() only clears the *calling* renderer's
model. Every other owner keeps vertex data pointing into the rows that were
just wiped, and GlyphRenderer.beginFrame() has no way to notice, so those
terminals keep drawing from stale texture coords until something else happens
to invalidate them. Once the clearing terminal rasterizes new glyphs into the
freed rows, the siblings render whatever landed there instead of their own
text.

Embedders hit this whenever they force a redraw on one terminal while others
are alive; VS Code calls Terminal.clearTextureAtlas() on OS resume, which is
why a stale terminal there stays garbled even after opening a new one (the new
terminal re-acquires the same cached atlas) and only recovers once the whole
panel is closed and the last owner drops the atlas.

Bump _pageLayoutVersion on clear so sibling renderers rebuild their models on
their next frame, matching what page merges and evictions already do.

The added test fails on master (terminal B's row renders terminal A's flood
glyphs) and passes with the fix.
2026-07-16 18:38:24 +03:00
Anthony Kim ce21694856 Merge pull request #6043 from anthonykim1/anthonykim1/webgl-atlas-page-cap-eviction
Prevent WebGL atlas pages from exceeding texture capacity
2026-07-15 09:34:06 -07:00
Anthony Kim 2ea67f9ea8 Clean up WebGL atlas overflow coverage 2026-07-13 11:49:25 -07:00
Anthony Kim 2ae6e3a603 Useful comments. 2026-07-13 11:23:39 -07:00
Anthony Kim 06ce754fcc Don't mess with formatting 2026-07-13 11:10:08 -07:00
Anthony Kim 6791a0abea Log to measure eviction time 2026-07-13 10:58:05 -07:00
Anthony Kim 5501e931f7 Merge branch 'master' into anthonykim1/webgl-atlas-page-cap-eviction 2026-07-13 10:20:44 -07:00
Anthony Kim b1aee19ac6 Merge pull request #6042 from anthonykim1/anthonykim1/webgl-shared-atlas-pages-version
Fix stale rendering after shared texture atlas page merges
2026-07-13 10:16:29 -07:00
Anthony Kim 2b982bc39c Prevent WebGL atlas page overflow 2026-07-09 15:54:33 -07:00
Anthony Kim 8237004d5c Add WebGL atlas page overflow repros 2026-07-09 15:51:27 -07:00
Anthony Kim 9559005bbc wroding 2026-07-09 11:39:38 -07:00
Anthony Kim 46556eb6cf Rename to pageLayoutVersion 2026-07-09 11:32:23 -07:00
Anthony Kim 64ecce4f25 Do a better job with types in testing 2026-07-09 11:18:29 -07:00
Anthony Kim 77bf56066c wordings 2026-07-09 11:00:31 -07:00
Anthony Kim 6fe6fe1af3 Fix shared atlas page invalidation per renderer 2026-07-04 14:44:23 -07:00
Anthony Kim 780cbef3cf Add shared atlas page merge garble repro 2026-07-04 14:43:52 -07:00
Anthony Kim 8aab310366 Merge pull request #6019 from anthonykim1/anthonykim1/fix-terminal-window-mouse-listeners
Use current document for mouse listeners
2026-06-28 13:56:22 -07:00
Anthony Kim 9f232d981b destructure doc from target like the old days 2026-06-16 19:53:03 -07:00
Anthony Kim 1efd80cd17 Dont forget target.document 2026-06-16 19:44:27 -07:00
Anthony Kim 1701dcef90 use disposables for transient mouse listeners 2026-06-16 19:35:29 -07:00
Anthony Kim 55dbe3b65e use current document for mouse listeners 2026-06-16 19:21:19 -07:00
Paul Horn 53a98a720a Add Cate to real-world uses (#6013) 2026-06-13 03:12:27 -07:00
dependabot[bot]andPretaSOFT b69ae4b3c9 build(deps-dev): Bump esbuild from 0.28.0 to 0.28.1 (#6016)
Bumps [esbuild](https://github.com/evanw/esbuild) from 0.28.0 to 0.28.1.
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.28.0...v0.28.1)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.28.1
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-13 03:09:12 -07:00
3cdbc77386 fix(addon-search): advance highlight scan by buffer match size (#5994)
* fix(addon-search): advance highlight scan by buffer match size

_highlightAllMatches() stepped to the next find() using term.length
and col + 1 when staying on the same row. Search results expose size
in buffer columns (wide glyphs, wrapped matches), which select() and
decorations already use.

Advance with col + size and wrap row/col when crossing the terminal
width so highlight-all does not skip, duplicate, or stop early on
non-ASCII matches.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(addon-search): regression for highlight-all wide char advance by size

Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>

* test(addon-search): move highlight-all regression to integration tests

Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>
2026-06-06 11:12:04 -07:00
f57b8e1534 Update GitHub Actions to Node 24 compatible versions (#6007)
Upgrade actions/checkout, setup-node, upload-artifact, download-artifact,
and codeql-action to their latest major versions that run on Node 24.

Replace NathanFirmo/wait-for-other-job with native needs: build for
test-unit and test-integration jobs.

Fixes #6006

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>
2026-06-06 16:58:42 +00:00
c8f11d63b5 fix(terminal): always run clear() at cursor home (#5992)
Remove early return when ybase===0 && y===0 so clear() always
clears markers, resets buffer lines, and refills the viewport.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>
2026-06-06 16:43:22 +00:00
3d929a1db0 fix(selection): drag-scroll end row and trim start clamp (#5993)
* fix(selection): drag-scroll end row matches last visible line

Use ydisp + rows - 1 for selectionEnd when scrolling down during drag,
consistent with finalSelectionEnd for select-all.

Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>

* fix(selection): reset start to origin when start row is trimmed

When handleTrim removes the selection start row, clamp to [0,0] and
refresh; do not keep a stale column on row 0.

Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>
2026-06-06 16:18:47 +00:00
2fe3fd13a1 fix(addon-webgl): skip missing buffer lines in _updateModel (#5991)
* fix(addon-webgl): skip missing buffer lines in _updateModel

_updateModel force-unwrapped buffer.lines.get(row), which can be
undefined during trim or resize. That threw and left stale glyphs on
rows below the gap.

Clear the WebGL model row and glyph cells, reset blink state, and
continue with remaining viewport rows, matching DomRenderer and
ImageStorage handling.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(addon-webgl): extract _nullModelCell helper

Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>
2026-06-06 09:15:09 -07:00
Daniel ImmsandCursor f33f502267 fix(DomRenderer): resilience when buffer lines are missing (#5998)
* fix(DomRenderer): skip missing buffer lines during row render

renderRows and link underline refresh stopped updating when any
viewport row lacked buffer data, leaving stale DOM on rows below.
Match ImageStorage.render behavior: clear the row element when
present and continue with remaining rows.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(DomRenderer): clear blink state when skipping missing lines

When a viewport row has no buffer line, renderRows clears the row DOM
and continues but did not reset _rowHasBlinkingCells for that row.
That could leave the text blink manager thinking blinking cells remain
after the row was emptied.

Clear blink state for the row when skipping a missing buffer line,
including during link underline refresh.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 09:09:32 -07:00
jerch 7c24c58007 fix non-ascii clipboard handling (#6002)
* fix non-ascii clipboard handling

* rename type helpers

* make linter happy
2026-06-06 09:07:03 -07:00
jerch 596634ac41 fix #6003 (#6004) 2026-06-06 09:02:43 -07:00
jerch 0c8271db49 fix atlas callstack exception (#6001)
* fix atlas callstack exception

* remove spread operator, integrate stress test into demo
2026-06-06 09:01:49 -07:00
Daniel ImmsandCursor f3f4dcaf9f fix(CharacterJoiner): bound join ranges to trimmed line length (#5990)
Character joiner scanning already iterated cells with
getTrimmedLength(), but trailing attribute runs and
_stringRangesToCellRanges used buffer cols. On short lines that
could run joiners on a single trailing cell and extend open ranges
through empty tail columns, affecting ligature/join rendering.

Use trimmed length consistently for trailing-run detection, the
cell-range walk, and the final range end column.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 07:05:19 -07:00
64718444e2 fix(webgl): avoid glyph atlas mipmaps (#5987)
Co-authored-by: Will Hampson <whamp@ggl.slmail.me>
Co-authored-by: jerch <jerch@rockborn.de>
2026-06-03 06:00:44 -07:00
ea75b99e2b fix(deps): override serialize-javascript to ^7.0.3 (#5989)
Mocha 11.7.x pulls in serialize-javascript 6.0.2, which is affected by
code injection via RegExp.flags and Date.toISOString (CVE incomplete fix).
Force the patched 7.x release via npm overrides.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>
2026-06-02 13:34:19 +00:00
Daniel ImmsandCursor 564113e053 Add unit tests for parser reset, buffer scroll, ConPTY, and search (#5988)
* Add InputHandler unit tests for ISO-2022 charset mapping

InputHandler unit tests always used MockCharsetService, so regressions in
print()'s ASCII remapping, G0/G1 designation (ESC ( ) * +), and SO/SI
level switching were never caught at unit level.

Add an ISO-2022 character sets suite wired to real CharsetService and
BufferService that verifies DEC line drawing on G0 (ESC ( 0), G1 after
ESC ) 0 + SO, and charset/glevel restoration via ESC 7 / ESC 8 before
printing.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add BufferService.scroll unit tests for isUserScrolling

BufferService.scroll() adjusts ybase and ydisp differently depending on
whether the circular buffer is full and whether isUserScrolling is set,
but no unit test asserted those branches. InputHandler and other callers
use MockBufferService.scroll, which throws, so real scroll viewport logic
was only exercised indirectly.

Add BufferService.test.ts covering full-buffer scroll with the user
scrolled up (ydisp decrements), partial-buffer scroll while scrolled up
(ydisp unchanged), and full-buffer scroll at the viewport bottom
(ydisp tracks ybase).

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add InputHandler unit tests for DECOM cursor positioning

CUP with DEC origin mode (DECOM) offsets rows by the scroll region top
and clamps within DECSTBM margins, but unit tests only toggled the mode
for save/restore. Playwright covered the combination; headless unit tests
did not.

Add a cursor positioning test matching the Playwright DECOM case: with
margins and origin on, CUP places the cursor relative to scrollTop, clamps
to the margin, and uses absolute rows when origin is off.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add WindowsMode unit tests for wrap heuristic edges

ConPTY does not set isWrapped on soft-wrapped lines; updateWindowsModeWrappedState
infers wrapping from the last cell of the previous row. Browser Terminal tests
exercise this only through full writes, with no direct coverage of the helper
or negative cases (trailing space or null).

Add WindowsMode.test.ts asserting isWrapped is set for a full non-space line,
cleared for trailing whitespace, and cleared when the previous line ends empty.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add OscParser.reset unit test for mid-payload abort

OscParser.reset() must call end(false) on active handlers when aborted
during PAYLOAD, but no test invoked reset() directly. EscapeSequenceParser
tests mock OSC, so production reset/cleanup was unverified at unit level.

Add a reset describe block asserting handlers receive END false after a
partial payload, then a subsequent OSC sequence completes normally.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add DcsParser.reset unit test for mid-payload abort

DcsParser.reset() must call unhook(false) on hooked handlers when aborted
mid-DCS, matching OscParser's end(false) cleanup. No DcsParser test called
reset() directly, leaving the abort path unverified at unit level.

Add a reset describe block asserting UNHOOK false after partial put, then a
subsequent DCS sequence completes with UNHOOK true.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add InputHandler print tests for grapheme joining

print() uses UnicodeService.shouldJoin to merge combining marks, but
InputHandler tests never exercised that path. The U+200B infinite-loop
regression test used mocks and had no assertions, so it would pass even
if print() misbehaved.

Add tests for e + combining acute in one parse and across two parses.
Strengthen the U+200B regression test to use BufferService and assert the
buffer does not grow spurious rows.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add CharsetService unit tests for glevel and designation

CharsetService only updates the active charset when setgCharset targets the
current glevel; most InputHandler tests use MockCharsetService instead. A
regression in setgLevel or inactive-slot designation would not be caught
without direct service tests.

Add CharsetService.test.ts covering inactive designation, setgLevel
activation, active-slot updates, and reset clearing state.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add reflowCursorLine unit tests for ConPTY resize behavior

reflowCursorLine lets resize reflow wrapped lines that contain the cursor
(needed when ConPTY does not). No test referenced the option or
reflowLargerGetLinesToRemove's cursor skip branch.

Add BufferReflow tests for skip vs reflow when the cursor is inside a
wrapped block, and Buffer.resize tests showing merge on widen only when
reflowCursorLine is enabled.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add EscapeSequenceParser reset test for async pause recovery

reset() sets ParserStackType.RESET so the next parse continues in GROUND
at chunkPos + 1 without resuming a paused async handler. Existing async
tests only verified reset lifts FAIL after improper continuation, not
mid-chunk recovery with trailing printable data.

Add a test that pauses on async CSI, calls reset(), then continues parsing
and asserts XY is printed once and the stack returns to NONE.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add Buffer.resize unit test for ConPTY row growth

When rows increase on Windows ConPTY, Buffer.resize appends lines without
decrementing ybase or ydisp so the viewport stays stable while ConPTY
repaints. Buffer tests covered the non-Windows scroll-up path but never
passed windowsPty into options.

Add a ConPTY row-growth test asserting ybase, ydisp, and line count when
windowsPty is configured.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add Buffer reflow test for ConPTY buildNumber threshold

Buffer disables reflow on ConPTY when buildNumber is below 21376, but no
unit test asserted that gate. Column shrink without reflow leaves wrapped
content on a single line instead of splitting across rows.

Add a test comparing shrink behavior at build 21375 versus 21376, plus
retain unwrap-on-widen coverage for supported ConPTY builds.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add ApcParser.reset unit test for mid-payload abort

ApcParser.reset() calls end(false) on active handlers when aborted mid-APC,
matching OscParser and DcsParser, but no ApcParser test invoked reset()
directly.

Add a reset describe block asserting END false after partial put and a
clean subsequent APC sequence.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add InputHandler unit test for REP with grapheme clusters

repeatPrecedingCharacter uses parser.precedingJoinState and reprints the
full cluster from the buffer, but only Playwright covered e + combining
acute with CSI b. A regression could break REP for joined sequences without
failing unit tests.

Add a print-suite test asserting CSI 2 b triples e + acute in one parse.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add InputHandler unit tests for REP no-op cases

repeatPrecedingCharacter returns early when parser.precedingJoinState is
zero, including after another escape sequence clears join state. Only the
positive grapheme REP case was unit tested.

Add tests for bare CSI b and for REP following SGR so regressions cannot
spuriously duplicate buffer content.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add DecorationManager unit test for wrapped search matches

DecorationManager splits matches across wrapped rows with per-segment x
and width, but only SearchEngine had unit coverage; decoration geometry
was left to Playwright.

Add DecorationManager.test.ts using a real Terminal, a wrapped-buffer
match from SearchEngine, and assertions on registerDecoration options
for both row segments.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add BufferService.scroll unit test for DECSTBM margins

When scrollTop is non-zero, scroll() shifts lines inside the margin with
shiftElements instead of pushing scrollback. Existing BufferService tests
only covered scrollTop === 0.

Add a test with margins on rows 1–3 that verifies rows outside the region
stay fixed and lines inside the region scroll correctly.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add BufferService.scrollLines unit tests

scrollLines adjusts ydisp and toggles isUserScrolling for viewport
scrolling, but only scroll() had unit coverage. Regressions in the
user-scroll flag or ydisp clamping would affect the whole viewport.

Add tests for scrolling up, clamping at ydisp 0, and clearing
isUserScrolling when reaching the buffer bottom.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add DecorationManager overview ruler dedup unit test

Multiple highlight matches on the same buffer line should only register
one overview ruler marker; later matches on that line omit ruler options.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Assert overview ruler on each line of wrapped search match

Wrapped highlight decorations span two buffer lines; each segment
should register overview ruler options unlike same-line dedup.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 12:41:54 +00:00
b3de9fa6db fix(buffer): clear stale attrs and combined data in BufferLine (#5972)
* fix(buffer): bound combined-cell copy in copyCellsFrom

When copying a column range, combined-string metadata was copied for
every source column >= srcCol with no upper limit. Partial copies could
pull _combined entries from outside [srcCol, srcCol + length) into the
destination and corrupt cells beyond the copied span.

Only copy combined keys within the same range as the cell data loop.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(buffer): clear stale _combined entry in BufferLine.setCell

setCell updated combined data when IS_COMBINED_MASK was set but left
orphaned _combined[index] entries when writing a non-combined cell.
Delete the map entry in that case so later combined copies and lookups
stay aligned with cell content flags.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(buffer): clear stale extended attrs in BufferLine.setCell

setCell stored extended attributes when HAS_EXTENDED was set but did
not remove orphaned _extendedAttrs[index] when overwriting with a
cell without extended background data. Delete the entry in that case,
matching the combined-cell cleanup added for setCell earlier.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(buffer): clear dest extended attrs in copyCellsFrom

When copying a column range, extended attributes were copied from
source cells with HAS_EXTENDED but stale _extendedAttrs on the
destination were left for cells without extended data. Delete dest
entries in that case, matching setCell behavior and the bounded
_combined copy loop.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(buffer): clear extended attrs in setCellFromCodepoint

The input-handler fast path set extended data when HAS_EXTENDED was
present but left orphaned _extendedAttrs entries when overwriting
with non-extended cells. Delete the map entry in that case, matching
setCell and copyCellsFrom.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(buffer): clear stale combined data in setCellFromCodepoint

When the input handler overwrites a cell that previously held a
grapheme cluster (IS_COMBINED_MASK), setCellFromCodepoint updated
_data and _extendedAttrs but left this._combined[index] intact.
setCell already deletes _combined for non-combined cells; this path
did not, so getString and renderers could show the old cluster string
after a normal codepoint write.

Add delete this._combined[index] at the start of setCellFromCodepoint,
matching setCell's non-combined branch and the extended-attrs cleanup
already performed in the same method.

Co-authored-by: Cursor <cursoragent@cursor.com>

* perf(buffer): only delete stale combined/extended map entries when present

Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>

* fix(buffer): treat combined/extended maps as flag-gated caches

_flags in _data are authoritative; sparse maps are only read when
IS_COMBINED_MASK or HAS_EXTENDED is set. setCellFromCodepoint no longer
touches _combined. loadCell clears CellData side fields when flags are off.
copyCellsFrom copies map entries per-cell from src flags only.

Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>
2026-06-02 03:04:25 +00:00