-
Notifications
You must be signed in to change notification settings - Fork 47.1k
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
Don't call onCommit et al if there are no effects #19863
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,10 +67,15 @@ import { | |
import { | ||
Ref, | ||
Update, | ||
Callback, | ||
Passive, | ||
Deletion, | ||
NoFlags, | ||
DidCapture, | ||
Snapshot, | ||
MutationMask, | ||
LayoutMask, | ||
PassiveMask, | ||
StaticMask, | ||
} from './ReactFiberFlags'; | ||
import invariant from 'shared/invariant'; | ||
|
@@ -787,6 +792,8 @@ function bubbleProperties(completedWork: Fiber) { | |
} | ||
|
||
completedWork.childLanes = newChildLanes; | ||
|
||
return didBailout; | ||
} | ||
|
||
function completeWork( | ||
|
@@ -804,7 +811,6 @@ function completeWork( | |
case ForwardRef: | ||
case Fragment: | ||
case Mode: | ||
case Profiler: | ||
case ContextConsumer: | ||
case MemoComponent: | ||
bubbleProperties(workInProgress); | ||
|
@@ -966,6 +972,53 @@ function completeWork( | |
bubbleProperties(workInProgress); | ||
return null; | ||
} | ||
case Profiler: { | ||
const didBailout = bubbleProperties(workInProgress); | ||
if (!didBailout) { | ||
// Use subtreeFlags to determine which commit callbacks should fire. | ||
// TODO: Move this logic to the commit phase, since we already check if | ||
// a fiber's subtree contains effects. Refactor the commit phase's | ||
// depth-first traversal so that we can put work tag-specific logic | ||
// before or after committing a subtree's effects. | ||
const OnRenderFlag = Update; | ||
const OnCommitFlag = Callback; | ||
const OnPostCommitFlag = Passive; | ||
const subtreeFlags = workInProgress.subtreeFlags; | ||
const flags = workInProgress.flags; | ||
let newFlags = flags; | ||
|
||
// Call onRender any time this fiber or its subtree are worked on, even | ||
// if there are no effects | ||
newFlags |= OnRenderFlag; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wasn't sure what the desired behavior was here, but I think conceptually this should fire any time one of the duration fields changes? So it should at least fire for the initial mount. Maybe for updates, we can check if the subtree flags includes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Not sure if I'm reading too literally, but we'll still want to call But yes, I think checking for work sounds right to me. I'll take a look at this. I think it might require a few tests updates too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
// Call onCommit only if the subtree contains layout work, or if it | ||
// contains deletions, since those might result in unmount work, which | ||
// we include in the same measure. | ||
// TODO: Can optimize by using a static flag to track whether a tree | ||
// contains layout effects, like we do for passive effects. | ||
Comment on lines
+997
to
+998
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we though? Static flags aren't specific to a render, so they wouldn't tell us if the layout effect happened to fire during the current update (which we care about for profiler) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right but it would at least let us optimize the case where there are no layout unmount work in the tree at all. Probably not that big of a win, though, since most trees have at least one, like a DOM ref or something. |
||
if ( | ||
(flags & (LayoutMask | Deletion)) !== NoFlags || | ||
(subtreeFlags & (LayoutMask | Deletion)) !== NoFlags | ||
) { | ||
newFlags |= OnCommitFlag; | ||
} | ||
|
||
// Call onPostCommit only if the subtree contains passive work. | ||
// Don't have to check for deletions, because Deletion is already | ||
// a passive flag. | ||
if ( | ||
(flags & PassiveMask) !== NoFlags || | ||
(subtreeFlags & PassiveMask) !== NoFlags | ||
) { | ||
newFlags |= OnPostCommitFlag; | ||
} | ||
workInProgress.flags = newFlags; | ||
} else { | ||
// This fiber and its subtree bailed out, so don't fire any callbacks. | ||
} | ||
|
||
return null; | ||
} | ||
case SuspenseComponent: { | ||
popSuspenseContext(workInProgress); | ||
const nextState: null | SuspenseState = workInProgress.memoizedState; | ||
|
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.
See: #19862 (comment)