diff --git a/packages/react-dom/index.classic.fb.js b/packages/react-dom/index.classic.fb.js index 1f451d70348b..e946df7b76db 100644 --- a/packages/react-dom/index.classic.fb.js +++ b/packages/react-dom/index.classic.fb.js @@ -7,7 +7,6 @@ * @flow */ -import {addUserTimingListener} from 'shared/ReactFeatureFlags'; import {isEnabled} from './src/events/ReactDOMEventListener'; import {__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from './src/client/ReactDOM'; @@ -17,8 +16,6 @@ Object.assign((__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: any), { ReactBrowserEventEmitter: { isEnabled, }, - // Perf experiment - addUserTimingListener, }); export { diff --git a/packages/react-reconciler/src/ReactDebugFiberPerf.js b/packages/react-reconciler/src/ReactDebugFiberPerf.js deleted file mode 100644 index 63dcf1af59a0..000000000000 --- a/packages/react-reconciler/src/ReactDebugFiberPerf.js +++ /dev/null @@ -1,506 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type {Fiber} from './ReactFiber'; - -import {enableUserTimingAPI} from 'shared/ReactFeatureFlags'; -import getComponentName from 'shared/getComponentName'; -import { - HostRoot, - HostComponent, - HostText, - HostPortal, - Fragment, - ContextProvider, - ContextConsumer, - Mode, - SuspenseComponent, -} from './ReactWorkTags'; - -type MeasurementPhase = - | 'componentWillMount' - | 'componentWillUnmount' - | 'componentWillReceiveProps' - | 'shouldComponentUpdate' - | 'componentWillUpdate' - | 'componentDidUpdate' - | 'componentDidMount' - | 'getChildContext' - | 'getSnapshotBeforeUpdate'; - -// Prefix measurements so that it's possible to filter them. -// Longer prefixes are hard to read in DevTools. -const reactEmoji = '\u269B'; -const warningEmoji = '\u26D4'; -const supportsUserTiming = - typeof performance !== 'undefined' && - typeof performance.mark === 'function' && - typeof performance.clearMarks === 'function' && - typeof performance.measure === 'function' && - typeof performance.clearMeasures === 'function'; - -// Keep track of current fiber so that we know the path to unwind on pause. -// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them? -let currentFiber: Fiber | null = null; -// If we're in the middle of user code, which fiber and method is it? -// Reusing `currentFiber` would be confusing for this because user code fiber -// can change during commit phase too, but we don't need to unwind it (since -// lifecycles in the commit phase don't resemble a tree). -let currentPhase: MeasurementPhase | null = null; -let currentPhaseFiber: Fiber | null = null; -// Did lifecycle hook schedule an update? This is often a performance problem, -// so we will keep track of it, and include it in the report. -// Track commits caused by cascading updates. -let isCommitting: boolean = false; -let hasScheduledUpdateInCurrentCommit: boolean = false; -let hasScheduledUpdateInCurrentPhase: boolean = false; -let commitCountInCurrentWorkLoop: number = 0; -let effectCountInCurrentCommit: number = 0; -let isWaitingForCallback: boolean = false; -// During commits, we only show a measurement once per method name -// to avoid stretch the commit phase with measurement overhead. -const labelsInCurrentCommit: Set = new Set(); - -const formatMarkName = (markName: string) => { - return `${reactEmoji} ${markName}`; -}; - -const formatLabel = (label: string, warning: string | null) => { - const prefix = warning ? `${warningEmoji} ` : `${reactEmoji} `; - const suffix = warning ? ` Warning: ${warning}` : ''; - return `${prefix}${label}${suffix}`; -}; - -const beginMark = (markName: string) => { - performance.mark(formatMarkName(markName)); -}; - -const clearMark = (markName: string) => { - performance.clearMarks(formatMarkName(markName)); -}; - -const endMark = (label: string, markName: string, warning: string | null) => { - const formattedMarkName = formatMarkName(markName); - const formattedLabel = formatLabel(label, warning); - try { - performance.measure(formattedLabel, formattedMarkName); - } catch (err) { - // If previous mark was missing for some reason, this will throw. - // This could only happen if React crashed in an unexpected place earlier. - // Don't pile on with more errors. - } - // Clear marks immediately to avoid growing buffer. - performance.clearMarks(formattedMarkName); - performance.clearMeasures(formattedLabel); -}; - -const getFiberMarkName = (label: string, debugID: number) => { - return `${label} (#${debugID})`; -}; - -const getFiberLabel = ( - componentName: string, - isMounted: boolean, - phase: MeasurementPhase | null, -) => { - if (phase === null) { - // These are composite component total time measurements. - return `${componentName} [${isMounted ? 'update' : 'mount'}]`; - } else { - // Composite component methods. - return `${componentName}.${phase}`; - } -}; - -const beginFiberMark = ( - fiber: Fiber, - phase: MeasurementPhase | null, -): boolean => { - const componentName = getComponentName(fiber.type) || 'Unknown'; - const debugID = ((fiber._debugID: any): number); - const isMounted = fiber.alternate !== null; - const label = getFiberLabel(componentName, isMounted, phase); - - if (isCommitting && labelsInCurrentCommit.has(label)) { - // During the commit phase, we don't show duplicate labels because - // there is a fixed overhead for every measurement, and we don't - // want to stretch the commit phase beyond necessary. - return false; - } - labelsInCurrentCommit.add(label); - - const markName = getFiberMarkName(label, debugID); - beginMark(markName); - return true; -}; - -const clearFiberMark = (fiber: Fiber, phase: MeasurementPhase | null) => { - const componentName = getComponentName(fiber.type) || 'Unknown'; - const debugID = ((fiber._debugID: any): number); - const isMounted = fiber.alternate !== null; - const label = getFiberLabel(componentName, isMounted, phase); - const markName = getFiberMarkName(label, debugID); - clearMark(markName); -}; - -const endFiberMark = ( - fiber: Fiber, - phase: MeasurementPhase | null, - warning: string | null, -) => { - const componentName = getComponentName(fiber.type) || 'Unknown'; - const debugID = ((fiber._debugID: any): number); - const isMounted = fiber.alternate !== null; - const label = getFiberLabel(componentName, isMounted, phase); - const markName = getFiberMarkName(label, debugID); - endMark(label, markName, warning); -}; - -const shouldIgnoreFiber = (fiber: Fiber): boolean => { - // Host components should be skipped in the timeline. - // We could check typeof fiber.type, but does this work with RN? - switch (fiber.tag) { - case HostRoot: - case HostComponent: - case HostText: - case HostPortal: - case Fragment: - case ContextProvider: - case ContextConsumer: - case Mode: - return true; - default: - return false; - } -}; - -const clearPendingPhaseMeasurement = () => { - if (currentPhase !== null && currentPhaseFiber !== null) { - clearFiberMark(currentPhaseFiber, currentPhase); - } - currentPhaseFiber = null; - currentPhase = null; - hasScheduledUpdateInCurrentPhase = false; -}; - -const pauseTimers = () => { - // Stops all currently active measurements so that they can be resumed - // if we continue in a later deferred loop from the same unit of work. - let fiber = currentFiber; - while (fiber) { - if (fiber._debugIsCurrentlyTiming) { - endFiberMark(fiber, null, null); - } - fiber = fiber.return; - } -}; - -const resumeTimersRecursively = (fiber: Fiber) => { - if (fiber.return !== null) { - resumeTimersRecursively(fiber.return); - } - if (fiber._debugIsCurrentlyTiming) { - beginFiberMark(fiber, null); - } -}; - -const resumeTimers = () => { - // Resumes all measurements that were active during the last deferred loop. - if (currentFiber !== null) { - resumeTimersRecursively(currentFiber); - } -}; - -export function recordEffect(): void { - if (enableUserTimingAPI) { - effectCountInCurrentCommit++; - } -} - -export function recordScheduleUpdate(): void { - if (enableUserTimingAPI) { - if (isCommitting) { - hasScheduledUpdateInCurrentCommit = true; - } - if ( - currentPhase !== null && - currentPhase !== 'componentWillMount' && - currentPhase !== 'componentWillReceiveProps' - ) { - hasScheduledUpdateInCurrentPhase = true; - } - } -} - -export function startRequestCallbackTimer(): void { - if (enableUserTimingAPI) { - if (supportsUserTiming && !isWaitingForCallback) { - isWaitingForCallback = true; - beginMark('(Waiting for async callback...)'); - } - } -} - -export function stopRequestCallbackTimer(didExpire: boolean): void { - if (enableUserTimingAPI) { - if (supportsUserTiming) { - isWaitingForCallback = false; - const warning = didExpire - ? 'Update expired; will flush synchronously' - : null; - endMark( - '(Waiting for async callback...)', - '(Waiting for async callback...)', - warning, - ); - } - } -} - -export function startWorkTimer(fiber: Fiber): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // If we pause, this is the fiber to unwind from. - currentFiber = fiber; - if (!beginFiberMark(fiber, null)) { - return; - } - fiber._debugIsCurrentlyTiming = true; - } -} - -export function cancelWorkTimer(fiber: Fiber): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // Remember we shouldn't complete measurement for this fiber. - // Otherwise flamechart will be deep even for small updates. - fiber._debugIsCurrentlyTiming = false; - clearFiberMark(fiber, null); - } -} - -export function stopWorkTimer(fiber: Fiber): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // If we pause, its parent is the fiber to unwind from. - currentFiber = fiber.return; - if (!fiber._debugIsCurrentlyTiming) { - return; - } - fiber._debugIsCurrentlyTiming = false; - endFiberMark(fiber, null, null); - } -} - -export function stopFailedWorkTimer(fiber: Fiber): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // If we pause, its parent is the fiber to unwind from. - currentFiber = fiber.return; - if (!fiber._debugIsCurrentlyTiming) { - return; - } - fiber._debugIsCurrentlyTiming = false; - const warning = - fiber.tag === SuspenseComponent - ? 'Rendering was suspended' - : 'An error was thrown inside this error boundary'; - endFiberMark(fiber, null, warning); - } -} - -export function startPhaseTimer(fiber: Fiber, phase: MeasurementPhase): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - clearPendingPhaseMeasurement(); - if (!beginFiberMark(fiber, phase)) { - return; - } - currentPhaseFiber = fiber; - currentPhase = phase; - } -} - -export function stopPhaseTimer(): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - if (currentPhase !== null && currentPhaseFiber !== null) { - const warning = hasScheduledUpdateInCurrentPhase - ? 'Scheduled a cascading update' - : null; - endFiberMark(currentPhaseFiber, currentPhase, warning); - } - currentPhase = null; - currentPhaseFiber = null; - } -} - -export function startWorkLoopTimer(nextUnitOfWork: Fiber | null): void { - if (enableUserTimingAPI) { - currentFiber = nextUnitOfWork; - if (!supportsUserTiming) { - return; - } - commitCountInCurrentWorkLoop = 0; - // This is top level call. - // Any other measurements are performed within. - beginMark('(React Tree Reconciliation)'); - // Resume any measurements that were in progress during the last loop. - resumeTimers(); - } -} - -export function stopWorkLoopTimer( - interruptedBy: Fiber | null, - didCompleteRoot: boolean, -): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - let warning = null; - if (interruptedBy !== null) { - if (interruptedBy.tag === HostRoot) { - warning = 'A top-level update interrupted the previous render'; - } else { - const componentName = getComponentName(interruptedBy.type) || 'Unknown'; - warning = `An update to ${componentName} interrupted the previous render`; - } - } else if (commitCountInCurrentWorkLoop > 1) { - warning = 'There were cascading updates'; - } - commitCountInCurrentWorkLoop = 0; - let label = didCompleteRoot - ? '(React Tree Reconciliation: Completed Root)' - : '(React Tree Reconciliation: Yielded)'; - // Pause any measurements until the next loop. - pauseTimers(); - endMark(label, '(React Tree Reconciliation)', warning); - } -} - -export function startCommitTimer(): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - isCommitting = true; - hasScheduledUpdateInCurrentCommit = false; - labelsInCurrentCommit.clear(); - beginMark('(Committing Changes)'); - } -} - -export function stopCommitTimer(): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - - let warning = null; - if (hasScheduledUpdateInCurrentCommit) { - warning = 'Lifecycle hook scheduled a cascading update'; - } else if (commitCountInCurrentWorkLoop > 0) { - warning = 'Caused by a cascading update in earlier commit'; - } - hasScheduledUpdateInCurrentCommit = false; - commitCountInCurrentWorkLoop++; - isCommitting = false; - labelsInCurrentCommit.clear(); - - endMark('(Committing Changes)', '(Committing Changes)', warning); - } -} - -export function startCommitSnapshotEffectsTimer(): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - effectCountInCurrentCommit = 0; - beginMark('(Committing Snapshot Effects)'); - } -} - -export function stopCommitSnapshotEffectsTimer(): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - const count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - `(Committing Snapshot Effects: ${count} Total)`, - '(Committing Snapshot Effects)', - null, - ); - } -} - -export function startCommitHostEffectsTimer(): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - effectCountInCurrentCommit = 0; - beginMark('(Committing Host Effects)'); - } -} - -export function stopCommitHostEffectsTimer(): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - const count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - `(Committing Host Effects: ${count} Total)`, - '(Committing Host Effects)', - null, - ); - } -} - -export function startCommitLifeCyclesTimer(): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - effectCountInCurrentCommit = 0; - beginMark('(Calling Lifecycle Methods)'); - } -} - -export function stopCommitLifeCyclesTimer(): void { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - const count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark( - `(Calling Lifecycle Methods: ${count} Total)`, - '(Calling Lifecycle Methods)', - null, - ); - } -} diff --git a/packages/react-reconciler/src/ReactFiber.js b/packages/react-reconciler/src/ReactFiber.js index 4f0af6fe331e..f84d7796c99b 100644 --- a/packages/react-reconciler/src/ReactFiber.js +++ b/packages/react-reconciler/src/ReactFiber.js @@ -31,7 +31,6 @@ import invariant from 'shared/invariant'; import { enableProfilerTimer, enableFundamentalAPI, - enableUserTimingAPI, enableScopeAPI, enableBlocksAPI, throwEarlyForMysteriousError, @@ -324,14 +323,9 @@ function FiberNode( this.treeBaseDuration = 0; } - // This is normally DEV-only except www when it adds listeners. - // TODO: remove the User Timing integration in favor of Root Events. - if (enableUserTimingAPI) { - this._debugID = debugCounter++; - this._debugIsCurrentlyTiming = false; - } - if (__DEV__) { + // This isn't directly used but is handy for debugging internals: + this._debugID = debugCounter++; this._debugSource = null; this._debugOwner = null; this._debugNeedsRemount = false; @@ -419,9 +413,7 @@ export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber { if (__DEV__) { // DEV-only fields - if (enableUserTimingAPI) { - workInProgress._debugID = current._debugID; - } + workInProgress._debugID = current._debugID; workInProgress._debugSource = current._debugSource; workInProgress._debugOwner = current._debugOwner; workInProgress._debugHookTypes = current._debugHookTypes; @@ -968,10 +960,7 @@ export function assignFiberPropertiesInDEV( target.selfBaseDuration = source.selfBaseDuration; target.treeBaseDuration = source.treeBaseDuration; } - if (enableUserTimingAPI) { - target._debugID = source._debugID; - target._debugIsCurrentlyTiming = source._debugIsCurrentlyTiming; - } + target._debugID = source._debugID; target._debugSource = source._debugSource; target._debugOwner = source._debugOwner; target._debugNeedsRemount = source._debugNeedsRemount; diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 2ffd2fe79c09..2c6472c60fc1 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -79,7 +79,6 @@ import { getCurrentFiberOwnerNameInDevOrNull, setIsRendering, } from './ReactCurrentFiber'; -import {startWorkTimer, cancelWorkTimer} from './ReactDebugFiberPerf'; import { resolveFunctionForHotReloading, resolveForwardRefForHotReloading, @@ -1128,9 +1127,6 @@ function mountLazyComponent( } const props = workInProgress.pendingProps; - // We can't start a User Timing measurement with correct label yet. - // Cancel and resume right after we know the tag. - cancelWorkTimer(workInProgress); let lazyComponent: LazyComponentType = elementType; let payload = lazyComponent._payload; let init = lazyComponent._init; @@ -1138,7 +1134,6 @@ function mountLazyComponent( // Store the unwrapped component in the type. workInProgress.type = Component; const resolvedTag = (workInProgress.tag = resolveLazyComponentTag(Component)); - startWorkTimer(workInProgress); const resolvedProps = resolveDefaultProps(Component, props); let child; switch (resolvedTag) { @@ -2886,8 +2881,6 @@ function bailoutOnAlreadyFinishedWork( workInProgress: Fiber, renderExpirationTime: ExpirationTime, ): Fiber | null { - cancelWorkTimer(workInProgress); - if (current !== null) { // Reuse previous dependencies workInProgress.dependencies = current.dependencies; diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.js b/packages/react-reconciler/src/ReactFiberClassComponent.js index 83eff60f9285..7065a64c0c0b 100644 --- a/packages/react-reconciler/src/ReactFiberClassComponent.js +++ b/packages/react-reconciler/src/ReactFiberClassComponent.js @@ -26,7 +26,6 @@ import getComponentName from 'shared/getComponentName'; import invariant from 'shared/invariant'; import {REACT_CONTEXT_TYPE, REACT_PROVIDER_TYPE} from 'shared/ReactSymbols'; -import {startPhaseTimer, stopPhaseTimer} from './ReactDebugFiberPerf'; import {resolveDefaultProps} from './ReactFiberLazyComponent'; import {StrictMode} from './ReactTypeOfMode'; @@ -271,13 +270,11 @@ function checkShouldComponentUpdate( instance.shouldComponentUpdate(newProps, newState, nextContext); } } - startPhaseTimer(workInProgress, 'shouldComponentUpdate'); const shouldUpdate = instance.shouldComponentUpdate( newProps, newState, nextContext, ); - stopPhaseTimer(); if (__DEV__) { if (shouldUpdate === undefined) { @@ -705,7 +702,6 @@ function constructClassInstance( } function callComponentWillMount(workInProgress, instance) { - startPhaseTimer(workInProgress, 'componentWillMount'); const oldState = instance.state; if (typeof instance.componentWillMount === 'function') { @@ -715,8 +711,6 @@ function callComponentWillMount(workInProgress, instance) { instance.UNSAFE_componentWillMount(); } - stopPhaseTimer(); - if (oldState !== instance.state) { if (__DEV__) { console.error( @@ -737,14 +731,12 @@ function callComponentWillReceiveProps( nextContext, ) { const oldState = instance.state; - startPhaseTimer(workInProgress, 'componentWillReceiveProps'); if (typeof instance.componentWillReceiveProps === 'function') { instance.componentWillReceiveProps(newProps, nextContext); } if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') { instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); } - stopPhaseTimer(); if (instance.state !== oldState) { if (__DEV__) { @@ -961,14 +953,12 @@ function resumeMountClassInstance( (typeof instance.UNSAFE_componentWillMount === 'function' || typeof instance.componentWillMount === 'function') ) { - startPhaseTimer(workInProgress, 'componentWillMount'); if (typeof instance.componentWillMount === 'function') { instance.componentWillMount(); } if (typeof instance.UNSAFE_componentWillMount === 'function') { instance.UNSAFE_componentWillMount(); } - stopPhaseTimer(); } if (typeof instance.componentDidMount === 'function') { workInProgress.effectTag |= Update; @@ -1113,14 +1103,12 @@ function updateClassInstance( (typeof instance.UNSAFE_componentWillUpdate === 'function' || typeof instance.componentWillUpdate === 'function') ) { - startPhaseTimer(workInProgress, 'componentWillUpdate'); if (typeof instance.componentWillUpdate === 'function') { instance.componentWillUpdate(newProps, newState, nextContext); } if (typeof instance.UNSAFE_componentWillUpdate === 'function') { instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); } - stopPhaseTimer(); } if (typeof instance.componentDidUpdate === 'function') { workInProgress.effectTag |= Update; diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.js b/packages/react-reconciler/src/ReactFiberCommitWork.js index 5af821dfc8fd..1e993acb65bb 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.js @@ -74,7 +74,6 @@ import getComponentName from 'shared/getComponentName'; import invariant from 'shared/invariant'; import {onCommitUnmount} from './ReactFiberDevToolsHook'; -import {startPhaseTimer, stopPhaseTimer} from './ReactDebugFiberPerf'; import {getStackByFiberInDevAndProd} from './ReactCurrentFiber'; import {logCapturedError} from './ReactFiberErrorLogger'; import {resolveDefaultProps} from './ReactFiberLazyComponent'; @@ -182,7 +181,6 @@ export function logError(boundary: Fiber, errorInfo: CapturedValue) { } const callComponentWillUnmountWithTimer = function(current, instance) { - startPhaseTimer(current, 'componentWillUnmount'); instance.props = current.memoizedProps; instance.state = current.memoizedState; if ( @@ -199,7 +197,6 @@ const callComponentWillUnmountWithTimer = function(current, instance) { } else { instance.componentWillUnmount(); } - stopPhaseTimer(); }; // Capture errors so they don't interrupt unmounting. @@ -280,7 +277,6 @@ function commitBeforeMutationLifeCycles( if (current !== null) { const prevProps = current.memoizedProps; const prevState = current.memoizedState; - startPhaseTimer(finishedWork, 'getSnapshotBeforeUpdate'); const instance = finishedWork.stateNode; // We could update instance props and state here, // but instead we rely on them being set during last render. @@ -330,7 +326,6 @@ function commitBeforeMutationLifeCycles( } } instance.__reactInternalSnapshotBeforeUpdate = snapshot; - stopPhaseTimer(); } } return; @@ -580,7 +575,6 @@ function commitLifeCycles( const instance = finishedWork.stateNode; if (finishedWork.effectTag & Update) { if (current === null) { - startPhaseTimer(finishedWork, 'componentDidMount'); // We could update instance props and state here, // but instead we rely on them being set during last render. // TODO: revisit this when we implement resuming. @@ -625,14 +619,12 @@ function commitLifeCycles( } else { instance.componentDidMount(); } - stopPhaseTimer(); } else { const prevProps = finishedWork.elementType === finishedWork.type ? current.memoizedProps : resolveDefaultProps(finishedWork.type, current.memoizedProps); const prevState = current.memoizedState; - startPhaseTimer(finishedWork, 'componentDidUpdate'); // We could update instance props and state here, // but instead we rely on them being set during last render. // TODO: revisit this when we implement resuming. @@ -685,7 +677,6 @@ function commitLifeCycles( instance.__reactInternalSnapshotBeforeUpdate, ); } - stopPhaseTimer(); } } const updateQueue = finishedWork.updateQueue; diff --git a/packages/react-reconciler/src/ReactFiberContext.js b/packages/react-reconciler/src/ReactFiberContext.js index 33ba72aeec10..d2e0b40431de 100644 --- a/packages/react-reconciler/src/ReactFiberContext.js +++ b/packages/react-reconciler/src/ReactFiberContext.js @@ -17,7 +17,6 @@ import getComponentName from 'shared/getComponentName'; import invariant from 'shared/invariant'; import checkPropTypes from 'shared/checkPropTypes'; -import {startPhaseTimer, stopPhaseTimer} from './ReactDebugFiberPerf'; import {createCursor, push, pop} from './ReactFiberStack'; let warnedAboutMissingGetChildContext; @@ -203,9 +202,7 @@ function processChildContext( } let childContext; - startPhaseTimer(fiber, 'getChildContext'); childContext = instance.getChildContext(); - stopPhaseTimer(); for (let contextKey in childContext) { invariant( contextKey in childContextTypes, diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index ec80c6c91c45..276795d2cee9 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -21,7 +21,6 @@ import { warnAboutDeprecatedLifecycles, deferPassiveEffectCleanupDuringUnmount, runAllPassiveEffectDestroysBeforeCreates, - enableUserTimingAPI, enableSuspenseServerRenderer, replayFailedUnitOfWorkWithInvokeGuardedCallback, enableProfilerTimer, @@ -167,23 +166,6 @@ import { setCurrentFiber as setCurrentDebugFiberInDEV, getStackByFiberInDevAndProd, } from './ReactCurrentFiber'; -import { - recordEffect, - recordScheduleUpdate, - startWorkTimer, - stopWorkTimer, - stopFailedWorkTimer, - startWorkLoopTimer, - stopWorkLoopTimer, - startCommitTimer, - stopCommitTimer, - startCommitSnapshotEffectsTimer, - stopCommitSnapshotEffectsTimer, - startCommitHostEffectsTimer, - stopCommitHostEffectsTimer, - startCommitLifeCyclesTimer, - stopCommitLifeCyclesTimer, -} from './ReactDebugFiberPerf'; import { invokeGuardedCallback, hasCaughtError, @@ -275,8 +257,6 @@ let rootWithNestedUpdates: FiberRoot | null = null; const NESTED_PASSIVE_UPDATE_LIMIT = 50; let nestedPassiveUpdateCount: number = 0; -let interruptedBy: Fiber | null = null; - // Marks the need to reschedule pending interactions at these expiration times // during the commit phase. This enables them to be traced across components // that spawn new work during render. E.g. hidden boundaries, suspended SSR @@ -397,9 +377,6 @@ export function scheduleUpdateOnFiber( return; } - checkForInterruption(fiber, expirationTime); - recordScheduleUpdate(); - // TODO: computeExpirationForFiber also reads the priority. Pass the // priority as an argument to that function and this one. const priorityLevel = getCurrentPriorityLevel(); @@ -1410,7 +1387,6 @@ function renderRootSync(root, expirationTime) { } const prevInteractions = pushInteractions(root); - startWorkLoopTimer(workInProgress); do { try { workLoopSync(); @@ -1436,8 +1412,6 @@ function renderRootSync(root, expirationTime) { ); } - stopFinishedWorkLoopTimer(); - // Set this to null to indicate there's no in-progress render. workInProgressRoot = null; @@ -1466,7 +1440,6 @@ function renderRootConcurrent(root, expirationTime) { } const prevInteractions = pushInteractions(root); - startWorkLoopTimer(workInProgress); do { try { workLoopConcurrent(); @@ -1486,12 +1459,9 @@ function renderRootConcurrent(root, expirationTime) { // Check if the tree has completed. if (workInProgress !== null) { // Still work remaining. - stopInterruptedWorkLoopTimer(); return RootIncomplete; } else { // Completed the tree. - stopFinishedWorkLoopTimer(); - // Set this to null to indicate there's no in-progress render. workInProgressRoot = null; @@ -1513,8 +1483,6 @@ function performUnitOfWork(unitOfWork: Fiber): Fiber | null { // nothing should rely on this, but relying on it here means that we don't // need an additional field on the work in progress. const current = unitOfWork.alternate; - - startWorkTimer(unitOfWork); setCurrentDebugFiberInDEV(unitOfWork); let next; @@ -1563,7 +1531,6 @@ function completeUnitOfWork(unitOfWork: Fiber): Fiber | null { // Update render duration assuming we didn't error. stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false); } - stopWorkTimer(workInProgress); resetCurrentDebugFiberInDEV(); resetChildExpirationTime(workInProgress); @@ -1640,13 +1607,9 @@ function completeUnitOfWork(unitOfWork: Fiber): Fiber | null { // back here again. // Since we're restarting, remove anything that is not a host effect // from the effect tag. - // TODO: The name stopFailedWorkTimer is misleading because Suspense - // also captures and restarts. - stopFailedWorkTimer(workInProgress); next.effectTag &= HostEffectMask; return next; } - stopWorkTimer(workInProgress); if (returnFiber !== null) { // Mark the parent fiber as incomplete and clear its effect list. @@ -1792,8 +1755,6 @@ function commitRootImpl(root, renderPriorityLevel) { root.callbackPriority = NoPriority; root.nextKnownPendingLevel = NoWork; - startCommitTimer(); - // Update the first and last pending times on this root. The new first // pending time is whatever is left on the root fiber. const remainingExpirationTimeBeforeCommit = getRemainingExpirationTime( @@ -1849,7 +1810,6 @@ function commitRootImpl(root, renderPriorityLevel) { // The first phase a "before mutation" phase. We use this phase to read the // state of the host tree right before we mutate it. This is where // getSnapshotBeforeUpdate is called. - startCommitSnapshotEffectsTimer(); prepareForCommit(root.containerInfo); nextEffect = firstEffect; do { @@ -1871,7 +1831,6 @@ function commitRootImpl(root, renderPriorityLevel) { } } } while (nextEffect !== null); - stopCommitSnapshotEffectsTimer(); if (enableProfilerTimer) { // Mark the current commit time to be shared by all Profilers in this @@ -1880,7 +1839,6 @@ function commitRootImpl(root, renderPriorityLevel) { } // The next phase is the mutation phase, where we mutate the host tree. - startCommitHostEffectsTimer(); nextEffect = firstEffect; do { if (__DEV__) { @@ -1907,7 +1865,6 @@ function commitRootImpl(root, renderPriorityLevel) { } } } while (nextEffect !== null); - stopCommitHostEffectsTimer(); resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after @@ -1919,7 +1876,6 @@ function commitRootImpl(root, renderPriorityLevel) { // The next phase is the layout phase, where we call effects that read // the host tree after it's been mutated. The idiomatic use case for this is // layout, but class component lifecycles also fire here for legacy reasons. - startCommitLifeCyclesTimer(); nextEffect = firstEffect; do { if (__DEV__) { @@ -1946,7 +1902,6 @@ function commitRootImpl(root, renderPriorityLevel) { } } } while (nextEffect !== null); - stopCommitLifeCyclesTimer(); nextEffect = null; @@ -1964,19 +1919,11 @@ function commitRootImpl(root, renderPriorityLevel) { // Measure these anyway so the flamegraph explicitly shows that there were // no effects. // TODO: Maybe there's a better way to report this. - startCommitSnapshotEffectsTimer(); - stopCommitSnapshotEffectsTimer(); if (enableProfilerTimer) { recordCommitTime(); } - startCommitHostEffectsTimer(); - stopCommitHostEffectsTimer(); - startCommitLifeCyclesTimer(); - stopCommitLifeCyclesTimer(); } - stopCommitTimer(); - const rootDidHavePassiveEffects = rootDoesHavePassiveEffects; if (rootDoesHavePassiveEffects) { @@ -2075,7 +2022,6 @@ function commitBeforeMutationEffects() { const effectTag = nextEffect.effectTag; if ((effectTag & Snapshot) !== NoEffect) { setCurrentDebugFiberInDEV(nextEffect); - recordEffect(); const current = nextEffect.alternate; commitBeforeMutationEffectOnFiber(current, nextEffect); @@ -2166,9 +2112,6 @@ function commitMutationEffects(root: FiberRoot, renderPriorityLevel) { } } - // TODO: Only record a mutation effect if primaryEffectTag is non-zero. - recordEffect(); - resetCurrentDebugFiberInDEV(); nextEffect = nextEffect.nextEffect; } @@ -2185,7 +2128,6 @@ function commitLayoutEffects( const effectTag = nextEffect.effectTag; if (effectTag & (Update | Callback)) { - recordEffect(); const current = nextEffect.alternate; commitLayoutEffectOnFiber( root, @@ -2196,7 +2138,6 @@ function commitLayoutEffects( } if (effectTag & Ref) { - recordEffect(); commitAttachRef(nextEffect); } @@ -2755,32 +2696,6 @@ function flushRenderPhaseStrictModeWarningsInDEV() { } } -function stopFinishedWorkLoopTimer() { - const didCompleteRoot = true; - stopWorkLoopTimer(interruptedBy, didCompleteRoot); - interruptedBy = null; -} - -function stopInterruptedWorkLoopTimer() { - // TODO: Track which fiber caused the interruption. - const didCompleteRoot = false; - stopWorkLoopTimer(interruptedBy, didCompleteRoot); - interruptedBy = null; -} - -function checkForInterruption( - fiberThatReceivedUpdate: Fiber, - updateExpirationTime: ExpirationTime, -) { - if ( - enableUserTimingAPI && - workInProgressRoot !== null && - updateExpirationTime > renderExpirationTime - ) { - interruptedBy = fiberThatReceivedUpdate; - } -} - let didWarnStateUpdateForUnmountedComponent: Set | null = null; function warnAboutUpdateOnUnmountedFiberInDEV(fiber) { if (__DEV__) { diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js deleted file mode 100644 index 08c569c23950..000000000000 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js +++ /dev/null @@ -1,683 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @emails react-core - * @jest-environment node - */ - -'use strict'; - -describe('ReactDebugFiberPerf', () => { - let React; - let ReactNoop; - let Scheduler; - let PropTypes; - - let root; - let activeMeasure; - let knownMarks; - let knownMeasures; - let comments; - - function resetFlamechart() { - root = { - children: [], - indent: -1, - markName: null, - label: null, - parent: null, - toString() { - return this.children.map(c => c.toString()).join('\n'); - }, - }; - activeMeasure = root; - knownMarks = new Set(); - knownMeasures = new Set(); - comments = []; - } - - function addComment(comment) { - comments.push(comment); - } - - function getFlameChart() { - // Make sure we unwind the measurement stack every time. - expect(activeMeasure.indent).toBe(-1); - expect(activeMeasure).toBe(root); - // We should always clean them up because browsers - // buffer user timing measurements forever. - expect(knownMarks.size).toBe(0); - expect(knownMeasures.size).toBe(0); - return root.toString(); - } - - function createUserTimingPolyfill() { - // This is not a true polyfill, but it gives us enough - // to capture measurements in a readable tree-like output. - // Reference: https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API - return { - mark(markName) { - const measure = { - children: [], - indent: activeMeasure.indent + 1, - markName: markName, - // Will be assigned on measure() call: - label: null, - parent: activeMeasure, - comments, - toString() { - return ( - [ - ...this.comments.map(c => ' '.repeat(this.indent) + '// ' + c), - ' '.repeat(this.indent) + this.label, - ...this.children.map(c => c.toString()), - ].join('\n') + - // Extra newline after each root reconciliation - (this.indent === 0 ? '\n' : '') - ); - }, - }; - comments = []; - // Step one level deeper - activeMeasure.children.push(measure); - activeMeasure = measure; - knownMarks.add(markName); - }, - // We don't use the overload with three arguments. - measure(label, markName) { - if (markName !== activeMeasure.markName) { - // Fail the test. - console.error( - 'Unexpected measure() call: "%s". Active mark is "%s".', - markName, - activeMeasure.markName, - ); - // This exception will be caught and ignored - // because in the real implementation, we don't want - // to spam the console due to a React bug. - throw new Error('Unexpected measure() call.'); - } - // Step one level up - activeMeasure.label = label; - activeMeasure = activeMeasure.parent; - knownMeasures.add(label); - }, - clearMarks(markName) { - if (markName === activeMeasure.markName) { - // Step one level up if we're in this measure - activeMeasure = activeMeasure.parent; - activeMeasure.children.length--; - } - knownMarks.delete(markName); - }, - clearMeasures(label) { - knownMeasures.delete(label); - }, - }; - } - - function Parent(props) { - return
{props.children}
; - } - - function Child(props) { - return
{props.children}
; - } - - beforeEach(() => { - jest.resetModules(); - resetFlamechart(); - global.performance = createUserTimingPolyfill(); - - require('shared/ReactFeatureFlags').enableUserTimingAPI = true; - require('shared/ReactFeatureFlags').enableProfilerTimer = false; - require('shared/ReactFeatureFlags').replayFailedUnitOfWorkWithInvokeGuardedCallback = false; - require('shared/ReactFeatureFlags').debugRenderPhaseSideEffectsForStrictMode = false; - require('scheduler/src/SchedulerFeatureFlags').enableProfiling = false; - - // Import after the polyfill is set up: - React = require('react'); - ReactNoop = require('react-noop-renderer'); - Scheduler = require('scheduler'); - PropTypes = require('prop-types'); - }); - - afterEach(() => { - delete global.performance; - }); - - it('measures a simple reconciliation', () => { - ReactNoop.render( - - - , - ); - addComment('Mount'); - expect(Scheduler).toFlushWithoutYielding(); - - ReactNoop.render( - - - , - ); - addComment('Update'); - expect(Scheduler).toFlushWithoutYielding(); - - ReactNoop.render(null); - addComment('Unmount'); - expect(Scheduler).toFlushWithoutYielding(); - - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('properly displays the forwardRef component in measurements', () => { - const AnonymousForwardRef = React.forwardRef((props, ref) => ( - - )); - const NamedForwardRef = React.forwardRef(function refForwarder(props, ref) { - return ; - }); - function notImportant(props, ref) { - return ; - } - notImportant.displayName = 'OverriddenName'; - const DisplayNamedForwardRef = React.forwardRef(notImportant); - - ReactNoop.render( - - - - - , - ); - addComment('Mount'); - expect(Scheduler).toFlushWithoutYielding(); - - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('does not include StrictMode or Profiler components in measurements', () => { - ReactNoop.render( - - - - - - - , - ); - addComment('Mount'); - expect(Scheduler).toFlushWithoutYielding(); - - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('does not include context provider or consumer in measurements', () => { - const {Consumer, Provider} = React.createContext(true); - - ReactNoop.render( - - - {value => } - - , - ); - addComment('Mount'); - expect(Scheduler).toFlushWithoutYielding(); - - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('skips parents during setState', () => { - class A extends React.Component { - render() { - return
{this.props.children}
; - } - } - - class B extends React.Component { - render() { - return
{this.props.children}
; - } - } - - let a; - let b; - ReactNoop.render( - - - - (a = inst)} /> - - - - (b = inst)} /> - - , - ); - expect(Scheduler).toFlushWithoutYielding(); - resetFlamechart(); - - a.setState({}); - b.setState({}); - addComment('Should include just A and B, no Parents'); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('warns on cascading renders from setState', () => { - class Cascading extends React.Component { - componentDidMount() { - this.setState({}); - } - render() { - return
{this.props.children}
; - } - } - - ReactNoop.render( - - - , - ); - addComment('Should print a warning'); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('warns on cascading renders from top-level render', () => { - class Cascading extends React.Component { - componentDidMount() { - ReactNoop.renderToRootWithID(, 'b'); - addComment('Scheduling another root from componentDidMount'); - } - render() { - return
{this.props.children}
; - } - } - - ReactNoop.renderToRootWithID(, 'a'); - addComment('Rendering the first root'); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('does not treat setState from cWM or cWRP as cascading', () => { - class NotCascading extends React.Component { - UNSAFE_componentWillMount() { - this.setState({}); - } - UNSAFE_componentWillReceiveProps() { - this.setState({}); - } - render() { - return
{this.props.children}
; - } - } - - ReactNoop.render( - - - , - ); - addComment('Should not print a warning'); - expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev( - [ - 'Using UNSAFE_componentWillMount in strict mode is not recommended', - 'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended', - ], - {withoutStack: true}, - ); - ReactNoop.render( - - - , - ); - addComment('Should not print a warning'); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('captures all lifecycles', () => { - class AllLifecycles extends React.Component { - static childContextTypes = { - foo: PropTypes.any, - }; - shouldComponentUpdate() { - return true; - } - getChildContext() { - return {foo: 42}; - } - UNSAFE_componentWillMount() {} - componentDidMount() {} - UNSAFE_componentWillReceiveProps() {} - UNSAFE_componentWillUpdate() {} - componentDidUpdate() {} - componentWillUnmount() {} - render() { - return
; - } - } - ReactNoop.render(); - addComment('Mount'); - expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev( - [ - 'Using UNSAFE_componentWillMount in strict mode is not recommended', - 'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended', - 'Using UNSAFE_componentWillUpdate in strict mode is not recommended', - 'Legacy context API has been detected within a strict-mode tree', - ], - {withoutStack: 3}, - ); - ReactNoop.render(); - addComment('Update'); - expect(Scheduler).toFlushWithoutYielding(); - ReactNoop.render(null); - addComment('Unmount'); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('measures deprioritized work', () => { - addComment('Flush the parent'); - ReactNoop.flushSync(() => { - ReactNoop.render( - - - , - ); - }); - addComment('Flush the child'); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('measures deferred work in chunks', () => { - class A extends React.Component { - render() { - Scheduler.unstable_yieldValue('A'); - return
{this.props.children}
; - } - } - - class B extends React.Component { - render() { - Scheduler.unstable_yieldValue('B'); - return
{this.props.children}
; - } - } - - class C extends React.Component { - render() { - Scheduler.unstable_yieldValue('C'); - return
{this.props.children}
; - } - } - - ReactNoop.render( - -
- - - - - - - - - , - ); - addComment('Start rendering through B'); - expect(Scheduler).toFlushAndYieldThrough(['A', 'B']); - addComment('Complete the rest'); - expect(Scheduler).toFlushAndYield(['C']); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('recovers from fatal errors', () => { - function Baddie() { - throw new Error('Game over'); - } - - ReactNoop.render( - - - , - ); - try { - addComment('Will fatal'); - expect(Scheduler).toFlushWithoutYielding(); - } catch (err) { - expect(err.message).toBe('Game over'); - } - ReactNoop.render( - - - , - ); - addComment('Will reconcile from a clean state'); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('recovers from caught errors', () => { - function Baddie() { - throw new Error('Game over'); - } - - function ErrorReport() { - return
; - } - - class Boundary extends React.Component { - state = {error: null}; - componentDidCatch(error) { - this.setState({error}); - } - render() { - if (this.state.error) { - return ; - } - return this.props.children; - } - } - - ReactNoop.render( - - - - - - - , - ); - addComment('Stop on Baddie and restart from Boundary'); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('deduplicates lifecycle names during commit to reduce overhead', () => { - class A extends React.Component { - componentDidUpdate() {} - render() { - return
; - } - } - - class B extends React.Component { - componentDidUpdate(prevProps) { - if (this.props.cascade && !prevProps.cascade) { - this.setState({}); - } - } - render() { - return
; - } - } - - ReactNoop.render( - - - - - - , - ); - expect(Scheduler).toFlushWithoutYielding(); - resetFlamechart(); - - ReactNoop.render( - - - - - - , - ); - addComment('The commit phase should mention A and B just once'); - expect(Scheduler).toFlushWithoutYielding(); - ReactNoop.render( - - - - - - , - ); - addComment("Because of deduplication, we don't know B was cascading,"); - addComment('but we should still see the warning for the commit phase.'); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('supports portals', () => { - const portalContainer = ReactNoop.getOrCreateRootContainer( - 'portalContainer', - ); - ReactNoop.render( - - {ReactNoop.createPortal(, portalContainer, null)} - , - ); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('supports memo', () => { - const MemoFoo = React.memo(function Foo() { - return
; - }); - ReactNoop.render( - - - , - ); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('supports Suspense and lazy', async () => { - function Spinner() { - return ; - } - - function fakeImport(result) { - return {default: result}; - } - - let resolve; - const LazyFoo = React.lazy( - () => - new Promise(r => { - resolve = r; - }), - ); - - // Initial render - ReactNoop.render( - - } /> - , - ); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - - // Update that suspends - ReactNoop.render( - - }> - - - , - ); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - - resolve( - fakeImport(function Foo() { - return
; - }), - ); - - await Promise.resolve(); - - ReactNoop.render( - - - - - , - ); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('does not schedule an extra callback if setState is called during a synchronous commit phase', () => { - class Component extends React.Component { - state = {step: 1}; - componentDidMount() { - this.setState({step: 2}); - } - render() { - return ; - } - } - ReactNoop.flushSync(() => { - ReactNoop.render(); - }); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('warns if an in-progress update is interrupted', () => { - function Foo() { - Scheduler.unstable_yieldValue('Foo'); - return ; - } - - ReactNoop.render(); - ReactNoop.flushNextYield(); - ReactNoop.flushSync(() => { - ReactNoop.render(); - }); - expect(Scheduler).toHaveYielded(['Foo']); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); - - it('warns if async work expires (starvation)', () => { - function Foo() { - return ; - } - - ReactNoop.render(); - ReactNoop.expire(6000); - expect(Scheduler).toFlushWithoutYielding(); - expect(getFlameChart()).toMatchSnapshot(); - }); -}); diff --git a/packages/react-reconciler/src/__tests__/__snapshots__/ReactIncrementalPerf-test.internal.js.snap b/packages/react-reconciler/src/__tests__/__snapshots__/ReactIncrementalPerf-test.internal.js.snap deleted file mode 100644 index b438a6f7e678..000000000000 --- a/packages/react-reconciler/src/__tests__/__snapshots__/ReactIncrementalPerf-test.internal.js.snap +++ /dev/null @@ -1,477 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ReactDebugFiberPerf captures all lifecycles 1`] = ` -"// Mount -⚛ (React Tree Reconciliation: Completed Root) - ⚛ AllLifecycles [mount] - ⚛ AllLifecycles.componentWillMount - ⚛ AllLifecycles.getChildContext - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 1 Total) - ⚛ AllLifecycles.componentDidMount - -// Update -⚛ (React Tree Reconciliation: Completed Root) - ⚛ AllLifecycles [update] - ⚛ AllLifecycles.componentWillReceiveProps - ⚛ AllLifecycles.shouldComponentUpdate - ⚛ AllLifecycles.componentWillUpdate - ⚛ AllLifecycles.getChildContext - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 2 Total) - ⚛ (Calling Lifecycle Methods: 2 Total) - ⚛ AllLifecycles.componentDidUpdate - -// Unmount -⚛ (React Tree Reconciliation: Completed Root) - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ AllLifecycles.componentWillUnmount - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf deduplicates lifecycle names during commit to reduce overhead 1`] = ` -"// The commit phase should mention A and B just once -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [update] - ⚛ A [update] - ⚛ B [update] - ⚛ A [update] - ⚛ B [update] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 9 Total) - ⚛ (Calling Lifecycle Methods: 9 Total) - ⚛ A.componentDidUpdate - ⚛ B.componentDidUpdate - -// Because of deduplication, we don't know B was cascading, -// but we should still see the warning for the commit phase. -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [update] - ⚛ A [update] - ⚛ B [update] - ⚛ A [update] - ⚛ B [update] - -⛔ (Committing Changes) Warning: Lifecycle hook scheduled a cascading update - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 9 Total) - ⚛ (Calling Lifecycle Methods: 9 Total) - ⚛ A.componentDidUpdate - ⚛ B.componentDidUpdate - -⚛ (React Tree Reconciliation: Completed Root) - ⚛ B [update] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 2 Total) - ⚛ (Calling Lifecycle Methods: 2 Total) - ⚛ B.componentDidUpdate -" -`; - -exports[`ReactDebugFiberPerf does not include StrictMode or Profiler components in measurements 1`] = ` -"// Mount -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Profiler [mount] - ⚛ Parent [mount] - ⚛ Child [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf does not include context provider or consumer in measurements 1`] = ` -"// Mount -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ Child [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf does not schedule an extra callback if setState is called during a synchronous commit phase 1`] = ` -"⚛ (React Tree Reconciliation: Completed Root) - ⚛ Component [mount] - -⛔ (Committing Changes) Warning: Lifecycle hook scheduled a cascading update - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 1 Total) - ⛔ Component.componentDidMount Warning: Scheduled a cascading update - -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Component [update] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 1 Total) -" -`; - -exports[`ReactDebugFiberPerf does not treat setState from cWM or cWRP as cascading 1`] = ` -"// Should not print a warning -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ NotCascading [mount] - ⚛ NotCascading.componentWillMount - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) - -// Should not print a warning -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [update] - ⚛ NotCascading [update] - ⚛ NotCascading.componentWillReceiveProps - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 2 Total) - ⚛ (Calling Lifecycle Methods: 2 Total) -" -`; - -exports[`ReactDebugFiberPerf measures a simple reconciliation 1`] = ` -"// Mount -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ Child [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) - -// Update -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [update] - ⚛ Child [update] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 2 Total) - ⚛ (Calling Lifecycle Methods: 2 Total) - -// Unmount -⚛ (React Tree Reconciliation: Completed Root) - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf measures deferred work in chunks 1`] = ` -"// Start rendering through B -⚛ (React Tree Reconciliation: Yielded) - ⚛ Parent [mount] - ⚛ A [mount] - ⚛ Child [mount] - ⚛ B [mount] - -// Complete the rest -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ B [mount] - ⚛ Child [mount] - ⚛ C [mount] - ⚛ Child [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf measures deprioritized work 1`] = ` -"// Flush the parent -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) - -// Flush the child -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Child [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf properly displays the forwardRef component in measurements 1`] = ` -"// Mount -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ ForwardRef [mount] - ⚛ Child [mount] - ⚛ ForwardRef(refForwarder) [mount] - ⚛ Child [mount] - ⚛ ForwardRef(OverriddenName) [mount] - ⚛ Child [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf recovers from caught errors 1`] = ` -"// Stop on Baddie and restart from Boundary -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⛔ Boundary [mount] Warning: An error was thrown inside this error boundary - ⚛ Parent [mount] - ⚛ Baddie [mount] - ⚛ Boundary [mount] - -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⛔ Boundary [mount] Warning: An error was thrown inside this error boundary - ⚛ Parent [mount] - ⚛ Baddie [mount] - ⚛ Boundary [mount] - -⛔ (Committing Changes) Warning: Lifecycle hook scheduled a cascading update - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 2 Total) - ⚛ (Calling Lifecycle Methods: 1 Total) - -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Boundary [update] - ⚛ ErrorReport [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf recovers from fatal errors 1`] = ` -"// Will fatal -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ Baddie [mount] - -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ Baddie [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 1 Total) - -// Will reconcile from a clean state -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ Child [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf skips parents during setState 1`] = ` -"// Should include just A and B, no Parents -⚛ (React Tree Reconciliation: Completed Root) - ⚛ A [update] - ⚛ B [update] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 2 Total) - ⚛ (Calling Lifecycle Methods: 2 Total) -" -`; - -exports[`ReactDebugFiberPerf supports Suspense and lazy 1`] = ` -"⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ Suspense [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf supports Suspense and lazy 2`] = ` -"⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ Suspense [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) - -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [update] - ⛔ Suspense [update] Warning: Rendering was suspended - ⚛ Suspense [update] - ⚛ Spinner [mount] -" -`; - -exports[`ReactDebugFiberPerf supports Suspense and lazy 3`] = ` -"⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ Suspense [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) - -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [update] - ⛔ Suspense [update] Warning: Rendering was suspended - ⚛ Suspense [update] - ⚛ Spinner [mount] - -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [update] - ⚛ Suspense [update] - ⚛ Foo [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 2 Total) - ⚛ (Calling Lifecycle Methods: 1 Total) -" -`; - -exports[`ReactDebugFiberPerf supports memo 1`] = ` -"⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ Foo [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf supports portals 1`] = ` -"⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ Child [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 2 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf warns if an in-progress update is interrupted 1`] = ` -"⚛ (React Tree Reconciliation: Yielded) - ⚛ Foo [mount] - -⛔ (React Tree Reconciliation: Completed Root) Warning: A top-level update interrupted the previous render - ⚛ Foo [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) - -⚛ (React Tree Reconciliation: Completed Root) - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 0 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf warns if async work expires (starvation) 1`] = ` -"⚛ (React Tree Reconciliation: Completed Root) - ⚛ Foo [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; - -exports[`ReactDebugFiberPerf warns on cascading renders from setState 1`] = ` -"// Should print a warning -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ Cascading [mount] - -⛔ (Committing Changes) Warning: Lifecycle hook scheduled a cascading update - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 2 Total) - ⚛ (Calling Lifecycle Methods: 1 Total) - ⛔ Cascading.componentDidMount Warning: Scheduled a cascading update - -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Cascading [update] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 1 Total) -" -`; - -exports[`ReactDebugFiberPerf warns on cascading renders from top-level render 1`] = ` -"// Rendering the first root -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Cascading [mount] - -⛔ (Committing Changes) Warning: Lifecycle hook scheduled a cascading update - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 1 Total) - ⛔ Cascading.componentDidMount Warning: Scheduled a cascading update - -// Scheduling another root from componentDidMount -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Child [mount] - -⚛ (Committing Changes) - ⚛ (Committing Snapshot Effects: 0 Total) - ⚛ (Committing Host Effects: 1 Total) - ⚛ (Calling Lifecycle Methods: 0 Total) -" -`; diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 650e24529098..cc1688e076de 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -7,8 +7,6 @@ * @flow strict */ -export const enableUserTimingAPI = __DEV__; - // Helps identify side effects in render-phase lifecycle hooks and setState // reducers by double invoking them in Strict Mode. export const debugRenderPhaseSideEffectsForStrictMode = __DEV__; @@ -39,11 +37,6 @@ export const enableBlocksAPI = __EXPERIMENTAL__; // Only used in www builds. export const enableSchedulerDebugging = false; -// Only used in www builds. -export function addUserTimingListener() { - throw new Error('Not implemented.'); -} - // Disable javascript: URL strings in href for XSS protection. export const disableJavaScriptURLs = false; diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index c70c777cfd9c..10f458679512 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -7,13 +7,10 @@ * @flow */ -import invariant from 'shared/invariant'; - import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags'; import typeof * as ExportsType from './ReactFeatureFlags.native-fb'; // The rest of the flags are static for better dead code elimination. -export const enableUserTimingAPI = __DEV__; export const enableProfilerTimer = __PROFILE__; export const enableProfilerCommitHooks = false; export const enableSchedulerTracing = __PROFILE__; @@ -54,11 +51,6 @@ export const throwEarlyForMysteriousError = true; export const enableNewReconciler = false; -// Only used in www builds. -export function addUserTimingListener() { - invariant(false, 'Not implemented.'); -} - // Flow magic to verify the exports of this file match the original version. // eslint-disable-next-line no-unused-vars type Check<_X, Y: _X, X: Y = _X> = null; diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index 61527ea6db69..2c01721d51d9 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -7,13 +7,10 @@ * @flow */ -import invariant from 'shared/invariant'; - import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags'; import typeof * as ExportsType from './ReactFeatureFlags.native-oss'; export const debugRenderPhaseSideEffectsForStrictMode = false; -export const enableUserTimingAPI = __DEV__; export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__; export const warnAboutDeprecatedLifecycles = true; export const enableProfilerTimer = __PROFILE__; @@ -53,11 +50,6 @@ export const throwEarlyForMysteriousError = false; export const enableNewReconciler = false; -// Only used in www builds. -export function addUserTimingListener() { - invariant(false, 'Not implemented.'); -} - // Flow magic to verify the exports of this file match the original version. // eslint-disable-next-line no-unused-vars type Check<_X, Y: _X, X: Y = _X> = null; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index ffc66b7acc8a..4ca1a4a381e6 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -7,13 +7,10 @@ * @flow */ -import invariant from 'shared/invariant'; - import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags'; import typeof * as ExportsType from './ReactFeatureFlags.test-renderer'; export const debugRenderPhaseSideEffectsForStrictMode = false; -export const enableUserTimingAPI = __DEV__; export const warnAboutDeprecatedLifecycles = true; export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false; export const enableProfilerTimer = __PROFILE__; @@ -53,11 +50,6 @@ export const throwEarlyForMysteriousError = false; export const enableNewReconciler = false; -// Only used in www builds. -export function addUserTimingListener() { - invariant(false, 'Not implemented.'); -} - // Flow magic to verify the exports of this file match the original version. // eslint-disable-next-line no-unused-vars type Check<_X, Y: _X, X: Y = _X> = null; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index 6734118d0a77..85859e15ffb5 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -7,13 +7,10 @@ * @flow */ -import invariant from 'shared/invariant'; - import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags'; import typeof * as ExportsType from './ReactFeatureFlags.test-renderer.www'; export const debugRenderPhaseSideEffectsForStrictMode = false; -export const enableUserTimingAPI = __DEV__; export const warnAboutDeprecatedLifecycles = true; export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false; export const enableProfilerTimer = __PROFILE__; @@ -53,11 +50,6 @@ export const throwEarlyForMysteriousError = false; export const enableNewReconciler = false; -// Only used in www builds. -export function addUserTimingListener() { - invariant(false, 'Not implemented.'); -} - // Flow magic to verify the exports of this file match the original version. // eslint-disable-next-line no-unused-vars type Check<_X, Y: _X, X: Y = _X> = null; diff --git a/packages/shared/forks/ReactFeatureFlags.testing.js b/packages/shared/forks/ReactFeatureFlags.testing.js index 6b279bc8a6a3..88386e30a679 100644 --- a/packages/shared/forks/ReactFeatureFlags.testing.js +++ b/packages/shared/forks/ReactFeatureFlags.testing.js @@ -7,13 +7,10 @@ * @flow */ -import invariant from 'shared/invariant'; - import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags'; import typeof * as ExportsType from './ReactFeatureFlags.testing'; export const debugRenderPhaseSideEffectsForStrictMode = false; -export const enableUserTimingAPI = __DEV__; export const warnAboutDeprecatedLifecycles = true; export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false; export const enableProfilerTimer = __PROFILE__; @@ -53,11 +50,6 @@ export const throwEarlyForMysteriousError = false; export const enableNewReconciler = false; -// Only used in www builds. -export function addUserTimingListener() { - invariant(false, 'Not implemented.'); -} - // Flow magic to verify the exports of this file match the original version. // eslint-disable-next-line no-unused-vars type Check<_X, Y: _X, X: Y = _X> = null; diff --git a/packages/shared/forks/ReactFeatureFlags.testing.www.js b/packages/shared/forks/ReactFeatureFlags.testing.www.js index afdacac78719..0e01547c769f 100644 --- a/packages/shared/forks/ReactFeatureFlags.testing.www.js +++ b/packages/shared/forks/ReactFeatureFlags.testing.www.js @@ -7,13 +7,10 @@ * @flow */ -import invariant from 'shared/invariant'; - import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags'; import typeof * as ExportsType from './ReactFeatureFlags.testing.www'; export const debugRenderPhaseSideEffectsForStrictMode = false; -export const enableUserTimingAPI = false; export const warnAboutDeprecatedLifecycles = true; export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false; export const enableProfilerTimer = false; @@ -53,11 +50,6 @@ export const throwEarlyForMysteriousError = false; export const enableNewReconciler = false; -// Only used in www builds. -export function addUserTimingListener() { - invariant(false, 'Not implemented.'); -} - // Flow magic to verify the exports of this file match the original version. // eslint-disable-next-line no-unused-vars type Check<_X, Y: _X, X: Y = _X> = null; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index d424e40b3dfb..5190aa0d4d4b 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -30,14 +30,6 @@ export const { // On WWW, __EXPERIMENTAL__ is used for a new modern build. // It's not used anywhere in production yet. -// In www, we have experimental support for gathering data -// from User Timing API calls in production. By default, we -// only emit performance.mark/measure calls in __DEV__. But if -// somebody calls addUserTimingListener() which is exposed as an -// experimental FB-only export, we call performance.mark/measure -// as long as there is more than a single listener. -export let enableUserTimingAPI = __DEV__ && !__EXPERIMENTAL__; - export const enableProfilerTimer = __PROFILE__; export const enableProfilerCommitHooks = __PROFILE__; @@ -59,33 +51,6 @@ export const enableBlocksAPI = true; export const disableJavaScriptURLs = true; -let refCount = 0; -export function addUserTimingListener() { - if (__DEV__) { - // Noop. - return () => {}; - } - refCount++; - updateFlagOutsideOfReactCallStack(); - return () => { - refCount--; - updateFlagOutsideOfReactCallStack(); - }; -} - -// The flag is intentionally updated in a timeout. -// We don't support toggling it during reconciliation or -// commit since that would cause mismatching user timing API calls. -let timeout = null; -function updateFlagOutsideOfReactCallStack() { - if (!timeout) { - timeout = setTimeout(() => { - timeout = null; - enableUserTimingAPI = refCount > 0; - }); - } -} - export const enableDeprecatedFlareAPI = true; export const enableFundamentalAPI = false; diff --git a/scripts/jest/setupTests.www.js b/scripts/jest/setupTests.www.js index f57f2b383e30..73a3f8769475 100644 --- a/scripts/jest/setupTests.www.js +++ b/scripts/jest/setupTests.www.js @@ -15,7 +15,6 @@ jest.mock('shared/ReactFeatureFlags', () => { // configuration, too. Then remove these overrides. wwwFlags.disableLegacyContext = defaultFlags.disableLegacyContext; wwwFlags.warnAboutUnmockedScheduler = defaultFlags.warnAboutUnmockedScheduler; - wwwFlags.enableUserTimingAPI = defaultFlags.enableUserTimingAPI; wwwFlags.disableJavaScriptURLs = defaultFlags.disableJavaScriptURLs; wwwFlags.enableDeprecatedFlareAPI = defaultFlags.enableDeprecatedFlareAPI; wwwFlags.disableModulePatternComponents =