From 3c0f5623dfab3f308a891491260edcb376827671 Mon Sep 17 00:00:00 2001 From: dormouse-bot <287024035+dormouse-bot@users.noreply.github.com> Date: Sat, 11 Jul 2026 08:22:30 +0000 Subject: [PATCH] fix(website): route trailing bytes to a program launched mid-chunk in tutorial shell MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TutorialShell.handleInput only checked activeProgram at the top of the method, so when a single input chunk both launched an interactive program (via a trailing \r) and carried the program's first keystroke — as a paste of "cmd\rinput" would — the leftover bytes were parsed as shell line-editor input instead of being forwarded to the just-started program. Forward any bytes remaining after a program launch to that program and stop parsing the chunk. Adds a regression test that fails without the fix. --- website/src/lib/tutorial-shell.test.ts | 16 ++++++++++++++++ website/src/lib/tutorial-shell.ts | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/website/src/lib/tutorial-shell.test.ts b/website/src/lib/tutorial-shell.test.ts index 3b22ed88..0e81c050 100644 --- a/website/src/lib/tutorial-shell.test.ts +++ b/website/src/lib/tutorial-shell.test.ts @@ -45,6 +45,22 @@ describe("TutorialShell program dispatch", () => { expect(output.join("")).toContain("$ "); }); + it("forwards trailing bytes to a program launched within the same chunk", () => { + const { program, shell, startProgram } = createHarness(); + + // A single chunk (e.g. a paste) both launches the program and carries the + // first keystroke for it. The trailing `q` must reach the program, not the + // shell line editor. + shell.handleInput("ascii-splash --no-mouse\rq"); + + expect(startProgram).toHaveBeenCalledWith( + "ascii-splash", + ["--no-mouse"], + expect.any(Function), + ); + expect(program.handleInput).toHaveBeenCalledWith("q"); + }); + it("disposes the active program with the shell", () => { const { program, shell } = createHarness(); diff --git a/website/src/lib/tutorial-shell.ts b/website/src/lib/tutorial-shell.ts index 8caa1fec..cb1efa97 100644 --- a/website/src/lib/tutorial-shell.ts +++ b/website/src/lib/tutorial-shell.ts @@ -101,6 +101,14 @@ export class TutorialShell { this.lineBuffer = ''; this.historyIndex = null; this.historyDraft = ''; + // `processCommand` may have launched an interactive program. Any bytes + // left in this chunk (e.g. a paste of `cmd\rinput`) belong to that + // program, not the shell line editor — forward them and stop parsing. + if (this.activeProgram) { + const rest = data.slice(index + 1); + if (rest) this.activeProgram.handleInput(rest); + return; + } } else if (ch === '\x7f' || ch === '\b') { if (this.lineBuffer.length > 0) { this.lineBuffer = this.lineBuffer.slice(0, -1);