@@ -69,8 +69,11 @@ import {
69
69
import { pushHostContext , pushHostContainer } from './ReactFiberHostContext' ;
70
70
import {
71
71
pushProvider ,
72
- getContextCurrentValue ,
73
- getContextChangedBits ,
72
+ propagateContextChange ,
73
+ checkForPendingContext ,
74
+ readContext ,
75
+ prepareToReadContext ,
76
+ finishReadingContext ,
74
77
} from './ReactFiberNewContext' ;
75
78
import {
76
79
markActualRenderTimeStarted ,
@@ -764,100 +767,6 @@ function updatePortalComponent(current, workInProgress, renderExpirationTime) {
764
767
return workInProgress . child ;
765
768
}
766
769
767
- function propagateContextChange < V > (
768
- workInProgress: Fiber,
769
- context: ReactContext< V > ,
770
- changedBits: number,
771
- renderExpirationTime: ExpirationTime,
772
- ): void {
773
- let fiber = workInProgress . child ;
774
- if ( fiber !== null ) {
775
- // Set the return pointer of the child to the work-in-progress fiber.
776
- fiber. return = workInProgress ;
777
- }
778
- while (fiber !== null) {
779
- let nextFiber ;
780
- // Visit this fiber.
781
- switch ( fiber . tag ) {
782
- case ContextConsumer :
783
- // Check if the context matches.
784
- const observedBits : number = fiber . stateNode | 0 ;
785
- if ( fiber . type === context && ( observedBits & changedBits ) !== 0 ) {
786
- // Update the expiration time of all the ancestors, including
787
- // the alternates.
788
- let node = fiber ;
789
- while ( node !== null ) {
790
- const alternate = node . alternate ;
791
- if (
792
- node . expirationTime === NoWork ||
793
- node . expirationTime > renderExpirationTime
794
- ) {
795
- node . expirationTime = renderExpirationTime ;
796
- if (
797
- alternate !== null &&
798
- ( alternate . expirationTime === NoWork ||
799
- alternate . expirationTime > renderExpirationTime )
800
- ) {
801
- alternate . expirationTime = renderExpirationTime ;
802
- }
803
- } else if (
804
- alternate !== null &&
805
- ( alternate . expirationTime === NoWork ||
806
- alternate . expirationTime > renderExpirationTime )
807
- ) {
808
- alternate . expirationTime = renderExpirationTime ;
809
- } else {
810
- // Neither alternate was updated, which means the rest of the
811
- // ancestor path already has sufficient priority.
812
- break ;
813
- }
814
- node = node . return ;
815
- }
816
- // Don't scan deeper than a matching consumer. When we render the
817
- // consumer, we'll continue scanning from that point. This way the
818
- // scanning work is time-sliced.
819
- nextFiber = null ;
820
- } else {
821
- // Traverse down.
822
- nextFiber = fiber . child ;
823
- }
824
- break;
825
- case ContextProvider:
826
- // Don't scan deeper if this is a matching provider
827
- nextFiber = fiber.type === workInProgress.type ? null : fiber.child;
828
- break;
829
- default:
830
- // Traverse down.
831
- nextFiber = fiber.child;
832
- break;
833
- }
834
- if ( nextFiber !== null ) {
835
- // Set the return pointer of the child to the work-in-progress fiber.
836
- nextFiber . return = fiber ;
837
- } else {
838
- // No child. Traverse to next sibling.
839
- nextFiber = fiber ;
840
- while ( nextFiber !== null ) {
841
- if ( nextFiber === workInProgress ) {
842
- // We're back to the root of this subtree. Exit.
843
- nextFiber = null ;
844
- break ;
845
- }
846
- let sibling = nextFiber.sibling;
847
- if (sibling !== null) {
848
- // Set the return pointer of the sibling to the work-in-progress fiber.
849
- sibling . return = nextFiber . return ;
850
- nextFiber = sibling ;
851
- break ;
852
- }
853
- // No more siblings. Traverse up.
854
- nextFiber = nextFiber.return;
855
- }
856
- }
857
- fiber = nextFiber ;
858
- }
859
- }
860
-
861
770
function updateContextProvider ( current , workInProgress , renderExpirationTime ) {
862
771
const providerType : ReactProviderType < any > = workInProgress.type;
863
772
const context: ReactContext< any > = providerType._context;
@@ -970,42 +879,16 @@ function updateContextConsumer(current, workInProgress, renderExpirationTime) {
970
879
const newProps = workInProgress . pendingProps ;
971
880
const oldProps = workInProgress . memoizedProps ;
972
881
973
- const newValue = getContextCurrentValue ( context ) ;
974
- const changedBits = getContextChangedBits ( context ) ;
975
-
976
- if ( hasLegacyContextChanged ( ) ) {
977
- // Normally we can bail out on props equality but if context has changed
978
- // we don't do the bailout and we have to reuse existing props instead.
979
- } else if ( changedBits === 0 && oldProps === newProps ) {
980
- return bailoutOnAlreadyFinishedWork ( current , workInProgress ) ;
981
- }
982
- workInProgress . memoizedProps = newProps ;
983
-
984
- let observedBits = newProps . unstable_observedBits ;
985
- if ( observedBits === undefined || observedBits === null ) {
986
- // Subscribe to all changes by default
987
- observedBits = MAX_SIGNED_31_BIT_INT ;
882
+ if ( ! checkForPendingContext ( workInProgress , renderExpirationTime ) ) {
883
+ if ( hasLegacyContextChanged ( ) ) {
884
+ // Normally we can bail out on props equality but if context has changed
885
+ // we don't do the bailout and we have to reuse existing props instead.
886
+ } else if ( oldProps === newProps ) {
887
+ return bailoutOnAlreadyFinishedWork ( current , workInProgress ) ;
888
+ }
988
889
}
989
- // Store the observedBits on the fiber's stateNode for quick access.
990
- workInProgress . stateNode = observedBits ;
991
890
992
- if ( ( changedBits & observedBits ) !== 0 ) {
993
- // Context change propagation stops at matching consumers, for time-
994
- // slicing. Continue the propagation here.
995
- propagateContextChange (
996
- workInProgress ,
997
- context ,
998
- changedBits ,
999
- renderExpirationTime ,
1000
- ) ;
1001
- } else if (oldProps === newProps) {
1002
- // Skip over a memoized parent with a bitmask bailout even
1003
- // if we began working on it because of a deeper matching child.
1004
- return bailoutOnAlreadyFinishedWork ( current , workInProgress ) ;
1005
- }
1006
- // There is no bailout on `children` equality because we expect people
1007
- // to often pass a bound method as a child, but it may reference
1008
- // `this.state` or `this.props` (and thus needs to re-render on `setState`).
891
+ workInProgress.memoizedProps = newProps;
1009
892
1010
893
const render = newProps.children;
1011
894
@@ -1019,6 +902,8 @@ function updateContextConsumer(current, workInProgress, renderExpirationTime) {
1019
902
) ;
1020
903
}
1021
904
905
+ prepareToReadContext();
906
+ const newValue = readContext(context, newProps.unstable_observedBits);
1022
907
let newChildren;
1023
908
if (__DEV__) {
1024
909
ReactCurrentOwner . current = workInProgress ;
@@ -1028,6 +913,7 @@ function updateContextConsumer(current, workInProgress, renderExpirationTime) {
1028
913
} else {
1029
914
newChildren = render ( newValue ) ;
1030
915
}
916
+ workInProgress.firstContextReader = finishReadingContext();
1031
917
1032
918
// React DevTools reads this flag.
1033
919
workInProgress.effectTag |= PerformedWork;
0 commit comments