Skip to content

Commit 466b26c

Browse files
author
Brian Vaughn
authored
Store commit durations on HostRoot for DevTools access (#20983)
Also add missing feature flag wrappers around effect duration attributes.
1 parent 89acfa6 commit 466b26c

8 files changed

+144
-72
lines changed

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

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import {
7575
debugRenderPhaseSideEffectsForStrictMode,
7676
disableLegacyContext,
7777
disableModulePatternComponents,
78+
enableProfilerCommitHooks,
7879
enableProfilerTimer,
7980
enableSchedulerTracing,
8081
enableSuspenseServerRenderer,
@@ -837,11 +838,13 @@ function updateProfiler(
837838
if (enableProfilerTimer) {
838839
workInProgress.flags |= Update;
839840

840-
// Reset effect durations for the next eventual effect phase.
841-
// These are reset during render to allow the DevTools commit hook a chance to read them,
842-
const stateNode = workInProgress.stateNode;
843-
stateNode.effectDuration = 0;
844-
stateNode.passiveEffectDuration = 0;
841+
if (enableProfilerCommitHooks) {
842+
// Reset effect durations for the next eventual effect phase.
843+
// These are reset during render to allow the DevTools commit hook a chance to read them,
844+
const stateNode = workInProgress.stateNode;
845+
stateNode.effectDuration = 0;
846+
stateNode.passiveEffectDuration = 0;
847+
}
845848
}
846849
const nextProps = workInProgress.pendingProps;
847850
const nextChildren = nextProps.children;
@@ -3320,11 +3323,13 @@ function beginWork(
33203323
workInProgress.flags |= Update;
33213324
}
33223325

3323-
// Reset effect durations for the next eventual effect phase.
3324-
// These are reset during render to allow the DevTools commit hook a chance to read them,
3325-
const stateNode = workInProgress.stateNode;
3326-
stateNode.effectDuration = 0;
3327-
stateNode.passiveEffectDuration = 0;
3326+
if (enableProfilerCommitHooks) {
3327+
// Reset effect durations for the next eventual effect phase.
3328+
// These are reset during render to allow the DevTools commit hook a chance to read them,
3329+
const stateNode = workInProgress.stateNode;
3330+
stateNode.effectDuration = 0;
3331+
stateNode.passiveEffectDuration = 0;
3332+
}
33283333
}
33293334
break;
33303335
case SuspenseComponent: {

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

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import {
7575
debugRenderPhaseSideEffectsForStrictMode,
7676
disableLegacyContext,
7777
disableModulePatternComponents,
78+
enableProfilerCommitHooks,
7879
enableProfilerTimer,
7980
enableSchedulerTracing,
8081
enableSuspenseServerRenderer,
@@ -837,11 +838,13 @@ function updateProfiler(
837838
if (enableProfilerTimer) {
838839
workInProgress.flags |= Update;
839840

840-
// Reset effect durations for the next eventual effect phase.
841-
// These are reset during render to allow the DevTools commit hook a chance to read them,
842-
const stateNode = workInProgress.stateNode;
843-
stateNode.effectDuration = 0;
844-
stateNode.passiveEffectDuration = 0;
841+
if (enableProfilerCommitHooks) {
842+
// Reset effect durations for the next eventual effect phase.
843+
// These are reset during render to allow the DevTools commit hook a chance to read them,
844+
const stateNode = workInProgress.stateNode;
845+
stateNode.effectDuration = 0;
846+
stateNode.passiveEffectDuration = 0;
847+
}
845848
}
846849
const nextProps = workInProgress.pendingProps;
847850
const nextChildren = nextProps.children;
@@ -3320,11 +3323,13 @@ function beginWork(
33203323
workInProgress.flags |= Update;
33213324
}
33223325

3323-
// Reset effect durations for the next eventual effect phase.
3324-
// These are reset during render to allow the DevTools commit hook a chance to read them,
3325-
const stateNode = workInProgress.stateNode;
3326-
stateNode.effectDuration = 0;
3327-
stateNode.passiveEffectDuration = 0;
3326+
if (enableProfilerCommitHooks) {
3327+
// Reset effect durations for the next eventual effect phase.
3328+
// These are reset during render to allow the DevTools commit hook a chance to read them,
3329+
const stateNode = workInProgress.stateNode;
3330+
stateNode.effectDuration = 0;
3331+
stateNode.passiveEffectDuration = 0;
3332+
}
33283333
}
33293334
break;
33303335
case SuspenseComponent: {

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

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -578,11 +578,16 @@ export function commitPassiveEffectDurations(
578578
// Bubble times to the next nearest ancestor Profiler.
579579
// After we process that Profiler, we'll bubble further up.
580580
let parentFiber = finishedWork.return;
581-
while (parentFiber !== null) {
582-
if (parentFiber.tag === Profiler) {
583-
const parentStateNode = parentFiber.stateNode;
584-
parentStateNode.passiveEffectDuration += passiveEffectDuration;
585-
break;
581+
outer: while (parentFiber !== null) {
582+
switch (parentFiber.tag) {
583+
case HostRoot:
584+
const root = parentFiber.stateNode;
585+
root.passiveEffectDuration += passiveEffectDuration;
586+
break outer;
587+
case Profiler:
588+
const parentStateNode = parentFiber.stateNode;
589+
parentStateNode.passiveEffectDuration += passiveEffectDuration;
590+
break outer;
586591
}
587592
parentFiber = parentFiber.return;
588593
}
@@ -885,11 +890,16 @@ function commitLayoutEffectOnFiber(
885890
// Propagate layout effect durations to the next nearest Profiler ancestor.
886891
// Do not reset these values until the next render so DevTools has a chance to read them first.
887892
let parentFiber = finishedWork.return;
888-
while (parentFiber !== null) {
889-
if (parentFiber.tag === Profiler) {
890-
const parentStateNode = parentFiber.stateNode;
891-
parentStateNode.effectDuration += effectDuration;
892-
break;
893+
outer: while (parentFiber !== null) {
894+
switch (parentFiber.tag) {
895+
case HostRoot:
896+
const root = parentFiber.stateNode;
897+
root.effectDuration += effectDuration;
898+
break outer;
899+
case Profiler:
900+
const parentStateNode = parentFiber.stateNode;
901+
parentStateNode.effectDuration += effectDuration;
902+
break outer;
893903
}
894904
parentFiber = parentFiber.return;
895905
}

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

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -578,11 +578,16 @@ export function commitPassiveEffectDurations(
578578
// Bubble times to the next nearest ancestor Profiler.
579579
// After we process that Profiler, we'll bubble further up.
580580
let parentFiber = finishedWork.return;
581-
while (parentFiber !== null) {
582-
if (parentFiber.tag === Profiler) {
583-
const parentStateNode = parentFiber.stateNode;
584-
parentStateNode.passiveEffectDuration += passiveEffectDuration;
585-
break;
581+
outer: while (parentFiber !== null) {
582+
switch (parentFiber.tag) {
583+
case HostRoot:
584+
const root = parentFiber.stateNode;
585+
root.passiveEffectDuration += passiveEffectDuration;
586+
break outer;
587+
case Profiler:
588+
const parentStateNode = parentFiber.stateNode;
589+
parentStateNode.passiveEffectDuration += passiveEffectDuration;
590+
break outer;
586591
}
587592
parentFiber = parentFiber.return;
588593
}
@@ -885,11 +890,16 @@ function commitLayoutEffectOnFiber(
885890
// Propagate layout effect durations to the next nearest Profiler ancestor.
886891
// Do not reset these values until the next render so DevTools has a chance to read them first.
887892
let parentFiber = finishedWork.return;
888-
while (parentFiber !== null) {
889-
if (parentFiber.tag === Profiler) {
890-
const parentStateNode = parentFiber.stateNode;
891-
parentStateNode.effectDuration += effectDuration;
892-
break;
893+
outer: while (parentFiber !== null) {
894+
switch (parentFiber.tag) {
895+
case HostRoot:
896+
const root = parentFiber.stateNode;
897+
root.effectDuration += effectDuration;
898+
break outer;
899+
case Profiler:
900+
const parentStateNode = parentFiber.stateNode;
901+
parentStateNode.effectDuration += effectDuration;
902+
break outer;
893903
}
894904
parentFiber = parentFiber.return;
895905
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import {
2222
enableSchedulerTracing,
2323
enableSuspenseCallback,
2424
enableCache,
25+
enableProfilerCommitHooks,
26+
enableProfilerTimer,
2527
} from 'shared/ReactFeatureFlags';
2628
import {unstable_getThreadID} from 'scheduler/tracing';
2729
import {initializeUpdateQueue} from './ReactUpdateQueue.new';
@@ -71,6 +73,11 @@ function FiberRootNode(containerInfo, tag, hydrate) {
7173
this.hydrationCallbacks = null;
7274
}
7375

76+
if (enableProfilerTimer && enableProfilerCommitHooks) {
77+
this.effectDuration = 0;
78+
this.passiveEffectDuration = 0;
79+
}
80+
7481
if (__DEV__) {
7582
switch (tag) {
7683
case ConcurrentRoot:

packages/react-reconciler/src/ReactFiberRoot.old.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import {
2222
enableSchedulerTracing,
2323
enableSuspenseCallback,
2424
enableCache,
25+
enableProfilerCommitHooks,
26+
enableProfilerTimer,
2527
} from 'shared/ReactFeatureFlags';
2628
import {unstable_getThreadID} from 'scheduler/tracing';
2729
import {initializeUpdateQueue} from './ReactUpdateQueue.old';
@@ -71,6 +73,11 @@ function FiberRootNode(containerInfo, tag, hydrate) {
7173
this.hydrationCallbacks = null;
7274
}
7375

76+
if (enableProfilerTimer && enableProfilerCommitHooks) {
77+
this.effectDuration = 0;
78+
this.passiveEffectDuration = 0;
79+
}
80+
7481
if (__DEV__) {
7582
switch (tag) {
7683
case ConcurrentRoot:

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

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
enableProfilerNestedUpdatePhase,
1515
enableProfilerTimer,
1616
} from 'shared/ReactFeatureFlags';
17-
import {Profiler} from './ReactWorkTags';
17+
import {HostRoot, Profiler} from './ReactWorkTags';
1818

1919
// Intentionally not named imports because Rollup would use dynamic dispatch for
2020
// CommonJS interop named imports.
@@ -140,13 +140,19 @@ function recordLayoutEffectDuration(fiber: Fiber): void {
140140

141141
layoutEffectStartTime = -1;
142142

143-
// Store duration on the next nearest Profiler ancestor.
143+
// Store duration on the next nearest Profiler ancestor
144+
// Or the root (for the DevTools Profiler to read)
144145
let parentFiber = fiber.return;
145146
while (parentFiber !== null) {
146-
if (parentFiber.tag === Profiler) {
147-
const parentStateNode = parentFiber.stateNode;
148-
parentStateNode.effectDuration += elapsedTime;
149-
break;
147+
switch (parentFiber.tag) {
148+
case HostRoot:
149+
const root = parentFiber.stateNode;
150+
root.effectDuration += elapsedTime;
151+
return;
152+
case Profiler:
153+
const parentStateNode = parentFiber.stateNode;
154+
parentStateNode.effectDuration += elapsedTime;
155+
return;
150156
}
151157
parentFiber = parentFiber.return;
152158
}
@@ -163,18 +169,26 @@ function recordPassiveEffectDuration(fiber: Fiber): void {
163169

164170
passiveEffectStartTime = -1;
165171

166-
// Store duration on the next nearest Profiler ancestor.
172+
// Store duration on the next nearest Profiler ancestor
173+
// Or the root (for the DevTools Profiler to read)
167174
let parentFiber = fiber.return;
168175
while (parentFiber !== null) {
169-
if (parentFiber.tag === Profiler) {
170-
const parentStateNode = parentFiber.stateNode;
171-
if (parentStateNode !== null) {
172-
// Detached fibers have their state node cleared out.
173-
// In this case, the return pointer is also cleared out,
174-
// so we won't be able to report the time spent in this Profiler's subtree.
175-
parentStateNode.passiveEffectDuration += elapsedTime;
176-
}
177-
break;
176+
switch (parentFiber.tag) {
177+
case HostRoot:
178+
const root = parentFiber.stateNode;
179+
if (root !== null) {
180+
root.passiveEffectDuration += elapsedTime;
181+
}
182+
return;
183+
case Profiler:
184+
const parentStateNode = parentFiber.stateNode;
185+
if (parentStateNode !== null) {
186+
// Detached fibers have their state node cleared out.
187+
// In this case, the return pointer is also cleared out,
188+
// so we won't be able to report the time spent in this Profiler's subtree.
189+
parentStateNode.passiveEffectDuration += elapsedTime;
190+
}
191+
return;
178192
}
179193
parentFiber = parentFiber.return;
180194
}

packages/react-reconciler/src/ReactProfilerTimer.old.js

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
enableProfilerNestedUpdatePhase,
1515
enableProfilerTimer,
1616
} from 'shared/ReactFeatureFlags';
17-
import {Profiler} from './ReactWorkTags';
17+
import {HostRoot, Profiler} from './ReactWorkTags';
1818

1919
// Intentionally not named imports because Rollup would use dynamic dispatch for
2020
// CommonJS interop named imports.
@@ -140,13 +140,19 @@ function recordLayoutEffectDuration(fiber: Fiber): void {
140140

141141
layoutEffectStartTime = -1;
142142

143-
// Store duration on the next nearest Profiler ancestor.
143+
// Store duration on the next nearest Profiler ancestor
144+
// Or the root (for the DevTools Profiler to read)
144145
let parentFiber = fiber.return;
145146
while (parentFiber !== null) {
146-
if (parentFiber.tag === Profiler) {
147-
const parentStateNode = parentFiber.stateNode;
148-
parentStateNode.effectDuration += elapsedTime;
149-
break;
147+
switch (parentFiber.tag) {
148+
case HostRoot:
149+
const root = parentFiber.stateNode;
150+
root.effectDuration += elapsedTime;
151+
return;
152+
case Profiler:
153+
const parentStateNode = parentFiber.stateNode;
154+
parentStateNode.effectDuration += elapsedTime;
155+
return;
150156
}
151157
parentFiber = parentFiber.return;
152158
}
@@ -163,18 +169,26 @@ function recordPassiveEffectDuration(fiber: Fiber): void {
163169

164170
passiveEffectStartTime = -1;
165171

166-
// Store duration on the next nearest Profiler ancestor.
172+
// Store duration on the next nearest Profiler ancestor
173+
// Or the root (for the DevTools Profiler to read)
167174
let parentFiber = fiber.return;
168175
while (parentFiber !== null) {
169-
if (parentFiber.tag === Profiler) {
170-
const parentStateNode = parentFiber.stateNode;
171-
if (parentStateNode !== null) {
172-
// Detached fibers have their state node cleared out.
173-
// In this case, the return pointer is also cleared out,
174-
// so we won't be able to report the time spent in this Profiler's subtree.
175-
parentStateNode.passiveEffectDuration += elapsedTime;
176-
}
177-
break;
176+
switch (parentFiber.tag) {
177+
case HostRoot:
178+
const root = parentFiber.stateNode;
179+
if (root !== null) {
180+
root.passiveEffectDuration += elapsedTime;
181+
}
182+
return;
183+
case Profiler:
184+
const parentStateNode = parentFiber.stateNode;
185+
if (parentStateNode !== null) {
186+
// Detached fibers have their state node cleared out.
187+
// In this case, the return pointer is also cleared out,
188+
// so we won't be able to report the time spent in this Profiler's subtree.
189+
parentStateNode.passiveEffectDuration += elapsedTime;
190+
}
191+
return;
178192
}
179193
parentFiber = parentFiber.return;
180194
}

0 commit comments

Comments
 (0)