WebKit Bugzilla
Attachment 358176 Details for
Bug 191901
: Web Inspector: Timelines: flatten the overview to show all records, one per line
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-191901-20190101174108.patch (text/plain), 88.97 KB, created by
Devin Rousso
on 2019-01-01 16:41:09 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Devin Rousso
Created:
2019-01-01 16:41:09 PST
Size:
88.97 KB
patch
obsolete
>diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog >index d0d8c6c2cb99a6a96941aac00f7af2287933ae7c..ec34c8d097811b38535ecdcd99de26307e30f99b 100644 >--- a/Source/WebInspectorUI/ChangeLog >+++ b/Source/WebInspectorUI/ChangeLog >@@ -1,3 +1,148 @@ >+2019-01-01 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: Timelines: flatten the overview to show all records, one per line >+ https://bugs.webkit.org/show_bug.cgi?id=191901 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * UserInterface/Views/TimelineDataGridNode.js: >+ (WI.TimelineDataGridNode.prototype.get records): >+ (WI.TimelineDataGridNode.prototype.get data): >+ (WI.TimelineDataGridNode.prototype.refresh): >+ Refactor `WI.TimelineDataGridNode` and its subclasses to use objects for optional parameters. >+ Unify the API surface of all of the `WI.TimelineDataGridNode` subclasses so that they can >+ all work nicely with the `WI.OverviewTimelineView`. >+ >+ * 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.graphDataSource.get startTime): >+ (WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar.graphDataSource.get currentTime): >+ (WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar.graphDataSource.get endTime): >+ (WI.ResourceTimelineDataGridNode.prototype._mouseoverRecordBar.graphDataSource.get _extraTimePadding): >+ (WI.ResourceTimelineDataGridNode.prototype.get records): Deleted. >+ * 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. >+ >+ * UserInterface/Views/ResourceTimingPopoverDataGridNode.js: >+ (WI.ResourceTimingPopoverDataGridNode): >+ (WI.ResourceTimingPopoverDataGridNode.prototype.get selectable): >+ (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): >+ (WI.SourceCodeTimelineTimelineDataGridNode.prototype.get data): >+ >+ * UserInterface/Views/OverviewTimelineView.js: >+ (WI.OverviewTimelineView): >+ (WI.OverviewTimelineView.groupBySourceCode): >+ (WI.OverviewTimelineView.prototype.closed): >+ (WI.OverviewTimelineView.prototype.get navigationItems): Added. >+ (WI.OverviewTimelineView.prototype.get selectionPathComponents): >+ (WI.OverviewTimelineView.prototype.reset): >+ (WI.OverviewTimelineView.prototype.layout): >+ (WI.OverviewTimelineView.prototype.get _relevantTimelines): Added. >+ (WI.OverviewTimelineView.prototype._addResourceToDataGridIfNeeded): >+ (WI.OverviewTimelineView.prototype._addSourceCodeTimeline): >+ (WI.OverviewTimelineView.prototype._processPendingRepresentedObjects): >+ (WI.OverviewTimelineView.prototype._handleGroupByResourceSettingChanged): Added. >+ (WI.OverviewTimelineView.prototype._handleGroupByResourceNavigationItemCheckedDidChange): Added. >+ (WI.OverviewTimelineView.prototype._handleTimelineRecordAdded): Added. >+ (WI.OverviewTimelineView.prototype._sourceCodeTimelineAdded): >+ (WI.OverviewTimelineView.prototype._networkTimelineRecordAdded): Deleted. >+ Listen for new records on all timelines. Add each record as a new line. Since each timeline >+ has different data to display, only show the "name" and "graph" for all records. >+ >+ * 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/RenderingFrameTimelineView.js: >+ (WI.RenderingFrameTimelineView.prototype._processPendingRecords): >+ * UserInterface/Views/ScriptDetailsTimelineView.js: >+ (WI.ScriptDetailsTimelineView.prototype.layout): >+ (WI.ScriptDetailsTimelineView.prototype._processPendingRecords): >+ >+ * UserInterface/Views/TimelineRecordBar.css: >+ (.timeline-record-bar.timeline-record-type-script.script-timeline-record-garbage-collected > .segment, .timeline-record-bar.timeline-record-type-heap-allocations > .segment): Added. >+ (.timeline-record-bar.timeline-record-type-script.script-timeline-record-garbage-collected > .segment): Deleted. >+ >+ * UserInterface/Models/TimelineRecording.js: >+ (WI.TimelineRecording.prototype.addRecord): >+ (WI.TimelineRecording.prototype._keyForRecord): >+ Drive-by: show Media timeline events under the owner frame's resource when grouped. >+ >+ * UserInterface/Main.html: >+ * UserInterface/Views/SourceCodeTimelineTreeElement.js: Removed. >+ > 2018-12-21 Devin Rousso <drousso@apple.com> > > Web Inspector: Styles Redesign: remove unused CSS style icons >diff --git a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >index aa78eeb05fb3e09d26342f7b42fbebef4a0d536d..c1ac3ec3bdc2ba57391a8132ac4c951ab1d8ac43 100644 >--- a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >+++ b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >@@ -460,6 +460,7 @@ localizedStrings["Global Lexical Environment"] = "Global Lexical Environment"; > localizedStrings["Global Variables"] = "Global Variables"; > localizedStrings["Grammar"] = "Grammar"; > localizedStrings["Group"] = "Group"; >+localizedStrings["Group By Resource"] = "Group By Resource"; > localizedStrings["Group Media Requests"] = "Group Media Requests"; > localizedStrings["Group by Event"] = "Group by Event"; > localizedStrings["Group by Node"] = "Group by Node"; >diff --git a/Source/WebInspectorUI/UserInterface/Base/Setting.js b/Source/WebInspectorUI/UserInterface/Base/Setting.js >index d0508a3317005c9354f571424d56ed90f61c17bd..a8bf599b37fe7d9cac703741629c7a7e2119de18 100644 >--- a/Source/WebInspectorUI/UserInterface/Base/Setting.js >+++ b/Source/WebInspectorUI/UserInterface/Base/Setting.js >@@ -126,6 +126,7 @@ WI.settings = { > showShadowDOM: new WI.Setting("show-shadow-dom", false), > showWhitespaceCharacters: new WI.Setting("show-whitespace-characters", false), > tabSize: new WI.Setting("tab-size", 4), >+ timelineOverviewGroupBySourceCode: new WI.Setting("timeline-overview-group-by-source-code", false), > zoomFactor: new WI.Setting("zoom-factor", 1), > > // Experimental >diff --git a/Source/WebInspectorUI/UserInterface/Main.html b/Source/WebInspectorUI/UserInterface/Main.html >index 0f3cca89e808bc9ffc676be437ae65c7160dcda2..95577ba2e0930ff192cd4a72bc6f1672a04db86a 100644 >--- a/Source/WebInspectorUI/UserInterface/Main.html >+++ b/Source/WebInspectorUI/UserInterface/Main.html >@@ -772,7 +772,6 @@ > <script src="Views/SoftContextMenu.js"></script> > <script src="Views/SourceCodeTextEditor.js"></script> > <script src="Views/SourceCodeTimelineTimelineDataGridNode.js"></script> >- <script src="Views/SourceCodeTimelineTreeElement.js"></script> > <script src="Views/SourceMapResourceTreeElement.js"></script> > <script src="Views/SpanningDataGridNode.js"></script> > >diff --git a/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js b/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js >index fc7587e82146757248c3380293a01b9b8ad3d869..3dbe625aa15f7fbe2fdd0e7749754fdbc47797c8 100644 >--- a/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js >+++ b/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js >@@ -212,16 +212,23 @@ WI.TimelineRecording = class TimelineRecording extends WI.Object > if (record.type === WI.TimelineRecord.Type.Network > || record.type === WI.TimelineRecord.Type.RenderingFrame > || record.type === WI.TimelineRecord.Type.Memory >- || record.type === WI.TimelineRecord.Type.HeapAllocations >- || record.type === WI.TimelineRecord.Type.Media) >+ || record.type === WI.TimelineRecord.Type.HeapAllocations) > return; > > if (!WI.TimelineRecording.sourceCodeTimelinesSupported()) > return; > > // Add the record to the source code timelines. >- var activeMainResource = WI.networkManager.mainFrame.provisionalMainResource || WI.networkManager.mainFrame.mainResource; >- var sourceCode = record.sourceCodeLocation ? record.sourceCodeLocation.sourceCode : activeMainResource; >+ let sourceCode = null; >+ if (record.sourceCodeLocation) >+ sourceCode = record.sourceCodeLocation.sourceCode; >+ else if (record.type === WI.TimelineRecord.Type.Media) { >+ if (record.domNode && record.domNode.frame) >+ sourceCode = record.domNode.frame.mainResource; >+ } >+ >+ if (!sourceCode) >+ sourceCode = WI.networkManager.mainFrame.provisionalMainResource || WI.networkManager.mainFrame.mainResource; > > var sourceCodeTimelines = this._sourceCodeTimelinesMap.get(sourceCode); > if (!sourceCodeTimelines) { >@@ -330,10 +337,18 @@ WI.TimelineRecording = class TimelineRecording extends WI.Object > _keyForRecord(record) > { > var key = record.type; >- if (record instanceof WI.ScriptTimelineRecord || record instanceof WI.LayoutTimelineRecord || record instanceof WI.MediaTimelineRecord) >+ if (record instanceof WI.ScriptTimelineRecord || record instanceof WI.LayoutTimelineRecord) > key += ":" + record.eventType; > if (record instanceof WI.ScriptTimelineRecord && record.eventType === WI.ScriptTimelineRecord.EventType.EventDispatched) > key += ":" + record.details; >+ if (record instanceof WI.MediaTimelineRecord) { >+ key += ":" + record.eventType; >+ if (record.eventType === WI.MediaTimelineRecord.EventType.DOMEvent) { >+ if (record.domEvent && record.domEvent.eventName) >+ key += ":" + record.domEvent.eventName; >+ } else if (record.eventType === WI.MediaTimelineRecord.EventType.LowPower) >+ key += ":" + (record.isLowPower ? "enabled" : "disabled"); >+ } > if (record.sourceCodeLocation) > key += ":" + record.sourceCodeLocation.lineNumber + ":" + record.sourceCodeLocation.columnNumber; > return key; >diff --git a/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineDataGridNode.js b/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineDataGridNode.js >index 393f4489a9a3e2701f804d3aef05a7f190127d92..ecf1798a665d34b2cd3c61bcd531a656dcb88ed3 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineDataGridNode.js >+++ b/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineDataGridNode.js >@@ -25,54 +25,68 @@ > > WI.HeapAllocationsTimelineDataGridNode = class HeapAllocationsTimelineDataGridNode extends WI.TimelineDataGridNode > { >- constructor(heapAllocationsTimelineRecord, zeroTime, heapAllocationsView) >+ constructor(record, options = {}) > { >- super(false, null); >+ console.assert(record instanceof WI.HeapAllocationsTimelineRecord); > >- this._record = heapAllocationsTimelineRecord; >- this._heapAllocationsView = heapAllocationsView; >+ super([record], options); > >- this._data = { >- name: this.displayName(), >- timestamp: zeroTime ? this._record.timestamp - zeroTime : NaN, >- size: this._record.heapSnapshot.totalSize, >- liveSize: this._record.heapSnapshot.liveSize, >- }; >+ this._heapAllocationsView = options.heapAllocationsView; > >- this._record.heapSnapshot.addEventListener(WI.HeapSnapshotProxy.Event.CollectedNodes, this._heapSnapshotCollectedNodes, this); >- this._record.heapSnapshot.addEventListener(WI.HeapSnapshotProxy.Event.Invalidated, this._heapSnapshotInvalidated, this); >+ this.heapSnapshot.addEventListener(WI.HeapSnapshotProxy.Event.CollectedNodes, this._handleHeapSnapshotCollectedNodes, this); >+ this.heapSnapshot.addEventListener(WI.HeapSnapshotProxy.Event.Invalidated, this._handleHeapSnapshotInvalidated, this); > } > > // Public > >- get record() { return this._record; } >- get data() { return this._data; } >+ get heapSnapshot() >+ { >+ return this.record.heapSnapshot; >+ } >+ >+ 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; >+ } > > createCellContent(columnIdentifier, cell) > { >+ const higherResolution = true; >+ >+ let value = this.data[columnIdentifier]; >+ > switch (columnIdentifier) { > case "name": > cell.classList.add(...this.iconClassNames()); > > var fragment = document.createDocumentFragment(); > var titleElement = fragment.appendChild(document.createElement("span")); >- titleElement.textContent = this._data.name; >- if (!this._record.heapSnapshot.invalid) { >+ titleElement.textContent = value; >+ >+ if (this._heapAllocationsView && !this.heapSnapshot.invalid) { > var goToButton = fragment.appendChild(WI.createGoToArrowButton()); > goToButton.addEventListener("click", (event) => { >- this._heapAllocationsView.showHeapSnapshotTimelineRecord(this._record); >+ this._heapAllocationsView.showHeapSnapshotTimelineRecord(this.record); > }); > } >+ > return fragment; > >- case "timestamp": >- return isNaN(this._data.timestamp) ? emDash : Number.secondsToString(this._data.timestamp, true); >+ case "timestamp": { >+ return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution); >+ } > > case "size": >- return Number.bytesToString(this._data.size); >- > case "liveSize": >- return Number.bytesToString(this._data.liveSize); >+ return Number.bytesToString(value, higherResolution); > } > > return super.createCellContent(columnIdentifier, cell); >@@ -88,42 +102,25 @@ WI.HeapAllocationsTimelineDataGridNode = class HeapAllocationsTimelineDataGridNo > this.element.classList.remove("baseline"); > } > >- updateTimestamp(zeroTime) >- { >- console.assert(isNaN(this._data.timestamp)); >- this._data.timestamp = this._record.timestamp - zeroTime; >- this.needsRefresh(); >- } >- > // Protected > > createCells() > { > super.createCells(); > >- if (this._record.heapSnapshot.invalid) >+ if (this.heapSnapshot.invalid) > this.element.classList.add("invalid"); > } > > // Private > >- _heapSnapshotCollectedNodes() >+ _handleHeapSnapshotCollectedNodes() > { >- let oldSize = this._data.liveSize; >- let newSize = this._record.heapSnapshot.liveSize; >- >- console.assert(newSize <= oldSize); >- if (oldSize === newSize) >- return; >- >- this._data.liveSize = newSize; > this.needsRefresh(); > } > >- _heapSnapshotInvalidated() >+ _handleHeapSnapshotInvalidated() > { >- this._data.liveSize = 0; >- > this.needsRefresh(); > } > }; >diff --git a/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js b/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js >index 73a604c7fbb4cfb0a2d476a5ff3410715a4c28d0..5499fd0bf1be3332da644278b2c3a3d56cc630ba 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js >+++ b/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js >@@ -96,7 +96,6 @@ WI.HeapAllocationsTimelineView = class HeapAllocationsTimelineView extends WI.Ti > WI.ContentView.addEventListener(WI.ContentView.Event.SelectionPathComponentsDidChange, this._contentViewSelectionPathComponentDidChange, this); > > this._pendingRecords = []; >- this._pendingZeroTimeDataGridNodes = []; > > timeline.addEventListener(WI.Timeline.Event.RecordAdded, this._heapAllocationsTimelineRecordAdded, this); > >@@ -258,19 +257,12 @@ WI.HeapAllocationsTimelineView = class HeapAllocationsTimelineView extends WI.Ti > > layout() > { >- 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) { >+ if (this._pendingRecords.length && this.zeroTime) { > for (let heapAllocationsTimelineRecord of this._pendingRecords) { >- let dataGridNode = new WI.HeapAllocationsTimelineDataGridNode(heapAllocationsTimelineRecord, this.zeroTime, this); >- this._dataGrid.addRowInSortOrder(dataGridNode); >- if (!this.zeroTime) >- this._pendingZeroTimeDataGridNodes.push(dataGridNode); >+ this._dataGrid.addRowInSortOrder(new WI.HeapAllocationsTimelineDataGridNode(heapAllocationsTimelineRecord, { >+ graphDataSource: this, >+ heapAllocationsView: this, >+ })); > } > > this._pendingRecords = []; >@@ -286,7 +278,6 @@ WI.HeapAllocationsTimelineView = class HeapAllocationsTimelineView extends WI.Ti > > this.showHeapSnapshotList(); > this._pendingRecords = []; >- this._pendingZeroTimeDataGridNodes = []; > this._updateCompareHeapSnapshotButton(); > } > >diff --git a/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js b/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js >index 725da09f200360fd9fdcb934a197abecd286bae9..2f824be2bdafbcfcf2fa732063828fd7b488e5af 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js >+++ b/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js >@@ -25,42 +25,36 @@ > > WI.LayoutTimelineDataGridNode = class LayoutTimelineDataGridNode extends WI.TimelineDataGridNode > { >- constructor(layoutTimelineRecord, baseStartTime) >+ constructor(record, options = {}) > { >- super(false, null); >+ console.assert(record instanceof WI.LayoutTimelineRecord); > >- this._record = layoutTimelineRecord; >- this._baseStartTime = baseStartTime || 0; >+ super([record], options); > } > > // Public > >- get records() >- { >- return [this._record]; >- } >- > get data() > { >- 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, >- }; >- } >+ if (this._cachedData) >+ return this._cachedData; > >+ 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; > return this._cachedData; > } > > createCellContent(columnIdentifier, cell) > { > var value = this.data[columnIdentifier]; >+ const higherResolution = true; > > switch (columnIdentifier) { > case "name": >@@ -75,10 +69,10 @@ WI.LayoutTimelineDataGridNode = class LayoutTimelineDataGridNode extends WI.Time > return isNaN(value) ? emDash : WI.UIString("%dpx\u00B2").format(value); > > case "startTime": >- return isNaN(value) ? emDash : Number.secondsToString(value - this._baseStartTime, true); >+ return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution); > > case "totalTime": >- return isNaN(value) ? emDash : Number.secondsToString(value, true); >+ return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution); > } > > return super.createCellContent(columnIdentifier, cell); >diff --git a/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js b/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js >index c117240cc919e7ff5cdb15648f6f4f117e2ff06e..235c3f453e6f91a9f8bb87ee65b146e685aac81d 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js >+++ b/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js >@@ -201,7 +201,9 @@ WI.LayoutTimelineView = class LayoutTimelineView extends WI.TimelineView > return; > > for (var layoutTimelineRecord of this._pendingRecords) { >- let dataGridNode = new WI.LayoutTimelineDataGridNode(layoutTimelineRecord, this.zeroTime); >+ let dataGridNode = new WI.LayoutTimelineDataGridNode(layoutTimelineRecord, { >+ graphDataSource: this, >+ }); > > this._dataGrid.addRowInSortOrder(dataGridNode); > >@@ -214,14 +216,24 @@ WI.LayoutTimelineView = class LayoutTimelineView extends WI.TimelineView > } > > let childRecord = entry.children[entry.index]; >- console.assert(childRecord.type === WI.TimelineRecord.Type.Layout, childRecord); > >- let childDataGridNode = new WI.LayoutTimelineDataGridNode(childRecord, this.zeroTime); >+ 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); >+ } >+ > console.assert(entry.parentDataGridNode, "Missing parent node for entry.", entry); > this._dataGrid.addRowInSortOrder(childDataGridNode, entry.parentDataGridNode); > > if (childDataGridNode && childRecord.children.length) > stack.push({children: childRecord.children, parentDataGridNode: childDataGridNode, index: 0}); >+ > ++entry.index; > } > } >diff --git a/Source/WebInspectorUI/UserInterface/Views/MediaTimelineDataGridNode.js b/Source/WebInspectorUI/UserInterface/Views/MediaTimelineDataGridNode.js >index a18f471a5de06a1300d2f6176c03e2dc2e85a888..6cf4e6ba4db28206f1bea0097e37cb9ae42e9ee5 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/MediaTimelineDataGridNode.js >+++ b/Source/WebInspectorUI/UserInterface/Views/MediaTimelineDataGridNode.js >@@ -25,20 +25,15 @@ > > WI.MediaTimelineDataGridNode = class MediaTimelineDataGridNode extends WI.TimelineDataGridNode > { >- constructor(record, graphDataSource) >+ constructor(record, options = {}) > { > console.assert(record instanceof WI.MediaTimelineRecord); > >- const includesGraph = false; >- super(includesGraph, graphDataSource); >- >- this._records = [record]; >+ super([record], options); > } > > // Public > >- get records() { return this._records; } >- > get data() > { > if (this._cachedData) >diff --git a/Source/WebInspectorUI/UserInterface/Views/MediaTimelineView.js b/Source/WebInspectorUI/UserInterface/Views/MediaTimelineView.js >index 3b402dcd5f815cdf6d85267e1964e884649bd15d..94e543912f274b17c14de1f1376d0e9569c48212 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/MediaTimelineView.js >+++ b/Source/WebInspectorUI/UserInterface/Views/MediaTimelineView.js >@@ -183,7 +183,9 @@ WI.MediaTimelineView = class MediaTimelineView extends WI.TimelineView > if (timelineRecord.domEvent && timelineRecord.domEvent.originator) > this._dataGrid.setColumnVisible("originator", true); > >- this._dataGrid.addRowInSortOrder(new WI.MediaTimelineDataGridNode(timelineRecord, this)); >+ this._dataGrid.addRowInSortOrder(new WI.MediaTimelineDataGridNode(timelineRecord, { >+ graphDataSource: this, >+ })); > } > > this._pendingRecords = []; >diff --git a/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js b/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js >index f65a495cfb3e0aea760def530fc3f4c657efaee9..7d104431b69f51b41549dd0680c1fd809cffd406 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js >+++ b/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js >@@ -254,9 +254,11 @@ WI.NetworkTimelineView = class NetworkTimelineView extends WI.TimelineView > if (dataGridNode) > continue; > >- const includesGraph = false; >- const shouldShowPopover = true; >- dataGridNode = new WI.ResourceTimelineDataGridNode(resourceTimelineRecord, includesGraph, this, shouldShowPopover); >+ dataGridNode = new WI.ResourceTimelineDataGridNode(resourceTimelineRecord, { >+ graphDataSource: this, >+ shouldShowPopover: true, >+ }); >+ > this._resourceDataGridNodeMap.set(resourceTimelineRecord.resource, dataGridNode); > > this._dataGrid.addRowInSortOrder(dataGridNode); >diff --git a/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js b/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js >index a895b77f512fd6027e8c7512cad50f6a2ed3b548..ef4a8a75f5bd9edd91526d8fa0e2a87d82325654 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js >+++ b/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js >@@ -27,25 +27,38 @@ WI.OverviewTimelineView = class OverviewTimelineView extends WI.TimelineView > { > constructor(recording, extraArguments) > { >+ console.assert(recording instanceof WI.TimelineRecording); >+ > super(recording, extraArguments); > > this._recording = recording; >+ this._pendingRepresentedObjects = []; >+ this._resourceDataGridNodeMap = new Map; >+ >+ if (WI.TimelineRecording.sourceCodeTimelinesSupported()) { >+ WI.settings.timelineOverviewGroupBySourceCode.addEventListener(WI.Setting.Event.Changed, this._handleGroupBySourceCodeSettingChanged, this); >+ >+ this._groupBySourceCodeNavigationItem = new WI.CheckboxNavigationItem("overview-timeline-group-by-resource", WI.UIString("Group By Resource"), WI.settings.timelineOverviewGroupBySourceCode.value); >+ this._groupBySourceCodeNavigationItem.addEventListener(WI.CheckboxNavigationItem.Event.CheckedDidChange, this._handleGroupBySourceCodeNavigationItemCheckedDidChange, this); >+ } > > let columns = {name: {}, graph: {}}; > > columns.name.title = WI.UIString("Name"); > columns.name.width = "20%"; > columns.name.icon = true; >- columns.name.disclosure = true; >+ columns.name.locked = true; >+ if (WI.OverviewTimelineView.groupBySourceCode()) >+ columns.name.disclosure = true; > > this._timelineRuler = new WI.TimelineRuler; > this._timelineRuler.allowsClippedLabels = true; > > columns.graph.width = "80%"; > columns.graph.headerView = this._timelineRuler; >+ columns.graph.locked = true; > >- this._dataGrid = new WI.DataGrid(columns); >- >+ this._dataGrid = new WI.TimelineDataGrid(columns); > this.setupDataGrid(this._dataGrid); > > this._currentTimeMarker = new WI.TimelineMarker(0, WI.TimelineMarker.Type.CurrentTime); >@@ -54,16 +67,19 @@ WI.OverviewTimelineView = class OverviewTimelineView extends WI.TimelineView > this.element.classList.add("overview"); > this.addSubview(this._dataGrid); > >- this._networkTimeline = recording.timelines.get(WI.TimelineRecord.Type.Network); >- if (this._networkTimeline) >- this._networkTimeline.addEventListener(WI.Timeline.Event.RecordAdded, this._networkTimelineRecordAdded, this); >+ for (let timeline of this._relevantTimelines) >+ timeline.addEventListener(WI.Timeline.Event.RecordAdded, this._handleTimelineRecordAdded, this); > > recording.addEventListener(WI.TimelineRecording.Event.SourceCodeTimelineAdded, this._sourceCodeTimelineAdded, this); > recording.addEventListener(WI.TimelineRecording.Event.MarkerAdded, this._markerAdded, this); > recording.addEventListener(WI.TimelineRecording.Event.Reset, this._recordingReset, this); >+ } > >- this._pendingRepresentedObjects = []; >- this._resourceDataGridNodeMap = new Map; >+ // Static >+ >+ static groupBySourceCode() >+ { >+ return WI.TimelineRecording.sourceCodeTimelinesSupported() && WI.settings.timelineOverviewGroupBySourceCode.value; > } > > // Public >@@ -87,11 +103,20 @@ WI.OverviewTimelineView = class OverviewTimelineView extends WI.TimelineView > > closed() > { >- if (this._networkTimeline) >- this._networkTimeline.removeEventListener(null, null, this); >+ for (let timeline of this._recording.timelines.values()) >+ timeline.removeEventListener(null, null, this); >+ > this._recording.removeEventListener(null, null, this); > } > >+ get navigationItems() >+ { >+ let navigationItems = []; >+ if (this._groupBySourceCodeNavigationItem) >+ navigationItems.push(this._groupBySourceCodeNavigationItem); >+ return navigationItems; >+ } >+ > get selectionPathComponents() > { > let dataGridNode = this._dataGrid.selectedNode; >@@ -118,9 +143,10 @@ WI.OverviewTimelineView = class OverviewTimelineView extends WI.TimelineView > { > super.reset(); > >- this._dataGrid.removeChildren(); >+ this._dataGrid.reset(); > > this._pendingRepresentedObjects = []; >+ this._resourceDataGridNodeMap.clear(); > } > > // Protected >@@ -160,6 +186,17 @@ WI.OverviewTimelineView = class OverviewTimelineView extends WI.TimelineView > > // Private > >+ get _relevantTimelines() >+ { >+ let timelines = []; >+ for (let [type, timeline] of this._recording.timelines) { >+ if (type === WI.TimelineRecord.Type.RenderingFrame || type === WI.TimelineRecord.Type.Memory) >+ continue; >+ timelines.push(timeline); >+ } >+ return timelines; >+ } >+ > _compareDataGridNodesByStartTime(a, b) > { > function getStartTime(dataGridNode) >@@ -200,54 +237,63 @@ WI.OverviewTimelineView = class OverviewTimelineView extends WI.TimelineView > > // FIXME: replace with this._dataGrid.findDataGridNode(resource) once <https://webkit.org/b/155305> is fixed. > let dataGridNode = this._resourceDataGridNodeMap.get(resource); >- if (dataGridNode) >- return dataGridNode; >+ if (!dataGridNode) { >+ let resourceTimelineRecord = this._networkTimeline ? this._networkTimeline.recordForResource(resource) : null; >+ if (!resourceTimelineRecord) >+ resourceTimelineRecord = new WI.ResourceTimelineRecord(resource); > >- let parentFrame = resource.parentFrame; >- if (!parentFrame) >- return null; >- >- let resourceTimelineRecord = this._networkTimeline ? this._networkTimeline.recordForResource(resource) : null; >- if (!resourceTimelineRecord) >- resourceTimelineRecord = new WI.ResourceTimelineRecord(resource); >- >- const includesGraph = true; >- const shouldShowPopover = false; >- let resourceDataGridNode = new WI.ResourceTimelineDataGridNode(resourceTimelineRecord, includesGraph, this, shouldShowPopover); >- this._resourceDataGridNodeMap.set(resource, resourceDataGridNode); >- >- let expandedByDefault = false; >- if (parentFrame.mainResource === resource || parentFrame.provisionalMainResource === resource) { >- parentFrame = parentFrame.parentFrame; >- expandedByDefault = !parentFrame; // Main frame expands by default. >+ dataGridNode = new WI.ResourceTimelineDataGridNode(resourceTimelineRecord, { >+ graphDataSource: this, >+ includesGraph: true, >+ }); >+ this._resourceDataGridNodeMap.set(resource, dataGridNode); > } > >- if (expandedByDefault) >- resourceDataGridNode.expand(); >- >- let parentDataGridNode = null; >- if (parentFrame) { >- // Find the parent main resource, adding it if needed, to append this resource as a child. >- let parentResource = parentFrame.provisionalMainResource || parentFrame.mainResource; >- >- parentDataGridNode = this._addResourceToDataGridIfNeeded(parentResource); >- console.assert(parentDataGridNode); >- if (!parentDataGridNode) >+ if (!dataGridNode.parent) { >+ let parentFrame = resource.parentFrame; >+ if (!parentFrame) > return null; >+ >+ let expandedByDefault = false; >+ if (parentFrame.mainResource === resource || parentFrame.provisionalMainResource === resource) { >+ parentFrame = parentFrame.parentFrame; >+ expandedByDefault = !parentFrame; // Main frame expands by default. >+ } >+ >+ if (expandedByDefault) >+ dataGridNode.expand(); >+ >+ let parentDataGridNode = null; >+ if (parentFrame) { >+ // Find the parent main resource, adding it if needed, to append this resource as a child. >+ let parentResource = parentFrame.provisionalMainResource || parentFrame.mainResource; >+ >+ parentDataGridNode = this._addResourceToDataGridIfNeeded(parentResource); >+ console.assert(parentDataGridNode); >+ if (!parentDataGridNode) >+ return null; >+ } >+ >+ this._insertDataGridNode(dataGridNode, parentDataGridNode); > } > >- this._insertDataGridNode(resourceDataGridNode, parentDataGridNode); >- >- return resourceDataGridNode; >+ return dataGridNode; > } > > _addSourceCodeTimeline(sourceCodeTimeline) > { >- let parentDataGridNode = sourceCodeTimeline.sourceCodeLocation ? this._addResourceToDataGridIfNeeded(sourceCodeTimeline.sourceCode) : null; >- let sourceCodeTimelineDataGridNode = new WI.SourceCodeTimelineTimelineDataGridNode(sourceCodeTimeline, this); >- this._resourceDataGridNodeMap.set(sourceCodeTimeline, sourceCodeTimelineDataGridNode); >+ let dataGridNode = this._resourceDataGridNodeMap.get(sourceCodeTimeline); >+ if (!dataGridNode) { >+ dataGridNode = new WI.SourceCodeTimelineTimelineDataGridNode(sourceCodeTimeline, { >+ graphDataSource: this, >+ }); >+ this._resourceDataGridNodeMap.set(sourceCodeTimeline, dataGridNode); >+ } > >- this._insertDataGridNode(sourceCodeTimelineDataGridNode, parentDataGridNode); >+ if (!dataGridNode.parent) { >+ let parentDataGridNode = sourceCodeTimeline.sourceCodeLocation ? this._addResourceToDataGridIfNeeded(sourceCodeTimeline.sourceCode) : null; >+ this._insertDataGridNode(dataGridNode, parentDataGridNode); >+ } > } > > _processPendingRepresentedObjects() >@@ -256,32 +302,105 @@ WI.OverviewTimelineView = class OverviewTimelineView extends WI.TimelineView > return; > > for (var representedObject of this._pendingRepresentedObjects) { >- if (representedObject instanceof WI.Resource) >- this._addResourceToDataGridIfNeeded(representedObject); >- else if (representedObject instanceof WI.SourceCodeTimeline) >- this._addSourceCodeTimeline(representedObject); >- else >- console.error("Unknown represented object"); >+ if (WI.OverviewTimelineView.groupBySourceCode()) { >+ if (representedObject instanceof WI.Resource) >+ this._addResourceToDataGridIfNeeded(representedObject); >+ else if (representedObject instanceof WI.SourceCodeTimeline) >+ this._addSourceCodeTimeline(representedObject); >+ else >+ console.error("Unknown represented object"); >+ } else { >+ const options = { >+ graphDataSource: this, >+ shouldShowPopover: true, >+ }; >+ >+ let dataGridNode = null; >+ if (representedObject instanceof WI.ResourceTimelineRecord) >+ dataGridNode = new WI.ResourceTimelineDataGridNode(representedObject, options); >+ else if (representedObject instanceof WI.LayoutTimelineRecord) >+ dataGridNode = new WI.LayoutTimelineDataGridNode(representedObject, options); >+ else if (representedObject instanceof WI.MediaTimelineRecord) >+ dataGridNode = new WI.MediaTimelineDataGridNode(representedObject, options); >+ else if (representedObject instanceof WI.ScriptTimelineRecord) >+ dataGridNode = new WI.ScriptTimelineDataGridNode(representedObject, options); >+ else if (representedObject instanceof WI.HeapAllocationsTimelineRecord) >+ dataGridNode = new WI.HeapAllocationsTimelineDataGridNode(representedObject, options); >+ >+ console.assert(dataGridNode, representedObject); >+ if (!dataGridNode) >+ continue; >+ >+ let comparator = (a, b) => { >+ return a.record.startTime - b.record.startTime; >+ }; >+ >+ this._dataGrid.insertChild(dataGridNode, insertionIndexForObjectInListSortedByFunction(dataGridNode, this._dataGrid.children, comparator)); >+ } > } > > this._pendingRepresentedObjects = []; > } > >- _networkTimelineRecordAdded(event) >+ _handleGroupBySourceCodeSettingChanged(event) > { >- var resourceTimelineRecord = event.data.record; >- console.assert(resourceTimelineRecord instanceof WI.ResourceTimelineRecord); >+ let groupBySourceCode = WI.OverviewTimelineView.groupBySourceCode(); >+ this._dataGrid.disclosureColumnIdentifier = groupBySourceCode ? "name" : undefined; >+ if (this._groupBySourceCodeNavigationItem) >+ this._groupBySourceCodeNavigationItem.checked = groupBySourceCode; > >- this._pendingRepresentedObjects.push(resourceTimelineRecord.resource); >+ this._pendingRepresentedObjects = []; >+ this._dataGrid.removeChildren(); >+ >+ if (groupBySourceCode) { >+ let networkTimeline = this._recording.timelines.get(WI.TimelineRecord.Type.Network); >+ if (networkTimeline) >+ this._pendingRepresentedObjects = this._pendingRepresentedObjects.concat(networkTimeline.records.map((record) => record.resource)); >+ >+ for (let [key, dataGridNode] of this._resourceDataGridNodeMap) { >+ dataGridNode.removeChildren(); >+ >+ if (key instanceof WI.SourceCodeTimeline) >+ this._pendingRepresentedObjects.push(key); >+ } >+ } else { >+ for (let timeline of this._relevantTimelines) >+ this._pendingRepresentedObjects = this._pendingRepresentedObjects.concat(timeline.records); >+ } > > this.needsLayout(); >+ } > >- // We don't expect to have any source code timelines yet. Those should be added with _sourceCodeTimelineAdded. >- console.assert(!this._recording.sourceCodeTimelinesForSourceCode(resourceTimelineRecord.resource).length); >+ _handleGroupBySourceCodeNavigationItemCheckedDidChange(event) >+ { >+ WI.settings.timelineOverviewGroupBySourceCode.value = !WI.settings.timelineOverviewGroupBySourceCode.value; >+ } >+ >+ _handleTimelineRecordAdded(event) >+ { >+ let {record} = event.data; >+ >+ if (WI.OverviewTimelineView.groupBySourceCode()) { >+ if (event.target.type !== WI.TimelineRecord.Type.Network) >+ return; >+ >+ console.assert(record instanceof WI.ResourceTimelineRecord); >+ >+ this._pendingRepresentedObjects.push(record.resource); >+ >+ // We don't expect to have any source code timelines yet. Those should be added with _sourceCodeTimelineAdded. >+ console.assert(!this._recording.sourceCodeTimelinesForSourceCode(record.resource).length); >+ } else >+ this._pendingRepresentedObjects.push(record); >+ >+ this.needsLayout(); > } > > _sourceCodeTimelineAdded(event) > { >+ if (!WI.OverviewTimelineView.groupBySourceCode()) >+ return; >+ > var sourceCodeTimeline = event.data.sourceCodeTimeline; > console.assert(sourceCodeTimeline); > if (!sourceCodeTimeline) >diff --git a/Source/WebInspectorUI/UserInterface/Views/ProfileNodeDataGridNode.js b/Source/WebInspectorUI/UserInterface/Views/ProfileNodeDataGridNode.js >index 01645d1b720c4a7c8264659dfd154c7bfe912c5c..3d3969c1c17c4274335468f6356beb5f12ab89fa 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/ProfileNodeDataGridNode.js >+++ b/Source/WebInspectorUI/UserInterface/Views/ProfileNodeDataGridNode.js >@@ -25,93 +25,53 @@ > > WI.ProfileNodeDataGridNode = class ProfileNodeDataGridNode extends WI.TimelineDataGridNode > { >- constructor(profileNode, baseStartTime, rangeStartTime, rangeEndTime) >+ constructor(profileNode, options = {}) > { >- var hasChildren = !!profileNode.childNodes.length; >+ console.assert(profileNode instanceof WI.ProfileNode); > >- super(false, null, hasChildren); >+ options.hasChildren = !!profileNode.childNodes.length; >+ >+ super(null, options); > > this._profileNode = profileNode; >- this._baseStartTime = baseStartTime || 0; >- this._rangeStartTime = rangeStartTime || 0; >- this._rangeEndTime = typeof rangeEndTime === "number" ? rangeEndTime : Infinity; >- >- this._cachedData = null; > > this.addEventListener("populate", this._populate, this); > } > > // Public > >- get profileNode() >- { >- return this._profileNode; >- } >- >- get records() >- { >- return null; >- } >- >- get baseStartTime() >- { >- return this._baseStartTime; >- } >- >- get rangeStartTime() >- { >- return this._rangeStartTime; >- } >- >- get rangeEndTime() >- { >- return this._rangeEndTime; >- } >+ get profileNode() { return this._profileNode; } > > 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; >+ if (this._cachedData) >+ return this._cachedData; >+ >+ let baseStartTime = 0; >+ let rangeStartTime = 0; >+ let rangeEndTime = Infinity; >+ if (this.graphDataSource) { >+ baseStartTime = this.graphDataSource.zeroTime; >+ rangeStartTime = this.graphDataSource.startTime; >+ rangeEndTime = this.graphDataSource.endTime; > } > >+ let callInfo = this._profileNode.computeCallInfoForTimeRange(rangeStartTime, rangeEndTime); >+ >+ 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; >+ > return this._cachedData; > } > >- updateRangeTimes(startTime, endTime) >- { >- var oldRangeStartTime = this._rangeStartTime; >- var oldRangeEndTime = this._rangeEndTime; >- >- 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) > { >+ const higherResolution = true; >+ > var value = this.data[columnIdentifier]; > > switch (columnIdentifier) { >@@ -120,12 +80,10 @@ WI.ProfileNodeDataGridNode = class ProfileNodeDataGridNode extends WI.TimelineDa > return value; > > case "startTime": >- return isNaN(value) ? emDash : Number.secondsToString(value - this._baseStartTime, true); >- > case "selfTime": > case "totalTime": > case "averageTime": >- return isNaN(value) ? emDash : Number.secondsToString(value, true); >+ return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution); > } > > return super.createCellContent(columnIdentifier, cell); >@@ -186,6 +144,8 @@ WI.ProfileNodeDataGridNode = class ProfileNodeDataGridNode extends WI.TimelineDa > this.removeChildren(); > > for (let node of this._profileNode.childNodes) >- this.appendChild(new WI.ProfileNodeDataGridNode(node, this.baseStartTime, this.rangeStartTime, this.rangeEndTime)); >+ this.appendChild(new WI.ProfileNodeDataGridNode(node, { >+ graphDataSource: this.graphDataSource, >+ })); > } > }; >diff --git a/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineDataGridNode.js b/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineDataGridNode.js >index 1b0f2bc31b4a55dc24d5c45d8bf177e10dd29861..5208a094f8fc76c6cac511ca8df32d5fa2776409 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineDataGridNode.js >+++ b/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineDataGridNode.js >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2015 Apple Inc. All rights reserved. >+ * Copyright (C) 2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -25,45 +25,35 @@ > > WI.RenderingFrameTimelineDataGridNode = class RenderingFrameTimelineDataGridNode extends WI.TimelineDataGridNode > { >- constructor(renderingFrameTimelineRecord, baseStartTime) >+ constructor(record, options = {}) > { >- super(false, null); >+ console.assert(record instanceof WI.RenderingFrameTimelineRecord); > >- this._record = renderingFrameTimelineRecord; >- this._baseStartTime = baseStartTime || 0; >+ super([record], options); > } > > // Public > >- get records() >- { >- return [this._record]; >- } >- > get data() > { >- 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, >- }; >- } >+ if (this._cachedData) >+ return this._cachedData; > >+ 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); > return this._cachedData; > } > > createCellContent(columnIdentifier, cell) > { >+ const higherResolution = true; >+ > var value = this.data[columnIdentifier]; > > switch (columnIdentifier) { >@@ -72,14 +62,14 @@ WI.RenderingFrameTimelineDataGridNode = class RenderingFrameTimelineDataGridNode > return value; > > case "startTime": >- return isNaN(value) ? emDash : Number.secondsToString(value - this._baseStartTime, true); >+ return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution); > > case "scriptTime": > case "layoutTime": > case "paintTime": > case "otherTime": > case "totalTime": >- return (isNaN(value) || value === 0) ? emDash : Number.secondsToString(value, true); >+ return (isNaN(value) || value === 0) ? emDash : Number.secondsToString(value, higherResolution); > } > > return super.createCellContent(columnIdentifier, cell); >diff --git a/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js b/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js >index 68e0d02fc456c5487cbe16aa0cc99a80ab641a73..137eb80036801f418f00e2672a91bef671ea1949 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js >+++ b/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js >@@ -232,7 +232,9 @@ WI.RenderingFrameTimelineView = class RenderingFrameTimelineView extends WI.Time > for (let renderingFrameTimelineRecord of this._pendingRecords) { > console.assert(renderingFrameTimelineRecord instanceof WI.RenderingFrameTimelineRecord); > >- let dataGridNode = new WI.RenderingFrameTimelineDataGridNode(renderingFrameTimelineRecord, this.zeroTime); >+ let dataGridNode = new WI.RenderingFrameTimelineDataGridNode(renderingFrameTimelineRecord, { >+ graphDataSource: this, >+ }); > this._dataGrid.addRowInSortOrder(dataGridNode); > > let stack = [{children: renderingFrameTimelineRecord.children, parentDataGridNode: dataGridNode, index: 0}]; >@@ -246,7 +248,9 @@ WI.RenderingFrameTimelineView = class RenderingFrameTimelineView extends WI.Time > let childRecord = entry.children[entry.index]; > let childDataGridNode = null; > if (childRecord.type === WI.TimelineRecord.Type.Layout) { >- childDataGridNode = new WI.LayoutTimelineDataGridNode(childRecord, this.zeroTime); >+ childDataGridNode = new WI.LayoutTimelineDataGridNode(childRecord, { >+ graphDataSource: this, >+ }); > > this._dataGrid.addRowInSortOrder(childDataGridNode, entry.parentDataGridNode); > } else if (childRecord.type === WI.TimelineRecord.Type.Script) { >@@ -256,12 +260,16 @@ WI.RenderingFrameTimelineView = class RenderingFrameTimelineView extends WI.Time > rootNodes = childRecord.profile.topDownRootNodes; > } > >- childDataGridNode = new WI.ScriptTimelineDataGridNode(childRecord, this.zeroTime); >+ childDataGridNode = new WI.ScriptTimelineDataGridNode(childRecord, { >+ graphDataSource: this, >+ }); > > this._dataGrid.addRowInSortOrder(childDataGridNode, entry.parentDataGridNode); > > for (let profileNode of rootNodes) { >- let profileNodeDataGridNode = new WI.ProfileNodeDataGridNode(profileNode, this.zeroTime, this.startTime, this.endTime); >+ let profileNodeDataGridNode = new WI.ProfileNodeDataGridNode(profileNode, { >+ graphDataSource: this, >+ }); > this._dataGrid.addRowInSortOrder(profileNodeDataGridNode, childDataGridNode); > } > } >diff --git a/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.css b/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.css >index 13b058c695f2ced7da2c30a466c7799ff55a989a..ea80137c6ddec8db14ea7c3d9fd038eb21abe1fc 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.css >+++ b/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.css >@@ -37,7 +37,7 @@ > } > > .resource-timing-popover-content .data-grid td.graph-column { >- padding: 4px 0 0; >+ padding: 4px 2px 0; > } > > .resource-timing-popover-content .data-grid table.data { >diff --git a/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js b/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js >index 7559642c1b0913150a6cc5cef79179ec83359866..0f0004fb6d2bf84fd221e11ef7b2e7a6cab0b3cf 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js >+++ b/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js >@@ -25,37 +25,32 @@ > > WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI.TimelineDataGridNode > { >- constructor(resourceTimelineRecord, includesGraph, graphDataSource, shouldShowPopover) >+ constructor(record, options = {}) > { >- super(includesGraph, graphDataSource); >+ console.assert(record instanceof WI.ResourceTimelineRecord); > >- this._resource = resourceTimelineRecord.resource; >- this._record = resourceTimelineRecord; >- this._shouldShowPopover = shouldShowPopover; >+ super([record], options); > >- 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); >+ this._shouldShowPopover = options.shouldShowPopover; > >- if (includesGraph) >- this._record.addEventListener(WI.TimelineRecord.Event.Updated, this._timelineRecordUpdated, this); >+ 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); > else { >- 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); >+ 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); > } > } > > // Public > >- get records() >- { >- return [this._record]; >- } >- > get resource() > { >- return this._resource; >+ return this.record.resource; > } > > get data() >@@ -63,40 +58,28 @@ WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI. > if (this._cachedData) > return this._cachedData; > >- 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; >+ 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; > } > > createCellContent(columnIdentifier, cell) > { >- let resource = this._resource; >- >- if (resource.hadLoadingError()) >+ if (this.resource.hadLoadingError()) > cell.classList.add("error"); > > let value = this.data[columnIdentifier]; >@@ -104,7 +87,7 @@ WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI. > switch (columnIdentifier) { > case "name": > cell.classList.add(...this.iconClassNames()); >- cell.title = resource.displayURL; >+ cell.title = this.resource.displayURL; > this._updateStatus(cell); > return this._createNameCellDocumentFragment(); > >@@ -114,7 +97,7 @@ WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI. > return text; > > case "statusCode": >- cell.title = resource.statusText || ""; >+ cell.title = this.resource.statusText || ""; > return value || emDash; > > case "cached": >@@ -180,7 +163,7 @@ WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI. > > appendContextMenuItems(contextMenu) > { >- WI.appendContextMenuItemsForSourceCode(contextMenu, this._resource); >+ WI.appendContextMenuItemsForSourceCode(contextMenu, this.resource); > } > > // Protected >@@ -213,7 +196,7 @@ WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI. > filterableDataForColumn(columnIdentifier) > { > if (columnIdentifier === "name") >- return this._resource.url; >+ return this.resource.url; > return super.filterableDataForColumn(columnIdentifier); > } > >@@ -226,8 +209,8 @@ WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI. > fragment.append(mainTitle); > > // Show the host as the subtitle if it is different from the main resource or if this is the main frame's main resource. >- let frame = this._resource.parentFrame; >- let isMainResource = this._resource.isMainResource(); >+ let frame = this.resource.parentFrame; >+ let isMainResource = this.resource.isMainResource(); > let parentResourceHost; > if (frame && isMainResource) { > // When the resource is a main resource, get the host from the current frame's parent frame instead of the current frame. >@@ -237,8 +220,8 @@ WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI. > parentResourceHost = frame.mainResource.urlComponents.host; > } > >- if (parentResourceHost !== this._resource.urlComponents.host || frame.isMainFrame() && isMainResource) { >- let subtitle = WI.displayNameForHost(this._resource.urlComponents.host); >+ if (parentResourceHost !== this.resource.urlComponents.host || frame.isMainFrame() && isMainResource) { >+ let subtitle = WI.displayNameForHost(this.resource.urlComponents.host); > if (mainTitle !== subtitle) { > let subtitleElement = document.createElement("span"); > subtitleElement.classList.add("subtitle"); >@@ -252,12 +235,12 @@ WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI. > > _cachedCellContent() > { >- if (!this._resource.hasResponse()) >+ if (!this.resource.hasResponse()) > return emDash; > >- let responseSource = this._resource.responseSource; >+ let responseSource = this.resource.responseSource; > if (responseSource === WI.Resource.ResponseSource.MemoryCache || responseSource === WI.Resource.ResponseSource.DiskCache) { >- console.assert(this._resource.cached, "This resource has a cache responseSource it should also be marked as cached", this._resource); >+ console.assert(this.resource.cached, "This resource has a cache responseSource it should also be marked as cached", this.resource); > let span = document.createElement("span"); > let cacheType = document.createElement("span"); > cacheType.classList = "cache-type"; >@@ -267,7 +250,7 @@ WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI. > } > > let fragment = document.createDocumentFragment(); >- fragment.append(this._resource.cached ? WI.UIString("Yes") : WI.UIString("No")); >+ fragment.append(this.resource.cached ? WI.UIString("Yes") : WI.UIString("No")); > return fragment; > } > >@@ -286,7 +269,7 @@ WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI. > > _timelineRecordUpdated(event) > { >- if (this.isRecordVisible(this._record)) >+ if (this.isRecordVisible(this.record)) > this.needsGraphRefresh(); > } > >@@ -296,21 +279,21 @@ WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI. > ignoreNetworkTab: true, > ignoreSearchTab: true, > }; >- WI.showSourceCode(this._resource, options); >+ WI.showSourceCode(this.resource, options); > } > > _updateStatus(cell) > { >- if (this._resource.failed) >+ if (this.resource.failed) > cell.classList.add("error"); > else { > cell.classList.remove("error"); > >- if (this._resource.finished) >+ if (this.resource.finished) > this.createGoToArrowButton(cell, this._dataGridNodeGoToArrowClicked.bind(this)); > } > >- if (this._resource.isLoading()) { >+ if (this.resource.isLoading()) { > if (!this._spinner) > this._spinner = new WI.IndeterminateProgressSpinner; > let contentElement = cell.firstChild; >@@ -386,14 +369,10 @@ WI.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WI. > let graphDataSource = { > get secondsPerPixel() { return resource.totalDuration / WI.ResourceTimelineDataGridNode.PopoverGraphColumnWidthPixels; }, > get zeroTime() { return resource.firstTimestamp; }, >- get startTime() { return resource.firstTimestamp; }, >- get currentTime() { return this.endTime; }, >- >- get endTime() >- { >- let endTimePadding = this.secondsPerPixel * WI.TimelineRecordBar.MinimumWidthPixels; >- return resource.lastTimestamp + endTimePadding; >- } >+ 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; }, > }; > > if (resource.timingData.redirectEnd - resource.timingData.redirectStart) { >diff --git a/Source/WebInspectorUI/UserInterface/Views/ResourceTimingPopoverDataGridNode.js b/Source/WebInspectorUI/UserInterface/Views/ResourceTimingPopoverDataGridNode.js >index 3bf03e4c31d066f1392eaf1b38012b3e2626947f..3eb8723e1bfb8ceed20a5dddaf7f12b328934f3b 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/ResourceTimingPopoverDataGridNode.js >+++ b/Source/WebInspectorUI/UserInterface/Views/ResourceTimingPopoverDataGridNode.js >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -27,20 +27,26 @@ WI.ResourceTimingPopoverDataGridNode = class ResourceTimingPopoverDataGridNode e > { > constructor(description, startTime, endTime, graphDataSource) > { >- super(true, graphDataSource); >+ let record = new WI.TimelineRecord(WI.TimelineRecord.Type.Network, startTime, endTime); >+ super([record], { >+ includesGraph: true, >+ graphDataSource, >+ }); > > const higherResolution = true; > let duration = Number.secondsToMillisecondsString(endTime - startTime, higherResolution); > > this._data = {description, duration}; >- this._record = new WI.TimelineRecord(WI.TimelineRecord.Type.Network, startTime, endTime); > } > > // Public > >- get records() { return [this._record]; } > get data() { return this._data; } >- get selectable() { return false; } >+ >+ get selectable() >+ { >+ return false; >+ } > > // Protected > >diff --git a/Source/WebInspectorUI/UserInterface/Views/ScriptDetailsTimelineView.js b/Source/WebInspectorUI/UserInterface/Views/ScriptDetailsTimelineView.js >index 88c392c0158cf5027febada68ab6a73a83e2ee8e..a1dee6ccca454d40db731b763c656bf3a8fffad6 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/ScriptDetailsTimelineView.js >+++ b/Source/WebInspectorUI/UserInterface/Views/ScriptDetailsTimelineView.js >@@ -176,9 +176,11 @@ WI.ScriptDetailsTimelineView = class ScriptDetailsTimelineView extends WI.Timeli > if (this.startTime !== this._oldStartTime || this.endTime !== this._oldEndTime) { > let dataGridNode = this._dataGrid.children[0]; > while (dataGridNode) { >- dataGridNode.updateRangeTimes(this.startTime, this.endTime); > if (dataGridNode.revealed) >- dataGridNode.refreshIfNeeded(); >+ dataGridNode.refresh(); >+ else >+ dataGridNode.needsRefresh(); >+ > dataGridNode = dataGridNode.traverseNextNode(false, null, true); > } > >@@ -199,10 +201,6 @@ WI.ScriptDetailsTimelineView = class ScriptDetailsTimelineView extends WI.Timeli > if (!this._pendingRecords.length) > return; > >- let zeroTime = this.zeroTime; >- let startTime = this.startTime; >- let endTime = this.endTime; >- > for (let scriptTimelineRecord of this._pendingRecords) { > let rootNodes = []; > if (scriptTimelineRecord.profile) { >@@ -210,11 +208,15 @@ WI.ScriptDetailsTimelineView = class ScriptDetailsTimelineView extends WI.Timeli > rootNodes = scriptTimelineRecord.profile.topDownRootNodes; > } > >- let dataGridNode = new WI.ScriptTimelineDataGridNode(scriptTimelineRecord, zeroTime); >+ let dataGridNode = new WI.ScriptTimelineDataGridNode(scriptTimelineRecord, { >+ graphDataSource: this, >+ }); > this._dataGrid.addRowInSortOrder(dataGridNode); > > for (let profileNode of rootNodes) { >- let profileNodeDataGridNode = new WI.ProfileNodeDataGridNode(profileNode, zeroTime, startTime, endTime); >+ let profileNodeDataGridNode = new WI.ProfileNodeDataGridNode(profileNode, { >+ graphDataSource: this, >+ }); > this._dataGrid.addRowInSortOrder(profileNodeDataGridNode, dataGridNode); > } > } >diff --git a/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js b/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js >index 05d9ad14c3bcd7a63b92ed7ad0c0c520b7c49f6f..3f4cde03b997b921d6f3f2ac9471cb1ece4f148a 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js >+++ b/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. >+ * Copyright (C) 2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -25,65 +25,51 @@ > > WI.ScriptTimelineDataGridNode = class ScriptTimelineDataGridNode extends WI.TimelineDataGridNode > { >- constructor(scriptTimelineRecord, baseStartTime, rangeStartTime, rangeEndTime) >+ constructor(record, options = {}) > { >- super(false, null); >+ console.assert(record instanceof WI.ScriptTimelineRecord); > >- this._record = scriptTimelineRecord; >- this._baseStartTime = baseStartTime || 0; >- this._rangeStartTime = rangeStartTime || 0; >- this._rangeEndTime = typeof rangeEndTime === "number" ? rangeEndTime : Infinity; >+ super([record], options); > } > > // Public > >- get records() >- { >- return [this._record]; >- } >- >- get baseStartTime() >- { >- return this._baseStartTime; >- } >- >- get rangeStartTime() >- { >- return this._rangeStartTime; >- } >- >- 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; >+ if (this._cachedData) >+ return this._cachedData; > >- // 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; >- } >- } >- >- this._cachedData = { >- eventType: this._record.eventType, >- startTime, >- selfTime: duration, >- totalTime: duration, >- averageTime: duration, >- callCount: this._record.callCountOrSamples, >- location: callFrameOrSourceCodeLocation, >- }; >+ let baseStartTime = 0; >+ let rangeStartTime = 0; >+ let rangeEndTime = Infinity; >+ if (this.graphDataSource) { >+ baseStartTime = this.graphDataSource.zeroTime; >+ rangeStartTime = this.graphDataSource.startTime; >+ rangeEndTime = this.graphDataSource.endTime; > } > >+ let startTime = this.record.startTime; >+ let duration = this.record.startTime + this.record.duration - startTime; >+ >+ // 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; >+ } >+ } >+ >+ 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; >+ > return this._cachedData; > } > >@@ -94,9 +80,9 @@ WI.ScriptTimelineDataGridNode = class ScriptTimelineDataGridNode extends WI.Time > > this._subtitle = ""; > >- if (this._record.eventType === WI.ScriptTimelineRecord.EventType.TimerInstalled) { >- let timeoutString = Number.secondsToString(this._record.details.timeout / 1000); >- if (this._record.details.repeating) >+ if (this.record.eventType === WI.ScriptTimelineRecord.EventType.TimerInstalled) { >+ let timeoutString = Number.secondsToString(this.record.details.timeout / 1000); >+ if (this.record.details.repeating) > this._subtitle = WI.UIString("%s interval").format(timeoutString); > else > this._subtitle = WI.UIString("%s delay").format(timeoutString); >@@ -105,35 +91,10 @@ WI.ScriptTimelineDataGridNode = class ScriptTimelineDataGridNode extends WI.Time > return this._subtitle; > } > >- updateRangeTimes(startTime, endTime) >- { >- var oldRangeStartTime = this._rangeStartTime; >- var oldRangeEndTime = this._rangeEndTime; >- >- 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) > { >+ const higherResolution = true; >+ > var value = this.data[columnIdentifier]; > > switch (columnIdentifier) { >@@ -142,15 +103,19 @@ WI.ScriptTimelineDataGridNode = class ScriptTimelineDataGridNode extends WI.Time > return this._createNameCellDocumentFragment(); > > case "startTime": >- return isNaN(value) ? emDash : Number.secondsToString(value - this._baseStartTime, true); >- > case "selfTime": > case "totalTime": > case "averageTime": >- return isNaN(value) ? emDash : Number.secondsToString(value, true); >+ return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution); > > case "callCount": > return isNaN(value) ? emDash : value.toLocaleString(); >+ >+ // Necessary to be displayed in WI.LayoutTimelineView. >+ case "width": >+ case "height": >+ case "area": >+ return zeroWidthSpace; > } > > return super.createCellContent(columnIdentifier, cell); >diff --git a/Source/WebInspectorUI/UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js b/Source/WebInspectorUI/UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js >index ef6011ef5c3fdc5983031b3846fa7a49b6c86241..807be168def340fb56d2ccd246d6b710bb9ecad1 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js >+++ b/Source/WebInspectorUI/UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js >@@ -25,9 +25,10 @@ > > WI.SourceCodeTimelineTimelineDataGridNode = class SourceCodeTimelineTimelineDataGridNode extends WI.TimelineDataGridNode > { >- constructor(sourceCodeTimeline, graphDataSource) >+ constructor(sourceCodeTimeline, options = {}) > { >- super(true, graphDataSource); >+ const records = []; >+ super(records, {includesGraph: true, ...options}); > > this._sourceCodeTimeline = sourceCodeTimeline; > this._sourceCodeTimeline.addEventListener(WI.Timeline.Event.RecordAdded, this._timelineRecordAdded, this); >@@ -47,7 +48,12 @@ WI.SourceCodeTimelineTimelineDataGridNode = class SourceCodeTimelineTimelineData > > get data() > { >- return {graph: this._sourceCodeTimeline.startTime}; >+ if (this._cachedData) >+ return this._cachedData; >+ >+ this._cachedData = super.data; >+ this._cachedData.graph = this._sourceCodeTimeline.startTime; >+ return this._cachedData; > } > > createCellContent(columnIdentifier, cell) >diff --git a/Source/WebInspectorUI/UserInterface/Views/SourceCodeTimelineTreeElement.js b/Source/WebInspectorUI/UserInterface/Views/SourceCodeTimelineTreeElement.js >deleted file mode 100644 >index f7bb5fb3d624729e4ce5dbe8dee65e7f6b285434..0000000000000000000000000000000000000000 >--- a/Source/WebInspectorUI/UserInterface/Views/SourceCodeTimelineTreeElement.js >+++ /dev/null >@@ -1,50 +0,0 @@ >-/* >- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * >- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >- * THE POSSIBILITY OF SUCH DAMAGE. >- */ >- >-WI.SourceCodeTimelineTreeElement = class SourceCodeTimelineTreeElement extends WI.TimelineRecordTreeElement >-{ >- constructor(sourceCodeTimeline, subtitleNameStyle, includeDetailsInMainTitle) >- { >- console.assert(sourceCodeTimeline); >- >- subtitleNameStyle = subtitleNameStyle || WI.SourceCodeLocation.NameStyle.None; >- >- super(sourceCodeTimeline.records[0], subtitleNameStyle, includeDetailsInMainTitle, sourceCodeTimeline.sourceCodeLocation, sourceCodeTimeline); >- >- this._sourceCodeTimeline = sourceCodeTimeline; >- } >- >- // Public >- >- get record() >- { >- return undefined; >- } >- >- get sourceCodeTimeline() >- { >- return this._sourceCodeTimeline; >- } >-}; >diff --git a/Source/WebInspectorUI/UserInterface/Views/TimelineDataGridNode.js b/Source/WebInspectorUI/UserInterface/Views/TimelineDataGridNode.js >index a2f6247a10eec742b3e99471599d362c746c8683..5a09168c1660b2942afac2f4392008f83bd3ffb5 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/TimelineDataGridNode.js >+++ b/Source/WebInspectorUI/UserInterface/Views/TimelineDataGridNode.js >@@ -25,16 +25,18 @@ > > WI.TimelineDataGridNode = class TimelineDataGridNode extends WI.DataGridNode > { >- constructor(includesGraph, graphDataSource, hasChildren) >+ constructor(records, options = {}) > { >- super({}, hasChildren); >+ super({}, options.hasChildren); > > this.copyable = false; > >- this._includesGraph = includesGraph || false; >- this._graphDataSource = graphDataSource || null; >+ this._records = records; >+ this._includesGraph = options.includesGraph || false; >+ this._graphDataSource = options.graphDataSource || null; >+ this._cachedData = null; > >- if (graphDataSource) { >+ if (this._graphDataSource) { > this._graphContainerElement = document.createElement("div"); > this._timelineRecordBars = []; > } >@@ -42,17 +44,13 @@ WI.TimelineDataGridNode = class TimelineDataGridNode extends WI.DataGridNode > > // Public > >+ get records() { return this._records; } >+ > get record() > { > return this.records && this.records.length ? this.records[0] : null; > } > >- get records() >- { >- // Implemented by subclasses. >- return []; >- } >- > get graphDataSource() > { > return this._graphDataSource; >@@ -63,8 +61,9 @@ WI.TimelineDataGridNode = class TimelineDataGridNode extends WI.DataGridNode > if (!this._graphDataSource) > return {}; > >- var records = this.records || []; >- return {graph: records.length ? records[0].startTime : 0}; >+ return { >+ graph: this.record ? this.record.startTime : 0, >+ }; > } > > collapse() >@@ -207,6 +206,8 @@ WI.TimelineDataGridNode = class TimelineDataGridNode extends WI.DataGridNode > > refresh() > { >+ this._cachedData = null; >+ > if (this._graphDataSource && this._includesGraph) > this.needsGraphRefresh(); > >diff --git a/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.css b/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.css >index 7df5e227d2cc02f15085e68bb11ed5f2f49e9280..4e7600f645860872dc8e679489308258ebaefcfb 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.css >+++ b/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.css >@@ -122,7 +122,8 @@ body[dir=rtl] :focus .selected .timeline-record-bar.has-inactive-segment > .segm > border-color: hsl(273, 33%, 58%); > } > >-.timeline-record-bar.timeline-record-type-script.script-timeline-record-garbage-collected > .segment { >+.timeline-record-bar.timeline-record-type-script.script-timeline-record-garbage-collected > .segment, >+.timeline-record-bar.timeline-record-type-heap-allocations > .segment { > background-color: hsl(23, 69%, 73%); > border-color: hsl(11, 54%, 62%); > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 191901
:
355450
|
355451
|
355452
|
355454
|
355609
|
358176
|
365237
|
365238
|
365500
|
365501