Title: [206654] trunk
Revision
206654
Author
[email protected]
Date
2016-09-30 12:24:29 -0700 (Fri, 30 Sep 2016)

Log Message

Web Inspector: Stepping through `a(); b(); c();` it is unclear where we are and what is about to execute
https://bugs.webkit.org/show_bug.cgi?id=161658
<rdar://problem/28181254>

Reviewed by Geoffrey Garen.

Source/_javascript_Core:

* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseAssignmentExpression):
Updated pause location for unary expressions.

Source/WebInspectorUI:

* UserInterface/Models/Script.js:
(WebInspector.Script.prototype.requestScriptSyntaxTree):
Fix first calls to requestScriptSyntaxTree. They were getting an uncaught
exception because the content argument was missing.

* UserInterface/Models/ScriptSyntaxTree.js:
(WebInspector.ScriptSyntaxTree.prototype.containersOfOffset):
Find all AST nodes that contain a particular offset.

* UserInterface/Views/SourceCodeTextEditor.js:
(WebInspector.SourceCodeTextEditor):
(WebInspector.SourceCodeTextEditor.prototype.close):
(WebInspector.SourceCodeTextEditor.prototype._activeCallFrameDidChange):
(WebInspector.SourceCodeTextEditor.prototype._activeCallFrameSourceCodeLocationChanged):
(WebInspector.SourceCodeTextEditor.prototype.textEditorExecutionHighlightRange):
Provide a good highlight range for a given offset. This is normally the start
of a statement/_expression_, inside a statement/_expression_, or the closing brace
of a function (leaving a function). Provide good ranges for each of these.

* UserInterface/Views/TextEditor.js:
(WebInspector.TextEditor):
(WebInspector.TextEditor.set string.update):
(WebInspector.TextEditor.prototype.set string):
(WebInspector.TextEditor.prototype.setExecutionLineAndColumn):
(WebInspector.TextEditor.prototype.revealPosition.revealAndHighlightLine):
(WebInspector.TextEditor.prototype.revealPosition):
(WebInspector.TextEditor.prototype.currentPositionToOriginalOffset):
(WebInspector.TextEditor.prototype._updateAfterFormatting):
(WebInspector.TextEditor.prototype.set executionLineNumber): Deleted.
(WebInspector.TextEditor.prototype.set executionColumnNumber): Deleted.
(WebInspector.TextEditor.prototype._updateExecutionLine.update): Deleted.
Always set the execution line and column together, to simplify how we update highlights.

(WebInspector.TextEditor.prototype._clearMultilineExecutionLineHighlights):
(WebInspector.TextEditor.prototype._updateExecutionLine):
When updating the main highlight clear any multi-line highlights.

(WebInspector.TextEditor.prototype._updateExecutionRangeHighlight):
Ask the delegate for a specific highlight range. If provided use that range,
otherwise just highlight the end of the line. Once we know the range, if it
is multiple lines, give the extra lines the full line highlight as well.
Also make adjustments, such as not highlighting trailing whitespace.

* UserInterface/Views/TextEditor.css:
(.text-editor > .CodeMirror .execution-line.primary .CodeMirror-linenumber::after):
(.text-editor > .CodeMirror .execution-line):
(.text-editor > .CodeMirror .execution-line .CodeMirror-matchingbracket):
(.text-editor > .CodeMirror .execution-range-highlight):
Styles for execution lines and execution range highlights.

LayoutTests:

* inspector/debugger/stepping/stepping-loops-expected.txt:
* inspector/debugger/stepping/stepping-misc-expected.txt:
Updated pause location for unary expressions.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (206653 => 206654)


