OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2014 Google Inc. All rights reserved. | 2 * Copyright (C) 2014 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
13 * distribution. | 13 * distribution. |
14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
17 * | 17 * |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | |
31 /** | 30 /** |
32 * @constructor | |
33 * @implements {WebInspector.FlameChartDataProvider} | 31 * @implements {WebInspector.FlameChartDataProvider} |
34 * @param {!WebInspector.TimelineModel} model | 32 * @unrestricted |
35 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters | |
36 */ | 33 */ |
37 WebInspector.TimelineFlameChartDataProviderBase = function(model, filters) | 34 WebInspector.TimelineFlameChartDataProviderBase = class { |
38 { | 35 /** |
| 36 * @param {!WebInspector.TimelineModel} model |
| 37 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters |
| 38 */ |
| 39 constructor(model, filters) { |
39 WebInspector.FlameChartDataProvider.call(this); | 40 WebInspector.FlameChartDataProvider.call(this); |
40 this.reset(); | 41 this.reset(); |
41 this._model = model; | 42 this._model = model; |
42 /** @type {?WebInspector.FlameChart.TimelineData} */ | 43 /** @type {?WebInspector.FlameChart.TimelineData} */ |
43 this._timelineData; | 44 this._timelineData; |
44 this._font = "11px " + WebInspector.fontFamily(); | 45 this._font = '11px ' + WebInspector.fontFamily(); |
45 this._filters = filters; | 46 this._filters = filters; |
46 }; | 47 } |
47 | 48 |
48 WebInspector.TimelineFlameChartDataProviderBase.prototype = { | 49 /** |
49 /** | 50 * @override |
50 * @override | 51 * @return {number} |
51 * @return {number} | 52 */ |
52 */ | 53 barHeight() { |
53 barHeight: function() | 54 return 17; |
54 { | 55 } |
55 return 17; | 56 |
56 }, | 57 /** |
57 | 58 * @override |
58 /** | 59 * @return {number} |
59 * @override | 60 */ |
60 * @return {number} | 61 textBaseline() { |
61 */ | 62 return 5; |
62 textBaseline: function() | 63 } |
63 { | 64 |
64 return 5; | 65 /** |
65 }, | 66 * @override |
66 | 67 * @return {number} |
67 /** | 68 */ |
68 * @override | 69 textPadding() { |
69 * @return {number} | 70 return 4; |
70 */ | 71 } |
71 textPadding: function() | 72 |
72 { | 73 /** |
73 return 4; | 74 * @override |
74 }, | 75 * @param {number} entryIndex |
75 | 76 * @return {string} |
76 /** | 77 */ |
77 * @override | 78 entryFont(entryIndex) { |
78 * @param {number} entryIndex | 79 return this._font; |
79 * @return {string} | 80 } |
80 */ | 81 |
81 entryFont: function(entryIndex) | 82 /** |
82 { | 83 * @override |
83 return this._font; | 84 * @param {number} entryIndex |
84 }, | 85 * @return {?string} |
85 | 86 */ |
86 /** | 87 entryTitle(entryIndex) { |
87 * @override | 88 return null; |
88 * @param {number} entryIndex | 89 } |
89 * @return {?string} | 90 |
90 */ | 91 reset() { |
91 entryTitle: function(entryIndex) | 92 this._timelineData = null; |
92 { | 93 } |
93 return null; | 94 |
94 }, | 95 /** |
95 | 96 * @override |
96 reset: function() | 97 * @return {number} |
97 { | 98 */ |
98 this._timelineData = null; | 99 minimumBoundary() { |
99 }, | 100 return this._minimumBoundary; |
100 | 101 } |
101 /** | 102 |
102 * @override | 103 /** |
103 * @return {number} | 104 * @override |
104 */ | 105 * @return {number} |
105 minimumBoundary: function() | 106 */ |
106 { | 107 totalTime() { |
107 return this._minimumBoundary; | 108 return this._timeSpan; |
108 }, | 109 } |
109 | 110 |
110 /** | 111 /** |
111 * @override | 112 * @override |
112 * @return {number} | 113 * @param {number} value |
113 */ | 114 * @param {number=} precision |
114 totalTime: function() | 115 * @return {string} |
115 { | 116 */ |
116 return this._timeSpan; | 117 formatValue(value, precision) { |
117 }, | 118 return Number.preciseMillisToString(value, precision); |
118 | 119 } |
119 /** | 120 |
120 * @override | 121 /** |
121 * @param {number} value | 122 * @override |
122 * @param {number=} precision | 123 * @return {number} |
123 * @return {string} | 124 */ |
124 */ | 125 maxStackDepth() { |
125 formatValue: function(value, precision) | 126 return this._currentLevel; |
126 { | 127 } |
127 return Number.preciseMillisToString(value, precision); | 128 |
128 }, | 129 /** |
129 | 130 * @override |
130 /** | 131 * @param {number} entryIndex |
131 * @override | 132 * @return {?Element} |
132 * @return {number} | 133 */ |
133 */ | 134 prepareHighlightedEntryInfo(entryIndex) { |
134 maxStackDepth: function() | 135 return null; |
135 { | 136 } |
136 return this._currentLevel; | 137 |
137 }, | 138 /** |
138 | 139 * @override |
139 /** | 140 * @param {number} entryIndex |
140 * @override | 141 * @return {boolean} |
141 * @param {number} entryIndex | 142 */ |
142 * @return {?Element} | 143 canJumpToEntry(entryIndex) { |
143 */ | 144 return false; |
144 prepareHighlightedEntryInfo: function(entryIndex) | 145 } |
145 { | 146 |
146 return null; | 147 /** |
147 }, | 148 * @override |
148 | 149 * @param {number} entryIndex |
149 /** | 150 * @return {string} |
150 * @override | 151 */ |
151 * @param {number} entryIndex | 152 entryColor(entryIndex) { |
152 * @return {boolean} | 153 return 'red'; |
153 */ | 154 } |
154 canJumpToEntry: function(entryIndex) | 155 |
155 { | 156 /** |
156 return false; | 157 * @override |
157 }, | 158 * @param {number} index |
158 | 159 * @return {boolean} |
159 /** | 160 */ |
160 * @override | 161 forceDecoration(index) { |
161 * @param {number} entryIndex | 162 return false; |
162 * @return {string} | 163 } |
163 */ | 164 |
164 entryColor: function(entryIndex) | 165 /** |
165 { | 166 * @override |
166 return "red"; | 167 * @param {number} entryIndex |
167 }, | 168 * @param {!CanvasRenderingContext2D} context |
168 | 169 * @param {?string} text |
169 /** | 170 * @param {number} barX |
170 * @override | 171 * @param {number} barY |
171 * @param {number} index | 172 * @param {number} barWidth |
172 * @return {boolean} | 173 * @param {number} barHeight |
173 */ | 174 * @param {number} unclippedBarX |
174 forceDecoration: function(index) | 175 * @param {number} timeToPixels |
175 { | 176 * @return {boolean} |
176 return false; | 177 */ |
177 }, | 178 decorateEntry(entryIndex, context, text, barX, barY, barWidth, barHeight, uncl
ippedBarX, timeToPixels) { |
178 | 179 return false; |
179 /** | 180 } |
180 * @override | 181 |
181 * @param {number} entryIndex | 182 /** |
182 * @param {!CanvasRenderingContext2D} context | 183 * @override |
183 * @param {?string} text | 184 * @return {number} |
184 * @param {number} barX | 185 */ |
185 * @param {number} barY | 186 paddingLeft() { |
186 * @param {number} barWidth | 187 return 0; |
187 * @param {number} barHeight | 188 } |
188 * @param {number} unclippedBarX | 189 |
189 * @param {number} timeToPixels | 190 /** |
190 * @return {boolean} | 191 * @override |
191 */ | 192 * @param {number} entryIndex |
192 decorateEntry: function(entryIndex, context, text, barX, barY, barWidth, bar
Height, unclippedBarX, timeToPixels) | 193 * @return {string} |
193 { | 194 */ |
194 return false; | 195 textColor(entryIndex) { |
195 }, | 196 return '#333'; |
196 | 197 } |
197 /** | 198 |
198 * @override | 199 /** |
199 * @return {number} | 200 * @param {number} entryIndex |
200 */ | 201 * @return {?WebInspector.TimelineSelection} |
201 paddingLeft: function() | 202 */ |
202 { | 203 createSelection(entryIndex) { |
203 return 0; | 204 return null; |
204 }, | 205 } |
205 | 206 |
206 /** | 207 /** |
207 * @override | 208 * @override |
208 * @param {number} entryIndex | 209 * @return {!WebInspector.FlameChart.TimelineData} |
209 * @return {string} | 210 */ |
210 */ | 211 timelineData() { |
211 textColor: function(entryIndex) | 212 throw new Error('Not implemented'); |
212 { | 213 } |
213 return "#333"; | 214 |
214 }, | 215 /** |
215 | 216 * @param {!WebInspector.TracingModel.Event} event |
216 /** | 217 * @return {boolean} |
217 * @param {number} entryIndex | 218 */ |
218 * @return {?WebInspector.TimelineSelection} | 219 _isVisible(event) { |
219 */ | 220 return this._filters.every(function(filter) { |
220 createSelection: function(entryIndex) | 221 return filter.accept(event); |
221 { | 222 }); |
222 return null; | 223 } |
223 }, | |
224 | |
225 /** | |
226 * @override | |
227 * @return {!WebInspector.FlameChart.TimelineData} | |
228 */ | |
229 timelineData: function() | |
230 { | |
231 throw new Error("Not implemented"); | |
232 }, | |
233 | |
234 /** | |
235 * @param {!WebInspector.TracingModel.Event} event | |
236 * @return {boolean} | |
237 */ | |
238 _isVisible: function(event) | |
239 { | |
240 return this._filters.every(function(filter) { return filter.accept(event
); }); | |
241 } | |
242 }; | 224 }; |
243 | 225 |
244 /** | 226 /** |
245 * @enum {symbol} | 227 * @enum {symbol} |
246 */ | 228 */ |
247 WebInspector.TimelineFlameChartEntryType = { | 229 WebInspector.TimelineFlameChartEntryType = { |
248 Frame: Symbol("Frame"), | 230 Frame: Symbol('Frame'), |
249 Event: Symbol("Event"), | 231 Event: Symbol('Event'), |
250 InteractionRecord: Symbol("InteractionRecord"), | 232 InteractionRecord: Symbol('InteractionRecord'), |
251 }; | 233 }; |
252 | 234 |
253 /** | 235 /** |
254 * @constructor | 236 * @unrestricted |
255 * @extends {WebInspector.TimelineFlameChartDataProviderBase} | |
256 * @param {!WebInspector.TimelineModel} model | |
257 * @param {!WebInspector.TimelineFrameModel} frameModel | |
258 * @param {!WebInspector.TimelineIRModel} irModel | |
259 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters | |
260 */ | 237 */ |
261 WebInspector.TimelineFlameChartDataProvider = function(model, frameModel, irMode
l, filters) | 238 WebInspector.TimelineFlameChartDataProvider = class extends WebInspector.Timelin
eFlameChartDataProviderBase { |
262 { | 239 /** |
263 WebInspector.TimelineFlameChartDataProviderBase.call(this, model, filters); | 240 * @param {!WebInspector.TimelineModel} model |
| 241 * @param {!WebInspector.TimelineFrameModel} frameModel |
| 242 * @param {!WebInspector.TimelineIRModel} irModel |
| 243 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters |
| 244 */ |
| 245 constructor(model, frameModel, irModel, filters) { |
| 246 super(model, filters); |
264 this._frameModel = frameModel; | 247 this._frameModel = frameModel; |
265 this._irModel = irModel; | 248 this._irModel = irModel; |
266 this._consoleColorGenerator = new WebInspector.FlameChart.ColorGenerator( | 249 this._consoleColorGenerator = |
267 { min: 30, max: 55 }, | 250 new WebInspector.FlameChart.ColorGenerator({min: 30, max: 55}, {min: 70,
max: 100, count: 6}, 50, 0.7); |
268 { min: 70, max: 100, count: 6 }, | |
269 50, 0.7); | |
270 | 251 |
271 this._headerLevel1 = { | 252 this._headerLevel1 = { |
272 padding: 4, | 253 padding: 4, |
273 height: 17, | 254 height: 17, |
274 collapsible: true, | 255 collapsible: true, |
275 color: WebInspector.themeSupport.patchColor("#222", WebInspector.ThemeSu
pport.ColorUsage.Foreground), | 256 color: WebInspector.themeSupport.patchColor('#222', WebInspector.ThemeSupp
ort.ColorUsage.Foreground), |
276 font: this._font, | 257 font: this._font, |
277 backgroundColor: WebInspector.themeSupport.patchColor("white", WebInspec
tor.ThemeSupport.ColorUsage.Background), | 258 backgroundColor: WebInspector.themeSupport.patchColor('white', WebInspecto
r.ThemeSupport.ColorUsage.Background), |
278 nestingLevel: 0 | 259 nestingLevel: 0 |
279 }; | 260 }; |
280 | 261 |
281 this._headerLevel2 = { | 262 this._headerLevel2 = { |
282 padding: 2, | 263 padding: 2, |
283 height: 17, | 264 height: 17, |
284 collapsible: false, | 265 collapsible: false, |
285 font: this._font, | 266 font: this._font, |
286 color: WebInspector.themeSupport.patchColor("#222", WebInspector.ThemeSu
pport.ColorUsage.Foreground), | 267 color: WebInspector.themeSupport.patchColor('#222', WebInspector.ThemeSupp
ort.ColorUsage.Foreground), |
287 backgroundColor: WebInspector.themeSupport.patchColor("white", WebInspec
tor.ThemeSupport.ColorUsage.Background), | 268 backgroundColor: WebInspector.themeSupport.patchColor('white', WebInspecto
r.ThemeSupport.ColorUsage.Background), |
288 nestingLevel: 1, | 269 nestingLevel: 1, |
289 shareHeaderLine: true | 270 shareHeaderLine: true |
290 }; | 271 }; |
291 | 272 |
292 this._interactionsHeaderLevel1 = { | 273 this._interactionsHeaderLevel1 = { |
293 padding: 4, | 274 padding: 4, |
294 height: 17, | 275 height: 17, |
295 collapsible: true, | 276 collapsible: true, |
296 color: WebInspector.themeSupport.patchColor("#222", WebInspector.ThemeSu
pport.ColorUsage.Foreground), | 277 color: WebInspector.themeSupport.patchColor('#222', WebInspector.ThemeSupp
ort.ColorUsage.Foreground), |
297 font: this._font, | 278 font: this._font, |
298 backgroundColor: WebInspector.themeSupport.patchColor("white", WebInspec
tor.ThemeSupport.ColorUsage.Background), | 279 backgroundColor: WebInspector.themeSupport.patchColor('white', WebInspecto
r.ThemeSupport.ColorUsage.Background), |
299 nestingLevel: 0, | 280 nestingLevel: 0, |
300 useFirstLineForOverview: true, | 281 useFirstLineForOverview: true, |
301 shareHeaderLine: true | 282 shareHeaderLine: true |
302 }; | 283 }; |
303 | 284 |
304 this._interactionsHeaderLevel2 = { | 285 this._interactionsHeaderLevel2 = { |
305 padding: 2, | 286 padding: 2, |
306 height: 17, | 287 height: 17, |
307 collapsible: true, | 288 collapsible: true, |
308 color: WebInspector.themeSupport.patchColor("#222", WebInspector.ThemeSu
pport.ColorUsage.Foreground), | 289 color: WebInspector.themeSupport.patchColor('#222', WebInspector.ThemeSupp
ort.ColorUsage.Foreground), |
309 font: this._font, | 290 font: this._font, |
310 backgroundColor: WebInspector.themeSupport.patchColor("white", WebInspec
tor.ThemeSupport.ColorUsage.Background), | 291 backgroundColor: WebInspector.themeSupport.patchColor('white', WebInspecto
r.ThemeSupport.ColorUsage.Background), |
311 nestingLevel: 1, | 292 nestingLevel: 1, |
312 shareHeaderLine: true | 293 shareHeaderLine: true |
313 }; | 294 }; |
314 }; | 295 } |
315 | 296 |
316 WebInspector.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs = 0.00
1; | 297 /** |
317 | 298 * @override |
318 WebInspector.TimelineFlameChartDataProvider.prototype = { | 299 * @param {number} entryIndex |
| 300 * @return {?string} |
| 301 */ |
| 302 entryTitle(entryIndex) { |
| 303 var entryType = this._entryType(entryIndex); |
| 304 if (entryType === WebInspector.TimelineFlameChartEntryType.Event) { |
| 305 var event = /** @type {!WebInspector.TracingModel.Event} */ (this._entryDa
ta[entryIndex]); |
| 306 if (event.phase === WebInspector.TracingModel.Phase.AsyncStepInto || |
| 307 event.phase === WebInspector.TracingModel.Phase.AsyncStepPast) |
| 308 return event.name + ':' + event.args['step']; |
| 309 if (event._blackboxRoot) |
| 310 return WebInspector.UIString('Blackboxed'); |
| 311 var name = WebInspector.TimelineUIUtils.eventStyle(event).title; |
| 312 // TODO(yurys): support event dividers |
| 313 var detailsText = |
| 314 WebInspector.TimelineUIUtils.buildDetailsTextForTraceEvent(event, this
._model.targetByEvent(event)); |
| 315 if (event.name === WebInspector.TimelineModel.RecordType.JSFrame && detail
sText) |
| 316 return detailsText; |
| 317 return detailsText ? WebInspector.UIString('%s (%s)', name, detailsText) :
name; |
| 318 } |
| 319 var title = this._entryIndexToTitle[entryIndex]; |
| 320 if (!title) { |
| 321 title = WebInspector.UIString('Unexpected entryIndex %d', entryIndex); |
| 322 console.error(title); |
| 323 } |
| 324 return title; |
| 325 } |
| 326 |
| 327 /** |
| 328 * @override |
| 329 * @param {number} index |
| 330 * @return {string} |
| 331 */ |
| 332 textColor(index) { |
| 333 var event = this._entryData[index]; |
| 334 if (event && event._blackboxRoot) |
| 335 return '#888'; |
| 336 else |
| 337 return super.textColor(index); |
| 338 } |
| 339 |
| 340 /** |
| 341 * @override |
| 342 */ |
| 343 reset() { |
| 344 super.reset(); |
| 345 /** @type {!Array<!WebInspector.TracingModel.Event|!WebInspector.TimelineFra
me|!WebInspector.TimelineIRModel.Phases>} */ |
| 346 this._entryData = []; |
| 347 /** @type {!Array<!WebInspector.TimelineFlameChartEntryType>} */ |
| 348 this._entryTypeByLevel = []; |
| 349 /** @type {!Array<string>} */ |
| 350 this._entryIndexToTitle = []; |
| 351 /** @type {!Array<!WebInspector.TimelineFlameChartMarker>} */ |
| 352 this._markers = []; |
| 353 /** @type {!Map<!WebInspector.TimelineCategory, string>} */ |
| 354 this._asyncColorByCategory = new Map(); |
| 355 /** @type {!Map<!WebInspector.TimelineIRModel.Phases, string>} */ |
| 356 this._asyncColorByInteractionPhase = new Map(); |
| 357 } |
| 358 |
| 359 /** |
| 360 * @override |
| 361 * @return {!WebInspector.FlameChart.TimelineData} |
| 362 */ |
| 363 timelineData() { |
| 364 if (this._timelineData) |
| 365 return this._timelineData; |
| 366 |
| 367 this._timelineData = new WebInspector.FlameChart.TimelineData([], [], [], []
); |
| 368 |
| 369 this._flowEventIndexById = {}; |
| 370 this._minimumBoundary = this._model.minimumRecordTime(); |
| 371 this._timeSpan = this._model.isEmpty() ? 1000 : this._model.maximumRecordTim
e() - this._minimumBoundary; |
| 372 this._currentLevel = 0; |
| 373 this._appendFrameBars(this._frameModel.frames()); |
| 374 |
| 375 this._appendHeader(WebInspector.UIString('Interactions'), this._interactions
HeaderLevel1); |
| 376 this._appendInteractionRecords(); |
| 377 |
| 378 var asyncEventGroups = WebInspector.TimelineModel.AsyncEventGroup; |
| 379 var inputLatencies = this._model.mainThreadAsyncEvents().get(asyncEventGroup
s.input); |
| 380 if (inputLatencies && inputLatencies.length) { |
| 381 var title = WebInspector.TimelineUIUtils.titleForAsyncEventGroup(asyncEven
tGroups.input); |
| 382 this._appendAsyncEventsGroup(title, inputLatencies, this._interactionsHead
erLevel2); |
| 383 } |
| 384 var animations = this._model.mainThreadAsyncEvents().get(asyncEventGroups.an
imation); |
| 385 if (animations && animations.length) { |
| 386 var title = WebInspector.TimelineUIUtils.titleForAsyncEventGroup(asyncEven
tGroups.animation); |
| 387 this._appendAsyncEventsGroup(title, animations, this._interactionsHeaderLe
vel2); |
| 388 } |
| 389 var threads = this._model.virtualThreads(); |
| 390 this._appendThreadTimelineData( |
| 391 WebInspector.UIString('Main'), this._model.mainThreadEvents(), this._mod
el.mainThreadAsyncEvents(), true); |
| 392 var compositorThreads = threads.filter(thread => thread.name.startsWith('Com
positorTileWorker')); |
| 393 var otherThreads = threads.filter(thread => !thread.name.startsWith('Composi
torTileWorker')); |
| 394 if (compositorThreads.length) { |
| 395 this._appendHeader(WebInspector.UIString('Raster'), this._headerLevel1); |
| 396 for (var i = 0; i < compositorThreads.length; ++i) |
| 397 this._appendSyncEvents( |
| 398 compositorThreads[i].events, WebInspector.UIString('Rasterizer Threa
d %d', i), this._headerLevel2); |
| 399 } |
| 400 this._appendGPUEvents(); |
| 401 |
| 402 otherThreads.forEach( |
| 403 thread => this._appendThreadTimelineData(thread.name, thread.events, thr
ead.asyncEventsByGroup)); |
| 404 |
319 /** | 405 /** |
320 * @override | 406 * @param {!WebInspector.TimelineFlameChartMarker} a |
321 * @param {number} entryIndex | 407 * @param {!WebInspector.TimelineFlameChartMarker} b |
322 * @return {?string} | |
323 */ | 408 */ |
324 entryTitle: function(entryIndex) | 409 function compareStartTime(a, b) { |
325 { | 410 return a.startTime() - b.startTime(); |
326 var entryType = this._entryType(entryIndex); | 411 } |
327 if (entryType === WebInspector.TimelineFlameChartEntryType.Event) { | 412 |
328 var event = /** @type {!WebInspector.TracingModel.Event} */ (this._e
ntryData[entryIndex]); | 413 this._markers.sort(compareStartTime); |
329 if (event.phase === WebInspector.TracingModel.Phase.AsyncStepInto ||
event.phase === WebInspector.TracingModel.Phase.AsyncStepPast) | 414 this._timelineData.markers = this._markers; |
330 return event.name + ":" + event.args["step"]; | 415 |
331 if (event._blackboxRoot) | 416 this._flowEventIndexById = {}; |
332 return WebInspector.UIString("Blackboxed"); | 417 return this._timelineData; |
333 var name = WebInspector.TimelineUIUtils.eventStyle(event).title; | 418 } |
334 // TODO(yurys): support event dividers | 419 |
335 var detailsText = WebInspector.TimelineUIUtils.buildDetailsTextForTr
aceEvent(event, this._model.targetByEvent(event)); | 420 /** |
336 if (event.name === WebInspector.TimelineModel.RecordType.JSFrame &&
detailsText) | 421 * @param {string} threadTitle |
337 return detailsText; | 422 * @param {!Array<!WebInspector.TracingModel.Event>} syncEvents |
338 return detailsText ? WebInspector.UIString("%s (%s)", name, detailsT
ext) : name; | 423 * @param {!Map<!WebInspector.TimelineModel.AsyncEventGroup, !Array<!WebInspec
tor.TracingModel.AsyncEvent>>} asyncEvents |
339 } | 424 * @param {boolean=} forceExpanded |
340 var title = this._entryIndexToTitle[entryIndex]; | 425 */ |
341 if (!title) { | 426 _appendThreadTimelineData(threadTitle, syncEvents, asyncEvents, forceExpanded)
{ |
342 title = WebInspector.UIString("Unexpected entryIndex %d", entryIndex
); | 427 this._appendAsyncEvents(asyncEvents); |
343 console.error(title); | 428 this._appendSyncEvents(syncEvents, threadTitle, this._headerLevel1, forceExp
anded); |
344 } | 429 } |
345 return title; | 430 |
346 }, | 431 /** |
| 432 * @param {!Array<!WebInspector.TracingModel.Event>} events |
| 433 * @param {string} title |
| 434 * @param {!WebInspector.FlameChart.GroupStyle} style |
| 435 * @param {boolean=} forceExpanded |
| 436 */ |
| 437 _appendSyncEvents(events, title, style, forceExpanded) { |
| 438 var openEvents = []; |
| 439 var flowEventsEnabled = Runtime.experiments.isEnabled('timelineFlowEvents'); |
| 440 var blackboxingEnabled = Runtime.experiments.isEnabled('blackboxJSFramesOnTi
meline'); |
| 441 var maxStackDepth = 0; |
| 442 for (var i = 0; i < events.length; ++i) { |
| 443 var e = events[i]; |
| 444 if (WebInspector.TimelineModel.isMarkerEvent(e)) |
| 445 this._markers.push(new WebInspector.TimelineFlameChartMarker( |
| 446 e.startTime, e.startTime - this._model.minimumRecordTime(), |
| 447 WebInspector.TimelineUIUtils.markerStyleForEvent(e))); |
| 448 if (!WebInspector.TracingModel.isFlowPhase(e.phase)) { |
| 449 if (!e.endTime && e.phase !== WebInspector.TracingModel.Phase.Instant) |
| 450 continue; |
| 451 if (WebInspector.TracingModel.isAsyncPhase(e.phase)) |
| 452 continue; |
| 453 if (!this._isVisible(e)) |
| 454 continue; |
| 455 } |
| 456 while (openEvents.length && openEvents.peekLast().endTime <= e.startTime) |
| 457 openEvents.pop(); |
| 458 e._blackboxRoot = false; |
| 459 if (blackboxingEnabled && this._isBlackboxedEvent(e)) { |
| 460 var parent = openEvents.peekLast(); |
| 461 if (parent && parent._blackboxRoot) |
| 462 continue; |
| 463 e._blackboxRoot = true; |
| 464 } |
| 465 if (title) { |
| 466 this._appendHeader(title, style, forceExpanded); |
| 467 title = ''; |
| 468 } |
| 469 |
| 470 var level = this._currentLevel + openEvents.length; |
| 471 this._appendEvent(e, level); |
| 472 if (flowEventsEnabled) |
| 473 this._appendFlowEvent(e, level); |
| 474 maxStackDepth = Math.max(maxStackDepth, openEvents.length + 1); |
| 475 if (e.endTime) |
| 476 openEvents.push(e); |
| 477 } |
| 478 this._entryTypeByLevel.length = this._currentLevel + maxStackDepth; |
| 479 this._entryTypeByLevel.fill(WebInspector.TimelineFlameChartEntryType.Event,
this._currentLevel); |
| 480 this._currentLevel += maxStackDepth; |
| 481 } |
| 482 |
| 483 /** |
| 484 * @param {!WebInspector.TracingModel.Event} event |
| 485 * @return {boolean} |
| 486 */ |
| 487 _isBlackboxedEvent(event) { |
| 488 if (event.name !== WebInspector.TimelineModel.RecordType.JSFrame) |
| 489 return false; |
| 490 var url = event.args['data']['url']; |
| 491 return url && this._isBlackboxedURL(url); |
| 492 } |
| 493 |
| 494 /** |
| 495 * @param {string} url |
| 496 * @return {boolean} |
| 497 */ |
| 498 _isBlackboxedURL(url) { |
| 499 return WebInspector.blackboxManager.isBlackboxedURL(url); |
| 500 } |
| 501 |
| 502 /** |
| 503 * @param {!Map<!WebInspector.TimelineModel.AsyncEventGroup, !Array<!WebInspec
tor.TracingModel.AsyncEvent>>} asyncEvents |
| 504 */ |
| 505 _appendAsyncEvents(asyncEvents) { |
| 506 var groups = WebInspector.TimelineModel.AsyncEventGroup; |
| 507 var groupArray = Object.keys(groups).map(key => groups[key]); |
| 508 |
| 509 groupArray.remove(groups.animation); |
| 510 groupArray.remove(groups.input); |
| 511 |
| 512 for (var groupIndex = 0; groupIndex < groupArray.length; ++groupIndex) { |
| 513 var group = groupArray[groupIndex]; |
| 514 var events = asyncEvents.get(group); |
| 515 if (!events) |
| 516 continue; |
| 517 var title = WebInspector.TimelineUIUtils.titleForAsyncEventGroup(group); |
| 518 this._appendAsyncEventsGroup(title, events, this._headerLevel1); |
| 519 } |
| 520 } |
| 521 |
| 522 /** |
| 523 * @param {string} header |
| 524 * @param {!Array<!WebInspector.TracingModel.AsyncEvent>} events |
| 525 * @param {!WebInspector.FlameChart.GroupStyle} style |
| 526 */ |
| 527 _appendAsyncEventsGroup(header, events, style) { |
| 528 var lastUsedTimeByLevel = []; |
| 529 var groupHeaderAppended = false; |
| 530 for (var i = 0; i < events.length; ++i) { |
| 531 var asyncEvent = events[i]; |
| 532 if (!this._isVisible(asyncEvent)) |
| 533 continue; |
| 534 if (!groupHeaderAppended) { |
| 535 this._appendHeader(header, style); |
| 536 groupHeaderAppended = true; |
| 537 } |
| 538 var startTime = asyncEvent.startTime; |
| 539 var level; |
| 540 for (level = 0; level < lastUsedTimeByLevel.length && lastUsedTimeByLevel[
level] > startTime; ++level) { |
| 541 } |
| 542 this._appendAsyncEvent(asyncEvent, this._currentLevel + level); |
| 543 lastUsedTimeByLevel[level] = asyncEvent.endTime; |
| 544 } |
| 545 this._entryTypeByLevel.length = this._currentLevel + lastUsedTimeByLevel.len
gth; |
| 546 this._entryTypeByLevel.fill(WebInspector.TimelineFlameChartEntryType.Event,
this._currentLevel); |
| 547 this._currentLevel += lastUsedTimeByLevel.length; |
| 548 } |
| 549 |
| 550 _appendGPUEvents() { |
| 551 if (this._appendSyncEvents(this._model.gpuEvents(), WebInspector.UIString('G
PU'), this._headerLevel1, false)) |
| 552 ++this._currentLevel; |
| 553 } |
| 554 |
| 555 _appendInteractionRecords() { |
| 556 this._irModel.interactionRecords().forEach(this._appendSegment, this); |
| 557 this._entryTypeByLevel[this._currentLevel++] = WebInspector.TimelineFlameCha
rtEntryType.InteractionRecord; |
| 558 } |
| 559 |
| 560 /** |
| 561 * @param {!Array.<!WebInspector.TimelineFrame>} frames |
| 562 */ |
| 563 _appendFrameBars(frames) { |
| 564 var style = WebInspector.TimelineUIUtils.markerStyleForFrame(); |
| 565 this._entryTypeByLevel[this._currentLevel] = WebInspector.TimelineFlameChart
EntryType.Frame; |
| 566 for (var i = 0; i < frames.length; ++i) { |
| 567 this._markers.push(new WebInspector.TimelineFlameChartMarker( |
| 568 frames[i].startTime, frames[i].startTime - this._model.minimumRecordTi
me(), style)); |
| 569 this._appendFrame(frames[i]); |
| 570 } |
| 571 ++this._currentLevel; |
| 572 } |
| 573 |
| 574 /** |
| 575 * @param {number} entryIndex |
| 576 * @return {!WebInspector.TimelineFlameChartEntryType} |
| 577 */ |
| 578 _entryType(entryIndex) { |
| 579 return this._entryTypeByLevel[this._timelineData.entryLevels[entryIndex]]; |
| 580 } |
| 581 |
| 582 /** |
| 583 * @override |
| 584 * @param {number} entryIndex |
| 585 * @return {?Element} |
| 586 */ |
| 587 prepareHighlightedEntryInfo(entryIndex) { |
| 588 var time = ''; |
| 589 var title; |
| 590 var warning; |
| 591 var type = this._entryType(entryIndex); |
| 592 if (type === WebInspector.TimelineFlameChartEntryType.Event) { |
| 593 var event = /** @type {!WebInspector.TracingModel.Event} */ (this._entryDa
ta[entryIndex]); |
| 594 var totalTime = event.duration; |
| 595 var selfTime = event.selfTime; |
| 596 var /** @const */ eps = 1e-6; |
| 597 if (typeof totalTime === 'number') { |
| 598 time = Math.abs(totalTime - selfTime) > eps && selfTime > eps ? |
| 599 WebInspector.UIString( |
| 600 '%s (self %s)', Number.millisToString(totalTime, true), Number.m
illisToString(selfTime, true)) : |
| 601 Number.millisToString(totalTime, true); |
| 602 } |
| 603 title = this.entryTitle(entryIndex); |
| 604 warning = WebInspector.TimelineUIUtils.eventWarning(event); |
| 605 } else if (type === WebInspector.TimelineFlameChartEntryType.Frame) { |
| 606 var frame = /** @type {!WebInspector.TimelineFrame} */ (this._entryData[en
tryIndex]); |
| 607 time = WebInspector.UIString( |
| 608 '%s ~ %.0f\u2009fps', Number.preciseMillisToString(frame.duration, 1),
(1000 / frame.duration)); |
| 609 title = frame.idle ? WebInspector.UIString('Idle Frame') : WebInspector.UI
String('Frame'); |
| 610 if (frame.hasWarnings()) { |
| 611 warning = createElement('span'); |
| 612 warning.textContent = WebInspector.UIString('Long frame'); |
| 613 } |
| 614 } else { |
| 615 return null; |
| 616 } |
| 617 var element = createElement('div'); |
| 618 var root = WebInspector.createShadowRootWithCoreStyles(element, 'timeline/ti
melineFlamechartPopover.css'); |
| 619 var contents = root.createChild('div', 'timeline-flamechart-popover'); |
| 620 contents.createChild('span', 'timeline-info-time').textContent = time; |
| 621 contents.createChild('span', 'timeline-info-title').textContent = title; |
| 622 if (warning) { |
| 623 warning.classList.add('timeline-info-warning'); |
| 624 contents.appendChild(warning); |
| 625 } |
| 626 return element; |
| 627 } |
| 628 |
| 629 /** |
| 630 * @override |
| 631 * @param {number} entryIndex |
| 632 * @return {string} |
| 633 */ |
| 634 entryColor(entryIndex) { |
| 635 // This is not annotated due to closure compiler failure to properly infer c
ache container's template type. |
| 636 function patchColorAndCache(cache, key, lookupColor) { |
| 637 var color = cache.get(key); |
| 638 if (color) |
| 639 return color; |
| 640 var parsedColor = WebInspector.Color.parse(lookupColor(key)); |
| 641 color = parsedColor.setAlpha(0.7).asString(WebInspector.Color.Format.RGBA)
|| ''; |
| 642 cache.set(key, color); |
| 643 return color; |
| 644 } |
| 645 |
| 646 var type = this._entryType(entryIndex); |
| 647 if (type === WebInspector.TimelineFlameChartEntryType.Event) { |
| 648 var event = /** @type {!WebInspector.TracingModel.Event} */ (this._entryDa
ta[entryIndex]); |
| 649 if (!WebInspector.TracingModel.isAsyncPhase(event.phase)) |
| 650 return WebInspector.TimelineUIUtils.eventColor(event); |
| 651 if (event.hasCategory(WebInspector.TimelineModel.Category.Console) || |
| 652 event.hasCategory(WebInspector.TimelineModel.Category.UserTiming)) |
| 653 return this._consoleColorGenerator.colorForID(event.name); |
| 654 if (event.hasCategory(WebInspector.TimelineModel.Category.LatencyInfo)) { |
| 655 var phase = |
| 656 WebInspector.TimelineIRModel.phaseForEvent(event) || WebInspector.Ti
melineIRModel.Phases.Uncategorized; |
| 657 return patchColorAndCache( |
| 658 this._asyncColorByInteractionPhase, phase, WebInspector.TimelineUIUt
ils.interactionPhaseColor); |
| 659 } |
| 660 var category = WebInspector.TimelineUIUtils.eventStyle(event).category; |
| 661 return patchColorAndCache(this._asyncColorByCategory, category, () => cate
gory.color); |
| 662 } |
| 663 if (type === WebInspector.TimelineFlameChartEntryType.Frame) |
| 664 return 'white'; |
| 665 if (type === WebInspector.TimelineFlameChartEntryType.InteractionRecord) |
| 666 return 'transparent'; |
| 667 return ''; |
| 668 } |
| 669 |
| 670 /** |
| 671 * @override |
| 672 * @param {number} entryIndex |
| 673 * @param {!CanvasRenderingContext2D} context |
| 674 * @param {?string} text |
| 675 * @param {number} barX |
| 676 * @param {number} barY |
| 677 * @param {number} barWidth |
| 678 * @param {number} barHeight |
| 679 * @param {number} unclippedBarX |
| 680 * @param {number} timeToPixels |
| 681 * @return {boolean} |
| 682 */ |
| 683 decorateEntry(entryIndex, context, text, barX, barY, barWidth, barHeight, uncl
ippedBarX, timeToPixels) { |
| 684 var data = this._entryData[entryIndex]; |
| 685 var type = this._entryType(entryIndex); |
| 686 if (type === WebInspector.TimelineFlameChartEntryType.Frame) { |
| 687 var /** @const */ vPadding = 1; |
| 688 var /** @const */ hPadding = 1; |
| 689 var frame = /** {!WebInspector.TimelineFrame} */ (data); |
| 690 barX += hPadding; |
| 691 barWidth -= 2 * hPadding; |
| 692 barY += vPadding; |
| 693 barHeight -= 2 * vPadding + 1; |
| 694 context.fillStyle = frame.idle ? 'white' : (frame.hasWarnings() ? '#fad1d1
' : '#d7f0d1'); |
| 695 context.fillRect(barX, barY, barWidth, barHeight); |
| 696 var frameDurationText = Number.preciseMillisToString(frame.duration, 1); |
| 697 var textWidth = context.measureText(frameDurationText).width; |
| 698 if (barWidth >= textWidth) { |
| 699 context.fillStyle = this.textColor(entryIndex); |
| 700 context.fillText(frameDurationText, barX + (barWidth - textWidth) / 2, b
arY + barHeight - 3); |
| 701 } |
| 702 return true; |
| 703 } |
| 704 |
| 705 if (type === WebInspector.TimelineFlameChartEntryType.InteractionRecord) { |
| 706 var color = WebInspector.TimelineUIUtils.interactionPhaseColor( |
| 707 /** @type {!WebInspector.TimelineIRModel.Phases} */ (this._entryData[e
ntryIndex])); |
| 708 context.fillStyle = color; |
| 709 context.fillRect(barX, barY, barWidth - 1, 2); |
| 710 context.fillRect(barX, barY - 3, 2, 3); |
| 711 context.fillRect(barX + barWidth - 3, barY - 3, 2, 3); |
| 712 return false; |
| 713 } |
| 714 |
| 715 if (type === WebInspector.TimelineFlameChartEntryType.Event) { |
| 716 var event = /** @type {!WebInspector.TracingModel.Event} */ (this._entryDa
ta[entryIndex]); |
| 717 if (event.hasCategory(WebInspector.TimelineModel.Category.LatencyInfo) &&
event.timeWaitingForMainThread) { |
| 718 context.fillStyle = 'hsla(0, 70%, 60%, 1)'; |
| 719 var width = Math.floor(unclippedBarX - barX + event.timeWaitingForMainTh
read * timeToPixels); |
| 720 context.fillRect(barX, barY + barHeight - 3, width, 2); |
| 721 } |
| 722 if (event.warning) |
| 723 paintWarningDecoration(barX, barWidth - 1.5); |
| 724 } |
347 | 725 |
348 /** | 726 /** |
349 * @override | 727 * @param {number} x |
350 * @param {number} index | 728 * @param {number} width |
351 * @return {string} | |
352 */ | 729 */ |
353 textColor: function(index) | 730 function paintWarningDecoration(x, width) { |
354 { | 731 var /** @const */ triangleSize = 8; |
355 var event = this._entryData[index]; | 732 context.save(); |
356 if (event && event._blackboxRoot) | 733 context.beginPath(); |
357 return "#888"; | 734 context.rect(x, barY, width, barHeight); |
358 else | 735 context.clip(); |
359 return WebInspector.TimelineFlameChartDataProviderBase.prototype.tex
tColor.call(this, index); | 736 context.beginPath(); |
360 }, | 737 context.fillStyle = 'red'; |
361 | 738 context.moveTo(x + width - triangleSize, barY); |
362 /** | 739 context.lineTo(x + width, barY); |
363 * @override | 740 context.lineTo(x + width, barY + triangleSize); |
364 */ | 741 context.fill(); |
365 reset: function() | 742 context.restore(); |
366 { | 743 } |
367 WebInspector.TimelineFlameChartDataProviderBase.prototype.reset.call(thi
s); | 744 |
368 /** @type {!Array<!WebInspector.TracingModel.Event|!WebInspector.Timelin
eFrame|!WebInspector.TimelineIRModel.Phases>} */ | 745 return false; |
369 this._entryData = []; | 746 } |
370 /** @type {!Array<!WebInspector.TimelineFlameChartEntryType>} */ | 747 |
371 this._entryTypeByLevel = []; | 748 /** |
372 /** @type {!Array<string>} */ | 749 * @override |
373 this._entryIndexToTitle = []; | 750 * @param {number} entryIndex |
374 /** @type {!Array<!WebInspector.TimelineFlameChartMarker>} */ | 751 * @return {boolean} |
375 this._markers = []; | 752 */ |
376 /** @type {!Map<!WebInspector.TimelineCategory, string>} */ | 753 forceDecoration(entryIndex) { |
377 this._asyncColorByCategory = new Map(); | 754 var type = this._entryType(entryIndex); |
378 /** @type {!Map<!WebInspector.TimelineIRModel.Phases, string>} */ | 755 return type === WebInspector.TimelineFlameChartEntryType.Frame || |
379 this._asyncColorByInteractionPhase = new Map(); | 756 type === WebInspector.TimelineFlameChartEntryType.Event && |
380 }, | 757 !!(/** @type {!WebInspector.TracingModel.Event} */ (this._entryData[entr
yIndex]).warning); |
381 | 758 } |
382 /** | 759 |
383 * @override | 760 /** |
384 * @return {!WebInspector.FlameChart.TimelineData} | 761 * @param {string} title |
385 */ | 762 * @param {!WebInspector.FlameChart.GroupStyle} style |
386 timelineData: function() | 763 * @param {boolean=} expanded |
387 { | 764 */ |
388 if (this._timelineData) | 765 _appendHeader(title, style, expanded) { |
389 return this._timelineData; | 766 this._timelineData.groups.push({startLevel: this._currentLevel, name: title,
expanded: expanded, style: style}); |
390 | 767 } |
391 this._timelineData = new WebInspector.FlameChart.TimelineData([], [], []
, []); | 768 |
392 | 769 /** |
393 this._flowEventIndexById = {}; | 770 * @param {!WebInspector.TracingModel.Event} event |
394 this._minimumBoundary = this._model.minimumRecordTime(); | 771 * @param {number} level |
395 this._timeSpan = this._model.isEmpty() ? 1000 : this._model.maximumReco
rdTime() - this._minimumBoundary; | 772 */ |
396 this._currentLevel = 0; | 773 _appendEvent(event, level) { |
397 this._appendFrameBars(this._frameModel.frames()); | 774 var index = this._entryData.length; |
398 | 775 this._entryData.push(event); |
399 this._appendHeader(WebInspector.UIString("Interactions"), this._interact
ionsHeaderLevel1); | 776 this._timelineData.entryLevels[index] = level; |
400 this._appendInteractionRecords(); | 777 var duration; |
401 | 778 if (WebInspector.TimelineModel.isMarkerEvent(event)) |
402 var asyncEventGroups = WebInspector.TimelineModel.AsyncEventGroup; | 779 duration = undefined; |
403 var inputLatencies = this._model.mainThreadAsyncEvents().get(asyncEventG
roups.input); | 780 else |
404 if (inputLatencies && inputLatencies.length) { | 781 duration = event.duration || WebInspector.TimelineFlameChartDataProvider.I
nstantEventVisibleDurationMs; |
405 var title = WebInspector.TimelineUIUtils.titleForAsyncEventGroup(asy
ncEventGroups.input); | 782 this._timelineData.entryTotalTimes[index] = duration; |
406 this._appendAsyncEventsGroup(title, inputLatencies, this._interactio
nsHeaderLevel2); | 783 this._timelineData.entryStartTimes[index] = event.startTime; |
407 } | 784 } |
408 var animations = this._model.mainThreadAsyncEvents().get(asyncEventGroup
s.animation); | 785 |
409 if (animations && animations.length) { | 786 /** |
410 var title = WebInspector.TimelineUIUtils.titleForAsyncEventGroup(asy
ncEventGroups.animation); | 787 * @param {!WebInspector.TracingModel.Event} event |
411 this._appendAsyncEventsGroup(title, animations, this._interactionsHe
aderLevel2); | 788 * @param {number} level |
412 } | 789 */ |
413 var threads = this._model.virtualThreads(); | 790 _appendFlowEvent(event, level) { |
414 this._appendThreadTimelineData(WebInspector.UIString("Main"), this._mode
l.mainThreadEvents(), this._model.mainThreadAsyncEvents(), true); | 791 var timelineData = this._timelineData; |
415 var compositorThreads = threads.filter(thread => thread.name.startsWith(
"CompositorTileWorker")); | |
416 var otherThreads = threads.filter(thread => !thread.name.startsWith("Com
positorTileWorker")); | |
417 if (compositorThreads.length) { | |
418 this._appendHeader(WebInspector.UIString("Raster"), this._headerLeve
l1); | |
419 for (var i = 0; i < compositorThreads.length; ++i) | |
420 this._appendSyncEvents(compositorThreads[i].events, WebInspector
.UIString("Rasterizer Thread %d", i), this._headerLevel2); | |
421 } | |
422 this._appendGPUEvents(); | |
423 | |
424 otherThreads.forEach(thread => this._appendThreadTimelineData(thread.nam
e, thread.events, thread.asyncEventsByGroup)); | |
425 | |
426 /** | |
427 * @param {!WebInspector.TimelineFlameChartMarker} a | |
428 * @param {!WebInspector.TimelineFlameChartMarker} b | |
429 */ | |
430 function compareStartTime(a, b) | |
431 { | |
432 return a.startTime() - b.startTime(); | |
433 } | |
434 | |
435 this._markers.sort(compareStartTime); | |
436 this._timelineData.markers = this._markers; | |
437 | |
438 this._flowEventIndexById = {}; | |
439 return this._timelineData; | |
440 }, | |
441 | |
442 /** | |
443 * @param {string} threadTitle | |
444 * @param {!Array<!WebInspector.TracingModel.Event>} syncEvents | |
445 * @param {!Map<!WebInspector.TimelineModel.AsyncEventGroup, !Array<!WebInsp
ector.TracingModel.AsyncEvent>>} asyncEvents | |
446 * @param {boolean=} forceExpanded | |
447 */ | |
448 _appendThreadTimelineData: function(threadTitle, syncEvents, asyncEvents, fo
rceExpanded) | |
449 { | |
450 this._appendAsyncEvents(asyncEvents); | |
451 this._appendSyncEvents(syncEvents, threadTitle, this._headerLevel1, forc
eExpanded); | |
452 }, | |
453 | |
454 /** | |
455 * @param {!Array<!WebInspector.TracingModel.Event>} events | |
456 * @param {string} title | |
457 * @param {!WebInspector.FlameChart.GroupStyle} style | |
458 * @param {boolean=} forceExpanded | |
459 */ | |
460 _appendSyncEvents: function(events, title, style, forceExpanded) | |
461 { | |
462 var openEvents = []; | |
463 var flowEventsEnabled = Runtime.experiments.isEnabled("timelineFlowEvent
s"); | |
464 var blackboxingEnabled = Runtime.experiments.isEnabled("blackboxJSFrames
OnTimeline"); | |
465 var maxStackDepth = 0; | |
466 for (var i = 0; i < events.length; ++i) { | |
467 var e = events[i]; | |
468 if (WebInspector.TimelineModel.isMarkerEvent(e)) | |
469 this._markers.push(new WebInspector.TimelineFlameChartMarker(e.s
tartTime, e.startTime - this._model.minimumRecordTime(), WebInspector.TimelineUI
Utils.markerStyleForEvent(e))); | |
470 if (!WebInspector.TracingModel.isFlowPhase(e.phase)) { | |
471 if (!e.endTime && e.phase !== WebInspector.TracingModel.Phase.In
stant) | |
472 continue; | |
473 if (WebInspector.TracingModel.isAsyncPhase(e.phase)) | |
474 continue; | |
475 if (!this._isVisible(e)) | |
476 continue; | |
477 } | |
478 while (openEvents.length && openEvents.peekLast().endTime <= e.start
Time) | |
479 openEvents.pop(); | |
480 e._blackboxRoot = false; | |
481 if (blackboxingEnabled && this._isBlackboxedEvent(e)) { | |
482 var parent = openEvents.peekLast(); | |
483 if (parent && parent._blackboxRoot) | |
484 continue; | |
485 e._blackboxRoot = true; | |
486 } | |
487 if (title) { | |
488 this._appendHeader(title, style, forceExpanded); | |
489 title = ""; | |
490 } | |
491 | |
492 var level = this._currentLevel + openEvents.length; | |
493 this._appendEvent(e, level); | |
494 if (flowEventsEnabled) | |
495 this._appendFlowEvent(e, level); | |
496 maxStackDepth = Math.max(maxStackDepth, openEvents.length + 1); | |
497 if (e.endTime) | |
498 openEvents.push(e); | |
499 } | |
500 this._entryTypeByLevel.length = this._currentLevel + maxStackDepth; | |
501 this._entryTypeByLevel.fill(WebInspector.TimelineFlameChartEntryType.Eve
nt, this._currentLevel); | |
502 this._currentLevel += maxStackDepth; | |
503 }, | |
504 | |
505 /** | 792 /** |
506 * @param {!WebInspector.TracingModel.Event} event | 793 * @param {!WebInspector.TracingModel.Event} event |
507 * @return {boolean} | 794 * @return {number} |
508 */ | 795 */ |
509 _isBlackboxedEvent: function(event) | 796 function pushStartFlow(event) { |
510 { | 797 var flowIndex = timelineData.flowStartTimes.length; |
511 if (event.name !== WebInspector.TimelineModel.RecordType.JSFrame) | 798 timelineData.flowStartTimes.push(event.startTime); |
512 return false; | 799 timelineData.flowStartLevels.push(level); |
513 var url = event.args["data"]["url"]; | 800 return flowIndex; |
514 return url && this._isBlackboxedURL(url); | 801 } |
515 }, | |
516 | |
517 /** | |
518 * @param {string} url | |
519 * @return {boolean} | |
520 */ | |
521 _isBlackboxedURL: function(url) | |
522 { | |
523 return WebInspector.blackboxManager.isBlackboxedURL(url); | |
524 }, | |
525 | |
526 /** | |
527 * @param {!Map<!WebInspector.TimelineModel.AsyncEventGroup, !Array<!WebInsp
ector.TracingModel.AsyncEvent>>} asyncEvents | |
528 */ | |
529 _appendAsyncEvents: function(asyncEvents) | |
530 { | |
531 var groups = WebInspector.TimelineModel.AsyncEventGroup; | |
532 var groupArray = Object.keys(groups).map(key => groups[key]); | |
533 | |
534 groupArray.remove(groups.animation); | |
535 groupArray.remove(groups.input); | |
536 | |
537 for (var groupIndex = 0; groupIndex < groupArray.length; ++groupIndex) { | |
538 var group = groupArray[groupIndex]; | |
539 var events = asyncEvents.get(group); | |
540 if (!events) | |
541 continue; | |
542 var title = WebInspector.TimelineUIUtils.titleForAsyncEventGroup(gro
up); | |
543 this._appendAsyncEventsGroup(title, events, this._headerLevel1); | |
544 } | |
545 }, | |
546 | |
547 /** | |
548 * @param {string} header | |
549 * @param {!Array<!WebInspector.TracingModel.AsyncEvent>} events | |
550 * @param {!WebInspector.FlameChart.GroupStyle} style | |
551 */ | |
552 _appendAsyncEventsGroup: function(header, events, style) | |
553 { | |
554 var lastUsedTimeByLevel = []; | |
555 var groupHeaderAppended = false; | |
556 for (var i = 0; i < events.length; ++i) { | |
557 var asyncEvent = events[i]; | |
558 if (!this._isVisible(asyncEvent)) | |
559 continue; | |
560 if (!groupHeaderAppended) { | |
561 this._appendHeader(header, style); | |
562 groupHeaderAppended = true; | |
563 } | |
564 var startTime = asyncEvent.startTime; | |
565 var level; | |
566 for (level = 0; level < lastUsedTimeByLevel.length && lastUsedTimeBy
Level[level] > startTime; ++level) {} | |
567 this._appendAsyncEvent(asyncEvent, this._currentLevel + level); | |
568 lastUsedTimeByLevel[level] = asyncEvent.endTime; | |
569 } | |
570 this._entryTypeByLevel.length = this._currentLevel + lastUsedTimeByLevel
.length; | |
571 this._entryTypeByLevel.fill(WebInspector.TimelineFlameChartEntryType.Eve
nt, this._currentLevel); | |
572 this._currentLevel += lastUsedTimeByLevel.length; | |
573 }, | |
574 | |
575 _appendGPUEvents: function() | |
576 { | |
577 if (this._appendSyncEvents(this._model.gpuEvents(), WebInspector.UIStrin
g("GPU"), this._headerLevel1, false)) | |
578 ++this._currentLevel; | |
579 }, | |
580 | |
581 _appendInteractionRecords: function() | |
582 { | |
583 this._irModel.interactionRecords().forEach(this._appendSegment, this); | |
584 this._entryTypeByLevel[this._currentLevel++] = WebInspector.TimelineFlam
eChartEntryType.InteractionRecord; | |
585 }, | |
586 | |
587 /** | |
588 * @param {!Array.<!WebInspector.TimelineFrame>} frames | |
589 */ | |
590 _appendFrameBars: function(frames) | |
591 { | |
592 var style = WebInspector.TimelineUIUtils.markerStyleForFrame(); | |
593 this._entryTypeByLevel[this._currentLevel] = WebInspector.TimelineFlameC
hartEntryType.Frame; | |
594 for (var i = 0; i < frames.length; ++i) { | |
595 this._markers.push(new WebInspector.TimelineFlameChartMarker(frames[
i].startTime, frames[i].startTime - this._model.minimumRecordTime(), style)); | |
596 this._appendFrame(frames[i]); | |
597 } | |
598 ++this._currentLevel; | |
599 }, | |
600 | |
601 /** | |
602 * @param {number} entryIndex | |
603 * @return {!WebInspector.TimelineFlameChartEntryType} | |
604 */ | |
605 _entryType: function(entryIndex) | |
606 { | |
607 return this._entryTypeByLevel[this._timelineData.entryLevels[entryIndex]
]; | |
608 }, | |
609 | |
610 /** | |
611 * @override | |
612 * @param {number} entryIndex | |
613 * @return {?Element} | |
614 */ | |
615 prepareHighlightedEntryInfo: function(entryIndex) | |
616 { | |
617 var time = ""; | |
618 var title; | |
619 var warning; | |
620 var type = this._entryType(entryIndex); | |
621 if (type === WebInspector.TimelineFlameChartEntryType.Event) { | |
622 var event = /** @type {!WebInspector.TracingModel.Event} */ (this._e
ntryData[entryIndex]); | |
623 var totalTime = event.duration; | |
624 var selfTime = event.selfTime; | |
625 var /** @const */ eps = 1e-6; | |
626 if (typeof totalTime === "number") { | |
627 time = Math.abs(totalTime - selfTime) > eps && selfTime > eps ? | |
628 WebInspector.UIString("%s (self %s)", Number.millisToString(
totalTime, true), Number.millisToString(selfTime, true)) : | |
629 Number.millisToString(totalTime, true); | |
630 } | |
631 title = this.entryTitle(entryIndex); | |
632 warning = WebInspector.TimelineUIUtils.eventWarning(event); | |
633 } else if (type === WebInspector.TimelineFlameChartEntryType.Frame) { | |
634 var frame = /** @type {!WebInspector.TimelineFrame} */ (this._entryD
ata[entryIndex]); | |
635 time = WebInspector.UIString("%s ~ %.0f\u2009fps", Number.preciseMil
lisToString(frame.duration, 1), (1000 / frame.duration)); | |
636 title = frame.idle ? WebInspector.UIString("Idle Frame") : WebInspec
tor.UIString("Frame"); | |
637 if (frame.hasWarnings()) { | |
638 warning = createElement("span"); | |
639 warning.textContent = WebInspector.UIString("Long frame"); | |
640 } | |
641 } else { | |
642 return null; | |
643 } | |
644 var element = createElement("div"); | |
645 var root = WebInspector.createShadowRootWithCoreStyles(element, "timelin
e/timelineFlamechartPopover.css"); | |
646 var contents = root.createChild("div", "timeline-flamechart-popover"); | |
647 contents.createChild("span", "timeline-info-time").textContent = time; | |
648 contents.createChild("span", "timeline-info-title").textContent = title; | |
649 if (warning) { | |
650 warning.classList.add("timeline-info-warning"); | |
651 contents.appendChild(warning); | |
652 } | |
653 return element; | |
654 }, | |
655 | |
656 /** | |
657 * @override | |
658 * @param {number} entryIndex | |
659 * @return {string} | |
660 */ | |
661 entryColor: function(entryIndex) | |
662 { | |
663 // This is not annotated due to closure compiler failure to properly inf
er cache container's template type. | |
664 function patchColorAndCache(cache, key, lookupColor) | |
665 { | |
666 var color = cache.get(key); | |
667 if (color) | |
668 return color; | |
669 var parsedColor = WebInspector.Color.parse(lookupColor(key)); | |
670 color = parsedColor.setAlpha(0.7).asString(WebInspector.Color.Format
.RGBA) || ""; | |
671 cache.set(key, color); | |
672 return color; | |
673 } | |
674 | |
675 var type = this._entryType(entryIndex); | |
676 if (type === WebInspector.TimelineFlameChartEntryType.Event) { | |
677 var event = /** @type {!WebInspector.TracingModel.Event} */ (this._e
ntryData[entryIndex]); | |
678 if (!WebInspector.TracingModel.isAsyncPhase(event.phase)) | |
679 return WebInspector.TimelineUIUtils.eventColor(event); | |
680 if (event.hasCategory(WebInspector.TimelineModel.Category.Console) |
| event.hasCategory(WebInspector.TimelineModel.Category.UserTiming)) | |
681 return this._consoleColorGenerator.colorForID(event.name); | |
682 if (event.hasCategory(WebInspector.TimelineModel.Category.LatencyInf
o)) { | |
683 var phase = WebInspector.TimelineIRModel.phaseForEvent(event) ||
WebInspector.TimelineIRModel.Phases.Uncategorized; | |
684 return patchColorAndCache(this._asyncColorByInteractionPhase, ph
ase, WebInspector.TimelineUIUtils.interactionPhaseColor); | |
685 } | |
686 var category = WebInspector.TimelineUIUtils.eventStyle(event).catego
ry; | |
687 return patchColorAndCache(this._asyncColorByCategory, category, () =
> category.color); | |
688 } | |
689 if (type === WebInspector.TimelineFlameChartEntryType.Frame) | |
690 return "white"; | |
691 if (type === WebInspector.TimelineFlameChartEntryType.InteractionRecord) | |
692 return "transparent"; | |
693 return ""; | |
694 }, | |
695 | |
696 /** | |
697 * @override | |
698 * @param {number} entryIndex | |
699 * @param {!CanvasRenderingContext2D} context | |
700 * @param {?string} text | |
701 * @param {number} barX | |
702 * @param {number} barY | |
703 * @param {number} barWidth | |
704 * @param {number} barHeight | |
705 * @param {number} unclippedBarX | |
706 * @param {number} timeToPixels | |
707 * @return {boolean} | |
708 */ | |
709 decorateEntry: function(entryIndex, context, text, barX, barY, barWidth, bar
Height, unclippedBarX, timeToPixels) | |
710 { | |
711 var data = this._entryData[entryIndex]; | |
712 var type = this._entryType(entryIndex); | |
713 if (type === WebInspector.TimelineFlameChartEntryType.Frame) { | |
714 var /** @const */ vPadding = 1; | |
715 var /** @const */ hPadding = 1; | |
716 var frame = /** {!WebInspector.TimelineFrame} */ (data); | |
717 barX += hPadding; | |
718 barWidth -= 2 * hPadding; | |
719 barY += vPadding; | |
720 barHeight -= 2 * vPadding + 1; | |
721 context.fillStyle = frame.idle ? "white" : (frame.hasWarnings() ? "#
fad1d1" : "#d7f0d1"); | |
722 context.fillRect(barX, barY, barWidth, barHeight); | |
723 var frameDurationText = Number.preciseMillisToString(frame.duration,
1); | |
724 var textWidth = context.measureText(frameDurationText).width; | |
725 if (barWidth >= textWidth) { | |
726 context.fillStyle = this.textColor(entryIndex); | |
727 context.fillText(frameDurationText, barX + (barWidth - textWidth
) / 2, barY + barHeight - 3); | |
728 } | |
729 return true; | |
730 } | |
731 | |
732 if (type === WebInspector.TimelineFlameChartEntryType.InteractionRecord)
{ | |
733 var color = WebInspector.TimelineUIUtils.interactionPhaseColor(/** @
type {!WebInspector.TimelineIRModel.Phases} */ (this._entryData[entryIndex])); | |
734 context.fillStyle = color; | |
735 context.fillRect(barX, barY, barWidth - 1, 2); | |
736 context.fillRect(barX, barY - 3, 2, 3); | |
737 context.fillRect(barX + barWidth - 3, barY - 3, 2, 3); | |
738 return false; | |
739 } | |
740 | |
741 if (type === WebInspector.TimelineFlameChartEntryType.Event) { | |
742 var event = /** @type {!WebInspector.TracingModel.Event} */ (this._e
ntryData[entryIndex]); | |
743 if (event.hasCategory(WebInspector.TimelineModel.Category.LatencyInf
o) && event.timeWaitingForMainThread) { | |
744 context.fillStyle = "hsla(0, 70%, 60%, 1)"; | |
745 var width = Math.floor(unclippedBarX - barX + event.timeWaitingF
orMainThread * timeToPixels); | |
746 context.fillRect(barX, barY + barHeight - 3, width, 2); | |
747 } | |
748 if (event.warning) | |
749 paintWarningDecoration(barX, barWidth - 1.5); | |
750 } | |
751 | |
752 /** | |
753 * @param {number} x | |
754 * @param {number} width | |
755 */ | |
756 function paintWarningDecoration(x, width) | |
757 { | |
758 var /** @const */ triangleSize = 8; | |
759 context.save(); | |
760 context.beginPath(); | |
761 context.rect(x, barY, width, barHeight); | |
762 context.clip(); | |
763 context.beginPath(); | |
764 context.fillStyle = "red"; | |
765 context.moveTo(x + width - triangleSize, barY); | |
766 context.lineTo(x + width, barY); | |
767 context.lineTo(x + width, barY + triangleSize); | |
768 context.fill(); | |
769 context.restore(); | |
770 } | |
771 | |
772 return false; | |
773 }, | |
774 | |
775 /** | |
776 * @override | |
777 * @param {number} entryIndex | |
778 * @return {boolean} | |
779 */ | |
780 forceDecoration: function(entryIndex) | |
781 { | |
782 var type = this._entryType(entryIndex); | |
783 return type === WebInspector.TimelineFlameChartEntryType.Frame || | |
784 type === WebInspector.TimelineFlameChartEntryType.Event && !!(/** @t
ype {!WebInspector.TracingModel.Event} */ (this._entryData[entryIndex]).warning)
; | |
785 }, | |
786 | |
787 /** | |
788 * @param {string} title | |
789 * @param {!WebInspector.FlameChart.GroupStyle} style | |
790 * @param {boolean=} expanded | |
791 */ | |
792 _appendHeader: function(title, style, expanded) | |
793 { | |
794 this._timelineData.groups.push({startLevel: this._currentLevel, name: ti
tle, expanded: expanded, style: style}); | |
795 }, | |
796 | 802 |
797 /** | 803 /** |
798 * @param {!WebInspector.TracingModel.Event} event | 804 * @param {!WebInspector.TracingModel.Event} event |
799 * @param {number} level | 805 * @param {number} flowIndex |
800 */ | 806 */ |
801 _appendEvent: function(event, level) | 807 function pushEndFlow(event, flowIndex) { |
802 { | 808 timelineData.flowEndTimes[flowIndex] = event.startTime; |
803 var index = this._entryData.length; | 809 timelineData.flowEndLevels[flowIndex] = level; |
804 this._entryData.push(event); | 810 } |
805 this._timelineData.entryLevels[index] = level; | 811 |
806 var duration; | 812 switch (event.phase) { |
807 if (WebInspector.TimelineModel.isMarkerEvent(event)) | 813 case WebInspector.TracingModel.Phase.FlowBegin: |
808 duration = undefined; | 814 this._flowEventIndexById[event.id] = pushStartFlow(event); |
809 else | 815 break; |
810 duration = event.duration || WebInspector.TimelineFlameChartDataProv
ider.InstantEventVisibleDurationMs; | 816 case WebInspector.TracingModel.Phase.FlowStep: |
811 this._timelineData.entryTotalTimes[index] = duration; | 817 pushEndFlow(event, this._flowEventIndexById[event.id]); |
812 this._timelineData.entryStartTimes[index] = event.startTime; | 818 this._flowEventIndexById[event.id] = pushStartFlow(event); |
813 }, | 819 break; |
814 | 820 case WebInspector.TracingModel.Phase.FlowEnd: |
815 /** | 821 pushEndFlow(event, this._flowEventIndexById[event.id]); |
816 * @param {!WebInspector.TracingModel.Event} event | 822 delete this._flowEventIndexById[event.id]; |
817 * @param {number} level | 823 break; |
818 */ | 824 } |
819 _appendFlowEvent: function(event, level) | 825 } |
820 { | 826 |
821 var timelineData = this._timelineData; | 827 /** |
822 /** | 828 * @param {!WebInspector.TracingModel.AsyncEvent} asyncEvent |
823 * @param {!WebInspector.TracingModel.Event} event | 829 * @param {number} level |
824 * @return {number} | 830 */ |
825 */ | 831 _appendAsyncEvent(asyncEvent, level) { |
826 function pushStartFlow(event) | 832 if (WebInspector.TracingModel.isNestableAsyncPhase(asyncEvent.phase)) { |
827 { | 833 // FIXME: also add steps once we support event nesting in the FlameChart. |
828 var flowIndex = timelineData.flowStartTimes.length; | 834 this._appendEvent(asyncEvent, level); |
829 timelineData.flowStartTimes.push(event.startTime); | 835 return; |
830 timelineData.flowStartLevels.push(level); | 836 } |
831 return flowIndex; | 837 var steps = asyncEvent.steps; |
832 } | 838 // If we have past steps, put the end event for each range rather than start
one. |
833 | 839 var eventOffset = steps.length > 1 && steps[1].phase === WebInspector.Tracin
gModel.Phase.AsyncStepPast ? 1 : 0; |
834 /** | 840 for (var i = 0; i < steps.length - 1; ++i) { |
835 * @param {!WebInspector.TracingModel.Event} event | 841 var index = this._entryData.length; |
836 * @param {number} flowIndex | 842 this._entryData.push(steps[i + eventOffset]); |
837 */ | 843 var startTime = steps[i].startTime; |
838 function pushEndFlow(event, flowIndex) | 844 this._timelineData.entryLevels[index] = level; |
839 { | 845 this._timelineData.entryTotalTimes[index] = steps[i + 1].startTime - start
Time; |
840 timelineData.flowEndTimes[flowIndex] = event.startTime; | 846 this._timelineData.entryStartTimes[index] = startTime; |
841 timelineData.flowEndLevels[flowIndex] = level; | 847 } |
842 } | 848 } |
843 | 849 |
844 switch (event.phase) { | 850 /** |
845 case WebInspector.TracingModel.Phase.FlowBegin: | 851 * @param {!WebInspector.TimelineFrame} frame |
846 this._flowEventIndexById[event.id] = pushStartFlow(event); | 852 */ |
847 break; | 853 _appendFrame(frame) { |
848 case WebInspector.TracingModel.Phase.FlowStep: | 854 var index = this._entryData.length; |
849 pushEndFlow(event, this._flowEventIndexById[event.id]); | 855 this._entryData.push(frame); |
850 this._flowEventIndexById[event.id] = pushStartFlow(event); | 856 this._entryIndexToTitle[index] = Number.millisToString(frame.duration, true)
; |
851 break; | 857 this._timelineData.entryLevels[index] = this._currentLevel; |
852 case WebInspector.TracingModel.Phase.FlowEnd: | 858 this._timelineData.entryTotalTimes[index] = frame.duration; |
853 pushEndFlow(event, this._flowEventIndexById[event.id]); | 859 this._timelineData.entryStartTimes[index] = frame.startTime; |
854 delete this._flowEventIndexById[event.id]; | 860 } |
855 break; | 861 |
856 } | 862 /** |
857 }, | 863 * @param {!WebInspector.Segment} segment |
858 | 864 */ |
859 /** | 865 _appendSegment(segment) { |
860 * @param {!WebInspector.TracingModel.AsyncEvent} asyncEvent | 866 var index = this._entryData.length; |
861 * @param {number} level | 867 this._entryData.push(/** @type {!WebInspector.TimelineIRModel.Phases} */ (se
gment.data)); |
862 */ | 868 this._entryIndexToTitle[index] = /** @type {string} */ (segment.data); |
863 _appendAsyncEvent: function(asyncEvent, level) | 869 this._timelineData.entryLevels[index] = this._currentLevel; |
864 { | 870 this._timelineData.entryTotalTimes[index] = segment.end - segment.begin; |
865 if (WebInspector.TracingModel.isNestableAsyncPhase(asyncEvent.phase)) { | 871 this._timelineData.entryStartTimes[index] = segment.begin; |
866 // FIXME: also add steps once we support event nesting in the FlameC
hart. | 872 } |
867 this._appendEvent(asyncEvent, level); | 873 |
868 return; | 874 /** |
869 } | 875 * @override |
870 var steps = asyncEvent.steps; | 876 * @param {number} entryIndex |
871 // If we have past steps, put the end event for each range rather than s
tart one. | 877 * @return {?WebInspector.TimelineSelection} |
872 var eventOffset = steps.length > 1 && steps[1].phase === WebInspector.Tr
acingModel.Phase.AsyncStepPast ? 1 : 0; | 878 */ |
873 for (var i = 0; i < steps.length - 1; ++i) { | 879 createSelection(entryIndex) { |
874 var index = this._entryData.length; | 880 var type = this._entryType(entryIndex); |
875 this._entryData.push(steps[i + eventOffset]); | 881 var timelineSelection = null; |
876 var startTime = steps[i].startTime; | 882 if (type === WebInspector.TimelineFlameChartEntryType.Event) |
877 this._timelineData.entryLevels[index] = level; | 883 timelineSelection = WebInspector.TimelineSelection.fromTraceEvent( |
878 this._timelineData.entryTotalTimes[index] = steps[i + 1].startTime -
startTime; | 884 /** @type {!WebInspector.TracingModel.Event} */ (this._entryData[entry
Index])); |
879 this._timelineData.entryStartTimes[index] = startTime; | 885 else if (type === WebInspector.TimelineFlameChartEntryType.Frame) |
880 } | 886 timelineSelection = WebInspector.TimelineSelection.fromFrame( |
881 }, | 887 /** @type {!WebInspector.TimelineFrame} */ (this._entryData[entryIndex
])); |
882 | 888 if (timelineSelection) |
883 /** | 889 this._lastSelection = new WebInspector.TimelineFlameChartView.Selection(ti
melineSelection, entryIndex); |
884 * @param {!WebInspector.TimelineFrame} frame | 890 return timelineSelection; |
885 */ | 891 } |
886 _appendFrame: function(frame) | 892 |
887 { | 893 /** |
888 var index = this._entryData.length; | 894 * @param {?WebInspector.TimelineSelection} selection |
889 this._entryData.push(frame); | 895 * @return {number} |
890 this._entryIndexToTitle[index] = Number.millisToString(frame.duration, t
rue); | 896 */ |
891 this._timelineData.entryLevels[index] = this._currentLevel; | 897 entryIndexForSelection(selection) { |
892 this._timelineData.entryTotalTimes[index] = frame.duration; | 898 if (!selection || selection.type() === WebInspector.TimelineSelection.Type.R
ange) |
893 this._timelineData.entryStartTimes[index] = frame.startTime; | 899 return -1; |
894 }, | 900 |
895 | 901 if (this._lastSelection && this._lastSelection.timelineSelection.object() ==
= selection.object()) |
896 /** | 902 return this._lastSelection.entryIndex; |
897 * @param {!WebInspector.Segment} segment | 903 var index = this._entryData.indexOf( |
898 */ | 904 /** @type {!WebInspector.TracingModel.Event|!WebInspector.TimelineFrame|
!WebInspector.TimelineIRModel.Phases} */ |
899 _appendSegment: function(segment) | 905 (selection.object())); |
900 { | 906 if (index !== -1) |
901 var index = this._entryData.length; | 907 this._lastSelection = new WebInspector.TimelineFlameChartView.Selection(se
lection, index); |
902 this._entryData.push(/** @type {!WebInspector.TimelineIRModel.Phases} */
(segment.data)); | 908 return index; |
903 this._entryIndexToTitle[index] = /** @type {string} */ (segment.data); | 909 } |
904 this._timelineData.entryLevels[index] = this._currentLevel; | |
905 this._timelineData.entryTotalTimes[index] = segment.end - segment.begin; | |
906 this._timelineData.entryStartTimes[index] = segment.begin; | |
907 }, | |
908 | |
909 /** | |
910 * @override | |
911 * @param {number} entryIndex | |
912 * @return {?WebInspector.TimelineSelection} | |
913 */ | |
914 createSelection: function(entryIndex) | |
915 { | |
916 var type = this._entryType(entryIndex); | |
917 var timelineSelection = null; | |
918 if (type === WebInspector.TimelineFlameChartEntryType.Event) | |
919 timelineSelection = WebInspector.TimelineSelection.fromTraceEvent(/*
* @type {!WebInspector.TracingModel.Event} */ (this._entryData[entryIndex])); | |
920 else if (type === WebInspector.TimelineFlameChartEntryType.Frame) | |
921 timelineSelection = WebInspector.TimelineSelection.fromFrame(/** @ty
pe {!WebInspector.TimelineFrame} */ (this._entryData[entryIndex])); | |
922 if (timelineSelection) | |
923 this._lastSelection = new WebInspector.TimelineFlameChartView.Select
ion(timelineSelection, entryIndex); | |
924 return timelineSelection; | |
925 }, | |
926 | |
927 /** | |
928 * @param {?WebInspector.TimelineSelection} selection | |
929 * @return {number} | |
930 */ | |
931 entryIndexForSelection: function(selection) | |
932 { | |
933 if (!selection || selection.type() === WebInspector.TimelineSelection.Ty
pe.Range) | |
934 return -1; | |
935 | |
936 if (this._lastSelection && this._lastSelection.timelineSelection.object(
) === selection.object()) | |
937 return this._lastSelection.entryIndex; | |
938 var index = this._entryData.indexOf(/** @type {!WebInspector.TracingMode
l.Event|!WebInspector.TimelineFrame|!WebInspector.TimelineIRModel.Phases} */(sel
ection.object())); | |
939 if (index !== -1) | |
940 this._lastSelection = new WebInspector.TimelineFlameChartView.Select
ion(selection, index); | |
941 return index; | |
942 }, | |
943 | |
944 __proto__: WebInspector.TimelineFlameChartDataProviderBase.prototype | |
945 }; | 910 }; |
946 | 911 |
| 912 WebInspector.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs = 0.00
1; |
| 913 |
947 /** | 914 /** |
948 * @constructor | 915 * @unrestricted |
949 * @extends {WebInspector.TimelineFlameChartDataProviderBase} | |
950 * @param {!WebInspector.TimelineModel} model | |
951 */ | 916 */ |
952 WebInspector.TimelineFlameChartNetworkDataProvider = function(model) | 917 WebInspector.TimelineFlameChartNetworkDataProvider = class extends WebInspector.
TimelineFlameChartDataProviderBase { |
953 { | 918 /** |
954 WebInspector.TimelineFlameChartDataProviderBase.call(this, model, []); | 919 * @param {!WebInspector.TimelineModel} model |
955 var loadingCategory = WebInspector.TimelineUIUtils.categories()["loading"]; | 920 */ |
| 921 constructor(model) { |
| 922 super(model, []); |
| 923 var loadingCategory = WebInspector.TimelineUIUtils.categories()['loading']; |
956 this._waitingColor = loadingCategory.childColor; | 924 this._waitingColor = loadingCategory.childColor; |
957 this._processingColor = loadingCategory.color; | 925 this._processingColor = loadingCategory.color; |
| 926 } |
| 927 |
| 928 /** |
| 929 * @override |
| 930 * @return {!WebInspector.FlameChart.TimelineData} |
| 931 */ |
| 932 timelineData() { |
| 933 if (this._timelineData) |
| 934 return this._timelineData; |
| 935 /** @type {!Array<!WebInspector.TimelineModel.NetworkRequest>} */ |
| 936 this._requests = []; |
| 937 this._timelineData = new WebInspector.FlameChart.TimelineData([], [], [], []
); |
| 938 this._appendTimelineData(this._model.mainThreadEvents()); |
| 939 return this._timelineData; |
| 940 } |
| 941 |
| 942 /** |
| 943 * @override |
| 944 */ |
| 945 reset() { |
| 946 super.reset(); |
| 947 /** @type {!Array<!WebInspector.TimelineModel.NetworkRequest>} */ |
| 948 this._requests = []; |
| 949 } |
| 950 |
| 951 /** |
| 952 * @param {number} startTime |
| 953 * @param {number} endTime |
| 954 */ |
| 955 setWindowTimes(startTime, endTime) { |
| 956 this._startTime = startTime; |
| 957 this._endTime = endTime; |
| 958 this._updateTimelineData(); |
| 959 } |
| 960 |
| 961 /** |
| 962 * @override |
| 963 * @param {number} index |
| 964 * @return {?WebInspector.TimelineSelection} |
| 965 */ |
| 966 createSelection(index) { |
| 967 if (index === -1) |
| 968 return null; |
| 969 var request = this._requests[index]; |
| 970 this._lastSelection = new WebInspector.TimelineFlameChartView.Selection( |
| 971 WebInspector.TimelineSelection.fromNetworkRequest(request), index); |
| 972 return this._lastSelection.timelineSelection; |
| 973 } |
| 974 |
| 975 /** |
| 976 * @param {?WebInspector.TimelineSelection} selection |
| 977 * @return {number} |
| 978 */ |
| 979 entryIndexForSelection(selection) { |
| 980 if (!selection) |
| 981 return -1; |
| 982 |
| 983 if (this._lastSelection && this._lastSelection.timelineSelection.object() ==
= selection.object()) |
| 984 return this._lastSelection.entryIndex; |
| 985 |
| 986 if (selection.type() !== WebInspector.TimelineSelection.Type.NetworkRequest) |
| 987 return -1; |
| 988 var request = /** @type{!WebInspector.TimelineModel.NetworkRequest} */ (sele
ction.object()); |
| 989 var index = this._requests.indexOf(request); |
| 990 if (index !== -1) |
| 991 this._lastSelection = new WebInspector.TimelineFlameChartView.Selection( |
| 992 WebInspector.TimelineSelection.fromNetworkRequest(request), index); |
| 993 return index; |
| 994 } |
| 995 |
| 996 /** |
| 997 * @override |
| 998 * @param {number} index |
| 999 * @return {string} |
| 1000 */ |
| 1001 entryColor(index) { |
| 1002 var request = /** @type {!WebInspector.TimelineModel.NetworkRequest} */ (thi
s._requests[index]); |
| 1003 var category = WebInspector.TimelineUIUtils.networkRequestCategory(request); |
| 1004 return WebInspector.TimelineUIUtils.networkCategoryColor(category); |
| 1005 } |
| 1006 |
| 1007 /** |
| 1008 * @override |
| 1009 * @param {number} index |
| 1010 * @return {?string} |
| 1011 */ |
| 1012 entryTitle(index) { |
| 1013 var request = /** @type {!WebInspector.TimelineModel.NetworkRequest} */ (thi
s._requests[index]); |
| 1014 return request.url || null; |
| 1015 } |
| 1016 |
| 1017 /** |
| 1018 * @override |
| 1019 * @param {number} index |
| 1020 * @param {!CanvasRenderingContext2D} context |
| 1021 * @param {?string} text |
| 1022 * @param {number} barX |
| 1023 * @param {number} barY |
| 1024 * @param {number} barWidth |
| 1025 * @param {number} barHeight |
| 1026 * @param {number} unclippedBarX |
| 1027 * @param {number} timeToPixels |
| 1028 * @return {boolean} |
| 1029 */ |
| 1030 decorateEntry(index, context, text, barX, barY, barWidth, barHeight, unclipped
BarX, timeToPixels) { |
| 1031 var minTransferWidthPx = 2; |
| 1032 var request = /** @type {!WebInspector.TimelineModel.NetworkRequest} */ (thi
s._requests[index]); |
| 1033 var startTime = request.startTime; |
| 1034 var endTime = request.endTime; |
| 1035 var lastX = unclippedBarX; |
| 1036 context.fillStyle = 'hsla(0, 0%, 100%, 0.6)'; |
| 1037 for (var i = 0; i < request.children.length; ++i) { |
| 1038 var event = request.children[i]; |
| 1039 var t0 = event.startTime; |
| 1040 var t1 = event.endTime || event.startTime; |
| 1041 var x0 = Math.floor(unclippedBarX + (t0 - startTime) * timeToPixels - 1); |
| 1042 var x1 = Math.floor(unclippedBarX + (t1 - startTime) * timeToPixels + 1); |
| 1043 if (x0 > lastX) |
| 1044 context.fillRect(lastX, barY, x0 - lastX, barHeight); |
| 1045 lastX = x1; |
| 1046 } |
| 1047 var endX = unclippedBarX + (endTime - startTime) * timeToPixels; |
| 1048 if (endX > lastX) |
| 1049 context.fillRect(lastX, barY, Math.min(endX - lastX, 1e5), barHeight); |
| 1050 if (typeof request.priority === 'string') { |
| 1051 var color = this._colorForPriority(request.priority); |
| 1052 if (color) { |
| 1053 context.fillStyle = 'hsl(0, 0%, 100%)'; |
| 1054 context.fillRect(barX, barY, 4, 4); |
| 1055 context.fillStyle = color; |
| 1056 context.fillRect(barX, barY, 3, 3); |
| 1057 } |
| 1058 } |
| 1059 return false; |
| 1060 } |
| 1061 |
| 1062 /** |
| 1063 * @override |
| 1064 * @param {number} index |
| 1065 * @return {boolean} |
| 1066 */ |
| 1067 forceDecoration(index) { |
| 1068 return true; |
| 1069 } |
| 1070 |
| 1071 /** |
| 1072 * @override |
| 1073 * @param {number} index |
| 1074 * @return {?Element} |
| 1075 */ |
| 1076 prepareHighlightedEntryInfo(index) { |
| 1077 var /** @const */ maxURLChars = 80; |
| 1078 var request = /** @type {!WebInspector.TimelineModel.NetworkRequest} */ (thi
s._requests[index]); |
| 1079 if (!request.url) |
| 1080 return null; |
| 1081 var element = createElement('div'); |
| 1082 var root = WebInspector.createShadowRootWithCoreStyles(element, 'timeline/ti
melineFlamechartPopover.css'); |
| 1083 var contents = root.createChild('div', 'timeline-flamechart-popover'); |
| 1084 var duration = request.endTime - request.startTime; |
| 1085 if (request.startTime && isFinite(duration)) |
| 1086 contents.createChild('span', 'timeline-info-network-time').textContent = N
umber.millisToString(duration); |
| 1087 if (typeof request.priority === 'string') { |
| 1088 var div = contents.createChild('span'); |
| 1089 div.textContent = |
| 1090 WebInspector.uiLabelForPriority(/** @type {!NetworkAgent.ResourcePrior
ity} */ (request.priority)); |
| 1091 div.style.color = this._colorForPriority(request.priority) || 'black'; |
| 1092 } |
| 1093 contents.createChild('span').textContent = request.url.trimMiddle(maxURLChar
s); |
| 1094 return element; |
| 1095 } |
| 1096 |
| 1097 /** |
| 1098 * @param {string} priority |
| 1099 * @return {?string} |
| 1100 */ |
| 1101 _colorForPriority(priority) { |
| 1102 switch (/** @type {!NetworkAgent.ResourcePriority} */ (priority)) { |
| 1103 case NetworkAgent.ResourcePriority.VeryLow: |
| 1104 return '#080'; |
| 1105 case NetworkAgent.ResourcePriority.Low: |
| 1106 return '#6c0'; |
| 1107 case NetworkAgent.ResourcePriority.Medium: |
| 1108 return '#fa0'; |
| 1109 case NetworkAgent.ResourcePriority.High: |
| 1110 return '#f60'; |
| 1111 case NetworkAgent.ResourcePriority.VeryHigh: |
| 1112 return '#f00'; |
| 1113 } |
| 1114 return null; |
| 1115 } |
| 1116 |
| 1117 /** |
| 1118 * @param {!Array.<!WebInspector.TracingModel.Event>} events |
| 1119 */ |
| 1120 _appendTimelineData(events) { |
| 1121 this._minimumBoundary = this._model.minimumRecordTime(); |
| 1122 this._maximumBoundary = this._model.maximumRecordTime(); |
| 1123 this._timeSpan = this._model.isEmpty() ? 1000 : this._maximumBoundary - this
._minimumBoundary; |
| 1124 this._model.networkRequests().forEach(this._appendEntry.bind(this)); |
| 1125 this._updateTimelineData(); |
| 1126 } |
| 1127 |
| 1128 _updateTimelineData() { |
| 1129 if (!this._timelineData) |
| 1130 return; |
| 1131 var index = -1; |
| 1132 var lastTime = Infinity; |
| 1133 for (var i = 0; i < this._requests.length; ++i) { |
| 1134 var r = this._requests[i]; |
| 1135 var visible = r.startTime < this._endTime && r.endTime > this._startTime; |
| 1136 if (!visible) { |
| 1137 this._timelineData.entryLevels[i] = -1; |
| 1138 continue; |
| 1139 } |
| 1140 if (lastTime > r.startTime) |
| 1141 ++index; |
| 1142 lastTime = r.endTime; |
| 1143 this._timelineData.entryLevels[i] = index; |
| 1144 } |
| 1145 ++index; |
| 1146 for (var i = 0; i < this._requests.length; ++i) { |
| 1147 if (this._timelineData.entryLevels[i] === -1) |
| 1148 this._timelineData.entryLevels[i] = index; |
| 1149 } |
| 1150 this._timelineData = new WebInspector.FlameChart.TimelineData( |
| 1151 this._timelineData.entryLevels, this._timelineData.entryTotalTimes, this
._timelineData.entryStartTimes, null); |
| 1152 this._currentLevel = index; |
| 1153 } |
| 1154 |
| 1155 /** |
| 1156 * @param {!WebInspector.TimelineModel.NetworkRequest} request |
| 1157 */ |
| 1158 _appendEntry(request) { |
| 1159 this._requests.push(request); |
| 1160 this._timelineData.entryStartTimes.push(request.startTime); |
| 1161 this._timelineData.entryTotalTimes.push(request.endTime - request.startTime)
; |
| 1162 this._timelineData.entryLevels.push(this._requests.length - 1); |
| 1163 } |
958 }; | 1164 }; |
959 | 1165 |
960 WebInspector.TimelineFlameChartNetworkDataProvider.prototype = { | |
961 /** | |
962 * @override | |
963 * @return {!WebInspector.FlameChart.TimelineData} | |
964 */ | |
965 timelineData: function() | |
966 { | |
967 if (this._timelineData) | |
968 return this._timelineData; | |
969 /** @type {!Array<!WebInspector.TimelineModel.NetworkRequest>} */ | |
970 this._requests = []; | |
971 this._timelineData = new WebInspector.FlameChart.TimelineData([], [], []
, []); | |
972 this._appendTimelineData(this._model.mainThreadEvents()); | |
973 return this._timelineData; | |
974 }, | |
975 | |
976 /** | |
977 * @override | |
978 */ | |
979 reset: function() | |
980 { | |
981 WebInspector.TimelineFlameChartDataProviderBase.prototype.reset.call(thi
s); | |
982 /** @type {!Array<!WebInspector.TimelineModel.NetworkRequest>} */ | |
983 this._requests = []; | |
984 }, | |
985 | |
986 /** | |
987 * @param {number} startTime | |
988 * @param {number} endTime | |
989 */ | |
990 setWindowTimes: function(startTime, endTime) | |
991 { | |
992 this._startTime = startTime; | |
993 this._endTime = endTime; | |
994 this._updateTimelineData(); | |
995 }, | |
996 | |
997 /** | |
998 * @override | |
999 * @param {number} index | |
1000 * @return {?WebInspector.TimelineSelection} | |
1001 */ | |
1002 createSelection: function(index) | |
1003 { | |
1004 if (index === -1) | |
1005 return null; | |
1006 var request = this._requests[index]; | |
1007 this._lastSelection = new WebInspector.TimelineFlameChartView.Selection(
WebInspector.TimelineSelection.fromNetworkRequest(request), index); | |
1008 return this._lastSelection.timelineSelection; | |
1009 }, | |
1010 | |
1011 /** | |
1012 * @param {?WebInspector.TimelineSelection} selection | |
1013 * @return {number} | |
1014 */ | |
1015 entryIndexForSelection: function(selection) | |
1016 { | |
1017 if (!selection) | |
1018 return -1; | |
1019 | |
1020 if (this._lastSelection && this._lastSelection.timelineSelection.object(
) === selection.object()) | |
1021 return this._lastSelection.entryIndex; | |
1022 | |
1023 if (selection.type() !== WebInspector.TimelineSelection.Type.NetworkRequ
est) | |
1024 return -1; | |
1025 var request = /** @type{!WebInspector.TimelineModel.NetworkRequest} */ (
selection.object()); | |
1026 var index = this._requests.indexOf(request); | |
1027 if (index !== -1) | |
1028 this._lastSelection = new WebInspector.TimelineFlameChartView.Select
ion(WebInspector.TimelineSelection.fromNetworkRequest(request), index); | |
1029 return index; | |
1030 }, | |
1031 | |
1032 /** | |
1033 * @override | |
1034 * @param {number} index | |
1035 * @return {string} | |
1036 */ | |
1037 entryColor: function(index) | |
1038 { | |
1039 var request = /** @type {!WebInspector.TimelineModel.NetworkRequest} */
(this._requests[index]); | |
1040 var category = WebInspector.TimelineUIUtils.networkRequestCategory(reque
st); | |
1041 return WebInspector.TimelineUIUtils.networkCategoryColor(category); | |
1042 }, | |
1043 | |
1044 /** | |
1045 * @override | |
1046 * @param {number} index | |
1047 * @return {?string} | |
1048 */ | |
1049 entryTitle: function(index) | |
1050 { | |
1051 var request = /** @type {!WebInspector.TimelineModel.NetworkRequest} */
(this._requests[index]); | |
1052 return request.url || null; | |
1053 }, | |
1054 | |
1055 /** | |
1056 * @override | |
1057 * @param {number} index | |
1058 * @param {!CanvasRenderingContext2D} context | |
1059 * @param {?string} text | |
1060 * @param {number} barX | |
1061 * @param {number} barY | |
1062 * @param {number} barWidth | |
1063 * @param {number} barHeight | |
1064 * @param {number} unclippedBarX | |
1065 * @param {number} timeToPixels | |
1066 * @return {boolean} | |
1067 */ | |
1068 decorateEntry: function(index, context, text, barX, barY, barWidth, barHeigh
t, unclippedBarX, timeToPixels) | |
1069 { | |
1070 var minTransferWidthPx = 2; | |
1071 var request = /** @type {!WebInspector.TimelineModel.NetworkRequest} */
(this._requests[index]); | |
1072 var startTime = request.startTime; | |
1073 var endTime = request.endTime; | |
1074 var lastX = unclippedBarX; | |
1075 context.fillStyle = "hsla(0, 0%, 100%, 0.6)"; | |
1076 for (var i = 0; i < request.children.length; ++i) { | |
1077 var event = request.children[i]; | |
1078 var t0 = event.startTime; | |
1079 var t1 = event.endTime || event.startTime; | |
1080 var x0 = Math.floor(unclippedBarX + (t0 - startTime) * timeToPixels
- 1); | |
1081 var x1 = Math.floor(unclippedBarX + (t1 - startTime) * timeToPixels
+ 1); | |
1082 if (x0 > lastX) | |
1083 context.fillRect(lastX, barY, x0 - lastX, barHeight); | |
1084 lastX = x1; | |
1085 } | |
1086 var endX = unclippedBarX + (endTime - startTime) * timeToPixels; | |
1087 if (endX > lastX) | |
1088 context.fillRect(lastX, barY, Math.min(endX - lastX, 1e5), barHeight
); | |
1089 if (typeof request.priority === "string") { | |
1090 var color = this._colorForPriority(request.priority); | |
1091 if (color) { | |
1092 context.fillStyle = "hsl(0, 0%, 100%)"; | |
1093 context.fillRect(barX, barY, 4, 4); | |
1094 context.fillStyle = color; | |
1095 context.fillRect(barX, barY, 3, 3); | |
1096 } | |
1097 } | |
1098 return false; | |
1099 }, | |
1100 | |
1101 /** | |
1102 * @override | |
1103 * @param {number} index | |
1104 * @return {boolean} | |
1105 */ | |
1106 forceDecoration: function(index) | |
1107 { | |
1108 return true; | |
1109 }, | |
1110 | |
1111 /** | |
1112 * @override | |
1113 * @param {number} index | |
1114 * @return {?Element} | |
1115 */ | |
1116 prepareHighlightedEntryInfo: function(index) | |
1117 { | |
1118 var /** @const */ maxURLChars = 80; | |
1119 var request = /** @type {!WebInspector.TimelineModel.NetworkRequest} */
(this._requests[index]); | |
1120 if (!request.url) | |
1121 return null; | |
1122 var element = createElement("div"); | |
1123 var root = WebInspector.createShadowRootWithCoreStyles(element, "timelin
e/timelineFlamechartPopover.css"); | |
1124 var contents = root.createChild("div", "timeline-flamechart-popover"); | |
1125 var duration = request.endTime - request.startTime; | |
1126 if (request.startTime && isFinite(duration)) | |
1127 contents.createChild("span", "timeline-info-network-time").textConte
nt = Number.millisToString(duration); | |
1128 if (typeof request.priority === "string") { | |
1129 var div = contents.createChild("span"); | |
1130 div.textContent = WebInspector.uiLabelForPriority(/** @type {!Networ
kAgent.ResourcePriority} */ (request.priority)); | |
1131 div.style.color = this._colorForPriority(request.priority) || "black
"; | |
1132 } | |
1133 contents.createChild("span").textContent = request.url.trimMiddle(maxURL
Chars); | |
1134 return element; | |
1135 }, | |
1136 | |
1137 /** | |
1138 * @param {string} priority | |
1139 * @return {?string} | |
1140 */ | |
1141 _colorForPriority: function(priority) | |
1142 { | |
1143 switch (/** @type {!NetworkAgent.ResourcePriority} */ (priority)) { | |
1144 case NetworkAgent.ResourcePriority.VeryLow: return "#080"; | |
1145 case NetworkAgent.ResourcePriority.Low: return "#6c0"; | |
1146 case NetworkAgent.ResourcePriority.Medium: return "#fa0"; | |
1147 case NetworkAgent.ResourcePriority.High: return "#f60"; | |
1148 case NetworkAgent.ResourcePriority.VeryHigh: return "#f00"; | |
1149 } | |
1150 return null; | |
1151 }, | |
1152 | |
1153 /** | |
1154 * @param {!Array.<!WebInspector.TracingModel.Event>} events | |
1155 */ | |
1156 _appendTimelineData: function(events) | |
1157 { | |
1158 this._minimumBoundary = this._model.minimumRecordTime(); | |
1159 this._maximumBoundary = this._model.maximumRecordTime(); | |
1160 this._timeSpan = this._model.isEmpty() ? 1000 : this._maximumBoundary -
this._minimumBoundary; | |
1161 this._model.networkRequests().forEach(this._appendEntry.bind(this)); | |
1162 this._updateTimelineData(); | |
1163 }, | |
1164 | |
1165 _updateTimelineData: function() | |
1166 { | |
1167 if (!this._timelineData) | |
1168 return; | |
1169 var index = -1; | |
1170 var lastTime = Infinity; | |
1171 for (var i = 0; i < this._requests.length; ++i) { | |
1172 var r = this._requests[i]; | |
1173 var visible = r.startTime < this._endTime && r.endTime > this._start
Time; | |
1174 if (!visible) { | |
1175 this._timelineData.entryLevels[i] = -1; | |
1176 continue; | |
1177 } | |
1178 if (lastTime > r.startTime) | |
1179 ++index; | |
1180 lastTime = r.endTime; | |
1181 this._timelineData.entryLevels[i] = index; | |
1182 } | |
1183 ++index; | |
1184 for (var i = 0; i < this._requests.length; ++i) { | |
1185 if (this._timelineData.entryLevels[i] === -1) | |
1186 this._timelineData.entryLevels[i] = index; | |
1187 } | |
1188 this._timelineData = new WebInspector.FlameChart.TimelineData( | |
1189 this._timelineData.entryLevels, | |
1190 this._timelineData.entryTotalTimes, | |
1191 this._timelineData.entryStartTimes, | |
1192 null); | |
1193 this._currentLevel = index; | |
1194 }, | |
1195 | |
1196 /** | |
1197 * @param {!WebInspector.TimelineModel.NetworkRequest} request | |
1198 */ | |
1199 _appendEntry: function(request) | |
1200 { | |
1201 this._requests.push(request); | |
1202 this._timelineData.entryStartTimes.push(request.startTime); | |
1203 this._timelineData.entryTotalTimes.push(request.endTime - request.startT
ime); | |
1204 this._timelineData.entryLevels.push(this._requests.length - 1); | |
1205 }, | |
1206 | |
1207 __proto__: WebInspector.TimelineFlameChartDataProviderBase.prototype | |
1208 }; | |
1209 | |
1210 /** | 1166 /** |
1211 * @constructor | |
1212 * @implements {WebInspector.FlameChartMarker} | 1167 * @implements {WebInspector.FlameChartMarker} |
1213 * @param {number} startTime | 1168 * @unrestricted |
1214 * @param {number} startOffset | |
1215 * @param {!WebInspector.TimelineMarkerStyle} style | |
1216 */ | 1169 */ |
1217 WebInspector.TimelineFlameChartMarker = function(startTime, startOffset, style) | 1170 WebInspector.TimelineFlameChartMarker = class { |
1218 { | 1171 /** |
| 1172 * @param {number} startTime |
| 1173 * @param {number} startOffset |
| 1174 * @param {!WebInspector.TimelineMarkerStyle} style |
| 1175 */ |
| 1176 constructor(startTime, startOffset, style) { |
1219 this._startTime = startTime; | 1177 this._startTime = startTime; |
1220 this._startOffset = startOffset; | 1178 this._startOffset = startOffset; |
1221 this._style = style; | 1179 this._style = style; |
| 1180 } |
| 1181 |
| 1182 /** |
| 1183 * @override |
| 1184 * @return {number} |
| 1185 */ |
| 1186 startTime() { |
| 1187 return this._startTime; |
| 1188 } |
| 1189 |
| 1190 /** |
| 1191 * @override |
| 1192 * @return {string} |
| 1193 */ |
| 1194 color() { |
| 1195 return this._style.color; |
| 1196 } |
| 1197 |
| 1198 /** |
| 1199 * @override |
| 1200 * @return {string} |
| 1201 */ |
| 1202 title() { |
| 1203 var startTime = Number.millisToString(this._startOffset); |
| 1204 return WebInspector.UIString('%s at %s', this._style.title, startTime); |
| 1205 } |
| 1206 |
| 1207 /** |
| 1208 * @override |
| 1209 * @param {!CanvasRenderingContext2D} context |
| 1210 * @param {number} x |
| 1211 * @param {number} height |
| 1212 * @param {number} pixelsPerMillisecond |
| 1213 */ |
| 1214 draw(context, x, height, pixelsPerMillisecond) { |
| 1215 var lowPriorityVisibilityThresholdInPixelsPerMs = 4; |
| 1216 |
| 1217 if (this._style.lowPriority && pixelsPerMillisecond < lowPriorityVisibilityT
hresholdInPixelsPerMs) |
| 1218 return; |
| 1219 context.save(); |
| 1220 |
| 1221 if (!this._style.lowPriority) { |
| 1222 context.strokeStyle = this._style.color; |
| 1223 context.lineWidth = 2; |
| 1224 context.beginPath(); |
| 1225 context.moveTo(x, 0); |
| 1226 context.lineTo(x, height); |
| 1227 context.stroke(); |
| 1228 } |
| 1229 |
| 1230 if (this._style.tall) { |
| 1231 context.strokeStyle = this._style.color; |
| 1232 context.lineWidth = this._style.lineWidth; |
| 1233 context.translate(this._style.lineWidth < 1 || (this._style.lineWidth & 1)
? 0.5 : 0, 0.5); |
| 1234 context.beginPath(); |
| 1235 context.moveTo(x, height); |
| 1236 context.setLineDash(this._style.dashStyle); |
| 1237 context.lineTo(x, context.canvas.height); |
| 1238 context.stroke(); |
| 1239 } |
| 1240 context.restore(); |
| 1241 } |
1222 }; | 1242 }; |
1223 | 1243 |
1224 WebInspector.TimelineFlameChartMarker.prototype = { | |
1225 /** | |
1226 * @override | |
1227 * @return {number} | |
1228 */ | |
1229 startTime: function() | |
1230 { | |
1231 return this._startTime; | |
1232 }, | |
1233 | |
1234 /** | |
1235 * @override | |
1236 * @return {string} | |
1237 */ | |
1238 color: function() | |
1239 { | |
1240 return this._style.color; | |
1241 }, | |
1242 | |
1243 /** | |
1244 * @override | |
1245 * @return {string} | |
1246 */ | |
1247 title: function() | |
1248 { | |
1249 var startTime = Number.millisToString(this._startOffset); | |
1250 return WebInspector.UIString("%s at %s", this._style.title, startTime); | |
1251 }, | |
1252 | |
1253 /** | |
1254 * @override | |
1255 * @param {!CanvasRenderingContext2D} context | |
1256 * @param {number} x | |
1257 * @param {number} height | |
1258 * @param {number} pixelsPerMillisecond | |
1259 */ | |
1260 draw: function(context, x, height, pixelsPerMillisecond) | |
1261 { | |
1262 var lowPriorityVisibilityThresholdInPixelsPerMs = 4; | |
1263 | |
1264 if (this._style.lowPriority && pixelsPerMillisecond < lowPriorityVisibil
ityThresholdInPixelsPerMs) | |
1265 return; | |
1266 context.save(); | |
1267 | |
1268 if (!this._style.lowPriority) { | |
1269 context.strokeStyle = this._style.color; | |
1270 context.lineWidth = 2; | |
1271 context.beginPath(); | |
1272 context.moveTo(x, 0); | |
1273 context.lineTo(x, height); | |
1274 context.stroke(); | |
1275 } | |
1276 | |
1277 if (this._style.tall) { | |
1278 context.strokeStyle = this._style.color; | |
1279 context.lineWidth = this._style.lineWidth; | |
1280 context.translate(this._style.lineWidth < 1 || (this._style.lineWidt
h & 1) ? 0.5 : 0, 0.5); | |
1281 context.beginPath(); | |
1282 context.moveTo(x, height); | |
1283 context.setLineDash(this._style.dashStyle); | |
1284 context.lineTo(x, context.canvas.height); | |
1285 context.stroke(); | |
1286 } | |
1287 context.restore(); | |
1288 } | |
1289 }; | |
1290 | |
1291 /** | 1244 /** |
1292 * @constructor | |
1293 * @extends {WebInspector.VBox} | |
1294 * @implements {WebInspector.TimelineModeView} | 1245 * @implements {WebInspector.TimelineModeView} |
1295 * @implements {WebInspector.FlameChartDelegate} | 1246 * @implements {WebInspector.FlameChartDelegate} |
1296 * @param {!WebInspector.TimelineModeViewDelegate} delegate | 1247 * @unrestricted |
1297 * @param {!WebInspector.TimelineModel} timelineModel | |
1298 * @param {!WebInspector.TimelineFrameModel} frameModel | |
1299 * @param {!WebInspector.TimelineIRModel} irModel | |
1300 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters | |
1301 */ | 1248 */ |
1302 WebInspector.TimelineFlameChartView = function(delegate, timelineModel, frameMod
el, irModel, filters) | 1249 WebInspector.TimelineFlameChartView = class extends WebInspector.VBox { |
1303 { | 1250 /** |
1304 WebInspector.VBox.call(this); | 1251 * @param {!WebInspector.TimelineModeViewDelegate} delegate |
1305 this.element.classList.add("timeline-flamechart"); | 1252 * @param {!WebInspector.TimelineModel} timelineModel |
| 1253 * @param {!WebInspector.TimelineFrameModel} frameModel |
| 1254 * @param {!WebInspector.TimelineIRModel} irModel |
| 1255 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters |
| 1256 */ |
| 1257 constructor(delegate, timelineModel, frameModel, irModel, filters) { |
| 1258 super(); |
| 1259 this.element.classList.add('timeline-flamechart'); |
1306 this._delegate = delegate; | 1260 this._delegate = delegate; |
1307 this._model = timelineModel; | 1261 this._model = timelineModel; |
1308 | 1262 |
1309 this._splitWidget = new WebInspector.SplitWidget(false, false, "timelineFlam
echartMainView", 150); | 1263 this._splitWidget = new WebInspector.SplitWidget(false, false, 'timelineFlam
echartMainView', 150); |
1310 | 1264 |
1311 this._dataProvider = new WebInspector.TimelineFlameChartDataProvider(this._m
odel, frameModel, irModel, filters); | 1265 this._dataProvider = new WebInspector.TimelineFlameChartDataProvider(this._m
odel, frameModel, irModel, filters); |
1312 var mainViewGroupExpansionSetting = WebInspector.settings.createSetting("tim
elineFlamechartMainViewGroupExpansion", {}); | 1266 var mainViewGroupExpansionSetting = |
| 1267 WebInspector.settings.createSetting('timelineFlamechartMainViewGroupExpa
nsion', {}); |
1313 this._mainView = new WebInspector.FlameChart(this._dataProvider, this, mainV
iewGroupExpansionSetting); | 1268 this._mainView = new WebInspector.FlameChart(this._dataProvider, this, mainV
iewGroupExpansionSetting); |
1314 | 1269 |
1315 this._networkDataProvider = new WebInspector.TimelineFlameChartNetworkDataPr
ovider(this._model); | 1270 this._networkDataProvider = new WebInspector.TimelineFlameChartNetworkDataPr
ovider(this._model); |
1316 this._networkView = new WebInspector.FlameChart(this._networkDataProvider, t
his); | 1271 this._networkView = new WebInspector.FlameChart(this._networkDataProvider, t
his); |
1317 | 1272 |
1318 this._splitWidget.setMainWidget(this._mainView); | 1273 this._splitWidget.setMainWidget(this._mainView); |
1319 this._splitWidget.setSidebarWidget(this._networkView); | 1274 this._splitWidget.setSidebarWidget(this._networkView); |
1320 this._splitWidget.show(this.element); | 1275 this._splitWidget.show(this.element); |
1321 | 1276 |
1322 this._onMainEntrySelected = this._onEntrySelected.bind(this, this._dataProvi
der); | 1277 this._onMainEntrySelected = this._onEntrySelected.bind(this, this._dataProvi
der); |
1323 this._onNetworkEntrySelected = this._onEntrySelected.bind(this, this._networ
kDataProvider); | 1278 this._onNetworkEntrySelected = this._onEntrySelected.bind(this, this._networ
kDataProvider); |
1324 this._mainView.addEventListener(WebInspector.FlameChart.Events.EntrySelected
, this._onMainEntrySelected, this); | 1279 this._mainView.addEventListener(WebInspector.FlameChart.Events.EntrySelected
, this._onMainEntrySelected, this); |
1325 this._networkView.addEventListener(WebInspector.FlameChart.Events.EntrySelec
ted, this._onNetworkEntrySelected, this); | 1280 this._networkView.addEventListener( |
| 1281 WebInspector.FlameChart.Events.EntrySelected, this._onNetworkEntrySelect
ed, this); |
1326 WebInspector.blackboxManager.addChangeListener(this.refreshRecords, this); | 1282 WebInspector.blackboxManager.addChangeListener(this.refreshRecords, this); |
1327 }; | 1283 } |
1328 | 1284 |
1329 WebInspector.TimelineFlameChartView.prototype = { | 1285 /** |
1330 /** | 1286 * @override |
1331 * @override | 1287 */ |
1332 */ | 1288 dispose() { |
1333 dispose: function() | 1289 this._mainView.removeEventListener(WebInspector.FlameChart.Events.EntrySelec
ted, this._onMainEntrySelected, this); |
1334 { | 1290 this._networkView.removeEventListener( |
1335 this._mainView.removeEventListener(WebInspector.FlameChart.Events.EntryS
elected, this._onMainEntrySelected, this); | 1291 WebInspector.FlameChart.Events.EntrySelected, this._onNetworkEntrySelect
ed, this); |
1336 this._networkView.removeEventListener(WebInspector.FlameChart.Events.Ent
rySelected, this._onNetworkEntrySelected, this); | 1292 WebInspector.blackboxManager.removeChangeListener(this.refreshRecords, this)
; |
1337 WebInspector.blackboxManager.removeChangeListener(this.refreshRecords, t
his); | 1293 } |
1338 }, | |
1339 | 1294 |
1340 /** | 1295 /** |
1341 * @override | 1296 * @override |
1342 * @return {?Element} | 1297 * @return {?Element} |
1343 */ | 1298 */ |
1344 resizerElement: function() | 1299 resizerElement() { |
1345 { | 1300 return null; |
1346 return null; | 1301 } |
1347 }, | |
1348 | 1302 |
1349 /** | 1303 /** |
1350 * @override | 1304 * @override |
1351 * @param {number} windowStartTime | 1305 * @param {number} windowStartTime |
1352 * @param {number} windowEndTime | 1306 * @param {number} windowEndTime |
1353 */ | 1307 */ |
1354 requestWindowTimes: function(windowStartTime, windowEndTime) | 1308 requestWindowTimes(windowStartTime, windowEndTime) { |
1355 { | 1309 this._delegate.requestWindowTimes(windowStartTime, windowEndTime); |
1356 this._delegate.requestWindowTimes(windowStartTime, windowEndTime); | 1310 } |
1357 }, | |
1358 | 1311 |
1359 /** | 1312 /** |
1360 * @override | 1313 * @override |
1361 * @param {number} startTime | 1314 * @param {number} startTime |
1362 * @param {number} endTime | 1315 * @param {number} endTime |
1363 */ | 1316 */ |
1364 updateRangeSelection: function(startTime, endTime) | 1317 updateRangeSelection(startTime, endTime) { |
1365 { | 1318 this._delegate.select(WebInspector.TimelineSelection.fromRange(startTime, en
dTime)); |
1366 this._delegate.select(WebInspector.TimelineSelection.fromRange(startTime
, endTime)); | 1319 } |
1367 }, | |
1368 | 1320 |
1369 /** | 1321 /** |
1370 * @override | 1322 * @override |
1371 */ | 1323 */ |
1372 refreshRecords: function() | 1324 refreshRecords() { |
1373 { | 1325 this._dataProvider.reset(); |
1374 this._dataProvider.reset(); | 1326 this._mainView.scheduleUpdate(); |
1375 this._mainView.scheduleUpdate(); | 1327 this._networkDataProvider.reset(); |
1376 this._networkDataProvider.reset(); | 1328 this._networkView.scheduleUpdate(); |
1377 this._networkView.scheduleUpdate(); | 1329 } |
1378 }, | |
1379 | 1330 |
1380 /** | 1331 /** |
1381 * @override | 1332 * @override |
1382 * @param {?WebInspector.TracingModel.Event} event | 1333 * @param {?WebInspector.TracingModel.Event} event |
1383 */ | 1334 */ |
1384 highlightEvent: function(event) | 1335 highlightEvent(event) { |
1385 { | 1336 var entryIndex = |
1386 var entryIndex = event ? this._dataProvider.entryIndexForSelection(WebIn
spector.TimelineSelection.fromTraceEvent(event)) : -1; | 1337 event ? this._dataProvider.entryIndexForSelection(WebInspector.TimelineS
election.fromTraceEvent(event)) : -1; |
1387 if (entryIndex >= 0) | 1338 if (entryIndex >= 0) |
1388 this._mainView.highlightEntry(entryIndex); | 1339 this._mainView.highlightEntry(entryIndex); |
1389 else | 1340 else |
1390 this._mainView.hideHighlight(); | 1341 this._mainView.hideHighlight(); |
1391 }, | 1342 } |
1392 | 1343 |
1393 /** | 1344 /** |
1394 * @override | 1345 * @override |
1395 */ | 1346 */ |
1396 wasShown: function() | 1347 wasShown() { |
1397 { | 1348 this._mainView.scheduleUpdate(); |
1398 this._mainView.scheduleUpdate(); | 1349 this._networkView.scheduleUpdate(); |
1399 this._networkView.scheduleUpdate(); | 1350 } |
1400 }, | |
1401 | 1351 |
1402 /** | 1352 /** |
1403 * @override | 1353 * @override |
1404 * @return {!WebInspector.Widget} | 1354 * @return {!WebInspector.Widget} |
1405 */ | 1355 */ |
1406 view: function() | 1356 view() { |
1407 { | 1357 return this; |
1408 return this; | 1358 } |
1409 }, | |
1410 | 1359 |
1411 /** | 1360 /** |
1412 * @override | 1361 * @override |
1413 */ | 1362 */ |
1414 reset: function() | 1363 reset() { |
1415 { | 1364 this._dataProvider.reset(); |
1416 this._dataProvider.reset(); | 1365 this._mainView.reset(); |
1417 this._mainView.reset(); | 1366 this._mainView.setWindowTimes(0, Infinity); |
1418 this._mainView.setWindowTimes(0, Infinity); | 1367 this._networkDataProvider.reset(); |
1419 this._networkDataProvider.reset(); | 1368 this._networkView.reset(); |
1420 this._networkView.reset(); | 1369 this._networkView.setWindowTimes(0, Infinity); |
1421 this._networkView.setWindowTimes(0, Infinity); | 1370 } |
1422 }, | |
1423 | 1371 |
1424 /** | 1372 /** |
1425 * @override | 1373 * @override |
1426 * @param {number} startTime | 1374 * @param {number} startTime |
1427 * @param {number} endTime | 1375 * @param {number} endTime |
1428 */ | 1376 */ |
1429 setWindowTimes: function(startTime, endTime) | 1377 setWindowTimes(startTime, endTime) { |
1430 { | 1378 this._mainView.setWindowTimes(startTime, endTime); |
1431 this._mainView.setWindowTimes(startTime, endTime); | 1379 this._networkView.setWindowTimes(startTime, endTime); |
1432 this._networkView.setWindowTimes(startTime, endTime); | 1380 this._networkDataProvider.setWindowTimes(startTime, endTime); |
1433 this._networkDataProvider.setWindowTimes(startTime, endTime); | 1381 } |
1434 }, | |
1435 | 1382 |
1436 /** | 1383 /** |
1437 * @override | 1384 * @override |
1438 * @param {?WebInspector.TracingModel.Event} event | 1385 * @param {?WebInspector.TracingModel.Event} event |
1439 * @param {string=} regex | 1386 * @param {string=} regex |
1440 * @param {boolean=} select | 1387 * @param {boolean=} select |
1441 */ | 1388 */ |
1442 highlightSearchResult: function(event, regex, select) | 1389 highlightSearchResult(event, regex, select) { |
1443 { | 1390 if (!event) { |
1444 if (!event) { | 1391 this._delegate.select(null); |
1445 this._delegate.select(null); | 1392 return; |
1446 return; | 1393 } |
1447 } | 1394 var entryIndex = this._dataProvider._entryData.indexOf(event); |
1448 var entryIndex = this._dataProvider._entryData.indexOf(event); | 1395 var timelineSelection = this._dataProvider.createSelection(entryIndex); |
1449 var timelineSelection = this._dataProvider.createSelection(entryIndex); | 1396 if (timelineSelection) |
1450 if (timelineSelection) | 1397 this._delegate.select(timelineSelection); |
1451 this._delegate.select(timelineSelection); | 1398 } |
1452 }, | |
1453 | 1399 |
1454 /** | 1400 /** |
1455 * @override | 1401 * @override |
1456 * @param {?WebInspector.TimelineSelection} selection | 1402 * @param {?WebInspector.TimelineSelection} selection |
1457 */ | 1403 */ |
1458 setSelection: function(selection) | 1404 setSelection(selection) { |
1459 { | 1405 var index = this._dataProvider.entryIndexForSelection(selection); |
1460 var index = this._dataProvider.entryIndexForSelection(selection); | 1406 this._mainView.setSelectedEntry(index); |
1461 this._mainView.setSelectedEntry(index); | 1407 index = this._networkDataProvider.entryIndexForSelection(selection); |
1462 index = this._networkDataProvider.entryIndexForSelection(selection); | 1408 this._networkView.setSelectedEntry(index); |
1463 this._networkView.setSelectedEntry(index); | 1409 } |
1464 }, | |
1465 | 1410 |
1466 /** | 1411 /** |
1467 * @param {!WebInspector.FlameChartDataProvider} dataProvider | 1412 * @param {!WebInspector.FlameChartDataProvider} dataProvider |
1468 * @param {!WebInspector.Event} event | 1413 * @param {!WebInspector.Event} event |
1469 */ | 1414 */ |
1470 _onEntrySelected: function(dataProvider, event) | 1415 _onEntrySelected(dataProvider, event) { |
1471 { | 1416 var entryIndex = /** @type{number} */ (event.data); |
1472 var entryIndex = /** @type{number} */ (event.data); | 1417 this._delegate.select(dataProvider.createSelection(entryIndex)); |
1473 this._delegate.select(dataProvider.createSelection(entryIndex)); | 1418 } |
1474 }, | |
1475 | 1419 |
1476 /** | 1420 /** |
1477 * @param {boolean} enable | 1421 * @param {boolean} enable |
1478 * @param {boolean=} animate | 1422 * @param {boolean=} animate |
1479 */ | 1423 */ |
1480 enableNetworkPane: function(enable, animate) | 1424 enableNetworkPane(enable, animate) { |
1481 { | 1425 if (enable) |
1482 if (enable) | 1426 this._splitWidget.showBoth(animate); |
1483 this._splitWidget.showBoth(animate); | 1427 else |
1484 else | 1428 this._splitWidget.hideSidebar(animate); |
1485 this._splitWidget.hideSidebar(animate); | 1429 } |
1486 }, | |
1487 | |
1488 __proto__: WebInspector.VBox.prototype | |
1489 }; | 1430 }; |
1490 | 1431 |
1491 /** | 1432 /** |
1492 * @constructor | 1433 * @unrestricted |
1493 * @param {!WebInspector.TimelineSelection} selection | 1434 */ |
1494 * @param {number} entryIndex | 1435 WebInspector.TimelineFlameChartView.Selection = class { |
1495 */ | 1436 /** |
1496 WebInspector.TimelineFlameChartView.Selection = function(selection, entryIndex) | 1437 * @param {!WebInspector.TimelineSelection} selection |
1497 { | 1438 * @param {number} entryIndex |
| 1439 */ |
| 1440 constructor(selection, entryIndex) { |
1498 this.timelineSelection = selection; | 1441 this.timelineSelection = selection; |
1499 this.entryIndex = entryIndex; | 1442 this.entryIndex = entryIndex; |
| 1443 } |
1500 }; | 1444 }; |
OLD | NEW |