From 01c6228c2a2668d0c78d9a74fe06f9772aa51e3b Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Thu, 5 Nov 2020 09:29:49 -0500 Subject: [PATCH] Add "nested-update" phase to Profiler API 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. --- .../src/ReactFiberCommitWork.new.js | 33 +++++++++----- .../src/ReactFiberCommitWork.old.js | 33 +++++++++----- .../src/ReactFiberWorkLoop.new.js | 11 +++++ .../src/ReactFiberWorkLoop.old.js | 11 +++++ .../src/ReactProfilerTimer.new.js | 45 ++++++++++++++++++- .../src/ReactProfilerTimer.old.js | 45 ++++++++++++++++++- .../__tests__/ReactProfiler-test.internal.js | 14 +++--- packages/shared/ReactFeatureFlags.js | 3 ++ .../forks/ReactFeatureFlags.native-fb.js | 1 + .../forks/ReactFeatureFlags.native-oss.js | 1 + .../forks/ReactFeatureFlags.test-renderer.js | 1 + .../ReactFeatureFlags.test-renderer.native.js | 1 + .../ReactFeatureFlags.test-renderer.www.js | 1 + .../shared/forks/ReactFeatureFlags.testing.js | 1 + .../forks/ReactFeatureFlags.testing.www.js | 1 + .../shared/forks/ReactFeatureFlags.www.js | 1 + 16 files changed, 173 insertions(+), 30 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.new.js b/packages/react-reconciler/src/ReactFiberCommitWork.new.js index a627cf4e17d08..df5e8d0dd0d71 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.new.js @@ -31,6 +31,7 @@ import { enableSchedulerTracing, enableProfilerTimer, enableProfilerCommitHooks, + enableProfilerNestedUpdatePhase, enableSuspenseServerRenderer, enableFundamentalAPI, enableSuspenseCallback, @@ -94,6 +95,7 @@ import { import {onCommitUnmount} from './ReactFiberDevToolsHook.new'; import {resolveDefaultProps} from './ReactFiberLazyComponent.new'; import { + isCurrentUpdateNested, getCommitTime, recordLayoutEffectDuration, startLayoutEffectTimer, @@ -369,22 +371,24 @@ function commitProfilerPassiveEffect( // It does not get reset until the start of the next commit phase. const commitTime = getCommitTime(); + let phase = finishedWork.alternate === null ? 'mount' : 'update'; + if (enableProfilerNestedUpdatePhase) { + if (isCurrentUpdateNested()) { + phase = 'nested-update'; + } + } + if (typeof onPostCommit === 'function') { if (enableSchedulerTracing) { onPostCommit( id, - finishedWork.alternate === null ? 'mount' : 'update', + phase, passiveEffectDuration, commitTime, finishedRoot.memoizedInteractions, ); } else { - onPostCommit( - id, - finishedWork.alternate === null ? 'mount' : 'update', - passiveEffectDuration, - commitTime, - ); + onPostCommit(id, phase, passiveEffectDuration, commitTime); } } break; @@ -1362,11 +1366,18 @@ function commitLayoutEffectsForProfiler( const OnRenderFlag = Update; const OnCommitFlag = Callback; + let phase = current === null ? 'mount' : 'update'; + if (enableProfilerNestedUpdatePhase) { + if (isCurrentUpdateNested()) { + phase = 'nested-update'; + } + } + if ((flags & OnRenderFlag) !== NoFlags && typeof onRender === 'function') { if (enableSchedulerTracing) { onRender( finishedWork.memoizedProps.id, - current === null ? 'mount' : 'update', + phase, finishedWork.actualDuration, finishedWork.treeBaseDuration, finishedWork.actualStartTime, @@ -1376,7 +1387,7 @@ function commitLayoutEffectsForProfiler( } else { onRender( finishedWork.memoizedProps.id, - current === null ? 'mount' : 'update', + phase, finishedWork.actualDuration, finishedWork.treeBaseDuration, finishedWork.actualStartTime, @@ -1393,7 +1404,7 @@ function commitLayoutEffectsForProfiler( if (enableSchedulerTracing) { onCommit( finishedWork.memoizedProps.id, - current === null ? 'mount' : 'update', + phase, effectDuration, commitTime, finishedRoot.memoizedInteractions, @@ -1401,7 +1412,7 @@ function commitLayoutEffectsForProfiler( } else { onCommit( finishedWork.memoizedProps.id, - current === null ? 'mount' : 'update', + phase, effectDuration, commitTime, ); diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.old.js b/packages/react-reconciler/src/ReactFiberCommitWork.old.js index 1ec6ed7874812..55db13cf3988d 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.old.js @@ -30,6 +30,7 @@ import { enableSchedulerTracing, enableProfilerTimer, enableProfilerCommitHooks, + enableProfilerNestedUpdatePhase, enableSuspenseServerRenderer, enableFundamentalAPI, enableSuspenseCallback, @@ -73,6 +74,7 @@ import invariant from 'shared/invariant'; import {onCommitUnmount} from './ReactFiberDevToolsHook.old'; import {resolveDefaultProps} from './ReactFiberLazyComponent.old'; import { + isCurrentUpdateNested, getCommitTime, recordLayoutEffectDuration, startLayoutEffectTimer, @@ -434,22 +436,24 @@ export function commitPassiveEffectDurations( // It does not get reset until the start of the next commit phase. const commitTime = getCommitTime(); + let phase = finishedWork.alternate === null ? 'mount' : 'update'; + if (enableProfilerNestedUpdatePhase) { + if (isCurrentUpdateNested()) { + phase = 'nested-update'; + } + } + if (typeof onPostCommit === 'function') { if (enableSchedulerTracing) { onPostCommit( id, - finishedWork.alternate === null ? 'mount' : 'update', + phase, passiveEffectDuration, commitTime, finishedRoot.memoizedInteractions, ); } else { - onPostCommit( - id, - finishedWork.alternate === null ? 'mount' : 'update', - passiveEffectDuration, - commitTime, - ); + onPostCommit(id, phase, passiveEffectDuration, commitTime); } } @@ -706,11 +710,18 @@ function commitLifeCycles( const commitTime = getCommitTime(); + let phase = current === null ? 'mount' : 'update'; + if (enableProfilerNestedUpdatePhase) { + if (isCurrentUpdateNested()) { + phase = 'nested-update'; + } + } + if (typeof onRender === 'function') { if (enableSchedulerTracing) { onRender( finishedWork.memoizedProps.id, - current === null ? 'mount' : 'update', + phase, finishedWork.actualDuration, finishedWork.treeBaseDuration, finishedWork.actualStartTime, @@ -720,7 +731,7 @@ function commitLifeCycles( } else { onRender( finishedWork.memoizedProps.id, - current === null ? 'mount' : 'update', + phase, finishedWork.actualDuration, finishedWork.treeBaseDuration, finishedWork.actualStartTime, @@ -734,7 +745,7 @@ function commitLifeCycles( if (enableSchedulerTracing) { onCommit( finishedWork.memoizedProps.id, - current === null ? 'mount' : 'update', + phase, effectDuration, commitTime, finishedRoot.memoizedInteractions, @@ -742,7 +753,7 @@ function commitLifeCycles( } else { onCommit( finishedWork.memoizedProps.id, - current === null ? 'mount' : 'update', + phase, effectDuration, commitTime, ); diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js index d80988906706c..979e42c5c1a4a 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js @@ -21,6 +21,7 @@ import { enableSuspenseServerRenderer, replayFailedUnitOfWorkWithInvokeGuardedCallback, enableProfilerTimer, + enableProfilerNestedUpdatePhase, enableSchedulerTracing, warnAboutUnmockedScheduler, deferRenderPhaseUpdateToNextBatch, @@ -195,9 +196,11 @@ import { } from './ReactFiberStack.new'; import { + markNestedUpdateScheduled, recordCommitTime, startProfilerTimer, stopProfilerTimerIfRunningAndRecordDelta, + syncNestedUpdateFlag, } from './ReactProfilerTimer.new'; // DEV stuff @@ -939,6 +942,10 @@ function markRootSuspended(root, suspendedLanes) { // This is the entry point for synchronous tasks that don't go // through Scheduler function performSyncWorkOnRoot(root) { + if (enableProfilerTimer && enableProfilerNestedUpdatePhase) { + syncNestedUpdateFlag(); + } + invariant( (executionContext & (RenderContext | CommitContext)) === NoContext, 'Should not already be working.', @@ -1996,6 +2003,10 @@ function commitRootImpl(root, renderPriorityLevel) { } if (remainingLanes === SyncLane) { + if (enableProfilerTimer && enableProfilerNestedUpdatePhase) { + markNestedUpdateScheduled(); + } + // Count the number of times the root synchronously re-renders without // finishing. If there are too many, it indicates an infinite update loop. if (root === rootWithNestedUpdates) { diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js index 24875508a9c3c..d63b4da10bea2 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js @@ -22,6 +22,7 @@ import { replayFailedUnitOfWorkWithInvokeGuardedCallback, enableProfilerTimer, enableProfilerCommitHooks, + enableProfilerNestedUpdatePhase, enableSchedulerTracing, warnAboutUnmockedScheduler, deferRenderPhaseUpdateToNextBatch, @@ -207,11 +208,13 @@ import { } from './ReactFiberStack.old'; import { + markNestedUpdateScheduled, recordCommitTime, recordPassiveEffectDuration, startPassiveEffectTimer, startProfilerTimer, stopProfilerTimerIfRunningAndRecordDelta, + syncNestedUpdateFlag, } from './ReactProfilerTimer.old'; // DEV stuff @@ -962,6 +965,10 @@ function markRootSuspended(root, suspendedLanes) { // This is the entry point for synchronous tasks that don't go // through Scheduler function performSyncWorkOnRoot(root) { + if (enableProfilerTimer && enableProfilerNestedUpdatePhase) { + syncNestedUpdateFlag(); + } + invariant( (executionContext & (RenderContext | CommitContext)) === NoContext, 'Should not already be working.', @@ -2189,6 +2196,10 @@ function commitRootImpl(root, renderPriorityLevel) { } if (remainingLanes === SyncLane) { + if (enableProfilerTimer && enableProfilerNestedUpdatePhase) { + markNestedUpdateScheduled(); + } + // Count the number of times the root synchronously re-renders without // finishing. If there are too many, it indicates an infinite update loop. if (root === rootWithNestedUpdates) { diff --git a/packages/react-reconciler/src/ReactProfilerTimer.new.js b/packages/react-reconciler/src/ReactProfilerTimer.new.js index e7f58e1b1bc2d..95395b6898ded 100644 --- a/packages/react-reconciler/src/ReactProfilerTimer.new.js +++ b/packages/react-reconciler/src/ReactProfilerTimer.new.js @@ -10,8 +10,9 @@ import type {Fiber} from './ReactInternalTypes'; import { - enableProfilerTimer, enableProfilerCommitHooks, + enableProfilerNestedUpdatePhase, + enableProfilerTimer, } from 'shared/ReactFeatureFlags'; import {Profiler} from './ReactWorkTags'; @@ -23,10 +24,13 @@ const {unstable_now: now} = Scheduler; export type ProfilerTimer = { getCommitTime(): number, + isCurrentUpdateNested(): boolean, + markNestedUpdateScheduled(): void, recordCommitTime(): void, startProfilerTimer(fiber: Fiber): void, stopProfilerTimerIfRunning(fiber: Fiber): void, stopProfilerTimerIfRunningAndRecordDelta(fiber: Fiber): void, + syncNestedUpdateFlag(): void, ... }; @@ -35,6 +39,42 @@ let layoutEffectStartTime: number = -1; let profilerStartTime: number = -1; let passiveEffectStartTime: number = -1; +/** + * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect). + * + * The overall sequence is: + * 1. render + * 2. commit (and call `onRender`, `onCommit`) + * 3. check for nested updates + * 4. flush passive effects (and call `onPostCommit`) + * + * Nested updates are identified in step 3 above, + * but step 4 still applies to the work that was just committed. + * We use two flags to track nested updates then: + * one tracks whether the upcoming update is a nested update, + * and the other tracks whether the current update was a nested update. + * The first value gets synced to the second at the start of the render phase. + */ +let currentUpdateIsNested: boolean = false; +let nestedUpdateScheduled: boolean = false; + +function isCurrentUpdateNested(): boolean { + return currentUpdateIsNested; +} + +function markNestedUpdateScheduled(): void { + if (enableProfilerNestedUpdatePhase) { + nestedUpdateScheduled = true; + } +} + +function syncNestedUpdateFlag(): void { + if (enableProfilerNestedUpdatePhase) { + currentUpdateIsNested = nestedUpdateScheduled; + nestedUpdateScheduled = false; + } +} + function getCommitTime(): number { return commitTime; } @@ -161,6 +201,8 @@ function transferActualDuration(fiber: Fiber): void { export { getCommitTime, + isCurrentUpdateNested, + markNestedUpdateScheduled, recordCommitTime, recordLayoutEffectDuration, recordPassiveEffectDuration, @@ -169,5 +211,6 @@ export { startProfilerTimer, stopProfilerTimerIfRunning, stopProfilerTimerIfRunningAndRecordDelta, + syncNestedUpdateFlag, transferActualDuration, }; diff --git a/packages/react-reconciler/src/ReactProfilerTimer.old.js b/packages/react-reconciler/src/ReactProfilerTimer.old.js index e7f58e1b1bc2d..95395b6898ded 100644 --- a/packages/react-reconciler/src/ReactProfilerTimer.old.js +++ b/packages/react-reconciler/src/ReactProfilerTimer.old.js @@ -10,8 +10,9 @@ import type {Fiber} from './ReactInternalTypes'; import { - enableProfilerTimer, enableProfilerCommitHooks, + enableProfilerNestedUpdatePhase, + enableProfilerTimer, } from 'shared/ReactFeatureFlags'; import {Profiler} from './ReactWorkTags'; @@ -23,10 +24,13 @@ const {unstable_now: now} = Scheduler; export type ProfilerTimer = { getCommitTime(): number, + isCurrentUpdateNested(): boolean, + markNestedUpdateScheduled(): void, recordCommitTime(): void, startProfilerTimer(fiber: Fiber): void, stopProfilerTimerIfRunning(fiber: Fiber): void, stopProfilerTimerIfRunningAndRecordDelta(fiber: Fiber): void, + syncNestedUpdateFlag(): void, ... }; @@ -35,6 +39,42 @@ let layoutEffectStartTime: number = -1; let profilerStartTime: number = -1; let passiveEffectStartTime: number = -1; +/** + * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect). + * + * The overall sequence is: + * 1. render + * 2. commit (and call `onRender`, `onCommit`) + * 3. check for nested updates + * 4. flush passive effects (and call `onPostCommit`) + * + * Nested updates are identified in step 3 above, + * but step 4 still applies to the work that was just committed. + * We use two flags to track nested updates then: + * one tracks whether the upcoming update is a nested update, + * and the other tracks whether the current update was a nested update. + * The first value gets synced to the second at the start of the render phase. + */ +let currentUpdateIsNested: boolean = false; +let nestedUpdateScheduled: boolean = false; + +function isCurrentUpdateNested(): boolean { + return currentUpdateIsNested; +} + +function markNestedUpdateScheduled(): void { + if (enableProfilerNestedUpdatePhase) { + nestedUpdateScheduled = true; + } +} + +function syncNestedUpdateFlag(): void { + if (enableProfilerNestedUpdatePhase) { + currentUpdateIsNested = nestedUpdateScheduled; + nestedUpdateScheduled = false; + } +} + function getCommitTime(): number { return commitTime; } @@ -161,6 +201,8 @@ function transferActualDuration(fiber: Fiber): void { export { getCommitTime, + isCurrentUpdateNested, + markNestedUpdateScheduled, recordCommitTime, recordLayoutEffectDuration, recordPassiveEffectDuration, @@ -169,5 +211,6 @@ export { startProfilerTimer, stopProfilerTimerIfRunning, stopProfilerTimerIfRunningAndRecordDelta, + syncNestedUpdateFlag, transferActualDuration, }; diff --git a/packages/react/src/__tests__/ReactProfiler-test.internal.js b/packages/react/src/__tests__/ReactProfiler-test.internal.js index 73812de49a3b0..d9c70ae73b75c 100644 --- a/packages/react/src/__tests__/ReactProfiler-test.internal.js +++ b/packages/react/src/__tests__/ReactProfiler-test.internal.js @@ -28,6 +28,7 @@ let resourcePromise; function loadModules({ enableProfilerTimer = true, enableProfilerCommitHooks = true, + enableProfilerNestedUpdatePhase = true, enableSchedulerTracing = true, replayFailedUnitOfWorkWithInvokeGuardedCallback = false, useNoopRenderer = false, @@ -36,6 +37,7 @@ function loadModules({ ReactFeatureFlags.enableProfilerTimer = enableProfilerTimer; ReactFeatureFlags.enableProfilerCommitHooks = enableProfilerCommitHooks; + ReactFeatureFlags.enableProfilerNestedUpdatePhase = enableProfilerNestedUpdatePhase; ReactFeatureFlags.enableSchedulerTracing = enableSchedulerTracing; ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = replayFailedUnitOfWorkWithInvokeGuardedCallback; @@ -1098,7 +1100,7 @@ describe('Profiler', () => { ); // The update includes the ErrorBoundary and its fallback child - expect(updateCall[1]).toBe('update'); + expect(updateCall[1]).toBe('nested-update'); // actual time includes: 2 (ErrorBoundary) + 20 (AdvanceTime) expect(updateCall[2]).toBe(22); // base time includes: 2 (ErrorBoundary) + 20 (AdvanceTime) @@ -1456,7 +1458,7 @@ describe('Profiler', () => { expect(call).toHaveLength(enableSchedulerTracing ? 5 : 4); expect(call[0]).toBe('mount-test'); - expect(call[1]).toBe('update'); + expect(call[1]).toBe('nested-update'); expect(call[2]).toBe(130); // durations expect(call[3]).toBe(1200001011); // commit start time (before mutations or effects) expect(call[4]).toEqual(enableSchedulerTracing ? new Set() : undefined); // interaction events @@ -1485,7 +1487,7 @@ describe('Profiler', () => { expect(call).toHaveLength(enableSchedulerTracing ? 5 : 4); expect(call[0]).toBe('update-test'); - expect(call[1]).toBe('update'); + expect(call[1]).toBe('nested-update'); expect(call[2]).toBe(10000); // durations expect(call[3]).toBe(3300011272); // commit start time (before mutations or effects) expect(call[4]).toEqual(enableSchedulerTracing ? new Set() : undefined); // interaction events @@ -1716,7 +1718,7 @@ describe('Profiler', () => { // Cleanup render from error boundary expect(call).toHaveLength(enableSchedulerTracing ? 5 : 4); expect(call[0]).toBe('root'); - expect(call[1]).toBe('update'); + expect(call[1]).toBe('nested-update'); expect(call[2]).toBe(100000000); // durations expect(call[3]).toBe(10110111); // commit start time (before mutations or effects) expect(call[4]).toEqual(enableSchedulerTracing ? new Set() : undefined); // interaction events @@ -1847,7 +1849,7 @@ describe('Profiler', () => { // Cleanup render from error boundary expect(call).toHaveLength(enableSchedulerTracing ? 5 : 4); expect(call[0]).toBe('root'); - expect(call[1]).toBe('update'); + expect(call[1]).toBe('nested-update'); expect(call[2]).toBe(100001000); // durations expect(call[3]).toBe(11221221); // commit start time (before mutations or effects) expect(call[4]).toEqual(enableSchedulerTracing ? new Set() : undefined); // interaction events @@ -1905,7 +1907,7 @@ describe('Profiler', () => { expect(call).toHaveLength(enableSchedulerTracing ? 5 : 4); expect(call[0]).toBe('root'); - expect(call[1]).toBe('update'); + expect(call[1]).toBe('nested-update'); expect(call[4]).toMatchInteractions([interaction]); }); } diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 2bb5e7a5dc3f8..a4e000ada1981 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -36,6 +36,9 @@ export const enableProfilerTimer = __PROFILE__; // Record durations for commit and passive effects phases. export const enableProfilerCommitHooks = false; +// Phase param passed to onRender callback differentiates between an "update" and a "cascading-update". +export const enableProfilerNestedUpdatePhase = false; + // Trace which interactions trigger each commit. export const enableSchedulerTracing = __PROFILE__; diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index 40bee41d566a2..cf59d4e38159f 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -15,6 +15,7 @@ export const enableDebugTracing = false; export const enableSchedulingProfiler = false; export const enableProfilerTimer = __PROFILE__; export const enableProfilerCommitHooks = false; +export const enableProfilerNestedUpdatePhase = false; export const enableSchedulerTracing = __PROFILE__; export const enableSuspenseServerRenderer = false; export const enableSelectiveHydration = false; diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index 0665b4b5d71b9..3e60d97e59c56 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -17,6 +17,7 @@ export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__; export const warnAboutDeprecatedLifecycles = true; export const enableProfilerTimer = __PROFILE__; export const enableProfilerCommitHooks = false; +export const enableProfilerNestedUpdatePhase = false; export const enableSchedulerTracing = __PROFILE__; export const enableSuspenseServerRenderer = false; export const enableSelectiveHydration = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index 2102c905be9f4..a920b57b7a39c 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -17,6 +17,7 @@ export const warnAboutDeprecatedLifecycles = true; export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false; export const enableProfilerTimer = __PROFILE__; export const enableProfilerCommitHooks = false; +export const enableProfilerNestedUpdatePhase = false; export const enableSchedulerTracing = __PROFILE__; export const enableSuspenseServerRenderer = false; export const enableSelectiveHydration = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js index f2dc6d7f0ad05..ef1d4518ed36a 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js @@ -17,6 +17,7 @@ export const warnAboutDeprecatedLifecycles = true; export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false; export const enableProfilerTimer = __PROFILE__; export const enableProfilerCommitHooks = false; +export const enableProfilerNestedUpdatePhase = false; export const enableSchedulerTracing = __PROFILE__; export const enableSuspenseServerRenderer = false; export const enableSelectiveHydration = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index 7c6588150ef95..d668a8fbe6293 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -17,6 +17,7 @@ export const warnAboutDeprecatedLifecycles = true; export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false; export const enableProfilerTimer = __PROFILE__; export const enableProfilerCommitHooks = false; +export const enableProfilerNestedUpdatePhase = false; export const enableSchedulerTracing = __PROFILE__; export const enableSuspenseServerRenderer = false; export const enableSelectiveHydration = false; diff --git a/packages/shared/forks/ReactFeatureFlags.testing.js b/packages/shared/forks/ReactFeatureFlags.testing.js index 36cf66d18e4be..62beb73dd7061 100644 --- a/packages/shared/forks/ReactFeatureFlags.testing.js +++ b/packages/shared/forks/ReactFeatureFlags.testing.js @@ -17,6 +17,7 @@ export const warnAboutDeprecatedLifecycles = true; export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false; export const enableProfilerTimer = __PROFILE__; export const enableProfilerCommitHooks = false; +export const enableProfilerNestedUpdatePhase = false; export const enableSchedulerTracing = __PROFILE__; export const enableSuspenseServerRenderer = false; export const enableSelectiveHydration = false; diff --git a/packages/shared/forks/ReactFeatureFlags.testing.www.js b/packages/shared/forks/ReactFeatureFlags.testing.www.js index fd6eba5a52087..2eac96c9de024 100644 --- a/packages/shared/forks/ReactFeatureFlags.testing.www.js +++ b/packages/shared/forks/ReactFeatureFlags.testing.www.js @@ -17,6 +17,7 @@ export const warnAboutDeprecatedLifecycles = true; export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false; export const enableProfilerTimer = false; export const enableProfilerCommitHooks = false; +export const enableProfilerNestedUpdatePhase = false; export const enableSchedulerTracing = false; export const enableSuspenseServerRenderer = true; export const enableSelectiveHydration = true; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index c12be6366806f..5fe35f24a536b 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -36,6 +36,7 @@ export const { export const enableProfilerTimer = __PROFILE__; export const enableProfilerCommitHooks = __PROFILE__; +export const enableProfilerNestedUpdatePhase = __PROFILE__; // Logs additional User Timing API marks for use with an experimental profiling tool. export const enableSchedulingProfiler = __PROFILE__;