1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @flow
    
  8.  */
    
  9. 
    
  10. import {
    
  11.   ElementTypeForwardRef,
    
  12.   ElementTypeMemo,
    
  13. } from 'react-devtools-shared/src/frontend/types';
    
  14. import {formatDuration} from './utils';
    
  15. import ProfilerStore from 'react-devtools-shared/src/devtools/ProfilerStore';
    
  16. 
    
  17. import type {CommitTree} from './types';
    
  18. 
    
  19. export type ChartNode = {
    
  20.   id: number,
    
  21.   label: string,
    
  22.   name: string,
    
  23.   value: number,
    
  24. };
    
  25. 
    
  26. export type ChartData = {
    
  27.   maxValue: number,
    
  28.   nodes: Array<ChartNode>,
    
  29. };
    
  30. 
    
  31. const cachedChartData: Map<string, ChartData> = new Map();
    
  32. 
    
  33. export function getChartData({
    
  34.   commitIndex,
    
  35.   commitTree,
    
  36.   profilerStore,
    
  37.   rootID,
    
  38. }: {
    
  39.   commitIndex: number,
    
  40.   commitTree: CommitTree,
    
  41.   profilerStore: ProfilerStore,
    
  42.   rootID: number,
    
  43. }): ChartData {
    
  44.   const commitDatum = profilerStore.getCommitData(rootID, commitIndex);
    
  45. 
    
  46.   const {fiberActualDurations, fiberSelfDurations} = commitDatum;
    
  47.   const {nodes} = commitTree;
    
  48. 
    
  49.   const chartDataKey = `${rootID}-${commitIndex}`;
    
  50.   if (cachedChartData.has(chartDataKey)) {
    
  51.     return ((cachedChartData.get(chartDataKey): any): ChartData);
    
  52.   }
    
  53. 
    
  54.   let maxSelfDuration = 0;
    
  55. 
    
  56.   const chartNodes: Array<ChartNode> = [];
    
  57.   fiberActualDurations.forEach((actualDuration, id) => {
    
  58.     const node = nodes.get(id);
    
  59. 
    
  60.     if (node == null) {
    
  61.       throw Error(`Could not find node with id "${id}" in commit tree`);
    
  62.     }
    
  63. 
    
  64.     const {displayName, key, parentID, type} = node;
    
  65. 
    
  66.     // Don't show the root node in this chart.
    
  67.     if (parentID === 0) {
    
  68.       return;
    
  69.     }
    
  70.     const selfDuration = fiberSelfDurations.get(id) || 0;
    
  71.     maxSelfDuration = Math.max(maxSelfDuration, selfDuration);
    
  72. 
    
  73.     const name = displayName || 'Anonymous';
    
  74.     const maybeKey = key !== null ? ` key="${key}"` : '';
    
  75. 
    
  76.     let maybeBadge = '';
    
  77.     if (type === ElementTypeForwardRef) {
    
  78.       maybeBadge = ' (ForwardRef)';
    
  79.     } else if (type === ElementTypeMemo) {
    
  80.       maybeBadge = ' (Memo)';
    
  81.     }
    
  82. 
    
  83.     const label = `${name}${maybeBadge}${maybeKey} (${formatDuration(
    
  84.       selfDuration,
    
  85.     )}ms)`;
    
  86.     chartNodes.push({
    
  87.       id,
    
  88.       label,
    
  89.       name,
    
  90.       value: selfDuration,
    
  91.     });
    
  92.   });
    
  93. 
    
  94.   const chartData = {
    
  95.     maxValue: maxSelfDuration,
    
  96.     nodes: chartNodes.sort((a, b) => b.value - a.value),
    
  97.   };
    
  98. 
    
  99.   cachedChartData.set(chartDataKey, chartData);
    
  100. 
    
  101.   return chartData;
    
  102. }
    
  103. 
    
  104. export function invalidateChartData(): void {
    
  105.   cachedChartData.clear();
    
  106. }