From 393c452e39a72932af734c7c25998b48a20698f7 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 10 Nov 2020 09:40:30 -0500 Subject: [PATCH] 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. --- .../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 0f16c4c0a3fb..6f0b923c1444 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, @@ -357,22 +359,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; @@ -1333,11 +1337,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, @@ -1347,7 +1358,7 @@ function commitLayoutEffectsForProfiler( } else { onRender( finishedWork.memoizedProps.id, - current === null ? 'mount' : 'update', + phase, finishedWork.actualDuration, finishedWork.treeBaseDuration, finishedWork.actualStartTime, @@ -1364,7 +1375,7 @@ function commitLayoutEffectsForProfiler( if (enableSchedulerTracing) { onCommit( finishedWork.memoizedProps.id, - current === null ? 'mount' : 'update', + phase, effectDuration, commitTime, finishedRoot.memoizedInteractions, @@ -1372,7 +1383,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 1ec6ed787481..55db13cf3988 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 9988e7b3b1ad..9153c03049b9 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, @@ -194,9 +195,11 @@ import { } from './ReactFiberStack.new'; import { + markNestedUpdateScheduled, recordCommitTime, startProfilerTimer, stopProfilerTimerIfRunningAndRecordDelta, + syncNestedUpdateFlag, } from './ReactProfilerTimer.new'; // DEV stuff @@ -938,6 +941,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.', @@ -1995,6 +2002,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 47eb654b6ac7..b2476dad5b61 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 e7f58e1b1bc2..95395b6898de 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 e7f58e1b1bc2..95395b6898de 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 73812de49a3b..d9c70ae73b75 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 e1b3f657f3f9..b796e5b1ffac 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 53eb440cffd1..5a5bc9ea85f8 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 b0bad62bae54..82c57055f1c0 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 2b5f7985cb19..6a572127e5ea 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 ef0d466da4a2..2fae5f7e2bda 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 45bd15b5c72b..d254b9274ad3 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 881c6f156b53..7b470ba5bf67 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 af360493b19d..a0bc67a833bd 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 4ab58388642c..2e8d9d39cfa4 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -35,6 +35,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__;