diff --git a/fixtures/flight/server/handler.server.js b/fixtures/flight/server/handler.server.js
index cdaef9f13a8be..f695f0366e70a 100644
--- a/fixtures/flight/server/handler.server.js
+++ b/fixtures/flight/server/handler.server.js
@@ -22,10 +22,9 @@ module.exports = function(req, res) {
const moduleMap = JSON.parse(data);
const {startWriting} = renderToNodePipe(
React.createElement(App),
- res,
moduleMap
);
- startWriting();
+ startWriting(res);
}
);
});
diff --git a/fixtures/ssr/server/render.js b/fixtures/ssr/server/render.js
index 4922c5cdf7e44..63a795718cc7b 100644
--- a/fixtures/ssr/server/render.js
+++ b/fixtures/ssr/server/render.js
@@ -20,12 +20,12 @@ export default function render(url, res) {
console.error('Fatal', error);
});
let didError = false;
- const {startWriting, abort} = renderToNodePipe(, res, {
+ const {startWriting, abort} = renderToNodePipe(, {
onCompleteShell() {
// If something errored before we started streaming, we set the error code appropriately.
res.statusCode = didError ? 500 : 200;
res.setHeader('Content-type', 'text/html');
- startWriting();
+ startWriting(res);
},
onError(x) {
didError = true;
diff --git a/fixtures/ssr2/server/render.js b/fixtures/ssr2/server/render.js
index 92a4f248f3fa2..aa17e1121b0e0 100644
--- a/fixtures/ssr2/server/render.js
+++ b/fixtures/ssr2/server/render.js
@@ -41,13 +41,12 @@ module.exports = function render(url, res) {
,
- res,
{
onCompleteShell() {
// If something errored before we started streaming, we set the error code appropriately.
res.statusCode = didError ? 500 : 200;
res.setHeader('Content-type', 'text/html');
- startWriting();
+ startWriting(res);
},
onError(x) {
didError = true;
diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
index b368cedede5a7..bc5d127c35184 100644
--- a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
@@ -252,9 +252,8 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
);
- startWriting();
+ startWriting(writable);
});
expect(getVisibleChildren(container)).toEqual(
@@ -306,14 +305,14 @@ describe('ReactDOMFizzServer', () => {
await act(async () => {
const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
,
- writable,
+
{
onError(x) {
loggedErrors.push(x);
},
},
);
- startWriting();
+ startWriting(writable);
});
expect(loggedErrors).toEqual([]);
@@ -362,9 +361,8 @@ describe('ReactDOMFizzServer', () => {
{lazyElement}
,
- writable,
);
- startWriting();
+ startWriting(writable);
});
expect(getVisibleChildren(container)).toEqual(Loading...
);
await act(async () => {
@@ -398,14 +396,14 @@ describe('ReactDOMFizzServer', () => {
await act(async () => {
const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
,
- writable,
+
{
onError(x) {
loggedErrors.push(x);
},
},
);
- startWriting();
+ startWriting(writable);
});
expect(loggedErrors).toEqual([]);
@@ -447,9 +445,8 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
);
- startWriting();
+ startWriting(writable);
});
expect(getVisibleChildren(container)).toEqual(Loading...
);
await act(async () => {
@@ -475,11 +472,8 @@ describe('ReactDOMFizzServer', () => {
}
await act(async () => {
- const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
- ,
- writable,
- );
- startWriting();
+ const {startWriting} = ReactDOMFizzServer.renderToNodePipe();
+ startWriting(writable);
});
// We're still showing a fallback.
@@ -552,14 +546,14 @@ describe('ReactDOMFizzServer', () => {
await act(async () => {
const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
,
- writable,
+
{
onError(x) {
loggedErrors.push(x);
},
},
);
- startWriting();
+ startWriting(writable);
});
// We're still showing a fallback.
@@ -635,9 +629,8 @@ describe('ReactDOMFizzServer', () => {
await act(async () => {
const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
,
- writable,
);
- startWriting();
+ startWriting(writable);
});
const root = ReactDOM.createRoot(container, {hydrate: true});
@@ -701,8 +694,8 @@ describe('ReactDOMFizzServer', () => {
let controls;
await act(async () => {
- controls = ReactDOMFizzServer.renderToNodePipe(, writable);
- controls.startWriting();
+ controls = ReactDOMFizzServer.renderToNodePipe();
+ controls.startWriting(writable);
});
// We're still showing a fallback.
@@ -765,12 +758,11 @@ describe('ReactDOMFizzServer', () => {
>
,
- writableA,
{
identifierPrefix: 'A_',
onCompleteShell() {
writableA.write('');
- startWriting();
+ startWriting(writableA);
writableA.write('
');
},
},
@@ -785,12 +777,11 @@ describe('ReactDOMFizzServer', () => {
,
- writableB,
{
identifierPrefix: 'B_',
onCompleteShell() {
writableB.write('');
- startWriting();
+ startWriting(writableB);
writableB.write('
');
},
},
@@ -876,11 +867,8 @@ describe('ReactDOMFizzServer', () => {
}
await act(async () => {
- const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
- ,
- writable,
- );
- startWriting();
+ const {startWriting} = ReactDOMFizzServer.renderToNodePipe();
+ startWriting(writable);
});
expect(getVisibleChildren(container)).toEqual(
@@ -967,11 +955,8 @@ describe('ReactDOMFizzServer', () => {
}
await act(async () => {
- const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
- ,
- writable,
- );
- startWriting();
+ const {startWriting} = ReactDOMFizzServer.renderToNodePipe();
+ startWriting(writable);
});
expect(getVisibleChildren(container)).toEqual(
@@ -1026,12 +1011,12 @@ describe('ReactDOMFizzServer', () => {
await act(async () => {
const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
,
- writable,
+
{
namespaceURI: 'http://www.w3.org/2000/svg',
onCompleteShell() {
writable.write('');
},
},
@@ -1111,11 +1096,8 @@ describe('ReactDOMFizzServer', () => {
try {
await act(async () => {
- const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
- ,
- writable,
- );
- startWriting();
+ const {startWriting} = ReactDOMFizzServer.renderToNodePipe();
+ startWriting(writable);
});
expect(getVisibleChildren(container)).toEqual(
@@ -1224,9 +1206,8 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
);
- startWriting();
+ startWriting(writable);
});
expect(getVisibleChildren(container)).toEqual(
@@ -1287,9 +1268,8 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
);
- startWriting();
+ startWriting(writable);
});
expect(getVisibleChildren(container)).toEqual(
@@ -1355,14 +1335,14 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
+
{
onError(x) {
loggedErrors.push(x);
},
},
);
- startWriting();
+ startWriting(writable);
});
expect(loggedErrors.length).toBe(1);
expect(loggedErrors[0].message).toEqual('A0.1.1');
@@ -1398,14 +1378,14 @@ describe('ReactDOMFizzServer', () => {
await act(async () => {
controls = ReactDOMFizzServer.renderToNodePipe(
,
- writable,
+
{
onError(x) {
loggedErrors.push(x);
},
},
);
- controls.startWriting();
+ controls.startWriting(writable);
});
// We're still showing a fallback.
@@ -1470,9 +1450,8 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
);
- startWriting();
+ startWriting(writable);
});
expect(getVisibleChildren(container)).toEqual('Loading Outer');
// We should have received a partial segment containing the a partial of the fallback.
@@ -1556,9 +1535,8 @@ describe('ReactDOMFizzServer', () => {
await act(async () => {
const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
,
- writable,
);
- startWriting();
+ startWriting(writable);
});
// Nothing is output since root has a suspense with avoidedThisFallback that hasn't resolved
@@ -1673,14 +1651,14 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
+
{
onError(x) {
loggedErrors.push(x);
},
},
);
- startWriting();
+ startWriting(writable);
});
expect(Scheduler).toHaveYielded(['server']);
@@ -1756,14 +1734,14 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
+
{
onError(x) {
loggedErrors.push(x);
},
},
);
- startWriting();
+ startWriting(writable);
});
expect(Scheduler).toHaveYielded(['server']);
@@ -1838,11 +1816,8 @@ describe('ReactDOMFizzServer', () => {
}
await act(async () => {
- const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
- ,
- writable,
- );
- startWriting();
+ const {startWriting} = ReactDOMFizzServer.renderToNodePipe();
+ startWriting(writable);
});
expect(Scheduler).toHaveYielded(['Yay!']);
@@ -1922,11 +1897,8 @@ describe('ReactDOMFizzServer', () => {
}
await act(async () => {
- const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
- ,
- writable,
- );
- startWriting();
+ const {startWriting} = ReactDOMFizzServer.renderToNodePipe();
+ startWriting(writable);
});
expect(Scheduler).toHaveYielded(['Yay!']);
@@ -1997,11 +1969,8 @@ describe('ReactDOMFizzServer', () => {
}
await act(async () => {
- const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
- ,
- writable,
- );
- startWriting();
+ const {startWriting} = ReactDOMFizzServer.renderToNodePipe();
+ startWriting(writable);
});
expect(Scheduler).toHaveYielded(['Yay!']);
diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServerNode-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServerNode-test.js
index dd6aea74b5348..f422a91e29e38 100644
--- a/packages/react-dom/src/__tests__/ReactDOMFizzServerNode-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMFizzServerNode-test.js
@@ -61,9 +61,8 @@ describe('ReactDOMFizzServer', () => {
const {writable, output} = getTestWritable();
const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
hello world
,
- writable,
);
- startWriting();
+ startWriting(writable);
jest.runAllTimers();
expect(output.result).toMatchInlineSnapshot(`"hello world
"`);
});
@@ -75,9 +74,8 @@ describe('ReactDOMFizzServer', () => {
hello world
,
- writable,
);
- startWriting();
+ startWriting(writable);
jest.runAllTimers();
expect(output.result).toMatchInlineSnapshot(
`"hello world"`,
@@ -89,14 +87,13 @@ describe('ReactDOMFizzServer', () => {
const {writable, output} = getTestWritable();
const {startWriting} = ReactDOMFizzServer.renderToNodePipe(
hello world
,
- writable,
);
jest.runAllTimers();
// First we write our header.
output.result +=
'test';
// Then React starts writing.
- startWriting();
+ startWriting(writable);
expect(output.result).toMatchInlineSnapshot(
`"testhello world
"`,
);
@@ -121,7 +118,7 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
+
{
onCompleteAll() {
isCompleteCalls++;
@@ -144,7 +141,7 @@ describe('ReactDOMFizzServer', () => {
output.result +=
'test';
// Then React starts writing.
- startWriting();
+ startWriting(writable);
expect(output.result).toMatchInlineSnapshot(
`"testDone
"`,
);
@@ -158,7 +155,7 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
+
{
onError(x) {
reportedErrors.push(x);
@@ -167,7 +164,7 @@ describe('ReactDOMFizzServer', () => {
);
// The stream is errored once we start writing.
- startWriting();
+ startWriting(writable);
await completed;
@@ -187,14 +184,14 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
+
{
onError(x) {
reportedErrors.push(x);
},
},
);
- startWriting();
+ startWriting(writable);
await completed;
@@ -213,14 +210,14 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
+
{
onError(x) {
reportedErrors.push(x);
},
},
);
- startWriting();
+ startWriting(writable);
await completed;
@@ -246,9 +243,8 @@ describe('ReactDOMFizzServer', () => {
}>
,
- writable,
);
- startWriting();
+ startWriting(writable);
await completed;
@@ -267,14 +263,14 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
+
{
onCompleteAll() {
isCompleteCalls++;
},
},
);
- startWriting();
+ startWriting(writable);
jest.runAllTimers();
@@ -302,14 +298,14 @@ describe('ReactDOMFizzServer', () => {
,
- writable,
+
{
onCompleteAll() {
isCompleteCalls++;
},
},
);
- startWriting();
+ startWriting(writable);
jest.runAllTimers();
diff --git a/packages/react-dom/src/server/ReactDOMFizzServerNode.js b/packages/react-dom/src/server/ReactDOMFizzServerNode.js
index 6d6bb31e06ade..5d381c268f0f5 100644
--- a/packages/react-dom/src/server/ReactDOMFizzServerNode.js
+++ b/packages/react-dom/src/server/ReactDOMFizzServerNode.js
@@ -41,7 +41,7 @@ type Controls = {|
// Cancel any pending I/O and put anything remaining into
// client rendered mode.
abort(): void,
- startWriting(): void,
+ startWriting(destination: Writable): void,
|};
function createRequestImpl(children: ReactNodeList, options: void | Options) {
@@ -58,14 +58,13 @@ function createRequestImpl(children: ReactNodeList, options: void | Options) {
function renderToNodePipe(
children: ReactNodeList,
- destination: Writable,
options?: Options,
): Controls {
const request = createRequestImpl(children, options);
let hasStartedFlowing = false;
startWork(request);
return {
- startWriting() {
+ startWriting(destination) {
if (hasStartedFlowing) {
return;
}
diff --git a/packages/react-server-dom-webpack/src/ReactFlightDOMServerNode.js b/packages/react-server-dom-webpack/src/ReactFlightDOMServerNode.js
index b9f191a258c9a..192db0fd61cb4 100644
--- a/packages/react-server-dom-webpack/src/ReactFlightDOMServerNode.js
+++ b/packages/react-server-dom-webpack/src/ReactFlightDOMServerNode.js
@@ -26,12 +26,11 @@ type Options = {
};
type Controls = {|
- startWriting(): void,
+ startWriting(destination: Writable): void,
|};
function renderToNodePipe(
model: ReactModel,
- destination: Writable,
webpackMap: BundlerConfig,
options?: Options,
): Controls {
@@ -40,11 +39,16 @@ function renderToNodePipe(
webpackMap,
options ? options.onError : undefined,
);
+ let hasStartedFlowing = false;
startWork(request);
- destination.on('drain', createDrainHandler(destination, request));
return {
- startWriting() {
+ startWriting(destination) {
+ if (hasStartedFlowing) {
+ return;
+ }
+ hasStartedFlowing = true;
startFlowing(request, destination);
+ destination.on('drain', createDrainHandler(destination, request));
},
};
}
diff --git a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js
index 98ade7a7389a8..b158b96cd11e8 100644
--- a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js
+++ b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js
@@ -57,8 +57,8 @@ describe('ReactFlightDOM', () => {
},
});
return {
- writable,
readable,
+ writable,
};
}
@@ -115,10 +115,9 @@ describe('ReactFlightDOM', () => {
const {writable, readable} = getTestStream();
const {startWriting} = ReactServerDOMWriter.renderToNodePipe(
,
- writable,
webpackMap,
);
- startWriting();
+ startWriting(writable);
const response = ReactServerDOMReader.createFromReadableStream(readable);
await waitForSuspense(() => {
const model = response.readRoot();
@@ -169,10 +168,9 @@ describe('ReactFlightDOM', () => {
const {writable, readable} = getTestStream();
const {startWriting} = ReactServerDOMWriter.renderToNodePipe(
,
- writable,
webpackMap,
);
- startWriting();
+ startWriting(writable);
const response = ReactServerDOMReader.createFromReadableStream(readable);
const container = document.createElement('div');
@@ -208,10 +206,9 @@ describe('ReactFlightDOM', () => {
const {writable, readable} = getTestStream();
const {startWriting} = ReactServerDOMWriter.renderToNodePipe(
,
- writable,
webpackMap,
);
- startWriting();
+ startWriting(writable);
const response = ReactServerDOMReader.createFromReadableStream(readable);
const container = document.createElement('div');
@@ -245,10 +242,9 @@ describe('ReactFlightDOM', () => {
const {writable, readable} = getTestStream();
const {startWriting} = ReactServerDOMWriter.renderToNodePipe(
,
- writable,
webpackMap,
);
- startWriting();
+ startWriting(writable);
const response = ReactServerDOMReader.createFromReadableStream(readable);
const container = document.createElement('div');
@@ -381,7 +377,6 @@ describe('ReactFlightDOM', () => {
const {writable, readable} = getTestStream();
const {startWriting} = ReactServerDOMWriter.renderToNodePipe(
model,
- writable,
webpackMap,
{
onError(x) {
@@ -389,7 +384,7 @@ describe('ReactFlightDOM', () => {
},
},
);
- startWriting();
+ startWriting(writable);
const response = ReactServerDOMReader.createFromReadableStream(readable);
const container = document.createElement('div');
@@ -497,10 +492,9 @@ describe('ReactFlightDOM', () => {
const stream1 = getTestStream();
const {startWriting} = ReactServerDOMWriter.renderToNodePipe(
,
- stream1.writable,
webpackMap,
);
- startWriting();
+ startWriting(stream1.writable);
const response1 = ReactServerDOMReader.createFromReadableStream(
stream1.readable,
);
@@ -526,10 +520,9 @@ describe('ReactFlightDOM', () => {
const stream2 = getTestStream();
const {startWriting: startWriting2} = ReactServerDOMWriter.renderToNodePipe(
,
- stream2.writable,
webpackMap,
);
- startWriting2();
+ startWriting2(stream2.writable);
const response2 = ReactServerDOMReader.createFromReadableStream(
stream2.readable,
);