diff options
author | 2022-10-10 20:57:38 -0700 | |
---|---|---|
committer | 2022-10-10 20:57:38 -0700 | |
commit | 3cc61f8e30f494c10de08de8afcf7bef3dd67fec (patch) | |
tree | 11066938a4014f211aa286e93e9d5cfa66b8b567 | |
parent | ef2c9c330c1cf6a79a27d9ce06af1bdc7b5b18b6 (diff) | |
download | bun-3cc61f8e30f494c10de08de8afcf7bef3dd67fec.tar.gz bun-3cc61f8e30f494c10de08de8afcf7bef3dd67fec.tar.zst bun-3cc61f8e30f494c10de08de8afcf7bef3dd67fec.zip |
Fix issue with exit callback in Bun.spawn() never firing
Diffstat (limited to '')
-rw-r--r-- | src/bun.js/base.zig | 14 | ||||
-rw-r--r-- | test/bun.js/bun-streams-test-fifo.sh | 8 | ||||
-rw-r--r-- | test/bun.js/mkfifo.ts | 22 | ||||
-rw-r--r-- | test/bun.js/spawn.test.ts | 18 | ||||
-rw-r--r-- | test/bun.js/streams.test.js | 66 |
5 files changed, 115 insertions, 13 deletions
diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig index 59cad571b..199a1c381 100644 --- a/src/bun.js/base.zig +++ b/src/bun.js/base.zig @@ -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; diff --git a/test/bun.js/bun-streams-test-fifo.sh b/test/bun.js/bun-streams-test-fifo.sh new file mode 100644 index 000000000..57650ba1d --- /dev/null +++ b/test/bun.js/bun-streams-test-fifo.sh @@ -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 diff --git a/test/bun.js/mkfifo.ts b/test/bun.js/mkfifo.ts new file mode 100644 index 000000000..48471cbf5 --- /dev/null +++ b/test/bun.js/mkfifo.ts @@ -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`); + } +} diff --git a/test/bun.js/spawn.test.ts b/test/bun.js/spawn.test.ts index 0d62d0a5b..a393922c0 100644 --- a/test/bun.js/spawn.test.ts +++ b/test/bun.js/spawn.test.ts @@ -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", () => { diff --git a/test/bun.js/streams.test.js b/test/bun.js/streams.test.js index 1268a04c0..20aa5c270 100644 --- a/test/bun.js/streams.test.js +++ b/test/bun.js/streams.test.js @@ -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)); } |