diff --git a/packages/react-devtools-shared/src/backend/profilingHooks.js b/packages/react-devtools-shared/src/backend/profilingHooks.js index 48f090bf72c02..ca58cf655ce53 100644 --- a/packages/react-devtools-shared/src/backend/profilingHooks.js +++ b/packages/react-devtools-shared/src/backend/profilingHooks.js @@ -298,14 +298,16 @@ export function createProfilingHooks({ } function markCommitStarted(lanes: Lanes): void { - if (isProfiling) { - recordReactMeasureStarted('commit', lanes); - - // TODO (timeline) Re-think this approach to "batching"; I don't think it works for Suspense or pre-rendering. - // This issue applies to the User Timing data also. - nextRenderShouldStartNewBatch = true; + if (!isProfiling) { + return; } + recordReactMeasureStarted('commit', lanes); + + // TODO (timeline) Re-think this approach to "batching"; I don't think it works for Suspense or pre-rendering. + // This issue applies to the User Timing data also. + nextRenderShouldStartNewBatch = true; + if (supportsUserTimingV3) { markAndClear(`--commit-start-${lanes}`); @@ -318,50 +320,55 @@ export function createProfilingHooks({ } function markCommitStopped(): void { - if (isProfiling) { - recordReactMeasureCompleted('commit'); - recordReactMeasureCompleted('render-idle'); + if (!isProfiling) { + return; } + recordReactMeasureCompleted('commit'); + recordReactMeasureCompleted('render-idle'); if (supportsUserTimingV3) { markAndClear('--commit-stop'); } } function markComponentRenderStarted(fiber: Fiber): void { - if (isProfiling) { - const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; + if (!isProfiling) { + return; + } - // TODO (timeline) Record and cache component stack - currentReactComponentMeasure = { - componentName, - duration: 0, - timestamp: getRelativeTime(), - type: 'render', - warning: null, - }; + const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; - if (supportsUserTimingV3) { - markAndClear(`--component-render-start-${componentName}`); - } + // TODO (timeline) Record and cache component stack + currentReactComponentMeasure = { + componentName, + duration: 0, + timestamp: getRelativeTime(), + type: 'render', + warning: null, + }; + + if (supportsUserTimingV3) { + markAndClear(`--component-render-start-${componentName}`); } } function markComponentRenderStopped(): void { - if (isProfiling) { - if (currentReactComponentMeasure) { - if (currentTimelineData) { - currentTimelineData.componentMeasures.push( - currentReactComponentMeasure, - ); - } + if (!isProfiling) { + return; + } - // $FlowFixMe[incompatible-use] found when upgrading Flow - currentReactComponentMeasure.duration = - // $FlowFixMe[incompatible-use] found when upgrading Flow - getRelativeTime() - currentReactComponentMeasure.timestamp; - currentReactComponentMeasure = null; + if (currentReactComponentMeasure) { + if (currentTimelineData) { + currentTimelineData.componentMeasures.push( + currentReactComponentMeasure, + ); } + + // $FlowFixMe[incompatible-use] found when upgrading Flow + currentReactComponentMeasure.duration = + // $FlowFixMe[incompatible-use] found when upgrading Flow + getRelativeTime() - currentReactComponentMeasure.timestamp; + currentReactComponentMeasure = null; } if (supportsUserTimingV3) { @@ -370,39 +377,43 @@ export function createProfilingHooks({ } function markComponentLayoutEffectMountStarted(fiber: Fiber): void { - if (isProfiling) { - const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; + if (!isProfiling) { + return; + } - // TODO (timeline) Record and cache component stack - currentReactComponentMeasure = { - componentName, - duration: 0, - timestamp: getRelativeTime(), - type: 'layout-effect-mount', - warning: null, - }; + const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; - if (supportsUserTimingV3) { - markAndClear(`--component-layout-effect-mount-start-${componentName}`); - } + // TODO (timeline) Record and cache component stack + currentReactComponentMeasure = { + componentName, + duration: 0, + timestamp: getRelativeTime(), + type: 'layout-effect-mount', + warning: null, + }; + + if (supportsUserTimingV3) { + markAndClear(`--component-layout-effect-mount-start-${componentName}`); } } function markComponentLayoutEffectMountStopped(): void { - if (isProfiling) { - if (currentReactComponentMeasure) { - if (currentTimelineData) { - currentTimelineData.componentMeasures.push( - currentReactComponentMeasure, - ); - } + if (!isProfiling) { + return; + } - // $FlowFixMe[incompatible-use] found when upgrading Flow - currentReactComponentMeasure.duration = - // $FlowFixMe[incompatible-use] found when upgrading Flow - getRelativeTime() - currentReactComponentMeasure.timestamp; - currentReactComponentMeasure = null; + if (currentReactComponentMeasure) { + if (currentTimelineData) { + currentTimelineData.componentMeasures.push( + currentReactComponentMeasure, + ); } + + // $FlowFixMe[incompatible-use] found when upgrading Flow + currentReactComponentMeasure.duration = + // $FlowFixMe[incompatible-use] found when upgrading Flow + getRelativeTime() - currentReactComponentMeasure.timestamp; + currentReactComponentMeasure = null; } if (supportsUserTimingV3) { @@ -411,41 +422,43 @@ export function createProfilingHooks({ } function markComponentLayoutEffectUnmountStarted(fiber: Fiber): void { - if (isProfiling) { - const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; + if (!isProfiling) { + return; + } - // TODO (timeline) Record and cache component stack - currentReactComponentMeasure = { - componentName, - duration: 0, - timestamp: getRelativeTime(), - type: 'layout-effect-unmount', - warning: null, - }; + const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; - if (supportsUserTimingV3) { - markAndClear( - `--component-layout-effect-unmount-start-${componentName}`, - ); - } + // TODO (timeline) Record and cache component stack + currentReactComponentMeasure = { + componentName, + duration: 0, + timestamp: getRelativeTime(), + type: 'layout-effect-unmount', + warning: null, + }; + + if (supportsUserTimingV3) { + markAndClear(`--component-layout-effect-unmount-start-${componentName}`); } } function markComponentLayoutEffectUnmountStopped(): void { - if (isProfiling) { - if (currentReactComponentMeasure) { - if (currentTimelineData) { - currentTimelineData.componentMeasures.push( - currentReactComponentMeasure, - ); - } + if (!isProfiling) { + return; + } - // $FlowFixMe[incompatible-use] found when upgrading Flow - currentReactComponentMeasure.duration = - // $FlowFixMe[incompatible-use] found when upgrading Flow - getRelativeTime() - currentReactComponentMeasure.timestamp; - currentReactComponentMeasure = null; + if (currentReactComponentMeasure) { + if (currentTimelineData) { + currentTimelineData.componentMeasures.push( + currentReactComponentMeasure, + ); } + + // $FlowFixMe[incompatible-use] found when upgrading Flow + currentReactComponentMeasure.duration = + // $FlowFixMe[incompatible-use] found when upgrading Flow + getRelativeTime() - currentReactComponentMeasure.timestamp; + currentReactComponentMeasure = null; } if (supportsUserTimingV3) { @@ -454,39 +467,43 @@ export function createProfilingHooks({ } function markComponentPassiveEffectMountStarted(fiber: Fiber): void { - if (isProfiling) { - const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; + if (!isProfiling) { + return; + } - // TODO (timeline) Record and cache component stack - currentReactComponentMeasure = { - componentName, - duration: 0, - timestamp: getRelativeTime(), - type: 'passive-effect-mount', - warning: null, - }; + const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; - if (supportsUserTimingV3) { - markAndClear(`--component-passive-effect-mount-start-${componentName}`); - } + // TODO (timeline) Record and cache component stack + currentReactComponentMeasure = { + componentName, + duration: 0, + timestamp: getRelativeTime(), + type: 'passive-effect-mount', + warning: null, + }; + + if (supportsUserTimingV3) { + markAndClear(`--component-passive-effect-mount-start-${componentName}`); } } function markComponentPassiveEffectMountStopped(): void { - if (isProfiling) { - if (currentReactComponentMeasure) { - if (currentTimelineData) { - currentTimelineData.componentMeasures.push( - currentReactComponentMeasure, - ); - } + if (!isProfiling) { + return; + } - // $FlowFixMe[incompatible-use] found when upgrading Flow - currentReactComponentMeasure.duration = - // $FlowFixMe[incompatible-use] found when upgrading Flow - getRelativeTime() - currentReactComponentMeasure.timestamp; - currentReactComponentMeasure = null; + if (currentReactComponentMeasure) { + if (currentTimelineData) { + currentTimelineData.componentMeasures.push( + currentReactComponentMeasure, + ); } + + // $FlowFixMe[incompatible-use] found when upgrading Flow + currentReactComponentMeasure.duration = + // $FlowFixMe[incompatible-use] found when upgrading Flow + getRelativeTime() - currentReactComponentMeasure.timestamp; + currentReactComponentMeasure = null; } if (supportsUserTimingV3) { @@ -495,41 +512,43 @@ export function createProfilingHooks({ } function markComponentPassiveEffectUnmountStarted(fiber: Fiber): void { - if (isProfiling) { - const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; + if (!isProfiling) { + return; + } - // TODO (timeline) Record and cache component stack - currentReactComponentMeasure = { - componentName, - duration: 0, - timestamp: getRelativeTime(), - type: 'passive-effect-unmount', - warning: null, - }; + const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; - if (supportsUserTimingV3) { - markAndClear( - `--component-passive-effect-unmount-start-${componentName}`, - ); - } + // TODO (timeline) Record and cache component stack + currentReactComponentMeasure = { + componentName, + duration: 0, + timestamp: getRelativeTime(), + type: 'passive-effect-unmount', + warning: null, + }; + + if (supportsUserTimingV3) { + markAndClear(`--component-passive-effect-unmount-start-${componentName}`); } } function markComponentPassiveEffectUnmountStopped(): void { - if (isProfiling) { - if (currentReactComponentMeasure) { - if (currentTimelineData) { - currentTimelineData.componentMeasures.push( - currentReactComponentMeasure, - ); - } + if (!isProfiling) { + return; + } - // $FlowFixMe[incompatible-use] found when upgrading Flow - currentReactComponentMeasure.duration = - // $FlowFixMe[incompatible-use] found when upgrading Flow - getRelativeTime() - currentReactComponentMeasure.timestamp; - currentReactComponentMeasure = null; + if (currentReactComponentMeasure) { + if (currentTimelineData) { + currentTimelineData.componentMeasures.push( + currentReactComponentMeasure, + ); } + + // $FlowFixMe[incompatible-use] found when upgrading Flow + currentReactComponentMeasure.duration = + // $FlowFixMe[incompatible-use] found when upgrading Flow + getRelativeTime() - currentReactComponentMeasure.timestamp; + currentReactComponentMeasure = null; } if (supportsUserTimingV3) { @@ -542,35 +561,37 @@ export function createProfilingHooks({ thrownValue: mixed, lanes: Lanes, ): void { - if (isProfiling) { - const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; - const phase = fiber.alternate === null ? 'mount' : 'update'; - - let message = ''; - if ( - thrownValue !== null && - typeof thrownValue === 'object' && - typeof thrownValue.message === 'string' - ) { - message = thrownValue.message; - } else if (typeof thrownValue === 'string') { - message = thrownValue; - } + if (!isProfiling) { + return; + } - // TODO (timeline) Record and cache component stack - if (currentTimelineData) { - currentTimelineData.thrownErrors.push({ - componentName, - message, - phase, - timestamp: getRelativeTime(), - type: 'thrown-error', - }); - } + const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; + const phase = fiber.alternate === null ? 'mount' : 'update'; - if (supportsUserTimingV3) { - markAndClear(`--error-${componentName}-${phase}-${message}`); - } + let message = ''; + if ( + thrownValue !== null && + typeof thrownValue === 'object' && + typeof thrownValue.message === 'string' + ) { + message = thrownValue.message; + } else if (typeof thrownValue === 'string') { + message = thrownValue; + } + + // TODO (timeline) Record and cache component stack + if (currentTimelineData) { + currentTimelineData.thrownErrors.push({ + componentName, + message, + phase, + timestamp: getRelativeTime(), + type: 'thrown-error', + }); + } + + if (supportsUserTimingV3) { + markAndClear(`--error-${componentName}-${phase}-${message}`); } } @@ -591,165 +612,176 @@ export function createProfilingHooks({ wakeable: Wakeable, lanes: Lanes, ): void { - if (isProfiling) { - const eventType = wakeableIDs.has(wakeable) ? 'resuspend' : 'suspend'; - const id = getWakeableID(wakeable); - const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; - const phase = fiber.alternate === null ? 'mount' : 'update'; - - // Following the non-standard fn.displayName convention, - // frameworks like Relay may also annotate Promises with a displayName, - // describing what operation/data the thrown Promise is related to. - // When this is available we should pass it along to the Timeline. - const displayName = (wakeable: any).displayName || ''; - - let suspenseEvent: SuspenseEvent | null = null; - // TODO (timeline) Record and cache component stack - suspenseEvent = { - componentName, - depth: 0, - duration: 0, - id: `${id}`, - phase, - promiseName: displayName, - resolution: 'unresolved', - timestamp: getRelativeTime(), - type: 'suspense', - warning: null, - }; + if (!isProfiling) { + return; + } - if (currentTimelineData) { - currentTimelineData.suspenseEvents.push(suspenseEvent); - } + const eventType = wakeableIDs.has(wakeable) ? 'resuspend' : 'suspend'; + const id = getWakeableID(wakeable); + const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; + const phase = fiber.alternate === null ? 'mount' : 'update'; - if (supportsUserTimingV3) { - markAndClear( - `--suspense-${eventType}-${id}-${componentName}-${phase}-${lanes}-${displayName}`, - ); + // Following the non-standard fn.displayName convention, + // frameworks like Relay may also annotate Promises with a displayName, + // describing what operation/data the thrown Promise is related to. + // When this is available we should pass it along to the Timeline. + const displayName = (wakeable: any).displayName || ''; - wakeable.then( - () => { - if (suspenseEvent) { - suspenseEvent.duration = - getRelativeTime() - suspenseEvent.timestamp; - suspenseEvent.resolution = 'resolved'; - } + let suspenseEvent: SuspenseEvent | null = null; + // TODO (timeline) Record and cache component stack + suspenseEvent = { + componentName, + depth: 0, + duration: 0, + id: `${id}`, + phase, + promiseName: displayName, + resolution: 'unresolved', + timestamp: getRelativeTime(), + type: 'suspense', + warning: null, + }; - if (supportsUserTimingV3) { - markAndClear(`--suspense-resolved-${id}-${componentName}`); - } - }, - () => { - if (suspenseEvent) { - suspenseEvent.duration = - getRelativeTime() - suspenseEvent.timestamp; - suspenseEvent.resolution = 'rejected'; - } + if (currentTimelineData) { + currentTimelineData.suspenseEvents.push(suspenseEvent); + } - if (supportsUserTimingV3) { - markAndClear(`--suspense-rejected-${id}-${componentName}`); - } - }, - ); - } + if (supportsUserTimingV3) { + markAndClear( + `--suspense-${eventType}-${id}-${componentName}-${phase}-${lanes}-${displayName}`, + ); + + wakeable.then( + () => { + if (suspenseEvent) { + suspenseEvent.duration = + getRelativeTime() - suspenseEvent.timestamp; + suspenseEvent.resolution = 'resolved'; + } + + if (supportsUserTimingV3) { + markAndClear(`--suspense-resolved-${id}-${componentName}`); + } + }, + () => { + if (suspenseEvent) { + suspenseEvent.duration = + getRelativeTime() - suspenseEvent.timestamp; + suspenseEvent.resolution = 'rejected'; + } + + if (supportsUserTimingV3) { + markAndClear(`--suspense-rejected-${id}-${componentName}`); + } + }, + ); } } function markLayoutEffectsStarted(lanes: Lanes): void { - if (isProfiling) { - recordReactMeasureStarted('layout-effects', lanes); + if (!isProfiling) { + return; } + recordReactMeasureStarted('layout-effects', lanes); if (supportsUserTimingV3) { markAndClear(`--layout-effects-start-${lanes}`); } } function markLayoutEffectsStopped(): void { - if (isProfiling) { - recordReactMeasureCompleted('layout-effects'); + if (!isProfiling) { + return; } + recordReactMeasureCompleted('layout-effects'); if (supportsUserTimingV3) { markAndClear('--layout-effects-stop'); } } function markPassiveEffectsStarted(lanes: Lanes): void { - if (isProfiling) { - recordReactMeasureStarted('passive-effects', lanes); + if (!isProfiling) { + return; } + recordReactMeasureStarted('passive-effects', lanes); if (supportsUserTimingV3) { markAndClear(`--passive-effects-start-${lanes}`); } } function markPassiveEffectsStopped(): void { - if (isProfiling) { - recordReactMeasureCompleted('passive-effects'); + if (!isProfiling) { + return; } + recordReactMeasureCompleted('passive-effects'); if (supportsUserTimingV3) { markAndClear('--passive-effects-stop'); } } function markRenderStarted(lanes: Lanes): void { - if (isProfiling) { - if (nextRenderShouldStartNewBatch) { - nextRenderShouldStartNewBatch = false; - currentBatchUID++; - } + if (!isProfiling) { + return; + } - // If this is a new batch of work, wrap an "idle" measure around it. - // Log it before the "render" measure to preserve the stack ordering. - if ( - currentReactMeasuresStack.length === 0 || - currentReactMeasuresStack[currentReactMeasuresStack.length - 1].type !== - 'render-idle' - ) { - recordReactMeasureStarted('render-idle', lanes); - } + if (nextRenderShouldStartNewBatch) { + nextRenderShouldStartNewBatch = false; + currentBatchUID++; + } - recordReactMeasureStarted('render', lanes); + // If this is a new batch of work, wrap an "idle" measure around it. + // Log it before the "render" measure to preserve the stack ordering. + if ( + currentReactMeasuresStack.length === 0 || + currentReactMeasuresStack[currentReactMeasuresStack.length - 1].type !== + 'render-idle' + ) { + recordReactMeasureStarted('render-idle', lanes); } + recordReactMeasureStarted('render', lanes); if (supportsUserTimingV3) { markAndClear(`--render-start-${lanes}`); } } function markRenderYielded(): void { - if (isProfiling) { - recordReactMeasureCompleted('render'); + if (!isProfiling) { + return; } + recordReactMeasureCompleted('render'); if (supportsUserTimingV3) { markAndClear('--render-yield'); } } function markRenderStopped(): void { - if (isProfiling) { - recordReactMeasureCompleted('render'); + if (!isProfiling) { + return; } + recordReactMeasureCompleted('render'); if (supportsUserTimingV3) { markAndClear('--render-stop'); } } function markRenderScheduled(lane: Lane): void { - if (isProfiling) { - if (currentTimelineData) { - currentTimelineData.schedulingEvents.push({ - lanes: laneToLanesArray(lane), - timestamp: getRelativeTime(), - type: 'schedule-render', - warning: null, - }); - } + if (!isProfiling) { + return; + } + + if (currentTimelineData) { + currentTimelineData.schedulingEvents.push({ + lanes: laneToLanesArray(lane), + timestamp: getRelativeTime(), + type: 'schedule-render', + warning: null, + }); } if (supportsUserTimingV3) { @@ -758,23 +790,25 @@ export function createProfilingHooks({ } function markForceUpdateScheduled(fiber: Fiber, lane: Lane): void { - if (isProfiling) { - const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; + if (!isProfiling) { + return; + } - // TODO (timeline) Record and cache component stack - if (currentTimelineData) { - currentTimelineData.schedulingEvents.push({ - componentName, - lanes: laneToLanesArray(lane), - timestamp: getRelativeTime(), - type: 'schedule-force-update', - warning: null, - }); - } + const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; - if (supportsUserTimingV3) { - markAndClear(`--schedule-forced-update-${lane}-${componentName}`); - } + // TODO (timeline) Record and cache component stack + if (currentTimelineData) { + currentTimelineData.schedulingEvents.push({ + componentName, + lanes: laneToLanesArray(lane), + timestamp: getRelativeTime(), + type: 'schedule-force-update', + warning: null, + }); + } + + if (supportsUserTimingV3) { + markAndClear(`--schedule-forced-update-${lane}-${componentName}`); } } @@ -789,28 +823,30 @@ export function createProfilingHooks({ } function markStateUpdateScheduled(fiber: Fiber, lane: Lane): void { - if (isProfiling) { - const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; + if (!isProfiling) { + return; + } - // TODO (timeline) Record and cache component stack - if (currentTimelineData) { - const event: ReactScheduleStateUpdateEvent = { - componentName, - // Store the parent fibers so we can post process - // them after we finish profiling - lanes: laneToLanesArray(lane), - timestamp: getRelativeTime(), - type: 'schedule-state-update', - warning: null, - }; - currentFiberStacks.set(event, getParentFibers(fiber)); - // $FlowFixMe[incompatible-use] found when upgrading Flow - currentTimelineData.schedulingEvents.push(event); - } + const componentName = getDisplayNameForFiber(fiber) || 'Unknown'; - if (supportsUserTimingV3) { - markAndClear(`--schedule-state-update-${lane}-${componentName}`); - } + // TODO (timeline) Record and cache component stack + if (currentTimelineData) { + const event: ReactScheduleStateUpdateEvent = { + componentName, + // Store the parent fibers so we can post process + // them after we finish profiling + lanes: laneToLanesArray(lane), + timestamp: getRelativeTime(), + type: 'schedule-state-update', + warning: null, + }; + currentFiberStacks.set(event, getParentFibers(fiber)); + // $FlowFixMe[incompatible-use] found when upgrading Flow + currentTimelineData.schedulingEvents.push(event); + } + + if (supportsUserTimingV3) { + markAndClear(`--schedule-state-update-${lane}-${componentName}`); } }