<!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>[208895] 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/208895">208895</a></dd>
<dt>Author</dt> <dd>mattbaker@apple.com</dd>
<dt>Date</dt> <dd>2016-11-18 14:04:08 -0800 (Fri, 18 Nov 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: TimelineDataGridNode assertions when refreshing page
https://bugs.webkit.org/show_bug.cgi?id=162642
&lt;rdar://problem/28505898&gt;

Reviewed by Timothy Hatcher.

This patch fixes a number of deficiencies in the Network tab that caused
TimelineDataGridNode graphs to refresh before the tab became visible.

* UserInterface/Views/ElementsTabContentView.js:
(WebInspector.ElementsTabContentView):
(WebInspector.ElementsTabContentView.prototype.shown):
Drive-by fix: defer showing the DOM content view until the tab is shown.

* UserInterface/Views/NetworkGridContentView.js:
(WebInspector.NetworkGridContentView):
Drive-by event listener cleanup.
(WebInspector.NetworkGridContentView.prototype.get startTime):
(WebInspector.NetworkGridContentView.prototype.get endTime):
Back endTime with a variable, instead of using the ruler value which
isn't valid before the tab is shown for the first time.

(WebInspector.NetworkGridContentView.prototype.shown):
Force the grid to update its layout, and that of the Timeline column ruler.
During layout the ruler's secondsPerPixel value is used, which isn't
valid until the ruler does an initial layout.

(WebInspector.NetworkGridContentView.prototype.reset):
Clear pending records. This was causing duplicates to appear when the
inspected page was refreshed multiple times prior to showing the Network
tab for the first time.

(WebInspector.NetworkGridContentView.prototype.layout):
Should more closely match behavior in NetworkTimelineView.prototype.layout.
Graph end time padding is added if no longer updating the current time.

(WebInspector.NetworkGridContentView.prototype._networkTimelineRecordAdded):
Track endTime of the last record added, so that the graph end time can
be padded once the current time is no longer being updated.

(WebInspector.NetworkGridContentView.prototype._update):
(WebInspector.NetworkGridContentView.prototype._stopUpdatingCurrentTime):
Graph end time padding shouldn't be applied here, since this isn't called
if the inspected page finishes loading before the view is shown.

(WebInspector.NetworkGridContentView.prototype._clearNetworkItems): Deleted.
Replaced by an arrow function.

* UserInterface/Views/NetworkSidebarPanel.js:
(WebInspector.NetworkSidebarPanel.prototype._networkTimelineReset):
Don't show the content view if the tab is hidden.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsElementsTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/ElementsTabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsNetworkGridContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/NetworkGridContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsNetworkSidebarPaneljs">trunk/Source/WebInspectorUI/UserInterface/Views/NetworkSidebarPanel.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (208894 => 208895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-11-18 21:55:09 UTC (rev 208894)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-11-18 22:04:08 UTC (rev 208895)
</span><span class="lines">@@ -1,3 +1,57 @@
</span><ins>+2016-11-18  Matt Baker  &lt;mattbaker@apple.com&gt;
+
+        Web Inspector: TimelineDataGridNode assertions when refreshing page
+        https://bugs.webkit.org/show_bug.cgi?id=162642
+        &lt;rdar://problem/28505898&gt;
+
+        Reviewed by Timothy Hatcher.
+
+        This patch fixes a number of deficiencies in the Network tab that caused
+        TimelineDataGridNode graphs to refresh before the tab became visible.
+
+        * UserInterface/Views/ElementsTabContentView.js:
+        (WebInspector.ElementsTabContentView):
+        (WebInspector.ElementsTabContentView.prototype.shown):
+        Drive-by fix: defer showing the DOM content view until the tab is shown.
+
+        * UserInterface/Views/NetworkGridContentView.js:
+        (WebInspector.NetworkGridContentView):
+        Drive-by event listener cleanup.
+        (WebInspector.NetworkGridContentView.prototype.get startTime):
+        (WebInspector.NetworkGridContentView.prototype.get endTime):
+        Back endTime with a variable, instead of using the ruler value which
+        isn't valid before the tab is shown for the first time.
+
+        (WebInspector.NetworkGridContentView.prototype.shown):
+        Force the grid to update its layout, and that of the Timeline column ruler.
+        During layout the ruler's secondsPerPixel value is used, which isn't
+        valid until the ruler does an initial layout.
+
+        (WebInspector.NetworkGridContentView.prototype.reset):
+        Clear pending records. This was causing duplicates to appear when the
+        inspected page was refreshed multiple times prior to showing the Network
+        tab for the first time.
+
+        (WebInspector.NetworkGridContentView.prototype.layout):
+        Should more closely match behavior in NetworkTimelineView.prototype.layout.
+        Graph end time padding is added if no longer updating the current time.
+
+        (WebInspector.NetworkGridContentView.prototype._networkTimelineRecordAdded):
+        Track endTime of the last record added, so that the graph end time can
+        be padded once the current time is no longer being updated.
+
+        (WebInspector.NetworkGridContentView.prototype._update):
+        (WebInspector.NetworkGridContentView.prototype._stopUpdatingCurrentTime):
+        Graph end time padding shouldn't be applied here, since this isn't called
+        if the inspected page finishes loading before the view is shown.
+
+        (WebInspector.NetworkGridContentView.prototype._clearNetworkItems): Deleted.
+        Replaced by an arrow function.
+
+        * UserInterface/Views/NetworkSidebarPanel.js:
+        (WebInspector.NetworkSidebarPanel.prototype._networkTimelineReset):
+        Don't show the content view if the tab is hidden.
+
</ins><span class="cx"> 2016-11-17  Devin Rousso  &lt;dcrousso+webkit@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Shift clicking on named color value only shows its hex form
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsElementsTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ElementsTabContentView.js (208894 => 208895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ElementsTabContentView.js        2016-11-18 21:55:09 UTC (rev 208894)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ElementsTabContentView.js        2016-11-18 22:04:08 UTC (rev 208895)
</span><span class="lines">@@ -38,8 +38,6 @@
</span><span class="cx"> 
</span><span class="cx">         WebInspector.frameResourceManager.addEventListener(WebInspector.FrameResourceManager.Event.MainFrameDidChange, this._mainFrameDidChange, this);
</span><span class="cx">         WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
</span><del>-
-        this._showDOMTreeContentView();
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static tabInfo()
</span><span class="lines">@@ -86,6 +84,13 @@
</span><span class="cx">         cookie.nodeToSelect = undefined;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    shown()
+    {
+        super.shown();
+
+        this._showDOMTreeContentView();
+    }
+
</ins><span class="cx">     closed()
</span><span class="cx">     {
</span><span class="cx">         super.closed();
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsNetworkGridContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkGridContentView.js (208894 => 208895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkGridContentView.js        2016-11-18 21:55:09 UTC (rev 208894)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkGridContentView.js        2016-11-18 22:04:08 UTC (rev 208895)
</span><span class="lines">@@ -102,10 +102,11 @@
</span><span class="cx">         networkTimeline.addEventListener(WebInspector.Timeline.Event.Reset, this._networkTimelineReset, this);
</span><span class="cx"> 
</span><span class="cx">         this._clearNetworkItemsNavigationItem = new WebInspector.ButtonNavigationItem(&quot;clear-network-items&quot;, WebInspector.UIString(&quot;Clear Network Items&quot;), &quot;Images/NavigationItemTrash.svg&quot;, 15, 15);
</span><del>-        this._clearNetworkItemsNavigationItem.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, this._clearNetworkItems, this);
</del><ins>+        this._clearNetworkItemsNavigationItem.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, () =&gt; this.reset());
</ins><span class="cx"> 
</span><span class="cx">         this._pendingRecords = [];
</span><span class="cx">         this._loadingResourceCount = 0;
</span><ins>+        this._lastRecordEndTime = NaN;
</ins><span class="cx">         this._lastUpdateTimestamp = NaN;
</span><span class="cx">         this._startTime = NaN;
</span><span class="cx">         this._endTime = NaN;
</span><span class="lines">@@ -115,9 +116,9 @@
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     get secondsPerPixel() { return this._timelineRuler.secondsPerPixel; }
</span><del>-    get startTime() { return this._startTime || 0; }
</del><ins>+    get startTime() { return this._startTime; }
</ins><span class="cx">     get currentTime() { return this.endTime || this.startTime; }
</span><del>-    get endTime() { return this._timelineRuler.endTime; }
</del><ins>+    get endTime() { return this._endTime; }
</ins><span class="cx">     get zeroTime() { return this.startTime; }
</span><span class="cx"> 
</span><span class="cx">     get selectionPathComponents()
</span><span class="lines">@@ -141,6 +142,8 @@
</span><span class="cx"> 
</span><span class="cx">         this._dataGrid.shown();
</span><span class="cx"> 
</span><ins>+        this._dataGrid.updateLayout(WebInspector.View.LayoutReason.Resize);
+
</ins><span class="cx">         if (this._loadingResourceCount &amp;&amp; !this._scheduledCurrentTimeUpdateIdentifier)
</span><span class="cx">             this._startUpdatingCurrentTime();
</span><span class="cx">     }
</span><span class="lines">@@ -170,7 +173,9 @@
</span><span class="cx">         if (this._scheduledCurrentTimeUpdateIdentifier)
</span><span class="cx">             this._stopUpdatingCurrentTime();
</span><span class="cx"> 
</span><ins>+        this._pendingRecords = [];
</ins><span class="cx">         this._loadingResourceCount = 0;
</span><ins>+        this._lastRecordEndTime = NaN;
</ins><span class="cx">         this._lastUpdateTimestamp = NaN;
</span><span class="cx">         this._startTime = NaN;
</span><span class="cx">         this._endTime = NaN;
</span><span class="lines">@@ -183,17 +188,32 @@
</span><span class="cx"> 
</span><span class="cx">     layout()
</span><span class="cx">     {
</span><del>-        if (!isNaN(this._startTime)) {
-            this._timelineRuler.zeroTime = this._startTime;
-            this._timelineRuler.startTime = this._startTime;
-        }
</del><ins>+        if (isNaN(this.startTime) || isNaN(this.endTime))
+            return;
</ins><span class="cx"> 
</span><ins>+        let oldZeroTime = this._timelineRuler.zeroTime;
+        let oldStartTime = this._timelineRuler.startTime;
+        let oldEndTime = this._timelineRuler.endTime;
+
+        this._timelineRuler.zeroTime = this.zeroTime;
+        this._timelineRuler.startTime = this.startTime;
+
</ins><span class="cx">         if (this.startTime &gt;= this.endTime)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        for (let dataGridNode of this._dataGrid.children)
-            dataGridNode.refreshGraph();
</del><ins>+        if (!this._scheduledCurrentTimeUpdateIdentifier) {
+            this._timelineRuler.endTime = this.endTime;
+            this._endTime = this._lastRecordEndTime + WebInspector.TimelineRecordBar.MinimumWidthPixels * this.secondsPerPixel;
+        }
</ins><span class="cx"> 
</span><ins>+        this._timelineRuler.endTime = this.endTime;
+
+        // We only need to refresh the graphs when the any of the times change.
+        if (this.zeroTime !== oldZeroTime || this.startTime !== oldStartTime || this.endTime !== oldEndTime) {
+            for (let dataGridNode of this._dataGrid.children)
+                dataGridNode.refreshGraph();
+        }
+
</ins><span class="cx">         this._processPendingRecords();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -243,7 +263,8 @@
</span><span class="cx">             if (this._loadingResourceCount)
</span><span class="cx">                 return;
</span><span class="cx"> 
</span><del>-            this._endTime = resourceTimelineRecord.endTime;
</del><ins>+            this._lastRecordEndTime = resourceTimelineRecord.endTime;
+            this._endTime = Math.max(this._lastRecordEndTime, this._endTime);
</ins><span class="cx"> 
</span><span class="cx">             if (this._scheduledCurrentTimeUpdateIdentifier)
</span><span class="cx">                 this.debounce(150)._stopUpdatingCurrentTime();
</span><span class="lines">@@ -266,7 +287,7 @@
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         if (isNaN(this._startTime))
</span><del>-            this._startTime = resourceTimelineRecord.startTime;
</del><ins>+            this._startTime = this._endTime = resourceTimelineRecord.startTime;
</ins><span class="cx"> 
</span><span class="cx">         // FIXME: &lt;https://webkit.org/b/153634&gt; Web Inspector: some background tabs think they are the foreground tab and do unnecessary work
</span><span class="cx">         if (!(WebInspector.tabBrowser.selectedTabContentView instanceof WebInspector.NetworkTabContentView))
</span><span class="lines">@@ -304,10 +325,6 @@
</span><span class="cx">         this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    _clearNetworkItems(event) {
-        this.reset();
-    }
-
</del><span class="cx">     _update(timestamp)
</span><span class="cx">     {
</span><span class="cx">         console.assert(this._scheduledCurrentTimeUpdateIdentifier);
</span><span class="lines">@@ -314,7 +331,7 @@
</span><span class="cx"> 
</span><span class="cx">         if (!isNaN(this._lastUpdateTimestamp)) {
</span><span class="cx">             let timespanSinceLastUpdate = (timestamp - this._lastUpdateTimestamp) / 1000 || 0;
</span><del>-            this._timelineRuler.endTime = this.currentTime + timespanSinceLastUpdate;
</del><ins>+            this._endTime += timespanSinceLastUpdate;
</ins><span class="cx"> 
</span><span class="cx">             this.updateLayout();
</span><span class="cx">         }
</span><span class="lines">@@ -350,7 +367,6 @@
</span><span class="cx">         cancelAnimationFrame(this._scheduledCurrentTimeUpdateIdentifier);
</span><span class="cx">         this._scheduledCurrentTimeUpdateIdentifier = undefined;
</span><span class="cx"> 
</span><del>-        this._timelineRuler.endTime = this._endTime + WebInspector.TimelineRecordBar.MinimumWidthPixels * this.secondsPerPixel;
</del><span class="cx">         this.needsLayout();
</span><span class="cx">     }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsNetworkSidebarPaneljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkSidebarPanel.js (208894 => 208895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkSidebarPanel.js        2016-11-18 21:55:09 UTC (rev 208894)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkSidebarPanel.js        2016-11-18 22:04:08 UTC (rev 208895)
</span><span class="lines">@@ -174,7 +174,9 @@
</span><span class="cx">     _networkTimelineReset(event)
</span><span class="cx">     {
</span><span class="cx">         this.contentBrowser.contentViewContainer.closeAllContentViews();
</span><del>-        this.showDefaultContentView();
</del><ins>+
+        if (this.visible)
+            this.showDefaultContentView();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _contentBrowserCurrentContentViewDidChange(event)
</span></span></pre>
</div>
</div>

</body>
</html>