@@ -33,7 +33,11 @@ import {
3333 mergeLanes ,
3434 pickArbitraryLane ,
3535} from './ReactFiberLane.new' ;
36- import { NoFlags , DidPropagateContext } from './ReactFiberFlags' ;
36+ import {
37+ NoFlags ,
38+ DidPropagateContext ,
39+ NeedsPropagation ,
40+ } from './ReactFiberFlags' ;
3741
3842import invariant from 'shared/invariant' ;
3943import is from 'shared/objectIs' ;
@@ -292,9 +296,6 @@ function propagateContextChange_eager<T>(
292296 }
293297 dependency = dependency . next ;
294298 }
295- } else if ( fiber . tag === ContextProvider ) {
296- // Don't scan deeper if this is a matching provider
297- nextFiber = fiber . type === workInProgress . type ? null : fiber . child ;
298299 } else if (
299300 enableSuspenseServerRenderer &&
300301 fiber . tag === DehydratedFragment
@@ -409,14 +410,6 @@ function propagateContextChanges<T>(
409410 // visit them during render. We should continue propagating the
410411 // siblings, though
411412 nextFiber = null ;
412-
413- // Keep track of subtrees whose propagation we deferred
414- if ( deferredPropagation === null ) {
415- deferredPropagation = new Set ( [ consumer ] ) ;
416- } else {
417- deferredPropagation . add ( consumer ) ;
418- }
419- nextFiber = null ;
420413 }
421414
422415 // Since we already found a match, we can stop traversing the
@@ -513,29 +506,14 @@ export function propagateParentContextChangesToDeferredTree(
513506 ) ;
514507}
515508
516- // Used by lazy context propagation algorithm. When we find a context dependency
517- // match, we don't propagate the changes any further into that fiber's subtree.
518- // We add the matched fibers to this set. Later, if something inside that
519- // subtree bails out of rendering, the presence of a parent fiber in this Set
520- // tells us that we need to continue propagating.
521- //
522- // This is a set of _current_ fibers, not work-in-progress fibers. That's why
523- // it's a set instead of a flag on the fiber.
524- let deferredPropagation: Set< Fiber > | null = null;
525-
526- export function resetDeferredContextPropagation() {
527- // This is called by prepareFreshStack
528- deferredPropagation = null ;
529- }
530-
531509function propagateParentContextChanges(
532510 current: Fiber,
533511 workInProgress: Fiber,
534512 renderLanes: Lanes,
535513 forcePropagateEntireTree: boolean,
536514) {
537515 if ( ! enableLazyContextPropagation ) {
538- return false ;
516+ return ;
539517 }
540518
541519 // Collect all the parent providers that changed. Since this is usually small
@@ -544,58 +522,36 @@ function propagateParentContextChanges(
544522 let parent = workInProgress;
545523 let isInsidePropagationBailout = false;
546524 while (parent !== null) {
547- const currentParent = parent . alternate ;
548- invariant (
549- currentParent !== null ,
550- 'Should have a current fiber. This is a bug in React.' ,
551- ) ;
552-
553525 if ( ! isInsidePropagationBailout ) {
554- if ( deferredPropagation === null ) {
555- if ( ( parent . flags & DidPropagateContext ) !== NoFlags ) {
556- break ;
557- }
558- } else {
559- if ( currentParent !== null && deferredPropagation . has ( currentParent ) ) {
560- // We're inside a subtree that previously bailed out of propagation.
561- // We must disregard the the DidPropagateContext flag as we continue
562- // searching for parent providers.
563- isInsidePropagationBailout = true ;
564- // We know that none of the providers in between the propagation
565- // bailout and the nearest render bailout above that could have
566- // changed. So we can skip those.
567- do {
568- parent = parent . return ;
569- invariant (
570- parent !== null ,
571- 'Expected to find a bailed out fiber. This is a bug in React.' ,
572- ) ;
573- } while ( ( parent . flags & DidPropagateContext ) === NoFlags ) ;
574- } else if ((parent.flags & DidPropagateContext ) !== NoFlags ) {
575- break ;
576- }
526+ if ( ( parent . flags & NeedsPropagation ) !== NoFlags ) {
527+ isInsidePropagationBailout = true ;
528+ } else if ((parent.flags & DidPropagateContext ) !== NoFlags ) {
529+ break ;
577530 }
578531 }
579532
580533 if ( parent . tag === ContextProvider ) {
581- if ( currentParent !== null ) {
582- const oldProps = currentParent . memoizedProps ;
583- if ( oldProps !== null ) {
584- const providerType : ReactProviderType < any > = parent . type ;
585- const context : ReactContext < any > = providerType . _context ;
586-
587- const newProps = parent . pendingProps ;
588- const newValue = newProps . value ;
589-
590- const oldValue = oldProps . value ;
591-
592- const changedBits = calculateChangedBits ( context , newValue , oldValue ) ;
593- if ( changedBits !== 0 ) {
594- if ( contexts !== null ) {
595- contexts . push ( context , changedBits ) ;
596- } else {
597- contexts = [ context , changedBits ] ;
598- }
534+ const currentParent = parent . alternate ;
535+ invariant (
536+ currentParent !== null ,
537+ 'Should have a current fiber. This is a bug in React.' ,
538+ ) ;
539+ const oldProps = currentParent . memoizedProps ;
540+ if ( oldProps !== null ) {
541+ const providerType : ReactProviderType < any > = parent . type ;
542+ const context : ReactContext < any > = providerType . _context ;
543+
544+ const newProps = parent . pendingProps ;
545+ const newValue = newProps . value ;
546+
547+ const oldValue = oldProps . value ;
548+
549+ const changedBits = calculateChangedBits ( context , newValue , oldValue ) ;
550+ if ( changedBits !== 0 ) {
551+ if ( contexts !== null ) {
552+ contexts . push ( context , changedBits ) ;
553+ } else {
554+ contexts = [ context , changedBits ] ;
599555 }
600556 }
601557 }
@@ -628,10 +584,10 @@ function propagateParentContextChanges(
628584 //
629585 // Unfortunately, though, we need to ignore this flag when we're inside a
630586 // tree whose context propagation was deferred — that's what the
631- // `deferredPropagation` set is for.
587+ // `NeedsPropagation` flag is for.
632588 //
633- // If we could instead bail out before entering the siblings' beging phase,
634- // then we could remove both `DidPropagateContext` and `deferredPropagation `.
589+ // If we could instead bail out before entering the siblings' begin phase,
590+ // then we could remove both `DidPropagateContext` and `NeedsPropagation `.
635591 // Consider this as part of the next refactor to the fiber tree structure.
636592 workInProgress.flags |= DidPropagateContext;
637593}
@@ -750,6 +706,9 @@ export function readContext<T>(
750706 // TODO: This is an old field. Delete it.
751707 responders : null ,
752708 } ;
709+ if ( enableLazyContextPropagation ) {
710+ currentlyRenderingFiber . flags |= NeedsPropagation ;
711+ }
753712 } else {
754713 // Append a new context item.
755714 lastContextDependency = lastContextDependency . next = contextItem ;
0 commit comments