--- a/devtools/client/memory/app.js
+++ b/devtools/client/memory/app.js
@@ -1,17 +1,17 @@
/* 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 } = require("devtools/shared/DevToolsUtils");
const { appinfo } = require("Services");
-const { DOM: dom, createClass, createFactory, PropTypes } = require("devtools/client/shared/vendor/react");
+const { DOM: dom, Component, createFactory, PropTypes } = require("devtools/client/shared/vendor/react");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { censusDisplays, labelDisplays, treeMapDisplays, diffingState, viewState } = require("./constants");
const { toggleRecordingAllocationStacks } = require("./actions/allocations");
const { setCensusDisplayAndRefresh } = require("./actions/census-display");
const { setLabelDisplayAndRefresh } = require("./actions/label-display");
const { setTreeMapDisplayAndRefresh } = require("./actions/tree-map-display");
const {
@@ -46,49 +46,59 @@ const {
const { changeViewAndRefresh, popViewAndRefresh } = require("./actions/view");
const { resizeShortestPaths } = require("./actions/sizes");
const Toolbar = createFactory(require("./components/Toolbar"));
const List = createFactory(require("./components/List"));
const SnapshotListItem = createFactory(require("./components/SnapshotListItem"));
const Heap = createFactory(require("./components/Heap"));
const { app: appModel } = require("./models");
-const MemoryApp = createClass({
- displayName: "MemoryApp",
-
- propTypes: appModel,
+class MemoryApp extends Component {
+ static get propTypes() {
+ return appModel;
+ }
- childContextTypes: {
- front: PropTypes.any,
- heapWorker: PropTypes.any,
- toolbox: PropTypes.any,
- },
+ static get childContextTypes() {
+ return {
+ front: PropTypes.any,
+ heapWorker: PropTypes.any,
+ toolbox: PropTypes.any,
+ };
+ }
- getDefaultProps() {
+ static get defaultProps() {
return {};
- },
+ }
+
+ constructor(props) {
+ super(props);
+ this.onKeyDown = this.onKeyDown.bind(this);
+ this._getCensusDisplays = this._getCensusDisplays.bind(this);
+ this._getLabelDisplays = this._getLabelDisplays.bind(this);
+ this._getTreeMapDisplays = this._getTreeMapDisplays.bind(this);
+ }
getChildContext() {
return {
front: this.props.front,
heapWorker: this.props.heapWorker,
toolbox: this.props.toolbox,
};
- },
+ }
componentDidMount() {
// Attach the keydown listener directly to the window. When an element that
// has the focus (such as a tree node) is removed from the DOM, the focus
// falls back to the body.
window.addEventListener("keydown", this.onKeyDown);
- },
+ }
componentWillUnmount() {
window.removeEventListener("keydown", this.onKeyDown);
- },
+ }
onKeyDown(e) {
let { snapshots, dispatch, heapWorker } = this.props;
const selectedSnapshot = snapshots.find(s => s.selected);
const selectedIndex = snapshots.indexOf(selectedSnapshot);
let isOSX = appinfo.OS == "Darwin";
let isAccelKey = (isOSX && e.metaKey) || (!isOSX && e.ctrlKey);
@@ -101,56 +111,56 @@ const MemoryApp = createClass({
}
// On ACCEL+DOWN, select next snapshot.
if (isAccelKey && e.key === "ArrowDown") {
let nextIndex = Math.min(snapshots.length - 1, selectedIndex + 1);
let nextSnapshotId = snapshots[nextIndex].id;
dispatch(selectSnapshotAndRefresh(heapWorker, nextSnapshotId));
}
- },
+ }
_getCensusDisplays() {
const customDisplays = getCustomCensusDisplays();
const custom = Object.keys(customDisplays).reduce((arr, key) => {
arr.push(customDisplays[key]);
return arr;
}, []);
return [
censusDisplays.coarseType,
censusDisplays.allocationStack,
censusDisplays.invertedAllocationStack,
].concat(custom);
- },
+ }
_getLabelDisplays() {
const customDisplays = getCustomLabelDisplays();
const custom = Object.keys(customDisplays).reduce((arr, key) => {
arr.push(customDisplays[key]);
return arr;
}, []);
return [
labelDisplays.coarseType,
labelDisplays.allocationStack,
].concat(custom);
- },
+ }
_getTreeMapDisplays() {
const customDisplays = getCustomTreeMapDisplays();
const custom = Object.keys(customDisplays).reduce((arr, key) => {
arr.push(customDisplays[key]);
return arr;
}, []);
return [
treeMapDisplays.coarseType
].concat(custom);
- },
+ }
render() {
let {
dispatch,
snapshots,
front,
heapWorker,
allocations,
@@ -312,18 +322,18 @@ const MemoryApp = createClass({
dispatch(resizeShortestPaths(newSize));
},
sizes,
view,
})
)
)
);
- },
-});
+ }
+}
/**
* Passed into react-redux's `connect` method that is called on store change
* and passed to components.
*/
function mapStateToProps(state) {
return state;
}
--- a/devtools/client/memory/components/Census.js
+++ b/devtools/client/memory/components/Census.js
@@ -1,32 +1,32 @@
/* 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 { createClass, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
+const { Component, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
const Tree = createFactory(require("devtools/client/shared/components/Tree"));
const CensusTreeItem = createFactory(require("./CensusTreeItem"));
const { TREE_ROW_HEIGHT } = require("../constants");
const { censusModel, diffingModel } = require("../models");
-module.exports = createClass({
- displayName: "Census",
-
- propTypes: {
- census: censusModel,
- onExpand: PropTypes.func.isRequired,
- onCollapse: PropTypes.func.isRequired,
- onFocus: PropTypes.func.isRequired,
- onViewSourceInDebugger: PropTypes.func.isRequired,
- onViewIndividuals: PropTypes.func.isRequired,
- diffing: diffingModel,
- },
+class Census extends Component {
+ static get propTypes() {
+ return {
+ census: censusModel,
+ onExpand: PropTypes.func.isRequired,
+ onCollapse: PropTypes.func.isRequired,
+ onFocus: PropTypes.func.isRequired,
+ onViewSourceInDebugger: PropTypes.func.isRequired,
+ onViewIndividuals: PropTypes.func.isRequired,
+ diffing: diffingModel,
+ };
+ }
render() {
let {
census,
onExpand,
onCollapse,
onFocus,
diffing,
@@ -72,9 +72,11 @@ module.exports = createClass({
inverted: census.display.inverted,
onViewIndividuals,
}),
getRoots: () => report.children || [],
getKey: node => node.id,
itemHeight: TREE_ROW_HEIGHT,
});
}
-});
+}
+
+module.exports = Census;
--- a/devtools/client/memory/components/CensusHeader.js
+++ b/devtools/client/memory/components/CensusHeader.js
@@ -1,24 +1,24 @@
/* 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 } = require("devtools/client/shared/vendor/react");
+const { DOM: dom, Component } = require("devtools/client/shared/vendor/react");
const { L10N } = require("../utils");
const models = require("../models");
-module.exports = createClass({
- displayName: "CensusHeader",
-
- propTypes: {
- diffing: models.diffingModel,
- },
+class CensusHeader extends Component {
+ static get propTypes() {
+ return {
+ diffing: models.diffingModel,
+ };
+ }
render() {
let individualsCell;
if (!this.props.diffing) {
individualsCell = dom.span({
className: "heap-tree-item-field heap-tree-item-individuals"
});
}
@@ -66,9 +66,11 @@ module.exports = createClass({
{
className: "heap-tree-item-name",
title: L10N.getStr("heapview.field.name.tooltip"),
},
L10N.getStr("heapview.field.name")
)
);
}
-});
+}
+
+module.exports = CensusHeader;
--- a/devtools/client/memory/components/CensusTreeItem.js
+++ b/devtools/client/memory/components/CensusTreeItem.js
@@ -1,49 +1,54 @@
/* 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 { isSavedFrame } = require("devtools/shared/DevToolsUtils");
const {
DOM: dom,
- createClass,
+ Component,
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 models = require("../models");
-module.exports = createClass({
- displayName: "CensusTreeItem",
+class CensusTreeItem extends Component {
+ static get propTypes() {
+ return {
+ arrow: PropTypes.any,
+ depth: PropTypes.number.isRequired,
+ diffing: models.app.diffing,
+ expanded: PropTypes.bool.isRequired,
+ focused: PropTypes.bool.isRequired,
+ getPercentBytes: PropTypes.func.isRequired,
+ getPercentCount: PropTypes.func.isRequired,
+ inverted: PropTypes.bool,
+ item: PropTypes.object.isRequired,
+ onViewIndividuals: PropTypes.func.isRequired,
+ onViewSourceInDebugger: PropTypes.func.isRequired,
+ };
+ }
- propTypes: {
- arrow: PropTypes.any,
- depth: PropTypes.number.isRequired,
- diffing: models.app.diffing,
- expanded: PropTypes.bool.isRequired,
- focused: PropTypes.bool.isRequired,
- getPercentBytes: PropTypes.func.isRequired,
- getPercentCount: PropTypes.func.isRequired,
- inverted: PropTypes.bool,
- item: PropTypes.object.isRequired,
- onViewIndividuals: PropTypes.func.isRequired,
- onViewSourceInDebugger: PropTypes.func.isRequired,
- },
+ constructor(props) {
+ super(props);
+ this.toLabel = this.toLabel.bind(this);
+ }
shouldComponentUpdate(nextProps, nextState) {
return this.props.item != nextProps.item
|| this.props.depth != nextProps.depth
|| this.props.expanded != nextProps.expanded
|| this.props.focused != nextProps.focused
|| this.props.diffing != nextProps.diffing;
- },
+ }
toLabel(name, linkToDebugger) {
if (isSavedFrame(name)) {
return Frame({
frame: name,
onClick: () => linkToDebugger(name),
showFunctionName: true,
showHost: true,
@@ -58,17 +63,17 @@ module.exports = createClass({
return L10N.getStr("tree-item.nostack");
}
if (name === "noFilename") {
return L10N.getStr("tree-item.nofilename");
}
return String(name);
- },
+ }
render() {
let {
item,
depth,
arrow,
focused,
getPercentBytes,
@@ -145,10 +150,12 @@ module.exports = createClass({
className: "heap-tree-item-field heap-tree-item-name",
style: { marginInlineStart: depth * TREE_ROW_HEIGHT }
},
arrow,
pointer,
this.toLabel(item.name, onViewSourceInDebugger)
)
);
- },
-});
+ }
+}
+
+module.exports = CensusTreeItem;
--- a/devtools/client/memory/components/DominatorTree.js
+++ b/devtools/client/memory/components/DominatorTree.js
@@ -1,42 +1,42 @@
/* 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, createFactory } = require("devtools/client/shared/vendor/react");
+const { DOM: dom, Component, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
const { assert } = require("devtools/shared/DevToolsUtils");
const { createParentMap } = require("devtools/shared/heapsnapshot/CensusUtils");
const Tree = createFactory(require("devtools/client/shared/components/Tree"));
const DominatorTreeItem = createFactory(require("./DominatorTreeItem"));
const { L10N } = require("../utils");
const { TREE_ROW_HEIGHT, dominatorTreeState } = require("../constants");
const { dominatorTreeModel } = require("../models");
const DominatorTreeLazyChildren = require("../dominator-tree-lazy-children");
const DOMINATOR_TREE_AUTO_EXPAND_DEPTH = 3;
/**
* A throbber that represents a subtree in the dominator tree that is actively
* being incrementally loaded and fetched from the `HeapAnalysesWorker`.
*/
-const DominatorTreeSubtreeFetching = createFactory(createClass({
- displayName: "DominatorTreeSubtreeFetching",
-
- propTypes: {
- depth: PropTypes.number.isRequired,
- focused: PropTypes.bool.isRequired,
- },
+class DominatorTreeSubtreeFetchingClass extends Component {
+ static get propTypes() {
+ return {
+ depth: PropTypes.number.isRequired,
+ focused: PropTypes.bool.isRequired,
+ };
+ }
shouldComponentUpdate(nextProps, nextState) {
return this.props.depth !== nextProps.depth
|| this.props.focused !== nextProps.focused;
- },
+ }
render() {
let {
depth,
focused,
} = this.props;
return dom.div(
@@ -46,36 +46,36 @@ const DominatorTreeSubtreeFetching = cre
dom.span({ className: "heap-tree-item-field heap-tree-item-bytes" }),
dom.span({ className: "heap-tree-item-field heap-tree-item-bytes" }),
dom.span({
className: "heap-tree-item-field heap-tree-item-name devtools-throbber",
style: { marginInlineStart: depth * TREE_ROW_HEIGHT }
})
);
}
-}));
+}
/**
* A link to fetch and load more siblings in the dominator tree, when there are
* already many loaded above.
*/
-const DominatorTreeSiblingLink = createFactory(createClass({
- displayName: "DominatorTreeSiblingLink",
-
- propTypes: {
- depth: PropTypes.number.isRequired,
- focused: PropTypes.bool.isRequired,
- item: PropTypes.instanceOf(DominatorTreeLazyChildren).isRequired,
- onLoadMoreSiblings: PropTypes.func.isRequired,
- },
+class DominatorTreeSiblingLinkClass extends Component {
+ static get propTypes() {
+ return {
+ depth: PropTypes.number.isRequired,
+ focused: PropTypes.bool.isRequired,
+ item: PropTypes.instanceOf(DominatorTreeLazyChildren).isRequired,
+ onLoadMoreSiblings: PropTypes.func.isRequired,
+ };
+ }
shouldComponentUpdate(nextProps, nextState) {
return this.props.depth !== nextProps.depth
|| this.props.focused !== nextProps.focused;
- },
+ }
render() {
let {
depth,
focused,
item,
onLoadMoreSiblings,
} = this.props;
@@ -95,42 +95,39 @@ const DominatorTreeSiblingLink = createF
{
onClick: () => onLoadMoreSiblings(item)
},
L10N.getStr("tree-item.load-more")
)
)
);
}
-}));
-
-/**
- * The actual dominator tree rendered as an expandable and collapsible tree.
- */
-module.exports = createClass({
- displayName: "DominatorTree",
+}
- propTypes: {
- dominatorTree: dominatorTreeModel.isRequired,
- onLoadMoreSiblings: PropTypes.func.isRequired,
- onViewSourceInDebugger: PropTypes.func.isRequired,
- onExpand: PropTypes.func.isRequired,
- onCollapse: PropTypes.func.isRequired,
- onFocus: PropTypes.func.isRequired,
- },
+class DominatorTree extends Component {
+ static get propTypes() {
+ return {
+ dominatorTree: dominatorTreeModel.isRequired,
+ onLoadMoreSiblings: PropTypes.func.isRequired,
+ onViewSourceInDebugger: PropTypes.func.isRequired,
+ onExpand: PropTypes.func.isRequired,
+ onCollapse: PropTypes.func.isRequired,
+ onFocus: PropTypes.func.isRequired,
+ };
+ }
shouldComponentUpdate(nextProps, nextState) {
// Safe to use referential equality here because all of our mutations on
// dominator tree models use immutableUpdate in a persistent manner. The
// exception to the rule are mutations of the expanded set, however we take
// care that the dominatorTree model itself is still re-allocated when
// mutations to the expanded set occur. Because of the re-allocations, we
// can continue using referential equality here.
return this.props.dominatorTree !== nextProps.dominatorTree;
- },
+ }
render() {
const { dominatorTree, onViewSourceInDebugger, onLoadMoreSiblings } = this.props;
const parentMap = createParentMap(dominatorTree.root, node => node.nodeId);
return Tree({
key: "dominator-tree-tree",
@@ -211,9 +208,14 @@ module.exports = createClass({
});
},
getRoots: () => [dominatorTree.root],
getKey: node =>
node instanceof DominatorTreeLazyChildren ? node.key() : node.nodeId,
itemHeight: TREE_ROW_HEIGHT,
});
}
-});
+}
+
+const DominatorTreeSubtreeFetching = createFactory(DominatorTreeSubtreeFetchingClass);
+const DominatorTreeSiblingLink = createFactory(DominatorTreeSiblingLinkClass);
+
+module.exports = DominatorTree;
--- a/devtools/client/memory/components/DominatorTreeHeader.js
+++ b/devtools/client/memory/components/DominatorTreeHeader.js
@@ -1,21 +1,21 @@
/* 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 } = require("devtools/client/shared/vendor/react");
+const { DOM: dom, Component } = require("devtools/client/shared/vendor/react");
const { L10N } = require("../utils");
-module.exports = createClass({
- displayName: "DominatorTreeHeader",
-
- propTypes: { },
+class DominatorTreeHeader extends Component {
+ static get propTypes() {
+ return { };
+ }
render() {
return dom.div(
{
className: "header"
},
dom.span(
@@ -38,9 +38,11 @@ module.exports = createClass({
{
className: "heap-tree-item-name",
title: L10N.getStr("dominatortree.field.label.tooltip"),
},
L10N.getStr("dominatortree.field.label")
)
);
}
-});
+}
+
+module.exports = DominatorTreeHeader;
--- a/devtools/client/memory/components/DominatorTreeItem.js
+++ b/devtools/client/memory/components/DominatorTreeItem.js
@@ -1,47 +1,47 @@
/* 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 { DOM: dom, createClass, createFactory, PropTypes } = require("devtools/client/shared/vendor/react");
+const { DOM: dom, Component, 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",
-
+class SeparatorClass extends Component {
render() {
return dom.span({ className: "separator" }, "›");
}
-}));
+}
-module.exports = createClass({
- displayName: "DominatorTreeItem",
+const Separator = createFactory(SeparatorClass);
- propTypes: {
- 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,
- },
+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() {
let {
item,
depth,
arrow,
focused,
getPercentSize,
@@ -136,10 +136,12 @@ module.exports = createClass({
style: { marginInlineStart: depth * TREE_ROW_HEIGHT }
},
arrow,
label,
dom.span({ className: "heap-tree-item-address" },
`@ 0x${item.nodeId.toString(16)}`)
)
);
- },
-});
+ }
+}
+
+module.exports = DominatorTreeItem;
--- a/devtools/client/memory/components/Heap.js
+++ b/devtools/client/memory/components/Heap.js
@@ -1,15 +1,15 @@
/* 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, createFactory } = require("devtools/client/shared/vendor/react");
+const { DOM: dom, Component, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
const { assert, safeErrorString } = require("devtools/shared/DevToolsUtils");
const Census = createFactory(require("./Census"));
const CensusHeader = createFactory(require("./CensusHeader"));
const DominatorTree = createFactory(require("./DominatorTree"));
const DominatorTreeHeader = createFactory(require("./DominatorTreeHeader"));
const TreeMap = createFactory(require("./TreeMap"));
const HSplitBox = createFactory(require("devtools/client/shared/components/HSplitBox"));
const Individuals = createFactory(require("./Individuals"));
@@ -175,39 +175,51 @@ function getError(snapshot, diffing, ind
/**
* Main view for the memory tool.
*
* The Heap component contains several panels for different states; an initial
* state of only a button to take a snapshot, loading states, the census view
* tree, the dominator tree, etc.
*/
-module.exports = createClass({
- displayName: "Heap",
+class Heap extends Component {
+ static get propTypes() {
+ return {
+ onSnapshotClick: PropTypes.func.isRequired,
+ onLoadMoreSiblings: PropTypes.func.isRequired,
+ onCensusExpand: PropTypes.func.isRequired,
+ onCensusCollapse: PropTypes.func.isRequired,
+ onDominatorTreeExpand: PropTypes.func.isRequired,
+ onDominatorTreeCollapse: PropTypes.func.isRequired,
+ onCensusFocus: PropTypes.func.isRequired,
+ onDominatorTreeFocus: PropTypes.func.isRequired,
+ onShortestPathsResize: PropTypes.func.isRequired,
+ snapshot: snapshotModel,
+ onViewSourceInDebugger: PropTypes.func.isRequired,
+ onPopView: PropTypes.func.isRequired,
+ individuals: models.individuals,
+ onViewIndividuals: PropTypes.func.isRequired,
+ onFocusIndividual: PropTypes.func.isRequired,
+ diffing: diffingModel,
+ view: models.view.isRequired,
+ sizes: PropTypes.object.isRequired,
+ };
+ }
- propTypes: {
- onSnapshotClick: PropTypes.func.isRequired,
- onLoadMoreSiblings: PropTypes.func.isRequired,
- onCensusExpand: PropTypes.func.isRequired,
- onCensusCollapse: PropTypes.func.isRequired,
- onDominatorTreeExpand: PropTypes.func.isRequired,
- onDominatorTreeCollapse: PropTypes.func.isRequired,
- onCensusFocus: PropTypes.func.isRequired,
- onDominatorTreeFocus: PropTypes.func.isRequired,
- onShortestPathsResize: PropTypes.func.isRequired,
- snapshot: snapshotModel,
- onViewSourceInDebugger: PropTypes.func.isRequired,
- onPopView: PropTypes.func.isRequired,
- individuals: models.individuals,
- onViewIndividuals: PropTypes.func.isRequired,
- onFocusIndividual: PropTypes.func.isRequired,
- diffing: diffingModel,
- view: models.view.isRequired,
- sizes: PropTypes.object.isRequired,
- },
+ constructor(props) {
+ super(props);
+ this._renderHeapView = this._renderHeapView.bind(this);
+ this._renderInitial = this._renderInitial.bind(this);
+ this._renderStatus = this._renderStatus.bind(this);
+ this._renderError = this._renderError.bind(this);
+ this._renderCensus = this._renderCensus.bind(this);
+ this._renderTreeMap = this._renderTreeMap.bind(this);
+ this._renderIndividuals = this._renderIndividuals.bind(this);
+ this._renderDominatorTree = this._renderDominatorTree.bind(this);
+ }
/**
* Render the heap view's container panel with the given contents inside of
* it.
*
* @param {snapshotState|diffingState|dominatorTreeState} state
* @param {...Any} contents
*/
@@ -220,50 +232,50 @@ module.exports = createClass({
dom.div(
{
className: "heap-view-panel",
"data-state": state,
},
...contents
)
);
- },
+ }
_renderInitial(onSnapshotClick) {
return this._renderHeapView("initial", dom.button(
{
className: "devtools-button take-snapshot",
onClick: onSnapshotClick,
"data-standalone": true,
},
L10N.getStr("take-snapshot")
));
- },
+ }
_renderStatus(state, statusText, diffing) {
let throbber = "";
if (shouldDisplayThrobber(diffing)) {
throbber = "devtools-throbber";
}
return this._renderHeapView(state, dom.span(
{
className: `snapshot-status ${throbber}`
},
statusText
));
- },
+ }
_renderError(state, statusText, error) {
return this._renderHeapView(
state,
dom.span({ className: "snapshot-status error" }, statusText),
dom.pre({}, safeErrorString(error))
);
- },
+ }
_renderCensus(state, census, diffing, onViewSourceInDebugger, onViewIndividuals) {
assert(census.report, "Should not render census that does not have a report");
if (!census.report.children) {
const censusFilterMsg = census.filter ? L10N.getStr("heapview.none-match")
: L10N.getStr("heapview.empty");
const msg = diffing ? L10N.getStr("heapview.no-difference")
@@ -288,24 +300,24 @@ module.exports = createClass({
diffing,
census,
onExpand: node => this.props.onCensusExpand(census, node),
onCollapse: node => this.props.onCensusCollapse(census, node),
onFocus: node => this.props.onCensusFocus(census, node),
}));
return this._renderHeapView(state, ...contents);
- },
+ }
_renderTreeMap(state, treeMap) {
return this._renderHeapView(
state,
TreeMap({ treeMap })
);
- },
+ }
_renderIndividuals(state, individuals, dominatorTree, onViewSourceInDebugger) {
assert(individuals.state === individualsState.FETCHED,
"Should have fetched individuals");
assert(dominatorTree && dominatorTree.root,
"Should have a dominator tree and its root");
const tree = dom.div(
@@ -350,17 +362,17 @@ module.exports = createClass({
),
HSplitBox({
start: tree,
end: shortestPaths,
startWidth: this.props.sizes.shortestPathsSize,
onResize: this.props.onShortestPathsResize,
})
);
- },
+ }
_renderDominatorTree(state, onViewSourceInDebugger, dominatorTree, onLoadMoreSiblings) {
const tree = dom.div(
{
className: "vbox",
style: {
overflowY: "auto"
}
@@ -386,17 +398,17 @@ module.exports = createClass({
state,
HSplitBox({
start: tree,
end: shortestPaths,
startWidth: this.props.sizes.shortestPathsSize,
onResize: this.props.onShortestPathsResize,
})
);
- },
+ }
render() {
let {
snapshot,
diffing,
onSnapshotClick,
onLoadMoreSiblings,
onViewSourceInDebugger,
@@ -449,10 +461,12 @@ module.exports = createClass({
"If we aren't in progress, looking at a census, or diffing, then we " +
"must be looking at a dominator tree");
assert(!diffing, "Should not have diffing");
assert(snapshot.dominatorTree, "Should have a dominator tree");
return this._renderDominatorTree(state, onViewSourceInDebugger,
snapshot.dominatorTree,
onLoadMoreSiblings);
- },
-});
+ }
+}
+
+module.exports = Heap;
--- a/devtools/client/memory/components/Individuals.js
+++ b/devtools/client/memory/components/Individuals.js
@@ -1,32 +1,32 @@
/* 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 { createClass, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
+const { Component, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
const Tree = createFactory(require("devtools/client/shared/components/Tree"));
const DominatorTreeItem = createFactory(require("./DominatorTreeItem"));
const { TREE_ROW_HEIGHT } = require("../constants");
const models = require("../models");
/**
* The list of individuals in a census group.
*/
-module.exports = createClass({
- displayName: "Individuals",
-
- propTypes: {
- onViewSourceInDebugger: PropTypes.func.isRequired,
- onFocus: PropTypes.func.isRequired,
- individuals: models.individuals,
- dominatorTree: models.dominatorTreeModel,
- },
+class Individuals extends Component {
+ static get propTypes() {
+ return {
+ onViewSourceInDebugger: PropTypes.func.isRequired,
+ onFocus: PropTypes.func.isRequired,
+ individuals: models.individuals,
+ dominatorTree: models.dominatorTreeModel,
+ };
+ }
render() {
const {
individuals,
dominatorTree,
onViewSourceInDebugger,
onFocus,
} = this.props;
@@ -52,9 +52,11 @@ module.exports = createClass({
onViewSourceInDebugger,
});
},
getRoots: () => individuals.nodes,
getKey: node => node.nodeId,
itemHeight: TREE_ROW_HEIGHT,
});
}
-});
+}
+
+module.exports = Individuals;
--- a/devtools/client/memory/components/IndividualsHeader.js
+++ b/devtools/client/memory/components/IndividualsHeader.js
@@ -1,21 +1,21 @@
/* 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 } = require("devtools/client/shared/vendor/react");
+const { DOM: dom, Component } = require("devtools/client/shared/vendor/react");
const { L10N } = require("../utils");
-module.exports = createClass({
- displayName: "IndividualsHeader",
-
- propTypes: { },
+class IndividualsHeader extends Component {
+ static get propTypes() {
+ return { };
+ }
render() {
return dom.div(
{
className: "header"
},
dom.span(
@@ -38,9 +38,11 @@ module.exports = createClass({
{
className: "heap-tree-item-name",
title: L10N.getStr("individuals.field.node.tooltip"),
},
L10N.getStr("individuals.field.node")
)
);
}
-});
+}
+
+module.exports = IndividualsHeader;
--- a/devtools/client/memory/components/List.js
+++ b/devtools/client/memory/components/List.js
@@ -1,37 +1,39 @@
/* 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 { DOM: dom, Component, PropTypes } = require("devtools/client/shared/vendor/react");
/**
* Generic list component that takes another react component to represent
* the children nodes as `itemComponent`, and a list of items to render
* as that component with a click handler.
*/
-module.exports = createClass({
- displayName: "List",
-
- propTypes: {
- itemComponent: PropTypes.any.isRequired,
- onClick: PropTypes.func,
- items: PropTypes.array.isRequired,
- },
+class List extends Component {
+ static get propTypes() {
+ return {
+ itemComponent: PropTypes.any.isRequired,
+ onClick: PropTypes.func,
+ items: PropTypes.array.isRequired,
+ };
+ }
render() {
let { items, onClick, itemComponent: Item } = this.props;
return (
dom.ul({ className: "list" }, ...items.map((item, index) => {
return Item(Object.assign({}, this.props, {
key: index,
item,
index,
onClick: () => onClick(item),
}));
}))
);
}
-});
+}
+
+module.exports = List;
--- a/devtools/client/memory/components/ShortestPaths.js
+++ b/devtools/client/memory/components/ShortestPaths.js
@@ -1,17 +1,17 @@
/* 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,
+ Component,
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],
@@ -45,51 +45,53 @@ function stringifyLabel(label, id) {
} else {
sanitized[i] = "" + piece;
}
}
return `${sanitized.join(" › ")} @ 0x${id.toString(16)}`;
}
-module.exports = createClass({
- displayName: "ShortestPaths",
+class ShortestPaths extends Component {
+ static get propTypes() {
+ return {
+ graph: PropTypes.shape({
+ nodes: PropTypes.arrayOf(PropTypes.object),
+ edges: PropTypes.arrayOf(PropTypes.object),
+ }),
+ };
+ }
- propTypes: {
- graph: PropTypes.shape({
- nodes: PropTypes.arrayOf(PropTypes.object),
- edges: PropTypes.arrayOf(PropTypes.object),
- }),
- },
-
- getInitialState() {
- return { zoom: null };
- },
+ constructor(props) {
+ super(props);
+ this.state = { zoom: null };
+ this._renderGraph = this._renderGraph.bind(this);
+ }
componentDidMount() {
if (this.props.graph) {
this._renderGraph(this.refs.container, this.props.graph);
}
- },
+ }
shouldComponentUpdate(nextProps) {
return this.props.graph != nextProps.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);
}
- },
+ }
_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%";
@@ -139,17 +141,17 @@ module.exports = createClass({
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);
- },
+ }
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",
@@ -177,10 +179,12 @@ module.exports = createClass({
{
id: "shortest-paths-header",
className: "header",
},
L10N.getStr("shortest-paths.header")
),
contents
);
- },
-});
+ }
+}
+
+module.exports = ShortestPaths;
--- a/devtools/client/memory/components/SnapshotListItem.js
+++ b/devtools/client/memory/components/SnapshotListItem.js
@@ -1,37 +1,37 @@
/* 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 { DOM: dom, Component, PropTypes } = require("devtools/client/shared/vendor/react");
const {
L10N,
getSnapshotTitle,
getSnapshotTotals,
getStatusText,
snapshotIsDiffable,
getSavedCensus
} = require("../utils");
const { diffingState } = require("../constants");
const { snapshot: snapshotModel, app: appModel } = require("../models");
-module.exports = createClass({
- displayName: "SnapshotListItem",
-
- propTypes: {
- onClick: PropTypes.func.isRequired,
- onSave: PropTypes.func.isRequired,
- onDelete: PropTypes.func.isRequired,
- item: snapshotModel.isRequired,
- index: PropTypes.number.isRequired,
- diffing: appModel.diffing,
- },
+class SnapshotListItem extends Component {
+ static get propTypes() {
+ return {
+ onClick: PropTypes.func.isRequired,
+ onSave: PropTypes.func.isRequired,
+ onDelete: PropTypes.func.isRequired,
+ item: snapshotModel.isRequired,
+ index: PropTypes.number.isRequired,
+ diffing: appModel.diffing,
+ };
+ }
render() {
let { item: snapshot, onClick, onSave, onDelete, diffing } = this.props;
let className = `snapshot-list-item ${snapshot.selected ? " selected" : ""}`;
let statusText = getStatusText(snapshot.state);
let wantThrobber = !!statusText;
let title = getSnapshotTitle(snapshot);
@@ -107,9 +107,11 @@ module.exports = createClass({
),
dom.span({ className: "snapshot-info" },
details,
saveLink
)
)
);
}
-});
+}
+
+module.exports = SnapshotListItem;
--- a/devtools/client/memory/components/Toolbar.js
+++ b/devtools/client/memory/components/Toolbar.js
@@ -1,54 +1,54 @@
/* 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 } = require("devtools/shared/DevToolsUtils");
-const { DOM: dom, createClass, PropTypes } = require("devtools/client/shared/vendor/react");
+const { DOM: dom, Component, PropTypes } = require("devtools/client/shared/vendor/react");
const { L10N } = require("../utils");
const models = require("../models");
const { viewState } = require("../constants");
-module.exports = createClass({
- displayName: "Toolbar",
-
- propTypes: {
- censusDisplays: PropTypes.arrayOf(PropTypes.shape({
- displayName: PropTypes.string.isRequired,
- })).isRequired,
- censusDisplay: PropTypes.shape({
- displayName: PropTypes.string.isRequired,
- }).isRequired,
- onTakeSnapshotClick: PropTypes.func.isRequired,
- onImportClick: PropTypes.func.isRequired,
- onClearSnapshotsClick: PropTypes.func.isRequired,
- onCensusDisplayChange: PropTypes.func.isRequired,
- onToggleRecordAllocationStacks: PropTypes.func.isRequired,
- allocations: models.allocations,
- filterString: PropTypes.string,
- setFilterString: PropTypes.func.isRequired,
- diffing: models.diffingModel,
- onToggleDiffing: PropTypes.func.isRequired,
- view: models.view.isRequired,
- onViewChange: PropTypes.func.isRequired,
- labelDisplays: PropTypes.arrayOf(PropTypes.shape({
- displayName: PropTypes.string.isRequired,
- })).isRequired,
- labelDisplay: PropTypes.shape({
- displayName: PropTypes.string.isRequired,
- }).isRequired,
- onLabelDisplayChange: PropTypes.func.isRequired,
- treeMapDisplays: PropTypes.arrayOf(PropTypes.shape({
- displayName: PropTypes.string.isRequired,
- })).isRequired,
- onTreeMapDisplayChange: PropTypes.func.isRequired,
- snapshots: PropTypes.arrayOf(models.snapshot).isRequired,
- },
+class Toolbar extends Component {
+ static get propTypes() {
+ return {
+ censusDisplays: PropTypes.arrayOf(PropTypes.shape({
+ displayName: PropTypes.string.isRequired,
+ })).isRequired,
+ censusDisplay: PropTypes.shape({
+ displayName: PropTypes.string.isRequired,
+ }).isRequired,
+ onTakeSnapshotClick: PropTypes.func.isRequired,
+ onImportClick: PropTypes.func.isRequired,
+ onClearSnapshotsClick: PropTypes.func.isRequired,
+ onCensusDisplayChange: PropTypes.func.isRequired,
+ onToggleRecordAllocationStacks: PropTypes.func.isRequired,
+ allocations: models.allocations,
+ filterString: PropTypes.string,
+ setFilterString: PropTypes.func.isRequired,
+ diffing: models.diffingModel,
+ onToggleDiffing: PropTypes.func.isRequired,
+ view: models.view.isRequired,
+ onViewChange: PropTypes.func.isRequired,
+ labelDisplays: PropTypes.arrayOf(PropTypes.shape({
+ displayName: PropTypes.string.isRequired,
+ })).isRequired,
+ labelDisplay: PropTypes.shape({
+ displayName: PropTypes.string.isRequired,
+ }).isRequired,
+ onLabelDisplayChange: PropTypes.func.isRequired,
+ treeMapDisplays: PropTypes.arrayOf(PropTypes.shape({
+ displayName: PropTypes.string.isRequired,
+ })).isRequired,
+ onTreeMapDisplayChange: PropTypes.func.isRequired,
+ snapshots: PropTypes.arrayOf(models.snapshot).isRequired,
+ };
+ }
render() {
let {
onTakeSnapshotClick,
onImportClick,
onClearSnapshotsClick,
onCensusDisplayChange,
censusDisplays,
@@ -293,9 +293,11 @@ module.exports = createClass({
L10N.getStr("checkbox.recordAllocationStacks")
),
viewSelect,
viewToolbarOptions
)
);
}
-});
+}
+
+module.exports = Toolbar;
--- a/devtools/client/memory/components/TreeMap.js
+++ b/devtools/client/memory/components/TreeMap.js
@@ -1,71 +1,76 @@
/* 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 } = require("devtools/client/shared/vendor/react");
+const { DOM: dom, Component } = require("devtools/client/shared/vendor/react");
const { treeMapModel } = require("../models");
const startVisualization = require("./tree-map/start");
-module.exports = createClass({
- displayName: "TreeMap",
+class TreeMap extends Component {
+ static get propTypes() {
+ return {
+ treeMap: treeMapModel
+ };
+ }
- propTypes: {
- treeMap: treeMapModel
- },
-
- getInitialState() {
- return {};
- },
+ constructor(props) {
+ super(props);
+ this.state = {};
+ this._stopVisualization = this._stopVisualization.bind(this);
+ this._startVisualization = this._startVisualization.bind(this);
+ }
componentDidMount() {
const { treeMap } = this.props;
if (treeMap && treeMap.report) {
this._startVisualization();
}
- },
+ }
shouldComponentUpdate(nextProps) {
const oldTreeMap = this.props.treeMap;
const newTreeMap = nextProps.treeMap;
return oldTreeMap !== newTreeMap;
- },
+ }
componentDidUpdate(prevProps) {
this._stopVisualization();
if (this.props.treeMap && this.props.treeMap.report) {
this._startVisualization();
}
- },
+ }
componentWillUnmount() {
if (this.state.stopVisualization) {
this.state.stopVisualization();
}
- },
+ }
_stopVisualization() {
if (this.state.stopVisualization) {
this.state.stopVisualization();
this.setState({ stopVisualization: null });
}
- },
+ }
_startVisualization() {
const { container } = this.refs;
const { report } = this.props.treeMap;
const stopVisualization = startVisualization(container, report);
this.setState({ stopVisualization });
- },
+ }
render() {
return dom.div(
{
ref: "container",
className: "tree-map-container"
}
);
}
-});
+}
+
+module.exports = TreeMap;