--- trunk/LayoutTests/ChangeLog	2016-09-30 19:22:50 UTC (rev 206653)
+++ trunk/LayoutTests/ChangeLog	2016-09-30 19:24:29 UTC (rev 206654)
@@ -1,3 +1,15 @@
+2016-09-28  Joseph Pecoraro  <[email protected]>
+
+        Web Inspector: Stepping through `a(); b(); c();` it is unclear where we are and what is about to execute
+        https://bugs.webkit.org/show_bug.cgi?id=161658
+        <rdar://problem/28181254>
+
+        Reviewed by Geoffrey Garen.
+
+        * inspector/debugger/stepping/stepping-loops-expected.txt:
+        * inspector/debugger/stepping/stepping-misc-expected.txt:
+        Updated pause location for unary expressions.
+
 2016-09-30  Joseph Pecoraro  <[email protected]>
 
         Breakpoints on blank lines or comments don't break

Modified: trunk/LayoutTests/inspector/debugger/stepping/stepping-loops-expected.txt (206653 => 206654)


--- trunk/LayoutTests/inspector/debugger/stepping/stepping-loops-expected.txt	2016-09-30 19:22:50 UTC (rev 206653)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepping-loops-expected.txt	2016-09-30 19:24:29 UTC (rev 206654)
@@ -180,11 +180,11 @@
      31    function entryTraditionalForNoInit() {
 
 ACTION: step-over
-PAUSE AT entryTraditionalFor:28:31
+PAUSE AT entryTraditionalFor:28:28
      24    
      25    function entryTraditionalFor() {
      26        debugger;
- ->  27        for (let i = 0; i < 2; ++i|)
+ ->  27        for (let i = 0; i < 2; |++i)
      28            a();
      29    }
      30    
@@ -210,11 +210,11 @@
      31    function entryTraditionalForNoInit() {
 
 ACTION: step-over
-PAUSE AT entryTraditionalFor:28:31
+PAUSE AT entryTraditionalFor:28:28
      24    
      25    function entryTraditionalFor() {
      26        debugger;
- ->  27        for (let i = 0; i < 2; ++i|)
+ ->  27        for (let i = 0; i < 2; |++i)
      28            a();
      29    }
      30    
@@ -287,11 +287,11 @@
      31    function entryTraditionalForNoInit() {
 
 ACTION: step-over
-PAUSE AT entryTraditionalFor:28:31
+PAUSE AT entryTraditionalFor:28:28
      24    
      25    function entryTraditionalFor() {
      26        debugger;
- ->  27        for (let i = 0; i < 2; ++i|)
+ ->  27        for (let i = 0; i < 2; |++i)
      28            a();
      29    }
      30    
@@ -317,11 +317,11 @@
      31    function entryTraditionalForNoInit() {
 
 ACTION: step-over
-PAUSE AT entryTraditionalFor:28:31
+PAUSE AT entryTraditionalFor:28:28
      24    
      25    function entryTraditionalFor() {
      26        debugger;
- ->  27        for (let i = 0; i < 2; ++i|)
+ ->  27        for (let i = 0; i < 2; |++i)
      28            a();
      29    }
      30    
@@ -384,11 +384,11 @@
      38    function entryForIn() {
 
 ACTION: step-over
-PAUSE AT entryTraditionalForNoInit:35:22
+PAUSE AT entryTraditionalForNoInit:35:19
      31    function entryTraditionalForNoInit() {
      32        let i = 0;
      33        debugger;
- ->  34        for (; i < 2; ++i|)
+ ->  34        for (; i < 2; |++i)
      35            a();
      36    }
      37    
@@ -414,11 +414,11 @@
      38    function entryForIn() {
 
 ACTION: step-over
-PAUSE AT entryTraditionalForNoInit:35:22
+PAUSE AT entryTraditionalForNoInit:35:19
      31    function entryTraditionalForNoInit() {
      32        let i = 0;
      33        debugger;
- ->  34        for (; i < 2; ++i|)
+ ->  34        for (; i < 2; |++i)
      35            a();
      36    }
      37    

Modified: trunk/LayoutTests/inspector/debugger/stepping/stepping-misc-expected.txt (206653 => 206654)


--- trunk/LayoutTests/inspector/debugger/stepping/stepping-misc-expected.txt	2016-09-30 19:22:50 UTC (rev 206653)
+++ trunk/LayoutTests/inspector/debugger/stepping/stepping-misc-expected.txt	2016-09-30 19:24:29 UTC (rev 206654)
@@ -264,11 +264,11 @@
      54    }
 
 ACTION: step-over
-PAUSE AT entryLabelBreakLoop:49:35
+PAUSE AT entryLabelBreakLoop:49:32
      45        debugger;
      46    outer:
      47        for (let i = 0; ; ++i) {
- ->  48            for (let j = 0; j < 2; ++j|) {
+ ->  48            for (let j = 0; j < 2; |++j) {
      49                if (i === 1 && j === 0)
      50                    break outer;
      51                a();
@@ -304,11 +304,11 @@
      54    }
 
 ACTION: step-over
-PAUSE AT entryLabelBreakLoop:49:35
+PAUSE AT entryLabelBreakLoop:49:32
      45        debugger;
      46    outer:
      47        for (let i = 0; ; ++i) {
- ->  48            for (let j = 0; j < 2; ++j|) {
+ ->  48            for (let j = 0; j < 2; |++j) {
      49                if (i === 1 && j === 0)
      50                    break outer;
      51                a();
@@ -324,11 +324,11 @@
      51                a();
 
 ACTION: step-over
-PAUSE AT entryLabelBreakLoop:48:26
+PAUSE AT entryLabelBreakLoop:48:23
      44    function entryLabelBreakLoop() {
      45        debugger;
      46    outer:
- ->  47        for (let i = 0; ; ++i|) {
+ ->  47        for (let i = 0; ; |++i) {
      48            for (let j = 0; j < 2; ++j) {
      49                if (i === 1 && j === 0)
      50                    break outer;

Modified: trunk/Source/_javascript_Core/ChangeLog (206653 => 206654)


--- trunk/Source/_javascript_Core/ChangeLog	2016-09-30 19:22:50 UTC (rev 206653)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-09-30 19:24:29 UTC (rev 206654)
@@ -1,5 +1,17 @@
 2016-09-30  Joseph Pecoraro  <[email protected]>
 
+        Web Inspector: Stepping through `a(); b(); c();` it is unclear where we are and what is about to execute
+        https://bugs.webkit.org/show_bug.cgi?id=161658
+        <rdar://problem/28181254>
+
+        Reviewed by Geoffrey Garen.
+
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseAssignmentExpression):
+        Updated pause location for unary expressions.
+
+2016-09-30  Joseph Pecoraro  <[email protected]>
+
         Breakpoints on blank lines or comments don't break
         https://bugs.webkit.org/show_bug.cgi?id=9885
         <rdar://problem/6134406>

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (206653 => 206654)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2016-09-30 19:22:50 UTC (rev 206653)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2016-09-30 19:24:29 UTC (rev 206654)
@@ -4626,6 +4626,8 @@
         return parseAwaitExpression(context);
 #endif
 
+    JSTokenLocation location(tokenLocation());
+
     while (isUnaryOp(m_token.m_type)) {
         if (strictMode()) {
             switch (m_token.m_type) {
@@ -4654,7 +4656,6 @@
     }
     JSTextPosition subExprStart = tokenStartPosition();
     ASSERT(subExprStart.offset >= subExprStart.lineStartOffset);
-    JSTokenLocation location(tokenLocation());
     TreeExpression expr = parseMemberExpression(context);
     if (!expr) {
         if (lastOperator)
@@ -4703,8 +4704,6 @@
     if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
         return expr;
 
-    location = tokenLocation();
-    location.line = m_lexer->lastLineNumber();
     while (tokenStackDepth) {
         switch (context.unaryTokenStackLastType(tokenStackDepth)) {
         case EXCLAMATION:
@@ -4749,7 +4748,6 @@
     return expr;
 }
 
-
 template <typename LexerType> void Parser<LexerType>::printUnexpectedTokenText(WTF::PrintStream& out)
 {
     switch (m_token.m_type) {

Modified: trunk/Source/WebInspectorUI/ChangeLog (206653 => 206654)


--- trunk/Source/WebInspectorUI/ChangeLog	2016-09-30 19:22:50 UTC (rev 206653)
+++ trunk/Source/WebInspectorUI/ChangeLog	2016-09-30 19:24:29 UTC (rev 206654)
@@ -1,3 +1,61 @@
+2016-09-30  Joseph Pecoraro  <[email protected]>
+
+        Web Inspector: Stepping through `a(); b(); c();` it is unclear where we are and what is about to execute
+        https://bugs.webkit.org/show_bug.cgi?id=161658
+        <rdar://problem/28181254>
+
+        Reviewed by Geoffrey Garen.
+
+        * UserInterface/Models/Script.js:
+        (WebInspector.Script.prototype.requestScriptSyntaxTree):
+        Fix first calls to requestScriptSyntaxTree. They were getting an uncaught
+        exception because the content argument was missing.
+
+        * UserInterface/Models/ScriptSyntaxTree.js:
+        (WebInspector.ScriptSyntaxTree.prototype.containersOfOffset):
+        Find all AST nodes that contain a particular offset.
+
+        * UserInterface/Views/SourceCodeTextEditor.js:
+        (WebInspector.SourceCodeTextEditor):
+        (WebInspector.SourceCodeTextEditor.prototype.close):
+        (WebInspector.SourceCodeTextEditor.prototype._activeCallFrameDidChange):
+        (WebInspector.SourceCodeTextEditor.prototype._activeCallFrameSourceCodeLocationChanged):
+        (WebInspector.SourceCodeTextEditor.prototype.textEditorExecutionHighlightRange):
+        Provide a good highlight range for a given offset. This is normally the start
+        of a statement/_expression_, inside a statement/_expression_, or the closing brace
+        of a function (leaving a function). Provide good ranges for each of these.
+
+        * UserInterface/Views/TextEditor.js:
+        (WebInspector.TextEditor):
+        (WebInspector.TextEditor.set string.update):
+        (WebInspector.TextEditor.prototype.set string):
+        (WebInspector.TextEditor.prototype.setExecutionLineAndColumn):
+        (WebInspector.TextEditor.prototype.revealPosition.revealAndHighlightLine):
+        (WebInspector.TextEditor.prototype.revealPosition):
+        (WebInspector.TextEditor.prototype.currentPositionToOriginalOffset):
+        (WebInspector.TextEditor.prototype._updateAfterFormatting):
+        (WebInspector.TextEditor.prototype.set executionLineNumber): Deleted.
+        (WebInspector.TextEditor.prototype.set executionColumnNumber): Deleted.
+        (WebInspector.TextEditor.prototype._updateExecutionLine.update): Deleted.
+        Always set the execution line and column together, to simplify how we update highlights.
+
+        (WebInspector.TextEditor.prototype._clearMultilineExecutionLineHighlights):
+        (WebInspector.TextEditor.prototype._updateExecutionLine):
+        When updating the main highlight clear any multi-line highlights.
+
+        (WebInspector.TextEditor.prototype._updateExecutionRangeHighlight):
+        Ask the delegate for a specific highlight range. If provided use that range,
+        otherwise just highlight the end of the line. Once we know the range, if it
+        is multiple lines, give the extra lines the full line highlight as well.
+        Also make adjustments, such as not highlighting trailing whitespace.
+
+        * UserInterface/Views/TextEditor.css:
+        (.text-editor > .CodeMirror .execution-line.primary .CodeMirror-linenumber::after):
+        (.text-editor > .CodeMirror .execution-line):
+        (.text-editor > .CodeMirror .execution-line .CodeMirror-matchingbracket):
+        (.text-editor > .CodeMirror .execution-range-highlight):
+        Styles for execution lines and execution range highlights.
+
 2016-09-29  Aaron Chu  <[email protected]>
 
         Web Inspector: AXI: linkified refs to #document and #text are not usually navigable nodes; consider delinkifying them

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/Script.js (206653 => 206654)


--- trunk/Source/WebInspectorUI/UserInterface/Models/Script.js	2016-09-30 19:22:50 UTC (rev 206653)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Script.js	2016-09-30 19:24:29 UTC (rev 206654)
@@ -221,7 +221,7 @@
             return;
         }
 
-        var makeSyntaxTreeAndCallCallback = () => {
+        var makeSyntaxTreeAndCallCallback = (content) => {
             this._makeSyntaxTree(content);
             callback(this._scriptSyntaxTree);
         };

Modified: trunk/Source/WebInspectorUI/UserInterface/Models/ScriptSyntaxTree.js (206653 => 206654)


--- trunk/Source/WebInspectorUI/UserInterface/Models/ScriptSyntaxTree.js	2016-09-30 19:22:50 UTC (rev 206653)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ScriptSyntaxTree.js	2016-09-30 19:24:29 UTC (rev 206654)
@@ -80,6 +80,28 @@
         return nodes;
     }
 
+    containersOfOffset(offset)
+    {
+        console.assert(this._parsedSuccessfully);
+        if (!this._parsedSuccessfully)
+            return [];
+
+        let allNodes = [];
+        const start = 0;
+        const end = 1;
+
+        this.forEachNode((node, state) => {
+            if (node.range[end] < offset)
+                state.skipChildNodes = true;
+            if (node.range[start] > offset)
+                state.shouldStopEarly = true;
+            if (node.range[start] <= offset && node.range[end] >= offset)
+                allNodes.push(node);
+        });
+
+        return allNodes;
+    }
+
     filterByRange(startOffset, endOffset)
     {
         console.assert(this._parsedSuccessfully);

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js (206653 => 206654)


--- trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js	2016-09-30 19:22:50 UTC (rev 206653)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js	2016-09-30 19:24:29 UTC (rev 206654)
@@ -41,6 +41,7 @@
         this._invalidLineNumbers = {0: true};
         this._ignoreContentDidChange = 0;
         this._requestingScriptContent = false;
+        this._activeCallFrameSourceCodeLocation = null;
 
         this._typeTokenScrollHandler = null;
         this._typeTokenAnnotator = null;
@@ -143,7 +144,7 @@
 
             if (this._activeCallFrameSourceCodeLocation) {
                 this._activeCallFrameSourceCodeLocation.removeEventListener(WebInspector.SourceCodeLocation.Event.LocationChanged, this._activeCallFrameSourceCodeLocationChanged, this);
-                delete this._activeCallFrameSourceCodeLocation;
+                this._activeCallFrameSourceCodeLocation = null;
             }
         }
 
@@ -634,13 +635,12 @@
 
         if (this._activeCallFrameSourceCodeLocation) {
             this._activeCallFrameSourceCodeLocation.removeEventListener(WebInspector.SourceCodeLocation.Event.LocationChanged, this._activeCallFrameSourceCodeLocationChanged, this);
-            delete this._activeCallFrameSourceCodeLocation;
+            this._activeCallFrameSourceCodeLocation = null;
         }
 
         var activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
         if (!activeCallFrame || !this._matchesSourceCodeLocation(activeCallFrame.sourceCodeLocation)) {
-            this.executionLineNumber = NaN;
-            this.executionColumnNumber = NaN;
+            this.setExecutionLineAndColumn(NaN, NaN);
             return;
         }
 
@@ -653,8 +653,7 @@
         // could have changed (e.g. continuing in a loop with a breakpoint inside).
 
         var lineInfo = this._editorLineInfoForSourceCodeLocation(activeCallFrame.sourceCodeLocation);
-        this.executionLineNumber = lineInfo.lineNumber;
-        this.executionColumnNumber = lineInfo.columnNumber;
+        this.setExecutionLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber);
 
         // If we have full content or this source code isn't a Resource we can return early.
         // Script source code populates from the request started in the constructor.
@@ -681,8 +680,7 @@
         console.assert(this._activeCallFrameSourceCodeLocation === WebInspector.debuggerManager.activeCallFrame.sourceCodeLocation);
 
         var lineInfo = this._editorLineInfoForSourceCodeLocation(this._activeCallFrameSourceCodeLocation);
-        this.executionLineNumber = lineInfo.lineNumber;
-        this.executionColumnNumber = lineInfo.columnNumber;
+        this.setExecutionLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber);
     }
 
     _populateWithInlineScriptContent()
@@ -1212,6 +1210,85 @@
         this._reinsertAllIssues();
     }
 
+    textEditorExecutionHighlightRange(offset, callback)
+    {
+        let script = this._getAssociatedScript();
+        if (!script) {
+            callback(null);
+            return;
+        }
+
+        script.requestScriptSyntaxTree((syntaxTree) => {
+            let nodes = syntaxTree.containersOfOffset(offset);
+            if (!nodes.length) {
+                callback(null);
+                return;
+            }
+
+            // Find a node starting at this offset.
+            for (let node of nodes) {
+                let startOffset = node.range[0];
+                if (startOffset === offset) {
+                    callback(node.range);
+                    return;
+                }
+                if (startOffset > offset)
+                    break;
+            }
+
+            // Find a node ending at this offset. (Leaving a block).
+            // We check this after ensuring nothing starts with this offset,
+            // as that would be more important.
+            for (let node of nodes) {
+                let startOffset = node.range[0];
+                let endOffset = node.range[1];
+                if (endOffset === offset) {
+                    if (node.type === WebInspector.ScriptSyntaxTree.NodeType.BlockStatement) {
+                        // Closing brace of a block, only highlight the closing brace character.
+                        callback([offset - 1, offset]);
+                        return;
+                    }
+                }
+                if (startOffset > offset)
+                    break;
+            }
+
+            // Find the best container node for this _expression_.
+            // Sort by the tightest bounds so we can walk from specific to general nodes.
+            nodes.sort((a, b) => {
+                let aLength = a.range[1] - a.range[0];
+                let bLength = b.range[1] - b.range[0];
+                return aLength - bLength;
+            });
+
+            for (let i = 0; i < nodes.length; ++i) {
+                let node = nodes[i];
+
+                // In a function call.
+                if (node.type === WebInspector.ScriptSyntaxTree.NodeType.CallExpression
+                    || node.type === WebInspector.ScriptSyntaxTree.NodeType.NewExpression) {
+                    callback(node.range);
+                    return;
+                }
+
+                // In the middle of a member _expression_.
+                if (node.type === WebInspector.ScriptSyntaxTree.NodeType.ThisExpression
+                    || node.type === WebInspector.ScriptSyntaxTree.NodeType.IdentifierExpression) {
+                    let nextNode = nodes[i + 1];
+                    if (nextNode && nextNode.type === WebInspector.ScriptSyntaxTree.NodeType.MemberExpression) {
+                        callback(nextNode.range);
+                        return;
+                    }
+                    callback(node.range);
+                    return;
+                }
+            }
+
+            // No matches, just highlight the line.
+            callback(null);
+        });
+    }
+
     _clearWidgets()
     {
         for (var widget of this._widgetMap.values())
@@ -1422,7 +1499,7 @@
         var sourceCode = this._sourceCode;
         var sourceID = sourceCode instanceof WebInspector.Script ? sourceCode.id : sourceCode.scripts[0].id;
         var range = candidate.hoveredTokenRange;
-        var offset = this.currentPositionToOriginalOffset({line: range.start.line, ch: range.start.ch});
+        var offset = this.positionToOffset({line: range.start.line, ch: range.start.ch});
 
         var allRequests = [{
             typeInformationDescriptor: WebInspector.ScriptSyntaxTree.TypeProfilerSearchDescriptor.NormalExpression,

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TextEditor.css (206653 => 206654)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TextEditor.css	2016-09-30 19:22:50 UTC (rev 206653)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TextEditor.css	2016-09-30 19:24:29 UTC (rev 206654)
@@ -82,7 +82,7 @@
     text-indent: -1px;
 }
 
-.text-editor > .CodeMirror .execution-line .CodeMirror-linenumber::after {
+.text-editor > .CodeMirror .execution-line.primary .CodeMirror-linenumber::after {
     position: absolute;
     top: 0;
     bottom: 0;
@@ -99,9 +99,18 @@
 }
 
 .text-editor > .CodeMirror .execution-line {
-    background-color: hsl(99, 38%, 86%) !important;
+    background-color: hsla(99, 38%, 86%, 0.5) !important;
 }
 
+.text-editor > .CodeMirror .execution-line .CodeMirror-matchingbracket {
+    background-color: hsla(90, 30%, 82%, 0.7);
+    border-bottom: 1px dotted hsl(78, 18%, 58%);
+}
+
+.text-editor > .CodeMirror .execution-range-highlight {
+    background-color: hsl(90, 30%, 82%);
+}
+
 .text-editor > .CodeMirror .highlighted {
     animation: "text-editor-highlight-fadeout" 2s;
 }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TextEditor.js (206653 => 206654)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TextEditor.js	2016-09-30 19:22:50 UTC (rev 206653)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TextEditor.js	2016-09-30 19:24:29 UTC (rev 206654)
@@ -58,6 +58,10 @@
         this._executionLineNumber = NaN;
         this._executionColumnNumber = NaN;
 
+        this._executionLineHandle = null;
+        this._executionMultilineHandles = [];
+        this._executionRangeHighlightMarker = null;
+
         this._searchQuery = null;
         this._searchResults = [];
         this._currentSearchResultIndex = -1;
@@ -107,6 +111,7 @@
 
             // Update the execution line now that we might have content for that line.
             this._updateExecutionLine();
+            this._updateExecutionRangeHighlight();
 
             // Set the breakpoint styles now that we might have content for those lines.
             for (var lineNumber in this._breakpoints)
@@ -206,30 +211,11 @@
         return this._executionLineNumber;
     }
 
-    set executionLineNumber(lineNumber)
-    {
-        // Only return early if there isn't a line handle and that isn't changing.
-        if (!this._executionLineHandle && isNaN(lineNumber))
-            return;
-
-        this._executionLineNumber = lineNumber;
-        this._updateExecutionLine();
-
-        // Still dispatch the event even if the number didn't change. The execution state still
-        // could have changed (e.g. continuing in a loop with a breakpoint inside).
-        this.dispatchEventToListeners(WebInspector.TextEditor.Event.ExecutionLineNumberDidChange);
-    }
-
     get executionColumnNumber()
     {
         return this._executionColumnNumber;
     }
 
-    set executionColumnNumber(columnNumber)
-    {
-        this._executionColumnNumber = columnNumber;
-    }
-
     get formatterSourceMap()
     {
         return this._formatterSourceMap;
@@ -340,6 +326,23 @@
         boundBatchSearch();
     }
 
+    setExecutionLineAndColumn(lineNumber, columnNumber)
+    {
+        // Only return early if there isn't a line handle and that isn't changing.
+        if (!this._executionLineHandle && isNaN(lineNumber))
+            return;
+
+        this._executionLineNumber = lineNumber;
+        this._executionColumnNumber = columnNumber;
+
+        this._updateExecutionLine();
+        this._updateExecutionRangeHighlight();
+
+        // Still dispatch the event even if the number didn't change. The execution state still
+        // could have changed (e.g. continuing in a loop with a breakpoint inside).
+        this.dispatchEventToListeners(WebInspector.TextEditor.Event.ExecutionLineNumberDidChange);
+    }
+
     addSearchResults(textRanges)
     {
         console.assert(textRanges);
@@ -493,6 +496,11 @@
             if (noHighlight)
                 return;
 
+            // Don't show blue line highlight when debugging.
+            // FIXME: This could be better, we could avoid highlight only when switching for active call frames switches.
+            if (WebInspector.debuggerManager.paused)
+                return;
+
             this._codeMirror.addLineClass(lineHandle, "wrap", WebInspector.TextEditor.HighlightedStyleClassName);
 
             // Use a timeout instead of a animationEnd event listener because the line element might
@@ -690,7 +698,8 @@
 
     currentPositionToOriginalOffset(position)
     {
-        var offset = null;
+        let offset = null;
+
         if (this._formatterSourceMap)
             offset = this._formatterSourceMap.formattedToOriginalOffset(position.line, position.ch);
         else
@@ -900,8 +909,8 @@
 
         if (newExecutionLocation) {
             this._executionLineHandle = null;
-            this.executionColumnNumber = newExecutionLocation.columnNumber;
-            this.executionLineNumber = newExecutionLocation.lineNumber;
+            this._executionMultilineHandles = [];
+            this.setExecutionLineAndColumn(newExecutionLocation.lineNumber, newExecutionLocation.columnNumber);
         }
 
         // FIXME: <rdar://problem/13129955> FindBanner: New searches should not lose search position (start from current selection/caret)
@@ -1178,20 +1187,82 @@
         }
     }
 
+    _clearMultilineExecutionLineHighlights()
+    {
+        if (this._executionMultilineHandles.length) {
+            for (let lineHandle of this._executionMultilineHandles)
+                this._codeMirror.removeLineClass(lineHandle, "wrap", WebInspector.TextEditor.ExecutionLineStyleClassName);
+            this._executionMultilineHandles = [];
+        }
+    }
+
     _updateExecutionLine()
     {
-        function update()
-        {
-            if (this._executionLineHandle)
+        this._codeMirror.operation(() => {
+            if (this._executionLineHandle) {
                 this._codeMirror.removeLineClass(this._executionLineHandle, "wrap", WebInspector.TextEditor.ExecutionLineStyleClassName);
+                this._codeMirror.removeLineClass(this._executionLineHandle, "wrap", "primary");
+            }
 
+            this._clearMultilineExecutionLineHighlights();
+
             this._executionLineHandle = !isNaN(this._executionLineNumber) ? this._codeMirror.getLineHandle(this._executionLineNumber) : null;
 
-            if (this._executionLineHandle)
+            if (this._executionLineHandle) {
                 this._codeMirror.addLineClass(this._executionLineHandle, "wrap", WebInspector.TextEditor.ExecutionLineStyleClassName);
+                this._codeMirror.addLineClass(this._executionLineHandle, "wrap", "primary");
+            }
+        });
+    }
+
+    _updateExecutionRangeHighlight()
+    {
+        if (this._executionRangeHighlightMarker) {
+            this._executionRangeHighlightMarker.clear();
+            this._executionRangeHighlightMarker = null;
         }
 
-        this._codeMirror.operation(update.bind(this));
+        if (isNaN(this._executionLineNumber))
+            return;
+
+        let offset = this.currentPositionToOriginalOffset({line: this._executionLineNumber, ch: this._executionColumnNumber});
+
+        this._delegate.textEditorExecutionHighlightRange(offset, (range) => {
+            let start, end;
+            if (!range) {
+                // Highlight the rest of the line.
+                start = {line: this._executionLineNumber, ch: this._executionColumnNumber};
+                end = {line: this._executionLineNumber};
+            } else {
+                // Highlight the range.
+                start = this.originalOffsetToCurrentPosition(range[0]);
+                end = this.originalOffsetToCurrentPosition(range[1]);
+            }
+
+            // Ensure the marker is cleared in case there were multiple updates very quickly.
+            if (this._executionRangeHighlightMarker) {
+                this._executionRangeHighlightMarker.clear();
+                this._executionRangeHighlightMarker = null;
+            }
+
+            // Avoid highlighting trailing whitespace.
+            let text = this._codeMirror.getRange(start, end);
+            let trailingWhitespace = text.match(/\s+$/);
+            if (trailingWhitespace)
+                end.ch = Math.max(0, end.ch - trailingWhitespace[0].length);
+
+            // Give each line containing part of the range the full line style.
+            this._clearMultilineExecutionLineHighlights();
+            if (start.line !== end.line) {
+                for (let line = start.line; line < end.line; ++line) {
+                    let lineHandle = this._codeMirror.getLineHandle(line);
+                    this._codeMirror.addLineClass(lineHandle, "wrap", WebInspector.TextEditor.ExecutionLineStyleClassName);
+                    this._executionMultilineHandles.push(lineHandle);
+                }
+            }
+
+            this._executionRangeHighlightMarker = this._codeMirror.markText(start, end, {className: "execution-range-highlight"});
+        });
     }
 
     _setBreakpointStylesOnLine(lineNumber)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to