Skip to content

fix(runtime): preserve legacy input and clipped terminal output - #286

Merged
hyfdev merged 1 commit into
mainfrom
review/full-adversarial
Sep 7, 2026
Merged

hyfdev merged 1 commit into
mainfrom
review/full-adversarial

Conversation

@hyfdev-agent

@hyfdev-agent hyfdev-agent commented Aug 26, 2026 •

Copy link
Copy Markdown
Collaborator

Legacy shortcuts and clipped text can disappear, and an exception during deferred output settlement can prevent later output. This PR preserves those events and cells and releases failed output transactions.

ESC [       → key(character: "[", alt: true), after the Escape timeout
ESC 🙂      → key(character: "🙂", alt: true)
ESC ESC[200~helloESC[201~ → Escape, then paste("hello")

Fix

  • Decode UTF-8 input with a cursor and batch ASCII runs while preserving input ownership across byte boundaries.
  • Deliver legacy Alt/Ctrl identities through the public input subscription; complete CSI and SS3 sequences retain their named-key behavior.
  • Paint visible rows when a text write starts above the surface, and round text origins consistently with sibling layout.
  • Release output ownership when a deferred settlement callback throws. Keep blocked writes subject to suspension and teardown gates.
  • Document and test the fixed non-TTY document dimensions separately from test-emulator dimensions.

Validation

The mounted useInput regressions for Alt+[ and Alt+🙂 fail before the fix and pass after it. Integration tests cover Escape followed by UTF-8 paste, clipped rows, adjacent text, suspension, blocked output and non-TTY dimensions. Focused tests cover decoder boundaries and settlement callbacks. vp run check passes, including Runtime integration and real-PTY suites.

Implemented and reviewed with AI assistance.

@hyfdev-agent
hyfdev-agent force-pushed the review/full-adversarial branch 5 times, most recently from c70b08d to 4e19253 Compare August 26, 2026 09:01
@hyfdev
hyfdev force-pushed the review/full-adversarial branch 4 times, most recently from 23a0e13 to 466c529 Compare August 29, 2026 10:12
@hyfdev
hyfdev force-pushed the review/full-adversarial branch from 466c529 to 548e09f Compare August 29, 2026 10:47
@hyfdev
hyfdev force-pushed the review/full-adversarial branch 2 times, most recently from 02ca952 to ca8cb83 Compare September 7, 2026 14:38
@hyfdev hyfdev changed the title fix: correctness sweep across runtime, components, use, and vite fix(runtime): preserve legacy input and clipped terminal output Sep 7, 2026
Deliver legacy Alt and Ctrl shortcuts, retain Escape before bracketed paste, and decode large UTF-8 chunks in linear work. Keep visible paint rows and rounded text origins aligned with layout. Settle output ownership when a handoff observer throws, with mounted lifecycle and modeled-host coverage.
@hyfdev
hyfdev force-pushed the review/full-adversarial branch from ca8cb83 to 25589d9 Compare September 7, 2026 14:46
@hyfdev
hyfdev marked this pull request as ready for review September 7, 2026 14:50
Copilot AI lite review requested due to automatic review settings September 7, 2026 14:50
@hyfdev
hyfdev merged commit f418964 into main Sep 7, 2026
2 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Two newly added integration tests don’t consistently clean up created streams/writables, which risks leaking handles/timers and causing flaky or hanging CI runs.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR fixes several Runtime edge cases where legacy input chords and clipped paint rows could be dropped, and where output settlement errors could leave the output coordinator blocked, then adds integration/unit coverage and updates docs to reflect the corrected behavior.

Changes:

  • Improve legacy input handling (Alt-prefixed code points, Ctrl punctuation, Escape + paste framing) and UTF-8 decode performance while preserving event ownership across chunk boundaries.
  • Fix paint-cell preservation for multi-line writes that start above the surface and align Text origins consistently with fractional layout siblings.
  • Ensure output transactions unblock even when deferred settlement observers throw; expand integration/unit tests and adjust testing-host documentation around non-TTY document sizing.
File summaries
File Description
tests/runtime/integration/types/fixtures/template-children-types.vue Update type-fixture commentary to reflect the PublicComponent shim.
tests/runtime/integration/types/fixtures/jsx-children-types.tsx Update JSX type-fixture commentary to reflect the PublicComponent shim.
tests/runtime/integration/paint/write-above-surface.test.tsx New integration test covering visible-row preservation for writes starting above row 0.
tests/runtime/integration/paint/text-origin-grid.test.tsx New integration tests pinning Text origin rounding behavior against fractional siblings.
tests/runtime/integration/lifecycle/suspension-transaction.sequential.test.tsx Add sequential suspension/backpressure test for blocked write readiness behavior.
tests/runtime/integration/lifecycle/output-backpressure.test.tsx Add integration test ensuring patched console during backpressured teardown doesn’t deadlock exit.
tests/runtime/integration/lifecycle/mount-mode.test.tsx Add integration test asserting non-TTY mounts don’t probe controlling TTY size.
tests/runtime/integration/composables/use-input/legacy-shortcuts.test.tsx New integration coverage for legacy Alt/Ctrl shortcuts and Escape + UTF-8 paste sequencing.
README.md Update testing-host option docs (color/frames/screen async) and clarify supported Node engine range.
packages/testing/tests/render/host.test.tsx Add test asserting fullscreen-on-stream mounts the fixed document host (80x24).
packages/testing/src/render.ts Clarify columns/rows semantics in RenderOptions docstrings.
packages/testing/README.md Update testing docs for stream-host fullscreen behavior and clarify emulator vs modeled document sizing.
packages/runtime/tests/vue/public-input.test.ts Add unit coverage for projecting legacy Alt/Ctrl identities into the public input events.
packages/runtime/tests/terminal/output-coordinator.test.ts Add unit coverage for settlement observer throws still settling/unblocking transactions.
packages/runtime/tests/input/stdin-ingress-decode.test.ts New tests pinning large paste decode integrity and ASCII-run/UTF-8 boundary correctness.
packages/runtime/tests/input/parse-keypress/core.test.ts Add tests for Alt+Shift(O), Alt+punction, and SS3 precedence behavior.
packages/runtime/tests/input/input-parser.test.ts Add tests ensuring Escape isn’t swallowed by paste marker edge cases/splits.
packages/runtime/src/terminal/output-coordinator.ts Ensure deferred-settlement exceptions unblock/release the transaction correctly.
packages/runtime/src/paint/paint.ts Fix multi-line write row advancement when starting above surface; round Text origins; clarify viewport vs semantic geometry.
packages/runtime/src/layout/yoga.ts Align text cell-width clamping with rounded painted Text origins.
packages/runtime/src/input/shared-input-ingress.ts Optimize UTF-8 decode to avoid quadratic splicing and batch ASCII runs while tracking recipients.
packages/runtime/src/input/parse-keypress.ts Broaden legacy Alt parsing to one Unicode code point; correctly model Ctrl punctuation bytes and Alt chords.
packages/runtime/src/input/normalized-input.ts Treat astral-plane single code points as printable when determining key printability.
packages/runtime/src/input/input-parser.ts Prevent Escape from being merged into bracketed-paste markers (start/end) after ESC.
packages/runtime/README.md Tighten wording about removed ARIA/caret experiments and clarify absence of hidden enablement paths.
.gitignore Ignore /docs/ per repo policy for local working notes/specs.
.agents/docs/runtime-api-design.md Update example signature to use a public Box instance type (PublicBoxInstance).
Review details
  • Files reviewed: 26/27 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +421 to +443
test("a patched console record during backpressured teardown does not deadlock exit", async () => {
const slow = createSlowWritable({ highWaterMark: 1, firstDelayMs: 120, laterDelayMs: 40 });
const { stream: stdin } = makeTrackedStdin();
const App = defineComponent(() => () => <Text>{"x".repeat(8_192)}</Text>);
const app = createApp(App);
app.mount(
createInternalMountOptions({
stdin,
stdout: slow.stream,
stderr: makeFakeWritable(),
maxFps: 0,
patchConsole: true,
}),
);
// Deliberately not flushed: the first frame is still draining, so teardown parks
// on the output coordinator with the console gate still closed.
await nextTick();

app.unmount();
console.log("done");

await expect(app.waitUntilExit()).resolves.toBeUndefined();
}, 10_000);
Comment on lines +558 to +560
} finally {
app.unmount();
}
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.

3 participants