The recorded composition extent tracks the preedit, so for any conversion engine
it overshoots the commit it produced. Used as a floor it made the strict variant
of the pending-input read exclude nothing, and the character typed straight after
a commit went to the pty twice.
Co-authored-by: Orca <help@stably.ai>
`CompositionHelper._handleAnyTextareaChanges` is the path an active IME takes
when it commits a plain glyph outside a composition — punctuation and digits,
the first key after a macOS input-source switch, Sogou/fcitx candidate commits
on Linux. `xterm-bypass-policy.ts` deliberately lets a bare keydown-229 through
to it on both platforms, so this is live product behavior, not a latent path.
It derived the new text as `newValue.replace(oldValue, '')`. String.replace
removes the first occurrence of the pattern *anywhere*, not a prefix, so any
insertion that was not a pure append produced garbage: a buffer of "ab" with
the caret between the two characters gaining an "x" sent the whole "axb" to the
pty instead of "x". Confirmed by running the new tests against the prior patch —
they fail with `expected [ 'axb' ] to deeply equal [ 'x' ]`.
Records the caret alongside the buffer and reads the insertion as the slice
between two known offsets, which is what `_finalizeComposition` already does
and what the IME rule in AGENTS.md requires. When the caret does not account
for the growth the evidence is ambiguous and nothing is emitted rather than
guessing bytes into a live shell. `_dataAlreadySent` now always equals the text
actually sent, which is the invariant its consumer assumes when it advances the
composition start to avoid re-sending (xterm Issue #3191).
Deletion and same-length-replacement keep their existing behavior; neither is
the defect proven here. Windows keeps full 229 suppression: its race is preedit
reaching the textarea before compositionstart, which still reads as an ordinary
insertion, so the range fix does not close it.
Co-authored-by: Orca <help@stably.ai>
The xterm patch is 7.3 MB of diff over minified bundles with no recorded
provenance, so no one could regenerate it or tell whether the source hunks and
the bundle hunks still agree. Any IME fix that touches CompositionHelper had to
be hand-applied to four generated files.
Adds config/patches/xterm-src/ as the source of truth (832 lines over four
files), a pinned upstream manifest, and a generator that rebuilds the bundles
from that commit with the toolchain its lockfile pins, then derives the full
patch. `--check` runs it in CI as the new xterm_patch_sync job.
The committed patch is regenerated to match pnpm's own diff output (-U3 rather
than the hand-made -U6). This changes the patch bytes but no installed byte:
both patches applied to pristine tarballs produce recursively identical trees,
and all 8 patched files hash-identical to the installed package. pnpm's
patchedDependencies hash is sha256 of the patch file — verified for all five of
Orca's patches — so pnpm-lock.yaml carries the matching one-line update.