diff --git a/src/backend/renderer.js b/src/backend/renderer.js index c4e515829b..3b029be297 100644 --- a/src/backend/renderer.js +++ b/src/backend/renderer.js @@ -28,17 +28,17 @@ import { getUID } from '../utils'; import { inspectHooksOfFiber } from './ReactDebugHooks'; import type { - CommitDetails, + CommitDetailsBackend, DevToolsHook, Fiber, - FiberCommits, + FiberCommitsBackend, FiberData, - Interaction, - Interactions, - InteractionWithCommits, + InteractionBackend, + InteractionsBackend, + InteractionWithCommitsBackend, PathFrame, PathMatch, - ProfilingSummary, + ProfilingSummaryBackend, ReactRenderer, RendererInterface, } from './types'; @@ -1160,7 +1160,7 @@ export function attach( actualDurations: [], commitTime: performance.now() - profilingStartTime, interactions: Array.from(root.memoizedInteractions).map( - (interaction: Interaction) => ({ + (interaction: InteractionBackend) => ({ ...interaction, timestamp: interaction.timestamp - profilingStartTime, }) @@ -1202,7 +1202,7 @@ export function attach( actualDurations: [], commitTime: performance.now() - profilingStartTime, interactions: Array.from(root.memoizedInteractions).map( - (interaction: Interaction) => ({ + (interaction: InteractionBackend) => ({ ...interaction, timestamp: interaction.timestamp - profilingStartTime, }) @@ -1789,7 +1789,7 @@ export function attach( type CommitProfilingData = {| actualDurations: Array, commitTime: number, - interactions: Array, + interactions: Array, maxActualDuration: number, |}; @@ -1805,7 +1805,7 @@ export function attach( function getCommitDetails( rootID: number, commitIndex: number - ): CommitDetails { + ): CommitDetailsBackend { const commitProfilingMetadata = ((rootToCommitProfilingMetadataMap: any): CommitProfilingMetadataMap).get( rootID ); @@ -1833,7 +1833,10 @@ export function attach( }; } - function getFiberCommits(rootID: number, fiberID: number): FiberCommits { + function getFiberCommits( + rootID: number, + fiberID: number + ): FiberCommitsBackend { const commitProfilingMetadata = ((rootToCommitProfilingMetadataMap: any): CommitProfilingMetadataMap).get( rootID ); @@ -1866,12 +1869,15 @@ export function attach( }; } - function getInteractions(rootID: number): Interactions { + function getInteractions(rootID: number): InteractionsBackend { const commitProfilingMetadata = ((rootToCommitProfilingMetadataMap: any): CommitProfilingMetadataMap).get( rootID ); if (commitProfilingMetadata != null) { - const interactionsMap: Map = new Map(); + const interactionsMap: Map< + number, + InteractionWithCommitsBackend + > = new Map(); commitProfilingMetadata.forEach((commitProfilingData, commitIndex) => { commitProfilingData.interactions.forEach(interaction => { @@ -1921,7 +1927,7 @@ export function attach( }; } - function getProfilingSummary(rootID: number): ProfilingSummary { + function getProfilingSummary(rootID: number): ProfilingSummaryBackend { const interactions = new Set(); const commitDurations = []; const commitTimes = []; diff --git a/src/backend/types.js b/src/backend/types.js index 0bd1648233..d1946d164a 100644 --- a/src/backend/types.js +++ b/src/backend/types.js @@ -53,36 +53,36 @@ export type ReactRenderer = { currentDispatcherRef?: {| current: null | Dispatcher |}, }; -export type Interaction = {| +export type InteractionBackend = {| id: number, name: string, timestamp: number, |}; -export type CommitDetails = {| +export type CommitDetailsBackend = {| actualDurations: Array, commitIndex: number, - interactions: Array, + interactions: Array, rootID: number, |}; -export type FiberCommits = {| +export type FiberCommitsBackend = {| commitDurations: Array, fiberID: number, rootID: number, |}; -export type InteractionWithCommits = {| - ...Interaction, +export type InteractionWithCommitsBackend = {| + ...InteractionBackend, commits: Array, |}; -export type Interactions = {| - interactions: Array, +export type InteractionsBackend = {| + interactions: Array, rootID: number, |}; -export type ProfilingSummary = {| +export type ProfilingSummaryBackend = {| commitDurations: Array, commitTimes: Array, initialTreeBaseDurations: Array, @@ -106,15 +106,18 @@ export type RendererInterface = { findNativeByFiberID: (id: number) => ?NativeType, flushInitialOperations: () => void, getBestMatchForTrackedPath: () => PathMatch | null, - getCommitDetails: (rootID: number, commitIndex: number) => CommitDetails, + getCommitDetails: ( + rootID: number, + commitIndex: number + ) => CommitDetailsBackend, getFiberIDFromNative: ( component: NativeType, findNearestUnfilteredAncestor?: boolean ) => number | null, - getFiberCommits: (rootID: number, fiberID: number) => FiberCommits, - getInteractions: (rootID: number) => Interactions, + getFiberCommits: (rootID: number, fiberID: number) => FiberCommitsBackend, + getInteractions: (rootID: number) => InteractionsBackend, getProfilingDataForDownload: (rootID: number) => Object, - getProfilingSummary: (rootID: number) => ProfilingSummary, + getProfilingSummary: (rootID: number) => ProfilingSummaryBackend, getPathForElement: (id: number) => Array | null, handleCommitFiberRoot: (fiber: Object) => void, handleCommitFiberUnmount: (fiber: Object) => void, diff --git a/src/devtools/ProfilingCache.js b/src/devtools/ProfilingCache.js index d313111e67..1ebbba06e1 100644 --- a/src/devtools/ProfilingCache.js +++ b/src/devtools/ProfilingCache.js @@ -22,18 +22,18 @@ import { import type { Resource } from './cache'; import type { Bridge } from '../types'; import type { - CommitDetails as CommitDetailsBackend, - FiberCommits as FiberCommitsBackend, - Interactions as InteractionsBackend, - ProfilingSummary as ProfilingSummaryBackend, + CommitDetailsBackend, + FiberCommitsBackend, + InteractionsBackend, + ProfilingSummaryBackend, } from 'src/backend/types'; import type { - CommitDetails as CommitDetailsFrontend, - FiberCommits as FiberCommitsFrontend, - Interactions as InteractionsFrontend, - InteractionWithCommits, - CommitTree as CommitTreeFrontend, - ProfilingSummary as ProfilingSummaryFrontend, + CommitDetailsFrontend, + FiberCommitsFrontend, + InteractionsFrontend, + InteractionWithCommitsFrontend, + CommitTreeFrontend, + ProfilingSummaryFrontend, } from 'src/devtools/views/Profiler/types'; import type { ChartData as FlamegraphChartData } from 'src/devtools/views/Profiler/FlamegraphChartBuilder'; import type { ChartData as InteractionsChartData } from 'src/devtools/views/Profiler/InteractionsChartBuilder'; @@ -273,7 +273,7 @@ export default class ProfilingCache { profilingSummary, rootID, }: {| - interactions: Array, + interactions: Array, profilingSummary: ProfilingSummaryFrontend, |}): InteractionsChartData => getInteractionsChartData({ diff --git a/src/devtools/views/Profiler/CommitFlamegraph.js b/src/devtools/views/Profiler/CommitFlamegraph.js index a4ad534a82..84a1ca5134 100644 --- a/src/devtools/views/Profiler/CommitFlamegraph.js +++ b/src/devtools/views/Profiler/CommitFlamegraph.js @@ -13,7 +13,7 @@ import { StoreContext } from '../context'; import styles from './CommitFlamegraph.css'; import type { ChartData, ChartNode } from './FlamegraphChartBuilder'; -import type { CommitDetails, CommitTree } from './types'; +import type { CommitDetailsFrontend, CommitTreeFrontend } from './types'; export type ItemData = {| chartData: ChartData, @@ -43,8 +43,8 @@ export default function CommitFlamegraphAutoSizer(_: {||}) { rootID: ((rootID: any): number), }); - let commitDetails: CommitDetails | null = null; - let commitTree: CommitTree | null = null; + let commitDetails: CommitDetailsFrontend | null = null; + let commitTree: CommitTreeFrontend | null = null; let chartData: ChartData | null = null; if (selectedCommitIndex !== null) { commitDetails = profilingCache.CommitDetails.read({ @@ -75,10 +75,12 @@ export default function CommitFlamegraphAutoSizer(_: {||}) {
{({ height, width }) => ( + // Force Flow types to avoid checking for `null` here because there's no static proof that + // by the time this render prop function is called, the values of the `let` variables have not changed. @@ -93,8 +95,8 @@ export default function CommitFlamegraphAutoSizer(_: {||}) { type Props = {| chartData: ChartData, - commitDetails: CommitDetails, - commitTree: CommitTree, + commitDetails: CommitDetailsFrontend, + commitTree: CommitTreeFrontend, height: number, width: number, |}; diff --git a/src/devtools/views/Profiler/CommitRanked.js b/src/devtools/views/Profiler/CommitRanked.js index 63cb41cd71..63200f37ba 100644 --- a/src/devtools/views/Profiler/CommitRanked.js +++ b/src/devtools/views/Profiler/CommitRanked.js @@ -13,7 +13,7 @@ import { StoreContext } from '../context'; import styles from './CommitRanked.css'; import type { ChartData } from './RankedChartBuilder'; -import type { CommitDetails, CommitTree } from './types'; +import type { CommitDetailsFrontend, CommitTreeFrontend } from './types'; export type ItemData = {| chartData: ChartData, @@ -43,8 +43,8 @@ export default function CommitRankedAutoSizer(_: {||}) { rootID: ((rootID: any): number), }); - let commitDetails: CommitDetails | null = null; - let commitTree: CommitTree | null = null; + let commitDetails: CommitDetailsFrontend | null = null; + let commitTree: CommitTreeFrontend | null = null; let chartData: ChartData | null = null; if (selectedCommitIndex !== null) { commitDetails = profilingCache.CommitDetails.read({ @@ -77,8 +77,8 @@ export default function CommitRankedAutoSizer(_: {||}) { {({ height, width }) => ( @@ -93,8 +93,8 @@ export default function CommitRankedAutoSizer(_: {||}) { type Props = {| chartData: ChartData, - commitDetails: CommitDetails, - commitTree: CommitTree, + commitDetails: CommitDetailsFrontend, + commitTree: CommitTreeFrontend, height: number, width: number, |}; diff --git a/src/devtools/views/Profiler/CommitTreeBuilder.js b/src/devtools/views/Profiler/CommitTreeBuilder.js index c04cc6a6ae..fdf98533c2 100644 --- a/src/devtools/views/Profiler/CommitTreeBuilder.js +++ b/src/devtools/views/Profiler/CommitTreeBuilder.js @@ -13,9 +13,9 @@ import Store from 'src/devtools/store'; import type { ElementType } from 'src/devtools/types'; import type { - CommitTree, - Node, - ProfilingSummary as ProfilingSummaryFrontend, + CommitTreeFrontend, + CommitTreeNodeFrontend, + ProfilingSummaryFrontend, } from 'src/devtools/views/Profiler/types'; const debug = (methodName, ...args) => { @@ -29,7 +29,7 @@ const debug = (methodName, ...args) => { } }; -const rootToCommitTreeMap: Map> = new Map(); +const rootToCommitTreeMap: Map> = new Map(); export function getCommitTree({ commitIndex, @@ -39,7 +39,7 @@ export function getCommitTree({ commitIndex: number, profilingSummary: ProfilingSummaryFrontend, store: Store, -|}): CommitTree { +|}): CommitTreeFrontend { const { rootID } = profilingSummary; if (!rootToCommitTreeMap.has(rootID)) { @@ -48,7 +48,7 @@ export function getCommitTree({ const commitTrees = ((rootToCommitTreeMap.get( rootID - ): any): Array); + ): any): Array); if (commitIndex < commitTrees.length) { return commitTrees[commitIndex]; @@ -120,7 +120,7 @@ export function getCommitTree({ function recursivelyInitializeTree( id: number, parentID: number, - nodes: Map, + nodes: Map, initialTreeBaseDurations: Map, store: Store ): void { @@ -153,15 +153,18 @@ function recursivelyInitializeTree( } function updateTree( - commitTree: CommitTree, + commitTree: CommitTreeFrontend, operations: Uint32Array -): CommitTree { +): CommitTreeFrontend { // Clone the original tree so edits don't affect it. const nodes = new Map(commitTree.nodes); // Clone nodes before mutating them so edits don't affect them. - const getClonedNode = (id: number): Node => { - const clonedNode = ((Object.assign({}, nodes.get(id)): any): Node); + const getClonedNode = (id: number): CommitTreeNodeFrontend => { + const clonedNode = ((Object.assign( + {}, + nodes.get(id) + ): any): CommitTreeNodeFrontend); nodes.set(id, clonedNode); return clonedNode; }; @@ -209,7 +212,7 @@ function updateTree( debug('Add', `new root fiber ${id}`); } - const node: Node = { + const node: CommitTreeNodeFrontend = { children: [], displayName: null, id, @@ -243,7 +246,7 @@ function updateTree( const parentNode = getClonedNode(parentID); parentNode.children = parentNode.children.concat(id); - const node: Node = { + const node: CommitTreeNodeFrontend = { children: [], displayName, id, @@ -343,7 +346,7 @@ export function invalidateCommitTrees(): void { } // DEBUG -const __printTree = (commitTree: CommitTree) => { +const __printTree = (commitTree: CommitTreeFrontend) => { if (__DEBUG__) { const { nodes, rootID } = commitTree; console.group('__printTree()'); @@ -352,7 +355,10 @@ const __printTree = (commitTree: CommitTree) => { const id = queue.shift(); const depth = queue.shift(); - const node = ((nodes.get(id): any): Node); + const node = nodes.get(id); + if (node == null) { + throw Error(`Could not find node with id "${id}" in commit tree`); + } console.log( `${'•'.repeat(depth)}${node.id}:${node.displayName || ''} ${ diff --git a/src/devtools/views/Profiler/FlamegraphChartBuilder.js b/src/devtools/views/Profiler/FlamegraphChartBuilder.js index bfb912adcc..8096972175 100644 --- a/src/devtools/views/Profiler/FlamegraphChartBuilder.js +++ b/src/devtools/views/Profiler/FlamegraphChartBuilder.js @@ -2,7 +2,7 @@ import { calculateSelfDuration } from './utils'; -import type { CommitDetails, CommitTree, Node } from './types'; +import type { CommitDetailsFrontend, CommitTreeFrontend } from './types'; export type ChartNode = {| actualDuration: number, @@ -29,9 +29,9 @@ export function getChartData({ commitIndex, commitTree, }: {| - commitDetails: CommitDetails, + commitDetails: CommitDetailsFrontend, commitIndex: number, - commitTree: CommitTree, + commitTree: CommitTreeFrontend, |}): ChartData { const { actualDurations, rootID } = commitDetails; const { nodes } = commitTree; @@ -55,8 +55,7 @@ export function getChartData({ ) => { idToDepthMap.set(id, currentDepth); - const node = ((nodes.get(id): any): Node); - + const node = nodes.get(id); if (node == null) { throw Error(`Could not find node with id "${id}" in commit tree`); } @@ -104,7 +103,12 @@ export function getChartData({ }; // Skip over the root; we don't want to show it in the flamegraph. - const root = ((nodes.get(rootID): any): Node); + const root = nodes.get(rootID); + if (root == null) { + throw Error(`Could not find root node with id "${rootID}" in commit tree`); + } + + // TODO: Looks like there's an assumption here that a root has only one child. Is that so with a fragment in the root? walkTree(root.children[0]); const chartData = { diff --git a/src/devtools/views/Profiler/Interactions.js b/src/devtools/views/Profiler/Interactions.js index 6ce175c245..f2ebbefce3 100644 --- a/src/devtools/views/Profiler/Interactions.js +++ b/src/devtools/views/Profiler/Interactions.js @@ -13,13 +13,16 @@ import styles from './Interactions.css'; import type { ChartData } from './InteractionsChartBuilder'; import type { TabID } from './ProfilerContext'; -import type { InteractionWithCommits, ProfilingSummary } from './types'; +import type { + InteractionWithCommitsFrontend, + ProfilingSummaryFrontend, +} from './types'; export type ItemData = {| chartData: ChartData, - interactions: Array, + interactions: Array, labelWidth: number, - profilingSummary: ProfilingSummary, + profilingSummary: ProfilingSummaryFrontend, scaleX: (value: number, fallbackValue: number) => number, selectedInteractionID: number | null, selectCommitIndex: (id: number | null) => void, diff --git a/src/devtools/views/Profiler/InteractionsChartBuilder.js b/src/devtools/views/Profiler/InteractionsChartBuilder.js index b1391a6eea..08bf71be00 100644 --- a/src/devtools/views/Profiler/InteractionsChartBuilder.js +++ b/src/devtools/views/Profiler/InteractionsChartBuilder.js @@ -1,6 +1,9 @@ // @flow -import type { InteractionWithCommits, ProfilingSummary } from './types'; +import type { + InteractionWithCommitsFrontend, + ProfilingSummaryFrontend, +} from './types'; export type ChartData = {| lastInteractionTime: number, @@ -13,8 +16,8 @@ export function getChartData({ interactions, profilingSummary, }: {| - interactions: Array, - profilingSummary: ProfilingSummary, + interactions: Array, + profilingSummary: ProfilingSummaryFrontend, |}): ChartData { const { rootID } = profilingSummary; diff --git a/src/devtools/views/Profiler/RankedChartBuilder.js b/src/devtools/views/Profiler/RankedChartBuilder.js index 981692c90c..4274bac0c4 100644 --- a/src/devtools/views/Profiler/RankedChartBuilder.js +++ b/src/devtools/views/Profiler/RankedChartBuilder.js @@ -2,7 +2,7 @@ import { calculateSelfDuration } from './utils'; -import type { CommitDetails, CommitTree, Node } from './types'; +import type { CommitDetailsFrontend, CommitTreeFrontend } from './types'; export type ChartNode = {| id: number, @@ -23,9 +23,9 @@ export function getChartData({ commitIndex, commitTree, }: {| - commitDetails: CommitDetails, + commitDetails: CommitDetailsFrontend, commitIndex: number, - commitTree: CommitTree, + commitTree: CommitTreeFrontend, |}): ChartData { const { actualDurations, rootID } = commitDetails; const { nodes } = commitTree; @@ -39,7 +39,7 @@ export function getChartData({ const chartNodes: Array = []; actualDurations.forEach((actualDuration, id) => { - const node = ((nodes.get(id): any): Node); + const node = nodes.get(id); if (node == null) { throw Error(`Could not find node with id "${id}" in commit tree`); diff --git a/src/devtools/views/Profiler/SidebarInteractions.js b/src/devtools/views/Profiler/SidebarInteractions.js index 22fb062e68..992a815c49 100644 --- a/src/devtools/views/Profiler/SidebarInteractions.js +++ b/src/devtools/views/Profiler/SidebarInteractions.js @@ -8,8 +8,6 @@ import { getGradientColor } from './utils'; import styles from './SidebarInteractions.css'; -import type { InteractionWithCommits } from './types'; - export type Props = {||}; export default function SidebarInteractions(_: Props) { @@ -31,6 +29,14 @@ export default function SidebarInteractions(_: Props) { rendererID: ((rendererID: any): number), rootID: ((rootID: any): number), }); + const interaction = interactions.find( + interaction => interaction.id === selectedInteractionID + ); + if (interaction == null) { + throw Error( + `Could not find interaction by selected interaction id "${selectedInteractionID}"` + ); + } const profilingSummary = profilingCache.ProfilingSummary.read({ rendererID: ((rendererID: any): number), @@ -44,10 +50,6 @@ export default function SidebarInteractions(_: Props) { const { commitDurations, commitTimes } = profilingSummary; - const interaction = ((interactions.find( - interaction => interaction.id === selectedInteractionID - ): any): InteractionWithCommits); - const viewCommit = (commitIndex: number) => { selectTab('flame-chart'); selectCommitIndex(commitIndex); diff --git a/src/devtools/views/Profiler/types.js b/src/devtools/views/Profiler/types.js index eb9dd1b494..2cb024f808 100644 --- a/src/devtools/views/Profiler/types.js +++ b/src/devtools/views/Profiler/types.js @@ -1,6 +1,6 @@ // @flow -export type Node = {| +export type CommitTreeNodeFrontend = {| id: number, children: Array, displayName: string | null, @@ -9,38 +9,38 @@ export type Node = {| treeBaseDuration: number, |}; -export type CommitTree = {| - nodes: Map, +export type CommitTreeFrontend = {| + nodes: Map, rootID: number, |}; -export type Interaction = {| +export type InteractionFrontend = {| id: number, name: string, timestamp: number, |}; -export type InteractionWithCommits = {| - ...Interaction, +export type InteractionWithCommitsFrontend = {| + ...InteractionFrontend, commits: Array, |}; -export type Interactions = Array; +export type InteractionsFrontend = Array; -export type CommitDetails = {| +export type CommitDetailsFrontend = {| rootID: number, commitIndex: number, actualDurations: Map, - interactions: Array, + interactions: Array, |}; -export type FiberCommits = {| +export type FiberCommitsFrontend = {| commitDurations: Array, fiberID: number, rootID: number, |}; -export type ProfilingSummary = {| +export type ProfilingSummaryFrontend = {| rootID: number, // Commit durations @@ -66,7 +66,7 @@ export type ImportedProfilingData = {| version: number, profilingOperations: Map>, profilingSnapshot: Map, - commitDetails: CommitDetails, - interactions: Interactions, - profilingSummary: ProfilingSummary, + commitDetails: CommitDetailsFrontend, + interactions: InteractionsFrontend, + profilingSummary: ProfilingSummaryFrontend, |}; diff --git a/src/devtools/views/Profiler/utils.js b/src/devtools/views/Profiler/utils.js index c8e439ce73..33c9217f86 100644 --- a/src/devtools/views/Profiler/utils.js +++ b/src/devtools/views/Profiler/utils.js @@ -1,6 +1,6 @@ // @flow -import type { CommitDetails, CommitTree, Node } from './types'; +import type { CommitDetailsFrontend, CommitTreeFrontend } from './types'; const commitGradient = [ 'var(--color-commit-gradient-0)', @@ -17,8 +17,8 @@ const commitGradient = [ export const calculateSelfDuration = ( id: number, - commitTree: CommitTree, - commitDetails: CommitDetails + commitTree: CommitTreeFrontend, + commitDetails: CommitDetailsFrontend ): number => { const { actualDurations } = commitDetails; const { nodes } = commitTree; @@ -28,8 +28,11 @@ export const calculateSelfDuration = ( } let selfDuration = ((actualDurations.get(id): any): number); + const node = nodes.get(id); + if (node == null) { + throw Error(`Could not find node with id "${id}" in commit tree`); + } - const node = ((nodes.get(id): any): Node); node.children.forEach(childID => { if (actualDurations.has(childID)) { selfDuration -= ((actualDurations.get(childID): any): number);