From c113503ad131101b19b4a5c1e4639b8588ecd993 Mon Sep 17 00:00:00 2001
From: Kenta Iwasaki <63115601+lithdew@users.noreply.github.com>
Date: Mon, 15 Apr 2024 23:25:08 +0800
Subject: [PATCH] Flush direct streams in Bun (#28837)
## Summary
The ReadableStreamController for [direct
streams](https://bun.sh/docs/api/streams#direct-readablestream) in Bun
supports a flush() method to flush all buffered items to its underlying
sink.
Without manually calling flush(), all buffered items are only flushed to
the underlying sink when the stream is closed. This behavior causes the
shell rendered against Suspense boundaries never to be flushed to the
underlying sink.
## How did you test this change?
A lot of changes to the test runner will need to be made in order to
support the Bun runtime. A separate test was manually run in order to
ensure that the changes made are correct.
The test works by sanity-checking that the shell rendered against
Suspense boundaries are emitted first in the stream.
This test was written and run on Bun v1.1.3.
```ts
import { Suspense } from "react";
import { renderToReadableStream } from "react-dom/server";
if (!import.meta.resolveSync("react-dom/server").endsWith("server.bun.js")) {
throw new Error("react-dom/server is not the correct version:\n " + import.meta.resolveSync("react-dom/server"));
}
const A = async () => {
await new Promise(resolve => setImmediate(resolve));
return
hi
;
};
const B = async () => {
return (
loading}>
);
};
const stream = await renderToReadableStream();
let text = "";
let count = 0;
for await (const chunk of stream) {
text += new TextDecoder().decode(chunk);
count++;
}
if (
text !==
`loading
`
) {
throw new Error("unexpected output");
}
if (count !== 2) {
throw new Error("expected 2 chunks from react ssr stream");
}
```
---
packages/react-server/src/ReactServerStreamConfigBun.js | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/packages/react-server/src/ReactServerStreamConfigBun.js b/packages/react-server/src/ReactServerStreamConfigBun.js
index ac8ae3f1a52eb..4686e0e970b12 100644
--- a/packages/react-server/src/ReactServerStreamConfigBun.js
+++ b/packages/react-server/src/ReactServerStreamConfigBun.js
@@ -13,6 +13,7 @@ type BunReadableStreamController = ReadableStreamController & {
end(): mixed,
write(data: Chunk | BinaryChunk): void,
error(error: Error): void,
+ flush?: () => void,
};
export type Destination = BunReadableStreamController;
@@ -25,8 +26,12 @@ export function scheduleWork(callback: () => void) {
}
export function flushBuffered(destination: Destination) {
- // WHATWG Streams do not yet have a way to flush the underlying
- // transform streams. https://github.com/whatwg/streams/issues/960
+ // Bun direct streams provide a flush function.
+ // If we don't have any more data to send right now.
+ // Flush whatever is in the buffer to the wire.
+ if (typeof destination.flush === 'function') {
+ destination.flush();
+ }
}
export function beginWriting(destination: Destination) {}