summaryrefslogtreecommitdiffstats
path: root/devtools/client/memory/components/DominatorTreeItem.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /devtools/client/memory/components/DominatorTreeItem.js
parentInitial commit. (diff)
downloadfirefox-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.js167
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;