Changeset 208783 in webkit


Ignore:
Timestamp:
Nov 15, 2016 10:03:45 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

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 <Joseph Pecoraro> 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.

  1. line -> widget

Gets the widget on a line so we can modify and eventually remove it.

  1. 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.

Location:
trunk/Source/WebInspectorUI
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r208779 r208783  
     12016-11-15  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: SourceCodeTextEditor should display execution lines for background threads
     4        https://bugs.webkit.org/show_bug.cgi?id=164679
     5        <rdar://problem/29233026>
     6
     7        Reviewed by Timothy Hatcher.
     8
     9        There may be multiple threads paused in the same content view. With
     10        this change we should a thread indicator for each primary line a
     11        thread is paused on. It uses the same inline line indicator that
     12        inline errors/warnings (issues) use.
     13
     14        When there is a single thread (just the Page) we don't show thread
     15        indicators. But as soon as there are multiple threads we start
     16        managing and showing them. The line indicator contains the name of
     17        the thread on the side.
     18
     19        Note that SourceCodeTextEditor maintains the thread indicators, but
     20        it still always handles the ActiveCallFrame as it used to, pushing
     21        values down into TextEditor. The ActiveCallFrame styles override
     22        the thread line indicators (albeit with the same styles). The reason
     23        these are still separate is that TextEditor has some special styles
     24        regarding its gutter for the active execution line. Eventually we
     25        may want to find a way to push this up into SourceCodeTextEditor.
     26
     27        * Localizations/en.lproj/localizedStrings.js:
     28        New string "%d Threads" when multiple threads are on the same line.
     29
     30        * UserInterface/Views/ScopeChainDetailsSidebarPanel.js:
     31        (WebInspector.ScopeChainDetailsSidebarPanel):
     32        (WebInspector.ScopeChainDetailsSidebarPanel.prototype._activeCallFrameDidChange):
     33        Update Watch Expressions when the active call frame changes.
     34
     35        * UserInterface/Views/SourceCodeTextEditor.css:
     36        (.source-code.text-editor > .CodeMirror .line-indicator-widget):
     37        (.source-code.text-editor > .CodeMirror .line-indicator-widget.inline):
     38        (.source-code.text-editor > .CodeMirror .line-indicator-widget > .arrow):
     39        (.source-code.text-editor > .CodeMirror .line-indicator-widget.inline > .arrow):
     40        (.source-code.text-editor > .CodeMirror .line-indicator-widget > .icon):
     41        (.source-code.text-editor > .CodeMirror .line-indicator-widget > .text):
     42        (.source-code.text-editor > .CodeMirror .line-indicator-widget.inline > .text):
     43        Share line indicator widget styles between issue widgets and thread widgets.
     44
     45        (.source-code.text-editor > .CodeMirror .thread-indicator):
     46        (.source-code.text-editor > .CodeMirror .thread-widget):
     47        (.source-code.text-editor > .CodeMirror .thread-widget.inline):
     48        (.source-code.text-editor > .CodeMirror .thread-widget.inline > .arrow):
     49        Colors for the thread-widget line-indicators.
     50
     51        * UserInterface/Views/SourceCodeTextEditor.js:
     52        (WebInspector.SourceCodeTextEditor):
     53        (WebInspector.SourceCodeTextEditor.prototype.close):
     54        New event listeners handling for Target added / removed events.
     55
     56        (WebInspector.SourceCodeTextEditor.prototype._targetAdded):
     57        (WebInspector.SourceCodeTextEditor.prototype._targetRemoved):
     58        Update thread indicators as needed.
     59
     60        (WebInspector.SourceCodeTextEditor.prototype._looselyMatchesSourceCodeLocation):
     61        More generic match based just on the URLs. Even if the exact script comes
     62        from a different target, if they share the same URL that is fine.
     63
     64        (WebInspector.SourceCodeTextEditor.prototype._callFramesDidChange):
     65        (WebInspector.SourceCodeTextEditor.prototype._addThreadIndicatorForTarget):
     66        (WebInspector.SourceCodeTextEditor.prototype._removeThreadIndicatorForTarget):
     67        (WebInspector.SourceCodeTextEditor.prototype._threadIndicatorWidgetForLine):
     68        (WebInspector.SourceCodeTextEditor.prototype._updateThreadIndicatorWidget):
     69        (WebInspector.SourceCodeTextEditor.prototype._handleThreadIndicatorWidgetClick):
     70        Manage thread line indicator widgets. There are 3 maps we maintain.
     71
     72          1. line -> [threads]
     73              List of threads paused on a line, needed for the UI text.
     74          2. line -> widget
     75              Gets the widget on a line so we can modify and eventually remove it.
     76          3. target -> line
     77              If a target is removed, we need to know what line it had an indicator on.
     78
     79        (WebInspector.SourceCodeTextEditor.prototype._isWidgetToggleable):
     80        Generalize for all of our different line indicator widgets.
     81
     82        (WebInspector.SourceCodeTextEditor.prototype._contentDidPopulate):
     83        (WebInspector.SourceCodeTextEditor.prototype.textEditorUpdatedFormatting):       
     84        (WebInspector.SourceCodeTextEditor.prototype._reinsertAllThreadIndicators):
     85        When first populated, or reformatted, clear and reinsert all widgets.
     86
     87        (WebInspector.SourceCodeTextEditor.prototype._reinsertAllIssues):
     88        (WebInspector.SourceCodeTextEditor.prototype._logCleared):
     89        (WebInspector.SourceCodeTextEditor.prototype._clearIssueWidgets): Renamed.
     90        Rename _clearWidgets to _clearIssueWidgets.
     91
    1922016-11-15  Joseph Pecoraro  <pecoraro@apple.com>
    293
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r208779 r208783  
    2323localizedStrings["%d Errors, %d Warnings"] = "%d Errors, %d Warnings";
    2424localizedStrings["%d More\u2026"] = "%d More\u2026";
     25localizedStrings["%d Threads"] = "%d Threads";
    2526localizedStrings["%d Warnings"] = "%d Warnings";
    2627localizedStrings["%d \xd7 %d pixels"] = "%d \xd7 %d pixels";
  • trunk/Source/WebInspectorUI/UserInterface/Views/ScopeChainDetailsSidebarPanel.js

    r208664 r208783  
    6969        // Update watch expressions on navigations.
    7070        WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
     71
     72        // Update watch expressions on active call frame changes.
     73        WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, this._activeCallFrameDidChange, this);
    7174    }
    7275
     
    425428    }
    426429
     430    _activeCallFrameDidChange()
     431    {
     432        this.needsLayout();
     433    }
     434
    427435    _mainResourceDidChange(event)
    428436    {
  • trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.css

    r205832 r208783  
    3737}
    3838
    39 .source-code.text-editor > .CodeMirror .issue-widget {
     39.source-code.text-editor > .CodeMirror .thread-indicator {
     40    background-color: hsla(99, 38%, 86%, 0.5);
     41}
     42
     43.source-code.text-editor > .CodeMirror .line-indicator-widget {
    4044    float: right;
    4145    padding: 0 5px 1px 5px;
     
    4448}
    4549
    46 .source-code.text-editor > .CodeMirror .issue-widget.inline {
     50.source-code.text-editor > .CodeMirror .line-indicator-widget.inline {
    4751    position: relative;
    4852    top: -13px;
     
    5256}
    5357
    54 .source-code.text-editor > .CodeMirror .issue-widget > .arrow {
     58.source-code.text-editor > .CodeMirror .line-indicator-widget > .arrow {
    5559    display: none;
    5660}
    5761
    58 .source-code.text-editor > .CodeMirror .issue-widget.inline > .arrow {
     62.source-code.text-editor > .CodeMirror .line-indicator-widget.inline > .arrow {
    5963    position: absolute;
    6064    left: -5px;
     
    7175
    7276@media (-webkit-min-device-pixel-ratio: 2) {
    73     .source-code.text-editor > .CodeMirror .issue-widget.inline > .arrow {
     77    .source-code.text-editor > .CodeMirror .line-indicator-widget.inline > .arrow {
    7478        left: -5.5px;
    7579    }
    7680}
    7781
    78 .source-code.text-editor > .CodeMirror .issue-widget > .icon {
     82.source-code.text-editor > .CodeMirror .line-indicator-widget > .icon {
    7983    height: 9px;
    8084    width: 9px;
     
    8690}
    8791
    88 .source-code.text-editor > .CodeMirror .issue-widget > .icon.icon-warning {
    89     background-image: url(../Images/Warning.svg);
    90 }
    91 
    92 .source-code.text-editor > .CodeMirror .issue-widget > .icon.icon-error {
    93     background-image: url(../Images/Error.svg);
    94 }
    95 
    96 .source-code.text-editor > .CodeMirror .issue-widget.warning {
    97     background-color: hsl(51, 87%, 93%);
    98 }
    99 
    100 .source-code.text-editor > .CodeMirror .issue-widget.inline.warning {
    101     background-color: hsl(43, 97%, 84%);
    102 }
    103 
    104 .source-code.text-editor > .CodeMirror .issue-widget.inline.warning > .arrow {
    105     border-right-color: hsl(43, 97%, 84%);
    106 }
    107 
    108 .source-code.text-editor > .CodeMirror .issue-widget.error {
    109     background-color: hsl(15, 100%, 90%);
    110 }
    111 
    112 .source-code.text-editor > .CodeMirror .issue-widget.inline.error {
    113     background-color: hsl(11, 100%, 80%);
    114 }
    115 
    116 .source-code.text-editor > .CodeMirror .issue-widget.inline.error > .arrow {
    117     border-right-color: hsl(11, 100%, 80%);
    118 }
    119 
    120 .source-code.text-editor > .CodeMirror .issue-widget > .text {
     92.source-code.text-editor > .CodeMirror .line-indicator-widget > .text {
    12193    font-family: -apple-system, sans-serif;
    12294}
    12395
    124 .source-code.text-editor > .CodeMirror .issue-widget.inline > .text {
     96.source-code.text-editor > .CodeMirror .line-indicator-widget.inline > .text {
    12597    display: inline-block;
    12698    max-width: 300px;
     
    128100    text-overflow: ellipsis;
    129101    white-space: nowrap;
     102}
     103
     104.source-code.text-editor > .CodeMirror .issue-widget > .icon.icon-warning {
     105    background-image: url(../Images/Warning.svg);
     106}
     107
     108.source-code.text-editor > .CodeMirror .issue-widget > .icon.icon-error {
     109    background-image: url(../Images/Error.svg);
     110}
     111
     112.source-code.text-editor > .CodeMirror .issue-widget.warning {
     113    background-color: hsl(51, 87%, 93%);
     114}
     115
     116.source-code.text-editor > .CodeMirror .issue-widget.inline.warning {
     117    background-color: hsl(43, 97%, 84%);
     118}
     119
     120.source-code.text-editor > .CodeMirror .issue-widget.inline.warning > .arrow {
     121    border-right-color: hsl(43, 97%, 84%);
     122}
     123
     124.source-code.text-editor > .CodeMirror .issue-widget.error {
     125    background-color: hsl(15, 100%, 90%);
     126}
     127
     128.source-code.text-editor > .CodeMirror .issue-widget.inline.error {
     129    background-color: hsl(11, 100%, 80%);
     130}
     131
     132.source-code.text-editor > .CodeMirror .issue-widget.inline.error > .arrow {
     133    border-right-color: hsl(11, 100%, 80%);
     134}
     135
     136.source-code.text-editor > .CodeMirror .thread-widget {
     137    background-color: hsl(90, 30%, 82%);
     138}
     139
     140.source-code.text-editor > .CodeMirror .thread-widget.inline {
     141    background-color: hsl(90, 30%, 82%);
     142}
     143
     144.source-code.text-editor > .CodeMirror .thread-widget.inline > .arrow {
     145    border-right-color: hsl(90, 30%, 82%);
    130146}
    131147
  • trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js

    r208664 r208783  
    4343        this._activeCallFrameSourceCodeLocation = null;
    4444
     45        this._threadLineNumberMap = new Map; // line -> [targets]
     46        this._threadWidgetMap = new Map; // line -> widget
     47        this._threadTargetMap = new Map; // target -> line
     48
    4549        this._typeTokenScrollHandler = null;
    4650        this._typeTokenAnnotator = null;
     
    6872            WebInspector.Breakpoint.addEventListener(WebInspector.Breakpoint.Event.LocationDidChange, this._updateBreakpointLocation, this);
    6973
     74            WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event.TargetAdded, this._targetAdded, this);
     75            WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event.TargetRemoved, this._targetRemoved, this);
     76
    7077            WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointsEnabledDidChange, this._breakpointsEnabledDidChange, this);
    7178            WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointAdded, this._breakpointAdded, this);
    7279            WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointRemoved, this._breakpointRemoved, this);
     80            WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.CallFramesDidChange, this._callFramesDidChange, this);
    7381            WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, this._activeCallFrameDidChange, this);
    7482
     
    163171            WebInspector.Breakpoint.removeEventListener(null, null, this);
    164172            WebInspector.debuggerManager.removeEventListener(null, null, this);
     173            WebInspector.targetManager.removeEventListener(null, null, this);
    165174
    166175            if (this._activeCallFrameSourceCodeLocation) {
     
    480489
    481490        this._reinsertAllIssues();
     491        this._reinsertAllThreadIndicators();
    482492
    483493        this._updateEditableMarkers();
     
    651661    }
    652662
     663    _targetAdded(event)
     664    {
     665        if (WebInspector.targets.size === 2)
     666            this._reinsertAllThreadIndicators();
     667    }
     668
     669    _targetRemoved(event)
     670    {
     671        if (WebInspector.targets.size === 1) {
     672            // Back to one thread, remove thread indicators.
     673            this._reinsertAllThreadIndicators();
     674            return;
     675        }
     676
     677        let target = event.data.target;
     678        this._removeThreadIndicatorForTarget(target);
     679    }
     680
     681    _callFramesDidChange(event)
     682    {
     683        if (WebInspector.targets.size === 1)
     684            return;
     685
     686        let target = event.data.target;
     687        this._removeThreadIndicatorForTarget(target);
     688        this._addThreadIndicatorForTarget(target);
     689    }
     690
     691    _addThreadIndicatorForTarget(target)
     692    {
     693        let targetData = WebInspector.debuggerManager.dataForTarget(target);
     694        let topCallFrame = targetData.callFrames[0];
     695        if (!topCallFrame)
     696            return;
     697
     698        let sourceCodeLocation = topCallFrame.sourceCodeLocation;
     699        console.assert(sourceCodeLocation, "Expected source code location to place thread indicator.");
     700        if (!sourceCodeLocation)
     701            return;
     702
     703        if (!this._looselyMatchesSourceCodeLocation(sourceCodeLocation))
     704            return;
     705
     706        let lineNumberWithIndicator = sourceCodeLocation.formattedLineNumber;
     707        this._threadTargetMap.set(target, lineNumberWithIndicator);
     708
     709        let threads = this._threadLineNumberMap.get(lineNumberWithIndicator);
     710        if (!threads) {
     711            threads = [];
     712            this._threadLineNumberMap.set(lineNumberWithIndicator, threads);
     713        }
     714        threads.push(target);
     715
     716        let widget = this._threadIndicatorWidgetForLine(target, lineNumberWithIndicator);
     717        this._updateThreadIndicatorWidget(widget, threads);
     718
     719        this.addStyleClassToLine(lineNumberWithIndicator, "thread-indicator");
     720    }
     721
     722    _removeThreadIndicatorForTarget(target)
     723    {
     724        let lineNumberWithIndicator = this._threadTargetMap.take(target);
     725        if (lineNumberWithIndicator === undefined)
     726            return;
     727
     728        let threads = this._threadLineNumberMap.get(lineNumberWithIndicator);
     729        threads.remove(target);
     730        if (threads.length) {
     731            let widget = this._threadWidgetMap.get(lineNumberWithIndicator);
     732            this._updateThreadIndicatorWidget(widget, threads);
     733            return;
     734        }
     735
     736        this._threadLineNumberMap.delete(lineNumberWithIndicator);
     737
     738        let widget = this._threadWidgetMap.take(lineNumberWithIndicator);
     739        if (widget)
     740            widget.clear();
     741
     742        this.removeStyleClassFromLine(lineNumberWithIndicator, "thread-indicator");
     743    }
     744
     745    _threadIndicatorWidgetForLine(target, lineNumber)
     746    {
     747        let widget = this._threadWidgetMap.get(lineNumber);
     748        if (widget)
     749            return widget;
     750
     751        widget = this.createWidgetForLine(lineNumber);
     752        if (!widget)
     753            return null;
     754
     755        let widgetElement = widget.widgetElement;
     756        widgetElement.classList.add("line-indicator-widget", "thread-widget", "inline");
     757        widgetElement.addEventListener("click", this._handleThreadIndicatorWidgetClick.bind(this, widget, lineNumber));
     758
     759        this._threadWidgetMap.set(lineNumber, widget);
     760
     761        return widget;
     762    }
     763
     764    _updateThreadIndicatorWidget(widget, threads)
     765    {
     766        if (!widget)
     767            return;
     768
     769        console.assert(WebInspector.targets.size > 1);
     770
     771        let widgetElement = widget.widgetElement;
     772        widgetElement.removeChildren();
     773
     774        widget[WebInspector.SourceCodeTextEditor.WidgetContainsMultipleThreadsSymbol] = threads.length > 1;
     775
     776        if (widgetElement.classList.contains("inline") || threads.length === 1) {
     777            let arrowElement = widgetElement.appendChild(document.createElement("span"));
     778            arrowElement.className = "arrow";
     779
     780            let textElement = widgetElement.appendChild(document.createElement("span"));
     781            textElement.className = "text";
     782            textElement.textContent = threads.length === 1 ? threads[0].displayName : WebInspector.UIString("%d Threads").format(threads.length);
     783        } else {
     784            for (let target of threads) {
     785                let textElement = widgetElement.appendChild(document.createElement("span"));
     786                textElement.className = "text";
     787                textElement.textContent = target.displayName;
     788
     789                widgetElement.appendChild(document.createElement("br"));
     790            }
     791        }
     792
     793        widget.update();
     794    }
     795
     796    _handleThreadIndicatorWidgetClick(widget, lineNumber, event)
     797    {
     798        if (!this._isWidgetToggleable(widget))
     799            return;
     800
     801        widget.widgetElement.classList.toggle("inline");
     802
     803        let threads = this._threadLineNumberMap.get(lineNumber);
     804        this._updateThreadIndicatorWidget(widget, threads);
     805    }
     806
    653807    _activeCallFrameDidChange()
    654808    {
     
    660814        }
    661815
    662         var activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
     816        let activeCallFrame = WebInspector.debuggerManager.activeCallFrame;
    663817        if (!activeCallFrame || !this._matchesSourceCodeLocation(activeCallFrame.sourceCodeLocation)) {
    664818            this.setExecutionLineAndColumn(NaN, NaN);
     
    674828        // could have changed (e.g. continuing in a loop with a breakpoint inside).
    675829
    676         var lineInfo = this._editorLineInfoForSourceCodeLocation(activeCallFrame.sourceCodeLocation);
     830        let lineInfo = this._editorLineInfoForSourceCodeLocation(activeCallFrame.sourceCodeLocation);
    677831        this.setExecutionLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber);
    678832
     
    812966    }
    813967
     968    _looselyMatchesSourceCodeLocation(sourceCodeLocation)
     969    {
     970        if (this._sourceCode instanceof WebInspector.SourceMapResource)
     971            return sourceCodeLocation.displaySourceCode === this._sourceCode;
     972        if (this._sourceCode instanceof WebInspector.Resource || this._sourceCode instanceof WebInspector.Script)
     973            return sourceCodeLocation.sourceCode.url === this._sourceCode.url;
     974        return false;
     975    }
     976
    814977    _matchesSourceCodeLocation(sourceCodeLocation)
    815978    {
     
    8961059
    8971060        var widgetElement = widget.widgetElement;
    898         widgetElement.classList.add("issue-widget", "inline");
     1061        widgetElement.classList.add("line-indicator-widget", "issue-widget", "inline");
    8991062        widgetElement.addEventListener("click", this._handleWidgetClick.bind(this, widget, lineNumber));
    9001063
     
    9761139            return true;
    9771140
     1141        if (widget[WebInspector.SourceCodeTextEditor.WidgetContainsMultipleThreadsSymbol])
     1142            return true;
     1143
    9781144        if (!widget.widgetElement.classList.contains("inline"))
    9791145            return true;
     
    12281394
    12291395        this._reinsertAllIssues();
     1396        this._reinsertAllThreadIndicators();
    12301397    }
    12311398
     
    13531520    }
    13541521
    1355     _clearWidgets()
     1522    _clearIssueWidgets()
    13561523    {
    13571524        for (var widget of this._widgetMap.values())
     
    13641531    {
    13651532        this._issuesLineNumberMap.clear();
    1366         this._clearWidgets();
    1367 
    1368         var issues = WebInspector.issueManager.issuesForSourceCode(this._sourceCode);
    1369         for (var issue of issues)
     1533        this._clearIssueWidgets();
     1534
     1535        let issues = WebInspector.issueManager.issuesForSourceCode(this._sourceCode);
     1536        for (let issue of issues)
    13701537            this._addIssue(issue);
     1538    }
     1539
     1540    _reinsertAllThreadIndicators()
     1541    {
     1542        // Clear line styles.
     1543        for (let lineNumber of this._threadLineNumberMap.keys())
     1544            this.removeStyleClassFromLine(lineNumber, "thread-indicator");
     1545        this._threadLineNumberMap.clear();
     1546
     1547        // Clear widgets.
     1548        for (let widget of this._threadWidgetMap.values())
     1549            widget.clear();
     1550        this._threadWidgetMap.clear();
     1551
     1552        // Clear other maps.
     1553        this._threadTargetMap.clear();
     1554
     1555        if (WebInspector.targets.size > 1) {
     1556            for (let target of WebInspector.targets)
     1557                this._addThreadIndicatorForTarget(target);
     1558        }
    13711559    }
    13721560
     
    20502238
    20512239        this._issuesLineNumberMap.clear();
    2052         this._clearWidgets();
     2240        this._clearIssueWidgets();
    20532241    }
    20542242};
     
    20622250WebInspector.SourceCodeTextEditor.DurationToUpdateTypeTokensAfterScrolling = 100;
    20632251WebInspector.SourceCodeTextEditor.WidgetContainsMultipleIssuesSymbol = Symbol("source-code-widget-contains-multiple-issues");
     2252WebInspector.SourceCodeTextEditor.WidgetContainsMultipleThreadsSymbol = Symbol("source-code-widget-contains-multiple-threads");
    20642253
    20652254WebInspector.SourceCodeTextEditor.Event = {
Note: See TracChangeset for help on using the changeset viewer.