editor-breakpoint.js (8867B)
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 { showMenu } from "../../context-menu/menu"; 6 import { getSelectedLocation } from "../../utils/selected-location"; 7 import { features } from "../../utils/prefs"; 8 import { isLineBlackboxed } from "../../utils/source"; 9 const { 10 stringifyFromElectronKey, 11 } = require("resource://devtools/client/shared/key-shortcuts.js"); 12 13 import { 14 getSelectedSource, 15 getBlackBoxRanges, 16 isSourceMapIgnoreListEnabled, 17 isSourceOnSourceMapIgnoreList, 18 } from "../../selectors/index"; 19 import { 20 addBreakpoint, 21 removeBreakpoint, 22 setBreakpointOptions, 23 } from "../../actions/breakpoints/modify"; 24 import { 25 enableBreakpointsAtLine, 26 disableBreakpointsAtLine, 27 toggleDisabledBreakpoint, 28 removeBreakpointsAtLine, 29 } from "../../actions/breakpoints/index"; 30 import { openConditionalPanel } from "../../actions/ui"; 31 32 export function showEditorEditBreakpointContextMenu(event, breakpoint) { 33 return async ({ dispatch, getState }) => { 34 const state = getState(); 35 const selectedSource = getSelectedSource(state); 36 const selectedLocation = getSelectedLocation(breakpoint, selectedSource); 37 const blackboxedRanges = getBlackBoxRanges(state); 38 const blackboxedRangesForSelectedSource = 39 blackboxedRanges[selectedSource.url]; 40 const isSelectedSourceOnIgnoreList = 41 selectedSource && 42 isSourceMapIgnoreListEnabled(state) && 43 isSourceOnSourceMapIgnoreList(state, selectedSource); 44 45 const items = [ 46 removeBreakpointItem(breakpoint, dispatch), 47 toggleDisabledBreakpointItem( 48 breakpoint, 49 blackboxedRangesForSelectedSource, 50 isSelectedSourceOnIgnoreList, 51 dispatch 52 ), 53 ]; 54 55 if (breakpoint.originalText.startsWith("debugger")) { 56 items.push( 57 { type: "separator" }, 58 toggleDbgStatementItem(selectedLocation, breakpoint, dispatch) 59 ); 60 } 61 62 items.push( 63 { type: "separator" }, 64 removeBreakpointsOnLineItem(selectedLocation, dispatch), 65 breakpoint.disabled 66 ? enableBreakpointsOnLineItem( 67 selectedLocation, 68 blackboxedRangesForSelectedSource, 69 isSelectedSourceOnIgnoreList, 70 dispatch 71 ) 72 : disableBreakpointsOnLineItem(selectedLocation, dispatch), 73 { type: "separator" } 74 ); 75 76 items.push( 77 conditionalBreakpointItem(breakpoint, selectedLocation, dispatch) 78 ); 79 items.push(logPointItem(breakpoint, selectedLocation, dispatch)); 80 81 showMenu(event, items); 82 }; 83 } 84 85 export function showEditorCreateBreakpointContextMenu( 86 event, 87 location, 88 lineText 89 ) { 90 return async ({ dispatch }) => { 91 const items = createBreakpointItems(location, lineText, dispatch); 92 93 showMenu(event, items); 94 }; 95 } 96 97 export function createBreakpointItems(location, lineText, dispatch) { 98 const items = [ 99 addBreakpointItem(location, dispatch), 100 addConditionalBreakpointItem(location, dispatch), 101 ]; 102 103 if (features.logPoints) { 104 items.push(addLogPointItem(location, dispatch)); 105 } 106 107 if (lineText && lineText.startsWith("debugger")) { 108 items.push(toggleDbgStatementItem(location, null, dispatch)); 109 } 110 return items; 111 } 112 113 const addBreakpointItem = (location, dispatch) => ({ 114 id: "node-menu-add-breakpoint", 115 label: L10N.getStr("editor.addBreakpoint"), 116 accesskey: L10N.getStr("shortcuts.toggleBreakpoint.accesskey"), 117 disabled: false, 118 click: () => dispatch(addBreakpoint(location)), 119 accelerator: stringifyFromElectronKey(L10N.getStr("toggleBreakpoint.key")), 120 }); 121 122 const removeBreakpointItem = (breakpoint, dispatch) => ({ 123 id: "node-menu-remove-breakpoint", 124 label: L10N.getStr("editor.removeBreakpoint"), 125 accesskey: L10N.getStr("shortcuts.toggleBreakpoint.accesskey"), 126 disabled: false, 127 click: () => dispatch(removeBreakpoint(breakpoint)), 128 accelerator: stringifyFromElectronKey(L10N.getStr("toggleBreakpoint.key")), 129 }); 130 131 const addConditionalBreakpointItem = (location, dispatch) => ({ 132 id: "node-menu-add-conditional-breakpoint", 133 label: L10N.getStr("editor.addConditionBreakpoint"), 134 accelerator: stringifyFromElectronKey( 135 L10N.getStr("toggleCondPanel.breakpoint.key") 136 ), 137 accesskey: L10N.getStr("editor.addConditionBreakpoint.accesskey"), 138 disabled: false, 139 click: () => dispatch(openConditionalPanel(location)), 140 }); 141 142 const editConditionalBreakpointItem = (location, dispatch) => ({ 143 id: "node-menu-edit-conditional-breakpoint", 144 label: L10N.getStr("editor.editConditionBreakpoint"), 145 accelerator: stringifyFromElectronKey( 146 L10N.getStr("toggleCondPanel.breakpoint.key") 147 ), 148 accesskey: L10N.getStr("editor.addConditionBreakpoint.accesskey"), 149 disabled: false, 150 click: () => dispatch(openConditionalPanel(location)), 151 }); 152 153 const conditionalBreakpointItem = (breakpoint, location, dispatch) => { 154 const { 155 options: { condition }, 156 } = breakpoint; 157 return condition 158 ? editConditionalBreakpointItem(location, dispatch) 159 : addConditionalBreakpointItem(location, dispatch); 160 }; 161 162 const addLogPointItem = (location, dispatch) => ({ 163 id: "node-menu-add-log-point", 164 label: L10N.getStr("editor.addLogPoint"), 165 accesskey: L10N.getStr("editor.addLogPoint.accesskey"), 166 disabled: false, 167 click: () => dispatch(openConditionalPanel(location, true)), 168 accelerator: stringifyFromElectronKey( 169 L10N.getStr("toggleCondPanel.logPoint.key") 170 ), 171 }); 172 173 const editLogPointItem = (location, dispatch) => ({ 174 id: "node-menu-edit-log-point", 175 label: L10N.getStr("editor.editLogPoint"), 176 accesskey: L10N.getStr("editor.editLogPoint.accesskey"), 177 disabled: false, 178 click: () => dispatch(openConditionalPanel(location, true)), 179 accelerator: stringifyFromElectronKey( 180 L10N.getStr("toggleCondPanel.logPoint.key") 181 ), 182 }); 183 184 const logPointItem = (breakpoint, location, dispatch) => { 185 const { 186 options: { logValue }, 187 } = breakpoint; 188 return logValue 189 ? editLogPointItem(location, dispatch) 190 : addLogPointItem(location, dispatch); 191 }; 192 193 const toggleDisabledBreakpointItem = ( 194 breakpoint, 195 blackboxedRangesForSelectedSource, 196 isSelectedSourceOnIgnoreList, 197 dispatch 198 ) => { 199 return { 200 accesskey: L10N.getStr("editor.disableBreakpoint.accesskey"), 201 disabled: isLineBlackboxed( 202 blackboxedRangesForSelectedSource, 203 breakpoint.location.line, 204 isSelectedSourceOnIgnoreList 205 ), 206 click: () => dispatch(toggleDisabledBreakpoint(breakpoint)), 207 ...(breakpoint.disabled 208 ? { 209 id: "node-menu-enable-breakpoint", 210 label: L10N.getStr("editor.enableBreakpoint"), 211 } 212 : { 213 id: "node-menu-disable-breakpoint", 214 label: L10N.getStr("editor.disableBreakpoint"), 215 }), 216 }; 217 }; 218 219 const toggleDbgStatementItem = (location, breakpoint, dispatch) => { 220 if (breakpoint && breakpoint.options.condition === "false") { 221 return { 222 disabled: false, 223 id: "node-menu-enable-dbgStatement", 224 label: L10N.getStr("breakpointMenuItem.enabledbg.label"), 225 click: () => 226 dispatch( 227 setBreakpointOptions(location, { 228 ...breakpoint.options, 229 condition: null, 230 }) 231 ), 232 }; 233 } 234 235 return { 236 disabled: false, 237 id: "node-menu-disable-dbgStatement", 238 label: L10N.getStr("breakpointMenuItem.disabledbg.label"), 239 click: () => 240 dispatch( 241 setBreakpointOptions(location, { 242 condition: "false", 243 }) 244 ), 245 }; 246 }; 247 248 // ToDo: Only enable if there are more than one breakpoints on a line? 249 const removeBreakpointsOnLineItem = (location, dispatch) => ({ 250 id: "node-menu-remove-breakpoints-on-line", 251 label: L10N.getStr("breakpointMenuItem.removeAllAtLine.label"), 252 accesskey: L10N.getStr("breakpointMenuItem.removeAllAtLine.accesskey"), 253 disabled: false, 254 click: () => 255 dispatch(removeBreakpointsAtLine(location.source, location.line)), 256 }); 257 258 const enableBreakpointsOnLineItem = ( 259 location, 260 blackboxedRangesForSelectedSource, 261 isSelectedSourceOnIgnoreList, 262 dispatch 263 ) => ({ 264 id: "node-menu-remove-breakpoints-on-line", 265 label: L10N.getStr("breakpointMenuItem.enableAllAtLine.label"), 266 accesskey: L10N.getStr("breakpointMenuItem.enableAllAtLine.accesskey"), 267 disabled: isLineBlackboxed( 268 blackboxedRangesForSelectedSource, 269 location.line, 270 isSelectedSourceOnIgnoreList 271 ), 272 click: () => 273 dispatch(enableBreakpointsAtLine(location.source, location.line)), 274 }); 275 276 const disableBreakpointsOnLineItem = (location, dispatch) => ({ 277 id: "node-menu-remove-breakpoints-on-line", 278 label: L10N.getStr("breakpointMenuItem.disableAllAtLine.label"), 279 accesskey: L10N.getStr("breakpointMenuItem.disableAllAtLine.accesskey"), 280 disabled: false, 281 click: () => 282 dispatch(disableBreakpointsAtLine(location.source, location.line)), 283 });