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 86fd83ac9dd4e3ed4802260a5036b5e518e9ef3b..84f38c1938304b22cf03861f0ab5b3deaddbc198 100644 |
| --- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js |
| +++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js |
| @@ -54,6 +54,7 @@ Sources.JavaScriptSourceFrame = class extends SourceFrame.UISourceCodeFrame { |
| this.textEditor.element.addEventListener('keydown', this._onKeyDown.bind(this), true); |
| this.textEditor.element.addEventListener('keyup', this._onKeyUp.bind(this), true); |
| this.textEditor.element.addEventListener('mousemove', this._onMouseMove.bind(this), false); |
| + this.textEditor.element.addEventListener('mousedown', this._onMouseDown.bind(this), true); |
| if (Runtime.experiments.isEnabled('continueToLocationMarkers')) { |
| this.textEditor.element.addEventListener('wheel', event => { |
| if (UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) |
| @@ -92,6 +93,8 @@ Sources.JavaScriptSourceFrame = class extends SourceFrame.UISourceCodeFrame { |
| this.onBindingChanged(); |
| Bindings.debuggerWorkspaceBinding.addEventListener( |
| Bindings.DebuggerWorkspaceBinding.Events.SourceMappingChanged, this._onSourceMappingChanged, this); |
| + /** @type {?Map<!Object, !Function>} */ |
| + this._continueToLocationDecorations = null; |
| } |
| /** |
| @@ -382,10 +385,12 @@ Sources.JavaScriptSourceFrame = class extends SourceFrame.UISourceCodeFrame { |
| } |
| /** |
| - * @param {!Event} event |
| + * @param {!MouseEvent} event |
| * @return {?UI.PopoverRequest} |
| */ |
| _getPopoverRequest(event) { |
| + if (UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) |
| + return null; |
| var target = UI.context.flavor(SDK.Target); |
| var debuggerModel = target ? target.model(SDK.DebuggerModel) : null; |
| if (!debuggerModel || !debuggerModel.isPaused()) |
| @@ -488,10 +493,8 @@ Sources.JavaScriptSourceFrame = class extends SourceFrame.UISourceCodeFrame { |
| return; |
| } |
| if (UI.KeyboardShortcut.eventHasCtrlOrMeta(event) && this._executionLocation) { |
| - if (!this._continueToLocationShown) { |
| + if (!this._continueToLocationDecorations) |
| this._showContinueToLocations(); |
| - this._continueToLocationShown = true; |
| - } |
| } |
| } |
| @@ -500,11 +503,31 @@ Sources.JavaScriptSourceFrame = class extends SourceFrame.UISourceCodeFrame { |
| */ |
| _onMouseMove(event) { |
| if (this._executionLocation && UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) { |
| - if (!this._continueToLocationShown) { |
| + if (!this._continueToLocationDecorations) |
| this._showContinueToLocations(); |
| - this._continueToLocationShown = true; |
| - } |
| + } |
| + } |
| + |
| + /** |
| + * @param {!MouseEvent} event |
| + */ |
| + _onMouseDown(event) { |
| + if (!this._executionLocation || !UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) |
| + return; |
| + if (!this._continueToLocationDecorations) |
| return; |
| + event.consume(); |
| + var textPosition = this.textEditor.coordinatesToCursorPosition(event.x, event.y); |
| + if (!textPosition) |
| + return; |
| + for (var decoration of this._continueToLocationDecorations.keys()) { |
| + var range = decoration.find(); |
| + if (range.from.line !== textPosition.startLine || range.to.line !== textPosition.startLine) |
| + continue; |
| + if (range.from.ch <= textPosition.startColumn && textPosition.startColumn <= range.to.ch) { |
| + this._continueToLocationDecorations.get(decoration)(); |
| + break; |
| + } |
| } |
| } |
| @@ -514,10 +537,7 @@ Sources.JavaScriptSourceFrame = class extends SourceFrame.UISourceCodeFrame { |
| _onKeyUp(event) { |
| if (UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) |
| return; |
| - if (!this._continueToLocationShown) |
| - return; |
| this._clearContinueToLocations(); |
| - this._continueToLocationShown = false; |
| } |
| /** |
| @@ -583,7 +603,7 @@ Sources.JavaScriptSourceFrame = class extends SourceFrame.UISourceCodeFrame { |
| setImmediate(() => { |
| this._generateValuesInSource(); |
| if (Runtime.experiments.isEnabled('continueToLocationMarkers')) { |
| - if (this._continueToLocationShown) |
| + if (this._continueToLocationDecorations) |
| this._showContinueToLocations(); |
| } |
| }); |
| @@ -616,77 +636,45 @@ Sources.JavaScriptSourceFrame = class extends SourceFrame.UISourceCodeFrame { |
| _showContinueToLocations() { |
| if (!Runtime.experiments.isEnabled('continueToLocationMarkers')) |
| return; |
| + this._popoverHelper.hidePopover(); |
| var executionContext = UI.context.flavor(SDK.ExecutionContext); |
| if (!executionContext) |
| return; |
| var callFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame); |
| if (!callFrame) |
| return; |
| - if (this._clearContinueToLocationsTimer) { |
| - clearTimeout(this._clearContinueToLocationsTimer); |
| - delete this._clearContinueToLocationsTimer; |
| - } |
| var localScope = callFrame.localScope(); |
| if (!localScope) { |
| - this.textEditor.operation(clearExistingLocations.bind(this)); |
| + this._clearContinueToLocations(); |
| return; |
| } |
| var start = localScope.startLocation(); |
| var end = localScope.endLocation(); |
| var debuggerModel = callFrame.debuggerModel; |
| - var executionLocation = callFrame.location(); |
| debuggerModel.getPossibleBreakpoints(start, end, true) |
| .then(locations => this.textEditor.operation(renderLocations.bind(this, locations))); |
| + |
| /** |
| * @param {!Array<!SDK.DebuggerModel.BreakLocation>} locations |
| * @this {Sources.JavaScriptSourceFrame} |
| */ |
| function renderLocations(locations) { |
| - clearExistingLocations.call(this); |
| + this._clearContinueToLocations(); |
| + this._continueToLocationDecorations = new Map(); |
| for (var location of locations) { |
| - var icon; |
| - var isCurrent = location.lineNumber === executionLocation.lineNumber && |
| - location.columnNumber === executionLocation.columnNumber; |
| - if (!isCurrent || (location.type !== SDK.DebuggerModel.BreakLocationType.Call && |
| - location.type !== SDK.DebuggerModel.BreakLocationType.Return)) { |
| - icon = UI.Icon.create('smallicon-green-arrow'); |
| - icon.addEventListener('click', location.continueToLocation.bind(location)); |
| - } else if (location.type === SDK.DebuggerModel.BreakLocationType.Call) { |
| - icon = UI.Icon.create('smallicon-step-in'); |
| - icon.addEventListener('click', () => { |
| - debuggerModel.scheduleStepIntoAsync(); |
| - debuggerModel.stepInto(); |
| - }); |
| - } else if (location.type === SDK.DebuggerModel.BreakLocationType.Return) { |
| - icon = UI.Icon.create('smallicon-step-out'); |
| - icon.addEventListener('click', () => { |
| - debuggerModel.stepOut(); |
| - }); |
| - } |
| - icon.classList.add('cm-continue-to-location'); |
| - icon.addEventListener('mousemove', hidePopoverAndConsumeEvent.bind(this)); |
| - this.textEditor.addBookmark( |
| - location.lineNumber, location.columnNumber, icon, |
| - Sources.JavaScriptSourceFrame.continueToLocationDecorationSymbol); |
| - } |
| - } |
| - |
| - /** |
| - * @this {Sources.JavaScriptSourceFrame} |
| - */ |
| - function clearExistingLocations() { |
| - var bookmarks = this.textEditor.bookmarks( |
| - this.textEditor.fullRange(), Sources.JavaScriptSourceFrame.continueToLocationDecorationSymbol); |
| - bookmarks.map(bookmark => bookmark.clear()); |
| - } |
| + var lineNumber = location.lineNumber; |
| + var token = this.textEditor.tokenAtTextPosition(lineNumber, location.columnNumber); |
| + if (!token || !token.type) |
| + continue; |
| + var line = this.textEditor.line(lineNumber); |
| + var tokenContent = line.substring(token.startColumn, token.endColumn); |
| + if (!this._isIdentifier(token.type) && (token.type !== 'js-keyword' || tokenContent !== 'this')) |
| + continue; |
| - /** |
| - * @param {!Event} event |
| - * @this {Sources.JavaScriptSourceFrame} |
| - */ |
| - function hidePopoverAndConsumeEvent(event) { |
| - event.consume(true); |
| - this._popoverHelper.hidePopover(); |
| + var highlightRange = new TextUtils.TextRange(lineNumber, token.startColumn, lineNumber, token.endColumn - 1); |
| + var decoration = this.textEditor.highlightRange(highlightRange, 'source-frame-continue-to-location'); |
| + this._continueToLocationDecorations.set(decoration, location.continueToLocation.bind(location)); |
| + } |
| } |
| } |
| @@ -834,28 +822,32 @@ Sources.JavaScriptSourceFrame = class extends SourceFrame.UISourceCodeFrame { |
| } |
| clearExecutionLine() { |
| - if (this.loaded && this._executionLocation) |
| - this.textEditor.clearExecutionLine(); |
| - delete this._executionLocation; |
| - this._clearValueWidgetsTimer = setTimeout(this._clearValueWidgets.bind(this), 1000); |
| - if (Runtime.experiments.isEnabled('continueToLocationMarkers')) |
| - this._clearContinueToLocationsTimer = setTimeout(this._clearContinueToLocations.bind(this), 1000); |
| + this.textEditor.operation(() => { |
| + if (this.loaded && this._executionLocation) |
| + this.textEditor.clearExecutionLine(); |
| + delete this._executionLocation; |
| + this._clearValueWidgetsTimer = setTimeout(this._clearValueWidgets.bind(this), 1000); |
|
dgozman
2017/04/26 16:04:58
I feel like we should do similar things for all de
pfeldman
2017/04/27 21:05:05
Sure. textEditor operation is a good-enough tool t
|
| + this._clearContinueToLocations(); |
|
dgozman
2017/04/26 16:04:58
This is a nested operation. That's ok?
pfeldman
2017/04/27 21:05:05
Yes
|
| + }); |
| } |
| _clearValueWidgets() { |
| delete this._clearValueWidgetsTimer; |
| - for (var line of this._valueWidgets.keys()) |
| - this.textEditor.removeDecoration(this._valueWidgets.get(line), line); |
| - this._valueWidgets.clear(); |
| + this.textEditor.operation(() => { |
| + for (var line of this._valueWidgets.keys()) |
| + this.textEditor.removeDecoration(this._valueWidgets.get(line), line); |
| + this._valueWidgets.clear(); |
| + }); |
| } |
| _clearContinueToLocations() { |
| - if (!Runtime.experiments.isEnabled('continueToLocationMarkers')) |
| + if (!this._continueToLocationDecorations) |
| return; |
| - delete this._clearContinueToLocationsTimer; |
| - var bookmarks = this.textEditor.bookmarks( |
| - this.textEditor.fullRange(), Sources.JavaScriptSourceFrame.continueToLocationDecorationSymbol); |
| - this.textEditor.operation(() => bookmarks.map(bookmark => bookmark.clear())); |
| + this.textEditor.operation(() => { |
| + for (var decoration of this._continueToLocationDecorations.keys()) |
| + this.textEditor.removeHighlight(decoration); |
| + delete this._continueToLocationDecorations; |
| + }); |
| } |
| /** |