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 0f16c4c0a3fb1..6f0b923c14445 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 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 9988e7b3b1ad3..9153c03049b9f 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 47eb654b6ac75..b2476dad5b615 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 e1b3f657f3f96..b796e5b1ffacc 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 53eb440cffd1d..5a5bc9ea85f80 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 b0bad62bae54c..82c57055f1c0c 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 2b5f7985cb192..6a572127e5ea2 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 ef0d466da4a27..2fae5f7e2bdaa 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 45bd15b5c72bc..d254b9274ad3a 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 881c6f156b535..7b470ba5bf674 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 af360493b19db..a0bc67a833bda 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 4ab58388642cc..2e8d9d39cfa43 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__;