Web Inspector: Debugger statement in console does not provide any call frames and...
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / DebuggerSidebarPanel.js
index 619ddbc..3ccab04 100644 (file)
@@ -31,7 +31,7 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
 
         this.contentBrowser = contentBrowser;
 
-        WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceChanged, this);
+        WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
         WebInspector.Frame.addEventListener(WebInspector.Frame.Event.ResourceWasAdded, this._resourceAdded, this);
 
         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointsEnabledDidChange, this._breakpointsEnabledDidChange, this);
@@ -39,23 +39,32 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointAdded, this._breakpointAdded, this);
         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.BreakpointRemoved, this._breakpointRemoved, this);
         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ScriptAdded, this._scriptAdded, this);
+        WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ScriptRemoved, this._scriptRemoved, this);
         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ScriptsCleared, this._scriptsCleared, this);
         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Paused, this._debuggerDidPause, this);
         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Resumed, this._debuggerDidResume, this);
         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.ActiveCallFrameDidChange, this._debuggerActiveCallFrameDidChange, this);
         WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.WaitingToPause, this._debuggerWaitingToPause, this);
 
-        this._navigationBar = new WebInspector.NavigationBar;
-        this.element.appendChild(this._navigationBar.element);
+        WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.CapturingWillStart, this._timelineRecordingWillStart, this);
+        WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.CapturingStopped, this._timelineRecordingStopped, this);        
+
+        this._timelineRecordingWarningElement = document.createElement("div");
+        this._timelineRecordingWarningElement.classList.add("timeline-recording-warning");
+        this._timelineRecordingWarningElement.append(WebInspector.UIString("Debugger is disabled during a Timeline recording."), " ");
+        let stopRecordingLink = this._timelineRecordingWarningElement.appendChild(document.createElement("a"));
+        stopRecordingLink.textContent = WebInspector.UIString("Stop recording.");
+        stopRecordingLink.addEventListener("click", () => { WebInspector.timelineManager.stopCapturing(); });
 
-        var imageSize = WebInspector.Platform.isLegacyMacOS ? 16 : 15;
+        this._navigationBar = new WebInspector.NavigationBar;
+        this.addSubview(this._navigationBar);
 
-        var breakpointsImage = {src: platformImagePath("Breakpoints.svg"), width: imageSize, height: imageSize};
-        var pauseImage = {src: platformImagePath("Pause.svg"), width: imageSize, height: imageSize};
-        var resumeImage = {src: platformImagePath("Resume.svg"), width: imageSize, height: imageSize};
-        var stepOverImage = {src: platformImagePath("StepOver.svg"), width: imageSize, height: imageSize};
-        var stepIntoImage = {src: platformImagePath("StepInto.svg"), width: imageSize, height: imageSize};
-        var stepOutImage = {src: platformImagePath("StepOut.svg"), width: imageSize, height: imageSize};
+        var breakpointsImage = {src: "Images/Breakpoints.svg", width: 15, height: 15};
+        var pauseImage = {src: "Images/Pause.svg", width: 15, height: 15};
+        var resumeImage = {src: "Images/Resume.svg", width: 15, height: 15};
+        var stepOverImage = {src: "Images/StepOver.svg", width: 15, height: 15};
+        var stepIntoImage = {src: "Images/StepInto.svg", width: 15, height: 15};
+        var stepOutImage = {src: "Images/StepOut.svg", width: 15, height: 15};
 
         var toolTip = WebInspector.UIString("Enable all breakpoints (%s)").format(WebInspector.toggleBreakpointsKeyboardShortcut.displayName);
         var altToolTip = WebInspector.UIString("Disable all breakpoints (%s)").format(WebInspector.toggleBreakpointsKeyboardShortcut.displayName);
@@ -93,25 +102,11 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
         this._globalBreakpointsFolderTreeElement = new WebInspector.FolderTreeElement(WebInspector.UIString("Global Breakpoints"), null, WebInspector.DebuggerSidebarPanel.GlobalIconStyleClassName);
         this._allExceptionsBreakpointTreeElement = new WebInspector.BreakpointTreeElement(WebInspector.debuggerManager.allExceptionsBreakpoint, WebInspector.DebuggerSidebarPanel.ExceptionIconStyleClassName, WebInspector.UIString("All Exceptions"));
         this._allUncaughtExceptionsBreakpointTreeElement = new WebInspector.BreakpointTreeElement(WebInspector.debuggerManager.allUncaughtExceptionsBreakpoint, WebInspector.DebuggerSidebarPanel.ExceptionIconStyleClassName, WebInspector.UIString("All Uncaught Exceptions"));
