TracePanel.js (4543B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ 4 5 import { Component } from "devtools/client/shared/vendor/react"; 6 import { 7 button, 8 div, 9 span, 10 } from "devtools/client/shared/vendor/react-dom-factories"; 11 import ReactDOM from "devtools/client/shared/vendor/react-dom"; 12 import PropTypes from "devtools/client/shared/vendor/react-prop-types"; 13 import { connect } from "devtools/client/shared/vendor/react-redux"; 14 import { toEditorLine } from "../../utils/editor/index"; 15 import actions from "../../actions/index"; 16 17 import { 18 getSelectedTraceLocation, 19 getAllTraces, 20 getSelectedTraceIndex, 21 getSelectedLocationTraces, 22 } from "../../selectors/index"; 23 24 export class TracePanel extends Component { 25 constructor() { 26 super(); 27 } 28 29 static get propTypes() { 30 return { 31 editor: PropTypes.object.isRequired, 32 selectedTraceLocation: PropTypes.any.isRequired, 33 }; 34 } 35 36 shouldComponentUpdate(nextProps) { 37 return ( 38 nextProps.selectedTraceLocation.source.id != 39 this.props.selectedTraceLocation.source.id || 40 nextProps.selectedTraceLocation.line != 41 this.props.selectedTraceLocation.line || 42 nextProps.allTraces.length != this.props.allTraces.length || 43 nextProps.selectedTraceLocationTraces !== 44 this.props.selectedTraceLocationTraces || 45 nextProps.selectedTraceIndex != this.props.selectedTraceIndex 46 ); 47 } 48 49 // FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=1774507 50 UNSAFE_componentWillMount() { 51 return this.renderToWidget(this.props); 52 } 53 54 // FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=1774507 55 UNSAFE_componentWillUpdate() {} 56 57 componentDidUpdate() { 58 this.renderToWidget(this.props); 59 } 60 61 componentWillUnmount() { 62 const { editor } = this.props; 63 editor.removeLineContentMarker(editor.markerTypes.TRACE_MARKER); 64 } 65 66 renderToWidget(props) { 67 const { selectedTraceLocation, editor } = props; 68 69 editor.removeLineContentMarker(editor.markerTypes.TRACE_MARKER); 70 71 if (!selectedTraceLocation || !this.props.selectedTraceLocationTraces) { 72 return; 73 } 74 75 const editorLine = toEditorLine( 76 selectedTraceLocation.source.id, 77 selectedTraceLocation.line || 0 78 ); 79 editor.setLineContentMarker({ 80 id: editor.markerTypes.TRACE_MARKER, 81 lines: [{ line: editorLine }], 82 renderAsBlock: true, 83 createLineElementNode: () => { 84 return this.renderTracePanel(this.props); 85 }, 86 }); 87 } 88 89 renderTracePanel() { 90 const panel = document.createElement("aside"); 91 panel.className = "trace-inline-panel-container"; 92 93 const { allTraces, selectedTraceLocationTraces, selectedTraceIndex } = 94 this.props; 95 const traceButtons = []; 96 const selectedIndex = selectedTraceLocationTraces.indexOf( 97 allTraces[selectedTraceIndex] 98 ); 99 const startIndex = selectedIndex == -1 ? 0 : Math.max(0, selectedIndex - 5); 100 const lastIndex = Math.min( 101 selectedTraceLocationTraces.length, 102 startIndex + 10 103 ); 104 for (let traceIndex = startIndex; traceIndex < lastIndex; traceIndex++) { 105 const selected = traceIndex === selectedIndex; 106 traceButtons.push( 107 button( 108 { 109 key: `${traceIndex}-${selected}`, 110 className: `trace-item${selected ? " selected" : ""}`, 111 112 onClick: () => { 113 this.props.selectTrace( 114 allTraces.indexOf(selectedTraceLocationTraces[traceIndex]) 115 ); 116 }, 117 }, 118 traceIndex + 1 119 ) 120 ); 121 } 122 const traceCount = this.props.selectedTraceLocationTraces.length; 123 ReactDOM.render( 124 div( 125 { className: "trace-panel" }, 126 span(null, `${traceCount} execution${traceCount > 1 ? "s" : ""}: `), 127 traceButtons 128 ), 129 panel 130 ); 131 return panel; 132 } 133 134 render() { 135 return null; 136 } 137 } 138 139 const mapStateToProps = state => { 140 const selectedTraceLocation = getSelectedTraceLocation(state); 141 142 const allTraces = getAllTraces(state); 143 const selectedTraceIndex = getSelectedTraceIndex(state); 144 const selectedTraceLocationTraces = getSelectedLocationTraces(state); 145 146 return { 147 selectedTraceLocation, 148 allTraces, 149 selectedTraceLocationTraces, 150 selectedTraceIndex, 151 }; 152 }; 153 154 const mapDispatchToProps = { 155 selectTrace: actions.selectTrace, 156 }; 157 158 export default connect(mapStateToProps, mapDispatchToProps)(TracePanel);