88 */ 
99
1010import  type  { Fiber }  from  './ReactInternalTypes' ; 
11- import  type  { Lanes }  from  './ReactFiberLane' ; 
11+ import  type  { Lanes ,   Lane }  from  './ReactFiberLane' ; 
1212import  type  { 
1313  ReactFundamentalComponentInstance , 
1414  ReactScopeInstance , 
@@ -58,14 +58,20 @@ import {
5858  OffscreenComponent , 
5959  LegacyHiddenComponent , 
6060}  from  './ReactWorkTags' ; 
61- import  { NoMode ,  BlockingMode ,  ProfileMode }  from  './ReactTypeOfMode' ; 
61+ import  { 
62+   NoMode , 
63+   BlockingMode , 
64+   ConcurrentMode , 
65+   ProfileMode , 
66+ }  from  './ReactTypeOfMode' ; 
6267import  { 
6368  Ref , 
6469  Update , 
6570  NoFlags , 
6671  DidCapture , 
6772  Snapshot , 
6873  MutationMask , 
74+   StaticMask , 
6975}  from  './ReactFiberFlags' ; 
7076import  invariant  from  'shared/invariant' ; 
7177
@@ -137,9 +143,16 @@ import {
137143  renderHasNotSuspendedYet , 
138144  popRenderLanes , 
139145  getRenderTargetTime , 
146+   subtreeRenderLanes , 
140147}  from  './ReactFiberWorkLoop.new' ; 
141148import  { createFundamentalStateInstance }  from  './ReactFiberFundamental.new' ; 
142- import  { OffscreenLane ,  SomeRetryLane }  from  './ReactFiberLane' ; 
149+ import  { 
150+   OffscreenLane , 
151+   SomeRetryLane , 
152+   NoLanes , 
153+   includesSomeLane , 
154+   mergeLanes , 
155+ }  from  './ReactFiberLane' ; 
143156import  { resetChildFibers }  from  './ReactChildFiber.new' ; 
144157import  { createScopeInstance }  from  './ReactFiberScope.new' ; 
145158import  { transferActualDuration }  from  './ReactProfilerTimer.new' ; 
@@ -668,6 +681,114 @@ function cutOffTailIfNeeded(
668681  } 
669682} 
670683
684+ function  bubbleProperties ( completedWork : Fiber )  { 
685+   const  didBailout  = 
686+     completedWork . alternate  !==  null  && 
687+     completedWork . alternate . child  ===  completedWork . child ; 
688+ 
689+   let  newChildLanes  =  NoLanes ; 
690+   let  subtreeFlags  =  NoFlags ; 
691+ 
692+   if  ( ! didBailout )  { 
693+     // Bubble up the earliest expiration time. 
694+     if  ( enableProfilerTimer  &&  ( completedWork . mode  &  ProfileMode )  !==  NoMode )  { 
695+       // In profiling mode, resetChildExpirationTime is also used to reset 
696+       // profiler durations. 
697+       let  actualDuration  =  completedWork . actualDuration ; 
698+       let  treeBaseDuration  =  ( ( completedWork . selfBaseDuration : any ) : number ) ; 
699+ 
700+       let  child  =  completedWork . child ; 
701+       while  ( child  !==  null )  { 
702+         newChildLanes  =  mergeLanes ( 
703+           newChildLanes , 
704+           mergeLanes ( child . lanes ,  child . childLanes ) , 
705+         ) ; 
706+ 
707+         subtreeFlags  |=  child . subtreeFlags ; 
708+         subtreeFlags  |=  child . flags ; 
709+ 
710+         // When a fiber is cloned, its actualDuration is reset to 0. This value will 
711+         // only be updated if work is done on the fiber (i.e. it doesn't bailout). 
712+         // When work is done, it should bubble to the parent's actualDuration. If 
713+         // the fiber has not been cloned though, (meaning no work was done), then 
714+         // this value will reflect the amount of time spent working on a previous 
715+         // render. In that case it should not bubble. We determine whether it was 
716+         // cloned by comparing the child pointer. 
717+         actualDuration  +=  child . actualDuration ; 
718+ 
719+         treeBaseDuration  +=  child . treeBaseDuration ; 
720+         child  =  child . sibling ; 
721+       } 
722+ 
723+       completedWork . actualDuration  =  actualDuration ; 
724+       completedWork . treeBaseDuration  =  treeBaseDuration ; 
725+     }  else  { 
726+       let  child  =  completedWork . child ; 
727+       while  ( child  !==  null )  { 
728+         newChildLanes  =  mergeLanes ( 
729+           newChildLanes , 
730+           mergeLanes ( child . lanes ,  child . childLanes ) , 
731+         ) ; 
732+ 
733+         subtreeFlags  |=  child . subtreeFlags ; 
734+         subtreeFlags  |=  child . flags ; 
735+ 
736+         child  =  child . sibling ; 
737+       } 
738+     } 
739+ 
740+     completedWork . subtreeFlags  |=  subtreeFlags ; 
741+   }  else  { 
742+     // Bubble up the earliest expiration time. 
743+     if  ( enableProfilerTimer  &&  ( completedWork . mode  &  ProfileMode )  !==  NoMode )  { 
744+       // In profiling mode, resetChildExpirationTime is also used to reset 
745+       // profiler durations. 
746+       let  treeBaseDuration  =  ( ( completedWork . selfBaseDuration : any ) : number ) ; 
747+ 
748+       let  child  =  completedWork . child ; 
749+       while  ( child  !==  null )  { 
750+         newChildLanes  =  mergeLanes ( 
751+           newChildLanes , 
752+           mergeLanes ( child . lanes ,  child . childLanes ) , 
753+         ) ; 
754+ 
755+         // "Static" flags share the lifetime of the fiber/hook they belong to, 
756+         // so we should bubble those up even during a bailout. All the other 
757+         // flags have a lifetime only of a single render + commit, so we should 
758+         // ignore them. 
759+         subtreeFlags  |=  child . subtreeFlags  &  StaticMask ; 
760+         subtreeFlags  |=  child . flags  &  StaticMask ; 
761+ 
762+         treeBaseDuration  +=  child . treeBaseDuration ; 
763+         child  =  child . sibling ; 
764+       } 
765+ 
766+       completedWork . treeBaseDuration  =  treeBaseDuration ; 
767+     }  else  { 
768+       let  child  =  completedWork . child ; 
769+       while  ( child  !==  null )  { 
770+         newChildLanes  =  mergeLanes ( 
771+           newChildLanes , 
772+           mergeLanes ( child . lanes ,  child . childLanes ) , 
773+         ) ; 
774+ 
775+         // "Static" flags share the lifetime of the fiber/hook they belong to, 
776+         // so we should bubble those up even during a bailout. All the other 
777+         // flags have a lifetime only of a single render + commit, so we should 
778+         // ignore them. 
779+         subtreeFlags  |=  child . subtreeFlags  &  StaticMask ; 
780+         subtreeFlags  |=  child . flags  &  StaticMask ; 
781+ 
782+         child  =  child . sibling ; 
783+       } 
784+     } 
785+ 
786+     completedWork . subtreeFlags  |=  subtreeFlags ; 
787+   } 
788+ 
789+   completedWork . childLanes  =  newChildLanes ; 
790+ } 
791+ 
671792function  completeWork ( 
672793  current : Fiber  |  null , 
673794  workInProgress : Fiber , 
@@ -686,12 +807,14 @@ function completeWork(
686807    case  Profiler :
687808    case  ContextConsumer :
688809    case  MemoComponent :
810+       bubbleProperties ( workInProgress ) ; 
689811      return  null ; 
690812    case  ClassComponent : { 
691813      const  Component  =  workInProgress . type ; 
692814      if  ( isLegacyContextProvider ( Component ) )  { 
693815        popLegacyContext ( workInProgress ) ; 
694816      } 
817+       bubbleProperties ( workInProgress ) ; 
695818      return  null ; 
696819    } 
697820    case  HostRoot : { 
@@ -720,6 +843,7 @@ function completeWork(
720843        } 
721844      } 
722845      updateHostContainer ( current ,  workInProgress ) ; 
846+       bubbleProperties ( workInProgress ) ; 
723847      return  null ; 
724848    } 
725849    case  HostComponent : { 
@@ -746,6 +870,7 @@ function completeWork(
746870              'caused by a bug in React. Please file an issue.' , 
747871          ) ; 
748872          // This can happen when we abort work. 
873+           bubbleProperties ( workInProgress ) ; 
749874          return  null ; 
750875        } 
751876
@@ -803,6 +928,7 @@ function completeWork(
803928          markRef ( workInProgress ) ; 
804929        } 
805930      } 
931+       bubbleProperties ( workInProgress ) ; 
806932      return  null ; 
807933    } 
808934    case  HostText : { 
@@ -837,6 +963,7 @@ function completeWork(
837963          ) ; 
838964        } 
839965      } 
966+       bubbleProperties ( workInProgress ) ; 
840967      return  null ; 
841968    } 
842969    case  SuspenseComponent : { 
@@ -856,6 +983,20 @@ function completeWork(
856983            if  ( enableSchedulerTracing )  { 
857984              markSpawnedWork ( OffscreenLane ) ; 
858985            } 
986+             bubbleProperties ( workInProgress ) ; 
987+             if  ( enableProfilerTimer )  { 
988+               if  ( ( workInProgress . mode  &  ProfileMode )  !==  NoMode )  { 
989+                 const  isTimedOutSuspense  =  nextState  !==  null ; 
990+                 if  ( isTimedOutSuspense )  { 
991+                   // Don't count time spent in a timed out Suspense subtree as part of the base duration. 
992+                   const  primaryChildFragment  =  workInProgress . child ; 
993+                   if  ( primaryChildFragment  !==  null )  { 
994+                     // $FlowFixMe Flow doens't support type casting in combiation with the -= operator 
995+                     workInProgress . treeBaseDuration  -=  ( ( primaryChildFragment . treeBaseDuration : any ) : number ) ; 
996+                   } 
997+                 } 
998+               } 
999+             } 
8591000            return  null ; 
8601001          }  else  { 
8611002            // We should never have been in a hydration state if we didn't have a current. 
@@ -872,6 +1013,20 @@ function completeWork(
8721013            // If something suspended, schedule an effect to attach retry listeners. 
8731014            // So we might as well always mark this. 
8741015            workInProgress . flags  |=  Update ; 
1016+             bubbleProperties ( workInProgress ) ; 
1017+             if  ( enableProfilerTimer )  { 
1018+               if  ( ( workInProgress . mode  &  ProfileMode )  !==  NoMode )  { 
1019+                 const  isTimedOutSuspense  =  nextState  !==  null ; 
1020+                 if  ( isTimedOutSuspense )  { 
1021+                   // Don't count time spent in a timed out Suspense subtree as part of the base duration. 
1022+                   const  primaryChildFragment  =  workInProgress . child ; 
1023+                   if  ( primaryChildFragment  !==  null )  { 
1024+                     // $FlowFixMe Flow doens't support type casting in combiation with the -= operator 
1025+                     workInProgress . treeBaseDuration  -=  ( ( primaryChildFragment . treeBaseDuration : any ) : number ) ; 
1026+                   } 
1027+                 } 
1028+               } 
1029+             } 
8751030            return  null ; 
8761031          } 
8771032        } 
@@ -887,6 +1042,7 @@ function completeWork(
8871042        )  { 
8881043          transferActualDuration ( workInProgress ) ; 
8891044        } 
1045+         // Don't bubble properties in this case. 
8901046        return  workInProgress ; 
8911047      } 
8921048
@@ -964,6 +1120,19 @@ function completeWork(
9641120        // Always notify the callback 
9651121        workInProgress . flags  |=  Update ; 
9661122      } 
1123+       bubbleProperties ( workInProgress ) ; 
1124+       if  ( enableProfilerTimer )  { 
1125+         if  ( ( workInProgress . mode  &  ProfileMode )  !==  NoMode )  { 
1126+           if  ( nextDidTimeout )  { 
1127+             // Don't count time spent in a timed out Suspense subtree as part of the base duration. 
1128+             const  primaryChildFragment  =  workInProgress . child ; 
1129+             if  ( primaryChildFragment  !==  null )  { 
1130+               // $FlowFixMe Flow doens't support type casting in combiation with the -= operator 
1131+               workInProgress . treeBaseDuration  -=  ( ( primaryChildFragment . treeBaseDuration : any ) : number ) ; 
1132+             } 
1133+           } 
1134+         } 
1135+       } 
9671136      return  null ; 
9681137    } 
9691138    case  HostPortal :
@@ -972,10 +1141,12 @@ function completeWork(
9721141      if  ( current  ===  null )  { 
9731142        preparePortalMount ( workInProgress . stateNode . containerInfo ) ; 
9741143      } 
1144+       bubbleProperties ( workInProgress ) ; 
9751145      return  null ; 
9761146    case  ContextProvider :
9771147      // Pop provider fiber 
9781148      popProvider ( workInProgress ) ; 
1149+       bubbleProperties ( workInProgress ) ; 
9791150      return  null ; 
9801151    case  IncompleteClassComponent : { 
9811152      // Same as class component case. I put it down here so that the tags are 
@@ -984,6 +1155,7 @@ function completeWork(
9841155      if  ( isLegacyContextProvider ( Component ) )  { 
9851156        popLegacyContext ( workInProgress ) ; 
9861157      } 
1158+       bubbleProperties ( workInProgress ) ; 
9871159      return  null ; 
9881160    } 
9891161    case  SuspenseListComponent : { 
@@ -995,6 +1167,7 @@ function completeWork(
9951167      if  ( renderState  ===  null )  { 
9961168        // We're running in the default, "independent" mode. 
9971169        // We don't do anything in this mode. 
1170+         bubbleProperties ( workInProgress ) ; 
9981171        return  null ; 
9991172      } 
10001173
@@ -1060,6 +1233,7 @@ function completeWork(
10601233                    ForceSuspenseFallback , 
10611234                  ) , 
10621235                ) ; 
1236+                 // Don't bubble properties in this case. 
10631237                return  workInProgress . child ; 
10641238              } 
10651239              row  =  row . sibling ; 
@@ -1117,6 +1291,7 @@ function completeWork(
11171291              ! getIsHydrating ( )  // We don't cut it if we're hydrating. 
11181292            )  { 
11191293              // We're done. 
1294+               bubbleProperties ( workInProgress ) ; 
11201295              return  null ; 
11211296            } 
11221297          }  else  if  ( 
@@ -1188,8 +1363,10 @@ function completeWork(
11881363        } 
11891364        pushSuspenseContext ( workInProgress ,  suspenseContext ) ; 
11901365        // Do a pass over the next row. 
1366+         // Don't bubble properties in this case. 
11911367        return  next ; 
11921368      } 
1369+       bubbleProperties ( workInProgress ) ; 
11931370      return  null ; 
11941371    } 
11951372    case  FundamentalComponent : { 
@@ -1217,6 +1394,7 @@ function completeWork(
12171394          ) : any ) : Instance ) ; 
12181395          fundamentalInstance . instance  =  instance ; 
12191396          if  ( fundamentalImpl . reconcileChildren  ===  false )  { 
1397+             bubbleProperties ( workInProgress ) ; 
12201398            return  null ; 
12211399          } 
12221400          appendAllChildren ( instance ,  workInProgress ,  false ,  false ) ; 
@@ -1239,6 +1417,7 @@ function completeWork(
12391417            markUpdate ( workInProgress ) ; 
12401418          } 
12411419        } 
1420+         bubbleProperties ( workInProgress ) ; 
12421421        return  null ; 
12431422      } 
12441423      break ; 
@@ -1261,31 +1440,44 @@ function completeWork(
12611440            markRef ( workInProgress ) ; 
12621441          } 
12631442        } 
1443+         bubbleProperties ( workInProgress ) ; 
12641444        return  null ; 
12651445      } 
12661446      break ; 
12671447    } 
12681448    case  Block :
12691449      if  ( enableBlocksAPI )  { 
1450+         bubbleProperties ( workInProgress ) ; 
12701451        return  null ; 
12711452      } 
12721453      break ; 
12731454    case  OffscreenComponent :
12741455    case  LegacyHiddenComponent : { 
12751456      popRenderLanes ( workInProgress ) ; 
1457+       const  nextState : OffscreenState  |  null  =  workInProgress . memoizedState ; 
1458+       const  nextIsHidden  =  nextState  !==  null ; 
1459+ 
12761460      if  ( current  !==  null )  { 
1277-         const  nextState : OffscreenState  |  null  =  workInProgress . memoizedState ; 
12781461        const  prevState : OffscreenState  |  null  =  current . memoizedState ; 
12791462
12801463        const  prevIsHidden  =  prevState  !==  null ; 
1281-         const  nextIsHidden  =  nextState  !==  null ; 
12821464        if  ( 
12831465          prevIsHidden  !==  nextIsHidden  && 
12841466          newProps . mode  !==  'unstable-defer-without-hiding' 
12851467        )  { 
12861468          workInProgress . flags  |=  Update ; 
12871469        } 
12881470      } 
1471+ 
1472+       // Don't bubble properties for hidden children. 
1473+       if  ( 
1474+         ! nextIsHidden  || 
1475+         includesSomeLane ( subtreeRenderLanes ,  ( OffscreenLane : Lane ) )  || 
1476+         ( workInProgress . mode  &  ConcurrentMode )  ===  NoLanes 
1477+       )  { 
1478+         bubbleProperties ( workInProgress ) ; 
1479+       } 
1480+ 
12891481      return  null ; 
12901482    } 
12911483  } 
0 commit comments