mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
Fix issue with exit callback in Bun.spawn() never firing
This commit is contained in:
@@ -4017,6 +4017,20 @@ pub const Strong = struct {
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn has(this: *Strong) bool {
|
||||
var ref = this.ref orelse return false;
|
||||
return ref.get() != .zero;
|
||||
}
|
||||
|
||||
pub fn trySwap(this: *Strong) ?JSValue {
|
||||
const result = this.swap();
|
||||
if (result == .zero) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn set(this: *Strong, globalThis: *JSC.JSGlobalObject, value: JSValue) void {
|
||||
var ref: *JSC.napi.Ref = this.ref orelse {
|
||||
if (value == .zero) return;
|
||||
|
||||
8
test/bun.js/bun-streams-test-fifo.sh
Normal file
8
test/bun.js/bun-streams-test-fifo.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echoerr() { echo "$@" 1>&2; }
|
||||
|
||||
echoerr "bun-streams-test-fifo.sh: starting"
|
||||
echo -e "$FIFO_TEST" >>${@: -1}
|
||||
echoerr "bun-streams-test-fifo.sh: ending"
|
||||
exit 0
|
||||
22
test/bun.js/mkfifo.ts
Normal file
22
test/bun.js/mkfifo.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { dlopen, ptr } from "bun:ffi";
|
||||
|
||||
var lazyMkfifo;
|
||||
export function mkfifo(path: string, permissions: number = 0o666): void {
|
||||
if (!lazyMkfifo) {
|
||||
const suffix = process.platform === "darwin" ? "dylib" : "so.6";
|
||||
lazyMkfifo = dlopen(`libc.${suffix}`, {
|
||||
mkfifo: {
|
||||
args: ["ptr", "i32"],
|
||||
returns: "i32",
|
||||
},
|
||||
}).symbols.mkfifo;
|
||||
}
|
||||
|
||||
const buf = new Uint8Array(Buffer.byteLength(path) + 1);
|
||||
new TextEncoder().encodeInto(path, buf);
|
||||
const rc = lazyMkfifo(ptr(buf), permissions);
|
||||
|
||||
if (rc < 0) {
|
||||
throw new Error(`mkfifo failed`);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,18 @@
|
||||
import { test, expect, it, describe } from "bun:test";
|
||||
import { readableStreamToText, spawn } from "bun";
|
||||
import { describe, expect, it } from "bun:test";
|
||||
|
||||
describe("spawn", () => {
|
||||
const hugeString = "hello".repeat(100000).slice();
|
||||
|
||||
it("stdin can write", async () => {
|
||||
const { stdin, stdout } = spawn({
|
||||
cmd: ["cat"],
|
||||
stdin: "pipe",
|
||||
it("stdout can be read", async () => {
|
||||
await Bun.write("/tmp/out.txt", hugeString);
|
||||
const { stdout } = spawn({
|
||||
cmd: ["cat", "/tmp/out.txt"],
|
||||
stdout: "pipe",
|
||||
});
|
||||
await stdin.write(hugeString);
|
||||
stdin.end();
|
||||
return readableStreamToText(stdout).then((text) => {
|
||||
expect(text).toBe(hugeString);
|
||||
});
|
||||
|
||||
const text = await readableStreamToText(stdout);
|
||||
expect(text).toBe(hugeString);
|
||||
});
|
||||
|
||||
describe("pipe", () => {
|
||||
|
||||
@@ -1,11 +1,72 @@
|
||||
import { file, readableStreamToArrayBuffer, readableStreamToArray } from "bun";
|
||||
import {
|
||||
file,
|
||||
readableStreamToArrayBuffer,
|
||||
readableStreamToArray,
|
||||
readableStreamToText,
|
||||
} from "bun";
|
||||
import { expect, it, beforeEach, afterEach } from "bun:test";
|
||||
import { writeFileSync } from "node:fs";
|
||||
import { mkfifo } from "mkfifo";
|
||||
import { unlinkSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { gc } from "./gc";
|
||||
new Uint8Array();
|
||||
|
||||
beforeEach(() => gc());
|
||||
afterEach(() => gc());
|
||||
it("Bun.file() read text from pipe", async () => {
|
||||
try {
|
||||
unlinkSync("/tmp/fifo");
|
||||
} catch (e) {}
|
||||
|
||||
mkfifo("/tmp/fifo", 0o666);
|
||||
|
||||
const large = "HELLO!".repeat((((1024 * 512) / "HELLO!".length) | 0) + 1);
|
||||
|
||||
const chunks = [];
|
||||
var out = Bun.file("/tmp/fifo").stream();
|
||||
const proc = Bun.spawn({
|
||||
cmd: [
|
||||
"bash",
|
||||
join(import.meta.dir + "/", "bun-streams-test-fifo.sh"),
|
||||
"/tmp/fifo",
|
||||
],
|
||||
stderr: "inherit",
|
||||
env: {
|
||||
FIFO_TEST: large,
|
||||
},
|
||||
});
|
||||
const exited = proc.exited;
|
||||
proc.ref();
|
||||
var prom = new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
(async function () {
|
||||
var reader = out.getReader();
|
||||
while (true) {
|
||||
const chunk = await reader.read();
|
||||
if (chunk.done) {
|
||||
if (chunks.length == 0) {
|
||||
out = Bun.file("/tmp/fifo").stream();
|
||||
reader = out.getReader();
|
||||
continue;
|
||||
}
|
||||
const output = new TextDecoder()
|
||||
.decode(new Uint8Array(Buffer.concat(chunks)))
|
||||
.trim();
|
||||
resolve(output);
|
||||
break;
|
||||
}
|
||||
chunks.push(chunk.value);
|
||||
}
|
||||
})();
|
||||
});
|
||||
});
|
||||
|
||||
const [status, output] = await Promise.all([exited, prom]);
|
||||
|
||||
expect(output.length).toBe(large.length);
|
||||
expect(output).toBe(large);
|
||||
expect(status).toBe(0);
|
||||
});
|
||||
|
||||
it("exists globally", () => {
|
||||
expect(typeof ReadableStream).toBe("function");
|
||||
@@ -191,7 +252,6 @@ it("ReadableStream for Blob", async () => {
|
||||
console.error(e);
|
||||
console.error(e.stack);
|
||||
}
|
||||
|
||||
if (chunk.done) break;
|
||||
chunks.push(new TextDecoder().decode(chunk.value));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user