Skip to content

fix(flterm): recover text input when a delta desyncs from the sentinel - #145

Open
jacobaraujo7 wants to merge 1 commit into
elias8:mainfrom
jacobaraujo7:fix/flterm-ios-input-desync
Open

fix(flterm): recover text input when a delta desyncs from the sentinel#145
jacobaraujo7 wants to merge 1 commit into
elias8:mainfrom
jacobaraujo7:fix/flterm-ios-input-desync

Conversation

@jacobaraujo7

Copy link
Copy Markdown
Contributor

Summary

On iOS, composing an accent (dead key + vowel) freezes the terminal: after the
accent commits, no further typing registers. Plain keys are fine until the first
accent.

Root cause

TextInputSession keeps a one-space sentinel and pushes it back via
setEditingState after every commit, translating deltas relative to it. iOS,
however, keeps its own marked-text buffer and ignores that reset right after
a composition. An accent commits an IME-like character (> 0x7f), the buffer is
reset on our side but not on iOS's, and the next delta iOS sends references
offsets past our sentinel value.

delta.apply(_value) then throws a RangeError. Because that happens inside
updateEditingValueWithDeltas, the exception tears down the platform text-input
channel — every subsequent keystroke is dropped, so typing freezes entirely.
Desktop platforms honor the reset, so they never hit it.

Fix

Guard each delta.apply; on failure, resync the platform back to the sentinel
and drop that batch instead of letting the exception kill the connection. The
channel stays alive and input keeps working.

Test

Adds a regression test that drives a delta whose range exceeds the sentinel
(which throws today) and asserts the session recovers, stays attached, and keeps
committing subsequent input. flutter analyze is clean; the full flterm suite
passes.

Note: the throwing delta is reproduced synthetically in the test. Validation
of the exact iOS accent sequence on a device/simulator is still recommended,
but the recovery is a strict robustness improvement regardless of the trigger.

The session keeps a one-space sentinel and pushes it back via setEditingState
after every commit. Some platforms -- notably iOS -- keep their own marked-text
buffer and ignore that reset, so a later delta references offsets past our
sentinel value. Applying it throws (RangeError), and because that happens
inside updateEditingValueWithDeltas the exception tears down the text-input
channel: typing freezes completely. It reproduces on iOS right after composing
an accent (dead key + vowel), which commits an IME-like character and resets
the buffer the platform then ignores.

Guard each delta.apply; on failure, resync the platform back to the sentinel
and drop the batch instead of letting the exception kill the connection. A
regression test drives a delta whose range exceeds the sentinel and asserts the
session recovers, stays attached, and keeps accepting input.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@elias8

elias8 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

The tests pass with and without the fix. I'm also not able to reproduce this on my phone; have you? What are the steps?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants