Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 470e4ef

Browse files
author
Brian Vaughn
committedFeb 12, 2020
Implemented Profiler onCommit() and onPostCommit() hooks
1 parent f727803 commit 470e4ef

File tree

6 files changed

+2721
-1059
lines changed

6 files changed

+2721
-1059
lines changed
 

‎packages/react-reconciler/src/ReactFiber.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -815,13 +815,8 @@ function createFiberFromProfiler(
815815
key: null | string,
816816
): Fiber {
817817
if (__DEV__) {
818-
if (
819-
typeof pendingProps.id !== 'string' ||
820-
typeof pendingProps.onRender !== 'function'
821-
) {
822-
console.error(
823-
'Profiler must specify an "id" string and "onRender" function as props',
824-
);
818+
if (typeof pendingProps.id !== 'string') {
819+
console.error('Profiler must specify an "id" as a prop');
825820
}
826821
}
827822

@@ -831,6 +826,13 @@ function createFiberFromProfiler(
831826
fiber.type = REACT_PROFILER_TYPE;
832827
fiber.expirationTime = expirationTime;
833828

829+
if (enableProfilerTimer) {
830+
fiber.stateNode = {
831+
effectDuration: 0,
832+
passiveEffectDuration: 0,
833+
};
834+
}
835+
834836
return fiber;
835837
}
836838

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,12 @@ function updateProfiler(
577577
) {
578578
if (enableProfilerTimer) {
579579
workInProgress.effectTag |= Update;
580+
581+
// Reset effect durations for the next eventual effect phase.
582+
// These are reset during render to allow the DevTools commit hook a chance to read them,
583+
const stateNode = workInProgress.stateNode;
584+
stateNode.effectDuration = 0;
585+
stateNode.passiveEffectDuration = 0;
580586
}
581587
const nextProps = workInProgress.pendingProps;
582588
const nextChildren = nextProps.children;
@@ -2974,6 +2980,12 @@ function beginWork(
29742980
if (hasChildWork) {
29752981
workInProgress.effectTag |= Update;
29762982
}
2983+
2984+
// Reset effect durations for the next eventual effect phase.
2985+
// These are reset during render to allow the DevTools commit hook a chance to read them,
2986+
const stateNode = workInProgress.stateNode;
2987+
stateNode.effectDuration = 0;
2988+
stateNode.passiveEffectDuration = 0;
29772989
}
29782990
break;
29792991
case SuspenseComponent: {

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

Lines changed: 217 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,14 @@ import {startPhaseTimer, stopPhaseTimer} from './ReactDebugFiberPerf';
7575
import {getStackByFiberInDevAndProd} from './ReactCurrentFiber';
7676
import {logCapturedError} from './ReactFiberErrorLogger';
7777
import {resolveDefaultProps} from './ReactFiberLazyComponent';
78-
import {getCommitTime} from './ReactProfilerTimer';
78+
import {
79+
getCommitTime,
80+
recordLayoutEffectDuration,
81+
recordPassiveEffectDuration,
82+
startLayoutEffectTimer,
83+
startPassiveEffectTimer,
84+
} from './ReactProfilerTimer';
85+
import {ProfileMode} from './ReactTypeOfMode';
7986
import {commitUpdateQueue} from './ReactUpdateQueue';
8087
import {
8188
getPublicInstance,
@@ -112,6 +119,7 @@ import {
112119
markCommitTimeOfFallback,
113120
enqueuePendingPassiveHookEffectMount,
114121
enqueuePendingPassiveHookEffectUnmount,
122+
enqueuePendingPassiveProfilerEffect,
115123
} from './ReactFiberWorkLoop';
116124
import {
117125
NoEffect as NoHookEffect,
@@ -174,7 +182,16 @@ const callComponentWillUnmountWithTimer = function(current, instance) {
174182
startPhaseTimer(current, 'componentWillUnmount');
175183
instance.props = current.memoizedProps;
176184
instance.state = current.memoizedState;
177-
instance.componentWillUnmount();
185+
if (enableProfilerTimer && current.mode & ProfileMode) {
186+
try {
187+
startLayoutEffectTimer();
188+
instance.componentWillUnmount();
189+
} finally {
190+
recordLayoutEffectDuration(current);
191+
}
192+
} else {
193+
instance.componentWillUnmount();
194+
}
178195
stopPhaseTimer();
179196
};
180197

@@ -429,8 +446,27 @@ export function commitPassiveHookEffects(finishedWork: Fiber): void {
429446
// TODO (#17945) We should call all passive destroy functions (for all fibers)
430447
// before calling any create functions. The current approach only serializes
431448
// these for a single fiber.
432-
commitHookEffectListUnmount(HookPassive | HookHasEffect, finishedWork);
433-
commitHookEffectListMount(HookPassive | HookHasEffect, finishedWork);
449+
if (enableProfilerTimer && finishedWork.mode & ProfileMode) {
450+
try {
451+
startPassiveEffectTimer();
452+
commitHookEffectListUnmount(
453+
HookPassive | HookHasEffect,
454+
finishedWork,
455+
);
456+
commitHookEffectListMount(
457+
HookPassive | HookHasEffect,
458+
finishedWork,
459+
);
460+
} finally {
461+
recordPassiveEffectDuration(finishedWork);
462+
}
463+
} else {
464+
commitHookEffectListUnmount(
465+
HookPassive | HookHasEffect,
466+
finishedWork,
467+
);
468+
commitHookEffectListMount(HookPassive | HookHasEffect, finishedWork);
469+
}
434470
break;
435471
}
436472
default:
@@ -439,6 +475,61 @@ export function commitPassiveHookEffects(finishedWork: Fiber): void {
439475
}
440476
}
441477

478+
export function commitPassiveEffectDurations(
479+
finishedRoot: FiberRoot,
480+
finishedWork: Fiber,
481+
): void {
482+
if (enableProfilerTimer) {
483+
// Only Profilers with work in their subtree will have an Update effect scheduled.
484+
if ((finishedWork.effectTag & Update) !== NoEffect) {
485+
switch (finishedWork.tag) {
486+
case Profiler: {
487+
const {passiveEffectDuration} = finishedWork.stateNode;
488+
const {id, onPostCommit} = finishedWork.memoizedProps;
489+
490+
// This value will still reflect the previous commit phase.
491+
// It does not get reset until the start of the next commit phase.
492+
const commitTime = getCommitTime();
493+
494+
if (typeof onPostCommit === 'function') {
495+
if (enableSchedulerTracing) {
496+
onPostCommit(
497+
id,
498+
finishedWork.alternate === null ? 'mount' : 'update',
499+
passiveEffectDuration,
500+
commitTime,
501+
finishedRoot.memoizedInteractions,
502+
);
503+
} else {
504+
onPostCommit(
505+
id,
506+
finishedWork.alternate === null ? 'mount' : 'update',
507+
passiveEffectDuration,
508+
commitTime,
509+
);
510+
}
511+
}
512+
513+
// Bubble times to the next nearest ancestor Profiler.
514+
// After we process that Profiler, we'll bubble further up.
515+
let parentFiber = finishedWork.return;
516+
while (parentFiber !== null) {
517+
if (parentFiber.tag === Profiler) {
518+
const parentStateNode = parentFiber.stateNode;
519+
parentStateNode.passiveEffectDuration += passiveEffectDuration;
520+
break;
521+
}
522+
parentFiber = parentFiber.return;
523+
}
524+
break;
525+
}
526+
default:
527+
break;
528+
}
529+
}
530+
}
531+
}
532+
442533
function commitLifeCycles(
443534
finishedRoot: FiberRoot,
444535
current: Fiber | null,
@@ -454,7 +545,16 @@ function commitLifeCycles(
454545
// This is done to prevent sibling component effects from interfering with each other,
455546
// e.g. a destroy function in one component should never override a ref set
456547
// by a create function in another component during the same commit.
457-
commitHookEffectListMount(HookLayout | HookHasEffect, finishedWork);
548+
if (enableProfilerTimer && finishedWork.mode & ProfileMode) {
549+
try {
550+
startLayoutEffectTimer();
551+
commitHookEffectListMount(HookLayout | HookHasEffect, finishedWork);
552+
} finally {
553+
recordLayoutEffectDuration(finishedWork);
554+
}
555+
} else {
556+
commitHookEffectListMount(HookLayout | HookHasEffect, finishedWork);
557+
}
458558

459559
if (deferPassiveEffectCleanupDuringUnmount) {
460560
schedulePassiveEffects(finishedWork);
@@ -496,7 +596,16 @@ function commitLifeCycles(
496596
}
497597
}
498598
}
499-
instance.componentDidMount();
599+
if (enableProfilerTimer && finishedWork.mode & ProfileMode) {
600+
try {
601+
startLayoutEffectTimer();
602+
instance.componentDidMount();
603+
} finally {
604+
recordLayoutEffectDuration(finishedWork);
605+
}
606+
} else {
607+
instance.componentDidMount();
608+
}
500609
stopPhaseTimer();
501610
} else {
502611
const prevProps =
@@ -535,11 +644,24 @@ function commitLifeCycles(
535644
}
536645
}
537646
}
538-
instance.componentDidUpdate(
539-
prevProps,
540-
prevState,
541-
instance.__reactInternalSnapshotBeforeUpdate,
542-
);
647+
if (enableProfilerTimer && finishedWork.mode & ProfileMode) {
648+
try {
649+
startLayoutEffectTimer();
650+
instance.componentDidUpdate(
651+
prevProps,
652+
prevState,
653+
instance.__reactInternalSnapshotBeforeUpdate,
654+
);
655+
} finally {
656+
recordLayoutEffectDuration(finishedWork);
657+
}
658+
} else {
659+
instance.componentDidUpdate(
660+
prevProps,
661+
prevState,
662+
instance.__reactInternalSnapshotBeforeUpdate,
663+
);
664+
}
543665
stopPhaseTimer();
544666
}
545667
}
@@ -632,7 +754,10 @@ function commitLifeCycles(
632754
}
633755
case Profiler: {
634756
if (enableProfilerTimer) {
635-
const onRender = finishedWork.memoizedProps.onRender;
757+
const {onCommit, onRender} = finishedWork.memoizedProps;
758+
const {effectDuration} = finishedWork.stateNode;
759+
760+
const commitTime = getCommitTime();
636761

637762
if (typeof onRender === 'function') {
638763
if (enableSchedulerTracing) {
@@ -642,7 +767,7 @@ function commitLifeCycles(
642767
finishedWork.actualDuration,
643768
finishedWork.treeBaseDuration,
644769
finishedWork.actualStartTime,
645-
getCommitTime(),
770+
commitTime,
646771
finishedRoot.memoizedInteractions,
647772
);
648773
} else {
@@ -652,10 +777,46 @@ function commitLifeCycles(
652777
finishedWork.actualDuration,
653778
finishedWork.treeBaseDuration,
654779
finishedWork.actualStartTime,
655-
getCommitTime(),
780+
commitTime,
656781
);
657782
}
658783
}
784+
785+
if (typeof onCommit === 'function') {
786+
if (enableSchedulerTracing) {
787+
onCommit(
788+
finishedWork.memoizedProps.id,
789+
current === null ? 'mount' : 'update',
790+
effectDuration,
791+
commitTime,
792+
finishedRoot.memoizedInteractions,
793+
);
794+
} else {
795+
onCommit(
796+
finishedWork.memoizedProps.id,
797+
current === null ? 'mount' : 'update',
798+
effectDuration,
799+
commitTime,
800+
);
801+
}
802+
}
803+
804+
// Schedule a passive effect for this Profiler to call onPostCommit hooks.
805+
// This effect should be scheduled even if there is no onPostCommit callback for this Profiler,
806+
// because the effect is also where times bubble to parent Profilers.
807+
enqueuePendingPassiveProfilerEffect(finishedWork);
808+
809+
// Propagate layout effect durations to the next nearest Profiler ancestor.
810+
// Do not reset these values until the next render so DevTools has a chance to read them first.
811+
let parentFiber = finishedWork.return;
812+
while (parentFiber !== null) {
813+
if (parentFiber.tag === Profiler) {
814+
const parentStateNode = parentFiber.stateNode;
815+
parentStateNode.effectDuration += effectDuration;
816+
break;
817+
}
818+
parentFiber = parentFiber.return;
819+
}
659820
}
660821
return;
661822
}
@@ -803,7 +964,13 @@ function commitUnmount(
803964
if ((tag & HookPassive) !== NoHookEffect) {
804965
enqueuePendingPassiveHookEffectUnmount(current, effect);
805966
} else {
806-
safelyCallDestroy(current, destroy);
967+
if (enableProfilerTimer && current.mode & ProfileMode) {
968+
startLayoutEffectTimer();
969+
safelyCallDestroy(current, destroy);
970+
recordLayoutEffectDuration(current);
971+
} else {
972+
safelyCallDestroy(current, destroy);
973+
}
807974
}
808975
}
809976
effect = effect.next;
@@ -828,9 +995,19 @@ function commitUnmount(
828995
runWithPriority(priorityLevel, () => {
829996
let effect = firstEffect;
830997
do {
831-
const destroy = effect.destroy;
998+
const {destroy, tag} = effect;
832999
if (destroy !== undefined) {
833-
safelyCallDestroy(current, destroy);
1000+
if (enableProfilerTimer && current.mode & ProfileMode) {
1001+
if ((tag & HookPassive) !== NoHookEffect) {
1002+
safelyCallDestroy(current, destroy);
1003+
} else {
1004+
startLayoutEffectTimer();
1005+
safelyCallDestroy(current, destroy);
1006+
recordLayoutEffectDuration(current);
1007+
}
1008+
} else {
1009+
safelyCallDestroy(current, destroy);
1010+
}
8341011
}
8351012
effect = effect.next;
8361013
} while (effect !== firstEffect);
@@ -1372,7 +1549,19 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
13721549
// This prevents sibling component effects from interfering with each other,
13731550
// e.g. a destroy function in one component should never override a ref set
13741551
// by a create function in another component during the same commit.
1375-
commitHookEffectListUnmount(HookLayout | HookHasEffect, finishedWork);
1552+
if (enableProfilerTimer && finishedWork.mode & ProfileMode) {
1553+
try {
1554+
startLayoutEffectTimer();
1555+
commitHookEffectListUnmount(
1556+
HookLayout | HookHasEffect,
1557+
finishedWork,
1558+
);
1559+
} finally {
1560+
recordLayoutEffectDuration(finishedWork);
1561+
}
1562+
} else {
1563+
commitHookEffectListUnmount(HookLayout | HookHasEffect, finishedWork);
1564+
}
13761565
return;
13771566
}
13781567
case Profiler: {
@@ -1415,7 +1604,16 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
14151604
// This prevents sibling component effects from interfering with each other,
14161605
// e.g. a destroy function in one component should never override a ref set
14171606
// by a create function in another component during the same commit.
1418-
commitHookEffectListUnmount(HookLayout | HookHasEffect, finishedWork);
1607+
if (enableProfilerTimer && finishedWork.mode & ProfileMode) {
1608+
try {
1609+
startLayoutEffectTimer();
1610+
commitHookEffectListUnmount(HookLayout | HookHasEffect, finishedWork);
1611+
} finally {
1612+
recordLayoutEffectDuration(finishedWork);
1613+
}
1614+
} else {
1615+
commitHookEffectListUnmount(HookLayout | HookHasEffect, finishedWork);
1616+
}
14191617
return;
14201618
}
14211619
case ClassComponent: {

‎packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ import {
138138
commitDeletion,
139139
commitDetachRef,
140140
commitAttachRef,
141+
commitPassiveEffectDurations,
141142
commitResetTextContent,
142143
} from './ReactFiberCommitWork';
143144
import {enqueueUpdate} from './ReactUpdateQueue';
@@ -147,6 +148,8 @@ import {createCapturedValue} from './ReactCapturedValue';
147148

148149
import {
149150
recordCommitTime,
151+
recordPassiveEffectDuration,
152+
startPassiveEffectTimer,
150153
startProfilerTimer,
151154
stopProfilerTimerIfRunningAndRecordDelta,
152155
} from './ReactProfilerTimer';
@@ -260,6 +263,7 @@ let pendingPassiveEffectsRenderPriority: ReactPriorityLevel = NoPriority;
260263
let pendingPassiveEffectsExpirationTime: ExpirationTime = NoWork;
261264
let pendingPassiveHookEffectsMount: Array<HookEffect | Fiber> = [];
262265
let pendingPassiveHookEffectsUnmount: Array<HookEffect | Fiber> = [];
266+
let pendingPassiveProfilerEffects: Array<Fiber> = [];
263267

264268
let rootsWithPendingDiscreteUpdates: Map<
265269
FiberRoot,
@@ -2170,6 +2174,19 @@ export function flushPassiveEffects() {
21702174
}
21712175
}
21722176

2177+
export function enqueuePendingPassiveProfilerEffect(fiber: Fiber): void {
2178+
if (enableProfilerTimer) {
2179+
pendingPassiveProfilerEffects.push(fiber);
2180+
if (!rootDoesHavePassiveEffects) {
2181+
rootDoesHavePassiveEffects = true;
2182+
scheduleCallback(NormalPriority, () => {
2183+
flushPassiveEffects();
2184+
return null;
2185+
});
2186+
}
2187+
}
2188+
}
2189+
21732190
export function enqueuePendingPassiveHookEffectMount(
21742191
fiber: Fiber,
21752192
effect: HookEffect,
@@ -2211,6 +2228,7 @@ function flushPassiveEffectsImpl() {
22112228
if (rootWithPendingPassiveEffects === null) {
22122229
return false;
22132230
}
2231+
22142232
const root = rootWithPendingPassiveEffects;
22152233
const expirationTime = pendingPassiveEffectsExpirationTime;
22162234
rootWithPendingPassiveEffects = null;
@@ -2243,7 +2261,13 @@ function flushPassiveEffectsImpl() {
22432261
if (typeof destroy === 'function') {
22442262
if (__DEV__) {
22452263
setCurrentDebugFiberInDEV(fiber);
2246-
invokeGuardedCallback(null, destroy, null);
2264+
if (enableProfilerTimer && fiber.mode & ProfileMode) {
2265+
startPassiveEffectTimer();
2266+
invokeGuardedCallback(null, destroy, null);
2267+
recordPassiveEffectDuration(fiber);
2268+
} else {
2269+
invokeGuardedCallback(null, destroy, null);
2270+
}
22472271
if (hasCaughtError()) {
22482272
invariant(fiber !== null, 'Should be working on an effect.');
22492273
const error = clearCaughtError();
@@ -2252,15 +2276,23 @@ function flushPassiveEffectsImpl() {
22522276
resetCurrentDebugFiberInDEV();
22532277
} else {
22542278
try {
2255-
destroy();
2279+
if (enableProfilerTimer && fiber.mode & ProfileMode) {
2280+
try {
2281+
startPassiveEffectTimer();
2282+
destroy();
2283+
} finally {
2284+
recordPassiveEffectDuration(fiber);
2285+
}
2286+
} else {
2287+
destroy();
2288+
}
22562289
} catch (error) {
22572290
invariant(fiber !== null, 'Should be working on an effect.');
22582291
captureCommitPhaseError(fiber, error);
22592292
}
22602293
}
22612294
}
22622295
}
2263-
22642296
// Second pass: Create new passive effects.
22652297
let mountEffects = pendingPassiveHookEffectsMount;
22662298
pendingPassiveHookEffectsMount = [];
@@ -2269,7 +2301,13 @@ function flushPassiveEffectsImpl() {
22692301
const fiber = ((mountEffects[i + 1]: any): Fiber);
22702302
if (__DEV__) {
22712303
setCurrentDebugFiberInDEV(fiber);
2272-
invokeGuardedCallback(null, invokePassiveEffectCreate, null, effect);
2304+
if (enableProfilerTimer && fiber.mode & ProfileMode) {
2305+
startPassiveEffectTimer();
2306+
invokeGuardedCallback(null, invokePassiveEffectCreate, null, effect);
2307+
recordPassiveEffectDuration(fiber);
2308+
} else {
2309+
invokeGuardedCallback(null, invokePassiveEffectCreate, null, effect);
2310+
}
22732311
if (hasCaughtError()) {
22742312
invariant(fiber !== null, 'Should be working on an effect.');
22752313
const error = clearCaughtError();
@@ -2279,7 +2317,16 @@ function flushPassiveEffectsImpl() {
22792317
} else {
22802318
try {
22812319
const create = effect.create;
2282-
effect.destroy = create();
2320+
if (enableProfilerTimer && fiber.mode & ProfileMode) {
2321+
try {
2322+
startPassiveEffectTimer();
2323+
effect.destroy = create();
2324+
} finally {
2325+
recordPassiveEffectDuration(fiber);
2326+
}
2327+
} else {
2328+
effect.destroy = create();
2329+
}
22832330
} catch (error) {
22842331
invariant(fiber !== null, 'Should be working on an effect.');
22852332
captureCommitPhaseError(fiber, error);
@@ -2309,13 +2356,23 @@ function flushPassiveEffectsImpl() {
23092356
captureCommitPhaseError(effect, error);
23102357
}
23112358
}
2359+
23122360
const nextNextEffect = effect.nextEffect;
23132361
// Remove nextEffect pointer to assist GC
23142362
effect.nextEffect = null;
23152363
effect = nextNextEffect;
23162364
}
23172365
}
23182366

2367+
if (enableProfilerTimer) {
2368+
let profilerEffects = pendingPassiveProfilerEffects;
2369+
pendingPassiveProfilerEffects = [];
2370+
for (let i = 0; i < profilerEffects.length; i++) {
2371+
const fiber = ((profilerEffects[i]: any): Fiber);
2372+
commitPassiveEffectDurations(root, fiber);
2373+
}
2374+
}
2375+
23192376
if (enableSchedulerTracing) {
23202377
popInteractions(((prevInteractions: any): Set<Interaction>));
23212378
finishPendingInteractions(root, expirationTime);

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

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import type {Fiber} from './ReactFiber';
1111

1212
import {enableProfilerTimer} from 'shared/ReactFeatureFlags';
13+
import {Profiler} from 'shared/ReactWorkTags';
1314

1415
// Intentionally not named imports because Rollup would use dynamic dispatch for
1516
// CommonJS interop named imports.
@@ -27,7 +28,9 @@ export type ProfilerTimer = {
2728
};
2829

2930
let commitTime: number = 0;
31+
let layoutEffectStartTime: number = -1;
3032
let profilerStartTime: number = -1;
33+
let passiveEffectStartTime: number = -1;
3134

3235
function getCommitTime(): number {
3336
return commitTime;
@@ -77,9 +80,78 @@ function stopProfilerTimerIfRunningAndRecordDelta(
7780
}
7881
}
7982

83+
function recordLayoutEffectDuration(fiber: Fiber): void {
84+
if (!enableProfilerTimer) {
85+
return;
86+
}
87+
88+
if (layoutEffectStartTime >= 0) {
89+
const elapsedTime = now() - layoutEffectStartTime;
90+
91+
layoutEffectStartTime = -1;
92+
93+
// Store duration on the next nearest Profiler ancestor.
94+
let parentFiber = fiber.return;
95+
while (parentFiber !== null) {
96+
if (parentFiber.tag === Profiler) {
97+
const parentStateNode = parentFiber.stateNode;
98+
parentStateNode.effectDuration += elapsedTime;
99+
break;
100+
}
101+
parentFiber = parentFiber.return;
102+
}
103+
}
104+
}
105+
106+
function recordPassiveEffectDuration(fiber: Fiber): void {
107+
if (!enableProfilerTimer) {
108+
return;
109+
}
110+
111+
if (passiveEffectStartTime >= 0) {
112+
const elapsedTime = now() - passiveEffectStartTime;
113+
114+
passiveEffectStartTime = -1;
115+
116+
// Store duration on the next nearest Profiler ancestor.
117+
let parentFiber = fiber.return;
118+
while (parentFiber !== null) {
119+
if (parentFiber.tag === Profiler) {
120+
const parentStateNode = parentFiber.stateNode;
121+
if (parentStateNode !== null) {
122+
// Detached fibers have their state node cleared out.
123+
// In this case, the return pointer is also cleared out,
124+
// so we won't be able to report the time spent in this Profiler's subtree.
125+
parentStateNode.passiveEffectDuration += elapsedTime;
126+
}
127+
break;
128+
}
129+
parentFiber = parentFiber.return;
130+
}
131+
}
132+
}
133+
134+
function startLayoutEffectTimer(): void {
135+
if (!enableProfilerTimer) {
136+
return;
137+
}
138+
layoutEffectStartTime = now();
139+
}
140+
141+
function startPassiveEffectTimer(): void {
142+
if (!enableProfilerTimer) {
143+
return;
144+
}
145+
passiveEffectStartTime = now();
146+
}
147+
80148
export {
81149
getCommitTime,
82150
recordCommitTime,
151+
recordLayoutEffectDuration,
152+
recordPassiveEffectDuration,
153+
startLayoutEffectTimer,
154+
startPassiveEffectTimer,
83155
startProfilerTimer,
84156
stopProfilerTimerIfRunning,
85157
stopProfilerTimerIfRunningAndRecordDelta,

‎packages/react/src/__tests__/ReactProfiler-test.internal.js

Lines changed: 2349 additions & 1028 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.