<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[208783] trunk/Source/WebInspectorUI</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/208783">208783</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-11-15 22:03:45 -0800 (Tue, 15 Nov 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Web Inspector: SourceCodeTextEditor should display execution lines for background threads
https://bugs.webkit.org/show_bug.cgi?id=164679
<rdar://problem/29233026>
Patch by Joseph Pecoraro <pecoraro@apple.com> on 2016-11-15
Reviewed by Timothy Hatcher.
There may be multiple threads paused in the same content view. With
this change we should a thread indicator for each primary line a
thread is paused on. It uses the same inline line indicator that
inline errors/warnings (issues) use.
When there is a single thread (just the Page) we don't show thread
indicators. But as soon as there are multiple threads we start
managing and showing them. The line indicator contains the name of
the thread on the side.
Note that SourceCodeTextEditor maintains the thread indicators, but
it still always handles the ActiveCallFrame as it used to, pushing
values down into TextEditor. The ActiveCallFrame styles override
the thread line indicators (albeit with the same styles). The reason
these are still separate is that TextEditor has some special styles
regarding its gutter for the active execution line. Eventually we
may want to find a way to push this up into SourceCodeTextEditor.
* Localizations/en.lproj/localizedStrings.js:
New string "%d Threads" when multiple threads are on the same line.
* UserInterface/Views/ScopeChainDetailsSidebarPanel.js:
(WebInspector.ScopeChainDetailsSidebarPanel):
(WebInspector.ScopeChainDetailsSidebarPanel.prototype._activeCallFrameDidChange):
Update Watch Expressions when the active call frame changes.
* UserInterface/Views/SourceCodeTextEditor.css:
(.source-code.text-editor > .CodeMirror .line-indicator-widget):
(.source-code.text-editor > .CodeMirror .line-indicator-widget.inline):
(.source-code.text-editor > .CodeMirror .line-indicator-widget > .arrow):
(.source-code.text-editor > .CodeMirror .line-indicator-widget.inline > .arrow):
(.source-code.text-editor > .CodeMirror .line-indicator-widget > .icon):
(.source-code.text-editor > .CodeMirror .line-indicator-widget > .text):
(.source-code.text-editor > .CodeMirror .line-indicator-widget.inline > .text):
Share line indicator widget styles between issue widgets and thread widgets.
(.source-code.text-editor > .CodeMirror .thread-indicator):
(.source-code.text-editor > .CodeMirror .thread-widget):
(.source-code.text-editor > .CodeMirror .thread-widget.inline):
(.source-code.text-editor > .CodeMirror .thread-widget.inline > .arrow):
Colors for the thread-widget line-indicators.
* UserInterface/Views/SourceCodeTextEditor.js:
(WebInspector.SourceCodeTextEditor):
(WebInspector.SourceCodeTextEditor.prototype.close):
New event listeners handling for Target added / removed events.
(WebInspector.SourceCodeTextEditor.prototype._targetAdded):
(WebInspector.SourceCodeTextEditor.prototype._targetRemoved):
Update thread indicators as needed.
(WebInspector.SourceCodeTextEditor.prototype._looselyMatchesSourceCodeLocation):
More generic match based just on the URLs. Even if the exact script comes
from a different target, if they share the same URL that is fine.
(WebInspector.SourceCodeTextEditor.prototype._callFramesDidChange):
(WebInspector.SourceCodeTextEditor.prototype._addThreadIndicatorForTarget):
(WebInspector.SourceCodeTextEditor.prototype._removeThreadIndicatorForTarget):
(WebInspector.SourceCodeTextEditor.prototype._threadIndicatorWidgetForLine):
(WebInspector.SourceCodeTextEditor.prototype._updateThreadIndicatorWidget):
(WebInspector.SourceCodeTextEditor.prototype._handleThreadIndicatorWidgetClick):
Manage thread line indicator widgets. There are 3 maps we maintain.
1. line -> [threads]
List of threads paused on a line, needed for the UI text.
2. line -> widget
Gets the widget on a line so we can modify and eventually remove it.
3. target -> line
If a target is removed, we need to know what line it had an indicator on.
(WebInspector.SourceCodeTextEditor.prototype._isWidgetToggleable):
Generalize for all of our different line indicator widgets.
(WebInspector.SourceCodeTextEditor.prototype._contentDidPopulate):
(WebInspector.SourceCodeTextEditor.prototype.textEditorUpdatedFormatting):
(WebInspector.SourceCodeTextEditor.prototype._reinsertAllThreadIndicators):
When first populated, or reformatted, clear and reinsert all widgets.
(WebInspector.SourceCodeTextEditor.prototype._reinsertAllIssues):
(WebInspector.SourceCodeTextEditor.prototype._logCleared):
(WebInspector.SourceCodeTextEditor.prototype._clearIssueWidgets): Renamed.
Rename _clearWidgets to _clearIssueWidgets.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs">trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsScopeChainDetailsSidebarPaneljs">trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSourceCodeTextEditorcss">trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSourceCodeTextEditorjs">trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (208782 => 208783)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-11-16 05:05:38 UTC (rev 208782)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-11-16 06:03:45 UTC (rev 208783)
</span><span class="lines">@@ -1,5 +1,96 @@
</span><span class="cx"> 2016-11-15 Joseph Pecoraro <pecoraro@apple.com>
</span><span class="cx">
</span><ins>+ Web Inspector: SourceCodeTextEditor should display execution lines for background threads
+ https://bugs.webkit.org/show_bug.cgi?id=164679
+ <rdar://problem/29233026>
+
+ Reviewed by Timothy Hatcher.
+
+ There may be multiple threads paused in the same content view. With
+ this change we should a thread indicator for each primary line a
+ thread is paused on. It uses the same inline line indicator that
+ inline errors/warnings (issues) use.
+
+ When there is a single thread (just the Page) we don't show thread
+ indicators. But as soon as there are multiple threads we start
+ managing and showing them. The line indicator contains the name of
+ the thread on the side.
+
+ Note that SourceCodeTextEditor maintains the thread indicators, but
+ it still always handles the ActiveCallFrame as it used to, pushing
+ values down into TextEditor. The ActiveCallFrame styles override
+ the thread line indicators (albeit with the same styles). The reason
+ these are still separate is that TextEditor has some special styles
+ regarding its gutter for the active execution line. Eventually we
+ may want to find a way to push this up into SourceCodeTextEditor.
+
+ * Localizations/en.lproj/localizedStrings.js:
+ New string "%d Threads" when multiple threads are on the same line.
+
+ * UserInterface/Views/ScopeChainDetailsSidebarPanel.js:
+ (WebInspector.ScopeChainDetailsSidebarPanel):
+ (WebInspector.ScopeChainDetailsSidebarPanel.prototype._activeCallFrameDidChange):
+ Update Watch Expressions when the active call frame changes.
+
+ * UserInterface/Views/SourceCodeTextEditor.css:
+ (.source-code.text-editor > .CodeMirror .line-indicator-widget):
+ (.source-code.text-editor > .CodeMirror .line-indicator-widget.inline):
+ (.source-code.text-editor > .CodeMirror .line-indicator-widget > .arrow):
+ (.source-code.text-editor > .CodeMirror .line-indicator-widget.inline > .arrow):
+ (.source-code.text-editor > .CodeMirror .line-indicator-widget > .icon):
+ (.source-code.text-editor > .CodeMirror .line-indicator-widget > .text):
+ (.source-code.text-editor > .CodeMirror .line-indicator-widget.inline > .text):
+ Share line indicator widget styles between issue widgets and thread widgets.
+
+ (.source-code.text-editor > .CodeMirror .thread-indicator):
+ (.source-code.text-editor > .CodeMirror .thread-widget):
+ (.source-code.text-editor > .CodeMirror .thread-widget.inline):
+ (.source-code.text-editor > .CodeMirror .thread-widget.inline > .arrow):
+ Colors for the thread-widget line-indicators.
+
+ * UserInterface/Views/SourceCodeTextEditor.js:
+ (WebInspector.SourceCodeTextEditor):
+ (WebInspector.SourceCodeTextEditor.prototype.close):
+ New event listeners handling for Target added / removed events.
+
+ (WebInspector.SourceCodeTextEditor.prototype._targetAdded):
+ (WebInspector.SourceCodeTextEditor.prototype._targetRemoved):
+ Update thread indicators as needed.
+
+ (WebInspector.SourceCodeTextEditor.prototype._looselyMatchesSourceCodeLocation):
+ More generic match based just on the URLs. Even if the exact script comes
+ from a different target, if they share the same URL that is fine.
+
+ (WebInspector.SourceCodeTextEditor.prototype._callFramesDidChange):
+ (WebInspector.SourceCodeTextEditor.prototype._addThreadIndicatorForTarget):
+ (WebInspector.SourceCodeTextEditor.prototype._removeThreadIndicatorForTarget):
+ (WebInspector.SourceCodeTextEditor.prototype._threadIndicatorWidgetForLine):
+ (WebInspector.SourceCodeTextEditor.prototype._updateThreadIndicatorWidget):
+ (WebInspector.SourceCodeTextEditor.prototype._handleThreadIndicatorWidgetClick):
+ Manage thread line indicator widgets. There are 3 maps we maintain.
+
+ 1. line -> [threads]
+ List of threads paused on a line, needed for the UI text.
+ 2. line -> widget
+ Gets the widget on a line so we can modify and eventually remove it.
+ 3. target -> line
+ If a target is removed, we need to know what line it had an indicator on.
+
+ (WebInspector.SourceCodeTextEditor.prototype._isWidgetToggleable):
+ Generalize for all of our different line indicator widgets.
+
+ (WebInspector.SourceCodeTextEditor.prototype._contentDidPopulate):
+ (WebInspector.SourceCodeTextEditor.prototype.textEditorUpdatedFormatting):
+ (WebInspector.SourceCodeTextEditor.prototype._reinsertAllThreadIndicators):
+ When first populated, or reformatted, clear and reinsert all widgets.
+
+ (WebInspector.SourceCodeTextEditor.prototype._reinsertAllIssues):
+ (WebInspector.SourceCodeTextEditor.prototype._logCleared):
+ (WebInspector.SourceCodeTextEditor.prototype._clearIssueWidgets): Renamed.
+ Rename _clearWidgets to _clearIssueWidgets.
+
+2016-11-15 Joseph Pecoraro <pecoraro@apple.com>
+
</ins><span class="cx"> Web Inspector: Remove unused and untested Page.setTouchEmulationEnabled command
</span><span class="cx"> https://bugs.webkit.org/show_bug.cgi?id=164793
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (208782 => 208783)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2016-11-16 05:05:38 UTC (rev 208782)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2016-11-16 06:03:45 UTC (rev 208783)
</span><span class="lines">@@ -22,6 +22,7 @@
</span><span class="cx"> localizedStrings["%d Errors"] = "%d Errors";
</span><span class="cx"> localizedStrings["%d Errors, %d Warnings"] = "%d Errors, %d Warnings";
</span><span class="cx"> localizedStrings["%d More\u2026"] = "%d More\u2026";
</span><ins>+localizedStrings["%d Threads"] = "%d Threads";
</ins><span class="cx"> localizedStrings["%d Warnings"] = "%d Warnings";
</span><span class="cx"> localizedStrings["%d \xd7 %d pixels"] = "%d \xd7 %d pixels";
</span><span class="cx"> localizedStrings["%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)"] = "%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)";
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsScopeChainDetailsSidebarPaneljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js (208782 => 208783)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js        2016-11-16 05:05:38 UTC (rev 208782)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js        2016-11-16 06:03:45 UTC (rev 208783)
</span><span class="lines">@@ -68,6 +68,9 @@
</span><span class="cx">
</span><span class="cx"> // Update watch expressions on navigations.
</span><span class="cx"> WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
</span><ins>+
+ // Update watch expressions on active call frame changes.
+ WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, this._activeCallFrameDidChange, this);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Public
</span><span class="lines">@@ -424,6 +427,11 @@
</span><span class="cx"> this.needsLayout();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ _activeCallFrameDidChange()
+ {
+ this.needsLayout();
+ }
+
</ins><span class="cx"> _mainResourceDidChange(event)
</span><span class="cx"> {
</span><span class="cx"> if (!event.target.isMainFrame())
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSourceCodeTextEditorcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.css (208782 => 208783)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.css        2016-11-16 05:05:38 UTC (rev 208782)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.css        2016-11-16 06:03:45 UTC (rev 208783)
</span><span class="lines">@@ -36,7 +36,11 @@
</span><span class="cx"> background-color: hsl(15, 100%, 90%);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-.source-code.text-editor > .CodeMirror .issue-widget {
</del><ins>+.source-code.text-editor > .CodeMirror .thread-indicator {
+ background-color: hsla(99, 38%, 86%, 0.5);
+}
+
+.source-code.text-editor > .CodeMirror .line-indicator-widget {
</ins><span class="cx"> float: right;
</span><span class="cx"> padding: 0 5px 1px 5px;
</span><span class="cx"> border-bottom-left-radius: 5px;
</span><span class="lines">@@ -43,7 +47,7 @@
</span><span class="cx"> cursor: default;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-.source-code.text-editor > .CodeMirror .issue-widget.inline {
</del><ins>+.source-code.text-editor > .CodeMirror .line-indicator-widget.inline {
</ins><span class="cx"> position: relative;
</span><span class="cx"> top: -13px;
</span><span class="cx"> height: 13px;
</span><span class="lines">@@ -51,11 +55,11 @@
</span><span class="cx"> border-bottom-left-radius: 0;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-.source-code.text-editor > .CodeMirror .issue-widget > .arrow {
</del><ins>+.source-code.text-editor > .CodeMirror .line-indicator-widget > .arrow {
</ins><span class="cx"> display: none;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-.source-code.text-editor > .CodeMirror .issue-widget.inline > .arrow {
</del><ins>+.source-code.text-editor > .CodeMirror .line-indicator-widget.inline > .arrow {
</ins><span class="cx"> position: absolute;
</span><span class="cx"> left: -5px;
</span><span class="cx"> display: block;
</span><span class="lines">@@ -70,12 +74,12 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> @media (-webkit-min-device-pixel-ratio: 2) {
</span><del>- .source-code.text-editor > .CodeMirror .issue-widget.inline > .arrow {
</del><ins>+ .source-code.text-editor > .CodeMirror .line-indicator-widget.inline > .arrow {
</ins><span class="cx"> left: -5.5px;
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-.source-code.text-editor > .CodeMirror .issue-widget > .icon {
</del><ins>+.source-code.text-editor > .CodeMirror .line-indicator-widget > .icon {
</ins><span class="cx"> height: 9px;
</span><span class="cx"> width: 9px;
</span><span class="cx"> padding-right: 12px;
</span><span class="lines">@@ -85,6 +89,18 @@
</span><span class="cx"> background-position-y: 1px;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+.source-code.text-editor > .CodeMirror .line-indicator-widget > .text {
+ font-family: -apple-system, sans-serif;
+}
+
+.source-code.text-editor > .CodeMirror .line-indicator-widget.inline > .text {
+ display: inline-block;
+ max-width: 300px;
+ vertical-align: baseline;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
</ins><span class="cx"> .source-code.text-editor > .CodeMirror .issue-widget > .icon.icon-warning {
</span><span class="cx"> background-image: url(../Images/Warning.svg);
</span><span class="cx"> }
</span><span class="lines">@@ -117,18 +133,18 @@
</span><span class="cx"> border-right-color: hsl(11, 100%, 80%);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-.source-code.text-editor > .CodeMirror .issue-widget > .text {
- font-family: -apple-system, sans-serif;
</del><ins>+.source-code.text-editor > .CodeMirror .thread-widget {
+ background-color: hsl(90, 30%, 82%);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-.source-code.text-editor > .CodeMirror .issue-widget.inline > .text {
- display: inline-block;
- max-width: 300px;
- vertical-align: baseline;
- text-overflow: ellipsis;
- white-space: nowrap;
</del><ins>+.source-code.text-editor > .CodeMirror .thread-widget.inline {
+ background-color: hsl(90, 30%, 82%);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+.source-code.text-editor > .CodeMirror .thread-widget.inline > .arrow {
+ border-right-color: hsl(90, 30%, 82%);
+}
+
</ins><span class="cx"> .popover .debugger-popover-content {
</span><span class="cx"> font-family: Menlo, monospace;
</span><span class="cx"> font-size: 11px;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSourceCodeTextEditorjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js (208782 => 208783)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js        2016-11-16 05:05:38 UTC (rev 208782)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js        2016-11-16 06:03:45 UTC (rev 208783)
</span><span class="lines">@@ -42,6 +42,10 @@
</span><span class="cx"> this._requestingScriptContent = false;
</span><span class="cx"> this._activeCallFrameSourceCodeLocation = null;
</span><span class="cx">
</span><ins>+ this._threadLineNumberMap = new Map; // line -> [targets]
+ this._threadWidgetMap = new Map; // line -> widget
+ this._threadTargetMap = new Map; // target -> line
+
</ins><span class="cx"> this._typeTokenScrollHandler = null;
</span><span class="cx"> this._typeTokenAnnotator = null;
</span><span class="cx"> this._basicBlockAnnotator = null;
</span><span class="lines">@@ -67,9 +71,13 @@
</span><span class="cx"> WebInspector.Breakpoint.addEventListener(WebInspector.Breakpoint.Event.ResolvedStateDidChange, this._breakpointStatusDidChange, this);
</span><span class="cx"> WebInspector.Breakpoint.addEventListener(WebInspector.Breakpoint.Event.LocationDidChange, this._updateBreakpointLocation, this);
</span><span class="cx">
</span><ins>+ WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event.TargetAdded, this._targetAdded, this);
+ WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event.TargetRemoved, this._targetRemoved, this);
+
</ins><span class="cx"> WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointsEnabledDidChange, this._breakpointsEnabledDidChange, this);
</span><span class="cx"> WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointAdded, this._breakpointAdded, this);
</span><span class="cx"> WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointRemoved, this._breakpointRemoved, this);
</span><ins>+ WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, this._callFramesDidChange, this);
</ins><span class="cx"> WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, this._activeCallFrameDidChange, this);
</span><span class="cx">
</span><span class="cx"> WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Paused, this._debuggerDidPause, this);
</span><span class="lines">@@ -162,6 +170,7 @@
</span><span class="cx"> if (this._supportsDebugging) {
</span><span class="cx"> WebInspector.Breakpoint.removeEventListener(null, null, this);
</span><span class="cx"> WebInspector.debuggerManager.removeEventListener(null, null, this);
</span><ins>+ WebInspector.targetManager.removeEventListener(null, null, this);
</ins><span class="cx">
</span><span class="cx"> if (this._activeCallFrameSourceCodeLocation) {
</span><span class="cx"> this._activeCallFrameSourceCodeLocation.removeEventListener(WebInspector.SourceCodeLocation.Event.LocationChanged, this._activeCallFrameSourceCodeLocationChanged, this);
</span><span class="lines">@@ -479,6 +488,7 @@
</span><span class="cx"> // partial script content this can be called multiple times.)
</span><span class="cx">
</span><span class="cx"> this._reinsertAllIssues();
</span><ins>+ this._reinsertAllThreadIndicators();
</ins><span class="cx">
</span><span class="cx"> this._updateEditableMarkers();
</span><span class="cx"> }
</span><span class="lines">@@ -650,6 +660,150 @@
</span><span class="cx"> this.setBreakpointInfoForLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber, null);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ _targetAdded(event)
+ {
+ if (WebInspector.targets.size === 2)
+ this._reinsertAllThreadIndicators();
+ }
+
+ _targetRemoved(event)
+ {
+ if (WebInspector.targets.size === 1) {
+ // Back to one thread, remove thread indicators.
+ this._reinsertAllThreadIndicators();
+ return;
+ }
+
+ let target = event.data.target;
+ this._removeThreadIndicatorForTarget(target);
+ }
+
+ _callFramesDidChange(event)
+ {
+ if (WebInspector.targets.size === 1)
+ return;
+
+ let target = event.data.target;
+ this._removeThreadIndicatorForTarget(target);
+ this._addThreadIndicatorForTarget(target);
+ }
+
+ _addThreadIndicatorForTarget(target)
+ {
+ let targetData = WebInspector.debuggerManager.dataForTarget(target);
+ let topCallFrame = targetData.callFrames[0];
+ if (!topCallFrame)
+ return;
+
+ let sourceCodeLocation = topCallFrame.sourceCodeLocation;
+ console.assert(sourceCodeLocation, "Expected source code location to place thread indicator.");
+ if (!sourceCodeLocation)
+ return;
+
+ if (!this._looselyMatchesSourceCodeLocation(sourceCodeLocation))
+ return;
+
+ let lineNumberWithIndicator = sourceCodeLocation.formattedLineNumber;
+ this._threadTargetMap.set(target, lineNumberWithIndicator);
+
+ let threads = this._threadLineNumberMap.get(lineNumberWithIndicator);
+ if (!threads) {
+ threads = [];
+ this._threadLineNumberMap.set(lineNumberWithIndicator, threads);
+ }
+ threads.push(target);
+
+ let widget = this._threadIndicatorWidgetForLine(target, lineNumberWithIndicator);
+ this._updateThreadIndicatorWidget(widget, threads);
+
+ this.addStyleClassToLine(lineNumberWithIndicator, "thread-indicator");
+ }
+
+ _removeThreadIndicatorForTarget(target)
+ {
+ let lineNumberWithIndicator = this._threadTargetMap.take(target);
+ if (lineNumberWithIndicator === undefined)
+ return;
+
+ let threads = this._threadLineNumberMap.get(lineNumberWithIndicator);
+ threads.remove(target);
+ if (threads.length) {
+ let widget = this._threadWidgetMap.get(lineNumberWithIndicator);
+ this._updateThreadIndicatorWidget(widget, threads);
+ return;
+ }
+
+ this._threadLineNumberMap.delete(lineNumberWithIndicator);
+
+ let widget = this._threadWidgetMap.take(lineNumberWithIndicator);
+ if (widget)
+ widget.clear();
+
+ this.removeStyleClassFromLine(lineNumberWithIndicator, "thread-indicator");
+ }
+
+ _threadIndicatorWidgetForLine(target, lineNumber)
+ {
+ let widget = this._threadWidgetMap.get(lineNumber);
+ if (widget)
+ return widget;
+
+ widget = this.createWidgetForLine(lineNumber);
+ if (!widget)
+ return null;
+
+ let widgetElement = widget.widgetElement;
+ widgetElement.classList.add("line-indicator-widget", "thread-widget", "inline");
+ widgetElement.addEventListener("click", this._handleThreadIndicatorWidgetClick.bind(this, widget, lineNumber));
+
+ this._threadWidgetMap.set(lineNumber, widget);
+
+ return widget;
+ }
+
+ _updateThreadIndicatorWidget(widget, threads)
+ {
+ if (!widget)
+ return;
+
+ console.assert(WebInspector.targets.size > 1);
+
+ let widgetElement = widget.widgetElement;
+ widgetElement.removeChildren();
+
+ widget[WebInspector.SourceCodeTextEditor.WidgetContainsMultipleThreadsSymbol] = threads.length > 1;
+
+ if (widgetElement.classList.contains("inline") || threads.length === 1) {
+ let arrowElement = widgetElement.appendChild(document.createElement("span"));
+ arrowElement.className = "arrow";
+
+ let textElement = widgetElement.appendChild(document.createElement("span"));
+ textElement.className = "text";
+ textElement.textContent = threads.length === 1 ? threads[0].displayName : WebInspector.UIString("%d Threads").format(threads.length);
+ } else {
+ for (let target of threads) {
+ let textElement = widgetElement.appendChild(document.createElement("span"));
+ textElement.className = "text";
+ textElement.textContent = target.displayName;
+
+ widgetElement.appendChild(document.createElement("br"));
+ }
+ }
+
+ widget.update();
+ }
+
+ _handleThreadIndicatorWidgetClick(widget, lineNumber, event)
+ {
+ if (!this._isWidgetToggleable(widget))
+ return;
+
+ widget.widgetElement.classList.toggle("inline");
+
+ let threads = this._threadLineNumberMap.get(lineNumber);
+ this._updateThreadIndicatorWidget(widget, threads);
+ }
+
</ins><span class="cx"> _activeCallFrameDidChange()
</span><span class="cx"> {
</span><span class="cx"> console.assert(this._supportsDebugging);
</span><span class="lines">@@ -659,7 +813,7 @@
</span><span class="cx"> this._activeCallFrameSourceCodeLocation = null;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- var activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
</del><ins>+ let activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
</ins><span class="cx"> if (!activeCallFrame || !this._matchesSourceCodeLocation(activeCallFrame.sourceCodeLocation)) {
</span><span class="cx"> this.setExecutionLineAndColumn(NaN, NaN);
</span><span class="cx"> return;
</span><span class="lines">@@ -673,7 +827,7 @@
</span><span class="cx"> // Don't return early if the line number didn't change. The execution state still
</span><span class="cx"> // could have changed (e.g. continuing in a loop with a breakpoint inside).
</span><span class="cx">
</span><del>- var lineInfo = this._editorLineInfoForSourceCodeLocation(activeCallFrame.sourceCodeLocation);
</del><ins>+ let lineInfo = this._editorLineInfoForSourceCodeLocation(activeCallFrame.sourceCodeLocation);
</ins><span class="cx"> this.setExecutionLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber);
</span><span class="cx">
</span><span class="cx"> // If we have full content or this source code isn't a Resource we can return early.
</span><span class="lines">@@ -811,6 +965,15 @@
</span><span class="cx"> scripts[0].requestContent().then(scriptContentAvailable.bind(this));
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ _looselyMatchesSourceCodeLocation(sourceCodeLocation)
+ {
+ if (this._sourceCode instanceof WebInspector.SourceMapResource)
+ return sourceCodeLocation.displaySourceCode === this._sourceCode;
+ if (this._sourceCode instanceof WebInspector.Resource || this._sourceCode instanceof WebInspector.Script)
+ return sourceCodeLocation.sourceCode.url === this._sourceCode.url;
+ return false;
+ }
+
</ins><span class="cx"> _matchesSourceCodeLocation(sourceCodeLocation)
</span><span class="cx"> {
</span><span class="cx"> if (this._sourceCode instanceof WebInspector.SourceMapResource)
</span><span class="lines">@@ -895,7 +1058,7 @@
</span><span class="cx"> return null;
</span><span class="cx">
</span><span class="cx"> var widgetElement = widget.widgetElement;
</span><del>- widgetElement.classList.add("issue-widget", "inline");
</del><ins>+ widgetElement.classList.add("line-indicator-widget", "issue-widget", "inline");
</ins><span class="cx"> widgetElement.addEventListener("click", this._handleWidgetClick.bind(this, widget, lineNumber));
</span><span class="cx">
</span><span class="cx"> this._widgetMap.set(lineNumber, widget);
</span><span class="lines">@@ -975,6 +1138,9 @@
</span><span class="cx"> if (widget[WebInspector.SourceCodeTextEditor.WidgetContainsMultipleIssuesSymbol])
</span><span class="cx"> return true;
</span><span class="cx">
</span><ins>+ if (widget[WebInspector.SourceCodeTextEditor.WidgetContainsMultipleThreadsSymbol])
+ return true;
+
</ins><span class="cx"> if (!widget.widgetElement.classList.contains("inline"))
</span><span class="cx"> return true;
</span><span class="cx">
</span><span class="lines">@@ -1227,6 +1393,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> this._reinsertAllIssues();
</span><ins>+ this._reinsertAllThreadIndicators();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> textEditorExecutionHighlightRange(offset, position, characterAtOffset, callback)
</span><span class="lines">@@ -1352,7 +1519,7 @@
</span><span class="cx"> });
</span><span class="cx"> }
</span><span class="cx">
</span><del>- _clearWidgets()
</del><ins>+ _clearIssueWidgets()
</ins><span class="cx"> {
</span><span class="cx"> for (var widget of this._widgetMap.values())
</span><span class="cx"> widget.clear();
</span><span class="lines">@@ -1363,13 +1530,34 @@
</span><span class="cx"> _reinsertAllIssues()
</span><span class="cx"> {
</span><span class="cx"> this._issuesLineNumberMap.clear();
</span><del>- this._clearWidgets();
</del><ins>+ this._clearIssueWidgets();
</ins><span class="cx">
</span><del>- var issues = WebInspector.issueManager.issuesForSourceCode(this._sourceCode);
- for (var issue of issues)
</del><ins>+ let issues = WebInspector.issueManager.issuesForSourceCode(this._sourceCode);
+ for (let issue of issues)
</ins><span class="cx"> this._addIssue(issue);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ _reinsertAllThreadIndicators()
+ {
+ // Clear line styles.
+ for (let lineNumber of this._threadLineNumberMap.keys())
+ this.removeStyleClassFromLine(lineNumber, "thread-indicator");
+ this._threadLineNumberMap.clear();
+
+ // Clear widgets.
+ for (let widget of this._threadWidgetMap.values())
+ widget.clear();
+ this._threadWidgetMap.clear();
+
+ // Clear other maps.
+ this._threadTargetMap.clear();
+
+ if (WebInspector.targets.size > 1) {
+ for (let target of WebInspector.targets)
+ this._addThreadIndicatorForTarget(target);
+ }
+ }
+
</ins><span class="cx"> _debuggerDidPause(event)
</span><span class="cx"> {
</span><span class="cx"> this._updateTokenTrackingControllerState();
</span><span class="lines">@@ -2049,7 +2237,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> this._issuesLineNumberMap.clear();
</span><del>- this._clearWidgets();
</del><ins>+ this._clearIssueWidgets();
</ins><span class="cx"> }
</span><span class="cx"> };
</span><span class="cx">
</span><span class="lines">@@ -2061,6 +2249,7 @@
</span><span class="cx"> WebInspector.SourceCodeTextEditor.DurationToMouseOutOfHoveredTokenToRelease = 1000;
</span><span class="cx"> WebInspector.SourceCodeTextEditor.DurationToUpdateTypeTokensAfterScrolling = 100;
</span><span class="cx"> WebInspector.SourceCodeTextEditor.WidgetContainsMultipleIssuesSymbol = Symbol("source-code-widget-contains-multiple-issues");
</span><ins>+WebInspector.SourceCodeTextEditor.WidgetContainsMultipleThreadsSymbol = Symbol("source-code-widget-contains-multiple-threads");
</ins><span class="cx">
</span><span class="cx"> WebInspector.SourceCodeTextEditor.Event = {
</span><span class="cx"> ContentWillPopulate: "source-code-text-editor-content-will-populate",
</span></span></pre>
</div>
</div>
</body>
</html>