Skip to content

Commit df96450

Browse files
committed
Don't call onCommit et al if there are no effects
Checks `subtreeFlags` before scheduling an effect on the Profiler.
1 parent 8b2d378 commit df96450

File tree

3 files changed

+67
-18
lines changed

3 files changed

+67
-18
lines changed

packages/react-reconciler/src/ReactFiberBeginWork.new.js

-15
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ import {
6060
Hydrating,
6161
ContentReset,
6262
DidCapture,
63-
Update,
64-
Passive,
6563
Ref,
6664
Deletion,
6765
ForceUpdateForLegacySuspense,
@@ -675,9 +673,6 @@ function updateProfiler(
675673
renderLanes: Lanes,
676674
) {
677675
if (enableProfilerTimer) {
678-
// TODO: Only call onRender et al if subtree has effects
679-
workInProgress.flags |= Update | Passive;
680-
681676
// Reset effect durations for the next eventual effect phase.
682677
// These are reset during render to allow the DevTools commit hook a chance to read them,
683678
const stateNode = workInProgress.stateNode;
@@ -3117,16 +3112,6 @@ function beginWork(
31173112
}
31183113
case Profiler:
31193114
if (enableProfilerTimer) {
3120-
// Profiler should only call onRender when one of its descendants actually rendered.
3121-
// TODO: Only call onRender et al if subtree has effects
3122-
const hasChildWork = includesSomeLane(
3123-
renderLanes,
3124-
workInProgress.childLanes,
3125-
);
3126-
if (hasChildWork) {
3127-
workInProgress.flags |= Passive | Update;
3128-
}
3129-
31303115
// Reset effect durations for the next eventual effect phase.
31313116
// These are reset during render to allow the DevTools commit hook a chance to read them,
31323117
const stateNode = workInProgress.stateNode;

packages/react-reconciler/src/ReactFiberCommitWork.new.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ import {
7171
Placement,
7272
Snapshot,
7373
Update,
74+
Callback,
7475
PassiveMask,
7576
} from './ReactFiberFlags';
7677
import getComponentName from 'shared/getComponentName';
@@ -792,10 +793,17 @@ function commitLifeCycles(
792793
if (enableProfilerTimer) {
793794
const {onCommit, onRender} = finishedWork.memoizedProps;
794795
const {effectDuration} = finishedWork.stateNode;
796+
const flags = finishedWork.flags;
795797

796798
const commitTime = getCommitTime();
797799

798-
if (typeof onRender === 'function') {
800+
const OnRenderFlag = Update;
801+
const OnCommitFlag = Callback;
802+
803+
if (
804+
(flags & OnRenderFlag) !== NoFlags &&
805+
typeof onRender === 'function'
806+
) {
799807
if (enableSchedulerTracing) {
800808
onRender(
801809
finishedWork.memoizedProps.id,
@@ -819,7 +827,10 @@ function commitLifeCycles(
819827
}
820828

821829
if (enableProfilerCommitHooks) {
822-
if (typeof onCommit === 'function') {
830+
if (
831+
(flags & OnCommitFlag) !== NoFlags &&
832+
typeof onCommit === 'function'
833+
) {
823834
if (enableSchedulerTracing) {
824835
onCommit(
825836
finishedWork.memoizedProps.id,

packages/react-reconciler/src/ReactFiberCompleteWork.new.js

+54-1
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,15 @@ import {
6767
import {
6868
Ref,
6969
Update,
70+
Callback,
71+
Passive,
72+
Deletion,
7073
NoFlags,
7174
DidCapture,
7275
Snapshot,
7376
MutationMask,
77+
LayoutMask,
78+
PassiveMask,
7479
StaticMask,
7580
} from './ReactFiberFlags';
7681
import invariant from 'shared/invariant';
@@ -787,6 +792,8 @@ function bubbleProperties(completedWork: Fiber) {
787792
}
788793

789794
completedWork.childLanes = newChildLanes;
795+
796+
return didBailout;
790797
}
791798

792799
function completeWork(
@@ -804,7 +811,6 @@ function completeWork(
804811
case ForwardRef:
805812
case Fragment:
806813
case Mode:
807-
case Profiler:
808814
case ContextConsumer:
809815
case MemoComponent:
810816
bubbleProperties(workInProgress);
@@ -966,6 +972,53 @@ function completeWork(
966972
bubbleProperties(workInProgress);
967973
return null;
968974
}
975+
case Profiler: {
976+
const didBailout = bubbleProperties(workInProgress);
977+
if (!didBailout) {
978+
// Use subtreeFlags to determine which commit callbacks should fire.
979+
// TODO: Move this logic to the commit phase, since we already check if
980+
// a fiber's subtree contains effects. Refactor the commit phase's
981+
// depth-first traversal so that we can put work tag-specific logic
982+
// before or after committing a subtree's effects.
983+
const OnRenderFlag = Update;
984+
const OnCommitFlag = Callback;
985+
const OnPostCommitFlag = Passive;
986+
const subtreeFlags = workInProgress.subtreeFlags;
987+
const flags = workInProgress.flags;
988+
let newFlags = flags;
989+
990+
// Call onRender any time this fiber or its subtree are worked on, even
991+
// if there are no effects
992+
newFlags |= OnRenderFlag;
993+
994+
// Call onCommit only if the subtree contains layout work, or if it
995+
// contains deletions, since those might result in unmount work, which
996+
// we include in the same measure.
997+
// TODO: Can optimize by using a static flag to track whether a tree
998+
// contains layout effects, like we do for passive effects.
999+
if (
1000+
(flags & (LayoutMask | Deletion)) !== NoFlags ||
1001+
(subtreeFlags & (LayoutMask | Deletion)) !== NoFlags
1002+
) {
1003+
newFlags |= OnCommitFlag;
1004+
}
1005+
1006+
// Call onPostCommit only if the subtree contains passive work.
1007+
// Don't have to check for deletions, because Deletion is already
1008+
// a passive flag.
1009+
if (
1010+
(flags & PassiveMask) !== NoFlags ||
1011+
(subtreeFlags & PassiveMask) !== NoFlags
1012+
) {
1013+
newFlags |= OnPostCommitFlag;
1014+
}
1015+
workInProgress.flags = newFlags;
1016+
} else {
1017+
// This fiber and its subtree bailed out, so don't fire any callbacks.
1018+
}
1019+
1020+
return null;
1021+
}
9691022
case SuspenseComponent: {
9701023
popSuspenseContext(workInProgress);
9711024
const nextState: null | SuspenseState = workInProgress.memoizedState;

0 commit comments

Comments
 (0)