@@ -26,6 +26,7 @@ import type {
26
26
OffscreenState ,
27
27
OffscreenInstance ,
28
28
OffscreenQueue ,
29
+ OffscreenProps ,
29
30
} from './ReactFiberOffscreenComponent' ;
30
31
import type { HookFlags } from './ReactHookEffectTags' ;
31
32
import type { Cache } from './ReactFiberCacheComponent.new' ;
@@ -1141,6 +1142,14 @@ function commitLayoutEffectOnFiber(
1141
1142
committedLanes ,
1142
1143
) ;
1143
1144
}
1145
+ if ( flags & Ref ) {
1146
+ const props : OffscreenProps = finishedWork . memoizedProps ;
1147
+ if ( props . mode === 'manual' ) {
1148
+ safelyAttachRef ( finishedWork , finishedWork . return ) ;
1149
+ } else {
1150
+ safelyDetachRef ( finishedWork , finishedWork . return ) ;
1151
+ }
1152
+ }
1144
1153
break ;
1145
1154
}
1146
1155
default : {
@@ -1314,7 +1323,7 @@ function commitTransitionProgress(offscreenFiber: Fiber) {
1314
1323
const wasHidden = prevState !== null ;
1315
1324
const isHidden = nextState !== null ;
1316
1325
1317
- const pendingMarkers = offscreenInstance . pendingMarkers ;
1326
+ const pendingMarkers = offscreenInstance . _pendingMarkers ;
1318
1327
// If there is a name on the suspense boundary, store that in
1319
1328
// the pending boundaries.
1320
1329
let name = null ;
@@ -2144,6 +2153,7 @@ function commitDeletionEffectsOnFiber(
2144
2153
return ;
2145
2154
}
2146
2155
case OffscreenComponent : {
2156
+ safelyDetachRef ( deletedFiber , nearestMountedAncestor ) ;
2147
2157
if ( deletedFiber . mode & ConcurrentMode ) {
2148
2158
// If this offscreen component is hidden, we already unmounted it. Before
2149
2159
// deleting the children, track that it's already unmounted so that we
@@ -2250,9 +2260,9 @@ function getRetryCache(finishedWork) {
2250
2260
}
2251
2261
case OffscreenComponent : {
2252
2262
const instance : OffscreenInstance = finishedWork . stateNode ;
2253
- let retryCache = instance . retryCache ;
2263
+ let retryCache = instance . _retryCache ;
2254
2264
if ( retryCache === null ) {
2255
- retryCache = instance . retryCache = new PossiblyWeakSet ( ) ;
2265
+ retryCache = instance . _retryCache = new PossiblyWeakSet ( ) ;
2256
2266
}
2257
2267
return retryCache ;
2258
2268
}
@@ -2623,6 +2633,12 @@ function commitMutationEffectsOnFiber(
2623
2633
return ;
2624
2634
}
2625
2635
case OffscreenComponent: {
2636
+ if ( flags & Ref ) {
2637
+ if ( current !== null ) {
2638
+ safelyDetachRef ( current , current . return ) ;
2639
+ }
2640
+ }
2641
+
2626
2642
const newState : OffscreenState | null = finishedWork . memoizedState ;
2627
2643
const isHidden = newState !== null ;
2628
2644
const wasHidden = current !== null && current . memoizedState !== null ;
@@ -2651,9 +2667,9 @@ function commitMutationEffectsOnFiber(
2651
2667
// Track the current state on the Offscreen instance so we can
2652
2668
// read it during an event
2653
2669
if ( isHidden ) {
2654
- offscreenInstance . visibility &= ~ OffscreenVisible ;
2670
+ offscreenInstance . _visibility &= ~ OffscreenVisible ;
2655
2671
} else {
2656
- offscreenInstance . visibility |= OffscreenVisible ;
2672
+ offscreenInstance . _visibility |= OffscreenVisible ;
2657
2673
}
2658
2674
2659
2675
if ( isHidden ) {
@@ -2838,6 +2854,9 @@ export function disappearLayoutEffects(finishedWork: Fiber) {
2838
2854
break ;
2839
2855
}
2840
2856
case OffscreenComponent : {
2857
+ // TODO (Offscreen) Check: flags & RefStatic
2858
+ safelyDetachRef ( finishedWork , finishedWork . return ) ;
2859
+
2841
2860
const isHidden = finishedWork . memoizedState !== null ;
2842
2861
if ( isHidden ) {
2843
2862
// Nested Offscreen tree is already hidden. Don't disappear
@@ -2985,6 +3004,8 @@ export function reappearLayoutEffects(
2985
3004
includeWorkInProgressEffects ,
2986
3005
) ;
2987
3006
}
3007
+ // TODO: Check flags & Ref
3008
+ safelyAttachRef ( finishedWork , finishedWork . return ) ;
2988
3009
break ;
2989
3010
}
2990
3011
default : {
@@ -3098,10 +3119,10 @@ function commitOffscreenPassiveMountEffects(
3098
3119
// Add all the transitions saved in the update queue during
3099
3120
// the render phase (ie the transitions associated with this boundary)
3100
3121
// into the transitions set.
3101
- if ( instance . transitions === null ) {
3102
- instance . transitions = new Set ( ) ;
3122
+ if ( instance . _transitions === null ) {
3123
+ instance . _transitions = new Set ( ) ;
3103
3124
}
3104
- instance . transitions . add ( transition ) ;
3125
+ instance . _transitions . add ( transition ) ;
3105
3126
} ) ;
3106
3127
}
3107
3128
@@ -3114,17 +3135,17 @@ function commitOffscreenPassiveMountEffects(
3114
3135
// caused them
3115
3136
if ( markerTransitions !== null ) {
3116
3137
markerTransitions . forEach ( transition => {
3117
- if ( instance . transitions === null ) {
3118
- instance . transitions = new Set ( ) ;
3119
- } else if ( instance . transitions . has ( transition ) ) {
3138
+ if ( instance . _transitions === null ) {
3139
+ instance . _transitions = new Set ( ) ;
3140
+ } else if ( instance . _transitions . has ( transition ) ) {
3120
3141
if ( markerInstance . pendingBoundaries === null ) {
3121
3142
markerInstance . pendingBoundaries = new Map ( ) ;
3122
3143
}
3123
- if ( instance . pendingMarkers === null ) {
3124
- instance . pendingMarkers = new Set ( ) ;
3144
+ if ( instance . _pendingMarkers === null ) {
3145
+ instance . _pendingMarkers = new Set ( ) ;
3125
3146
}
3126
3147
3127
- instance . pendingMarkers . add ( markerInstance ) ;
3148
+ instance . _pendingMarkers . add ( markerInstance ) ;
3128
3149
}
3129
3150
} ) ;
3130
3151
}
@@ -3139,8 +3160,8 @@ function commitOffscreenPassiveMountEffects(
3139
3160
3140
3161
// TODO: Refactor this into an if/else branch
3141
3162
if ( ! isHidden ) {
3142
- instance . transitions = null ;
3143
- instance . pendingMarkers = null ;
3163
+ instance . _transitions = null ;
3164
+ instance . _pendingMarkers = null ;
3144
3165
}
3145
3166
}
3146
3167
}
@@ -3320,7 +3341,7 @@ function commitPassiveMountOnFiber(
3320
3341
const isHidden = nextState !== null ;
3321
3342
3322
3343
if ( isHidden ) {
3323
- if ( instance . visibility & OffscreenPassiveEffectsConnected ) {
3344
+ if ( instance . _visibility & OffscreenPassiveEffectsConnected ) {
3324
3345
// The effects are currently connected. Update them.
3325
3346
recursivelyTraversePassiveMountEffects (
3326
3347
finishedRoot ,
@@ -3345,7 +3366,7 @@ function commitPassiveMountOnFiber(
3345
3366
}
3346
3367
} else {
3347
3368
// Legacy Mode: Fire the effects even if the tree is hidden.
3348
- instance . visibility |= OffscreenPassiveEffectsConnected ;
3369
+ instance . _visibility |= OffscreenPassiveEffectsConnected ;
3349
3370
recursivelyTraversePassiveMountEffects (
3350
3371
finishedRoot ,
3351
3372
finishedWork ,
@@ -3356,7 +3377,7 @@ function commitPassiveMountOnFiber(
3356
3377
}
3357
3378
} else {
3358
3379
// Tree is visible
3359
- if ( instance . visibility & OffscreenPassiveEffectsConnected ) {
3380
+ if ( instance . _visibility & OffscreenPassiveEffectsConnected ) {
3360
3381
// The effects are currently connected. Update them.
3361
3382
recursivelyTraversePassiveMountEffects (
3362
3383
finishedRoot ,
@@ -3368,7 +3389,7 @@ function commitPassiveMountOnFiber(
3368
3389
// The effects are currently disconnected. Reconnect them, while also
3369
3390
// firing effects inside newly mounted trees. This also applies to
3370
3391
// the initial render.
3371
- instance . visibility |= OffscreenPassiveEffectsConnected ;
3392
+ instance . _visibility |= OffscreenPassiveEffectsConnected ;
3372
3393
3373
3394
const includeWorkInProgressEffects =
3374
3395
( finishedWork . subtreeFlags & PassiveMask ) !== NoFlags ;
@@ -3500,7 +3521,7 @@ export function reconnectPassiveEffects(
3500
3521
const isHidden = nextState !== null ;
3501
3522
3502
3523
if ( isHidden ) {
3503
- if ( instance . visibility & OffscreenPassiveEffectsConnected ) {
3524
+ if ( instance . _visibility & OffscreenPassiveEffectsConnected ) {
3504
3525
// The effects are currently connected. Update them.
3505
3526
recursivelyTraverseReconnectPassiveEffects (
3506
3527
finishedRoot ,
@@ -3526,7 +3547,7 @@ export function reconnectPassiveEffects(
3526
3547
}
3527
3548
} else {
3528
3549
// Legacy Mode: Fire the effects even if the tree is hidden.
3529
- instance . visibility |= OffscreenPassiveEffectsConnected ;
3550
+ instance . _visibility |= OffscreenPassiveEffectsConnected ;
3530
3551
recursivelyTraverseReconnectPassiveEffects (
3531
3552
finishedRoot ,
3532
3553
finishedWork ,
@@ -3544,7 +3565,7 @@ export function reconnectPassiveEffects(
3544
3565
// continue traversing the tree and firing all the effects.
3545
3566
//
3546
3567
// We do need to set the "connected" flag on the instance, though.
3547
- instance . visibility |= OffscreenPassiveEffectsConnected ;
3568
+ instance . _visibility |= OffscreenPassiveEffectsConnected ;
3548
3569
3549
3570
recursivelyTraverseReconnectPassiveEffects (
3550
3571
finishedRoot ,
@@ -3799,7 +3820,7 @@ function commitPassiveUnmountOnFiber(finishedWork: Fiber): void {
3799
3820
3800
3821
if (
3801
3822
isHidden &&
3802
- instance . visibility & OffscreenPassiveEffectsConnected &&
3823
+ instance . _visibility & OffscreenPassiveEffectsConnected &&
3803
3824
// For backwards compatibility, don't unmount when a tree suspends. In
3804
3825
// the future we may change this to unmount after a delay.
3805
3826
( finishedWork . return === null ||
@@ -3809,7 +3830,7 @@ function commitPassiveUnmountOnFiber(finishedWork: Fiber): void {
3809
3830
// TODO: Add option or heuristic to delay before disconnecting the
3810
3831
// effects. Then if the tree reappears before the delay has elapsed, we
3811
3832
// can skip toggling the effects entirely.
3812
- instance . visibility &= ~ OffscreenPassiveEffectsConnected ;
3833
+ instance . _visibility &= ~ OffscreenPassiveEffectsConnected ;
3813
3834
recursivelyTraverseDisconnectPassiveEffects ( finishedWork ) ;
3814
3835
} else {
3815
3836
recursivelyTraversePassiveUnmountEffects ( finishedWork ) ;
@@ -3873,8 +3894,8 @@ export function disconnectPassiveEffect(finishedWork: Fiber): void {
3873
3894
}
3874
3895
case OffscreenComponent: {
3875
3896
const instance : OffscreenInstance = finishedWork . stateNode ;
3876
- if ( instance . visibility & OffscreenPassiveEffectsConnected ) {
3877
- instance . visibility &= ~ OffscreenPassiveEffectsConnected ;
3897
+ if ( instance . _visibility & OffscreenPassiveEffectsConnected ) {
3898
+ instance . _visibility &= ~ OffscreenPassiveEffectsConnected ;
3878
3899
recursivelyTraverseDisconnectPassiveEffects ( finishedWork ) ;
3879
3900
} else {
3880
3901
// The effects are already disconnected.
@@ -4002,7 +4023,7 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber(
4002
4023
// We need to mark this fiber's parents as deleted
4003
4024
const offscreenFiber : Fiber = ( current . child : any ) ;
4004
4025
const instance : OffscreenInstance = offscreenFiber . stateNode ;
4005
- const transitions = instance . transitions ;
4026
+ const transitions = instance . _transitions ;
4006
4027
if ( transitions !== null ) {
4007
4028
const abortReason = {
4008
4029
reason : 'suspense' ,
0 commit comments