aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-10-10 20:57:38 -0700
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-10-10 20:57:38 -0700
commit3cc61f8e30f494c10de08de8afcf7bef3dd67fec (patch)
tree11066938a4014f211aa286e93e9d5cfa66b8b567
parentef2c9c330c1cf6a79a27d9ce06af1bdc7b5b18b6 (diff)
downloadbun-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.zig14
-rw-r--r--test/bun.js/bun-streams-test-fifo.sh8
-rw-r--r--test/bun.js/mkfifo.ts22
-rw-r--r--test/bun.js/spawn.test.ts18
-rw-r--r--test/bun.js/streams.test.js66
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));
}