breakpoint.js (13044B)
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 { buildMenu, showMenu } from "../../context-menu/menu"; 6 import { getSelectedLocation } from "../../utils/selected-location"; 7 import { isLineBlackboxed } from "../../utils/source"; 8 import { features } from "../../utils/prefs"; 9 const { 10 stringifyFromElectronKey, 11 } = require("resource://devtools/client/shared/key-shortcuts.js"); 12 13 import { 14 getBreakpointsList, 15 getSelectedSource, 16 getBlackBoxRanges, 17 isSourceMapIgnoreListEnabled, 18 isSourceOnSourceMapIgnoreList, 19 } from "../../selectors/index"; 20 21 import { 22 removeBreakpoint, 23 setBreakpointOptions, 24 } from "../../actions/breakpoints/modify"; 25 import { 26 removeBreakpoints, 27 removeAllBreakpoints, 28 toggleBreakpoints, 29 toggleAllBreakpoints, 30 toggleDisabledBreakpoint, 31 } from "../../actions/breakpoints/index"; 32 import { selectSpecificLocation } from "../../actions/sources/select"; 33 import { openConditionalPanel } from "../../actions/ui"; 34 35 export function showBreakpointContextMenu(event, breakpoint, source) { 36 return async ({ dispatch, getState }) => { 37 const state = getState(); 38 const breakpoints = getBreakpointsList(state); 39 const blackboxedRanges = getBlackBoxRanges(state); 40 const blackboxedRangesForSource = blackboxedRanges[source.url]; 41 const checkSourceOnIgnoreList = _source => 42 isSourceMapIgnoreListEnabled(state) && 43 isSourceOnSourceMapIgnoreList(state, _source); 44 const selectedSource = getSelectedSource(state); 45 46 const deleteSelfLabel = L10N.getStr("breakpointMenuItem.deleteSelf2.label"); 47 const deleteAllLabel = L10N.getStr("breakpointMenuItem.deleteAll2.label"); 48 const deleteOthersLabel = L10N.getStr( 49 "breakpointMenuItem.deleteOthers2.label" 50 ); 51 const enableSelfLabel = L10N.getStr("breakpointMenuItem.enableSelf2.label"); 52 const enableAllLabel = L10N.getStr("breakpointMenuItem.enableAll2.label"); 53 const enableOthersLabel = L10N.getStr( 54 "breakpointMenuItem.enableOthers2.label" 55 ); 56 const disableSelfLabel = L10N.getStr( 57 "breakpointMenuItem.disableSelf2.label" 58 ); 59 const disableAllLabel = L10N.getStr("breakpointMenuItem.disableAll2.label"); 60 const disableOthersLabel = L10N.getStr( 61 "breakpointMenuItem.disableOthers2.label" 62 ); 63 const enableDbgStatementLabel = L10N.getStr( 64 "breakpointMenuItem.enabledbg.label" 65 ); 66 const disableDbgStatementLabel = L10N.getStr( 67 "breakpointMenuItem.disabledbg.label" 68 ); 69 const removeConditionLabel = L10N.getStr( 70 "breakpointMenuItem.removeCondition2.label" 71 ); 72 const addConditionLabel = L10N.getStr( 73 "breakpointMenuItem.addCondition2.label" 74 ); 75 const editConditionLabel = L10N.getStr( 76 "breakpointMenuItem.editCondition2.label" 77 ); 78 79 const deleteSelfKey = L10N.getStr( 80 "breakpointMenuItem.deleteSelf2.accesskey" 81 ); 82 const deleteAllKey = L10N.getStr("breakpointMenuItem.deleteAll2.accesskey"); 83 const deleteOthersKey = L10N.getStr( 84 "breakpointMenuItem.deleteOthers2.accesskey" 85 ); 86 const enableSelfKey = L10N.getStr( 87 "breakpointMenuItem.enableSelf2.accesskey" 88 ); 89 const enableAllKey = L10N.getStr("breakpointMenuItem.enableAll2.accesskey"); 90 const enableOthersKey = L10N.getStr( 91 "breakpointMenuItem.enableOthers2.accesskey" 92 ); 93 const disableSelfKey = L10N.getStr( 94 "breakpointMenuItem.disableSelf2.accesskey" 95 ); 96 const disableAllKey = L10N.getStr( 97 "breakpointMenuItem.disableAll2.accesskey" 98 ); 99 const disableOthersKey = L10N.getStr( 100 "breakpointMenuItem.disableOthers2.accesskey" 101 ); 102 const removeConditionKey = L10N.getStr( 103 "breakpointMenuItem.removeCondition2.accesskey" 104 ); 105 const editConditionKey = L10N.getStr( 106 "breakpointMenuItem.editCondition2.accesskey" 107 ); 108 const addConditionKey = L10N.getStr( 109 "breakpointMenuItem.addCondition2.accesskey" 110 ); 111 112 const selectedLocation = getSelectedLocation(breakpoint, selectedSource); 113 const otherBreakpoints = breakpoints.filter(b => b.id !== breakpoint.id); 114 const enabledBreakpoints = breakpoints.filter(b => !b.disabled); 115 const disabledBreakpoints = breakpoints.filter(b => b.disabled); 116 const otherEnabledBreakpoints = breakpoints.filter( 117 b => !b.disabled && b.id !== breakpoint.id 118 ); 119 const otherDisabledBreakpoints = breakpoints.filter( 120 b => b.disabled && b.id !== breakpoint.id 121 ); 122 123 const deleteSelfItem = { 124 id: "node-menu-delete-self", 125 label: deleteSelfLabel, 126 accesskey: deleteSelfKey, 127 disabled: false, 128 click: () => { 129 dispatch(removeBreakpoint(breakpoint)); 130 }, 131 }; 132 133 const deleteAllItem = { 134 id: "node-menu-delete-all", 135 label: deleteAllLabel, 136 accesskey: deleteAllKey, 137 disabled: false, 138 click: () => dispatch(removeAllBreakpoints()), 139 }; 140 141 const deleteOthersItem = { 142 id: "node-menu-delete-other", 143 label: deleteOthersLabel, 144 accesskey: deleteOthersKey, 145 disabled: false, 146 click: () => dispatch(removeBreakpoints(otherBreakpoints)), 147 }; 148 149 const enableSelfItem = { 150 id: "node-menu-enable-self", 151 label: enableSelfLabel, 152 accesskey: enableSelfKey, 153 disabled: isLineBlackboxed( 154 blackboxedRangesForSource, 155 breakpoint.location.line, 156 checkSourceOnIgnoreList(breakpoint.location.source) 157 ), 158 click: () => { 159 dispatch(toggleDisabledBreakpoint(breakpoint)); 160 }, 161 }; 162 163 const enableAllItem = { 164 id: "node-menu-enable-all", 165 label: enableAllLabel, 166 accesskey: enableAllKey, 167 disabled: isLineBlackboxed( 168 blackboxedRangesForSource, 169 breakpoint.location.line, 170 checkSourceOnIgnoreList(breakpoint.location.source) 171 ), 172 click: () => dispatch(toggleAllBreakpoints(false)), 173 }; 174 175 const enableOthersItem = { 176 id: "node-menu-enable-others", 177 label: enableOthersLabel, 178 accesskey: enableOthersKey, 179 disabled: isLineBlackboxed( 180 blackboxedRangesForSource, 181 breakpoint.location.line, 182 checkSourceOnIgnoreList(breakpoint.location.source) 183 ), 184 click: () => dispatch(toggleBreakpoints(false, otherDisabledBreakpoints)), 185 }; 186 187 const disableSelfItem = { 188 id: "node-menu-disable-self", 189 label: disableSelfLabel, 190 accesskey: disableSelfKey, 191 disabled: false, 192 click: () => { 193 dispatch(toggleDisabledBreakpoint(breakpoint)); 194 }, 195 }; 196 197 const disableAllItem = { 198 id: "node-menu-disable-all", 199 label: disableAllLabel, 200 accesskey: disableAllKey, 201 disabled: false, 202 click: () => dispatch(toggleAllBreakpoints(true)), 203 }; 204 205 const disableOthersItem = { 206 id: "node-menu-disable-others", 207 label: disableOthersLabel, 208 accesskey: disableOthersKey, 209 click: () => dispatch(toggleBreakpoints(true, otherEnabledBreakpoints)), 210 }; 211 212 const enableDbgStatementItem = { 213 id: "node-menu-enable-dbgStatement", 214 label: enableDbgStatementLabel, 215 disabled: false, 216 click: () => 217 dispatch( 218 setBreakpointOptions(selectedLocation, { 219 ...breakpoint.options, 220 condition: null, 221 }) 222 ), 223 }; 224 225 const disableDbgStatementItem = { 226 id: "node-menu-disable-dbgStatement", 227 label: disableDbgStatementLabel, 228 disabled: false, 229 click: () => 230 dispatch( 231 setBreakpointOptions(selectedLocation, { 232 ...breakpoint.options, 233 condition: "false", 234 }) 235 ), 236 }; 237 238 const removeConditionItem = { 239 id: "node-menu-remove-condition", 240 label: removeConditionLabel, 241 accesskey: removeConditionKey, 242 disabled: false, 243 click: () => 244 dispatch( 245 setBreakpointOptions(selectedLocation, { 246 ...breakpoint.options, 247 condition: null, 248 }) 249 ), 250 }; 251 252 const addConditionItem = { 253 id: "node-menu-add-condition", 254 label: addConditionLabel, 255 accesskey: addConditionKey, 256 click: async () => { 257 await dispatch(selectSpecificLocation(selectedLocation)); 258 await dispatch(openConditionalPanel(selectedLocation)); 259 }, 260 accelerator: stringifyFromElectronKey( 261 L10N.getStr("toggleCondPanel.breakpoint.key") 262 ), 263 }; 264 265 const editConditionItem = { 266 id: "node-menu-edit-condition", 267 label: editConditionLabel, 268 accesskey: editConditionKey, 269 click: async () => { 270 await dispatch(selectSpecificLocation(selectedLocation)); 271 await dispatch(openConditionalPanel(selectedLocation)); 272 }, 273 accelerator: stringifyFromElectronKey( 274 L10N.getStr("toggleCondPanel.breakpoint.key") 275 ), 276 }; 277 278 const addLogPointItem = { 279 id: "node-menu-add-log-point", 280 label: L10N.getStr("editor.addLogPoint"), 281 accesskey: L10N.getStr("editor.addLogPoint.accesskey"), 282 disabled: false, 283 click: async () => { 284 await dispatch(selectSpecificLocation(selectedLocation)); 285 await dispatch(openConditionalPanel(selectedLocation, true)); 286 }, 287 accelerator: stringifyFromElectronKey( 288 L10N.getStr("toggleCondPanel.logPoint.key") 289 ), 290 }; 291 292 const editLogPointItem = { 293 id: "node-menu-edit-log-point", 294 label: L10N.getStr("editor.editLogPoint"), 295 accesskey: L10N.getStr("editor.editLogPoint.accesskey"), 296 disabled: false, 297 click: async () => { 298 await dispatch(selectSpecificLocation(selectedLocation)); 299 await dispatch(openConditionalPanel(selectedLocation, true)); 300 }, 301 accelerator: stringifyFromElectronKey( 302 L10N.getStr("toggleCondPanel.logPoint.key") 303 ), 304 }; 305 306 const removeLogPointItem = { 307 id: "node-menu-remove-log", 308 label: L10N.getStr("editor.removeLogPoint.label"), 309 accesskey: L10N.getStr("editor.removeLogPoint.accesskey"), 310 disabled: false, 311 click: () => 312 dispatch( 313 setBreakpointOptions(selectedLocation, { 314 ...breakpoint.options, 315 logValue: null, 316 }) 317 ), 318 }; 319 320 const logPointItem = breakpoint.options.logValue 321 ? editLogPointItem 322 : addLogPointItem; 323 324 const hideEnableSelfItem = !breakpoint.disabled; 325 const hideEnableAllItem = disabledBreakpoints.length === 0; 326 const hideEnableOthersItem = otherDisabledBreakpoints.length === 0; 327 const hideDisableAllItem = enabledBreakpoints.length === 0; 328 const hideDisableOthersItem = otherEnabledBreakpoints.length === 0; 329 const hideDisableSelfItem = breakpoint.disabled; 330 const hideEnableDbgStatementItem = 331 !breakpoint.originalText.startsWith("debugger") || 332 (breakpoint.originalText.startsWith("debugger") && 333 breakpoint.options.condition !== "false"); 334 const hideDisableDbgStatementItem = 335 !breakpoint.originalText.startsWith("debugger") || 336 (breakpoint.originalText.startsWith("debugger") && 337 breakpoint.options.condition === "false"); 338 const items = [ 339 { item: enableSelfItem, hidden: () => hideEnableSelfItem }, 340 { item: enableAllItem, hidden: () => hideEnableAllItem }, 341 { item: enableOthersItem, hidden: () => hideEnableOthersItem }, 342 { 343 item: { type: "separator" }, 344 hidden: () => 345 hideEnableSelfItem && hideEnableAllItem && hideEnableOthersItem, 346 }, 347 { item: deleteSelfItem }, 348 { item: deleteAllItem }, 349 { item: deleteOthersItem, hidden: () => breakpoints.length === 1 }, 350 { 351 item: { type: "separator" }, 352 hidden: () => 353 hideDisableSelfItem && hideDisableAllItem && hideDisableOthersItem, 354 }, 355 356 { item: disableSelfItem, hidden: () => hideDisableSelfItem }, 357 { item: disableAllItem, hidden: () => hideDisableAllItem }, 358 { item: disableOthersItem, hidden: () => hideDisableOthersItem }, 359 { 360 item: { type: "separator" }, 361 }, 362 { 363 item: enableDbgStatementItem, 364 hidden: () => hideEnableDbgStatementItem, 365 }, 366 { 367 item: disableDbgStatementItem, 368 hidden: () => hideDisableDbgStatementItem, 369 }, 370 { 371 item: { type: "separator" }, 372 hidden: () => hideDisableDbgStatementItem && hideEnableDbgStatementItem, 373 }, 374 { 375 item: addConditionItem, 376 hidden: () => breakpoint.options.condition, 377 }, 378 { 379 item: editConditionItem, 380 hidden: () => !breakpoint.options.condition, 381 }, 382 { 383 item: removeConditionItem, 384 hidden: () => !breakpoint.options.condition, 385 }, 386 { 387 item: logPointItem, 388 hidden: () => !features.logPoints, 389 }, 390 { 391 item: removeLogPointItem, 392 hidden: () => !features.logPoints || !breakpoint.options.logValue, 393 }, 394 ]; 395 396 showMenu(event, buildMenu(items)); 397 }; 398 }