@samitouri / QOS-React-1 / commits / 0d721b60c2

[Flight] Don't hang after resolving cyclic references (#34988)

Hendrik Liebau committed Oct 27, 2025 at 22:06 UTC 0d721b60c2b0447f85f20f457e908a494acb28b0
2 files changed +41
packages/react-client/src/ReactFlightClient.js
+16
@@ -624,6 +624,22 @@ function wakeChunkIfInitialized<T>(
624 rejectListeners.splice(rejectionIdx, 1);
625 }
626 }
627 + // The status might have changed after fulfilling the reference.
628 + switch ((chunk: SomeChunk<T>).status) {
629 + case INITIALIZED:
630 + const initializedChunk: InitializedChunk<T> = (chunk: any);
631 + wakeChunk(
632 + resolveListeners,
633 + initializedChunk.value,
634 + initializedChunk,
635 + );
636 + return;
637 + case ERRORED:
638 + if (rejectListeners !== null) {
639 + rejectChunk(rejectListeners, chunk.reason);
640 + }
641 + return;
642 + }
643 }
644 }
645 }
packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js
+25
@@ -2196,4 +2196,29 @@ describe('ReactFlightDOMEdge', () => {
2196 'Switched to client rendering because the server rendering errored:\n\nssr-throw',
2197 );
2198 });
2199 +
2200 + it('should properly resolve with deduped objects', async () => {
2201 + const obj = {foo: 'hi'};
2202 +
2203 + function Test(props) {
2204 + return props.obj.foo;
2205 + }
2206 +
2207 + const root = {
2208 + obj: obj,
2209 + node: <Test obj={obj} />,
2210 + };
2211 +
2212 + const stream = ReactServerDOMServer.renderToReadableStream(root);
2213 +
2214 + const response = ReactServerDOMClient.createFromReadableStream(stream, {
2215 + serverConsumerManifest: {
2216 + moduleMap: null,
2217 + moduleLoading: null,
2218 + },
2219 + });
2220 +
2221 + const result = await response;
2222 + expect(result).toEqual({obj: obj, node: 'hi'});
2223 + });
2224 });