Breakpoints.js (4682B)
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 PropTypes from "devtools/client/shared/vendor/react-prop-types"; 6 import { Component } from "devtools/client/shared/vendor/react"; 7 8 import { 9 getSelectedSource, 10 getFirstVisibleBreakpoints, 11 } from "../../selectors/index"; 12 import { getSelectedLocation } from "../../utils/selected-location"; 13 import { connect } from "devtools/client/shared/vendor/react-redux"; 14 import { fromEditorLine } from "../../utils/editor/index"; 15 import actions from "../../actions/index"; 16 const classnames = require("resource://devtools/client/shared/classnames.js"); 17 18 const isMacOS = Services.appinfo.OS === "Darwin"; 19 20 class Breakpoints extends Component { 21 static get propTypes() { 22 return { 23 breakpoints: PropTypes.array, 24 editor: PropTypes.object, 25 selectedSource: PropTypes.object, 26 removeBreakpointsAtLine: PropTypes.func, 27 toggleBreakpointsAtLine: PropTypes.func, 28 continueToHere: PropTypes.func, 29 showEditorEditBreakpointContextMenu: PropTypes.func, 30 }; 31 } 32 33 constructor(props) { 34 super(props); 35 } 36 37 componentDidMount() { 38 this.setMarkers(); 39 } 40 41 componentDidUpdate() { 42 this.setMarkers(); 43 } 44 45 setMarkers() { 46 const { selectedSource, editor, breakpoints } = this.props; 47 48 if (!selectedSource || !breakpoints || !editor) { 49 return; 50 } 51 52 const isSourceWasm = editor.isWasm; 53 const wasmLineFormatter = editor.getWasmLineNumberFormatter(); 54 const markers = [ 55 { 56 id: editor.markerTypes.GUTTER_BREAKPOINT_MARKER, 57 lineClassName: "cm6-gutter-breakpoint", 58 condition: line => { 59 const lineNumber = fromEditorLine(selectedSource, line); 60 const breakpoint = breakpoints.find( 61 bp => getSelectedLocation(bp, selectedSource).line === lineNumber 62 ); 63 if (!breakpoint) { 64 return false; 65 } 66 return breakpoint; 67 }, 68 createLineElementNode: (line, breakpoint) => { 69 const lineNumber = fromEditorLine(selectedSource, line); 70 const displayLineNumber = 71 isSourceWasm && !selectedSource.isOriginal 72 ? wasmLineFormatter(line) 73 : lineNumber; 74 75 const breakpointNode = document.createElement("div"); 76 breakpointNode.appendChild( 77 document.createTextNode(displayLineNumber) 78 ); 79 breakpointNode.className = classnames("breakpoint-marker", { 80 "breakpoint-disabled": breakpoint.disabled, 81 "has-condition": breakpoint?.options.condition, 82 "has-log": breakpoint?.options.logValue, 83 }); 84 breakpointNode.onclick = event => this.onClick(event, breakpoint); 85 breakpointNode.oncontextmenu = event => 86 this.onContextMenu(event, breakpoint); 87 return breakpointNode; 88 }, 89 }, 90 ]; 91 editor.setLineGutterMarkers(markers); 92 } 93 94 onClick = (event, breakpoint) => { 95 const { 96 continueToHere, 97 toggleBreakpointsAtLine, 98 removeBreakpointsAtLine, 99 selectedSource, 100 } = this.props; 101 102 event.stopPropagation(); 103 event.preventDefault(); 104 105 // ignore right clicks when clicking on the breakpoint 106 if (event.button === 2) { 107 return; 108 } 109 110 const selectedLocation = getSelectedLocation(breakpoint, selectedSource); 111 const ctrlOrCmd = isMacOS ? event.metaKey : event.ctrlKey; 112 113 if (ctrlOrCmd) { 114 continueToHere(selectedLocation); 115 return; 116 } 117 118 if (event.shiftKey) { 119 toggleBreakpointsAtLine(!breakpoint.disabled, selectedLocation.line); 120 return; 121 } 122 123 removeBreakpointsAtLine(selectedLocation.source, selectedLocation.line); 124 }; 125 126 onContextMenu = (event, breakpoint) => { 127 event.stopPropagation(); 128 event.preventDefault(); 129 130 this.props.showEditorEditBreakpointContextMenu(event, breakpoint); 131 }; 132 133 render() { 134 return null; 135 } 136 } 137 138 const mapStateToProps = state => { 139 const selectedSource = getSelectedSource(state); 140 return { 141 // Retrieves only the first breakpoint per line so that the 142 // breakpoint marker represents only the first breakpoint 143 breakpoints: getFirstVisibleBreakpoints(state), 144 selectedSource, 145 }; 146 }; 147 148 export default connect(mapStateToProps, { 149 showEditorEditBreakpointContextMenu: 150 actions.showEditorEditBreakpointContextMenu, 151 continueToHere: actions.continueToHere, 152 toggleBreakpointsAtLine: actions.toggleBreakpointsAtLine, 153 removeBreakpointsAtLine: actions.removeBreakpointsAtLine, 154 })(Breakpoints);