Files
vue-tui/packages
Yunfei He c6be1f5a7a fix(runtime): attach the stdin input listener per-controller so two apps share one stdin (#118)
The terminal raw-mode toggle is refcounted per-stdin (a WeakMap shared across
controllers) so one app's unmount can't drop raw mode while another still needs
it — vue's deliberate improvement over Ink, whose per-App counts let the first
unmount disable raw for everyone. But the "data" input listener was ALSO gated
on that shared refcount, so when two apps (separate createApp/stdout) shared one
stdin, only the first app's handleData ever attached and the second was
permanently deaf — and it didn't even self-heal when the first unmounted (Ink at
least does, via its per-App readable listeners).

Make the "data" listener (and its synchronous clearInputState cleanup: parser
reset, pending-escape flush, listener detach) PER-CONTROLLER, gated on this
controller's own localRefs, while keeping the raw-mode enable/disable on the
shared refcount. Because vue uses the "data" (push) event, every listener gets
every chunk, so both apps now receive input — strictly better than Ink's
"readable" (pull) model where the first-registered listener drains the buffer.

Single-app behavior is byte-identical: with one controller localRefs and the
shared refs move 1:1, so the same-tick swap (parser reset + listener re-attach)
fires at exactly the same moments as before.

Test: two apps sharing one stdin both receive a keystroke, and the second keeps
receiving after the first unmounts while raw mode stays enabled (shared ref);
raw mode disables only when the last app unmounts.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 11:23:55 +08:00
..