diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /devtools/client/memory/components/DominatorTreeItem.js | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/client/memory/components/DominatorTreeItem.js')
-rw-r--r-- | devtools/client/memory/components/DominatorTreeItem.js | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/devtools/client/memory/components/DominatorTreeItem.js b/devtools/client/memory/components/DominatorTreeItem.js new file mode 100644 index 0000000000..f8d1660d1b --- /dev/null +++ b/devtools/client/memory/components/DominatorTreeItem.js @@ -0,0 +1,167 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { assert, isSavedFrame } = require("devtools/shared/DevToolsUtils"); +const { + Component, + createFactory, +} = require("devtools/client/shared/vendor/react"); +const dom = require("devtools/client/shared/vendor/react-dom-factories"); +const PropTypes = require("devtools/client/shared/vendor/react-prop-types"); +const { + L10N, + formatNumber, + formatPercent, +} = require("devtools/client/memory/utils"); +const Frame = createFactory(require("devtools/client/shared/components/Frame")); +const { TREE_ROW_HEIGHT } = require("devtools/client/memory/constants"); + +class SeparatorClass extends Component { + render() { + return dom.span({ className: "separator" }, "›"); + } +} + +const Separator = createFactory(SeparatorClass); + +class DominatorTreeItem extends Component { + static get propTypes() { + return { + item: PropTypes.object.isRequired, + depth: PropTypes.number.isRequired, + arrow: PropTypes.object, + expanded: PropTypes.bool.isRequired, + focused: PropTypes.bool.isRequired, + getPercentSize: PropTypes.func.isRequired, + onViewSourceInDebugger: PropTypes.func.isRequired, + }; + } + + shouldComponentUpdate(nextProps, nextState) { + return ( + this.props.item != nextProps.item || + this.props.depth != nextProps.depth || + this.props.expanded != nextProps.expanded || + this.props.focused != nextProps.focused + ); + } + + render() { + const { + item, + depth, + arrow, + focused, + getPercentSize, + onViewSourceInDebugger, + } = this.props; + + const retainedSize = formatNumber(item.retainedSize); + const percentRetainedSize = formatPercent( + getPercentSize(item.retainedSize) + ); + + const shallowSize = formatNumber(item.shallowSize); + const percentShallowSize = formatPercent(getPercentSize(item.shallowSize)); + + // Build up our label UI as an array of each label piece, which is either a + // string or a frame, and separators in between them. + + assert(item.label.length > 0, "Our label should not be empty"); + const label = Array(item.label.length * 2 - 1); + label.fill(undefined); + + for (let i = 0, length = item.label.length; i < length; i++) { + const piece = item.label[i]; + const key = `${item.nodeId}-label-${i}`; + + // `i` is the index of the label piece we are rendering, `label[i*2]` is + // where the rendered label piece belngs, and `label[i*2+1]` (if it isn't + // out of bounds) is where the separator belongs. + + if (isSavedFrame(piece)) { + label[i * 2] = Frame({ + key, + onClick: onViewSourceInDebugger, + frame: piece, + showFunctionName: true, + }); + } else if (piece === "noStack") { + label[i * 2] = dom.span( + { key, className: "not-available" }, + L10N.getStr("tree-item.nostack") + ); + } else if (piece === "noFilename") { + label[i * 2] = dom.span( + { key, className: "not-available" }, + L10N.getStr("tree-item.nofilename") + ); + } else if (piece === "JS::ubi::RootList") { + // Don't use the usual labeling machinery for root lists: replace it + // with the "GC Roots" string. + label.splice(0, label.length); + label.push(L10N.getStr("tree-item.rootlist")); + break; + } else { + label[i * 2] = piece; + } + + // If this is not the last piece of the label, add a separator. + if (i < length - 1) { + label[i * 2 + 1] = Separator({ key: `${item.nodeId}-separator-${i}` }); + } + } + + return dom.div( + { + className: `heap-tree-item ${focused ? "focused" : ""} node-${ + item.nodeId + }`, + }, + + dom.span( + { + className: "heap-tree-item-field heap-tree-item-bytes", + }, + dom.span( + { + className: "heap-tree-number", + }, + retainedSize + ), + dom.span({ className: "heap-tree-percent" }, percentRetainedSize) + ), + + dom.span( + { + className: "heap-tree-item-field heap-tree-item-bytes", + }, + dom.span( + { + className: "heap-tree-number", + }, + shallowSize + ), + dom.span({ className: "heap-tree-percent" }, percentShallowSize) + ), + + dom.span( + { + className: "heap-tree-item-field heap-tree-item-name", + style: { marginInlineStart: depth * TREE_ROW_HEIGHT }, + }, + arrow, + label, + dom.span( + { className: "heap-tree-item-address" }, + `@ 0x${item.nodeId.toString(16)}` + ) + ) + ); + } +} + +module.exports = DominatorTreeItem; |