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)