Created
April 27, 2026 16:33
-
-
Save kommander/6497152a8792d8646576ee7fcb2baf30 to your computer and use it in GitHub Desktop.
Bun spurious stdin close repro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bun | |
| import { join } from "node:path" | |
| import { pathToFileURL } from "node:url" | |
| const RESOURCE_PATH = join(import.meta.dir, ".bun-stdin-close-tiny-repro.txt") | |
| const RESOURCE_URL = pathToFileURL(RESOURCE_PATH).href | |
| const PALETTE_QUERY = Array.from({ length: 256 }, (_, index) => `\x1b]4;${index};?\x07`).join("") | |
| const RESET_SEQUENCE = "\x1b[?2026l\x1b[?1003l\x1b[?1002l\x1b[?1000l\x1b[?1006l\x1b[?2004l\x1b[?1049l\x1b[?2031l\x1b[?25h\x1b[0m" | |
| const STARTUP_QUERIES = [ | |
| "\x1b[?2031h", | |
| "\x1b]10;?\x07\x1b]11;?\x07", | |
| "\x1b[>0q\x1b[?25l\x1b[s", | |
| "\x1b[6n", | |
| "\x1b[?1016$p\x1b[?2027$p\x1b[?2031$p\x1b[?1004$p\x1b[?2004$p\x1b[?2026$p\x1b[?u", | |
| "\x1b[H\x1b]66;w=1; \x1b\\\x1b[6n\x1b[H\x1b]66;s=2; \x1b\\\x1b[6n\x1b[u", | |
| "\x1b[s\x1b[?1049h\x1b[>4;1m\x1b[?2004h\x1b[?1000h\x1b[?1002h\x1b[?1003h\x1b[?1006h", | |
| "\x1b[14t", | |
| "\x1b[?2026h", | |
| ].join("") | |
| let reproduced = false | |
| let cleanedUp = false | |
| let resolveFinished = () => {} | |
| const finished = new Promise((resolve) => { | |
| resolveFinished = resolve | |
| }) | |
| function cleanup() { | |
| if (cleanedUp) return | |
| cleanedUp = true | |
| try { | |
| process.stdout.write(RESET_SEQUENCE) | |
| } catch {} | |
| try { | |
| process.stdin.setRawMode?.(false) | |
| } catch {} | |
| } | |
| function markReproduced() { | |
| if (reproduced) return | |
| reproduced = true | |
| resolveFinished() | |
| } | |
| process.stdin.on("data", () => {}) | |
| process.stdin.on("end", markReproduced) | |
| process.stdin.on("close", markReproduced) | |
| process.on("SIGINT", () => { | |
| cleanup() | |
| process.exit(130) | |
| }) | |
| process.on("SIGTERM", () => { | |
| cleanup() | |
| process.exit(143) | |
| }) | |
| process.on("exit", cleanup) | |
| process.stdin.setRawMode?.(true) | |
| process.stdin.resume() | |
| await Bun.write(RESOURCE_PATH, `${"x".repeat(64 * 1024)}\n`) | |
| // Let Bun finish loading internal modules before the actual repro starts. | |
| await Bun.sleep(250) | |
| process.stdout.write(STARTUP_QUERIES) | |
| setTimeout(() => { | |
| process.stdout.write("\x1b_Gi=31337,s=1,v=1,a=q,t=d,f=24;AAAA\x1b\\\x1b[c") | |
| }, 35) | |
| setTimeout(() => { | |
| process.stdout.write(PALETTE_QUERY) | |
| }, 55) | |
| setTimeout(() => { | |
| void (async () => { | |
| const response = await fetch(RESOURCE_URL) | |
| const reader = response.body?.getReader() | |
| if (!reader) return | |
| while (true) { | |
| const { done } = await reader.read() | |
| if (done) break | |
| } | |
| })() | |
| }, 35) | |
| await Promise.race([Bun.sleep(6000), finished]) | |
| cleanup() | |
| console.log(reproduced ? "REPRODUCED" : "NOT_REPRODUCED") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment