mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
Fixes #21189 `.pause()` should unref but it should still continue to emit `readable` events (although it should not send `data` events) also stdin.unref() should not pause input, it should only prevent stdin from keeping the process alive. DRAFT: - [x] ~~this causes a bug where `process.stdin.on("readable", () => {}); process.stdin.pause()` will allow the process to exit when it shouldn't.~~ fixed --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
156 lines
3.7 KiB
TypeScript
156 lines
3.7 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { bunEnv, bunExe } from "harness";
|
|
|
|
test("pipe does the right thing", async () => {
|
|
// Note: Bun.spawnSync uses memfd_create on Linux for pipe, which means we see
|
|
// it as a file instead of a tty
|
|
const result = Bun.spawn({
|
|
cmd: [bunExe(), "-e", "console.log(typeof process.stdin.ref)"],
|
|
stdin: "pipe",
|
|
stdout: "pipe",
|
|
stderr: "inherit",
|
|
env: bunEnv,
|
|
});
|
|
|
|
expect((await new Response(result.stdout).text()).trim()).toBe("function");
|
|
expect(await result.exited).toBe(0);
|
|
});
|
|
|
|
test("file does the right thing", async () => {
|
|
const result = Bun.spawn({
|
|
cmd: [bunExe(), "-e", "console.log(typeof process.stdin.ref)"],
|
|
stdin: Bun.file(import.meta.path),
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
env: bunEnv,
|
|
});
|
|
|
|
expect(await result.stdout.text()).toMatchInlineSnapshot(`
|
|
"undefined
|
|
"
|
|
`);
|
|
expect(await result.stderr.text()).toMatchInlineSnapshot(`""`);
|
|
expect(await result.exited).toBe(0);
|
|
});
|
|
|
|
test("stdin with 'readable' event handler should receive data when paused", async () => {
|
|
const proc = Bun.spawn({
|
|
cmd: [
|
|
bunExe(),
|
|
"-e",
|
|
`
|
|
const handleReadable = () => {
|
|
let chunk;
|
|
while ((chunk = process.stdin.read())) {
|
|
console.log("got chunk", JSON.stringify(chunk));
|
|
}
|
|
};
|
|
|
|
process.stdin.on("readable", handleReadable);
|
|
process.stdin.pause();
|
|
|
|
setTimeout(() => {
|
|
process.exit(1);
|
|
}, 1000);
|
|
`,
|
|
],
|
|
stdin: "pipe",
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
env: bunEnv,
|
|
});
|
|
|
|
proc.stdin.write("abc\n");
|
|
proc.stdin.write("def\n");
|
|
proc.stdin.end();
|
|
|
|
await proc.exited;
|
|
|
|
expect(await proc.stdout.text()).toMatchInlineSnapshot(`
|
|
"got chunk {"type":"Buffer","data":[97,98,99,10,100,101,102,10]}
|
|
"
|
|
`);
|
|
expect(await proc.stderr.text()).toMatchInlineSnapshot(`""`);
|
|
expect(proc.exitCode).toBe(1);
|
|
});
|
|
|
|
test("stdin with 'data' event handler should NOT receive data when paused", async () => {
|
|
const proc = Bun.spawn({
|
|
cmd: [
|
|
bunExe(),
|
|
"-e",
|
|
`
|
|
const handleData = chunk => {
|
|
console.log("got chunk");
|
|
};
|
|
|
|
process.stdin.on("data", handleData);
|
|
process.stdin.pause();
|
|
|
|
setTimeout(() => {
|
|
process.exit(1);
|
|
}, 1000);
|
|
`,
|
|
],
|
|
stdin: "pipe",
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
env: bunEnv,
|
|
});
|
|
|
|
proc.stdin.write("abc\n");
|
|
proc.stdin.write("def\n");
|
|
proc.stdin.end();
|
|
|
|
const [stdout, exitCode] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
|
|
|
|
expect(await proc.stdout.text()).toMatchInlineSnapshot(`""`);
|
|
expect(await proc.stderr.text()).toMatchInlineSnapshot(`""`);
|
|
expect(proc.exitCode).toBe(1);
|
|
});
|
|
|
|
test("stdin should allow process to exit when paused", async () => {
|
|
const proc = Bun.spawn({
|
|
cmd: [
|
|
bunExe(),
|
|
"-e",
|
|
`
|
|
process.stdin.on("data", () => {});
|
|
process.stdin.pause();
|
|
`,
|
|
],
|
|
stdin: "pipe",
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
env: bunEnv,
|
|
});
|
|
|
|
await proc.exited;
|
|
expect(await proc.stdout.text()).toMatchInlineSnapshot(`""`);
|
|
expect(await proc.stderr.text()).toMatchInlineSnapshot(`""`);
|
|
expect(proc.exitCode).toBe(0);
|
|
});
|
|
|
|
test("stdin should not allow process to exit when not paused", async () => {
|
|
const proc = Bun.spawn({
|
|
cmd: [
|
|
bunExe(),
|
|
"-e",
|
|
`
|
|
process.stdin.on("data", () => {});
|
|
`,
|
|
],
|
|
stdin: "pipe",
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
env: bunEnv,
|
|
});
|
|
|
|
await Bun.sleep(1000);
|
|
expect(proc.exitCode).toBe(null);
|
|
proc.kill();
|
|
await proc.exited;
|
|
expect(await proc.stdout.text()).toMatchInlineSnapshot(`""`);
|
|
expect(await proc.stderr.text()).toMatchInlineSnapshot(`""`);
|
|
});
|