@samitouri / QOS-React-1 / commits / b4455a6ee6

[react-dom] Include all Node.js APIs in Bun entrypoint for `/server` (#34193)

Michael H committed Oct 28, 2025 at 09:06 UTC b4455a6ee6450fae830ae0b6e53e77f7a147bc27
7 files changed +65 -4
packages/react-dom/npm/server.bun.js
+2
@@ -12,6 +12,8 @@ if (process.env.NODE_ENV === 'production') {
12
13 exports.version = b.version;
14 exports.renderToReadableStream = b.renderToReadableStream;
15 +exports.renderToPipeableStream = b.renderToPipeableStream;
16 +exports.resumeToPipeableStream = b.resumeToPipeableStream;
17 exports.resume = b.resume;
18 exports.renderToString = l.renderToString;
19 exports.renderToStaticMarkup = l.renderToStaticMarkup;
packages/react-dom/server.bun.js
+14
@@ -38,3 +38,17 @@ export function resume() {
38 arguments,
39 );
40 }
41 +
42 +export function renderToPipeableStream() {
43 + return require('./src/server/react-dom-server.bun').renderToPipeableStream.apply(
44 + this,
45 + arguments,
46 + );
47 +}
48 +
49 +export function resumeToPipeableStream() {
50 + return require('./src/server/react-dom-server.bun').resumeToPipeableStream.apply(
51 + this,
52 + arguments,
53 + );
54 +}
packages/react-dom/src/server/react-dom-server.bun.js
+11
@@ -8,3 +8,14 @@
8 */
9
10 export * from './ReactDOMFizzServerBun.js';
11 +export {
12 + renderToPipeableStream,
13 + resumeToPipeableStream,
14 + resume,
15 +} from './ReactDOMFizzServerNode.js';
16 +export {
17 + prerenderToNodeStream,
18 + prerender,
19 + resumeAndPrerenderToNodeStream,
20 + resumeAndPrerender,
21 +} from './ReactDOMFizzStaticNode.js';
packages/react-dom/src/server/react-dom-server.bun.stable.js
+11
@@ -8,3 +8,14 @@
8 */
9
10 export {renderToReadableStream, version} from './ReactDOMFizzServerBun.js';
11 +export {
12 + renderToPipeableStream,
13 + resume,
14 + resumeToPipeableStream,
15 +} from './ReactDOMFizzServerNode.js';
16 +export {
17 + prerenderToNodeStream,
18 + prerender,
19 + resumeAndPrerenderToNodeStream,
20 + resumeAndPrerender,
21 +} from './ReactDOMFizzStaticNode.js';
packages/react-server/src/ReactServerStreamConfigBun.js
+24 -3
@@ -9,13 +9,22 @@
9
10 /* global Bun */
11
12 +import type {Writable} from 'stream';
13 +
14 type BunReadableStreamController = ReadableStreamController & {
15 end(): mixed,
16 write(data: Chunk | BinaryChunk): void,
17 error(error: Error): void,
18 flush?: () => void,
19 };
18 -export type Destination = BunReadableStreamController;
20 +
21 +interface MightBeFlushable {
22 + flush?: () => void;
23 +}
24 +
25 +export type Destination =
26 + | BunReadableStreamController
27 + | (Writable & MightBeFlushable);
28
29 export type PrecomputedChunk = string;
30 export opaque type Chunk = string;
@@ -46,6 +55,7 @@ export function writeChunk(
55 return;
56 }
57
58 + // $FlowFixMe[incompatible-call]: write() is compatible with both types in Bun
59 destination.write(chunk);
60 }
61
@@ -53,6 +63,7 @@ export function writeChunkAndReturn(
63 destination: Destination,
64 chunk: PrecomputedChunk | Chunk | BinaryChunk,
65 ): boolean {
66 + // $FlowFixMe[incompatible-call]: write() is compatible with both types in Bun
67 return !!destination.write(chunk);
68 }
69
@@ -86,11 +97,21 @@ export function byteLengthOfBinaryChunk(chunk: BinaryChunk): number {
97 }
98
99 export function closeWithError(destination: Destination, error: mixed): void {
100 + // $FlowFixMe[incompatible-use]
101 // $FlowFixMe[method-unbinding]
102 if (typeof destination.error === 'function') {
103 // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.
104 destination.error(error);
93 - } else {
105 +
106 + // $FlowFixMe[incompatible-use]
107 + // $FlowFixMe[method-unbinding]
108 + } else if (typeof destination.destroy === 'function') {
109 + // $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.
110 + destination.destroy(error);
111 +
112 + // $FlowFixMe[incompatible-use]
113 + // $FlowFixMe[method-unbinding]
114 + } else if (typeof destination.close === 'function') {
115 // Earlier implementations doesn't support this method. In that environment you're
116 // supposed to throw from a promise returned but we don't return a promise in our
117 // approach. We could fork this implementation but this is environment is an edge
@@ -101,7 +122,7 @@ export function closeWithError(destination: Destination, error: mixed): void {
122 }
123 }
124
104 -export function createFastHash(input: string): string | number {
125 +export function createFastHash(input: string): number {
126 return Bun.hash(input);
127 }
128
scripts/rollup/bundles.js
+1 -1
@@ -405,7 +405,7 @@ const bundles = [
405 global: 'ReactDOMServer',
406 minifyWithProdErrorCodes: false,
407 wrapWithModuleBoundaries: false,
408 - externals: ['react', 'react-dom'],
408 + externals: ['react', 'react-dom', 'crypto', 'stream', 'util'],
409 },
410
411 /******* React DOM Fizz Server External Runtime *******/
scripts/shared/inlinedHostConfigs.js
+2
@@ -250,6 +250,8 @@ module.exports = [
250 'react-dom/server.bun',
251 'react-dom/src/server/react-dom-server.bun',
252 'react-dom/src/server/ReactDOMFizzServerBun.js',
253 + 'react-dom/src/server/ReactDOMFizzServerNode.js',
254 + 'react-dom/src/server/ReactDOMFizzStaticNode.js',
255 'react-dom-bindings',
256 'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
257 'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',