@@ -20,9 +20,12 @@ import type {SharedQueue} from './ReactUpdateQueue.new';
20
20
import { isPrimaryRenderer } from './ReactFiberHostConfig' ;
21
21
import { createCursor , push , pop } from './ReactFiberStack.new' ;
22
22
import {
23
+ ContextConsumer ,
23
24
ContextProvider ,
24
25
ClassComponent ,
25
26
DehydratedFragment ,
27
+ OffscreenComponent ,
28
+ SuspenseComponent ,
26
29
} from './ReactWorkTags' ;
27
30
import {
28
31
NoLanes ,
@@ -157,6 +160,10 @@ export function scheduleWorkOnParentPath(
157
160
! isSubsetOfLanes ( alternate . childLanes , renderLanes )
158
161
) {
159
162
alternate . childLanes = mergeLanes ( alternate . childLanes , renderLanes ) ;
163
+ } else {
164
+ // Neither alternate was updated, which means the rest of the
165
+ // ancestor path already has sufficient priority.
166
+ break ;
160
167
}
161
168
node = node.return;
162
169
}
@@ -361,6 +368,69 @@ function propagateContextChanges<T>(
361
368
}
362
369
scheduleWorkOnParentPath ( consumer . return , renderLanes ) ;
363
370
371
+ // If Context.Consumer is a descendant of Suspense,
372
+ // `scheduleWorkOnParentPath` may break before it get to Suspense.
373
+ // Schedule work to avoid bailout before Context.Consumer receives the value.
374
+ const primaryChildFragment = workInProgress . child ;
375
+ if (
376
+ workInProgress . tag === SuspenseComponent &&
377
+ primaryChildFragment !== null &&
378
+ primaryChildFragment . tag === OffscreenComponent &&
379
+ consumer . tag === ContextConsumer
380
+ ) {
381
+ const workInProgressAlternate = workInProgress . alternate ;
382
+ if ( ! isSubsetOfLanes ( workInProgress . childLanes , renderLanes ) ) {
383
+ workInProgress . childLanes = mergeLanes (
384
+ workInProgress . childLanes ,
385
+ renderLanes ,
386
+ ) ;
387
+ if ( workInProgressAlternate !== null ) {
388
+ workInProgressAlternate . childLanes = mergeLanes (
389
+ workInProgressAlternate . childLanes ,
390
+ renderLanes ,
391
+ ) ;
392
+ }
393
+ } else if (
394
+ workInProgressAlternate !== null &&
395
+ ! isSubsetOfLanes (
396
+ workInProgressAlternate . childLanes ,
397
+ renderLanes ,
398
+ )
399
+ ) {
400
+ workInProgressAlternate . childLanes = mergeLanes (
401
+ workInProgressAlternate . childLanes ,
402
+ renderLanes ,
403
+ ) ;
404
+ }
405
+ const primaryChildFragmentAlternate =
406
+ primaryChildFragment . alternate ;
407
+ if (
408
+ ! isSubsetOfLanes ( primaryChildFragment . childLanes , renderLanes )
409
+ ) {
410
+ primaryChildFragment . childLanes = mergeLanes (
411
+ primaryChildFragment . childLanes ,
412
+ renderLanes ,
413
+ ) ;
414
+ if ( primaryChildFragmentAlternate !== null ) {
415
+ primaryChildFragmentAlternate . childLanes = mergeLanes (
416
+ primaryChildFragmentAlternate . childLanes ,
417
+ renderLanes ,
418
+ ) ;
419
+ }
420
+ } else if (
421
+ primaryChildFragmentAlternate !== null &&
422
+ ! isSubsetOfLanes (
423
+ primaryChildFragmentAlternate . childLanes ,
424
+ renderLanes ,
425
+ )
426
+ ) {
427
+ primaryChildFragmentAlternate . childLanes = mergeLanes (
428
+ primaryChildFragmentAlternate . childLanes ,
429
+ renderLanes ,
430
+ ) ;
431
+ }
432
+ }
433
+
364
434
if ( ! forcePropagateEntireTree ) {
365
435
// During lazy propagation, when we find a match, we can defer
366
436
// propagating changes to the children, because we're going to
0 commit comments