mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-19 02:43:07 +09:00
142 lines
4.5 KiB
JavaScript
142 lines
4.5 KiB
JavaScript
|
|
/* 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)}`)
|
|||
|
|
)
|
|||
|
|
);
|
|||
|
|
},
|
|||
|
|
});
|