@samitouri / QOS-React-2 / commits / 466b26c926

Store commit durations on HostRoot for DevTools access (#20983)

Also add missing feature flag wrappers around effect duration attributes.

Brian Vaughn committed Mar 16, 2021 at 13:53 UTC 466b26c926a2de92231f7cc2e75745563a91003d
8 files changed +144 -72
packages/react-reconciler/src/ReactFiberBeginWork.new.js
+15 -10
@@ -75,6 +75,7 @@ import {
75 debugRenderPhaseSideEffectsForStrictMode,
76 disableLegacyContext,
77 disableModulePatternComponents,
78 + enableProfilerCommitHooks,
79 enableProfilerTimer,
80 enableSchedulerTracing,
81 enableSuspenseServerRenderer,
@@ -837,11 +838,13 @@ function updateProfiler(
838 if (enableProfilerTimer) {
839 workInProgress.flags |= Update;
840
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 + }
848 }
849 const nextProps = workInProgress.pendingProps;
850 const nextChildren = nextProps.children;
@@ -3320,11 +3323,13 @@ function beginWork(
3323 workInProgress.flags |= Update;
3324 }
3325
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 + }
3333 }
3334 break;
3335 case SuspenseComponent: {
packages/react-reconciler/src/ReactFiberBeginWork.old.js
+15 -10
@@ -75,6 +75,7 @@ import {
75 debugRenderPhaseSideEffectsForStrictMode,
76 disableLegacyContext,
77 disableModulePatternComponents,
78 + enableProfilerCommitHooks,
79 enableProfilerTimer,
80 enableSchedulerTracing,
81 enableSuspenseServerRenderer,
@@ -837,11 +838,13 @@ function updateProfiler(
838 if (enableProfilerTimer) {
839 workInProgress.flags |= Update;
840
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 + }
848 }
849 const nextProps = workInProgress.pendingProps;
850 const nextChildren = nextProps.children;
@@ -3320,11 +3323,13 @@ function beginWork(
3323 workInProgress.flags |= Update;
3324 }
3325
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 + }
3333 }
3334 break;
3335 case SuspenseComponent: {
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+20 -10
@@ -578,11 +578,16 @@ export function commitPassiveEffectDurations(
578 // Bubble times to the next nearest ancestor Profiler.
579 // After we process that Profiler, we'll bubble further up.
580 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;
591 }
592 parentFiber = parentFiber.return;
593 }
@@ -885,11 +890,16 @@ function commitLayoutEffectOnFiber(
890 // Propagate layout effect durations to the next nearest Profiler ancestor.
891 // Do not reset these values until the next render so DevTools has a chance to read them first.
892 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;
903 }
904 parentFiber = parentFiber.return;
905 }
packages/react-reconciler/src/ReactFiberCommitWork.old.js
+20 -10
@@ -578,11 +578,16 @@ export function commitPassiveEffectDurations(
578 // Bubble times to the next nearest ancestor Profiler.
579 // After we process that Profiler, we'll bubble further up.
580 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;
591 }
592 parentFiber = parentFiber.return;
593 }
@@ -885,11 +890,16 @@ function commitLayoutEffectOnFiber(
890 // Propagate layout effect durations to the next nearest Profiler ancestor.
891 // Do not reset these values until the next render so DevTools has a chance to read them first.
892 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;
903 }
904 parentFiber = parentFiber.return;
905 }
packages/react-reconciler/src/ReactFiberRoot.new.js
+7
@@ -22,6 +22,8 @@ import {
22 enableSchedulerTracing,
23 enableSuspenseCallback,
24 enableCache,
25 + enableProfilerCommitHooks,
26 + enableProfilerTimer,
27 } from 'shared/ReactFeatureFlags';
28 import {unstable_getThreadID} from 'scheduler/tracing';
29 import {initializeUpdateQueue} from './ReactUpdateQueue.new';
@@ -71,6 +73,11 @@ function FiberRootNode(containerInfo, tag, hydrate) {
73 this.hydrationCallbacks = null;
74 }
75
76 + if (enableProfilerTimer && enableProfilerCommitHooks) {
77 + this.effectDuration = 0;
78 + this.passiveEffectDuration = 0;
79 + }
80 +
81 if (__DEV__) {
82 switch (tag) {
83 case ConcurrentRoot:
packages/react-reconciler/src/ReactFiberRoot.old.js
+7
@@ -22,6 +22,8 @@ import {
22 enableSchedulerTracing,
23 enableSuspenseCallback,
24 enableCache,
25 + enableProfilerCommitHooks,
26 + enableProfilerTimer,
27 } from 'shared/ReactFeatureFlags';
28 import {unstable_getThreadID} from 'scheduler/tracing';
29 import {initializeUpdateQueue} from './ReactUpdateQueue.old';
@@ -71,6 +73,11 @@ function FiberRootNode(containerInfo, tag, hydrate) {
73 this.hydrationCallbacks = null;
74 }
75
76 + if (enableProfilerTimer && enableProfilerCommitHooks) {
77 + this.effectDuration = 0;
78 + this.passiveEffectDuration = 0;
79 + }
80 +
81 if (__DEV__) {
82 switch (tag) {
83 case ConcurrentRoot:
packages/react-reconciler/src/ReactProfilerTimer.new.js
+30 -16
@@ -14,7 +14,7 @@ import {
14 enableProfilerNestedUpdatePhase,
15 enableProfilerTimer,
16 } from 'shared/ReactFeatureFlags';
17 -import {Profiler} from './ReactWorkTags';
17 +import {HostRoot, Profiler} from './ReactWorkTags';
18
19 // Intentionally not named imports because Rollup would use dynamic dispatch for
20 // CommonJS interop named imports.
@@ -140,13 +140,19 @@ function recordLayoutEffectDuration(fiber: Fiber): void {
140
141 layoutEffectStartTime = -1;
142
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)
145 let parentFiber = fiber.return;
146 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;
156 }
157 parentFiber = parentFiber.return;
158 }
@@ -163,18 +169,26 @@ function recordPassiveEffectDuration(fiber: Fiber): void {
169
170 passiveEffectStartTime = -1;
171
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)
174 let parentFiber = fiber.return;
175 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;
192 }
193 parentFiber = parentFiber.return;
194 }
packages/react-reconciler/src/ReactProfilerTimer.old.js
+30 -16
@@ -14,7 +14,7 @@ import {
14 enableProfilerNestedUpdatePhase,
15 enableProfilerTimer,
16 } from 'shared/ReactFeatureFlags';
17 -import {Profiler} from './ReactWorkTags';
17 +import {HostRoot, Profiler} from './ReactWorkTags';
18
19 // Intentionally not named imports because Rollup would use dynamic dispatch for
20 // CommonJS interop named imports.
@@ -140,13 +140,19 @@ function recordLayoutEffectDuration(fiber: Fiber): void {
140
141 layoutEffectStartTime = -1;
142
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)
145 let parentFiber = fiber.return;
146 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;
156 }
157 parentFiber = parentFiber.return;
158 }
@@ -163,18 +169,26 @@ function recordPassiveEffectDuration(fiber: Fiber): void {
169
170 passiveEffectStartTime = -1;
171
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)
174 let parentFiber = fiber.return;
175 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;
192 }
193 parentFiber = parentFiber.return;
194 }