diff options
Diffstat (limited to 'devtools/client/memory/components/dominator-tree-item.js')
-rw-r--r-- | devtools/client/memory/components/dominator-tree-item.js | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/devtools/client/memory/components/dominator-tree-item.js b/devtools/client/memory/components/dominator-tree-item.js new file mode 100644 index 000000000..bf76ee9b4 --- /dev/null +++ b/devtools/client/memory/components/dominator-tree-item.js @@ -0,0 +1,142 @@ +/* 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/. */ + +const { assert, isSavedFrame } = require("devtools/shared/DevToolsUtils"); +const { DOM: dom, createClass, createFactory, PropTypes } = require("devtools/client/shared/vendor/react"); +const { L10N, formatNumber, formatPercent } = require("../utils"); +const Frame = createFactory(require("devtools/client/shared/components/frame")); +const { TREE_ROW_HEIGHT } = require("../constants"); + +const Separator = createFactory(createClass({ + displayName: "Separator", + + render() { + return dom.span({ className: "separator" }, "›"); + } +})); + +const DominatorTreeItem = module.exports = createClass({ + displayName: "DominatorTreeItem", + + propTypes: { + item: PropTypes.object.isRequired, + depth: PropTypes.number.isRequired, + arrow: PropTypes.object, + 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() { + let { + 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(piece), + 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)}`) + ) + ); + }, +}); |