+        this.suppressFilteringOnTreeElements([this._globalBreakpointsFolderTreeElement, this._allExceptionsBreakpointTreeElement, this._allUncaughtExceptionsBreakpointTreeElement]);
 
         this.filterBar.placeholder = WebInspector.UIString("Filter Breakpoint List");
-        var showResourcesWithBreakpointsOnlyFilterFunction = function(treeElement)
-        {
-            // Keep breakpoints.
-            if (treeElement instanceof WebInspector.BreakpointTreeElement)
-                return true;
-
-            // Keep resources with breakpoints.
-            if (treeElement.hasChildren) {
-                for (var child of treeElement.children) {
-                    if (child instanceof WebInspector.BreakpointTreeElement)
-                        return true;
-                }
-            }
-            return false;
-        };
 
-        var showResourcesWithIssuesOnlyFilterFunction = function(treeElement)
+        function showResourcesWithIssuesOnlyFilterFunction(treeElement)
         {
             // Keep issues.
             if (treeElement instanceof WebInspector.IssueTreeElement)
@@ -119,7 +114,7 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
 
             // Keep resources with issues.
             if (treeElement.hasChildren) {
-                for (var child of treeElement.children) {
+                for (let child of treeElement.children) {
                     if (child instanceof WebInspector.IssueTreeElement)
                         return true;
                 }
@@ -127,11 +122,19 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
             return false;
         };
 
-        this.filterBar.addFilterBarButton("debugger-show-resources-with-breakpoints-only", showResourcesWithBreakpointsOnlyFilterFunction, true, WebInspector.UIString("Show only resources with breakpoints."), WebInspector.UIString("Show resources with and without breakpoints."), platformImagePath("Breakpoints.svg"), 15, 15);
-        this.filterBar.addFilterBarButton("debugger-show-resources-with-issues-only", showResourcesWithIssuesOnlyFilterFunction, true, WebInspector.UIString("Show only resources with issues."), WebInspector.UIString("Show resources with and without issues."), platformImagePath("Errors.svg"), 15, 15);
+        this.filterBar.addFilterBarButton("debugger-show-resources-with-issues-only", showResourcesWithIssuesOnlyFilterFunction, true, WebInspector.UIString("Show only resources with issues."), WebInspector.UIString("Show resources with and without issues."), "Images/Errors.svg", 15, 15);
 
         this._breakpointsContentTreeOutline = this.contentTreeOutline;
-        this._breakpointsContentTreeOutline.onselect = this._treeElementSelected.bind(this);
+
+        let breakpointsRow = new WebInspector.DetailsSectionRow;
+        breakpointsRow.element.appendChild(this._breakpointsContentTreeOutline.element);
+
+        let breakpointsGroup = new WebInspector.DetailsSectionGroup([breakpointsRow]);
+        let breakpointsSection = new WebInspector.DetailsSection("scripts", WebInspector.UIString("Scripts"), [breakpointsGroup]);
+        this.contentView.element.appendChild(breakpointsSection.element);
+
+        this._breakpointsContentTreeOutline.element.classList.add("breakpoints");
+        this._breakpointsContentTreeOutline.addEventListener(WebInspector.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
         this._breakpointsContentTreeOutline.ondelete = this._breakpointTreeOutlineDeleteTreeElement.bind(this);
         this._breakpointsContentTreeOutline.oncontextmenu = this._breakpointTreeOutlineContextMenuTreeElement.bind(this);
 
@@ -140,20 +143,13 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
         this._globalBreakpointsFolderTreeElement.appendChild(this._allUncaughtExceptionsBreakpointTreeElement);
         this._globalBreakpointsFolderTreeElement.expand();
 
-        var breakpointsRow = new WebInspector.DetailsSectionRow;
-        breakpointsRow.element.appendChild(this._breakpointsContentTreeOutline.element);
-
-        var breakpointsGroup = new WebInspector.DetailsSectionGroup([breakpointsRow]);
-        var breakpointsSection = new WebInspector.DetailsSection("scripts", WebInspector.UIString("Scripts"), [breakpointsGroup]);
-        this.contentElement.appendChild(breakpointsSection.element);
-
         this._callStackContentTreeOutline = this.createContentTreeOutline(true, true);
-        this._callStackContentTreeOutline.onselect = this._treeElementSelected.bind(this);
+        this._callStackContentTreeOutline.addEventListener(WebInspector.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
 
         this._callStackRow = new WebInspector.DetailsSectionRow(WebInspector.UIString("No Call Frames"));
         this._callStackRow.showEmptyMessage();
 
-        var callStackGroup = new WebInspector.DetailsSectionGroup([this._callStackRow]);
+        let callStackGroup = new WebInspector.DetailsSectionGroup([this._callStackRow]);
         this._callStackSection = new WebInspector.DetailsSection("call-stack", WebInspector.UIString("Call Stack"), [callStackGroup]);
 
         this._pauseReasonTreeOutline = null;
@@ -168,15 +164,29 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
         WebInspector.IssueMessage.addEventListener(WebInspector.IssueMessage.Event.DisplayLocationDidChange, this._handleDebuggerObjectDisplayLocationDidChange, this);
         WebInspector.issueManager.addEventListener(WebInspector.IssueManager.Event.IssueWasAdded, this._handleIssueAdded, this);
         WebInspector.issueManager.addEventListener(WebInspector.IssueManager.Event.Cleared, this._handleIssuesCleared, this);
+
+        if (WebInspector.frameResourceManager.mainFrame)
+            this._addResourcesRecursivelyForFrame(WebInspector.frameResourceManager.mainFrame);
+
+        for (var script of WebInspector.debuggerManager.knownNonResourceScripts)
+            this._addScript(script);
     }
 
     // Public
 
-    get hasSelectedElement()
+    get minimumWidth()
     {
-        return !!this._breakpointsContentTreeOutline.selectedTreeElement
-            || !!this._callStackContentTreeOutline.selectedTreeElement
-            || (this._pauseReasonTreeOutline && !!this._pauseReasonTreeOutline.selectedTreeElement);
+        return this._navigationBar.minimumWidth;
+    }
+
+    closed()
+    {
+        super.closed();
+
+        WebInspector.Frame.removeEventListener(null, null, this);
+        WebInspector.debuggerManager.removeEventListener(null, null, this);
+        WebInspector.Breakpoint.removeEventListener(null, null, this);
+        WebInspector.IssueMessage.removeEventListener(null, null, this);
     }
 
     showDefaultContentView()
@@ -184,7 +194,7 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
         var currentTreeElement = this._contentTreeOutline.children[0];
         while (currentTreeElement && !currentTreeElement.root) {
             if (currentTreeElement instanceof WebInspector.ResourceTreeElement || currentTreeElement instanceof WebInspector.ScriptTreeElement) {
-                currentTreeElement.revealAndSelect();
+                this.showDefaultContentViewForTreeElement(currentTreeElement);
                 return;
             }
 
@@ -198,7 +208,27 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
         if (representedObject instanceof WebInspector.Frame)
             representedObject = representedObject.mainResource;
 
-        return this.contentTreeOutline.getCachedTreeElement(representedObject);
+        let treeElement = this.contentTreeOutline.findTreeElement(representedObject);
+        if (treeElement)
+            return treeElement;
+
+        // Only special case Script objects.
+        if (!(representedObject instanceof WebInspector.Script)) {
+            console.error("Didn't find a TreeElement for representedObject", representedObject);
+            return null;
+        }
+
+        // If the Script has a URL we should have found it earlier.
+        if (representedObject.url) {
+            console.error("Didn't find a ScriptTreeElement for a Script with a URL.");
+            return null;
+        }
+
+        // Since the Script does not have a URL we consider it an 'anonymous' script. These scripts happen from calls to
+        // window.eval() or browser features like Auto Fill and Reader. They are not normally added to the sidebar, but since
+        // we have a ScriptContentView asking for the tree element we will make a ScriptTreeElement on demand and add it.
+
+        return this._addScript(representedObject);
     }
 
     // Protected
@@ -213,11 +243,15 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
 
         var representedObject = selectedTreeElement.representedObject;
 
-        if (representedObject === WebInspector.debuggerManager.allExceptionsBreakpoint)
+        if (representedObject === WebInspector.debuggerManager.allExceptionsBreakpoint) {
             cookie[WebInspector.DebuggerSidebarPanel.SelectedAllExceptionsCookieKey] = true;
+            return;
+        }
 
-        if (representedObject === WebInspector.debuggerManager.allUncaughtExceptionsBreakpoint)
+        if (representedObject === WebInspector.debuggerManager.allUncaughtExceptionsBreakpoint) {
             cookie[WebInspector.DebuggerSidebarPanel.SelectedAllUncaughtExceptionsCookieKey] = true;
+            return;
+        }
 
         super.saveStateToCookie(cookie);
     }
@@ -244,9 +278,9 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
 
     _debuggerDidPause(event)
     {
-        this.contentElement.insertBefore(this._callStackSection.element, this.contentElement.firstChild);
+        this.contentView.element.insertBefore(this._callStackSection.element, this.contentView.element.firstChild);
         if (this._updatePauseReason())
-            this.contentElement.insertBefore(this._pauseReasonSection.element, this.contentElement.firstChild);
+            this.contentView.element.insertBefore(this._pauseReasonSection.element, this.contentView.element.firstChild);
 
         this._debuggerPauseResumeButtonItem.enabled = true;
         this._debuggerPauseResumeButtonItem.toggled = true;
@@ -304,6 +338,13 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
             this._addBreakpoint(breakpoints[i], sourceCode);
     }
 
+    _addIssuesForSourceCode(sourceCode)
+    {
+        var issues = WebInspector.issueManager.issuesForSourceCode(sourceCode);
+        for (var issue of issues)
+            this._addIssue(issue);
+    }
+
     _addTreeElementForSourceCodeToContentTreeOutline(sourceCode)
     {
         var treeElement = this._breakpointsContentTreeOutline.getCachedTreeElement(sourceCode);
@@ -331,44 +372,108 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
         return treeElement;
     }
 
+    _addResourcesRecursivelyForFrame(frame)
+    {
+        this._addResource(frame.mainResource);
+
+        for (var resource of frame.resources)
+            this._addResource(resource);
+
+        for (var childFrame of frame.childFrames)
+            this._addResourcesRecursivelyForFrame(childFrame);
+    }
+
     _resourceAdded(event)
     {
-        var resource = event.data.resource;
+        this._addResource(event.data.resource);
+    }
 
+    _addResource(resource)
+    {
         if (![WebInspector.Resource.Type.Document, WebInspector.Resource.Type.Script].includes(resource.type))
             return;
 
-        this._addTreeElementForSourceCodeToContentTreeOutline(resource);
+        let treeElement = this._addTreeElementForSourceCodeToContentTreeOutline(resource);
         this._addBreakpointsForSourceCode(resource);
+        this._addIssuesForSourceCode(resource);
+
+        if (!this.contentBrowser.currentContentView)
+            this.showDefaultContentViewForTreeElement(treeElement);
     }
 
-    _mainResourceChanged(event)
+    _mainResourceDidChange(event)
     {
+        if (event.target.isMainFrame()) {
+            // Aggressively prune resources now so the old resources are removed before
+            // the new main resource is added below. This avoids a visual flash when the
+            // prune normally happens on a later event loop cycle.
+            this.pruneStaleResourceTreeElements();
+            this.contentBrowser.contentViewContainer.closeAllContentViews();
+        }
+
         var resource = event.target.mainResource;
         this._addTreeElementForSourceCodeToContentTreeOutline(resource);
         this._addBreakpointsForSourceCode(resource);
+        this._addIssuesForSourceCode(resource);
     }
 
-    _scriptAdded(event)
+    _timelineRecordingWillStart(event)
     {
-        var script = event.data.script;
+        WebInspector.debuggerManager.startDisablingBreakpointsTemporarily();
 
-        // FIXME: Allow for scripts generated by eval statements to appear, but filter out JSC internals
-        // and other WebInspector internals lacking __WebInspector in the url attribute.
-        if (!script.url)
-            return;
+        if (WebInspector.debuggerManager.paused)
+            WebInspector.debuggerManager.resume();
 
-        // Exclude inspector scripts.
-        if (script.url && script.url.startsWith("__WebInspector"))
-            return;
+        this._debuggerBreakpointsButtonItem.enabled = false;
+        this._debuggerPauseResumeButtonItem.enabled = false;
+
+        this.contentView.element.insertBefore(this._timelineRecordingWarningElement, this.contentView.element.firstChild);
+    }
+
+    _timelineRecordingStopped(event)
+    {
+        WebInspector.debuggerManager.stopDisablingBreakpointsTemporarily();
+
+        this._debuggerBreakpointsButtonItem.enabled = true;
+        this._debuggerPauseResumeButtonItem.enabled = true;
+
+        this._timelineRecordingWarningElement.remove();
+    }
+
+    _scriptAdded(event)
+    {
+        this._addScript(event.data.script);
+    }
+
+    _addScript(script)
+    {
+        // COMPATIBILITY(iOS 9): Backends could send the frontend built-in code, filter out JSC internals.
+        if (!script.url && !script.sourceURL)
+            return null;
 
         // Don't add breakpoints if the script is represented by a Resource. They were
         // already added by _resourceAdded.
         if (script.resource)
-            return;
+            return null;
 
-        this._addTreeElementForSourceCodeToContentTreeOutline(script);
+        let treeElement = this._addTreeElementForSourceCodeToContentTreeOutline(script);
         this._addBreakpointsForSourceCode(script);
+        this._addIssuesForSourceCode(script);
+
+        if (!this.contentBrowser.currentContentView)
+            this.showDefaultContentViewForTreeElement(treeElement);
+
+        return treeElement;
+    }
+
+    _scriptRemoved(event)
+    {
+        let script = event.data.script;
+        let scriptTreeElement = this._breakpointsContentTreeOutline.getCachedTreeElement(script);
+        if (!scriptTreeElement)
+            return;
+
+        scriptTreeElement.parent.removeChild(scriptTreeElement);
     }
 
     _scriptsCleared(event)
@@ -536,81 +641,54 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
         if (!(treeElement instanceof WebInspector.ResourceTreeElement) && !(treeElement instanceof WebInspector.ScriptTreeElement))
             return;
 
-        var breakpoints = this._breakpointsBeneathTreeElement(treeElement);
-        var shouldDisable = false;
-        for (var i = 0; i < breakpoints.length; ++i) {
-            if (!breakpoints[i].disabled) {
-                shouldDisable = true;
-                break;
-            }
-        }
+        let breakpoints = this._breakpointsBeneathTreeElement(treeElement);
+        let shouldDisable = breakpoints.some((breakpoint) => !breakpoint.disabled);
 
-        function removeAllResourceBreakpoints()
-        {
+        let removeAllResourceBreakpoints = () => {
             this._removeAllBreakpoints(breakpoints);
-        }
+        };
 
-        function toggleAllResourceBreakpoints()
-        {
+        let toggleAllResourceBreakpoints = () => {
             this._toggleAllBreakpoints(breakpoints, shouldDisable);
-        }
+        };
 
-        var contextMenu = new WebInspector.ContextMenu(event);
+        let contextMenu = WebInspector.ContextMenu.createFromEvent(event);
         if (shouldDisable)
-            contextMenu.appendItem(WebInspector.UIString("Disable Breakpoints"), toggleAllResourceBreakpoints.bind(this));
+            contextMenu.appendItem(WebInspector.UIString("Disable Breakpoints"), toggleAllResourceBreakpoints);
         else
-            contextMenu.appendItem(WebInspector.UIString("Enable Breakpoints"), toggleAllResourceBreakpoints.bind(this));
-        contextMenu.appendItem(WebInspector.UIString("Delete Breakpoints"), removeAllResourceBreakpoints.bind(this));
-        contextMenu.show();
+            contextMenu.appendItem(WebInspector.UIString("Enable Breakpoints"), toggleAllResourceBreakpoints);
+        contextMenu.appendItem(WebInspector.UIString("Delete Breakpoints"), removeAllResourceBreakpoints);
     }
 
-    _treeElementSelected(treeElement, selectedByUser)
+    _treeSelectionDidChange(event)
     {
-        function deselectCallStackContentTreeElements()
-        {
-            var selectedTreeElement = this._callStackContentTreeOutline.selectedTreeElement;
-            if (selectedTreeElement)
-                selectedTreeElement.deselect();
-        }
-
-        function deselectBreakpointContentTreeElements()
-        {
-            var selectedTreeElement = this._breakpointsContentTreeOutline.selectedTreeElement;
-            if (selectedTreeElement)
-                selectedTreeElement.deselect();
-        }
+        let treeElement = event.data.selectedElement;
+        if (!treeElement)
+            return;
 
-        function deselectPauseReasonContentTreeElements()
-        {
-            if (!this._pauseReasonTreeOutline)
-                return;
+        // Deselect any other tree elements to prevent two selections in the sidebar.
+        for (let treeOutline of this.visibleContentTreeOutlines) {
+            if (treeOutline === treeElement.treeOutline)
+                continue;
 
-            var selectedTreeElement = this._pauseReasonTreeOutline.selectedTreeElement;
+            let selectedTreeElement = treeOutline.selectedTreeElement;
             if (selectedTreeElement)
                 selectedTreeElement.deselect();
         }
 
         if (treeElement instanceof WebInspector.ResourceTreeElement || treeElement instanceof WebInspector.ScriptTreeElement) {
-            deselectCallStackContentTreeElements.call(this);
-            deselectPauseReasonContentTreeElements.call(this);
             WebInspector.showSourceCode(treeElement.representedObject);
             return;
         }
 
         if (treeElement instanceof WebInspector.CallFrameTreeElement) {
-            // Deselect any tree element in the breakpoint / pause reason content tree outlines to prevent two selections in the sidebar.
-            deselectBreakpointContentTreeElements.call(this);
-            deselectPauseReasonContentTreeElements.call(this);
-
-            var callFrame = treeElement.callFrame;
+            let callFrame = treeElement.callFrame;
             WebInspector.debuggerManager.activeCallFrame = callFrame;
             WebInspector.showSourceCodeLocation(callFrame.sourceCodeLocation);
             return;
         }
 
         if (treeElement instanceof WebInspector.IssueTreeElement) {
-            deselectCallStackContentTreeElements.call(this);
-            deselectPauseReasonContentTreeElements.call(this);
             WebInspector.showSourceCodeLocation(treeElement.issueMessage.sourceCodeLocation);
             return;
         }
@@ -618,15 +696,7 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
         if (!(treeElement instanceof WebInspector.BreakpointTreeElement) || treeElement.parent.constructor === WebInspector.FolderTreeElement)
             return;
 
-        // Deselect any other tree elements to prevent two selections in the sidebar.
-        deselectCallStackContentTreeElements.call(this);
-
-        if (treeElement.treeOutline === this._pauseReasonTreeOutline)
-            deselectBreakpointContentTreeElements.call(this);
-        else
-            deselectPauseReasonContentTreeElements.call(this);
-
-        var breakpoint = treeElement.breakpoint;
+        let breakpoint = treeElement.breakpoint;
         if (treeElement.treeOutline === this._pauseReasonTreeOutline) {
             WebInspector.showSourceCodeLocation(breakpoint.sourceCodeLocation);
             return;
@@ -695,16 +765,16 @@ WebInspector.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WebInspec
         case WebInspector.DebuggerManager.PauseReason.Breakpoint:
             console.assert(pauseData, "Expected breakpoint identifier, but found none.");
             if (pauseData && pauseData.breakpointId) {
-                var breakpoint = WebInspector.debuggerManager.breakpointForIdentifier(pauseData.breakpointId);
-                var breakpointTreeOutline = this.createContentTreeOutline(true, true);
-                breakpointTreeOutline.onselect = this._treeElementSelected.bind(this);
-                var breakpointTreeElement = new WebInspector.BreakpointTreeElement(breakpoint, WebInspector.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName, WebInspector.UIString("Triggered Breakpoint"));
-                var breakpointDetailsSection = new WebInspector.DetailsSectionRow;
-                breakpointTreeOutline.appendChild(breakpointTreeElement);
-                breakpointDetailsSection.element.appendChild(breakpointTreeOutline.element);
+                let breakpoint = WebInspector.debuggerManager.breakpointForIdentifier(pauseData.breakpointId);
+                this._pauseReasonTreeOutline = this.createContentTreeOutline(true, true);
+                this._pauseReasonTreeOutline.addEventListener(WebInspector.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
+
+                let breakpointTreeElement = new WebInspector.BreakpointTreeElement(breakpoint, WebInspector.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName, WebInspector.UIString("Triggered Breakpoint"));
+                let breakpointDetailsSection = new WebInspector.DetailsSectionRow;
+                this._pauseReasonTreeOutline.appendChild(breakpointTreeElement);
+                breakpointDetailsSection.element.appendChild(this._pauseReasonTreeOutline.element);
 
                 this._pauseReasonGroup.rows = [breakpointDetailsSection];
-                this._pauseReasonTreeOutline = breakpointTreeOutline;
                 return true;
             }
             break;