HighlightLine.js (4653B)
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 /** 6 * Uses of this panel are:- 7 * - Highlight line when source is opened using view source links from other panels 8 * - Highlight line with function or class from an Outline search result selection 9 * - Highlight line from a Quick open panel search result selection 10 * - Highlight the last selected line when a source is selected 11 * - Highlight the breakpoint line when the breakpoint is selected 12 */ 13 14 import { Component } from "devtools/client/shared/vendor/react"; 15 import PropTypes from "devtools/client/shared/vendor/react-prop-types"; 16 import { toEditorLine } from "../../utils/editor/index"; 17 18 import { connect } from "devtools/client/shared/vendor/react-redux"; 19 import { 20 getVisibleSelectedFrame, 21 getSelectedLocation, 22 getSelectedSourceTextContent, 23 getPauseCommand, 24 getCurrentThread, 25 getShouldHighlightSelectedLocation, 26 } from "../../selectors/index"; 27 28 function isDebugLine(selectedFrame, selectedLocation) { 29 if (!selectedFrame) { 30 return false; 31 } 32 33 return ( 34 selectedFrame.location.source.id == selectedLocation.source.id && 35 selectedFrame.location.line == selectedLocation.line 36 ); 37 } 38 39 export class HighlightLine extends Component { 40 isStepping = false; 41 previousEditorLine = null; 42 43 static get propTypes() { 44 return { 45 pauseCommand: PropTypes.oneOf([ 46 "expression", 47 "resume", 48 "stepOver", 49 "stepIn", 50 "stepOut", 51 ]), 52 selectedFrame: PropTypes.object, 53 selectedLocation: PropTypes.object.isRequired, 54 selectedSourceTextContent: PropTypes.object.isRequired, 55 shouldHighlightSelectedLocation: PropTypes.bool.isRequired, 56 editor: PropTypes.object, 57 }; 58 } 59 60 shouldComponentUpdate(nextProps) { 61 return this.shouldSetHighlightLine(nextProps); 62 } 63 64 componentDidUpdate(prevProps) { 65 this.highlightLine(prevProps); 66 } 67 68 componentDidMount() { 69 this.highlightLine(null); 70 } 71 72 shouldSetHighlightLine({ selectedLocation, selectedSourceTextContent }) { 73 const editorLine = toEditorLine( 74 selectedLocation.source, 75 selectedLocation.line 76 ); 77 78 if (!selectedLocation || !selectedSourceTextContent) { 79 return false; 80 } 81 82 if (this.isStepping && editorLine === this.previousEditorLine) { 83 return false; 84 } 85 86 return true; 87 } 88 89 highlightLine(prevProps) { 90 const { pauseCommand, shouldHighlightSelectedLocation } = this.props; 91 if (pauseCommand) { 92 this.isStepping = true; 93 } 94 95 if (prevProps) { 96 this.clearHighlightLine(prevProps); 97 } 98 if (shouldHighlightSelectedLocation) { 99 this.setHighlightLine(); 100 } 101 } 102 103 setHighlightLine() { 104 const { selectedLocation, selectedFrame, editor } = this.props; 105 if (!this.shouldSetHighlightLine(this.props)) { 106 return; 107 } 108 109 this.isStepping = false; 110 const editorLine = toEditorLine( 111 selectedLocation.source, 112 selectedLocation.line 113 ); 114 this.previousEditorLine = editorLine; 115 116 if ( 117 !selectedLocation.line || 118 isDebugLine(selectedFrame, selectedLocation) 119 ) { 120 return; 121 } 122 123 editor.setLineContentMarker({ 124 id: editor.markerTypes.HIGHLIGHT_LINE_MARKER, 125 lineClassName: "highlight-line", 126 lines: [{ line: editorLine }], 127 }); 128 this.clearHighlightLineAfterDuration(); 129 } 130 131 clearHighlightLineAfterDuration() { 132 const editorWrapper = document.querySelector(".editor-wrapper"); 133 134 if (editorWrapper === null) { 135 return; 136 } 137 138 const duration = parseInt( 139 getComputedStyle(editorWrapper).getPropertyValue( 140 "--highlight-line-duration" 141 ), 142 10 143 ); 144 145 setTimeout(() => this.clearHighlightLine(this.props), duration); 146 } 147 148 clearHighlightLine({ selectedLocation, selectedSourceTextContent }) { 149 if (!selectedLocation || !selectedSourceTextContent) { 150 return; 151 } 152 153 const { editor } = this.props; 154 if (!editor) { 155 return; 156 } 157 editor.removeLineContentMarker("highlight-line-marker"); 158 } 159 160 render() { 161 return null; 162 } 163 } 164 165 export default connect(state => { 166 const selectedLocation = getSelectedLocation(state); 167 if (!selectedLocation) { 168 return {}; 169 } 170 return { 171 pauseCommand: getPauseCommand(state, getCurrentThread(state)), 172 shouldHighlightSelectedLocation: getShouldHighlightSelectedLocation(state), 173 selectedFrame: getVisibleSelectedFrame(state), 174 selectedLocation, 175 selectedSourceTextContent: getSelectedSourceTextContent(state), 176 }; 177 })(HighlightLine);