-
Notifications
You must be signed in to change notification settings - Fork 47.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Fiber] Don't work on scheduled tasks while we're in an async commit but flush it eagerly if we're sync #31987
Conversation
In the same way we already do for passive effects.
This wrapper flushes any remaining effects.
When we flush from a task, we've yielded to paint. This only matters for performance.measure.
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
c55edd2
to
e8e7229
Compare
Comparing: 3ce77d5...7adb0b2 Critical size changesIncludes critical production bundles, as well as any change greater than 2%:
Significant size changesIncludes any change greater than 0.2%: Expand to show
|
@@ -3458,11 +3483,12 @@ function flushLayoutEffects( | |||
if (rootDidHavePassiveEffects) { | |||
// This commit has passive effects. Stash a reference to them. But don't | |||
// schedule a callback until after flushing layout work. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like we can remove this comment block now. We certainly don't stash a reference at this point anymore. And the scheduling is now obvious by advancing the phase.
suspendedCommitReason, | ||
completedRenderEndTime, | ||
); | ||
pendingEffectsStatus = PENDING_MUTATION_PHASE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it a problem that we potentially leave pendingEffectsRoot
as non-nullabble but pendingEffectsStatus === NO_PENDING_EFFECTS
when we throw in commitBeforeMutationEffects
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, not really because it'll just leak until we update anything again.
A bigger problem would be leaving pendingEffectsStatus
as something else. Leaving PENDING_PASSIVE_PHASE
doesn't really happen because it's immediately reset and even if it did it would try again. Leaving PENDING_MUTATION_PHASE
or PENDING_LAYOUT_PHASE
would stop any new update except sync which would be bad.
So I'll reset it in the beginning in case React itself throws so it doesn't get stuck.
That way we don't get stuck.
…but flush it eagerly if we're sync (#31987) This is a follow up to #31930 and a prerequisite for #31975. With View Transitions, the commit phase becomes async which means that other work can sneak in between. We need to be resilient to that. This PR first refactors the flushMutationEffects and flushLayoutEffects to use module scope variables to track its arguments so we can defer them. It shares these with how we were already doing it for flushPendingEffects. We also track how far along the commit phase we are so we know what we have left to flush. Then callers of flushPassiveEffects become flushPendingEffects. That helper synchronously flushes any remaining phases we've yet to commit. That ensure that things are at least consistent if that happens. Finally, when we are using a scheduled task, we don't do any work. This ensures that we're not flushing any work too early if we could've deferred it. This still ensures that we always do flush it before starting any new work on any root so new roots observe the committed state. There are some unfortunate effects that could happen from allowing things to flush eagerly. Such as if a flushSync sneaks in before startViewTransition, it'll skip the animation. If it's during a suspensey font it'll start the transition before the font has loaded which might be better than breaking flushSync. It'll also potentially flush passive effects inside the startViewTransition which should typically be ok. DiffTrain build for [defffdb](defffdb)
…but flush it eagerly if we're sync (#31987) This is a follow up to #31930 and a prerequisite for #31975. With View Transitions, the commit phase becomes async which means that other work can sneak in between. We need to be resilient to that. This PR first refactors the flushMutationEffects and flushLayoutEffects to use module scope variables to track its arguments so we can defer them. It shares these with how we were already doing it for flushPendingEffects. We also track how far along the commit phase we are so we know what we have left to flush. Then callers of flushPassiveEffects become flushPendingEffects. That helper synchronously flushes any remaining phases we've yet to commit. That ensure that things are at least consistent if that happens. Finally, when we are using a scheduled task, we don't do any work. This ensures that we're not flushing any work too early if we could've deferred it. This still ensures that we always do flush it before starting any new work on any root so new roots observe the committed state. There are some unfortunate effects that could happen from allowing things to flush eagerly. Such as if a flushSync sneaks in before startViewTransition, it'll skip the animation. If it's during a suspensey font it'll start the transition before the font has loaded which might be better than breaking flushSync. It'll also potentially flush passive effects inside the startViewTransition which should typically be ok. DiffTrain build for [defffdb](defffdb)
…but flush it eagerly if we're sync (facebook#31987) This is a follow up to facebook#31930 and a prerequisite for facebook#31975. With View Transitions, the commit phase becomes async which means that other work can sneak in between. We need to be resilient to that. This PR first refactors the flushMutationEffects and flushLayoutEffects to use module scope variables to track its arguments so we can defer them. It shares these with how we were already doing it for flushPendingEffects. We also track how far along the commit phase we are so we know what we have left to flush. Then callers of flushPassiveEffects become flushPendingEffects. That helper synchronously flushes any remaining phases we've yet to commit. That ensure that things are at least consistent if that happens. Finally, when we are using a scheduled task, we don't do any work. This ensures that we're not flushing any work too early if we could've deferred it. This still ensures that we always do flush it before starting any new work on any root so new roots observe the committed state. There are some unfortunate effects that could happen from allowing things to flush eagerly. Such as if a flushSync sneaks in before startViewTransition, it'll skip the animation. If it's during a suspensey font it'll start the transition before the font has loaded which might be better than breaking flushSync. It'll also potentially flush passive effects inside the startViewTransition which should typically be ok. DiffTrain build for [defffdb](facebook@defffdb)
…but flush it eagerly if we're sync (facebook#31987) This is a follow up to facebook#31930 and a prerequisite for facebook#31975. With View Transitions, the commit phase becomes async which means that other work can sneak in between. We need to be resilient to that. This PR first refactors the flushMutationEffects and flushLayoutEffects to use module scope variables to track its arguments so we can defer them. It shares these with how we were already doing it for flushPendingEffects. We also track how far along the commit phase we are so we know what we have left to flush. Then callers of flushPassiveEffects become flushPendingEffects. That helper synchronously flushes any remaining phases we've yet to commit. That ensure that things are at least consistent if that happens. Finally, when we are using a scheduled task, we don't do any work. This ensures that we're not flushing any work too early if we could've deferred it. This still ensures that we always do flush it before starting any new work on any root so new roots observe the committed state. There are some unfortunate effects that could happen from allowing things to flush eagerly. Such as if a flushSync sneaks in before startViewTransition, it'll skip the animation. If it's during a suspensey font it'll start the transition before the font has loaded which might be better than breaking flushSync. It'll also potentially flush passive effects inside the startViewTransition which should typically be ok. DiffTrain build for [defffdb](facebook@defffdb)
This is a follow up to #31930 and a prerequisite for #31975.
With View Transitions, the commit phase becomes async which means that other work can sneak in between. We need to be resilient to that.
This PR first refactors the flushMutationEffects and flushLayoutEffects to use module scope variables to track its arguments so we can defer them. It shares these with how we were already doing it for flushPendingEffects.
We also track how far along the commit phase we are so we know what we have left to flush.
Then callers of flushPassiveEffects become flushPendingEffects. That helper synchronously flushes any remaining phases we've yet to commit. That ensure that things are at least consistent if that happens.
Finally, when we are using a scheduled task, we don't do any work. This ensures that we're not flushing any work too early if we could've deferred it. This still ensures that we always do flush it before starting any new work on any root so new roots observe the committed state.
There are some unfortunate effects that could happen from allowing things to flush eagerly. Such as if a flushSync sneaks in before startViewTransition, it'll skip the animation. If it's during a suspensey font it'll start the transition before the font has loaded which might be better than breaking flushSync. It'll also potentially flush passive effects inside the startViewTransition which should typically be ok.