@samitouri / QOS-React-2 / commits / 393c452e39

Add "nested-update" phase to Profiler API (#20163)

Background: State updates that are scheduled in a layout effect (useLayoutEffect or componentDidMount / componentDidUpdate) get processed synchronously by React before it yields to the browser to paint. This is done so that components can adjust their layout (e.g. position and size a tooltip) without any visible shifting being seen by users. This type of update is often called a "nested update" or a "cascading update". Because they delay paint, nested updates are considered expensive and should be avoided when possible. For example, effects that do not impact layout (e.g. adding event handlers, logging impressions) can be safely deferred to the passive effect phase by using useEffect instead. This PR updates the Profiler API to explicitly flag nested updates so they can be monitored for and avoided when possible. Implementation: I considered a few approaches for this. Add a new callback (e.g. onNestedUpdateScheduled) to the Profiler that gets called when a nested updates gets scheduled. Add an additional boolean parameter to the end of existing callbacks (e.g. wasNestedUpdate). Update the phase param to add an additional variant: "mount", "update", or "nested-update" (new). I think the third option makes for the best API so that's what I've implemented in this PR. Because the Profiler API is stable, this change will need to remain behind a feature flag until v18. I've turned the feature flag on for Facebook builds though after confirming that Web Speed does not currently make use of the phase parameter. Quirks: One quirk about the implementation I've chosen is that errors thrown during the layout phase are also reported as nested updates. I believe this is appropriate since these errors get processed synchronously and block paint. Errors thrown during render or from within passive effects are not affected by this change.

Brian Vaughn committed Nov 10, 2020 at 09:40 UTC 393c452e39a72932af734c7c25998b48a20698f7
16 files changed +173 -30
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+22 -11
@@ -31,6 +31,7 @@ import {
31 enableSchedulerTracing,
32 enableProfilerTimer,
33 enableProfilerCommitHooks,
34 + enableProfilerNestedUpdatePhase,
35 enableSuspenseServerRenderer,
36 enableFundamentalAPI,
37 enableSuspenseCallback,
@@ -94,6 +95,7 @@ import {
95 import {onCommitUnmount} from './ReactFiberDevToolsHook.new';
96 import {resolveDefaultProps} from './ReactFiberLazyComponent.new';
97 import {
98 + isCurrentUpdateNested,
99 getCommitTime,
100 recordLayoutEffectDuration,
101 startLayoutEffectTimer,
@@ -357,22 +359,24 @@ function commitProfilerPassiveEffect(
359 // It does not get reset until the start of the next commit phase.
360 const commitTime = getCommitTime();
361
362 + let phase = finishedWork.alternate === null ? 'mount' : 'update';
363 + if (enableProfilerNestedUpdatePhase) {
364 + if (isCurrentUpdateNested()) {
365 + phase = 'nested-update';
366 + }
367 + }
368 +
369 if (typeof onPostCommit === 'function') {
370 if (enableSchedulerTracing) {
371 onPostCommit(
372 id,
364 - finishedWork.alternate === null ? 'mount' : 'update',
373 + phase,
374 passiveEffectDuration,
375 commitTime,
376 finishedRoot.memoizedInteractions,
377 );
378 } else {
370 - onPostCommit(
371 - id,
372 - finishedWork.alternate === null ? 'mount' : 'update',
373 - passiveEffectDuration,
374 - commitTime,
375 - );
379 + onPostCommit(id, phase, passiveEffectDuration, commitTime);
380 }
381 }
382 break;
@@ -1333,11 +1337,18 @@ function commitLayoutEffectsForProfiler(
1337 const OnRenderFlag = Update;
1338 const OnCommitFlag = Callback;
1339
1340 + let phase = current === null ? 'mount' : 'update';
1341 + if (enableProfilerNestedUpdatePhase) {
1342 + if (isCurrentUpdateNested()) {
1343 + phase = 'nested-update';
1344 + }
1345 + }
1346 +
1347 if ((flags & OnRenderFlag) !== NoFlags && typeof onRender === 'function') {
1348 if (enableSchedulerTracing) {
1349 onRender(
1350 finishedWork.memoizedProps.id,
1340 - current === null ? 'mount' : 'update',
1351 + phase,
1352 finishedWork.actualDuration,
1353 finishedWork.treeBaseDuration,
1354 finishedWork.actualStartTime,
@@ -1347,7 +1358,7 @@ function commitLayoutEffectsForProfiler(
1358 } else {
1359 onRender(
1360 finishedWork.memoizedProps.id,
1350 - current === null ? 'mount' : 'update',
1361 + phase,
1362 finishedWork.actualDuration,
1363 finishedWork.treeBaseDuration,
1364 finishedWork.actualStartTime,
@@ -1364,7 +1375,7 @@ function commitLayoutEffectsForProfiler(
1375 if (enableSchedulerTracing) {
1376 onCommit(
1377 finishedWork.memoizedProps.id,
1367 - current === null ? 'mount' : 'update',
1378 + phase,
1379 effectDuration,
1380 commitTime,
1381 finishedRoot.memoizedInteractions,
@@ -1372,7 +1383,7 @@ function commitLayoutEffectsForProfiler(
1383 } else {
1384 onCommit(
1385 finishedWork.memoizedProps.id,
1375 - current === null ? 'mount' : 'update',
1386 + phase,
1387 effectDuration,
1388 commitTime,
1389 );
packages/react-reconciler/src/ReactFiberCommitWork.old.js
+22 -11
@@ -30,6 +30,7 @@ import {
30 enableSchedulerTracing,
31 enableProfilerTimer,
32 enableProfilerCommitHooks,
33 + enableProfilerNestedUpdatePhase,
34 enableSuspenseServerRenderer,
35 enableFundamentalAPI,
36 enableSuspenseCallback,
@@ -73,6 +74,7 @@ import invariant from 'shared/invariant';
74 import {onCommitUnmount} from './ReactFiberDevToolsHook.old';
75 import {resolveDefaultProps} from './ReactFiberLazyComponent.old';
76 import {
77 + isCurrentUpdateNested,
78 getCommitTime,
79 recordLayoutEffectDuration,
80 startLayoutEffectTimer,
@@ -434,22 +436,24 @@ export function commitPassiveEffectDurations(
436 // It does not get reset until the start of the next commit phase.
437 const commitTime = getCommitTime();
438
439 + let phase = finishedWork.alternate === null ? 'mount' : 'update';
440 + if (enableProfilerNestedUpdatePhase) {
441 + if (isCurrentUpdateNested()) {
442 + phase = 'nested-update';
443 + }
444 + }
445 +
446 if (typeof onPostCommit === 'function') {
447 if (enableSchedulerTracing) {
448 onPostCommit(
449 id,
441 - finishedWork.alternate === null ? 'mount' : 'update',
450 + phase,
451 passiveEffectDuration,
452 commitTime,
453 finishedRoot.memoizedInteractions,
454 );
455 } else {
447 - onPostCommit(
448 - id,
449 - finishedWork.alternate === null ? 'mount' : 'update',
450 - passiveEffectDuration,
451 - commitTime,
452 - );
456 + onPostCommit(id, phase, passiveEffectDuration, commitTime);
457 }
458 }
459
@@ -706,11 +710,18 @@ function commitLifeCycles(
710
711 const commitTime = getCommitTime();
712
713 + let phase = current === null ? 'mount' : 'update';
714 + if (enableProfilerNestedUpdatePhase) {
715 + if (isCurrentUpdateNested()) {
716 + phase = 'nested-update';
717 + }
718 + }
719 +
720 if (typeof onRender === 'function') {
721 if (enableSchedulerTracing) {
722 onRender(
723 finishedWork.memoizedProps.id,
713 - current === null ? 'mount' : 'update',
724 + phase,
725 finishedWork.actualDuration,
726 finishedWork.treeBaseDuration,
727 finishedWork.actualStartTime,
@@ -720,7 +731,7 @@ function commitLifeCycles(
731 } else {
732 onRender(
733 finishedWork.memoizedProps.id,
723 - current === null ? 'mount' : 'update',
734 + phase,
735 finishedWork.actualDuration,
736 finishedWork.treeBaseDuration,
737 finishedWork.actualStartTime,
@@ -734,7 +745,7 @@ function commitLifeCycles(
745 if (enableSchedulerTracing) {
746 onCommit(
747 finishedWork.memoizedProps.id,
737 - current === null ? 'mount' : 'update',
748 + phase,
749 effectDuration,
750 commitTime,
751 finishedRoot.memoizedInteractions,
@@ -742,7 +753,7 @@ function commitLifeCycles(
753 } else {
754 onCommit(
755 finishedWork.memoizedProps.id,
745 - current === null ? 'mount' : 'update',
756 + phase,
757 effectDuration,
758 commitTime,
759 );
packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+11
@@ -21,6 +21,7 @@ import {
21 enableSuspenseServerRenderer,
22 replayFailedUnitOfWorkWithInvokeGuardedCallback,
23 enableProfilerTimer,
24 + enableProfilerNestedUpdatePhase,
25 enableSchedulerTracing,
26 warnAboutUnmockedScheduler,
27 deferRenderPhaseUpdateToNextBatch,
@@ -194,9 +195,11 @@ import {
195 } from './ReactFiberStack.new';
196
197 import {
198 + markNestedUpdateScheduled,
199 recordCommitTime,
200 startProfilerTimer,
201 stopProfilerTimerIfRunningAndRecordDelta,
202 + syncNestedUpdateFlag,
203 } from './ReactProfilerTimer.new';
204
205 // DEV stuff
@@ -938,6 +941,10 @@ function markRootSuspended(root, suspendedLanes) {
941 // This is the entry point for synchronous tasks that don't go
942 // through Scheduler
943 function performSyncWorkOnRoot(root) {
944 + if (enableProfilerTimer && enableProfilerNestedUpdatePhase) {
945 + syncNestedUpdateFlag();
946 + }
947 +
948 invariant(
949 (executionContext & (RenderContext | CommitContext)) === NoContext,
950 'Should not already be working.',
@@ -1995,6 +2002,10 @@ function commitRootImpl(root, renderPriorityLevel) {
2002 }
2003
2004 if (remainingLanes === SyncLane) {
2005 + if (enableProfilerTimer && enableProfilerNestedUpdatePhase) {
2006 + markNestedUpdateScheduled();
2007 + }
2008 +
2009 // Count the number of times the root synchronously re-renders without
2010 // finishing. If there are too many, it indicates an infinite update loop.
2011 if (root === rootWithNestedUpdates) {
packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+11
@@ -22,6 +22,7 @@ import {
22 replayFailedUnitOfWorkWithInvokeGuardedCallback,
23 enableProfilerTimer,
24 enableProfilerCommitHooks,
25 + enableProfilerNestedUpdatePhase,
26 enableSchedulerTracing,
27 warnAboutUnmockedScheduler,
28 deferRenderPhaseUpdateToNextBatch,
@@ -207,11 +208,13 @@ import {
208 } from './ReactFiberStack.old';
209
210 import {
211 + markNestedUpdateScheduled,
212 recordCommitTime,
213 recordPassiveEffectDuration,
214 startPassiveEffectTimer,
215 startProfilerTimer,
216 stopProfilerTimerIfRunningAndRecordDelta,
217 + syncNestedUpdateFlag,
218 } from './ReactProfilerTimer.old';
219
220 // DEV stuff
@@ -962,6 +965,10 @@ function markRootSuspended(root, suspendedLanes) {
965 // This is the entry point for synchronous tasks that don't go
966 // through Scheduler
967 function performSyncWorkOnRoot(root) {
968 + if (enableProfilerTimer && enableProfilerNestedUpdatePhase) {
969 + syncNestedUpdateFlag();
970 + }
971 +
972 invariant(
973 (executionContext & (RenderContext | CommitContext)) === NoContext,
974 'Should not already be working.',
@@ -2189,6 +2196,10 @@ function commitRootImpl(root, renderPriorityLevel) {
2196 }
2197
2198 if (remainingLanes === SyncLane) {
2199 + if (enableProfilerTimer && enableProfilerNestedUpdatePhase) {
2200 + markNestedUpdateScheduled();
2201 + }
2202 +
2203 // Count the number of times the root synchronously re-renders without
2204 // finishing. If there are too many, it indicates an infinite update loop.
2205 if (root === rootWithNestedUpdates) {
packages/react-reconciler/src/ReactProfilerTimer.new.js
+44 -1
@@ -10,8 +10,9 @@
10 import type {Fiber} from './ReactInternalTypes';
11
12 import {
13 - enableProfilerTimer,
13 enableProfilerCommitHooks,
14 + enableProfilerNestedUpdatePhase,
15 + enableProfilerTimer,
16 } from 'shared/ReactFeatureFlags';
17 import {Profiler} from './ReactWorkTags';
18
@@ -23,10 +24,13 @@ const {unstable_now: now} = Scheduler;
24
25 export type ProfilerTimer = {
26 getCommitTime(): number,
27 + isCurrentUpdateNested(): boolean,
28 + markNestedUpdateScheduled(): void,
29 recordCommitTime(): void,
30 startProfilerTimer(fiber: Fiber): void,
31 stopProfilerTimerIfRunning(fiber: Fiber): void,
32 stopProfilerTimerIfRunningAndRecordDelta(fiber: Fiber): void,
33 + syncNestedUpdateFlag(): void,
34 ...
35 };
36
@@ -35,6 +39,42 @@ let layoutEffectStartTime: number = -1;
39 let profilerStartTime: number = -1;
40 let passiveEffectStartTime: number = -1;
41
42 +/**
43 + * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect).
44 + *
45 + * The overall sequence is:
46 + * 1. render
47 + * 2. commit (and call `onRender`, `onCommit`)
48 + * 3. check for nested updates
49 + * 4. flush passive effects (and call `onPostCommit`)
50 + *
51 + * Nested updates are identified in step 3 above,
52 + * but step 4 still applies to the work that was just committed.
53 + * We use two flags to track nested updates then:
54 + * one tracks whether the upcoming update is a nested update,
55 + * and the other tracks whether the current update was a nested update.
56 + * The first value gets synced to the second at the start of the render phase.
57 + */
58 +let currentUpdateIsNested: boolean = false;
59 +let nestedUpdateScheduled: boolean = false;
60 +
61 +function isCurrentUpdateNested(): boolean {
62 + return currentUpdateIsNested;
63 +}
64 +
65 +function markNestedUpdateScheduled(): void {
66 + if (enableProfilerNestedUpdatePhase) {
67 + nestedUpdateScheduled = true;
68 + }
69 +}
70 +
71 +function syncNestedUpdateFlag(): void {
72 + if (enableProfilerNestedUpdatePhase) {
73 + currentUpdateIsNested = nestedUpdateScheduled;
74 + nestedUpdateScheduled = false;
75 + }
76 +}
77 +
78 function getCommitTime(): number {
79 return commitTime;
80 }
@@ -161,6 +201,8 @@ function transferActualDuration(fiber: Fiber): void {
201
202 export {
203 getCommitTime,
204 + isCurrentUpdateNested,
205 + markNestedUpdateScheduled,
206 recordCommitTime,
207 recordLayoutEffectDuration,
208 recordPassiveEffectDuration,
@@ -169,5 +211,6 @@ export {
211 startProfilerTimer,
212 stopProfilerTimerIfRunning,
213 stopProfilerTimerIfRunningAndRecordDelta,
214 + syncNestedUpdateFlag,
215 transferActualDuration,
216 };
packages/react-reconciler/src/ReactProfilerTimer.old.js
+44 -1
@@ -10,8 +10,9 @@
10 import type {Fiber} from './ReactInternalTypes';
11
12 import {
13 - enableProfilerTimer,
13 enableProfilerCommitHooks,
14 + enableProfilerNestedUpdatePhase,
15 + enableProfilerTimer,
16 } from 'shared/ReactFeatureFlags';
17 import {Profiler} from './ReactWorkTags';
18
@@ -23,10 +24,13 @@ const {unstable_now: now} = Scheduler;
24
25 export type ProfilerTimer = {
26 getCommitTime(): number,
27 + isCurrentUpdateNested(): boolean,
28 + markNestedUpdateScheduled(): void,
29 recordCommitTime(): void,
30 startProfilerTimer(fiber: Fiber): void,
31 stopProfilerTimerIfRunning(fiber: Fiber): void,
32 stopProfilerTimerIfRunningAndRecordDelta(fiber: Fiber): void,
33 + syncNestedUpdateFlag(): void,
34 ...
35 };
36
@@ -35,6 +39,42 @@ let layoutEffectStartTime: number = -1;
39 let profilerStartTime: number = -1;
40 let passiveEffectStartTime: number = -1;
41
42 +/**
43 + * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect).
44 + *
45 + * The overall sequence is:
46 + * 1. render
47 + * 2. commit (and call `onRender`, `onCommit`)
48 + * 3. check for nested updates
49 + * 4. flush passive effects (and call `onPostCommit`)
50 + *
51 + * Nested updates are identified in step 3 above,
52 + * but step 4 still applies to the work that was just committed.
53 + * We use two flags to track nested updates then:
54 + * one tracks whether the upcoming update is a nested update,
55 + * and the other tracks whether the current update was a nested update.
56 + * The first value gets synced to the second at the start of the render phase.
57 + */
58 +let currentUpdateIsNested: boolean = false;
59 +let nestedUpdateScheduled: boolean = false;
60 +
61 +function isCurrentUpdateNested(): boolean {
62 + return currentUpdateIsNested;
63 +}
64 +
65 +function markNestedUpdateScheduled(): void {
66 + if (enableProfilerNestedUpdatePhase) {
67 + nestedUpdateScheduled = true;
68 + }
69 +}
70 +
71 +function syncNestedUpdateFlag(): void {
72 + if (enableProfilerNestedUpdatePhase) {
73 + currentUpdateIsNested = nestedUpdateScheduled;
74 + nestedUpdateScheduled = false;
75 + }
76 +}
77 +
78 function getCommitTime(): number {
79 return commitTime;
80 }
@@ -161,6 +201,8 @@ function transferActualDuration(fiber: Fiber): void {
201
202 export {
203 getCommitTime,
204 + isCurrentUpdateNested,
205 + markNestedUpdateScheduled,
206 recordCommitTime,
207 recordLayoutEffectDuration,
208 recordPassiveEffectDuration,
@@ -169,5 +211,6 @@ export {
211 startProfilerTimer,
212 stopProfilerTimerIfRunning,
213 stopProfilerTimerIfRunningAndRecordDelta,
214 + syncNestedUpdateFlag,
215 transferActualDuration,
216 };
packages/react/src/__tests__/ReactProfiler-test.internal.js
+8 -6
@@ -28,6 +28,7 @@ let resourcePromise;
28 function loadModules({
29 enableProfilerTimer = true,
30 enableProfilerCommitHooks = true,
31 + enableProfilerNestedUpdatePhase = true,
32 enableSchedulerTracing = true,
33 replayFailedUnitOfWorkWithInvokeGuardedCallback = false,
34 useNoopRenderer = false,
@@ -36,6 +37,7 @@ function loadModules({
37
38 ReactFeatureFlags.enableProfilerTimer = enableProfilerTimer;
39 ReactFeatureFlags.enableProfilerCommitHooks = enableProfilerCommitHooks;
40 + ReactFeatureFlags.enableProfilerNestedUpdatePhase = enableProfilerNestedUpdatePhase;
41 ReactFeatureFlags.enableSchedulerTracing = enableSchedulerTracing;
42 ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = replayFailedUnitOfWorkWithInvokeGuardedCallback;
43
@@ -1098,7 +1100,7 @@ describe('Profiler', () => {
1100 );
1101
1102 // The update includes the ErrorBoundary and its fallback child
1101 - expect(updateCall[1]).toBe('update');
1103 + expect(updateCall[1]).toBe('nested-update');
1104 // actual time includes: 2 (ErrorBoundary) + 20 (AdvanceTime)
1105 expect(updateCall[2]).toBe(22);
1106 // base time includes: 2 (ErrorBoundary) + 20 (AdvanceTime)
@@ -1456,7 +1458,7 @@ describe('Profiler', () => {
1458
1459 expect(call).toHaveLength(enableSchedulerTracing ? 5 : 4);
1460 expect(call[0]).toBe('mount-test');
1459 - expect(call[1]).toBe('update');
1461 + expect(call[1]).toBe('nested-update');
1462 expect(call[2]).toBe(130); // durations
1463 expect(call[3]).toBe(1200001011); // commit start time (before mutations or effects)
1464 expect(call[4]).toEqual(enableSchedulerTracing ? new Set() : undefined); // interaction events
@@ -1485,7 +1487,7 @@ describe('Profiler', () => {
1487
1488 expect(call).toHaveLength(enableSchedulerTracing ? 5 : 4);
1489 expect(call[0]).toBe('update-test');
1488 - expect(call[1]).toBe('update');
1490 + expect(call[1]).toBe('nested-update');
1491 expect(call[2]).toBe(10000); // durations
1492 expect(call[3]).toBe(3300011272); // commit start time (before mutations or effects)
1493 expect(call[4]).toEqual(enableSchedulerTracing ? new Set() : undefined); // interaction events
@@ -1716,7 +1718,7 @@ describe('Profiler', () => {
1718 // Cleanup render from error boundary
1719 expect(call).toHaveLength(enableSchedulerTracing ? 5 : 4);
1720 expect(call[0]).toBe('root');
1719 - expect(call[1]).toBe('update');
1721 + expect(call[1]).toBe('nested-update');
1722 expect(call[2]).toBe(100000000); // durations
1723 expect(call[3]).toBe(10110111); // commit start time (before mutations or effects)
1724 expect(call[4]).toEqual(enableSchedulerTracing ? new Set() : undefined); // interaction events
@@ -1847,7 +1849,7 @@ describe('Profiler', () => {
1849 // Cleanup render from error boundary
1850 expect(call).toHaveLength(enableSchedulerTracing ? 5 : 4);
1851 expect(call[0]).toBe('root');
1850 - expect(call[1]).toBe('update');
1852 + expect(call[1]).toBe('nested-update');
1853 expect(call[2]).toBe(100001000); // durations
1854 expect(call[3]).toBe(11221221); // commit start time (before mutations or effects)
1855 expect(call[4]).toEqual(enableSchedulerTracing ? new Set() : undefined); // interaction events
@@ -1905,7 +1907,7 @@ describe('Profiler', () => {
1907
1908 expect(call).toHaveLength(enableSchedulerTracing ? 5 : 4);
1909 expect(call[0]).toBe('root');
1908 - expect(call[1]).toBe('update');
1910 + expect(call[1]).toBe('nested-update');
1911 expect(call[4]).toMatchInteractions([interaction]);
1912 });
1913 }
packages/shared/ReactFeatureFlags.js
+3
@@ -36,6 +36,9 @@ export const enableProfilerTimer = __PROFILE__;
36 // Record durations for commit and passive effects phases.
37 export const enableProfilerCommitHooks = false;
38
39 +// Phase param passed to onRender callback differentiates between an "update" and a "cascading-update".
40 +export const enableProfilerNestedUpdatePhase = false;
41 +
42 // Trace which interactions trigger each commit.
43 export const enableSchedulerTracing = __PROFILE__;
44
packages/shared/forks/ReactFeatureFlags.native-fb.js
+1
@@ -15,6 +15,7 @@ export const enableDebugTracing = false;
15 export const enableSchedulingProfiler = false;
16 export const enableProfilerTimer = __PROFILE__;
17 export const enableProfilerCommitHooks = false;
18 +export const enableProfilerNestedUpdatePhase = false;
19 export const enableSchedulerTracing = __PROFILE__;
20 export const enableSuspenseServerRenderer = false;
21 export const enableSelectiveHydration = false;
packages/shared/forks/ReactFeatureFlags.native-oss.js
+1
@@ -17,6 +17,7 @@ export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
17 export const warnAboutDeprecatedLifecycles = true;
18 export const enableProfilerTimer = __PROFILE__;
19 export const enableProfilerCommitHooks = false;
20 +export const enableProfilerNestedUpdatePhase = false;
21 export const enableSchedulerTracing = __PROFILE__;
22 export const enableSuspenseServerRenderer = false;
23 export const enableSelectiveHydration = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
+1
@@ -17,6 +17,7 @@ export const warnAboutDeprecatedLifecycles = true;
17 export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
18 export const enableProfilerTimer = __PROFILE__;
19 export const enableProfilerCommitHooks = false;
20 +export const enableProfilerNestedUpdatePhase = false;
21 export const enableSchedulerTracing = __PROFILE__;
22 export const enableSuspenseServerRenderer = false;
23 export const enableSelectiveHydration = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
+1
@@ -17,6 +17,7 @@ export const warnAboutDeprecatedLifecycles = true;
17 export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
18 export const enableProfilerTimer = __PROFILE__;
19 export const enableProfilerCommitHooks = false;
20 +export const enableProfilerNestedUpdatePhase = false;
21 export const enableSchedulerTracing = __PROFILE__;
22 export const enableSuspenseServerRenderer = false;
23 export const enableSelectiveHydration = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+1
@@ -17,6 +17,7 @@ export const warnAboutDeprecatedLifecycles = true;
17 export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
18 export const enableProfilerTimer = __PROFILE__;
19 export const enableProfilerCommitHooks = false;
20 +export const enableProfilerNestedUpdatePhase = false;
21 export const enableSchedulerTracing = __PROFILE__;
22 export const enableSuspenseServerRenderer = false;
23 export const enableSelectiveHydration = false;
packages/shared/forks/ReactFeatureFlags.testing.js
+1
@@ -17,6 +17,7 @@ export const warnAboutDeprecatedLifecycles = true;
17 export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
18 export const enableProfilerTimer = __PROFILE__;
19 export const enableProfilerCommitHooks = false;
20 +export const enableProfilerNestedUpdatePhase = false;
21 export const enableSchedulerTracing = __PROFILE__;
22 export const enableSuspenseServerRenderer = false;
23 export const enableSelectiveHydration = false;
packages/shared/forks/ReactFeatureFlags.testing.www.js
+1
@@ -17,6 +17,7 @@ export const warnAboutDeprecatedLifecycles = true;
17 export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
18 export const enableProfilerTimer = false;
19 export const enableProfilerCommitHooks = false;
20 +export const enableProfilerNestedUpdatePhase = false;
21 export const enableSchedulerTracing = false;
22 export const enableSuspenseServerRenderer = true;
23 export const enableSelectiveHydration = true;
packages/shared/forks/ReactFeatureFlags.www.js
+1
@@ -35,6 +35,7 @@ export const {
35
36 export const enableProfilerTimer = __PROFILE__;
37 export const enableProfilerCommitHooks = __PROFILE__;
38 +export const enableProfilerNestedUpdatePhase = __PROFILE__;
39
40 // Logs additional User Timing API marks for use with an experimental profiling tool.
41 export const enableSchedulingProfiler = __PROFILE__;