[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
});