mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
162 lines
4.3 KiB
TypeScript
162 lines
4.3 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { bunEnv, bunExe } from "harness";
|
|
|
|
describe.concurrent("spawnSync isolated event loop", () => {
|
|
test("JavaScript timers should not fire during spawnSync", async () => {
|
|
await using proc = Bun.spawn({
|
|
cmd: [
|
|
bunExe(),
|
|
"-e",
|
|
`
|
|
let timerFired = false;
|
|
|
|
// Set a timer that should NOT fire during spawnSync
|
|
const interval = setInterval(() => {
|
|
timerFired = true;
|
|
console.log("TIMER_FIRED");
|
|
process.exit(1);
|
|
}, 1);
|
|
|
|
// Run a subprocess synchronously
|
|
const result = Bun.spawnSync({
|
|
cmd: ["${bunExe()}", "-e", "Bun.sleepSync(16)"],
|
|
env: process.env,
|
|
});
|
|
|
|
clearInterval(interval);
|
|
|
|
console.log("SUCCESS: Timer did not fire during spawnSync");
|
|
process.exit(0);
|
|
`,
|
|
],
|
|
env: bunEnv,
|
|
stderr: "pipe",
|
|
stdout: "pipe",
|
|
});
|
|
|
|
const [stdout, exitCode] = await Promise.all([proc.stdout.text(), proc.exited]);
|
|
|
|
expect(stdout).toContain("SUCCESS");
|
|
expect(stdout).not.toContain("TIMER_FIRED");
|
|
expect(stdout).not.toContain("FAIL");
|
|
expect(exitCode).toBe(0);
|
|
});
|
|
|
|
test("microtasks should not drain during spawnSync", async () => {
|
|
await using proc = Bun.spawn({
|
|
cmd: [
|
|
bunExe(),
|
|
"-e",
|
|
`
|
|
queueMicrotask(() => {
|
|
console.log("MICROTASK_FIRED");
|
|
process.exit(1);
|
|
});
|
|
|
|
// Run a subprocess synchronously
|
|
const result = Bun.spawnSync({
|
|
cmd: ["${bunExe()}", "-e", "42"],
|
|
env: process.env,
|
|
});
|
|
|
|
console.log("SUCCESS: Timer did not fire during spawnSync");
|
|
process.exit(0);
|
|
`,
|
|
],
|
|
env: bunEnv,
|
|
stderr: "pipe",
|
|
stdout: "pipe",
|
|
});
|
|
|
|
const [stdout, exitCode] = await Promise.all([proc.stdout.text(), proc.exited]);
|
|
|
|
expect(stdout).toContain("SUCCESS");
|
|
expect(stdout).not.toContain("MICROTASK_FIRED");
|
|
expect(stdout).not.toContain("FAIL");
|
|
expect(exitCode).toBe(0);
|
|
});
|
|
|
|
test("stdin/stdout from main process should not be affected by spawnSync", async () => {
|
|
await using proc = Bun.spawn({
|
|
cmd: [
|
|
bunExe(),
|
|
"-e",
|
|
`
|
|
// Write to stdout before spawnSync
|
|
console.log("BEFORE");
|
|
|
|
// Run a subprocess synchronously
|
|
const result = Bun.spawnSync({
|
|
cmd: ["echo", "SUBPROCESS"],
|
|
env: process.env,
|
|
});
|
|
|
|
// Write to stdout after spawnSync
|
|
console.log("AFTER");
|
|
|
|
// Verify subprocess output
|
|
const subprocessOut = new TextDecoder().decode(result.stdout);
|
|
if (!subprocessOut.includes("SUBPROCESS")) {
|
|
console.log("FAIL: Subprocess output missing");
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log("SUCCESS");
|
|
process.exit(0);
|
|
`,
|
|
],
|
|
env: bunEnv,
|
|
stderr: "pipe",
|
|
stdout: "pipe",
|
|
});
|
|
|
|
const [stdout, exitCode] = await Promise.all([proc.stdout.text(), proc.exited]);
|
|
|
|
expect(stdout).toContain("BEFORE");
|
|
expect(stdout).toContain("AFTER");
|
|
expect(stdout).toContain("SUCCESS");
|
|
expect(exitCode).toBe(0);
|
|
});
|
|
|
|
test("multiple spawnSync calls should each use isolated event loop", async () => {
|
|
await using proc = Bun.spawn({
|
|
cmd: [
|
|
bunExe(),
|
|
"-e",
|
|
`
|
|
let timerCount = 0;
|
|
|
|
// Set timers that should NOT fire during spawnSync
|
|
setTimeout(() => { timerCount++; }, 10);
|
|
setTimeout(() => { timerCount++; }, 20);
|
|
setTimeout(() => { timerCount++; }, 30);
|
|
|
|
// Run multiple subprocesses synchronously
|
|
for (let i = 0; i < 3; i++) {
|
|
const result = Bun.spawnSync({
|
|
cmd: ["${bunExe()}", "-e", "Bun.sleepSync(50)"],
|
|
});
|
|
|
|
if (timerCount > 0) {
|
|
console.log(\`FAIL: Timer fired during spawnSync iteration \${i}\`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
console.log("SUCCESS: No timers fired during any spawnSync call");
|
|
process.exit();
|
|
`,
|
|
],
|
|
env: bunEnv,
|
|
stderr: "pipe",
|
|
stdout: "pipe",
|
|
});
|
|
|
|
const [stdout, exitCode] = await Promise.all([proc.stdout.text(), proc.exited]);
|
|
|
|
expect(stdout).toContain("SUCCESS");
|
|
expect(stdout).not.toContain("FAIL");
|
|
expect(exitCode).toBe(0);
|
|
});
|
|
});
|