Chromium Code Reviews| Index: third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js |
| diff --git a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js |
| index 46310859b8332b71005a7c9b91259332d1ebc768..71fbe43c95c03154b719b01867ad2ee8d22c5e35 100644 |
| --- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js |
| +++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js |
| @@ -54,9 +54,9 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| WebInspector.SourcesTextEditor.Events.GutterClick, this._handleGutterClick.bind(this), this); |
| this._breakpointManager.addEventListener( |
| - WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this); |
| + WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointChanged, this); |
| this._breakpointManager.addEventListener( |
| - WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this); |
| + WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointChanged, this); |
| this.uiSourceCode().addEventListener( |
| WebInspector.UISourceCode.Events.SourceMappingChanged, this._onSourceMappingChanged, this); |
| @@ -67,6 +67,10 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| this.uiSourceCode().addEventListener( |
| WebInspector.UISourceCode.Events.TitleChanged, this._showBlackboxInfobarIfNeeded, this); |
| + /** @type {!Set<number>} */ |
| + this._scheduledBreakpointDecorationsUpdates = new Set(); |
| + this._inlineBreakpointSymbol = Symbol('inline-breakpoint'); |
| + |
| /** @type {!Map.<!WebInspector.Target, !WebInspector.ResourceScriptFile>}*/ |
| this._scriptFileForTarget = new Map(); |
| var targets = WebInspector.targetManager.targets(); |
| @@ -266,19 +270,36 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| WebInspector.UIString('Never pause here'), |
| this._createNewBreakpoint.bind(this, lineNumber, 'false', true)); |
| } else { |
| - var breakpoint = breakpoints[0]; |
| - |
| - // This row has a breakpoint, we want to show edit and remove breakpoint, and either disable or enable. |
| - contextMenu.appendItem(WebInspector.UIString('Remove breakpoint'), breakpoint.remove.bind(breakpoint)); |
| - contextMenu.appendItem( |
| - WebInspector.UIString('Edit breakpoint…'), |
| - this._editBreakpointCondition.bind(this, lineNumber, breakpoint)); |
| - if (breakpoint.enabled()) |
| - contextMenu.appendItem( |
| - WebInspector.UIString('Disable breakpoint'), breakpoint.setEnabled.bind(breakpoint, false)); |
| - else |
| + if (breakpoints.length === 1) { |
|
lushnikov
2016/11/11 19:56:00
nit: can we make it non-nested?
|
| + var breakpoint = breakpoints[0]; |
| + // This row has a breakpoint, we want to show edit and remove breakpoint, and either disable or enable. |
| + contextMenu.appendItem(WebInspector.UIString('Remove breakpoint'), breakpoint.remove.bind(breakpoint)); |
| contextMenu.appendItem( |
| - WebInspector.UIString('Enable breakpoint'), breakpoint.setEnabled.bind(breakpoint, true)); |
| + WebInspector.UIString('Edit breakpoint…'), |
|
lushnikov
2016/11/11 19:56:00
nit: use \u.. for unicode
|
| + this._editBreakpointCondition.bind(this, lineNumber, breakpoint)); |
| + if (breakpoint.enabled()) |
| + contextMenu.appendItem( |
| + WebInspector.UIString('Disable breakpoint'), breakpoint.setEnabled.bind(breakpoint, false)); |
| + else |
| + contextMenu.appendItem( |
| + WebInspector.UIString('Enable breakpoint'), breakpoint.setEnabled.bind(breakpoint, true)); |
| + } else { |
| + var hasEnabled = breakpoints.some(breakpoint => breakpoint.enabled()); |
| + if (hasEnabled) { |
| + contextMenu.appendItem( |
| + WebInspector.UIString('Disable breakpoints in line'), |
| + () => breakpoints.map(breakpoint => breakpoint.setEnabled(false))); |
| + } |
| + var hasDisabled = breakpoints.some(breakpoint => !breakpoint.enabled()); |
| + if (hasDisabled) { |
| + contextMenu.appendItem( |
| + WebInspector.UIString('Enable breakpoints in line'), |
| + () => breakpoints.map(breakpoint => breakpoint.setEnabled(true))); |
| + } |
| + |
| + var breakpoint = breakpoints[0]; |
| + |
| + } |
| } |
| resolve(); |
| } |
| @@ -328,9 +349,6 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| } |
| _workingCopyChanged(event) { |
| - if (this._supportsEnabledBreakpointsWhileEditing() || this._scriptFileForTarget.size) |
|
lushnikov
2016/11/11 19:56:00
where did this go?
|
| - return; |
| - |
| if (this.uiSourceCode().isDirty()) |
| this._muteBreakpointsWhileEditing(); |
| else |
| @@ -339,23 +357,16 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| _workingCopyCommitted(event) { |
| this._scriptsPanel.updateLastModificationTime(); |
| - if (this._supportsEnabledBreakpointsWhileEditing()) |
| - return; |
| - |
| if (!this._scriptFileForTarget.size) |
| this._restoreBreakpointsAfterEditing(); |
| } |
| _didMergeToVM() { |
| - if (this._supportsEnabledBreakpointsWhileEditing()) |
| - return; |
| this._updateDivergedInfobar(); |
| this._restoreBreakpointsIfConsistentScripts(); |
| } |
| _didDivergeFromVM() { |
| - if (this._supportsEnabledBreakpointsWhileEditing()) |
| - return; |
| this._updateDivergedInfobar(); |
| this._muteBreakpointsWhileEditing(); |
| } |
| @@ -363,15 +374,8 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| _muteBreakpointsWhileEditing() { |
| if (this._muted) |
| return; |
| - for (var lineNumber = 0; lineNumber < this._textEditor.linesCount; ++lineNumber) { |
| - var breakpointDecoration = this._textEditor.getAttribute(lineNumber, 'breakpoint'); |
| - if (!breakpointDecoration) |
| - continue; |
| - this._removeBreakpointDecoration(lineNumber); |
| - this._addBreakpointDecoration( |
| - lineNumber, breakpointDecoration.columnNumber, breakpointDecoration.condition, breakpointDecoration.enabled, |
| - true); |
| - } |
| + for (var lineNumber = 0; lineNumber < this._textEditor.linesCount; ++lineNumber) |
|
lushnikov
2016/11/11 19:56:00
that's unfortunate. Maybe it's time to teach edito
|
| + this._scheduleBreakpointDecorationsUpdate(lineNumber); |
| this._muted = true; |
| } |
| @@ -395,10 +399,6 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| } |
| } |
| - _supportsEnabledBreakpointsWhileEditing() { |
| - return this.uiSourceCode().project().type() === WebInspector.projectTypes.Snippets; |
| - } |
| - |
| _restoreBreakpointsIfConsistentScripts() { |
| var scriptFiles = this._scriptFileForTarget.valuesArray(); |
| for (var i = 0; i < scriptFiles.length; ++i) |
| @@ -410,28 +410,12 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| _restoreBreakpointsAfterEditing() { |
| delete this._muted; |
| - var breakpoints = {}; |
| - // Save and remove muted breakpoint decorations. |
| - for (var lineNumber = 0; lineNumber < this._textEditor.linesCount; ++lineNumber) { |
| - var breakpointDecoration = this._textEditor.getAttribute(lineNumber, 'breakpoint'); |
| - if (breakpointDecoration) { |
| - breakpoints[lineNumber] = breakpointDecoration; |
| - this._removeBreakpointDecoration(lineNumber); |
| - } |
| - } |
| - |
| - // Remove all breakpoints. |
| - this._removeAllBreakpoints(); |
| - // Restore all breakpoints from saved decorations. |
| - for (var lineNumberString in breakpoints) { |
| - var lineNumber = parseInt(lineNumberString, 10); |
| - if (isNaN(lineNumber)) |
| - continue; |
| - var breakpointDecoration = breakpoints[lineNumberString]; |
| - this._setBreakpoint( |
| - lineNumber, breakpointDecoration.columnNumber, breakpointDecoration.condition, breakpointDecoration.enabled); |
| - } |
| + var allBreakpoints = this._breakpointManager.breakpointsForUISourceCode(this.uiSourceCode()); |
| + for (var breakpoint of allBreakpoints) |
| + breakpoint.remove(); |
| + for (var breakpoint of allBreakpoints) |
| + this._createNewBreakpoint(breakpoint.lineNumber(), breakpoint.condition(), breakpoint.enabled()); |
| } |
| _removeAllBreakpoints() { |
| @@ -564,27 +548,6 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| delete this._popoverAnchorBox; |
| } |
| - /** |
| - * @param {number} lineNumber |
| - * @param {number} columnNumber |
| - * @param {string} condition |
| - * @param {boolean} enabled |
| - * @param {boolean} mutedWhileEditing |
| - */ |
| - _addBreakpointDecoration(lineNumber, columnNumber, condition, enabled, mutedWhileEditing) { |
| - var breakpoint = {condition: condition, enabled: enabled, columnNumber: columnNumber}; |
| - |
| - this.textEditor.setAttribute(lineNumber, 'breakpoint', breakpoint); |
| - |
| - var disabled = !enabled || mutedWhileEditing; |
| - this.textEditor.addBreakpoint(lineNumber, disabled, !!condition); |
| - } |
| - |
| - _removeBreakpointDecoration(lineNumber) { |
| - this.textEditor.removeAttribute(lineNumber, 'breakpoint'); |
| - this.textEditor.removeBreakpoint(lineNumber); |
| - } |
| - |
| _onKeyDown(event) { |
| if (event.key === 'Escape') { |
| if (this._popoverHelper.isPopoverVisible()) { |
| @@ -612,9 +575,10 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| if (!committed) |
| return; |
| - if (breakpoint) |
| + if (breakpoint) { |
| breakpoint.setCondition(newText); |
| - else |
| + breakpoint.setEnabled(true); |
| + } else |
| this._createNewBreakpoint(lineNumber, newText, true); |
| } |
| @@ -832,45 +796,85 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| this._valueWidgets.clear(); |
| } |
| - /** |
| - * @return {boolean} |
| - */ |
| - _shouldIgnoreExternalBreakpointEvents() { |
| - if (this._supportsEnabledBreakpointsWhileEditing()) |
| - return false; |
| - if (this._muted) |
| - return true; |
| - var scriptFiles = this._scriptFileForTarget.valuesArray(); |
| - for (var i = 0; i < scriptFiles.length; ++i) { |
| - if (scriptFiles[i].isDivergingFromVM() || scriptFiles[i].isMergingToVM()) |
| - return true; |
| - } |
| - return false; |
| - } |
| - |
| - _breakpointAdded(event) { |
| + _breakpointChanged(event) { |
| var uiLocation = /** @type {!WebInspector.UILocation} */ (event.data.uiLocation); |
| if (uiLocation.uiSourceCode !== this.uiSourceCode()) |
| return; |
| - if (this._shouldIgnoreExternalBreakpointEvents()) |
| + this._scheduleBreakpointDecorationsUpdate(uiLocation.lineNumber); |
| + } |
| + |
| + _scheduleBreakpointDecorationsUpdate(lineNumber) { |
| + if (this._scheduledBreakpointDecorationsUpdates.has(lineNumber)) |
| return; |
| + if (!this._scheduledBreakpointDecorationsUpdates.size) |
| + setImmediate(() => this.textEditor.operation(update.bind(this))); |
| + this._scheduledBreakpointDecorationsUpdates.add(lineNumber); |
| - var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint); |
| - if (this.loaded) |
| - this._addBreakpointDecoration( |
| - uiLocation.lineNumber, uiLocation.columnNumber, breakpoint.condition(), breakpoint.enabled(), false); |
| + /** |
| + * @this {!WebInspector.JavaScriptSourceFrame} |
| + */ |
| + function update() { |
| + for (var lineNumber of this._scheduledBreakpointDecorationsUpdates) |
| + this._updateBreakpointDecorations(lineNumber); |
| + this._scheduledBreakpointDecorationsUpdates.clear(); |
| + } |
| } |
| - _breakpointRemoved(event) { |
| - var uiLocation = /** @type {!WebInspector.UILocation} */ (event.data.uiLocation); |
| - if (uiLocation.uiSourceCode !== this.uiSourceCode()) |
| + /** |
| + * @param {number} lineNumber |
| + */ |
| + _updateBreakpointDecorations(lineNumber) { |
| + if (lineNumber >= this.textEditor.linesCount) |
| return; |
| - if (this._shouldIgnoreExternalBreakpointEvents()) |
| + var lineLength = this.textEditor.line(lineNumber).length; |
| + var bookmarks = this.textEditor.bookmarks(new WebInspector.TextRange(lineNumber, 0, lineNumber, lineLength), this._inlineBreakpointSymbol); |
| + for (var bookmark of bookmarks) |
| + bookmark.clear(); |
| + |
| + var breakpoints = this._breakpointManager.findBreakpoints(this.uiSourceCode(), lineNumber); |
| + breakpoints.sort((breakpoint1, breakpoint2) => breakpoint1.columnNumber() - breakpoint2.columnNumber()); |
|
lushnikov
2016/11/11 19:56:00
why do you need to sort them?
|
| + var hasEnabled = breakpoints.some(breakpoint => breakpoint.enabled()); |
| + var hasConditional = breakpoints.some(breakpoint => !!breakpoint.condition()); |
| + var hasEnabledConditional = breakpoints.some(breakpoint => !!breakpoint.condition() && breakpoint.enabled()); |
| + |
| + if (!breakpoints.length) { |
| + this.textEditor.toggleLineClass(lineNumber, 'cm-breakpoint', false); |
| return; |
| + } |
| + this.textEditor.toggleLineClass(lineNumber, 'cm-breakpoint', true); |
| + this.textEditor.toggleLineClass(lineNumber, 'cm-breakpoint-conditional', hasEnabledConditional || (!hasEnabled && hasConditional)); |
| + this.textEditor.toggleLineClass(lineNumber, 'cm-breakpoint-disabled', !hasEnabled || this._muted); |
| + if (breakpoints.length <= 1 || this._muted) |
| + return; |
| + for (var i = 0; i < breakpoints.length; ++i) { |
| + let breakpoint = breakpoints[i]; |
| + var inlineBreakpoint = WebInspector.InlineBreakpoint.create(); |
| + inlineBreakpoint.setEnabled(breakpoint.enabled() || this._muted); |
| + inlineBreakpoint.setConditional(!!breakpoint.condition()); |
| + inlineBreakpoint.addEventListener('click', () => breakpoint.setEnabled(!breakpoint.enabled()), true); |
| + inlineBreakpoint.addEventListener('contextmenu', this._populateInlineBreakpointMenu.bind(this, breakpoint), true); |
| + this.textEditor.addBookmark(breakpoint.lineNumber(), breakpoint.columnNumber(), inlineBreakpoint, this._inlineBreakpointSymbol); |
| + } |
| + } |
| - var remainingBreakpoints = this._breakpointManager.findBreakpoints(this.uiSourceCode(), uiLocation.lineNumber); |
| - if (!remainingBreakpoints.length && this.loaded) |
| - this._removeBreakpointDecoration(uiLocation.lineNumber); |
| + /** |
| + * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint |
| + * @param {!Event} event |
| + */ |
| + _populateInlineBreakpointMenu(breakpoint, event) { |
| + event.consume(true); |
| + var contextMenu = new WebInspector.ContextMenu(event); |
| + if (!breakpoint.enabled()) { |
| + contextMenu.appendItem(WebInspector.UIString('Never pause here'), () => { |
| + breakpoint.setCondition('false'); breakpoint.setEnabled(true); |
| + }); |
| + } |
| + var conditionalBreakpointTitle = breakpoint.enabled() ? WebInspector.UIString('Edit breakpoint…') |
| + : WebInspector.UIString('Add conditional breakpoint…'); |
| + contextMenu.appendItem( |
| + conditionalBreakpointTitle, |
| + this._editBreakpointCondition.bind(this, breakpoint.lineNumber(), breakpoint)); |
| + contextMenu.show(); |
| } |
| /** |
| @@ -944,7 +948,7 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| var breakpointLocations = this._breakpointManager.breakpointLocationsForUISourceCode(this.uiSourceCode()); |
| for (var i = 0; i < breakpointLocations.length; ++i) |
| - this._breakpointAdded({data: breakpointLocations[i]}); |
| + this._breakpointChanged({data: breakpointLocations[i]}); |
| var scriptFiles = this._scriptFileForTarget.valuesArray(); |
| for (var i = 0; i < scriptFiles.length; ++i) |
| @@ -1017,12 +1021,15 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| _toggleBreakpoint(lineNumber, onlyDisable) { |
| var breakpoints = this._breakpointManager.findBreakpoints(this.uiSourceCode(), lineNumber); |
| if (breakpoints.length) { |
| - if (onlyDisable) |
| - breakpoints[0].setEnabled(!breakpoints[0].enabled()); |
| - else |
| - breakpoints[0].remove(); |
| - } else |
| + for (var breakpoint of breakpoints) { |
| + if (onlyDisable) |
| + breakpoint.setEnabled(false); |
| + else |
| + breakpoint.remove(); |
| + } |
| + } else { |
| this._createNewBreakpoint(lineNumber, '', true); |
| + } |
| } |
| /** |
| @@ -1069,10 +1076,13 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| * @param {?Array<!WebInspector.UILocation>} locations |
| */ |
| function setBreakpoint(locations) { |
| - if (!locations || !locations.length) |
| + if (!locations || !locations.length) { |
| this._setBreakpoint(lineNumber, 0, condition, enabled); |
| - else |
| - this._setBreakpoint(locations[0].lineNumber, locations[0].columnNumber, condition, enabled); |
| + WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.ScriptsBreakpointSet); |
| + return; |
| + } |
| + for (var i = 0; i < locations.length; ++i) |
| + this._setBreakpoint(locations[i].lineNumber, locations[i].columnNumber, condition, enabled && i === 0); |
| WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.ScriptsBreakpointSet); |
| } |
| } |
| @@ -1115,9 +1125,9 @@ WebInspector.JavaScriptSourceFrame = class extends WebInspector.UISourceCodeFram |
| */ |
| dispose() { |
| this._breakpointManager.removeEventListener( |
| - WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this); |
| + WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointChanged, this); |
| this._breakpointManager.removeEventListener( |
| - WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this); |
| + WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointChanged, this); |
| this.uiSourceCode().removeEventListener( |
| WebInspector.UISourceCode.Events.SourceMappingChanged, this._onSourceMappingChanged, this); |
| this.uiSourceCode().removeEventListener( |