tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CensusTreeItem.js (5710B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 "use strict";
      5 
      6 const { isSavedFrame } = require("resource://devtools/shared/DevToolsUtils.js");
      7 const {
      8  Component,
      9  createFactory,
     10 } = require("resource://devtools/client/shared/vendor/react.mjs");
     11 const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
     12 const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs");
     13 const {
     14  L10N,
     15  formatNumber,
     16  formatPercent,
     17 } = require("resource://devtools/client/memory/utils.js");
     18 const Frame = createFactory(
     19  require("resource://devtools/client/shared/components/Frame.js")
     20 );
     21 const {
     22  TREE_ROW_HEIGHT,
     23 } = require("resource://devtools/client/memory/constants.js");
     24 const models = require("resource://devtools/client/memory/models.js");
     25 
     26 class CensusTreeItem extends Component {
     27  static get propTypes() {
     28    return {
     29      arrow: PropTypes.any,
     30      depth: PropTypes.number.isRequired,
     31      diffing: models.app.diffing,
     32      expanded: PropTypes.bool.isRequired,
     33      focused: PropTypes.bool.isRequired,
     34      getPercentBytes: PropTypes.func.isRequired,
     35      getPercentCount: PropTypes.func.isRequired,
     36      inverted: PropTypes.bool,
     37      item: PropTypes.object.isRequired,
     38      onViewIndividuals: PropTypes.func.isRequired,
     39      onViewSourceInDebugger: PropTypes.func.isRequired,
     40    };
     41  }
     42 
     43  constructor(props) {
     44    super(props);
     45    this.toLabel = this.toLabel.bind(this);
     46  }
     47 
     48  shouldComponentUpdate(nextProps) {
     49    return (
     50      this.props.item != nextProps.item ||
     51      this.props.depth != nextProps.depth ||
     52      this.props.expanded != nextProps.expanded ||
     53      this.props.focused != nextProps.focused ||
     54      this.props.diffing != nextProps.diffing
     55    );
     56  }
     57 
     58  toLabel(name, onViewSourceInDebugger) {
     59    if (isSavedFrame(name)) {
     60      return Frame({
     61        frame: name,
     62        onClick: onViewSourceInDebugger,
     63        showFunctionName: true,
     64        showHost: true,
     65      });
     66    }
     67 
     68    if (name === null) {
     69      return L10N.getStr("tree-item.root");
     70    }
     71 
     72    if (name === "noStack") {
     73      return L10N.getStr("tree-item.nostack");
     74    }
     75 
     76    if (name === "noFilename") {
     77      return L10N.getStr("tree-item.nofilename");
     78    }
     79 
     80    return String(name);
     81  }
     82 
     83  render() {
     84    const {
     85      item,
     86      depth,
     87      arrow,
     88      focused,
     89      getPercentBytes,
     90      getPercentCount,
     91      diffing,
     92      onViewSourceInDebugger,
     93      onViewIndividuals,
     94      inverted,
     95    } = this.props;
     96 
     97    const bytes = formatNumber(item.bytes, !!diffing);
     98    const percentBytes = formatPercent(getPercentBytes(item.bytes), !!diffing);
     99 
    100    const count = formatNumber(item.count, !!diffing);
    101    const percentCount = formatPercent(getPercentCount(item.count), !!diffing);
    102 
    103    const totalBytes = formatNumber(item.totalBytes, !!diffing);
    104    const percentTotalBytes = formatPercent(
    105      getPercentBytes(item.totalBytes),
    106      !!diffing
    107    );
    108 
    109    const totalCount = formatNumber(item.totalCount, !!diffing);
    110    const percentTotalCount = formatPercent(
    111      getPercentCount(item.totalCount),
    112      !!diffing
    113    );
    114 
    115    let pointer;
    116    if (inverted && depth > 0) {
    117      pointer = dom.span({ className: "children-pointer" }, "↖");
    118    } else if (!inverted && item.children?.length) {
    119      pointer = dom.span({ className: "children-pointer" }, "↘");
    120    }
    121 
    122    let individualsCell;
    123    if (!diffing) {
    124      let individualsButton;
    125      if (item.reportLeafIndex !== undefined) {
    126        individualsButton = dom.button(
    127          {
    128            key: `individuals-button-${item.id}`,
    129            title: L10N.getStr("tree-item.view-individuals.tooltip"),
    130            className: "devtools-button individuals-button",
    131            onClick: e => {
    132              // Don't let the event bubble up to cause this item to focus after
    133              // we have switched views, which would lead to assertion failures.
    134              e.preventDefault();
    135              e.stopPropagation();
    136 
    137              onViewIndividuals(item);
    138            },
    139          },
    140          "⁂"
    141        );
    142      }
    143      individualsCell = dom.span(
    144        { className: "heap-tree-item-field heap-tree-item-individuals" },
    145        individualsButton
    146      );
    147    }
    148 
    149    return dom.div(
    150      { className: `heap-tree-item ${focused ? "focused" : ""}` },
    151      dom.span(
    152        { className: "heap-tree-item-field heap-tree-item-bytes" },
    153        dom.span({ className: "heap-tree-number" }, bytes),
    154        dom.span({ className: "heap-tree-percent" }, percentBytes)
    155      ),
    156      dom.span(
    157        { className: "heap-tree-item-field heap-tree-item-count" },
    158        dom.span({ className: "heap-tree-number" }, count),
    159        dom.span({ className: "heap-tree-percent" }, percentCount)
    160      ),
    161      dom.span(
    162        { className: "heap-tree-item-field heap-tree-item-total-bytes" },
    163        dom.span({ className: "heap-tree-number" }, totalBytes),
    164        dom.span({ className: "heap-tree-percent" }, percentTotalBytes)
    165      ),
    166      dom.span(
    167        { className: "heap-tree-item-field heap-tree-item-total-count" },
    168        dom.span({ className: "heap-tree-number" }, totalCount),
    169        dom.span({ className: "heap-tree-percent" }, percentTotalCount)
    170      ),
    171      individualsCell,
    172      dom.span(
    173        {
    174          className: "heap-tree-item-field heap-tree-item-name",
    175          style: { marginInlineStart: depth * TREE_ROW_HEIGHT },
    176        },
    177        arrow,
    178        pointer,
    179        this.toLabel(item.name, onViewSourceInDebugger)
    180      )
    181    );
    182  }
    183 }
    184 
    185 module.exports = CensusTreeItem;