[Flight] Don't block on debug channel if it's not wired up (#33757)
React Elements reference debug data (their stack and owner) in the debug channel. If the debug channel isn't wired up this can block the client from resolving. We can infer that if there's no debug channel wired up and the reference wasn't emitted before the element, then it's probably because it's in the debug channel. So we can skip it. This should also apply to debug chunks but they're not yet blocking until #33665 lands.
Sebastian Markbåge committed
Jul 15, 2025 at 11:45 UTC
2f0e7e570d3a99adc2a18e7575d1d2bb69660e1f
1 file changed
+20
packages/react-client/src/ReactFlightClient.js
+20
@@ -1353,6 +1353,26 @@ function waitForReference<T>(
1353
map: (response: Response, model: any, parentObject: Object, key: string) => T,
1354
path: Array<string>,
1355
): T {
1356
+ if (
1357
+ __DEV__ &&
1358
+ // TODO: This should check for the existence of the "readable" side, not the "writable".
1359
+ response._debugChannel === undefined
1360
+ ) {
1361
+ if (
1362
+ referencedChunk.status === PENDING &&
1363
+ parentObject[0] === REACT_ELEMENT_TYPE &&
1364
+ (key === '4' || key === '5')
1365
+ ) {
1366
+ // If the parent object is an unparsed React element tuple, and this is a reference
1367
+ // to the owner or debug stack. Then we expect the chunk to have been emitted earlier
1368
+ // in the stream. It might be blocked on other things but chunk should no longer be pending.
1369
+ // If it's still pending that suggests that it was referencing an object in the debug
1370
+ // channel, but no debug channel was wired up so it's missing. In this case we can just
1371
+ // drop the debug info instead of halting the whole stream.
1372
+ return (null: any);
1373
+ }
1374
+ }
1375
+
1376
let handler: InitializationHandler;
1377
if (initializingHandler) {
1378
handler = initializingHandler;