@samitouri / QOS-React / commits / 40351575d3

Split writeChunk into void and return value (#23343)

This function was modeled after Node streams where write returns a boolean whether to keep writing or not. I think we should probably switch this up and read desired size explicitly in appropriate places. However, in the meantime, we don't have to return a value where we're not going to use it. So I split this so that we call writeChunkAndReturn if we're going to return the boolean. This should help with the compilation so that they can be inlined.

Sebastian Markbåge committed Feb 23, 2022 at 11:35 UTC 40351575d3cfaef62426c889a90431c01fdeff0f
14 files changed +130 -61
packages/react-dom/src/server/ReactDOMLegacyServerStreamConfig.js
+7
@@ -28,6 +28,13 @@ let prevWasCommentSegmenter = false;
28 export function writeChunk(
29 destination: Destination,
30 chunk: Chunk | PrecomputedChunk,
31 +): void {
32 + writeChunkAndReturn(destination, chunk);
33 +}
34 +
35 +export function writeChunkAndReturn(
36 + destination: Destination,
37 + chunk: Chunk | PrecomputedChunk,
38 ): boolean {
39 if (prevWasCommentSegmenter) {
40 prevWasCommentSegmenter = false;
packages/react-dom/src/server/ReactDOMServerFormatConfig.js
+32 -28
@@ -30,6 +30,7 @@ import type {
30
31 import {
32 writeChunk,
33 + writeChunkAndReturn,
34 stringToChunk,
35 stringToPrecomputedChunk,
36 } from 'react-server/src/ReactServerStreamConfig';
@@ -1427,11 +1428,14 @@ export function writeCompletedRoot(
1428 responseState: ResponseState,
1429 ): boolean {
1430 const bootstrapChunks = responseState.bootstrapChunks;
1430 - let result = true;
1431 - for (let i = 0; i < bootstrapChunks.length; i++) {
1432 - result = writeChunk(destination, bootstrapChunks[i]);
1431 + let i = 0;
1432 + for (; i < bootstrapChunks.length - 1; i++) {
1433 + writeChunk(destination, bootstrapChunks[i]);
1434 }
1434 - return result;
1435 + if (i < bootstrapChunks.length) {
1436 + return writeChunkAndReturn(destination, bootstrapChunks[i]);
1437 + }
1438 + return true;
1439 }
1440
1441 // Structural Nodes
@@ -1450,7 +1454,7 @@ export function writePlaceholder(
1454 writeChunk(destination, responseState.placeholderPrefix);
1455 const formattedID = stringToChunk(id.toString(16));
1456 writeChunk(destination, formattedID);
1453 - return writeChunk(destination, placeholder2);
1457 + return writeChunkAndReturn(destination, placeholder2);
1458 }
1459
1460 // Suspense boundaries are encoded as comments.
@@ -1480,7 +1484,7 @@ export function writeStartCompletedSuspenseBoundary(
1484 destination: Destination,
1485 responseState: ResponseState,
1486 ): boolean {
1483 - return writeChunk(destination, startCompletedSuspenseBoundary);
1487 + return writeChunkAndReturn(destination, startCompletedSuspenseBoundary);
1488 }
1489 export function writeStartPendingSuspenseBoundary(
1490 destination: Destination,
@@ -1496,31 +1500,31 @@ export function writeStartPendingSuspenseBoundary(
1500 }
1501
1502 writeChunk(destination, id);
1499 - return writeChunk(destination, startPendingSuspenseBoundary2);
1503 + return writeChunkAndReturn(destination, startPendingSuspenseBoundary2);
1504 }
1505 export function writeStartClientRenderedSuspenseBoundary(
1506 destination: Destination,
1507 responseState: ResponseState,
1508 ): boolean {
1505 - return writeChunk(destination, startClientRenderedSuspenseBoundary);
1509 + return writeChunkAndReturn(destination, startClientRenderedSuspenseBoundary);
1510 }
1511 export function writeEndCompletedSuspenseBoundary(
1512 destination: Destination,
1513 responseState: ResponseState,
1514 ): boolean {
1511 - return writeChunk(destination, endSuspenseBoundary);
1515 + return writeChunkAndReturn(destination, endSuspenseBoundary);
1516 }
1517 export function writeEndPendingSuspenseBoundary(
1518 destination: Destination,
1519 responseState: ResponseState,
1520 ): boolean {
1517 - return writeChunk(destination, endSuspenseBoundary);
1521 + return writeChunkAndReturn(destination, endSuspenseBoundary);
1522 }
1523 export function writeEndClientRenderedSuspenseBoundary(
1524 destination: Destination,
1525 responseState: ResponseState,
1526 ): boolean {
1523 - return writeChunk(destination, endSuspenseBoundary);
1527 + return writeChunkAndReturn(destination, endSuspenseBoundary);
1528 }
1529
1530 const startSegmentHTML = stringToPrecomputedChunk('<div hidden id="');
@@ -1571,25 +1575,25 @@ export function writeStartSegment(
1575 writeChunk(destination, startSegmentHTML);
1576 writeChunk(destination, responseState.segmentPrefix);
1577 writeChunk(destination, stringToChunk(id.toString(16)));
1574 - return writeChunk(destination, startSegmentHTML2);
1578 + return writeChunkAndReturn(destination, startSegmentHTML2);
1579 }
1580 case SVG_MODE: {
1581 writeChunk(destination, startSegmentSVG);
1582 writeChunk(destination, responseState.segmentPrefix);
1583 writeChunk(destination, stringToChunk(id.toString(16)));
1580 - return writeChunk(destination, startSegmentSVG2);
1584 + return writeChunkAndReturn(destination, startSegmentSVG2);
1585 }
1586 case MATHML_MODE: {
1587 writeChunk(destination, startSegmentMathML);
1588 writeChunk(destination, responseState.segmentPrefix);
1589 writeChunk(destination, stringToChunk(id.toString(16)));
1586 - return writeChunk(destination, startSegmentMathML2);
1590 + return writeChunkAndReturn(destination, startSegmentMathML2);
1591 }
1592 case HTML_TABLE_MODE: {
1593 writeChunk(destination, startSegmentTable);
1594 writeChunk(destination, responseState.segmentPrefix);
1595 writeChunk(destination, stringToChunk(id.toString(16)));
1592 - return writeChunk(destination, startSegmentTable2);
1596 + return writeChunkAndReturn(destination, startSegmentTable2);
1597 }
1598 // TODO: For the rest of these, there will be extra wrapper nodes that never
1599 // get deleted from the document. We need to delete the table too as part
@@ -1599,19 +1603,19 @@ export function writeStartSegment(
1603 writeChunk(destination, startSegmentTableBody);
1604 writeChunk(destination, responseState.segmentPrefix);
1605 writeChunk(destination, stringToChunk(id.toString(16)));
1602 - return writeChunk(destination, startSegmentTableBody2);
1606 + return writeChunkAndReturn(destination, startSegmentTableBody2);
1607 }
1608 case HTML_TABLE_ROW_MODE: {
1609 writeChunk(destination, startSegmentTableRow);
1610 writeChunk(destination, responseState.segmentPrefix);
1611 writeChunk(destination, stringToChunk(id.toString(16)));
1608 - return writeChunk(destination, startSegmentTableRow2);
1612 + return writeChunkAndReturn(destination, startSegmentTableRow2);
1613 }
1614 case HTML_COLGROUP_MODE: {
1615 writeChunk(destination, startSegmentColGroup);
1616 writeChunk(destination, responseState.segmentPrefix);
1617 writeChunk(destination, stringToChunk(id.toString(16)));
1614 - return writeChunk(destination, startSegmentColGroup2);
1618 + return writeChunkAndReturn(destination, startSegmentColGroup2);
1619 }
1620 default: {
1621 throw new Error('Unknown insertion mode. This is a bug in React.');
@@ -1625,25 +1629,25 @@ export function writeEndSegment(
1629 switch (formatContext.insertionMode) {
1630 case ROOT_HTML_MODE:
1631 case HTML_MODE: {
1628 - return writeChunk(destination, endSegmentHTML);
1632 + return writeChunkAndReturn(destination, endSegmentHTML);
1633 }
1634 case SVG_MODE: {
1631 - return writeChunk(destination, endSegmentSVG);
1635 + return writeChunkAndReturn(destination, endSegmentSVG);
1636 }
1637 case MATHML_MODE: {
1634 - return writeChunk(destination, endSegmentMathML);
1638 + return writeChunkAndReturn(destination, endSegmentMathML);
1639 }
1640 case HTML_TABLE_MODE: {
1637 - return writeChunk(destination, endSegmentTable);
1641 + return writeChunkAndReturn(destination, endSegmentTable);
1642 }
1643 case HTML_TABLE_BODY_MODE: {
1640 - return writeChunk(destination, endSegmentTableBody);
1644 + return writeChunkAndReturn(destination, endSegmentTableBody);
1645 }
1646 case HTML_TABLE_ROW_MODE: {
1643 - return writeChunk(destination, endSegmentTableRow);
1647 + return writeChunkAndReturn(destination, endSegmentTableRow);
1648 }
1649 case HTML_COLGROUP_MODE: {
1646 - return writeChunk(destination, endSegmentColGroup);
1650 + return writeChunkAndReturn(destination, endSegmentColGroup);
1651 }
1652 default: {
1653 throw new Error('Unknown insertion mode. This is a bug in React.');
@@ -1790,7 +1794,7 @@ export function writeCompletedSegmentInstruction(
1794 writeChunk(destination, completeSegmentScript2);
1795 writeChunk(destination, responseState.placeholderPrefix);
1796 writeChunk(destination, formattedID);
1793 - return writeChunk(destination, completeSegmentScript3);
1797 + return writeChunkAndReturn(destination, completeSegmentScript3);
1798 }
1799
1800 const completeBoundaryScript1Full = stringToPrecomputedChunk(
@@ -1827,7 +1831,7 @@ export function writeCompletedBoundaryInstruction(
1831 writeChunk(destination, completeBoundaryScript2);
1832 writeChunk(destination, responseState.segmentPrefix);
1833 writeChunk(destination, formattedContentID);
1830 - return writeChunk(destination, completeBoundaryScript3);
1834 + return writeChunkAndReturn(destination, completeBoundaryScript3);
1835 }
1836
1837 const clientRenderScript1Full = stringToPrecomputedChunk(
@@ -1858,5 +1862,5 @@ export function writeClientRenderBoundaryInstruction(
1862 }
1863
1864 writeChunk(destination, boundaryID);
1861 - return writeChunk(destination, clientRenderScript2);
1865 + return writeChunkAndReturn(destination, clientRenderScript2);
1866 }
packages/react-native-renderer/src/server/ReactNativeServerFormatConfig.js
+12 -11
@@ -17,6 +17,7 @@ import type {
17
18 import {
19 writeChunk,
20 + writeChunkAndReturn,
21 stringToChunk,
22 stringToPrecomputedChunk,
23 } from 'react-server/src/ReactServerStreamConfig';
@@ -185,7 +186,7 @@ export function writePlaceholder(
186 id: number,
187 ): boolean {
188 writeChunk(destination, PLACEHOLDER);
188 - return writeChunk(destination, formatID(id));
189 + return writeChunkAndReturn(destination, formatID(id));
190 }
191
192 // Suspense boundaries are encoded as comments.
@@ -193,7 +194,7 @@ export function writeStartCompletedSuspenseBoundary(
194 destination: Destination,
195 responseState: ResponseState,
196 ): boolean {
196 - return writeChunk(destination, SUSPENSE_COMPLETE);
197 + return writeChunkAndReturn(destination, SUSPENSE_COMPLETE);
198 }
199
200 export function pushStartCompletedSuspenseBoundary(
@@ -208,19 +209,19 @@ export function writeStartPendingSuspenseBoundary(
209 id: SuspenseBoundaryID,
210 ): boolean {
211 writeChunk(destination, SUSPENSE_PENDING);
211 - return writeChunk(destination, formatID(id));
212 + return writeChunkAndReturn(destination, formatID(id));
213 }
214 export function writeStartClientRenderedSuspenseBoundary(
215 destination: Destination,
216 responseState: ResponseState,
217 ): boolean {
217 - return writeChunk(destination, SUSPENSE_CLIENT_RENDER);
218 + return writeChunkAndReturn(destination, SUSPENSE_CLIENT_RENDER);
219 }
220 export function writeEndCompletedSuspenseBoundary(
221 destination: Destination,
222 responseState: ResponseState,
223 ): boolean {
223 - return writeChunk(destination, END);
224 + return writeChunkAndReturn(destination, END);
225 }
226 export function pushEndCompletedSuspenseBoundary(
227 target: Array<Chunk | PrecomputedChunk>,
@@ -231,13 +232,13 @@ export function writeEndPendingSuspenseBoundary(
232 destination: Destination,
233 responseState: ResponseState,
234 ): boolean {
234 - return writeChunk(destination, END);
235 + return writeChunkAndReturn(destination, END);
236 }
237 export function writeEndClientRenderedSuspenseBoundary(
238 destination: Destination,
239 responseState: ResponseState,
240 ): boolean {
240 - return writeChunk(destination, END);
241 + return writeChunkAndReturn(destination, END);
242 }
243
244 export function writeStartSegment(
@@ -247,13 +248,13 @@ export function writeStartSegment(
248 id: number,
249 ): boolean {
250 writeChunk(destination, SEGMENT);
250 - return writeChunk(destination, formatID(id));
251 + return writeChunkAndReturn(destination, formatID(id));
252 }
253 export function writeEndSegment(
254 destination: Destination,
255 formatContext: FormatContext,
256 ): boolean {
256 - return writeChunk(destination, END);
257 + return writeChunkAndReturn(destination, END);
258 }
259
260 // Instruction Set
@@ -276,7 +277,7 @@ export function writeCompletedBoundaryInstruction(
277 ): boolean {
278 writeChunk(destination, SUSPENSE_UPDATE_TO_COMPLETE);
279 writeChunk(destination, formatID(boundaryID));
279 - return writeChunk(destination, formatID(contentSegmentID));
280 + return writeChunkAndReturn(destination, formatID(contentSegmentID));
281 }
282
283 export function writeClientRenderBoundaryInstruction(
@@ -285,5 +286,5 @@ export function writeClientRenderBoundaryInstruction(
286 boundaryID: SuspenseBoundaryID,
287 ): boolean {
288 writeChunk(destination, SUSPENSE_UPDATE_TO_CLIENT_RENDER);
288 - return writeChunk(destination, formatID(boundaryID));
289 + return writeChunkAndReturn(destination, formatID(boundaryID));
290 }
packages/react-noop-renderer/src/ReactNoopFlightServer.js
+4
@@ -30,6 +30,10 @@ const ReactNoopFlightServer = ReactFlightServer({
30 writeChunk(destination: Destination, chunk: string): void {
31 destination.push(chunk);
32 },
33 + writeChunkAndReturn(destination: Destination, chunk: string): boolean {
34 + destination.push(chunk);
35 + return true;
36 + },
37 completeWriting(destination: Destination): void {},
38 close(destination: Destination): void {},
39 closeWithError(destination: Destination, error: mixed): void {},
packages/react-noop-renderer/src/ReactNoopServer.js
+22 -14
@@ -53,26 +53,34 @@ type Destination = {
53
54 const POP = Buffer.from('/', 'utf8');
55
56 +function write(destination: Destination, buffer: Uint8Array): void {
57 + const stack = destination.stack;
58 + if (buffer === POP) {
59 + stack.pop();
60 + return;
61 + }
62 + // We assume one chunk is one instance.
63 + const instance = JSON.parse(Buffer.from((buffer: any)).toString('utf8'));
64 + if (stack.length === 0) {
65 + destination.root = instance;
66 + } else {
67 + const parent = stack[stack.length - 1];
68 + parent.children.push(instance);
69 + }
70 + stack.push(instance);
71 +}
72 +
73 const ReactNoopServer = ReactFizzServer({
74 scheduleWork(callback: () => void) {
75 callback();
76 },
77 beginWriting(destination: Destination): void {},
78 writeChunk(destination: Destination, buffer: Uint8Array): void {
62 - const stack = destination.stack;
63 - if (buffer === POP) {
64 - stack.pop();
65 - return;
66 - }
67 - // We assume one chunk is one instance.
68 - const instance = JSON.parse(Buffer.from((buffer: any)).toString('utf8'));
69 - if (stack.length === 0) {
70 - destination.root = instance;
71 - } else {
72 - const parent = stack[stack.length - 1];
73 - parent.children.push(instance);
74 - }
75 - stack.push(instance);
79 + write(destination, buffer);
80 + },
81 + writeChunkAndReturn(destination: Destination, buffer: Uint8Array): boolean {
82 + write(destination, buffer);
83 + return true;
84 },
85 completeWriting(destination: Destination): void {},
86 close(destination: Destination): void {},
packages/react-server-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js
+8 -1
@@ -141,7 +141,14 @@ export function flushBuffered(destination: Destination) {}
141
142 export function beginWriting(destination: Destination) {}
143
144 -export function writeChunk(destination: Destination, chunk: Chunk): boolean {
144 +export function writeChunk(destination: Destination, chunk: Chunk): void {
145 + emitRow(destination, chunk);
146 +}
147 +
148 +export function writeChunkAndReturn(
149 + destination: Destination,
150 + chunk: Chunk,
151 +): boolean {
152 emitRow(destination, chunk);
153 return true;
154 }
packages/react-server-dom-relay/src/ReactServerStreamConfigFB.js
+7
@@ -28,6 +28,13 @@ export function beginWriting(destination: Destination) {}
28 export function writeChunk(
29 destination: Destination,
30 chunk: Chunk | PrecomputedChunk,
31 +): void {
32 + destination.buffer += chunk;
33 +}
34 +
35 +export function writeChunkAndReturn(
36 + destination: Destination,
37 + chunk: Chunk | PrecomputedChunk,
38 ): boolean {
39 destination.buffer += chunk;
40 return true;
packages/react-server-native-relay/src/ReactFlightNativeRelayServerHostConfig.js
+8 -1
@@ -138,7 +138,14 @@ export function flushBuffered(destination: Destination) {}
138
139 export function beginWriting(destination: Destination) {}
140
141 -export function writeChunk(destination: Destination, chunk: Chunk): boolean {
141 +export function writeChunk(destination: Destination, chunk: Chunk): void {
142 + emitRow(destination, chunk);
143 +}
144 +
145 +export function writeChunkAndReturn(
146 + destination: Destination,
147 + chunk: Chunk,
148 +): boolean {
149 emitRow(destination, chunk);
150 return true;
151 }
packages/react-server/src/ReactFizzServer.js
+6 -2
@@ -31,6 +31,7 @@ import {
31 scheduleWork,
32 beginWriting,
33 writeChunk,
34 + writeChunkAndReturn,
35 completeWriting,
36 flushBuffered,
37 close,
@@ -1615,8 +1616,11 @@ function flushSubtree(
1616 r = flushSegment(request, destination, nextChild);
1617 }
1618 // Finally just write all the remaining chunks
1618 - for (; chunkIdx < chunks.length; chunkIdx++) {
1619 - r = writeChunk(destination, chunks[chunkIdx]);
1619 + for (; chunkIdx < chunks.length - 1; chunkIdx++) {
1620 + writeChunk(destination, chunks[chunkIdx]);
1621 + }
1622 + if (chunkIdx < chunks.length) {
1623 + r = writeChunkAndReturn(destination, chunks[chunkIdx]);
1624 }
1625 return r;
1626 }
packages/react-server/src/ReactFlightServer.js
+7 -4
@@ -20,7 +20,7 @@ import type {
20 import {
21 scheduleWork,
22 beginWriting,
23 - writeChunk,
23 + writeChunkAndReturn,
24 completeWriting,
25 flushBuffered,
26 close,
@@ -732,7 +732,8 @@ function flushCompletedChunks(
732 for (; i < moduleChunks.length; i++) {
733 request.pendingChunks--;
734 const chunk = moduleChunks[i];
735 - if (!writeChunk(destination, chunk)) {
735 + const keepWriting: boolean = writeChunkAndReturn(destination, chunk);
736 + if (!keepWriting) {
737 request.destination = null;
738 i++;
739 break;
@@ -745,7 +746,8 @@ function flushCompletedChunks(
746 for (; i < jsonChunks.length; i++) {
747 request.pendingChunks--;
748 const chunk = jsonChunks[i];
748 - if (!writeChunk(destination, chunk)) {
749 + const keepWriting: boolean = writeChunkAndReturn(destination, chunk);
750 + if (!keepWriting) {
751 request.destination = null;
752 i++;
753 break;
@@ -760,7 +762,8 @@ function flushCompletedChunks(
762 for (; i < errorChunks.length; i++) {
763 request.pendingChunks--;
764 const chunk = errorChunks[i];
763 - if (!writeChunk(destination, chunk)) {
765 + const keepWriting: boolean = writeChunkAndReturn(destination, chunk);
766 + if (!keepWriting) {
767 request.destination = null;
768 i++;
769 break;
packages/react-server/src/ReactFlightServerConfigStream.js
+1
@@ -124,6 +124,7 @@ export {
124 flushBuffered,
125 beginWriting,
126 writeChunk,
127 + writeChunkAndReturn,
128 completeWriting,
129 close,
130 closeWithError,
packages/react-server/src/ReactServerStreamConfigBrowser.js
+7
@@ -26,6 +26,13 @@ export function beginWriting(destination: Destination) {}
26 export function writeChunk(
27 destination: Destination,
28 chunk: PrecomputedChunk | Chunk,
29 +): void {
30 + destination.enqueue(chunk);
31 +}
32 +
33 +export function writeChunkAndReturn(
34 + destination: Destination,
35 + chunk: PrecomputedChunk | Chunk,
36 ): boolean {
37 destination.enqueue(chunk);
38 return destination.desiredSize > 0;
packages/react-server/src/ReactServerStreamConfigNode.js
+8
@@ -43,6 +43,14 @@ export function beginWriting(destination: Destination) {
43 export function writeChunk(
44 destination: Destination,
45 chunk: Chunk | PrecomputedChunk,
46 +): void {
47 + const nodeBuffer = ((chunk: any): Buffer | string); // close enough
48 + destination.write(nodeBuffer);
49 +}
50 +
51 +export function writeChunkAndReturn(
52 + destination: Destination,
53 + chunk: Chunk | PrecomputedChunk,
54 ): boolean {
55 const nodeBuffer = ((chunk: any): Buffer | string); // close enough
56 return destination.write(nodeBuffer);
packages/react-server/src/forks/ReactServerStreamConfig.custom.js
+1
@@ -32,6 +32,7 @@ export opaque type Chunk = mixed; // eslint-disable-line no-undef
32 export const scheduleWork = $$$hostConfig.scheduleWork;
33 export const beginWriting = $$$hostConfig.beginWriting;
34 export const writeChunk = $$$hostConfig.writeChunk;
35 +export const writeChunkAndReturn = $$$hostConfig.writeChunkAndReturn;
36 export const completeWriting = $$$hostConfig.completeWriting;
37 export const flushBuffered = $$$hostConfig.flushBuffered;
38 export const close = $$$hostConfig.close;