<!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>[243213] 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/243213">243213</a></dd>
<dt>Author</dt> <dd>drousso@apple.com</dd>
<dt>Date</dt> <dd>2019-03-20 10:43:05 -0700 (Wed, 20 Mar 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: refactor WI.TimelineDataGridNode and its subclasses to unify the API surface
https://bugs.webkit.org/show_bug.cgi?id=195959
<rdar://problem/49028896>

Reviewed by Timothy Hatcher.

* UserInterface/Views/TimelineDataGridNode.js:
(WI.TimelineDataGridNode.prototype.get records):
(WI.TimelineDataGridNode.prototype.get data):
(WI.TimelineDataGridNode.prototype.refresh):

* UserInterface/Views/HeapAllocationsTimelineDataGridNode.js:
(WI.HeapAllocationsTimelineDataGridNode):
(WI.HeapAllocationsTimelineDataGridNode.prototype.get heapSnapshot): Added.
(WI.HeapAllocationsTimelineDataGridNode.prototype.get data):
(WI.HeapAllocationsTimelineDataGridNode.prototype.createCellContent):
(WI.HeapAllocationsTimelineDataGridNode.prototype.createCells):
(WI.HeapAllocationsTimelineDataGridNode.prototype._handleHeapSnapshotCollectedNodes):
(WI.HeapAllocationsTimelineDataGridNode.prototype._handleHeapSnapshotInvalidated):
(WI.HeapAllocationsTimelineDataGridNode.prototype.get record): Deleted.
(WI.HeapAllocationsTimelineDataGridNode.prototype.updateTimestamp): Deleted.
(WI.HeapAllocationsTimelineDataGridNode.prototype._heapSnapshotCollectedNodes): Deleted.
(WI.HeapAllocationsTimelineDataGridNode.prototype._heapSnapshotInvalidated): Deleted.

* UserInterface/Views/LayoutTimelineDataGridNode.js:
(WI.LayoutTimelineDataGridNode):
(WI.LayoutTimelineDataGridNode.prototype.get data):
(WI.LayoutTimelineDataGridNode.prototype.createCellContent):
(WI.LayoutTimelineDataGridNode.prototype.get records): Deleted.

* UserInterface/Views/MediaTimelineDataGridNode.js:
(WI.MediaTimelineDataGridNode):
(WI.MediaTimelineDataGridNode.prototype.get records): Deleted.

* UserInterface/Views/ProfileNodeDataGridNode.js:
(WI.ProfileNodeDataGridNode):
(WI.ProfileNodeDataGridNode.prototype.get profileNode):
(WI.ProfileNodeDataGridNode.prototype.get data):
(WI.ProfileNodeDataGridNode.prototype.createCellContent):
(WI.ProfileNodeDataGridNode.prototype._populate):
(WI.ProfileNodeDataGridNode.prototype.get records): Deleted.
(WI.ProfileNodeDataGridNode.prototype.get baseStartTime): Deleted.
(WI.ProfileNodeDataGridNode.prototype.get rangeStartTime): Deleted.
(WI.ProfileNodeDataGridNode.prototype.get rangeEndTime): Deleted.
(WI.ProfileNodeDataGridNode.prototype.updateRangeTimes): Deleted.
(WI.ProfileNodeDataGridNode.prototype.refresh): Deleted.

* UserInterface/Views/RenderingFrameTimelineDataGridNode.js:
(WI.RenderingFrameTimelineDataGridNode):
(WI.RenderingFrameTimelineDataGridNode.prototype.get data):
(WI.RenderingFrameTimelineDataGridNode.prototype.createCellContent):
(WI.RenderingFrameTimelineDataGridNode.prototype.get records): Deleted.

* UserInterface/Views/ResourceTimelineDataGridNode.js:
(WI.ResourceTimelineDataGridNode):
(WI.ResourceTimelineDataGridNode.prototype.get resource):
(WI.ResourceTimelineDataGridNode.prototype.get data):
(WI.ResourceTimelineDataGridNode.prototype.createCellContent):
(WI.ResourceTimelineDataGridNode.prototype.appendContextMenuItems):
(WI.ResourceTimelineDataGridNode.prototype.filterableDataForColumn):
(WI.ResourceTimelineDataGridNode.prototype._createNameCellDocumentFragment):
(WI.ResourceTimelineDataGridNode.prototype._cachedCellContent):
(WI.ResourceTimelineDataGridNode.prototype._timelineRecordUpdated):
(WI.ResourceTimelineDataGridNode.prototype._dataGridNodeGoToArrowClicked):
(WI.ResourceTimelineDataGridNode.prototype._updateStatus):
(WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar.else.let.graphDataSource.get startTime):
(WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar.else.let.graphDataSource.get currentTime):
(WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar.else.let.graphDataSource.get endTime):
(WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar.else.let.graphDataSource.get _extraTimePadding):
(WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar):
(WI.ResourceTimelineDataGridNode.prototype.get records): Deleted.

* UserInterface/Views/ResourceTimingPopoverDataGridNode.js:
(WI.ResourceTimingPopoverDataGridNode):
(WI.ResourceTimingPopoverDataGridNode.prototype.get records): Deleted.

* UserInterface/Views/ScriptTimelineDataGridNode.js:
(WI.ScriptTimelineDataGridNode.prototype.get data):
(WI.ScriptTimelineDataGridNode.prototype.get subtitle):
(WI.ScriptTimelineDataGridNode.prototype.createCellContent):
(WI.ScriptTimelineDataGridNode.prototype.get records): Deleted.
(WI.ScriptTimelineDataGridNode.prototype.get baseStartTime): Deleted.
(WI.ScriptTimelineDataGridNode.prototype.get rangeStartTime): Deleted.
(WI.ScriptTimelineDataGridNode.prototype.get rangeEndTime): Deleted.
(WI.ScriptTimelineDataGridNode.prototype.updateRangeTimes): Deleted.

* UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js:
(WI.SourceCodeTimelineTimelineDataGridNode.prototype.get data):

* UserInterface/Views/HeapAllocationsTimelineView.js:
(WI.HeapAllocationsTimelineView):
(WI.HeapAllocationsTimelineView.prototype.layout):
(WI.HeapAllocationsTimelineView.prototype.reset):
* UserInterface/Views/LayoutTimelineView.js:
(WI.LayoutTimelineView.prototype._processPendingRecords):
* UserInterface/Views/MediaTimelineView.js:
(WI.MediaTimelineView.prototype._processPendingRecords):
* UserInterface/Views/NetworkTimelineView.js:
(WI.NetworkTimelineView.prototype._processPendingRecords):
* UserInterface/Views/OverviewTimelineView.js:
(WI.OverviewTimelineView.prototype._addResourceToDataGridIfNeeded):
(WI.OverviewTimelineView.prototype._addSourceCodeTimeline):
* UserInterface/Views/RenderingFrameTimelineView.js:
(WI.RenderingFrameTimelineView.prototype._processPendingRecords):
* UserInterface/Views/ScriptDetailsTimelineView.js:
(WI.ScriptDetailsTimelineView.prototype.layout):
(WI.ScriptDetailsTimelineView.prototype._processPendingRecords):
Update Timeline `WI.DataGrid` views to use the new constructor format.

* UserInterface/Views/ResourceTimelineDataGridNode.css:
(.resource-timing-popover-content .data-grid td.graph-column):
Drive-by: add extra padding before/after resource timing bars shown when hovering.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsHeapAllocationsTimelineDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineDataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsHeapAllocationsTimelineViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsLayoutTimelineDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsLayoutTimelineViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsMediaTimelineDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/MediaTimelineDataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsMediaTimelineViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/MediaTimelineView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsNetworkTimelineViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsOverviewTimelineViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsProfileNodeDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/ProfileNodeDataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsRenderingFrameTimelineDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineDataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsRenderingFrameTimelineViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsResourceTimelineDataGridNodecss">trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsResourceTimelineDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsResourceTimingPopoverDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimingPopoverDataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsScriptDetailsTimelineViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/ScriptDetailsTimelineView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsScriptTimelineDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSourceCodeTimelineTimelineDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTimelineDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/TimelineDataGridNode.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog    2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/ChangeLog       2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -1,5 +1,120 @@
</span><span class="cx"> 2019-03-20  Devin Rousso  <drousso@apple.com>
</span><span class="cx"> 
</span><ins>+        Web Inspector: refactor WI.TimelineDataGridNode and its subclasses to unify the API surface
+        https://bugs.webkit.org/show_bug.cgi?id=195959
+        <rdar://problem/49028896>
+
+        Reviewed by Timothy Hatcher.
+
+        * UserInterface/Views/TimelineDataGridNode.js:
+        (WI.TimelineDataGridNode.prototype.get records):
+        (WI.TimelineDataGridNode.prototype.get data):
+        (WI.TimelineDataGridNode.prototype.refresh):
+
+        * UserInterface/Views/HeapAllocationsTimelineDataGridNode.js:
+        (WI.HeapAllocationsTimelineDataGridNode):
+        (WI.HeapAllocationsTimelineDataGridNode.prototype.get heapSnapshot): Added.
+        (WI.HeapAllocationsTimelineDataGridNode.prototype.get data):
+        (WI.HeapAllocationsTimelineDataGridNode.prototype.createCellContent):
+        (WI.HeapAllocationsTimelineDataGridNode.prototype.createCells):
+        (WI.HeapAllocationsTimelineDataGridNode.prototype._handleHeapSnapshotCollectedNodes):
+        (WI.HeapAllocationsTimelineDataGridNode.prototype._handleHeapSnapshotInvalidated):
+        (WI.HeapAllocationsTimelineDataGridNode.prototype.get record): Deleted.
+        (WI.HeapAllocationsTimelineDataGridNode.prototype.updateTimestamp): Deleted.
+        (WI.HeapAllocationsTimelineDataGridNode.prototype._heapSnapshotCollectedNodes): Deleted.
+        (WI.HeapAllocationsTimelineDataGridNode.prototype._heapSnapshotInvalidated): Deleted.
+
+        * UserInterface/Views/LayoutTimelineDataGridNode.js:
+        (WI.LayoutTimelineDataGridNode):
+        (WI.LayoutTimelineDataGridNode.prototype.get data):
+        (WI.LayoutTimelineDataGridNode.prototype.createCellContent):
+        (WI.LayoutTimelineDataGridNode.prototype.get records): Deleted.
+
+        * UserInterface/Views/MediaTimelineDataGridNode.js:
+        (WI.MediaTimelineDataGridNode):
+        (WI.MediaTimelineDataGridNode.prototype.get records): Deleted.
+
+        * UserInterface/Views/ProfileNodeDataGridNode.js:
+        (WI.ProfileNodeDataGridNode):
+        (WI.ProfileNodeDataGridNode.prototype.get profileNode):
+        (WI.ProfileNodeDataGridNode.prototype.get data):
+        (WI.ProfileNodeDataGridNode.prototype.createCellContent):
+        (WI.ProfileNodeDataGridNode.prototype._populate):
+        (WI.ProfileNodeDataGridNode.prototype.get records): Deleted.
+        (WI.ProfileNodeDataGridNode.prototype.get baseStartTime): Deleted.
+        (WI.ProfileNodeDataGridNode.prototype.get rangeStartTime): Deleted.
+        (WI.ProfileNodeDataGridNode.prototype.get rangeEndTime): Deleted.
+        (WI.ProfileNodeDataGridNode.prototype.updateRangeTimes): Deleted.
+        (WI.ProfileNodeDataGridNode.prototype.refresh): Deleted.
+
+        * UserInterface/Views/RenderingFrameTimelineDataGridNode.js:
+        (WI.RenderingFrameTimelineDataGridNode):
+        (WI.RenderingFrameTimelineDataGridNode.prototype.get data):
+        (WI.RenderingFrameTimelineDataGridNode.prototype.createCellContent):
+        (WI.RenderingFrameTimelineDataGridNode.prototype.get records): Deleted.
+
+        * UserInterface/Views/ResourceTimelineDataGridNode.js:
+        (WI.ResourceTimelineDataGridNode):
+        (WI.ResourceTimelineDataGridNode.prototype.get resource):
+        (WI.ResourceTimelineDataGridNode.prototype.get data):
+        (WI.ResourceTimelineDataGridNode.prototype.createCellContent):
+        (WI.ResourceTimelineDataGridNode.prototype.appendContextMenuItems):
+        (WI.ResourceTimelineDataGridNode.prototype.filterableDataForColumn):
+        (WI.ResourceTimelineDataGridNode.prototype._createNameCellDocumentFragment):
+        (WI.ResourceTimelineDataGridNode.prototype._cachedCellContent):
+        (WI.ResourceTimelineDataGridNode.prototype._timelineRecordUpdated):
+        (WI.ResourceTimelineDataGridNode.prototype._dataGridNodeGoToArrowClicked):
+        (WI.ResourceTimelineDataGridNode.prototype._updateStatus):
+        (WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar.else.let.graphDataSource.get startTime):
+        (WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar.else.let.graphDataSource.get currentTime):
+        (WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar.else.let.graphDataSource.get endTime):
+        (WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar.else.let.graphDataSource.get _extraTimePadding):
+        (WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar):
+        (WI.ResourceTimelineDataGridNode.prototype.get records): Deleted.
+
+        * UserInterface/Views/ResourceTimingPopoverDataGridNode.js:
+        (WI.ResourceTimingPopoverDataGridNode):
+        (WI.ResourceTimingPopoverDataGridNode.prototype.get records): Deleted.
+
+        * UserInterface/Views/ScriptTimelineDataGridNode.js:
+        (WI.ScriptTimelineDataGridNode.prototype.get data):
+        (WI.ScriptTimelineDataGridNode.prototype.get subtitle):
+        (WI.ScriptTimelineDataGridNode.prototype.createCellContent):
+        (WI.ScriptTimelineDataGridNode.prototype.get records): Deleted.
+        (WI.ScriptTimelineDataGridNode.prototype.get baseStartTime): Deleted.
+        (WI.ScriptTimelineDataGridNode.prototype.get rangeStartTime): Deleted.
+        (WI.ScriptTimelineDataGridNode.prototype.get rangeEndTime): Deleted.
+        (WI.ScriptTimelineDataGridNode.prototype.updateRangeTimes): Deleted.
+
+        * UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js:
+        (WI.SourceCodeTimelineTimelineDataGridNode.prototype.get data):
+
+        * UserInterface/Views/HeapAllocationsTimelineView.js:
+        (WI.HeapAllocationsTimelineView):
+        (WI.HeapAllocationsTimelineView.prototype.layout):
+        (WI.HeapAllocationsTimelineView.prototype.reset):
+        * UserInterface/Views/LayoutTimelineView.js:
+        (WI.LayoutTimelineView.prototype._processPendingRecords):
+        * UserInterface/Views/MediaTimelineView.js:
+        (WI.MediaTimelineView.prototype._processPendingRecords):
+        * UserInterface/Views/NetworkTimelineView.js:
+        (WI.NetworkTimelineView.prototype._processPendingRecords):
+        * UserInterface/Views/OverviewTimelineView.js:
+        (WI.OverviewTimelineView.prototype._addResourceToDataGridIfNeeded):
+        (WI.OverviewTimelineView.prototype._addSourceCodeTimeline):
+        * UserInterface/Views/RenderingFrameTimelineView.js:
+        (WI.RenderingFrameTimelineView.prototype._processPendingRecords):
+        * UserInterface/Views/ScriptDetailsTimelineView.js:
+        (WI.ScriptDetailsTimelineView.prototype.layout):
+        (WI.ScriptDetailsTimelineView.prototype._processPendingRecords):
+        Update Timeline `WI.DataGrid` views to use the new constructor format.
+
+        * UserInterface/Views/ResourceTimelineDataGridNode.css:
+        (.resource-timing-popover-content .data-grid td.graph-column):
+        Drive-by: add extra padding before/after resource timing bars shown when hovering.
+
+2019-03-20  Devin Rousso  <drousso@apple.com>
+
</ins><span class="cx">         Web Inspector: changes to CSS resources only take affect once editing stops
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=195774
</span><span class="cx">         <rdar://problem/48905413>
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsHeapAllocationsTimelineDataGridNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineDataGridNode.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineDataGridNode.js   2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineDataGridNode.js      2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -25,31 +25,44 @@
</span><span class="cx"> 
</span><span class="cx"> WI.HeapAllocationsTimelineDataGridNode = class HeapAllocationsTimelineDataGridNode extends WI.TimelineDataGridNode
</span><span class="cx"> {
</span><del>-    constructor(heapAllocationsTimelineRecord, zeroTime, heapAllocationsView)
</del><ins>+    constructor(record, options = {})
</ins><span class="cx">     {
</span><del>-        super(false, null);
</del><ins>+        console.assert(record instanceof WI.HeapAllocationsTimelineRecord);
</ins><span class="cx"> 
</span><del>-        this._record = heapAllocationsTimelineRecord;
-        this._heapAllocationsView = heapAllocationsView;
</del><ins>+        super([record], options);
</ins><span class="cx"> 
</span><del>-        this._data = {
-            name: this.displayName(),
-            timestamp: zeroTime ? this._record.timestamp - zeroTime : NaN,
-            size: this._record.heapSnapshot.totalSize,
-            liveSize: this._record.heapSnapshot.liveSize,
-        };
</del><ins>+        this._heapAllocationsView = options.heapAllocationsView;
</ins><span class="cx"> 
</span><del>-        this._record.heapSnapshot.addEventListener(WI.HeapSnapshotProxy.Event.CollectedNodes, this._heapSnapshotCollectedNodes, this);
-        this._record.heapSnapshot.addEventListener(WI.HeapSnapshotProxy.Event.Invalidated, this._heapSnapshotInvalidated, this);
</del><ins>+        this.heapSnapshot.addEventListener(WI.HeapSnapshotProxy.Event.CollectedNodes, this._handleHeapSnapshotCollectedNodes, this);
+        this.heapSnapshot.addEventListener(WI.HeapSnapshotProxy.Event.Invalidated, this._handleHeapSnapshotInvalidated, this);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><del>-    get record() { return this._record; }
-    get data() { return this._data; }
</del><ins>+    get heapSnapshot()
+    {
+        return this.record.heapSnapshot;
+    }
</ins><span class="cx"> 
</span><ins>+    get data()
+    {
+        if (this._cachedData)
+            return this._cachedData;
+
+        this._cachedData = super.data;
+        this._cachedData.name = this.displayName();
+        this._cachedData.timestamp = this.record.timestamp - (this.graphDataSource ? this.graphDataSource.zeroTime : 0);
+        this._cachedData.size = this.heapSnapshot.totalSize;
+        this._cachedData.liveSize = this.heapSnapshot.liveSize;
+        return this._cachedData;
+    }
+
</ins><span class="cx">     createCellContent(columnIdentifier, cell)
</span><span class="cx">     {
</span><ins>+        const higherResolution = true;
+
+        let value = this.data[columnIdentifier];
+
</ins><span class="cx">         switch (columnIdentifier) {
</span><span class="cx">         case "name":
</span><span class="cx">             cell.classList.add(...this.iconClassNames());
</span><span class="lines">@@ -56,23 +69,24 @@
</span><span class="cx"> 
</span><span class="cx">             var fragment = document.createDocumentFragment();
</span><span class="cx">             var titleElement = fragment.appendChild(document.createElement("span"));
</span><del>-            titleElement.textContent = this._data.name;
-            if (!this._record.heapSnapshot.invalid) {
</del><ins>+            titleElement.textContent = value;
+
+            if (this._heapAllocationsView && !this.heapSnapshot.invalid) {
</ins><span class="cx">                 var goToButton = fragment.appendChild(WI.createGoToArrowButton());
</span><span class="cx">                 goToButton.addEventListener("click", (event) => {
</span><del>-                    this._heapAllocationsView.showHeapSnapshotTimelineRecord(this._record);
</del><ins>+                    this._heapAllocationsView.showHeapSnapshotTimelineRecord(this.record);
</ins><span class="cx">                 });
</span><span class="cx">             }
</span><ins>+
</ins><span class="cx">             return fragment;
</span><span class="cx"> 
</span><del>-        case "timestamp":
-            return isNaN(this._data.timestamp) ? emDash : Number.secondsToString(this._data.timestamp, true);
</del><ins>+        case "timestamp": {
+            return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution);
+        }
</ins><span class="cx"> 
</span><span class="cx">         case "size":
</span><del>-            return Number.bytesToString(this._data.size);
-
</del><span class="cx">         case "liveSize":
</span><del>-            return Number.bytesToString(this._data.liveSize);
</del><ins>+            return Number.bytesToString(value, higherResolution);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return super.createCellContent(columnIdentifier, cell);
</span><span class="lines">@@ -88,13 +102,6 @@
</span><span class="cx">         this.element.classList.remove("baseline");
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    updateTimestamp(zeroTime)
-    {
-        console.assert(isNaN(this._data.timestamp));
-        this._data.timestamp = this._record.timestamp - zeroTime;
-        this.needsRefresh();
-    }
-
</del><span class="cx">     // Protected
</span><span class="cx"> 
</span><span class="cx">     createCells()
</span><span class="lines">@@ -101,29 +108,19 @@
</span><span class="cx">     {
</span><span class="cx">         super.createCells();
</span><span class="cx"> 
</span><del>-        if (this._record.heapSnapshot.invalid)
</del><ins>+        if (this.heapSnapshot.invalid)
</ins><span class="cx">             this.element.classList.add("invalid");
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Private
</span><span class="cx"> 
</span><del>-    _heapSnapshotCollectedNodes()
</del><ins>+    _handleHeapSnapshotCollectedNodes()
</ins><span class="cx">     {
</span><del>-        let oldSize = this._data.liveSize;
-        let newSize = this._record.heapSnapshot.liveSize;
-
-        console.assert(newSize <= oldSize);
-        if (oldSize === newSize)
-            return;
-
-        this._data.liveSize = newSize;
</del><span class="cx">         this.needsRefresh();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    _heapSnapshotInvalidated()
</del><ins>+    _handleHeapSnapshotInvalidated()
</ins><span class="cx">     {
</span><del>-        this._data.liveSize = 0;
-
</del><span class="cx">         this.needsRefresh();
</span><span class="cx">     }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsHeapAllocationsTimelineViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js   2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js      2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -101,7 +101,6 @@
</span><span class="cx">         WI.ContentView.addEventListener(WI.ContentView.Event.SelectionPathComponentsDidChange, this._contentViewSelectionPathComponentDidChange, this);
</span><span class="cx"> 
</span><span class="cx">         this._pendingRecords = [];
</span><del>-        this._pendingZeroTimeDataGridNodes = [];
</del><span class="cx"> 
</span><span class="cx">         timeline.addEventListener(WI.Timeline.Event.RecordAdded, this._heapAllocationsTimelineRecordAdded, this);
</span><span class="cx"> 
</span><span class="lines">@@ -263,19 +262,12 @@
</span><span class="cx"> 
</span><span class="cx">     layout()
</span><span class="cx">     {
</span><del>-        if (this._pendingZeroTimeDataGridNodes.length && this.zeroTime) {
-            for (let dataGridNode of this._pendingZeroTimeDataGridNodes)
-                dataGridNode.updateTimestamp(this.zeroTime);
-            this._pendingZeroTimeDataGridNodes = [];
-            this._dataGrid._sort();
-        }
-
-        if (this._pendingRecords.length) {
</del><ins>+        if (this._pendingRecords.length && this.zeroTime) {
</ins><span class="cx">             for (let heapAllocationsTimelineRecord of this._pendingRecords) {
</span><del>-                let dataGridNode = new WI.HeapAllocationsTimelineDataGridNode(heapAllocationsTimelineRecord, this.zeroTime, this);
-                this._dataGrid.addRowInSortOrder(dataGridNode);
-                if (!this.zeroTime)
-                    this._pendingZeroTimeDataGridNodes.push(dataGridNode);
</del><ins>+                this._dataGrid.addRowInSortOrder(new WI.HeapAllocationsTimelineDataGridNode(heapAllocationsTimelineRecord, {
+                    graphDataSource: this,
+                    heapAllocationsView: this,
+                }));
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             this._pendingRecords = [];
</span><span class="lines">@@ -291,7 +283,6 @@
</span><span class="cx"> 
</span><span class="cx">         this.showHeapSnapshotList();
</span><span class="cx">         this._pendingRecords = [];
</span><del>-        this._pendingZeroTimeDataGridNodes = [];
</del><span class="cx">         this._updateCompareHeapSnapshotButton();
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsLayoutTimelineDataGridNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js    2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js       2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -25,36 +25,29 @@
</span><span class="cx"> 
</span><span class="cx"> WI.LayoutTimelineDataGridNode = class LayoutTimelineDataGridNode extends WI.TimelineDataGridNode
</span><span class="cx"> {
</span><del>-    constructor(layoutTimelineRecord, baseStartTime)
</del><ins>+    constructor(record, options = {})
</ins><span class="cx">     {
</span><del>-        super(false, null);
</del><ins>+        console.assert(record instanceof WI.LayoutTimelineRecord);
</ins><span class="cx"> 
</span><del>-        this._record = layoutTimelineRecord;
-        this._baseStartTime = baseStartTime || 0;
</del><ins>+        super([record], options);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><del>-    get records()
-    {
-        return [this._record];
-    }
-
</del><span class="cx">     get data()
</span><span class="cx">     {
</span><del>-        if (!this._cachedData) {
-            this._cachedData = {
-                type: this._record.eventType,
-                name: this.displayName(),
-                width: this._record.width,
-                height: this._record.height,
-                area: this._record.width * this._record.height,
-                startTime: this._record.startTime,
-                totalTime: this._record.duration,
-                location: this._record.initiatorCallFrame,
-            };
-        }
</del><ins>+        if (this._cachedData)
+            return this._cachedData;
</ins><span class="cx"> 
</span><ins>+        this._cachedData = super.data;
+        this._cachedData.type = this.record.eventType;
+        this._cachedData.name = this.displayName();
+        this._cachedData.width = this.record.width;
+        this._cachedData.height = this.record.height;
+        this._cachedData.area = this.record.width * this.record.height;
+        this._cachedData.startTime = this.record.startTime - (this.graphDataSource ? this.graphDataSource.zeroTime : 0);
+        this._cachedData.totalTime = this.record.duration;
+        this._cachedData.location = this.record.initiatorCallFrame;
</ins><span class="cx">         return this._cachedData;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -61,6 +54,7 @@
</span><span class="cx">     createCellContent(columnIdentifier, cell)
</span><span class="cx">     {
</span><span class="cx">         var value = this.data[columnIdentifier];
</span><ins>+        const higherResolution = true;
</ins><span class="cx"> 
</span><span class="cx">         switch (columnIdentifier) {
</span><span class="cx">         case "name":
</span><span class="lines">@@ -75,10 +69,10 @@
</span><span class="cx">             return isNaN(value) ? emDash : WI.UIString("%dpx\u00B2").format(value);
</span><span class="cx"> 
</span><span class="cx">         case "startTime":
</span><del>-            return isNaN(value) ? emDash : Number.secondsToString(value - this._baseStartTime, true);
</del><ins>+            return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution);
</ins><span class="cx"> 
</span><span class="cx">         case "totalTime":
</span><del>-            return isNaN(value) ? emDash : Number.secondsToString(value, true);
</del><ins>+            return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return super.createCellContent(columnIdentifier, cell);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsLayoutTimelineViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js    2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js       2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -204,7 +204,9 @@
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         for (var layoutTimelineRecord of this._pendingRecords) {
</span><del>-            let dataGridNode = new WI.LayoutTimelineDataGridNode(layoutTimelineRecord, this.zeroTime);
</del><ins>+            let dataGridNode = new WI.LayoutTimelineDataGridNode(layoutTimelineRecord, {
+                graphDataSource: this,
+            });
</ins><span class="cx"> 
</span><span class="cx">             this._dataGrid.addRowInSortOrder(dataGridNode);
</span><span class="cx"> 
</span><span class="lines">@@ -217,14 +219,24 @@
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 let childRecord = entry.children[entry.index];
</span><del>-                console.assert(childRecord.type === WI.TimelineRecord.Type.Layout, childRecord);
</del><span class="cx"> 
</span><del>-                let childDataGridNode = new WI.LayoutTimelineDataGridNode(childRecord, this.zeroTime);
</del><ins>+                const options = {
+                    graphDataSource: this,
+                };
+                let childDataGridNode = null;
+                if (childRecord.type === WI.TimelineRecord.Type.Script)
+                    childDataGridNode = new WI.ScriptTimelineDataGridNode(childRecord, options);
+                else {
+                    console.assert(childRecord.type === WI.TimelineRecord.Type.Layout, childRecord);
+                    childDataGridNode = new WI.LayoutTimelineDataGridNode(childRecord, options);
+                }
+
</ins><span class="cx">                 console.assert(entry.parentDataGridNode, "Missing parent node for entry.", entry);
</span><span class="cx">                 this._dataGrid.addRowInSortOrder(childDataGridNode, entry.parentDataGridNode);
</span><span class="cx"> 
</span><span class="cx">                 if (childDataGridNode && childRecord.children.length)
</span><span class="cx">                     stack.push({children: childRecord.children, parentDataGridNode: childDataGridNode, index: 0});
</span><ins>+
</ins><span class="cx">                 ++entry.index;
</span><span class="cx">             }
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsMediaTimelineDataGridNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/MediaTimelineDataGridNode.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/MediaTimelineDataGridNode.js     2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/MediaTimelineDataGridNode.js        2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -25,20 +25,15 @@
</span><span class="cx"> 
</span><span class="cx"> WI.MediaTimelineDataGridNode = class MediaTimelineDataGridNode extends WI.TimelineDataGridNode
</span><span class="cx"> {
</span><del>-    constructor(record, graphDataSource)
</del><ins>+    constructor(record, options = {})
</ins><span class="cx">     {
</span><span class="cx">         console.assert(record instanceof WI.MediaTimelineRecord);
</span><span class="cx"> 
</span><del>-        const includesGraph = false;
-        super(includesGraph, graphDataSource);
-
-        this._records = [record];
</del><ins>+        super([record], options);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><del>-    get records() { return this._records; }
-
</del><span class="cx">     get data()
</span><span class="cx">     {
</span><span class="cx">         if (this._cachedData)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsMediaTimelineViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/MediaTimelineView.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/MediaTimelineView.js     2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/MediaTimelineView.js        2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -186,7 +186,9 @@
</span><span class="cx">             if (timelineRecord.domEvent && timelineRecord.domEvent.originator)
</span><span class="cx">                 this._dataGrid.setColumnVisible("originator", true);
</span><span class="cx"> 
</span><del>-            this._dataGrid.addRowInSortOrder(new WI.MediaTimelineDataGridNode(timelineRecord, this));
</del><ins>+            this._dataGrid.addRowInSortOrder(new WI.MediaTimelineDataGridNode(timelineRecord, {
+                graphDataSource: this,
+            }));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         this._pendingRecords = [];
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsNetworkTimelineViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js   2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js      2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -257,9 +257,11 @@
</span><span class="cx">             if (dataGridNode)
</span><span class="cx">                 continue;
</span><span class="cx"> 
</span><del>-            const includesGraph = false;
-            const shouldShowPopover = true;
-            dataGridNode = new WI.ResourceTimelineDataGridNode(resourceTimelineRecord, includesGraph, this, shouldShowPopover);
</del><ins>+            dataGridNode = new WI.ResourceTimelineDataGridNode(resourceTimelineRecord, {
+                graphDataSource: this,
+                shouldShowPopover: true,
+            });
+
</ins><span class="cx">             this._resourceDataGridNodeMap.set(resourceTimelineRecord.resource, dataGridNode);
</span><span class="cx"> 
</span><span class="cx">             this._dataGrid.addRowInSortOrder(dataGridNode);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsOverviewTimelineViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js  2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js     2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -220,9 +220,10 @@
</span><span class="cx">         if (!resourceTimelineRecord)
</span><span class="cx">             resourceTimelineRecord = new WI.ResourceTimelineRecord(resource);
</span><span class="cx"> 
</span><del>-        const includesGraph = true;
-        const shouldShowPopover = false;
-        let resourceDataGridNode = new WI.ResourceTimelineDataGridNode(resourceTimelineRecord, includesGraph, this, shouldShowPopover);
</del><ins>+        let resourceDataGridNode = new WI.ResourceTimelineDataGridNode(resourceTimelineRecord, {
+            graphDataSource: this,
+            includesGraph: true,
+        });
</ins><span class="cx">         this._resourceDataGridNodeMap.set(resource, resourceDataGridNode);
</span><span class="cx"> 
</span><span class="cx">         let expandedByDefault = false;
</span><span class="lines">@@ -253,7 +254,9 @@
</span><span class="cx">     _addSourceCodeTimeline(sourceCodeTimeline)
</span><span class="cx">     {
</span><span class="cx">         let parentDataGridNode = sourceCodeTimeline.sourceCodeLocation ? this._addResourceToDataGridIfNeeded(sourceCodeTimeline.sourceCode) : null;
</span><del>-        let sourceCodeTimelineDataGridNode = new WI.SourceCodeTimelineTimelineDataGridNode(sourceCodeTimeline, this);
</del><ins>+        let sourceCodeTimelineDataGridNode = new WI.SourceCodeTimelineTimelineDataGridNode(sourceCodeTimeline, {
+            graphDataSource: this,
+        });
</ins><span class="cx">         this._resourceDataGridNodeMap.set(sourceCodeTimeline, sourceCodeTimelineDataGridNode);
</span><span class="cx"> 
</span><span class="cx">         this._insertDataGridNode(sourceCodeTimelineDataGridNode, parentDataGridNode);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsProfileNodeDataGridNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ProfileNodeDataGridNode.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ProfileNodeDataGridNode.js       2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ProfileNodeDataGridNode.js  2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -25,93 +25,53 @@
</span><span class="cx"> 
</span><span class="cx"> WI.ProfileNodeDataGridNode = class ProfileNodeDataGridNode extends WI.TimelineDataGridNode
</span><span class="cx"> {
</span><del>-    constructor(profileNode, baseStartTime, rangeStartTime, rangeEndTime)
</del><ins>+    constructor(profileNode, options = {})
</ins><span class="cx">     {
</span><del>-        var hasChildren = !!profileNode.childNodes.length;
</del><ins>+        console.assert(profileNode instanceof WI.ProfileNode);
</ins><span class="cx"> 
</span><del>-        super(false, null, hasChildren);
</del><ins>+        options.hasChildren = !!profileNode.childNodes.length;
</ins><span class="cx"> 
</span><ins>+        super(null, options);
+
</ins><span class="cx">         this._profileNode = profileNode;
</span><del>-        this._baseStartTime = baseStartTime || 0;
-        this._rangeStartTime = rangeStartTime || 0;
-        this._rangeEndTime = typeof rangeEndTime === "number" ? rangeEndTime : Infinity;
</del><span class="cx"> 
</span><del>-        this._cachedData = null;
-
</del><span class="cx">         this.addEventListener("populate", this._populate, this);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><del>-    get profileNode()
-    {
-        return this._profileNode;
-    }
</del><ins>+    get profileNode() { return this._profileNode; }
</ins><span class="cx"> 
</span><del>-    get records()
</del><ins>+    get data()
</ins><span class="cx">     {
</span><del>-        return null;
-    }
</del><ins>+        if (this._cachedData)
+            return this._cachedData;
</ins><span class="cx"> 
</span><del>-    get baseStartTime()
-    {
-        return this._baseStartTime;
-    }
</del><ins>+        let baseStartTime = 0;
+        let rangeStartTime = 0;
+        let rangeEndTime = Infinity;
+        if (this.graphDataSource) {
+            baseStartTime = this.graphDataSource.zeroTime;
+            rangeStartTime = this.graphDataSource.startTime;
+            rangeEndTime = this.graphDataSource.endTime;
+        }
</ins><span class="cx"> 
</span><del>-    get rangeStartTime()
-    {
-        return this._rangeStartTime;
-    }
</del><ins>+        let callInfo = this._profileNode.computeCallInfoForTimeRange(rangeStartTime, rangeEndTime);
</ins><span class="cx"> 
</span><del>-    get rangeEndTime()
-    {
-        return this._rangeEndTime;
-    }
</del><ins>+        this._cachedData = super.data;
+        for (let key in callInfo)
+            this._cachedData[key] = callInfo[key];
+        this._cachedData.startTime -= baseStartTime;
+        this._cachedData.name = this.displayName();
+        this._cachedData.location = this._profileNode.sourceCodeLocation;
</ins><span class="cx"> 
</span><del>-    get data()
-    {
-        if (!this._cachedData) {
-            this._cachedData = this._profileNode.computeCallInfoForTimeRange(this._rangeStartTime, this._rangeEndTime);
-            this._cachedData.name = this.displayName();
-            this._cachedData.location = this._profileNode.sourceCodeLocation;
-        }
-
</del><span class="cx">         return this._cachedData;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    updateRangeTimes(startTime, endTime)
</del><ins>+    createCellContent(columnIdentifier, cell)
</ins><span class="cx">     {
</span><del>-        var oldRangeStartTime = this._rangeStartTime;
-        var oldRangeEndTime = this._rangeEndTime;
</del><ins>+        const higherResolution = true;
</ins><span class="cx"> 
</span><del>-        if (oldRangeStartTime === startTime && oldRangeEndTime === endTime)
-            return;
-
-        this._rangeStartTime = startTime;
-        this._rangeEndTime = endTime;
-
-        // We only need a refresh if the new range time changes the visible portion of this record.
-        var profileStart = this._profileNode.startTime;
-        var profileEnd = this._profileNode.endTime;
-        var oldStartBoundary = Number.constrain(oldRangeStartTime, profileStart, profileEnd);
-        var oldEndBoundary = Number.constrain(oldRangeEndTime, profileStart, profileEnd);
-        var newStartBoundary = Number.constrain(startTime, profileStart, profileEnd);
-        var newEndBoundary = Number.constrain(endTime, profileStart, profileEnd);
-
-        if (oldStartBoundary !== newStartBoundary || oldEndBoundary !== newEndBoundary)
-            this.needsRefresh();
-    }
-
-    refresh()
-    {
-        this._data = this._profileNode.computeCallInfoForTimeRange(this._rangeStartTime, this._rangeEndTime);
-        this._data.location = this._profileNode.sourceCodeLocation;
-
-        super.refresh();
-    }
-
-    createCellContent(columnIdentifier, cell)
-    {
</del><span class="cx">         var value = this.data[columnIdentifier];
</span><span class="cx"> 
</span><span class="cx">         switch (columnIdentifier) {
</span><span class="lines">@@ -120,12 +80,10 @@
</span><span class="cx">             return value;
</span><span class="cx"> 
</span><span class="cx">         case "startTime":
</span><del>-            return isNaN(value) ? emDash : Number.secondsToString(value - this._baseStartTime, true);
-
</del><span class="cx">         case "selfTime":
</span><span class="cx">         case "totalTime":
</span><span class="cx">         case "averageTime":
</span><del>-            return isNaN(value) ? emDash : Number.secondsToString(value, true);
</del><ins>+            return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return super.createCellContent(columnIdentifier, cell);
</span><span class="lines">@@ -186,6 +144,8 @@
</span><span class="cx">         this.removeChildren();
</span><span class="cx"> 
</span><span class="cx">         for (let node of this._profileNode.childNodes)
</span><del>-            this.appendChild(new WI.ProfileNodeDataGridNode(node, this.baseStartTime, this.rangeStartTime, this.rangeEndTime));
</del><ins>+            this.appendChild(new WI.ProfileNodeDataGridNode(node, {
+                graphDataSource: this.graphDataSource,
+            }));
</ins><span class="cx">     }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsRenderingFrameTimelineDataGridNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineDataGridNode.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineDataGridNode.js    2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineDataGridNode.js       2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2019 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -25,45 +25,35 @@
</span><span class="cx"> 
</span><span class="cx"> WI.RenderingFrameTimelineDataGridNode = class RenderingFrameTimelineDataGridNode extends WI.TimelineDataGridNode
</span><span class="cx"> {
</span><del>-    constructor(renderingFrameTimelineRecord, baseStartTime)
</del><ins>+    constructor(record, options = {})
</ins><span class="cx">     {
</span><del>-        super(false, null);
</del><ins>+        console.assert(record instanceof WI.RenderingFrameTimelineRecord);
</ins><span class="cx"> 
</span><del>-        this._record = renderingFrameTimelineRecord;
-        this._baseStartTime = baseStartTime || 0;
</del><ins>+        super([record], options);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><del>-    get records()
-    {
-        return [this._record];
-    }
-
</del><span class="cx">     get data()
</span><span class="cx">     {
</span><del>-        if (!this._cachedData) {
-            let name = WI.TimelineTabContentView.displayNameForRecord(this._record);
-            let scriptTime = this._record.durationForTask(WI.RenderingFrameTimelineRecord.TaskType.Script);
-            let layoutTime = this._record.durationForTask(WI.RenderingFrameTimelineRecord.TaskType.Layout);
-            let paintTime = this._record.durationForTask(WI.RenderingFrameTimelineRecord.TaskType.Paint);
-            let otherTime = this._record.durationForTask(WI.RenderingFrameTimelineRecord.TaskType.Other);
-            this._cachedData = {
-                name,
-                startTime: this._record.startTime,
-                totalTime: this._record.duration,
-                scriptTime,
-                layoutTime,
-                paintTime,
-                otherTime,
-            };
-        }
</del><ins>+        if (this._cachedData)
+            return this._cachedData;
</ins><span class="cx"> 
</span><ins>+        this._cachedData = super.data;
+        this._cachedData.name = WI.TimelineTabContentView.displayNameForRecord(this.record);
+        this._cachedData.startTime = this.record.startTime - (this.graphDataSource ? this.graphDataSource.zeroTime : 0);
+        this._cachedData.totalTime = this.record.duration;
+        this._cachedData.scriptTime = this.record.durationForTask(WI.RenderingFrameTimelineRecord.TaskType.Script);
+        this._cachedData.layoutTime = this.record.durationForTask(WI.RenderingFrameTimelineRecord.TaskType.Layout);
+        this._cachedData.paintTime = this.record.durationForTask(WI.RenderingFrameTimelineRecord.TaskType.Paint);
+        this._cachedData.otherTime = this.record.durationForTask(WI.RenderingFrameTimelineRecord.TaskType.Other);
</ins><span class="cx">         return this._cachedData;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     createCellContent(columnIdentifier, cell)
</span><span class="cx">     {
</span><ins>+        const higherResolution = true;
+
</ins><span class="cx">         var value = this.data[columnIdentifier];
</span><span class="cx"> 
</span><span class="cx">         switch (columnIdentifier) {
</span><span class="lines">@@ -72,7 +62,7 @@
</span><span class="cx">             return value;
</span><span class="cx"> 
</span><span class="cx">         case "startTime":
</span><del>-            return isNaN(value) ? emDash : Number.secondsToString(value - this._baseStartTime, true);
</del><ins>+            return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution);
</ins><span class="cx"> 
</span><span class="cx">         case "scriptTime":
</span><span class="cx">         case "layoutTime":
</span><span class="lines">@@ -79,7 +69,7 @@
</span><span class="cx">         case "paintTime":
</span><span class="cx">         case "otherTime":
</span><span class="cx">         case "totalTime":
</span><del>-            return (isNaN(value) || value === 0) ? emDash : Number.secondsToString(value, true);
</del><ins>+            return (isNaN(value) || value === 0) ? emDash : Number.secondsToString(value, higherResolution);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return super.createCellContent(columnIdentifier, cell);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsRenderingFrameTimelineViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js    2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js       2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -235,7 +235,9 @@
</span><span class="cx">         for (let renderingFrameTimelineRecord of this._pendingRecords) {
</span><span class="cx">             console.assert(renderingFrameTimelineRecord instanceof WI.RenderingFrameTimelineRecord);
</span><span class="cx"> 
</span><del>-            let dataGridNode = new WI.RenderingFrameTimelineDataGridNode(renderingFrameTimelineRecord, this.zeroTime);
</del><ins>+            let dataGridNode = new WI.RenderingFrameTimelineDataGridNode(renderingFrameTimelineRecord, {
+                graphDataSource: this,
+            });
</ins><span class="cx">             this._dataGrid.addRowInSortOrder(dataGridNode);
</span><span class="cx"> 
</span><span class="cx">             let stack = [{children: renderingFrameTimelineRecord.children, parentDataGridNode: dataGridNode, index: 0}];
</span><span class="lines">@@ -249,7 +251,9 @@
</span><span class="cx">                 let childRecord = entry.children[entry.index];
</span><span class="cx">                 let childDataGridNode = null;
</span><span class="cx">                 if (childRecord.type === WI.TimelineRecord.Type.Layout) {
</span><del>-                    childDataGridNode = new WI.LayoutTimelineDataGridNode(childRecord, this.zeroTime);
</del><ins>+                    childDataGridNode = new WI.LayoutTimelineDataGridNode(childRecord, {
+                        graphDataSource: this,
+                    });
</ins><span class="cx"> 
</span><span class="cx">                     this._dataGrid.addRowInSortOrder(childDataGridNode, entry.parentDataGridNode);
</span><span class="cx">                 } else if (childRecord.type === WI.TimelineRecord.Type.Script) {
</span><span class="lines">@@ -259,12 +263,16 @@
</span><span class="cx">                         rootNodes = childRecord.profile.topDownRootNodes;
</span><span class="cx">                     }
</span><span class="cx"> 
</span><del>-                    childDataGridNode = new WI.ScriptTimelineDataGridNode(childRecord, this.zeroTime);
</del><ins>+                    childDataGridNode = new WI.ScriptTimelineDataGridNode(childRecord, {
+                        graphDataSource: this,
+                    });
</ins><span class="cx"> 
</span><span class="cx">                     this._dataGrid.addRowInSortOrder(childDataGridNode, entry.parentDataGridNode);
</span><span class="cx"> 
</span><span class="cx">                     for (let profileNode of rootNodes) {
</span><del>-                        let profileNodeDataGridNode = new WI.ProfileNodeDataGridNode(profileNode, this.zeroTime, this.startTime, this.endTime);
</del><ins>+                        let profileNodeDataGridNode = new WI.ProfileNodeDataGridNode(profileNode, {
+                            graphDataSource: this,
+                        });
</ins><span class="cx">                         this._dataGrid.addRowInSortOrder(profileNodeDataGridNode, childDataGridNode);
</span><span class="cx">                     }
</span><span class="cx">                 }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsResourceTimelineDataGridNodecss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.css (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.css 2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.css    2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .resource-timing-popover-content .data-grid td.graph-column {
</span><del>-    padding: 4px 0 0;
</del><ins>+    padding: 4px 2px 0;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .resource-timing-popover-content .data-grid table.data {
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsResourceTimelineDataGridNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js  2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js     2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -25,37 +25,32 @@
</span><span class="cx"> 
</span><span class="cx"> WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI.TimelineDataGridNode
</span><span class="cx"> {
</span><del>-    constructor(resourceTimelineRecord, includesGraph, graphDataSource, shouldShowPopover)
</del><ins>+    constructor(record, options = {})
</ins><span class="cx">     {
</span><del>-        super(includesGraph, graphDataSource);
</del><ins>+        console.assert(record instanceof WI.ResourceTimelineRecord);
</ins><span class="cx"> 
</span><del>-        this._resource = resourceTimelineRecord.resource;
-        this._record = resourceTimelineRecord;
-        this._shouldShowPopover = shouldShowPopover;
</del><ins>+        super([record], options);
</ins><span class="cx"> 
</span><del>-        this._resource.addEventListener(WI.Resource.Event.LoadingDidFinish, this._needsRefresh, this);
-        this._resource.addEventListener(WI.Resource.Event.LoadingDidFail, this._needsRefresh, this);
-        this._resource.addEventListener(WI.Resource.Event.URLDidChange, this._needsRefresh, this);
</del><ins>+        this._shouldShowPopover = options.shouldShowPopover;
</ins><span class="cx"> 
</span><del>-        if (includesGraph)
-            this._record.addEventListener(WI.TimelineRecord.Event.Updated, this._timelineRecordUpdated, this);
</del><ins>+        this.resource.addEventListener(WI.Resource.Event.LoadingDidFinish, this._needsRefresh, this);
+        this.resource.addEventListener(WI.Resource.Event.LoadingDidFail, this._needsRefresh, this);
+        this.resource.addEventListener(WI.Resource.Event.URLDidChange, this._needsRefresh, this);
+
+        if (options.includesGraph)
+            this.record.addEventListener(WI.TimelineRecord.Event.Updated, this._timelineRecordUpdated, this);
</ins><span class="cx">         else {
</span><del>-            this._resource.addEventListener(WI.Resource.Event.TypeDidChange, this._needsRefresh, this);
-            this._resource.addEventListener(WI.Resource.Event.SizeDidChange, this._needsRefresh, this);
-            this._resource.addEventListener(WI.Resource.Event.TransferSizeDidChange, this._needsRefresh, this);
</del><ins>+            this.resource.addEventListener(WI.Resource.Event.TypeDidChange, this._needsRefresh, this);
+            this.resource.addEventListener(WI.Resource.Event.SizeDidChange, this._needsRefresh, this);
+            this.resource.addEventListener(WI.Resource.Event.TransferSizeDidChange, this._needsRefresh, this);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><del>-    get records()
-    {
-        return [this._record];
-    }
-
</del><span class="cx">     get resource()
</span><span class="cx">     {
</span><del>-        return this._resource;
</del><ins>+        return this.record.resource;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     get data()
</span><span class="lines">@@ -63,40 +58,28 @@
</span><span class="cx">         if (this._cachedData)
</span><span class="cx">             return this._cachedData;
</span><span class="cx"> 
</span><del>-        var resource = this._resource;
-        var data = {};
-
-        if (!this._includesGraph) {
-            var zeroTime = this.graphDataSource ? this.graphDataSource.zeroTime : 0;
-
-            data.domain = WI.displayNameForHost(resource.urlComponents.host);
-            data.scheme = resource.urlComponents.scheme ? resource.urlComponents.scheme.toUpperCase() : "";
-            data.method = resource.requestMethod;
-            data.type = resource.type;
-            data.statusCode = resource.statusCode;
-            data.cached = resource.cached;
-            data.size = resource.size;
-            data.transferSize = !isNaN(resource.networkTotalTransferSize) ? resource.networkTotalTransferSize : resource.estimatedTotalTransferSize;
-            data.requestSent = resource.requestSentTimestamp - zeroTime;
-            data.duration = resource.receiveDuration;
-            data.latency = resource.latency;
-            data.protocol = resource.protocol;
-            data.priority = resource.priority;
-            data.remoteAddress = resource.remoteAddress;
-            data.connectionIdentifier = resource.connectionIdentifier;
-        }
-
-        data.graph = this._record.startTime;
-
-        this._cachedData = data;
-        return data;
</del><ins>+        this._cachedData = super.data;
+        this._cachedData.domain = WI.displayNameForHost(this.resource.urlComponents.host);
+        this._cachedData.scheme = this.resource.urlComponents.scheme ? this.resource.urlComponents.scheme.toUpperCase() : "";
+        this._cachedData.method = this.resource.requestMethod;
+        this._cachedData.type = this.resource.type;
+        this._cachedData.statusCode = this.resource.statusCode;
+        this._cachedData.cached = this.resource.cached;
+        this._cachedData.size = this.resource.size;
+        this._cachedData.transferSize = !isNaN(this.resource.networkTotalTransferSize) ? this.resource.networkTotalTransferSize : this.resource.estimatedTotalTransferSize;
+        this._cachedData.requestSent = this.resource.requestSentTimestamp - (this.graphDataSource ? this.graphDataSource.zeroTime : 0);
+        this._cachedData.duration = this.resource.receiveDuration;
+        this._cachedData.latency = this.resource.latency;
+        this._cachedData.protocol = this.resource.protocol;
+        this._cachedData.priority = this.resource.priority;
+        this._cachedData.remoteAddress = this.resource.remoteAddress;
+        this._cachedData.connectionIdentifier = this.resource.connectionIdentifier;
+        return this._cachedData;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     createCellContent(columnIdentifier, cell)
</span><span class="cx">     {
</span><del>-        let resource = this._resource;
-
-        if (resource.hadLoadingError())
</del><ins>+        if (this.resource.hadLoadingError())
</ins><span class="cx">             cell.classList.add("error");
</span><span class="cx"> 
</span><span class="cx">         let value = this.data[columnIdentifier];
</span><span class="lines">@@ -104,7 +87,7 @@
</span><span class="cx">         switch (columnIdentifier) {
</span><span class="cx">         case "name":
</span><span class="cx">             cell.classList.add(...this.iconClassNames());
</span><del>-            cell.title = resource.displayURL;
</del><ins>+            cell.title = this.resource.displayURL;
</ins><span class="cx">             this._updateStatus(cell);
</span><span class="cx">             return this._createNameCellDocumentFragment();
</span><span class="cx"> 
</span><span class="lines">@@ -114,7 +97,7 @@
</span><span class="cx">             return text;
</span><span class="cx"> 
</span><span class="cx">         case "statusCode":
</span><del>-            cell.title = resource.statusText || "";
</del><ins>+            cell.title = this.resource.statusText || "";
</ins><span class="cx">             return value || emDash;
</span><span class="cx"> 
</span><span class="cx">         case "cached":
</span><span class="lines">@@ -180,7 +163,7 @@
</span><span class="cx"> 
</span><span class="cx">     appendContextMenuItems(contextMenu)
</span><span class="cx">     {
</span><del>-        WI.appendContextMenuItemsForSourceCode(contextMenu, this._resource);
</del><ins>+        WI.appendContextMenuItemsForSourceCode(contextMenu, this.resource);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Protected
</span><span class="lines">@@ -213,7 +196,7 @@
</span><span class="cx">     filterableDataForColumn(columnIdentifier)
</span><span class="cx">     {
</span><span class="cx">         if (columnIdentifier === "name")
</span><del>-            return this._resource.url;
</del><ins>+            return this.resource.url;
</ins><span class="cx">         return super.filterableDataForColumn(columnIdentifier);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -226,8 +209,8 @@
</span><span class="cx">         fragment.append(mainTitle);
</span><span class="cx"> 
</span><span class="cx">         // Show the host as the subtitle if it is different from the main resource or if this is the main frame's main resource.
</span><del>-        let frame = this._resource.parentFrame;
-        let isMainResource = this._resource.isMainResource();
</del><ins>+        let frame = this.resource.parentFrame;
+        let isMainResource = this.resource.isMainResource();
</ins><span class="cx">         let parentResourceHost;
</span><span class="cx">         if (frame && isMainResource) {
</span><span class="cx">             // When the resource is a main resource, get the host from the current frame's parent frame instead of the current frame.
</span><span class="lines">@@ -237,8 +220,8 @@
</span><span class="cx">             parentResourceHost = frame.mainResource.urlComponents.host;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (parentResourceHost !== this._resource.urlComponents.host || frame.isMainFrame() && isMainResource) {
-            let subtitle = WI.displayNameForHost(this._resource.urlComponents.host);
</del><ins>+        if (parentResourceHost !== this.resource.urlComponents.host || frame.isMainFrame() && isMainResource) {
+            let subtitle = WI.displayNameForHost(this.resource.urlComponents.host);
</ins><span class="cx">             if (mainTitle !== subtitle) {
</span><span class="cx">                 let subtitleElement = document.createElement("span");
</span><span class="cx">                 subtitleElement.classList.add("subtitle");
</span><span class="lines">@@ -252,12 +235,12 @@
</span><span class="cx"> 
</span><span class="cx">     _cachedCellContent()
</span><span class="cx">     {
</span><del>-        if (!this._resource.hasResponse())
</del><ins>+        if (!this.resource.hasResponse())
</ins><span class="cx">             return emDash;
</span><span class="cx"> 
</span><del>-        let responseSource = this._resource.responseSource;
</del><ins>+        let responseSource = this.resource.responseSource;
</ins><span class="cx">         if (responseSource === WI.Resource.ResponseSource.MemoryCache || responseSource === WI.Resource.ResponseSource.DiskCache) {
</span><del>-            console.assert(this._resource.cached, "This resource has a cache responseSource it should also be marked as cached", this._resource);
</del><ins>+            console.assert(this.resource.cached, "This resource has a cache responseSource it should also be marked as cached", this.resource);
</ins><span class="cx">             let span = document.createElement("span");
</span><span class="cx">             let cacheType = document.createElement("span");
</span><span class="cx">             cacheType.classList = "cache-type";
</span><span class="lines">@@ -267,7 +250,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         let fragment = document.createDocumentFragment();
</span><del>-        fragment.append(this._resource.cached ? WI.UIString("Yes") : WI.UIString("No"));
</del><ins>+        fragment.append(this.resource.cached ? WI.UIString("Yes") : WI.UIString("No"));
</ins><span class="cx">         return fragment;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -286,7 +269,7 @@
</span><span class="cx"> 
</span><span class="cx">     _timelineRecordUpdated(event)
</span><span class="cx">     {
</span><del>-        if (this.isRecordVisible(this._record))
</del><ins>+        if (this.isRecordVisible(this.record))
</ins><span class="cx">             this.needsGraphRefresh();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -296,21 +279,21 @@
</span><span class="cx">             ignoreNetworkTab: true,
</span><span class="cx">             ignoreSearchTab: true,
</span><span class="cx">         };
</span><del>-        WI.showSourceCode(this._resource, options);
</del><ins>+        WI.showSourceCode(this.resource, options);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _updateStatus(cell)
</span><span class="cx">     {
</span><del>-        if (this._resource.failed)
</del><ins>+        if (this.resource.failed)
</ins><span class="cx">             cell.classList.add("error");
</span><span class="cx">         else {
</span><span class="cx">             cell.classList.remove("error");
</span><span class="cx"> 
</span><del>-            if (this._resource.finished)
</del><ins>+            if (this.resource.finished)
</ins><span class="cx">                 this.createGoToArrowButton(cell, this._dataGridNodeGoToArrowClicked.bind(this));
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (this._resource.isLoading()) {
</del><ins>+        if (this.resource.isLoading()) {
</ins><span class="cx">             if (!this._spinner)
</span><span class="cx">                 this._spinner = new WI.IndeterminateProgressSpinner;
</span><span class="cx">             let contentElement = cell.firstChild;
</span><span class="lines">@@ -386,14 +369,10 @@
</span><span class="cx">             let graphDataSource = {
</span><span class="cx">                 get secondsPerPixel() { return resource.totalDuration / WI.ResourceTimelineDataGridNode.PopoverGraphColumnWidthPixels; },
</span><span class="cx">                 get zeroTime() { return resource.firstTimestamp; },
</span><del>-                get startTime() { return resource.firstTimestamp; },
-                get currentTime() { return this.endTime; },
-
-                get endTime()
-                {
-                    let endTimePadding = this.secondsPerPixel * WI.TimelineRecordBar.MinimumWidthPixels;
-                    return resource.lastTimestamp + endTimePadding;
-                }
</del><ins>+                get startTime() { return this.zeroTime; },
+                get currentTime() { return resource.lastTimestamp + this._extraTimePadding; },
+                get endTime() { return this.currentTime; },
+                get _extraTimePadding() { return this.secondsPerPixel * WI.TimelineRecordBar.MinimumWidthPixels; },
</ins><span class="cx">             };
</span><span class="cx"> 
</span><span class="cx">             if (resource.timingData.redirectEnd - resource.timingData.redirectStart) {
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsResourceTimingPopoverDataGridNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimingPopoverDataGridNode.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimingPopoverDataGridNode.js     2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimingPopoverDataGridNode.js        2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2019 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -27,21 +27,27 @@
</span><span class="cx"> {
</span><span class="cx">     constructor(description, startTime, endTime, graphDataSource)
</span><span class="cx">     {
</span><del>-        super(true, graphDataSource);
</del><ins>+        let record = new WI.TimelineRecord(WI.TimelineRecord.Type.Network, startTime, endTime);
+        super([record], {
+            includesGraph: true,
+            graphDataSource,
+        });
</ins><span class="cx"> 
</span><span class="cx">         const higherResolution = true;
</span><span class="cx">         let duration = Number.secondsToMillisecondsString(endTime - startTime, higherResolution);
</span><span class="cx"> 
</span><span class="cx">         this._data = {description, duration};
</span><del>-        this._record = new WI.TimelineRecord(WI.TimelineRecord.Type.Network, startTime, endTime);
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><del>-    get records() { return [this._record]; }
</del><span class="cx">     get data() { return this._data; }
</span><del>-    get selectable() { return false; }
</del><span class="cx"> 
</span><ins>+    get selectable()
+    {
+        return false;
+    }
+
</ins><span class="cx">     // Protected
</span><span class="cx"> 
</span><span class="cx">     createCellContent(columnIdentifier, cell)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsScriptDetailsTimelineViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScriptDetailsTimelineView.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ScriptDetailsTimelineView.js     2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ScriptDetailsTimelineView.js        2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -179,9 +179,11 @@
</span><span class="cx">         if (this.startTime !== this._oldStartTime || this.endTime !== this._oldEndTime) {
</span><span class="cx">             let dataGridNode = this._dataGrid.children[0];
</span><span class="cx">             while (dataGridNode) {
</span><del>-                dataGridNode.updateRangeTimes(this.startTime, this.endTime);
</del><span class="cx">                 if (dataGridNode.revealed)
</span><del>-                    dataGridNode.refreshIfNeeded();
</del><ins>+                    dataGridNode.refresh();
+                else
+                    dataGridNode.needsRefresh();
+
</ins><span class="cx">                 dataGridNode = dataGridNode.traverseNextNode(false, null, true);
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -202,10 +204,6 @@
</span><span class="cx">         if (!this._pendingRecords.length)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        let zeroTime = this.zeroTime;
-        let startTime = this.startTime;
-        let endTime = this.endTime;
-
</del><span class="cx">         for (let scriptTimelineRecord of this._pendingRecords) {
</span><span class="cx">             let rootNodes = [];
</span><span class="cx">             if (scriptTimelineRecord.profile) {
</span><span class="lines">@@ -213,11 +211,15 @@
</span><span class="cx">                 rootNodes = scriptTimelineRecord.profile.topDownRootNodes;
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            let dataGridNode = new WI.ScriptTimelineDataGridNode(scriptTimelineRecord, zeroTime);
</del><ins>+            let dataGridNode = new WI.ScriptTimelineDataGridNode(scriptTimelineRecord, {
+                graphDataSource: this,
+            });
</ins><span class="cx">             this._dataGrid.addRowInSortOrder(dataGridNode);
</span><span class="cx"> 
</span><span class="cx">             for (let profileNode of rootNodes) {
</span><del>-                let profileNodeDataGridNode = new WI.ProfileNodeDataGridNode(profileNode, zeroTime, startTime, endTime);
</del><ins>+                let profileNodeDataGridNode = new WI.ProfileNodeDataGridNode(profileNode, {
+                    graphDataSource: this,
+                });
</ins><span class="cx">                 this._dataGrid.addRowInSortOrder(profileNodeDataGridNode, dataGridNode);
</span><span class="cx">             }
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsScriptTimelineDataGridNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js    2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js       2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2019 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -25,65 +25,51 @@
</span><span class="cx"> 
</span><span class="cx"> WI.ScriptTimelineDataGridNode = class ScriptTimelineDataGridNode extends WI.TimelineDataGridNode
</span><span class="cx"> {
</span><del>-    constructor(scriptTimelineRecord, baseStartTime, rangeStartTime, rangeEndTime)
</del><ins>+    constructor(record, options = {})
</ins><span class="cx">     {
</span><del>-        super(false, null);
</del><ins>+        console.assert(record instanceof WI.ScriptTimelineRecord);
</ins><span class="cx"> 
</span><del>-        this._record = scriptTimelineRecord;
-        this._baseStartTime = baseStartTime || 0;
-        this._rangeStartTime = rangeStartTime || 0;
-        this._rangeEndTime = typeof rangeEndTime === "number" ? rangeEndTime : Infinity;
</del><ins>+        super([record], options);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><del>-    get records()
</del><ins>+    get data()
</ins><span class="cx">     {
</span><del>-        return [this._record];
-    }
</del><ins>+        if (this._cachedData)
+            return this._cachedData;
</ins><span class="cx"> 
</span><del>-    get baseStartTime()
-    {
-        return this._baseStartTime;
-    }
</del><ins>+        let baseStartTime = 0;
+        let rangeStartTime = 0;
+        let rangeEndTime = Infinity;
+        if (this.graphDataSource) {
+            baseStartTime = this.graphDataSource.zeroTime;
+            rangeStartTime = this.graphDataSource.startTime;
+            rangeEndTime = this.graphDataSource.endTime;
+        }
</ins><span class="cx"> 
</span><del>-    get rangeStartTime()
-    {
-        return this._rangeStartTime;
-    }
</del><ins>+        let startTime = this.record.startTime;
+        let duration = this.record.startTime + this.record.duration - startTime;
</ins><span class="cx"> 
</span><del>-    get rangeEndTime()
-    {
-        return this._rangeEndTime;
-    }
-
-    get data()
-    {
-        if (!this._cachedData) {
-            var startTime = this._record.startTime;
-            var duration = this._record.startTime + this._record.duration - startTime;
-            var callFrameOrSourceCodeLocation = this._record.initiatorCallFrame || this._record.sourceCodeLocation;
-
-            // COMPATIBILITY (iOS 8): Profiles included per-call information and can be finely partitioned.
-            if (this._record.profile) {
-                var oneRootNode = this._record.profile.topDownRootNodes[0];
-                if (oneRootNode && oneRootNode.calls) {
-                    startTime = Math.max(this._rangeStartTime, this._record.startTime);
-                    duration = Math.min(this._record.startTime + this._record.duration, this._rangeEndTime) - startTime;
-                }
</del><ins>+        // COMPATIBILITY (iOS 8): Profiles included per-call information and can be finely partitioned.
+        if (this.record.profile) {
+            let oneRootNode = this.record.profile.topDownRootNodes[0];
+            if (oneRootNode && oneRootNode.calls) {
+                startTime = Math.max(rangeStartTime, this.record.startTime);
+                duration = Math.min(this.record.startTime + this.record.duration, rangeEndTime) - startTime;
</ins><span class="cx">             }
</span><del>-
-            this._cachedData = {
-                eventType: this._record.eventType,
-                startTime,
-                selfTime: duration,
-                totalTime: duration,
-                averageTime: duration,
-                callCount: this._record.callCountOrSamples,
-                location: callFrameOrSourceCodeLocation,
-            };
</del><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        this._cachedData = super.data;
+        this._cachedData.type = this.record.eventType;
+        this._cachedData.name = this.displayName();
+        this._cachedData.startTime = startTime - baseStartTime;
+        this._cachedData.selfTime = duration;
+        this._cachedData.totalTime = duration;
+        this._cachedData.averageTime = duration;
+        this._cachedData.callCount = this.record.callCountOrSamples;
+        this._cachedData.location = this.record.initiatorCallFrame || this.record.sourceCodeLocation;
+
</ins><span class="cx">         return this._cachedData;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -94,9 +80,9 @@
</span><span class="cx"> 
</span><span class="cx">         this._subtitle = "";
</span><span class="cx"> 
</span><del>-        if (this._record.eventType === WI.ScriptTimelineRecord.EventType.TimerInstalled) {
-            let timeoutString = Number.secondsToString(this._record.details.timeout / 1000);
-            if (this._record.details.repeating)
</del><ins>+        if (this.record.eventType === WI.ScriptTimelineRecord.EventType.TimerInstalled) {
+            let timeoutString = Number.secondsToString(this.record.details.timeout / 1000);
+            if (this.record.details.repeating)
</ins><span class="cx">                 this._subtitle = WI.UIString("%s interval").format(timeoutString);
</span><span class="cx">             else
</span><span class="cx">                 this._subtitle = WI.UIString("%s delay").format(timeoutString);
</span><span class="lines">@@ -105,35 +91,10 @@
</span><span class="cx">         return this._subtitle;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    updateRangeTimes(startTime, endTime)
</del><ins>+    createCellContent(columnIdentifier, cell)
</ins><span class="cx">     {
</span><del>-        var oldRangeStartTime = this._rangeStartTime;
-        var oldRangeEndTime = this._rangeEndTime;
</del><ins>+        const higherResolution = true;
</ins><span class="cx"> 
</span><del>-        if (oldRangeStartTime === startTime && oldRangeEndTime === endTime)
-            return;
-
-        this._rangeStartTime = startTime;
-        this._rangeEndTime = endTime;
-
-        // If we have no duration the range does not matter.
-        if (!this._record.duration)
-            return;
-
-        // We only need a refresh if the new range time changes the visible portion of this record.
-        var recordStart = this._record.startTime;
-        var recordEnd = this._record.startTime + this._record.duration;
-        var oldStartBoundary = Number.constrain(oldRangeStartTime, recordStart, recordEnd);
-        var oldEndBoundary = Number.constrain(oldRangeEndTime, recordStart, recordEnd);
-        var newStartBoundary = Number.constrain(startTime, recordStart, recordEnd);
-        var newEndBoundary = Number.constrain(endTime, recordStart, recordEnd);
-
-        if (oldStartBoundary !== newStartBoundary || oldEndBoundary !== newEndBoundary)
-            this.needsRefresh();
-    }
-
-    createCellContent(columnIdentifier, cell)
-    {
</del><span class="cx">         var value = this.data[columnIdentifier];
</span><span class="cx"> 
</span><span class="cx">         switch (columnIdentifier) {
</span><span class="lines">@@ -142,15 +103,19 @@
</span><span class="cx">             return this._createNameCellDocumentFragment();
</span><span class="cx"> 
</span><span class="cx">         case "startTime":
</span><del>-            return isNaN(value) ? emDash : Number.secondsToString(value - this._baseStartTime, true);
-
</del><span class="cx">         case "selfTime":
</span><span class="cx">         case "totalTime":
</span><span class="cx">         case "averageTime":
</span><del>-            return isNaN(value) ? emDash : Number.secondsToString(value, true);
</del><ins>+            return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution);
</ins><span class="cx"> 
</span><span class="cx">         case "callCount":
</span><span class="cx">             return isNaN(value) ? emDash : value.toLocaleString();
</span><ins>+
+        // Necessary to be displayed in WI.LayoutTimelineView.
+        case "width":
+        case "height":
+        case "area":
+            return zeroWidthSpace;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return super.createCellContent(columnIdentifier, cell);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSourceCodeTimelineTimelineDataGridNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js        2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js   2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -25,9 +25,10 @@
</span><span class="cx"> 
</span><span class="cx"> WI.SourceCodeTimelineTimelineDataGridNode = class SourceCodeTimelineTimelineDataGridNode extends WI.TimelineDataGridNode
</span><span class="cx"> {
</span><del>-    constructor(sourceCodeTimeline, graphDataSource)
</del><ins>+    constructor(sourceCodeTimeline, options = {})
</ins><span class="cx">     {
</span><del>-        super(true, graphDataSource);
</del><ins>+        const records = [];
+        super(records, {includesGraph: true, ...options});
</ins><span class="cx"> 
</span><span class="cx">         this._sourceCodeTimeline = sourceCodeTimeline;
</span><span class="cx">         this._sourceCodeTimeline.addEventListener(WI.Timeline.Event.RecordAdded, this._timelineRecordAdded, this);
</span><span class="lines">@@ -47,7 +48,12 @@
</span><span class="cx"> 
</span><span class="cx">     get data()
</span><span class="cx">     {
</span><del>-        return {graph: this._sourceCodeTimeline.startTime};
</del><ins>+        if (this._cachedData)
+            return this._cachedData;
+
+        this._cachedData = super.data;
+        this._cachedData.graph = this._sourceCodeTimeline.startTime;
+        return this._cachedData;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     createCellContent(columnIdentifier, cell)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTimelineDataGridNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineDataGridNode.js (243212 => 243213)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineDataGridNode.js  2019-03-20 16:47:55 UTC (rev 243212)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineDataGridNode.js     2019-03-20 17:43:05 UTC (rev 243213)
</span><span class="lines">@@ -25,16 +25,18 @@
</span><span class="cx"> 
</span><span class="cx"> WI.TimelineDataGridNode = class TimelineDataGridNode extends WI.DataGridNode
</span><span class="cx"> {
</span><del>-    constructor(includesGraph, graphDataSource, hasChildren)
</del><ins>+    constructor(records, options = {})
</ins><span class="cx">     {
</span><del>-        super({}, hasChildren);
</del><ins>+        super({}, options.hasChildren);
</ins><span class="cx"> 
</span><span class="cx">         this.copyable = false;
</span><span class="cx"> 
</span><del>-        this._includesGraph = includesGraph || false;
-        this._graphDataSource = graphDataSource || null;
</del><ins>+        this._records = records;
+        this._includesGraph = options.includesGraph || false;
+        this._graphDataSource = options.graphDataSource || null;
+        this._cachedData = null;
</ins><span class="cx"> 
</span><del>-        if (graphDataSource) {
</del><ins>+        if (this._graphDataSource) {
</ins><span class="cx">             this._graphContainerElement = document.createElement("div");
</span><span class="cx">             this._timelineRecordBars = [];
</span><span class="cx">         }
</span><span class="lines">@@ -42,17 +44,13 @@
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><ins>+    get records() { return this._records; }
+
</ins><span class="cx">     get record()
</span><span class="cx">     {
</span><span class="cx">         return this.records && this.records.length ? this.records[0] : null;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    get records()
-    {
-        // Implemented by subclasses.
-        return [];
-    }
-
</del><span class="cx">     get graphDataSource()
</span><span class="cx">     {
</span><span class="cx">         return this._graphDataSource;
</span><span class="lines">@@ -63,8 +61,9 @@
</span><span class="cx">         if (!this._graphDataSource)
</span><span class="cx">             return {};
</span><span class="cx"> 
</span><del>-        var records = this.records || [];
-        return {graph: records.length ? records[0].startTime : 0};
</del><ins>+        return {
+            graph: this.record ? this.record.startTime : 0,
+        };
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     collapse()
</span><span class="lines">@@ -207,6 +206,8 @@
</span><span class="cx"> 
</span><span class="cx">     refresh()
</span><span class="cx">     {
</span><ins>+        this._cachedData = null;
+
</ins><span class="cx">         if (this._graphDataSource && this._includesGraph)
</span><span class="cx">             this.needsGraphRefresh();
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>