diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /devtools/client/memory/components/shortest-paths.js | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'devtools/client/memory/components/shortest-paths.js')
-rw-r--r-- | devtools/client/memory/components/shortest-paths.js | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/devtools/client/memory/components/shortest-paths.js b/devtools/client/memory/components/shortest-paths.js new file mode 100644 index 000000000..23cb8134b --- /dev/null +++ b/devtools/client/memory/components/shortest-paths.js @@ -0,0 +1,184 @@ +/* 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 { + DOM: dom, + createClass, + PropTypes, +} = require("devtools/client/shared/vendor/react"); +const { isSavedFrame } = require("devtools/shared/DevToolsUtils"); +const { getSourceNames } = require("devtools/client/shared/source-utils"); +const { L10N } = require("../utils"); + +const GRAPH_DEFAULTS = { + translate: [20, 20], + scale: 1 +}; + +const NO_STACK = "noStack"; +const NO_FILENAME = "noFilename"; +const ROOT_LIST = "JS::ubi::RootList"; + +function stringifyLabel(label, id) { + const sanitized = []; + + for (let i = 0, length = label.length; i < length; i++) { + const piece = label[i]; + + if (isSavedFrame(piece)) { + const { short } = getSourceNames(piece.source); + sanitized[i] = `${piece.functionDisplayName} @ ${short}:${piece.line}:${piece.column}`; + } else if (piece === NO_STACK) { + sanitized[i] = L10N.getStr("tree-item.nostack"); + } else if (piece === NO_FILENAME) { + sanitized[i] = L10N.getStr("tree-item.nofilename"); + } else if (piece === ROOT_LIST) { + // Don't use the usual labeling machinery for root lists: replace it + // with the "GC Roots" string. + sanitized.splice(0, label.length); + sanitized.push(L10N.getStr("tree-item.rootlist")); + break; + } else { + sanitized[i] = "" + piece; + } + } + + return `${sanitized.join(" › ")} @ 0x${id.toString(16)}`; +} + +module.exports = createClass({ + displayName: "ShortestPaths", + + propTypes: { + graph: PropTypes.shape({ + nodes: PropTypes.arrayOf(PropTypes.object), + edges: PropTypes.arrayOf(PropTypes.object), + }), + }, + + getInitialState() { + return { zoom: null }; + }, + + shouldComponentUpdate(nextProps) { + return this.props.graph != nextProps.graph; + }, + + componentDidMount() { + if (this.props.graph) { + this._renderGraph(this.refs.container, this.props.graph); + } + }, + + componentDidUpdate() { + if (this.props.graph) { + this._renderGraph(this.refs.container, this.props.graph); + } + }, + + componentWillUnmount() { + if (this.state.zoom) { + this.state.zoom.on("zoom", null); + } + }, + + render() { + let contents; + if (this.props.graph) { + // Let the componentDidMount or componentDidUpdate method draw the graph + // with DagreD3. We just provide the container for the graph here. + contents = dom.div({ + ref: "container", + style: { + flex: 1, + height: "100%", + width: "100%", + } + }); + } else { + contents = dom.div( + { + id: "shortest-paths-select-node-msg" + }, + L10N.getStr("shortest-paths.select-node") + ); + } + + return dom.div( + { + id: "shortest-paths", + className: "vbox", + }, + dom.label( + { + id: "shortest-paths-header", + className: "header", + }, + L10N.getStr("shortest-paths.header") + ), + contents + ); + }, + + _renderGraph(container, { nodes, edges }) { + if (!container.firstChild) { + const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + svg.setAttribute("id", "graph-svg"); + svg.setAttribute("xlink", "http://www.w3.org/1999/xlink"); + svg.style.width = "100%"; + svg.style.height = "100%"; + + const target = document.createElementNS("http://www.w3.org/2000/svg", "g"); + target.setAttribute("id", "graph-target"); + target.style.width = "100%"; + target.style.height = "100%"; + + svg.appendChild(target); + container.appendChild(svg); + } + + const graph = new dagreD3.Digraph(); + + for (let i = 0; i < nodes.length; i++) { + graph.addNode(nodes[i].id, { + id: nodes[i].id, + label: stringifyLabel(nodes[i].label, nodes[i].id), + }); + } + + for (let i = 0; i < edges.length; i++) { + graph.addEdge(null, edges[i].from, edges[i].to, { + label: edges[i].name + }); + } + + const renderer = new dagreD3.Renderer(); + renderer.drawNodes(); + renderer.drawEdgePaths(); + + const svg = d3.select("#graph-svg"); + const target = d3.select("#graph-target"); + + let zoom = this.state.zoom; + if (!zoom) { + zoom = d3.behavior.zoom().on("zoom", function () { + target.attr( + "transform", + `translate(${d3.event.translate}) scale(${d3.event.scale})` + ); + }); + svg.call(zoom); + this.setState({ zoom }); + } + + const { translate, scale } = GRAPH_DEFAULTS; + zoom.scale(scale); + zoom.translate(translate); + target.attr("transform", `translate(${translate}) scale(${scale})`); + + const layout = dagreD3.layout(); + renderer.layout(layout).run(graph, target); + }, +}); |