Index: third_party/WebKit/Source/devtools/front_end/sdk/TracingModel.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/TracingModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/TracingModel.js |
index 245f5c025a16877461a0b3715848939f98e3c5fb..c90a0c9376bac2b41684c7547317a4a1786268c9 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/sdk/TracingModel.js |
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/TracingModel.js |
@@ -3,505 +3,489 @@ |
* Use of this source code is governed by a BSD-style license that can be |
* found in the LICENSE file. |
*/ |
- |
/** |
- * @constructor |
- * @param {!WebInspector.BackingStorage} backingStorage |
+ * @unrestricted |
*/ |
-WebInspector.TracingModel = function(backingStorage) |
-{ |
+WebInspector.TracingModel = class { |
+ /** |
+ * @param {!WebInspector.BackingStorage} backingStorage |
+ */ |
+ constructor(backingStorage) { |
this._backingStorage = backingStorage; |
// Avoid extra reset of the storage as it's expensive. |
this._firstWritePending = true; |
this.reset(); |
-}; |
- |
-/** |
- * @enum {string} |
- */ |
-WebInspector.TracingModel.Phase = { |
- Begin: "B", |
- End: "E", |
- Complete: "X", |
- Instant: "I", |
- AsyncBegin: "S", |
- AsyncStepInto: "T", |
- AsyncStepPast: "p", |
- AsyncEnd: "F", |
- NestableAsyncBegin: "b", |
- NestableAsyncEnd: "e", |
- NestableAsyncInstant: "n", |
- FlowBegin: "s", |
- FlowStep: "t", |
- FlowEnd: "f", |
- Metadata: "M", |
- Counter: "C", |
- Sample: "P", |
- CreateObject: "N", |
- SnapshotObject: "O", |
- DeleteObject: "D" |
-}; |
- |
-WebInspector.TracingModel.MetadataEvent = { |
- ProcessSortIndex: "process_sort_index", |
- ProcessName: "process_name", |
- ThreadSortIndex: "thread_sort_index", |
- ThreadName: "thread_name" |
-}; |
- |
-WebInspector.TracingModel.TopLevelEventCategory = "toplevel"; |
-WebInspector.TracingModel.DevToolsMetadataEventCategory = "disabled-by-default-devtools.timeline"; |
-WebInspector.TracingModel.DevToolsTimelineEventCategory = "disabled-by-default-devtools.timeline"; |
- |
-WebInspector.TracingModel.FrameLifecycleEventCategory = "cc,devtools"; |
- |
-/** |
- * @param {string} phase |
- * @return {boolean} |
- */ |
-WebInspector.TracingModel.isNestableAsyncPhase = function(phase) |
-{ |
- return phase === "b" || phase === "e" || phase === "n"; |
-}; |
- |
-/** |
- * @param {string} phase |
- * @return {boolean} |
- */ |
-WebInspector.TracingModel.isAsyncBeginPhase = function(phase) |
-{ |
- return phase === "S" || phase === "b"; |
-}; |
- |
-/** |
- * @param {string} phase |
- * @return {boolean} |
- */ |
-WebInspector.TracingModel.isAsyncPhase = function(phase) |
-{ |
- return WebInspector.TracingModel.isNestableAsyncPhase(phase) || phase === "S" || phase === "T" || phase === "F" || phase === "p"; |
-}; |
- |
-/** |
- * @param {string} phase |
- * @return {boolean} |
- */ |
-WebInspector.TracingModel.isFlowPhase = function(phase) |
-{ |
- return phase === "s" || phase === "t" || phase === "f"; |
-}; |
- |
-/** |
- * @param {!WebInspector.TracingModel.Event} event |
- * @return {boolean} |
- */ |
-WebInspector.TracingModel.isTopLevelEvent = function(event) |
-{ |
+ } |
+ |
+ /** |
+ * @param {string} phase |
+ * @return {boolean} |
+ */ |
+ static isNestableAsyncPhase(phase) { |
+ return phase === 'b' || phase === 'e' || phase === 'n'; |
+ } |
+ |
+ /** |
+ * @param {string} phase |
+ * @return {boolean} |
+ */ |
+ static isAsyncBeginPhase(phase) { |
+ return phase === 'S' || phase === 'b'; |
+ } |
+ |
+ /** |
+ * @param {string} phase |
+ * @return {boolean} |
+ */ |
+ static isAsyncPhase(phase) { |
+ return WebInspector.TracingModel.isNestableAsyncPhase(phase) || phase === 'S' || phase === 'T' || phase === 'F' || |
+ phase === 'p'; |
+ } |
+ |
+ /** |
+ * @param {string} phase |
+ * @return {boolean} |
+ */ |
+ static isFlowPhase(phase) { |
+ return phase === 's' || phase === 't' || phase === 'f'; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} event |
+ * @return {boolean} |
+ */ |
+ static isTopLevelEvent(event) { |
return event.hasCategory(WebInspector.TracingModel.TopLevelEventCategory) || |
- event.hasCategory(WebInspector.TracingModel.DevToolsMetadataEventCategory) && event.name === "Program"; // Older timelines may have this instead of toplevel. |
-}; |
- |
-/** |
- * @param {!WebInspector.TracingManager.EventPayload} payload |
- * @return {string|undefined} |
- */ |
-WebInspector.TracingModel._extractId = function(payload) |
-{ |
- var scope = payload.scope || ""; |
- if (typeof payload.id2 === "undefined") |
- return scope && payload.id ? `${scope}@${payload.id}` : payload.id; |
+ event.hasCategory(WebInspector.TracingModel.DevToolsMetadataEventCategory) && |
+ event.name === 'Program'; // Older timelines may have this instead of toplevel. |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingManager.EventPayload} payload |
+ * @return {string|undefined} |
+ */ |
+ static _extractId(payload) { |
+ var scope = payload.scope || ''; |
+ if (typeof payload.id2 === 'undefined') |
+ return scope && payload.id ? `${scope}@${payload.id}` : payload.id; |
var id2 = payload.id2; |
- if (typeof id2 === "object" && ("global" in id2) !== ("local" in id2)) |
- return typeof id2["global"] !== "undefined" ? `:${scope}:${id2["global"]}` : `:${scope}:${payload.pid}:${id2["local"]}`; |
- console.error(`Unexpected id2 field at ${payload.ts / 1000}, one and only one of 'local' and 'global' should be present.`); |
-}; |
- |
-/** |
- * @param {!WebInspector.TracingModel} tracingModel |
- * @return {?WebInspector.TracingModel.Thread} |
- * |
- * TODO: Move this to a better place. This is here just for convenience o |
- * re-use between modules. This really belongs to a higher level, since it |
- * is specific to chrome's usage of tracing. |
- */ |
-WebInspector.TracingModel.browserMainThread = function(tracingModel) |
-{ |
+ if (typeof id2 === 'object' && ('global' in id2) !== ('local' in id2)) |
+ return typeof id2['global'] !== 'undefined' ? `:${scope}:${id2['global']}` : |
+ `:${scope}:${payload.pid}:${id2['local']}`; |
+ console.error( |
+ `Unexpected id2 field at ${payload.ts / 1000}, one and only one of 'local' and 'global' should be present.`); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingModel} tracingModel |
+ * @return {?WebInspector.TracingModel.Thread} |
+ * |
+ * TODO: Move this to a better place. This is here just for convenience o |
+ * re-use between modules. This really belongs to a higher level, since it |
+ * is specific to chrome's usage of tracing. |
+ */ |
+ static browserMainThread(tracingModel) { |
var processes = tracingModel.sortedProcesses(); |
// Avoid warning for an empty model. |
if (!processes.length) |
- return null; |
+ return null; |
var browserProcesses = []; |
var crRendererMainThreads = []; |
for (var process of processes) { |
- if (process.name().toLowerCase().endsWith("browser")) |
- browserProcesses.push(process); |
- crRendererMainThreads.push(...process.sortedThreads().filter(t => t.name() === "CrBrowserMain")); |
+ if (process.name().toLowerCase().endsWith('browser')) |
+ browserProcesses.push(process); |
+ crRendererMainThreads.push(...process.sortedThreads().filter(t => t.name() === 'CrBrowserMain')); |
} |
if (crRendererMainThreads.length === 1) |
- return crRendererMainThreads[0]; |
+ return crRendererMainThreads[0]; |
if (browserProcesses.length === 1) |
- return browserProcesses[0].threadByName("CrBrowserMain"); |
- var tracingStartedInBrowser = tracingModel.devToolsMetadataEvents().filter(e => e.name === "TracingStartedInBrowser"); |
+ return browserProcesses[0].threadByName('CrBrowserMain'); |
+ var tracingStartedInBrowser = |
+ tracingModel.devToolsMetadataEvents().filter(e => e.name === 'TracingStartedInBrowser'); |
if (tracingStartedInBrowser.length === 1) |
- return tracingStartedInBrowser[0].thread; |
- WebInspector.console.error("Failed to find browser main thread in trace, some timeline features may be unavailable"); |
+ return tracingStartedInBrowser[0].thread; |
+ WebInspector.console.error( |
+ 'Failed to find browser main thread in trace, some timeline features may be unavailable'); |
return null; |
-}; |
- |
-/** |
- * @interface |
- */ |
-WebInspector.BackingStorage = function() |
-{ |
-}; |
- |
-WebInspector.BackingStorage.prototype = { |
- /** |
- * @param {string} string |
- */ |
- appendString: function(string) { }, |
- |
- /** |
- * @param {string} string |
- * @return {function():!Promise.<?string>} |
- */ |
- appendAccessibleString: function(string) { }, |
- |
- finishWriting: function() { }, |
- |
- reset: function() { }, |
-}; |
- |
- |
-WebInspector.TracingModel.prototype = { |
- /** |
- * @return {!Array.<!WebInspector.TracingModel.Event>} |
- */ |
- devToolsMetadataEvents: function() |
- { |
- return this._devToolsMetadataEvents; |
- }, |
- |
- /** |
- * @param {!Array.<!WebInspector.TracingManager.EventPayload>} events |
- */ |
- setEventsForTest: function(events) |
- { |
- this.reset(); |
- this.addEvents(events); |
- this.tracingComplete(); |
- }, |
+ } |
+ |
+ /** |
+ * @return {!Array.<!WebInspector.TracingModel.Event>} |
+ */ |
+ devToolsMetadataEvents() { |
+ return this._devToolsMetadataEvents; |
+ } |
+ |
+ /** |
+ * @param {!Array.<!WebInspector.TracingManager.EventPayload>} events |
+ */ |
+ setEventsForTest(events) { |
+ this.reset(); |
+ this.addEvents(events); |
+ this.tracingComplete(); |
+ } |
+ |
+ /** |
+ * @param {!Array.<!WebInspector.TracingManager.EventPayload>} events |
+ */ |
+ addEvents(events) { |
+ for (var i = 0; i < events.length; ++i) |
+ this._addEvent(events[i]); |
+ } |
+ |
+ tracingComplete() { |
+ this._processPendingAsyncEvents(); |
+ this._backingStorage.appendString(this._firstWritePending ? '[]' : ']'); |
+ this._backingStorage.finishWriting(); |
+ this._firstWritePending = false; |
+ for (var process of this._processById.values()) { |
+ for (var thread of process._threads.values()) |
+ thread.tracingComplete(); |
+ } |
+ } |
+ |
+ reset() { |
+ /** @type {!Map<(number|string), !WebInspector.TracingModel.Process>} */ |
+ this._processById = new Map(); |
+ this._processByName = new Map(); |
+ this._minimumRecordTime = 0; |
+ this._maximumRecordTime = 0; |
+ this._devToolsMetadataEvents = []; |
+ if (!this._firstWritePending) |
+ this._backingStorage.reset(); |
- /** |
- * @param {!Array.<!WebInspector.TracingManager.EventPayload>} events |
- */ |
- addEvents: function(events) |
- { |
- for (var i = 0; i < events.length; ++i) |
- this._addEvent(events[i]); |
- }, |
- |
- tracingComplete: function() |
- { |
- this._processPendingAsyncEvents(); |
- this._backingStorage.appendString(this._firstWritePending ? "[]" : "]"); |
- this._backingStorage.finishWriting(); |
- this._firstWritePending = false; |
- for (var process of this._processById.values()) { |
- for (var thread of process._threads.values()) |
- thread.tracingComplete(); |
- } |
- }, |
- |
- reset: function() |
- { |
- /** @type {!Map<(number|string), !WebInspector.TracingModel.Process>} */ |
- this._processById = new Map(); |
- this._processByName = new Map(); |
- this._minimumRecordTime = 0; |
- this._maximumRecordTime = 0; |
- this._devToolsMetadataEvents = []; |
- if (!this._firstWritePending) |
- this._backingStorage.reset(); |
- |
- this._firstWritePending = true; |
- /** @type {!Array<!WebInspector.TracingModel.Event>} */ |
- this._asyncEvents = []; |
- /** @type {!Map<string, !WebInspector.TracingModel.AsyncEvent>} */ |
- this._openAsyncEvents = new Map(); |
- /** @type {!Map<string, !Array<!WebInspector.TracingModel.AsyncEvent>>} */ |
- this._openNestableAsyncEvents = new Map(); |
- /** @type {!Map<string, !WebInspector.TracingModel.ProfileEventsGroup>} */ |
- this._profileGroups = new Map(); |
- /** @type {!Map<string, !Set<string>>} */ |
- this._parsedCategories = new Map(); |
- }, |
+ this._firstWritePending = true; |
+ /** @type {!Array<!WebInspector.TracingModel.Event>} */ |
+ this._asyncEvents = []; |
+ /** @type {!Map<string, !WebInspector.TracingModel.AsyncEvent>} */ |
+ this._openAsyncEvents = new Map(); |
+ /** @type {!Map<string, !Array<!WebInspector.TracingModel.AsyncEvent>>} */ |
+ this._openNestableAsyncEvents = new Map(); |
+ /** @type {!Map<string, !WebInspector.TracingModel.ProfileEventsGroup>} */ |
+ this._profileGroups = new Map(); |
+ /** @type {!Map<string, !Set<string>>} */ |
+ this._parsedCategories = new Map(); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingManager.EventPayload} payload |
+ */ |
+ _addEvent(payload) { |
+ var process = this._processById.get(payload.pid); |
+ if (!process) { |
+ process = new WebInspector.TracingModel.Process(this, payload.pid); |
+ this._processById.set(payload.pid, process); |
+ } |
- /** |
- * @param {!WebInspector.TracingManager.EventPayload} payload |
- */ |
- _addEvent: function(payload) |
- { |
- var process = this._processById.get(payload.pid); |
- if (!process) { |
- process = new WebInspector.TracingModel.Process(this, payload.pid); |
- this._processById.set(payload.pid, process); |
- } |
+ var eventsDelimiter = ',\n'; |
+ this._backingStorage.appendString(this._firstWritePending ? '[' : eventsDelimiter); |
+ this._firstWritePending = false; |
+ var stringPayload = JSON.stringify(payload); |
+ var isAccessible = payload.ph === WebInspector.TracingModel.Phase.SnapshotObject; |
+ var backingStorage = null; |
+ var keepStringsLessThan = 10000; |
+ if (isAccessible && stringPayload.length > keepStringsLessThan) |
+ backingStorage = this._backingStorage.appendAccessibleString(stringPayload); |
+ else |
+ this._backingStorage.appendString(stringPayload); |
+ |
+ var timestamp = payload.ts / 1000; |
+ // We do allow records for unrelated threads to arrive out-of-order, |
+ // so there's a chance we're getting records from the past. |
+ if (timestamp && (!this._minimumRecordTime || timestamp < this._minimumRecordTime)) |
+ this._minimumRecordTime = timestamp; |
+ var endTimeStamp = (payload.ts + (payload.dur || 0)) / 1000; |
+ this._maximumRecordTime = Math.max(this._maximumRecordTime, endTimeStamp); |
+ var event = process._addEvent(payload); |
+ if (!event) |
+ return; |
+ if (payload.ph === WebInspector.TracingModel.Phase.Sample) { |
+ this._addSampleEvent(event); |
+ return; |
+ } |
+ // Build async event when we've got events from all threads & processes, so we can sort them and process in the |
+ // chronological order. However, also add individual async events to the thread flow (above), so we can easily |
+ // display them on the same chart as other events, should we choose so. |
+ if (WebInspector.TracingModel.isAsyncPhase(payload.ph)) |
+ this._asyncEvents.push(event); |
+ event._setBackingStorage(backingStorage); |
+ if (event.hasCategory(WebInspector.TracingModel.DevToolsMetadataEventCategory)) |
+ this._devToolsMetadataEvents.push(event); |
+ |
+ if (payload.ph !== WebInspector.TracingModel.Phase.Metadata) |
+ return; |
+ |
+ switch (payload.name) { |
+ case WebInspector.TracingModel.MetadataEvent.ProcessSortIndex: |
+ process._setSortIndex(payload.args['sort_index']); |
+ break; |
+ case WebInspector.TracingModel.MetadataEvent.ProcessName: |
+ var processName = payload.args['name']; |
+ process._setName(processName); |
+ this._processByName.set(processName, process); |
+ break; |
+ case WebInspector.TracingModel.MetadataEvent.ThreadSortIndex: |
+ process.threadById(payload.tid)._setSortIndex(payload.args['sort_index']); |
+ break; |
+ case WebInspector.TracingModel.MetadataEvent.ThreadName: |
+ process.threadById(payload.tid)._setName(payload.args['name']); |
+ break; |
+ } |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} event |
+ */ |
+ _addSampleEvent(event) { |
+ var group = this._profileGroups.get(event.id); |
+ if (group) |
+ group._addChild(event); |
+ else |
+ this._profileGroups.set(event.id, new WebInspector.TracingModel.ProfileEventsGroup(event)); |
+ } |
+ |
+ /** |
+ * @param {string} id |
+ * @return {?WebInspector.TracingModel.ProfileEventsGroup} |
+ */ |
+ profileGroup(id) { |
+ return this._profileGroups.get(id) || null; |
+ } |
+ |
+ /** |
+ * @return {number} |
+ */ |
+ minimumRecordTime() { |
+ return this._minimumRecordTime; |
+ } |
+ |
+ /** |
+ * @return {number} |
+ */ |
+ maximumRecordTime() { |
+ return this._maximumRecordTime; |
+ } |
+ |
+ /** |
+ * @return {!Array.<!WebInspector.TracingModel.Process>} |
+ */ |
+ sortedProcesses() { |
+ return WebInspector.TracingModel.NamedObject._sort(this._processById.valuesArray()); |
+ } |
+ |
+ /** |
+ * @param {string} name |
+ * @return {?WebInspector.TracingModel.Process} |
+ */ |
+ processByName(name) { |
+ return this._processByName.get(name); |
+ } |
+ |
+ /** |
+ * @param {string} processName |
+ * @param {string} threadName |
+ * @return {?WebInspector.TracingModel.Thread} |
+ */ |
+ threadByName(processName, threadName) { |
+ var process = this.processByName(processName); |
+ return process && process.threadByName(threadName); |
+ } |
+ |
+ _processPendingAsyncEvents() { |
+ this._asyncEvents.stableSort(WebInspector.TracingModel.Event.compareStartTime); |
+ for (var i = 0; i < this._asyncEvents.length; ++i) { |
+ var event = this._asyncEvents[i]; |
+ if (WebInspector.TracingModel.isNestableAsyncPhase(event.phase)) |
+ this._addNestableAsyncEvent(event); |
+ else |
+ this._addAsyncEvent(event); |
+ } |
+ this._asyncEvents = []; |
+ this._closeOpenAsyncEvents(); |
+ } |
+ |
+ _closeOpenAsyncEvents() { |
+ for (var event of this._openAsyncEvents.values()) { |
+ event.setEndTime(this._maximumRecordTime); |
+ // FIXME: remove this once we figure a better way to convert async console |
+ // events to sync [waterfall] timeline records. |
+ event.steps[0].setEndTime(this._maximumRecordTime); |
+ } |
+ this._openAsyncEvents.clear(); |
- var eventsDelimiter = ",\n"; |
- this._backingStorage.appendString(this._firstWritePending ? "[" : eventsDelimiter); |
- this._firstWritePending = false; |
- var stringPayload = JSON.stringify(payload); |
- var isAccessible = payload.ph === WebInspector.TracingModel.Phase.SnapshotObject; |
- var backingStorage = null; |
- var keepStringsLessThan = 10000; |
- if (isAccessible && stringPayload.length > keepStringsLessThan) |
- backingStorage = this._backingStorage.appendAccessibleString(stringPayload); |
- else |
- this._backingStorage.appendString(stringPayload); |
- |
- var timestamp = payload.ts / 1000; |
- // We do allow records for unrelated threads to arrive out-of-order, |
- // so there's a chance we're getting records from the past. |
- if (timestamp && (!this._minimumRecordTime || timestamp < this._minimumRecordTime)) |
- this._minimumRecordTime = timestamp; |
- var endTimeStamp = (payload.ts + (payload.dur || 0)) / 1000; |
- this._maximumRecordTime = Math.max(this._maximumRecordTime, endTimeStamp); |
- var event = process._addEvent(payload); |
- if (!event) |
- return; |
- if (payload.ph === WebInspector.TracingModel.Phase.Sample) { |
- this._addSampleEvent(event); |
- return; |
+ for (var eventStack of this._openNestableAsyncEvents.values()) { |
+ while (eventStack.length) |
+ eventStack.pop().setEndTime(this._maximumRecordTime); |
+ } |
+ this._openNestableAsyncEvents.clear(); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} event |
+ */ |
+ _addNestableAsyncEvent(event) { |
+ var phase = WebInspector.TracingModel.Phase; |
+ var key = event.categoriesString + '.' + event.id; |
+ var openEventsStack = this._openNestableAsyncEvents.get(key); |
+ |
+ switch (event.phase) { |
+ case phase.NestableAsyncBegin: |
+ if (!openEventsStack) { |
+ openEventsStack = []; |
+ this._openNestableAsyncEvents.set(key, openEventsStack); |
} |
- // Build async event when we've got events from all threads & processes, so we can sort them and process in the |
- // chronological order. However, also add individual async events to the thread flow (above), so we can easily |
- // display them on the same chart as other events, should we choose so. |
- if (WebInspector.TracingModel.isAsyncPhase(payload.ph)) |
- this._asyncEvents.push(event); |
- event._setBackingStorage(backingStorage); |
- if (event.hasCategory(WebInspector.TracingModel.DevToolsMetadataEventCategory)) |
- this._devToolsMetadataEvents.push(event); |
- |
- if (payload.ph !== WebInspector.TracingModel.Phase.Metadata) |
- return; |
- |
- switch (payload.name) { |
- case WebInspector.TracingModel.MetadataEvent.ProcessSortIndex: |
- process._setSortIndex(payload.args["sort_index"]); |
- break; |
- case WebInspector.TracingModel.MetadataEvent.ProcessName: |
- var processName = payload.args["name"]; |
- process._setName(processName); |
- this._processByName.set(processName, process); |
- break; |
- case WebInspector.TracingModel.MetadataEvent.ThreadSortIndex: |
- process.threadById(payload.tid)._setSortIndex(payload.args["sort_index"]); |
- break; |
- case WebInspector.TracingModel.MetadataEvent.ThreadName: |
- process.threadById(payload.tid)._setName(payload.args["name"]); |
- break; |
+ var asyncEvent = new WebInspector.TracingModel.AsyncEvent(event); |
+ openEventsStack.push(asyncEvent); |
+ event.thread._addAsyncEvent(asyncEvent); |
+ break; |
+ |
+ case phase.NestableAsyncInstant: |
+ if (openEventsStack && openEventsStack.length) |
+ openEventsStack.peekLast()._addStep(event); |
+ break; |
+ |
+ case phase.NestableAsyncEnd: |
+ if (!openEventsStack || !openEventsStack.length) |
+ break; |
+ var top = openEventsStack.pop(); |
+ if (top.name !== event.name) { |
+ console.error( |
+ `Begin/end event mismatch for nestable async event, ${top.name} vs. ${event.name}, key: ${key}`); |
+ break; |
} |
- }, |
- |
- /** |
- * @param {!WebInspector.TracingModel.Event} event |
- */ |
- _addSampleEvent: function(event) |
- { |
- var group = this._profileGroups.get(event.id); |
- if (group) |
- group._addChild(event); |
- else |
- this._profileGroups.set(event.id, new WebInspector.TracingModel.ProfileEventsGroup(event)); |
- }, |
+ top._addStep(event); |
+ } |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} event |
+ */ |
+ _addAsyncEvent(event) { |
+ var phase = WebInspector.TracingModel.Phase; |
+ var key = event.categoriesString + '.' + event.name + '.' + event.id; |
+ var asyncEvent = this._openAsyncEvents.get(key); |
+ |
+ if (event.phase === phase.AsyncBegin) { |
+ if (asyncEvent) { |
+ console.error(`Event ${event.name} has already been started`); |
+ return; |
+ } |
+ asyncEvent = new WebInspector.TracingModel.AsyncEvent(event); |
+ this._openAsyncEvents.set(key, asyncEvent); |
+ event.thread._addAsyncEvent(asyncEvent); |
+ return; |
+ } |
+ if (!asyncEvent) { |
+ // Quietly ignore stray async events, we're probably too late for the start. |
+ return; |
+ } |
+ if (event.phase === phase.AsyncEnd) { |
+ asyncEvent._addStep(event); |
+ this._openAsyncEvents.delete(key); |
+ return; |
+ } |
+ if (event.phase === phase.AsyncStepInto || event.phase === phase.AsyncStepPast) { |
+ var lastStep = asyncEvent.steps.peekLast(); |
+ if (lastStep.phase !== phase.AsyncBegin && lastStep.phase !== event.phase) { |
+ console.assert( |
+ false, 'Async event step phase mismatch: ' + lastStep.phase + ' at ' + lastStep.startTime + ' vs. ' + |
+ event.phase + ' at ' + event.startTime); |
+ return; |
+ } |
+ asyncEvent._addStep(event); |
+ return; |
+ } |
+ console.assert(false, 'Invalid async event phase'); |
+ } |
+ |
+ /** |
+ * @param {string} str |
+ * @return {!Set<string>} |
+ */ |
+ _parsedCategoriesForString(str) { |
+ var parsedCategories = this._parsedCategories.get(str); |
+ if (!parsedCategories) { |
+ parsedCategories = new Set(str.split(',')); |
+ this._parsedCategories.set(str, parsedCategories); |
+ } |
+ return parsedCategories; |
+ } |
+}; |
- /** |
- * @param {string} id |
- * @return {?WebInspector.TracingModel.ProfileEventsGroup} |
- */ |
- profileGroup: function(id) |
- { |
- return this._profileGroups.get(id) || null; |
- }, |
+/** |
+ * @enum {string} |
+ */ |
+WebInspector.TracingModel.Phase = { |
+ Begin: 'B', |
+ End: 'E', |
+ Complete: 'X', |
+ Instant: 'I', |
+ AsyncBegin: 'S', |
+ AsyncStepInto: 'T', |
+ AsyncStepPast: 'p', |
+ AsyncEnd: 'F', |
+ NestableAsyncBegin: 'b', |
+ NestableAsyncEnd: 'e', |
+ NestableAsyncInstant: 'n', |
+ FlowBegin: 's', |
+ FlowStep: 't', |
+ FlowEnd: 'f', |
+ Metadata: 'M', |
+ Counter: 'C', |
+ Sample: 'P', |
+ CreateObject: 'N', |
+ SnapshotObject: 'O', |
+ DeleteObject: 'D' |
+}; |
- /** |
- * @return {number} |
- */ |
- minimumRecordTime: function() |
- { |
- return this._minimumRecordTime; |
- }, |
+WebInspector.TracingModel.MetadataEvent = { |
+ ProcessSortIndex: 'process_sort_index', |
+ ProcessName: 'process_name', |
+ ThreadSortIndex: 'thread_sort_index', |
+ ThreadName: 'thread_name' |
+}; |
- /** |
- * @return {number} |
- */ |
- maximumRecordTime: function() |
- { |
- return this._maximumRecordTime; |
- }, |
+WebInspector.TracingModel.TopLevelEventCategory = 'toplevel'; |
+WebInspector.TracingModel.DevToolsMetadataEventCategory = 'disabled-by-default-devtools.timeline'; |
+WebInspector.TracingModel.DevToolsTimelineEventCategory = 'disabled-by-default-devtools.timeline'; |
- /** |
- * @return {!Array.<!WebInspector.TracingModel.Process>} |
- */ |
- sortedProcesses: function() |
- { |
- return WebInspector.TracingModel.NamedObject._sort(this._processById.valuesArray()); |
- }, |
+WebInspector.TracingModel.FrameLifecycleEventCategory = 'cc,devtools'; |
- /** |
- * @param {string} name |
- * @return {?WebInspector.TracingModel.Process} |
- */ |
- processByName: function(name) |
- { |
- return this._processByName.get(name); |
- }, |
- /** |
- * @param {string} processName |
- * @param {string} threadName |
- * @return {?WebInspector.TracingModel.Thread} |
- */ |
- threadByName: function(processName, threadName) |
- { |
- var process = this.processByName(processName); |
- return process && process.threadByName(threadName); |
- }, |
- |
- _processPendingAsyncEvents: function() |
- { |
- this._asyncEvents.stableSort(WebInspector.TracingModel.Event.compareStartTime); |
- for (var i = 0; i < this._asyncEvents.length; ++i) { |
- var event = this._asyncEvents[i]; |
- if (WebInspector.TracingModel.isNestableAsyncPhase(event.phase)) |
- this._addNestableAsyncEvent(event); |
- else |
- this._addAsyncEvent(event); |
- } |
- this._asyncEvents = []; |
- this._closeOpenAsyncEvents(); |
- }, |
- |
- _closeOpenAsyncEvents: function() |
- { |
- for (var event of this._openAsyncEvents.values()) { |
- event.setEndTime(this._maximumRecordTime); |
- // FIXME: remove this once we figure a better way to convert async console |
- // events to sync [waterfall] timeline records. |
- event.steps[0].setEndTime(this._maximumRecordTime); |
- } |
- this._openAsyncEvents.clear(); |
+/** |
+ * @interface |
+ */ |
+WebInspector.BackingStorage = function() {}; |
- for (var eventStack of this._openNestableAsyncEvents.values()) { |
- while (eventStack.length) |
- eventStack.pop().setEndTime(this._maximumRecordTime); |
- } |
- this._openNestableAsyncEvents.clear(); |
- }, |
+WebInspector.BackingStorage.prototype = { |
+ /** |
+ * @param {string} string |
+ */ |
+ appendString: function(string) {}, |
- /** |
- * @param {!WebInspector.TracingModel.Event} event |
- */ |
- _addNestableAsyncEvent: function(event) |
- { |
- var phase = WebInspector.TracingModel.Phase; |
- var key = event.categoriesString + "." + event.id; |
- var openEventsStack = this._openNestableAsyncEvents.get(key); |
- |
- switch (event.phase) { |
- case phase.NestableAsyncBegin: |
- if (!openEventsStack) { |
- openEventsStack = []; |
- this._openNestableAsyncEvents.set(key, openEventsStack); |
- } |
- var asyncEvent = new WebInspector.TracingModel.AsyncEvent(event); |
- openEventsStack.push(asyncEvent); |
- event.thread._addAsyncEvent(asyncEvent); |
- break; |
- |
- case phase.NestableAsyncInstant: |
- if (openEventsStack && openEventsStack.length) |
- openEventsStack.peekLast()._addStep(event); |
- break; |
- |
- case phase.NestableAsyncEnd: |
- if (!openEventsStack || !openEventsStack.length) |
- break; |
- var top = openEventsStack.pop(); |
- if (top.name !== event.name) { |
- console.error(`Begin/end event mismatch for nestable async event, ${top.name} vs. ${event.name}, key: ${key}`); |
- break; |
- } |
- top._addStep(event); |
- } |
- }, |
+ /** |
+ * @param {string} string |
+ * @return {function():!Promise.<?string>} |
+ */ |
+ appendAccessibleString: function(string) {}, |
- /** |
- * @param {!WebInspector.TracingModel.Event} event |
- */ |
- _addAsyncEvent: function(event) |
- { |
- var phase = WebInspector.TracingModel.Phase; |
- var key = event.categoriesString + "." + event.name + "." + event.id; |
- var asyncEvent = this._openAsyncEvents.get(key); |
- |
- if (event.phase === phase.AsyncBegin) { |
- if (asyncEvent) { |
- console.error(`Event ${event.name} has already been started`); |
- return; |
- } |
- asyncEvent = new WebInspector.TracingModel.AsyncEvent(event); |
- this._openAsyncEvents.set(key, asyncEvent); |
- event.thread._addAsyncEvent(asyncEvent); |
- return; |
- } |
- if (!asyncEvent) { |
- // Quietly ignore stray async events, we're probably too late for the start. |
- return; |
- } |
- if (event.phase === phase.AsyncEnd) { |
- asyncEvent._addStep(event); |
- this._openAsyncEvents.delete(key); |
- return; |
- } |
- if (event.phase === phase.AsyncStepInto || event.phase === phase.AsyncStepPast) { |
- var lastStep = asyncEvent.steps.peekLast(); |
- if (lastStep.phase !== phase.AsyncBegin && lastStep.phase !== event.phase) { |
- console.assert(false, "Async event step phase mismatch: " + lastStep.phase + " at " + lastStep.startTime + " vs. " + event.phase + " at " + event.startTime); |
- return; |
- } |
- asyncEvent._addStep(event); |
- return; |
- } |
- console.assert(false, "Invalid async event phase"); |
- }, |
+ finishWriting: function() {}, |
- /** |
- * @param {string} str |
- * @return {!Set<string>} |
- */ |
- _parsedCategoriesForString: function(str) |
- { |
- var parsedCategories = this._parsedCategories.get(str); |
- if (!parsedCategories) { |
- parsedCategories = new Set(str.split(",")); |
- this._parsedCategories.set(str, parsedCategories); |
- } |
- return parsedCategories; |
- } |
+ reset: function() {}, |
}; |
/** |
- * @constructor |
- * @param {string} categories |
- * @param {string} name |
- * @param {!WebInspector.TracingModel.Phase} phase |
- * @param {number} startTime |
- * @param {!WebInspector.TracingModel.Thread} thread |
+ * @unrestricted |
*/ |
-WebInspector.TracingModel.Event = function(categories, name, phase, startTime, thread) |
-{ |
+WebInspector.TracingModel.Event = class { |
+ /** |
+ * @param {string} categories |
+ * @param {string} name |
+ * @param {!WebInspector.TracingModel.Phase} phase |
+ * @param {number} startTime |
+ * @param {!WebInspector.TracingModel.Thread} thread |
+ */ |
+ constructor(categories, name, phase, startTime, thread) { |
/** @type {string} */ |
this.categoriesString = categories; |
/** @type {!Set<string>} */ |
@@ -532,504 +516,465 @@ WebInspector.TracingModel.Event = function(categories, name, phase, startTime, t |
/** @type {number} */ |
this.selfTime = 0; |
-}; |
- |
-/** |
- * @param {!WebInspector.TracingManager.EventPayload} payload |
- * @param {!WebInspector.TracingModel.Thread} thread |
- * @return {!WebInspector.TracingModel.Event} |
- */ |
-WebInspector.TracingModel.Event.fromPayload = function(payload, thread) |
-{ |
- var event = new WebInspector.TracingModel.Event(payload.cat, payload.name, /** @type {!WebInspector.TracingModel.Phase} */ (payload.ph), payload.ts / 1000, thread); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingManager.EventPayload} payload |
+ * @param {!WebInspector.TracingModel.Thread} thread |
+ * @return {!WebInspector.TracingModel.Event} |
+ */ |
+ static fromPayload(payload, thread) { |
+ var event = new WebInspector.TracingModel.Event( |
+ payload.cat, payload.name, /** @type {!WebInspector.TracingModel.Phase} */ (payload.ph), payload.ts / 1000, |
+ thread); |
if (payload.args) |
- event.addArgs(payload.args); |
+ event.addArgs(payload.args); |
else |
- console.error("Missing mandatory event argument 'args' at " + payload.ts / 1000); |
- if (typeof payload.dur === "number") |
- event.setEndTime((payload.ts + payload.dur) / 1000); |
+ console.error('Missing mandatory event argument \'args\' at ' + payload.ts / 1000); |
+ if (typeof payload.dur === 'number') |
+ event.setEndTime((payload.ts + payload.dur) / 1000); |
var id = WebInspector.TracingModel._extractId(payload); |
- if (typeof id !== "undefined") |
- event.id = id; |
+ if (typeof id !== 'undefined') |
+ event.id = id; |
if (payload.bind_id) |
- event.bind_id = payload.bind_id; |
+ event.bind_id = payload.bind_id; |
return event; |
-}; |
- |
-WebInspector.TracingModel.Event.prototype = { |
- /** |
- * @param {string} categoryName |
- * @return {boolean} |
- */ |
- hasCategory: function(categoryName) |
- { |
- return this._parsedCategories.has(categoryName); |
- }, |
- |
- /** |
- * @param {number} endTime |
- */ |
- setEndTime: function(endTime) |
- { |
- if (endTime < this.startTime) { |
- console.assert(false, "Event out of order: " + this.name); |
- return; |
- } |
- this.endTime = endTime; |
- this.duration = endTime - this.startTime; |
- }, |
- |
- /** |
- * @param {!Object} args |
- */ |
- addArgs: function(args) |
- { |
- // Shallow copy args to avoid modifying original payload which may be saved to file. |
- for (var name in args) { |
- if (name in this.args) |
- console.error("Same argument name (" + name + ") is used for begin and end phases of " + this.name); |
- this.args[name] = args[name]; |
- } |
- }, |
- |
- /** |
- * @param {!WebInspector.TracingModel.Event} endEvent |
- */ |
- _complete: function(endEvent) |
- { |
- if (endEvent.args) |
- this.addArgs(endEvent.args); |
- else |
- console.error("Missing mandatory event argument 'args' at " + endEvent.startTime); |
- this.setEndTime(endEvent.startTime); |
- }, |
- |
- /** |
- * @param {?function():!Promise.<?string>} backingStorage |
- */ |
- _setBackingStorage: function(backingStorage) |
- { |
- } |
-}; |
- |
-/** |
- * @param {!WebInspector.TracingModel.Event} a |
- * @param {!WebInspector.TracingModel.Event} b |
- * @return {number} |
- */ |
-WebInspector.TracingModel.Event.compareStartTime = function(a, b) |
-{ |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} a |
+ * @param {!WebInspector.TracingModel.Event} b |
+ * @return {number} |
+ */ |
+ static compareStartTime(a, b) { |
return a.startTime - b.startTime; |
-}; |
- |
-/** |
- * @param {!WebInspector.TracingModel.Event} a |
- * @param {!WebInspector.TracingModel.Event} b |
- * @return {number} |
- */ |
-WebInspector.TracingModel.Event.compareStartAndEndTime = function(a, b) |
-{ |
- return a.startTime - b.startTime || (b.endTime !== undefined && a.endTime !== undefined && b.endTime - a.endTime) || 0; |
-}; |
- |
-/** |
- * @param {!WebInspector.TracingModel.Event} a |
- * @param {!WebInspector.TracingModel.Event} b |
- * @return {number} |
- */ |
-WebInspector.TracingModel.Event.orderedCompareStartTime = function(a, b) |
-{ |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} a |
+ * @param {!WebInspector.TracingModel.Event} b |
+ * @return {number} |
+ */ |
+ static compareStartAndEndTime(a, b) { |
+ return a.startTime - b.startTime || (b.endTime !== undefined && a.endTime !== undefined && b.endTime - a.endTime) || |
+ 0; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} a |
+ * @param {!WebInspector.TracingModel.Event} b |
+ * @return {number} |
+ */ |
+ static orderedCompareStartTime(a, b) { |
// Array.mergeOrdered coalesces objects if comparator returns 0. |
// To change this behavior this comparator return -1 in the case events |
// startTime's are equal, so both events got placed into the result array. |
return a.startTime - b.startTime || a.ordinal - b.ordinal || -1; |
-}; |
+ } |
+ |
+ /** |
+ * @param {string} categoryName |
+ * @return {boolean} |
+ */ |
+ hasCategory(categoryName) { |
+ return this._parsedCategories.has(categoryName); |
+ } |
+ |
+ /** |
+ * @param {number} endTime |
+ */ |
+ setEndTime(endTime) { |
+ if (endTime < this.startTime) { |
+ console.assert(false, 'Event out of order: ' + this.name); |
+ return; |
+ } |
+ this.endTime = endTime; |
+ this.duration = endTime - this.startTime; |
+ } |
+ |
+ /** |
+ * @param {!Object} args |
+ */ |
+ addArgs(args) { |
+ // Shallow copy args to avoid modifying original payload which may be saved to file. |
+ for (var name in args) { |
+ if (name in this.args) |
+ console.error('Same argument name (' + name + ') is used for begin and end phases of ' + this.name); |
+ this.args[name] = args[name]; |
+ } |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} endEvent |
+ */ |
+ _complete(endEvent) { |
+ if (endEvent.args) |
+ this.addArgs(endEvent.args); |
+ else |
+ console.error('Missing mandatory event argument \'args\' at ' + endEvent.startTime); |
+ this.setEndTime(endEvent.startTime); |
+ } |
-/** |
- * @constructor |
- * @extends {WebInspector.TracingModel.Event} |
- * @param {string} category |
- * @param {string} name |
- * @param {number} startTime |
- * @param {!WebInspector.TracingModel.Thread} thread |
- */ |
-WebInspector.TracingModel.ObjectSnapshot = function(category, name, startTime, thread) |
-{ |
- WebInspector.TracingModel.Event.call(this, category, name, WebInspector.TracingModel.Phase.SnapshotObject, startTime, thread); |
+ /** |
+ * @param {?function():!Promise.<?string>} backingStorage |
+ */ |
+ _setBackingStorage(backingStorage) { |
+ } |
}; |
+ |
/** |
- * @param {!WebInspector.TracingManager.EventPayload} payload |
- * @param {!WebInspector.TracingModel.Thread} thread |
- * @return {!WebInspector.TracingModel.ObjectSnapshot} |
+ * @unrestricted |
*/ |
-WebInspector.TracingModel.ObjectSnapshot.fromPayload = function(payload, thread) |
-{ |
+WebInspector.TracingModel.ObjectSnapshot = class extends WebInspector.TracingModel.Event { |
+ /** |
+ * @param {string} category |
+ * @param {string} name |
+ * @param {number} startTime |
+ * @param {!WebInspector.TracingModel.Thread} thread |
+ */ |
+ constructor(category, name, startTime, thread) { |
+ super(category, name, WebInspector.TracingModel.Phase.SnapshotObject, startTime, thread); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingManager.EventPayload} payload |
+ * @param {!WebInspector.TracingModel.Thread} thread |
+ * @return {!WebInspector.TracingModel.ObjectSnapshot} |
+ */ |
+ static fromPayload(payload, thread) { |
var snapshot = new WebInspector.TracingModel.ObjectSnapshot(payload.cat, payload.name, payload.ts / 1000, thread); |
var id = WebInspector.TracingModel._extractId(payload); |
- if (typeof id !== "undefined") |
- snapshot.id = id; |
- if (!payload.args || !payload.args["snapshot"]) { |
- console.error("Missing mandatory 'snapshot' argument at " + payload.ts / 1000); |
- return snapshot; |
+ if (typeof id !== 'undefined') |
+ snapshot.id = id; |
+ if (!payload.args || !payload.args['snapshot']) { |
+ console.error('Missing mandatory \'snapshot\' argument at ' + payload.ts / 1000); |
+ return snapshot; |
} |
if (payload.args) |
- snapshot.addArgs(payload.args); |
+ snapshot.addArgs(payload.args); |
return snapshot; |
+ } |
+ |
+ /** |
+ * @param {function(?)} callback |
+ */ |
+ requestObject(callback) { |
+ var snapshot = this.args['snapshot']; |
+ if (snapshot) { |
+ callback(snapshot); |
+ return; |
+ } |
+ this._backingStorage().then(onRead, callback.bind(null, null)); |
+ /** |
+ * @param {?string} result |
+ */ |
+ function onRead(result) { |
+ if (!result) { |
+ callback(null); |
+ return; |
+ } |
+ try { |
+ var payload = JSON.parse(result); |
+ callback(payload['args']['snapshot']); |
+ } catch (e) { |
+ WebInspector.console.error('Malformed event data in backing storage'); |
+ callback(null); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * @return {!Promise<?>} |
+ */ |
+ objectPromise() { |
+ if (!this._objectPromise) |
+ this._objectPromise = new Promise(this.requestObject.bind(this)); |
+ return this._objectPromise; |
+ } |
+ |
+ /** |
+ * @override |
+ * @param {?function():!Promise.<?>} backingStorage |
+ */ |
+ _setBackingStorage(backingStorage) { |
+ if (!backingStorage) |
+ return; |
+ this._backingStorage = backingStorage; |
+ this.args = {}; |
+ } |
}; |
-WebInspector.TracingModel.ObjectSnapshot.prototype = { |
- /** |
- * @param {function(?)} callback |
- */ |
- requestObject: function(callback) |
- { |
- var snapshot = this.args["snapshot"]; |
- if (snapshot) { |
- callback(snapshot); |
- return; |
- } |
- this._backingStorage().then(onRead, callback.bind(null, null)); |
- /** |
- * @param {?string} result |
- */ |
- function onRead(result) |
- { |
- if (!result) { |
- callback(null); |
- return; |
- } |
- try { |
- var payload = JSON.parse(result); |
- callback(payload["args"]["snapshot"]); |
- } catch (e) { |
- WebInspector.console.error("Malformed event data in backing storage"); |
- callback(null); |
- } |
- } |
- }, |
- |
- /** |
- * @return {!Promise<?>} |
- */ |
- objectPromise: function() |
- { |
- if (!this._objectPromise) |
- this._objectPromise = new Promise(this.requestObject.bind(this)); |
- return this._objectPromise; |
- }, |
- |
- /** |
- * @override |
- * @param {?function():!Promise.<?>} backingStorage |
- */ |
- _setBackingStorage: function(backingStorage) |
- { |
- if (!backingStorage) |
- return; |
- this._backingStorage = backingStorage; |
- this.args = {}; |
- }, |
- |
- __proto__: WebInspector.TracingModel.Event.prototype |
-}; |
/** |
- * @constructor |
- * @param {!WebInspector.TracingModel.Event} startEvent |
- * @extends {WebInspector.TracingModel.Event} |
+ * @unrestricted |
*/ |
-WebInspector.TracingModel.AsyncEvent = function(startEvent) |
-{ |
- WebInspector.TracingModel.Event.call(this, startEvent.categoriesString, startEvent.name, startEvent.phase, startEvent.startTime, startEvent.thread); |
+WebInspector.TracingModel.AsyncEvent = class extends WebInspector.TracingModel.Event { |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} startEvent |
+ */ |
+ constructor(startEvent) { |
+ super(startEvent.categoriesString, startEvent.name, startEvent.phase, startEvent.startTime, startEvent.thread); |
this.addArgs(startEvent.args); |
this.steps = [startEvent]; |
-}; |
- |
-WebInspector.TracingModel.AsyncEvent.prototype = { |
- /** |
- * @param {!WebInspector.TracingModel.Event} event |
- */ |
- _addStep: function(event) |
- { |
- this.steps.push(event); |
- if (event.phase === WebInspector.TracingModel.Phase.AsyncEnd || event.phase === WebInspector.TracingModel.Phase.NestableAsyncEnd) { |
- this.setEndTime(event.startTime); |
- // FIXME: ideally, we shouldn't do this, but this makes the logic of converting |
- // async console events to sync ones much simpler. |
- this.steps[0].setEndTime(event.startTime); |
- } |
- }, |
- |
- __proto__: WebInspector.TracingModel.Event.prototype |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} event |
+ */ |
+ _addStep(event) { |
+ this.steps.push(event); |
+ if (event.phase === WebInspector.TracingModel.Phase.AsyncEnd || |
+ event.phase === WebInspector.TracingModel.Phase.NestableAsyncEnd) { |
+ this.setEndTime(event.startTime); |
+ // FIXME: ideally, we shouldn't do this, but this makes the logic of converting |
+ // async console events to sync ones much simpler. |
+ this.steps[0].setEndTime(event.startTime); |
+ } |
+ } |
}; |
/** |
- * @constructor |
- * @param {!WebInspector.TracingModel.Event} event |
+ * @unrestricted |
*/ |
-WebInspector.TracingModel.ProfileEventsGroup = function(event) |
-{ |
+WebInspector.TracingModel.ProfileEventsGroup = class { |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} event |
+ */ |
+ constructor(event) { |
/** @type {!Array<!WebInspector.TracingModel.Event>} */ |
this.children = [event]; |
-}; |
+ } |
-WebInspector.TracingModel.ProfileEventsGroup.prototype = { |
- /** |
- * @param {!WebInspector.TracingModel.Event} event |
- */ |
- _addChild: function(event) |
- { |
- this.children.push(event); |
- } |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} event |
+ */ |
+ _addChild(event) { |
+ this.children.push(event); |
+ } |
}; |
/** |
- * @constructor |
+ * @unrestricted |
*/ |
-WebInspector.TracingModel.NamedObject = function() |
-{ |
-}; |
- |
-WebInspector.TracingModel.NamedObject.prototype = |
-{ |
- /** |
- * @param {string} name |
- */ |
- _setName: function(name) |
- { |
- this._name = name; |
- }, |
- |
- /** |
- * @return {string} |
- */ |
- name: function() |
- { |
- return this._name; |
- }, |
- |
- /** |
- * @param {number} sortIndex |
- */ |
- _setSortIndex: function(sortIndex) |
- { |
- this._sortIndex = sortIndex; |
- }, |
-}; |
- |
-/** |
- * @param {!Array.<!WebInspector.TracingModel.NamedObject>} array |
- */ |
-WebInspector.TracingModel.NamedObject._sort = function(array) |
-{ |
+WebInspector.TracingModel.NamedObject = class { |
+ /** |
+ * @param {!Array.<!WebInspector.TracingModel.NamedObject>} array |
+ */ |
+ static _sort(array) { |
/** |
* @param {!WebInspector.TracingModel.NamedObject} a |
* @param {!WebInspector.TracingModel.NamedObject} b |
*/ |
- function comparator(a, b) |
- { |
- return a._sortIndex !== b._sortIndex ? a._sortIndex - b._sortIndex : a.name().localeCompare(b.name()); |
+ function comparator(a, b) { |
+ return a._sortIndex !== b._sortIndex ? a._sortIndex - b._sortIndex : a.name().localeCompare(b.name()); |
} |
return array.sort(comparator); |
+ } |
+ |
+ /** |
+ * @param {string} name |
+ */ |
+ _setName(name) { |
+ this._name = name; |
+ } |
+ |
+ /** |
+ * @return {string} |
+ */ |
+ name() { |
+ return this._name; |
+ } |
+ |
+ /** |
+ * @param {number} sortIndex |
+ */ |
+ _setSortIndex(sortIndex) { |
+ this._sortIndex = sortIndex; |
+ } |
}; |
+ |
/** |
- * @constructor |
- * @extends {WebInspector.TracingModel.NamedObject} |
- * @param {!WebInspector.TracingModel} model |
- * @param {number} id |
+ * @unrestricted |
*/ |
-WebInspector.TracingModel.Process = function(model, id) |
-{ |
- WebInspector.TracingModel.NamedObject.call(this); |
- this._setName("Process " + id); |
+WebInspector.TracingModel.Process = class extends WebInspector.TracingModel.NamedObject { |
+ /** |
+ * @param {!WebInspector.TracingModel} model |
+ * @param {number} id |
+ */ |
+ constructor(model, id) { |
+ super(); |
+ this._setName('Process ' + id); |
this._id = id; |
/** @type {!Map<number, !WebInspector.TracingModel.Thread>} */ |
this._threads = new Map(); |
this._threadByName = new Map(); |
this._model = model; |
-}; |
- |
-WebInspector.TracingModel.Process.prototype = { |
- /** |
- * @return {number} |
- */ |
- id: function() |
- { |
- return this._id; |
- }, |
- |
- /** |
- * @param {number} id |
- * @return {!WebInspector.TracingModel.Thread} |
- */ |
- threadById: function(id) |
- { |
- var thread = this._threads.get(id); |
- if (!thread) { |
- thread = new WebInspector.TracingModel.Thread(this, id); |
- this._threads.set(id, thread); |
- } |
- return thread; |
- }, |
- |
- /** |
- * @param {string} name |
- * @return {?WebInspector.TracingModel.Thread} |
- */ |
- threadByName: function(name) |
- { |
- return this._threadByName.get(name) || null; |
- }, |
- |
- /** |
- * @param {string} name |
- * @param {!WebInspector.TracingModel.Thread} thread |
- */ |
- _setThreadByName: function(name, thread) |
- { |
- this._threadByName.set(name, thread); |
- }, |
- |
- /** |
- * @param {!WebInspector.TracingManager.EventPayload} payload |
- * @return {?WebInspector.TracingModel.Event} event |
- */ |
- _addEvent: function(payload) |
- { |
- return this.threadById(payload.tid)._addEvent(payload); |
- }, |
- |
- /** |
- * @return {!Array.<!WebInspector.TracingModel.Thread>} |
- */ |
- sortedThreads: function() |
- { |
- return WebInspector.TracingModel.NamedObject._sort(this._threads.valuesArray()); |
- }, |
- |
- __proto__: WebInspector.TracingModel.NamedObject.prototype |
+ } |
+ |
+ /** |
+ * @return {number} |
+ */ |
+ id() { |
+ return this._id; |
+ } |
+ |
+ /** |
+ * @param {number} id |
+ * @return {!WebInspector.TracingModel.Thread} |
+ */ |
+ threadById(id) { |
+ var thread = this._threads.get(id); |
+ if (!thread) { |
+ thread = new WebInspector.TracingModel.Thread(this, id); |
+ this._threads.set(id, thread); |
+ } |
+ return thread; |
+ } |
+ |
+ /** |
+ * @param {string} name |
+ * @return {?WebInspector.TracingModel.Thread} |
+ */ |
+ threadByName(name) { |
+ return this._threadByName.get(name) || null; |
+ } |
+ |
+ /** |
+ * @param {string} name |
+ * @param {!WebInspector.TracingModel.Thread} thread |
+ */ |
+ _setThreadByName(name, thread) { |
+ this._threadByName.set(name, thread); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingManager.EventPayload} payload |
+ * @return {?WebInspector.TracingModel.Event} event |
+ */ |
+ _addEvent(payload) { |
+ return this.threadById(payload.tid)._addEvent(payload); |
+ } |
+ |
+ /** |
+ * @return {!Array.<!WebInspector.TracingModel.Thread>} |
+ */ |
+ sortedThreads() { |
+ return WebInspector.TracingModel.NamedObject._sort(this._threads.valuesArray()); |
+ } |
}; |
/** |
- * @constructor |
- * @extends {WebInspector.TracingModel.NamedObject} |
- * @param {!WebInspector.TracingModel.Process} process |
- * @param {number} id |
+ * @unrestricted |
*/ |
-WebInspector.TracingModel.Thread = function(process, id) |
-{ |
- WebInspector.TracingModel.NamedObject.call(this); |
+WebInspector.TracingModel.Thread = class extends WebInspector.TracingModel.NamedObject { |
+ /** |
+ * @param {!WebInspector.TracingModel.Process} process |
+ * @param {number} id |
+ */ |
+ constructor(process, id) { |
+ super(); |
this._process = process; |
- this._setName("Thread " + id); |
+ this._setName('Thread ' + id); |
this._events = []; |
this._asyncEvents = []; |
this._id = id; |
this._model = process._model; |
-}; |
- |
-WebInspector.TracingModel.Thread.prototype = { |
- tracingComplete: function() |
- { |
- this._asyncEvents.stableSort(WebInspector.TracingModel.Event.compareStartAndEndTime); |
- this._events.stableSort(WebInspector.TracingModel.Event.compareStartTime); |
- var phases = WebInspector.TracingModel.Phase; |
- var stack = []; |
- for (var i = 0; i < this._events.length; ++i) { |
- var e = this._events[i]; |
- e.ordinal = i; |
- switch (e.phase) { |
- case phases.End: |
- this._events[i] = null; // Mark for removal. |
- // Quietly ignore unbalanced close events, they're legit (we could have missed start one). |
- if (!stack.length) |
- continue; |
- var top = stack.pop(); |
- if (top.name !== e.name || top.categoriesString !== e.categoriesString) |
- console.error("B/E events mismatch at " + top.startTime + " (" + top.name + ") vs. " + e.startTime + " (" + e.name + ")"); |
- else |
- top._complete(e); |
- break; |
- case phases.Begin: |
- stack.push(e); |
- break; |
- } |
- } |
- while (stack.length) |
- stack.pop().setEndTime(this._model.maximumRecordTime()); |
- this._events.remove(null, false); |
- }, |
- |
- /** |
- * @param {!WebInspector.TracingManager.EventPayload} payload |
- * @return {?WebInspector.TracingModel.Event} event |
- */ |
- _addEvent: function(payload) |
- { |
- var event = payload.ph === WebInspector.TracingModel.Phase.SnapshotObject |
- ? WebInspector.TracingModel.ObjectSnapshot.fromPayload(payload, this) |
- : WebInspector.TracingModel.Event.fromPayload(payload, this); |
- if (WebInspector.TracingModel.isTopLevelEvent(event)) { |
- // Discard nested "top-level" events. |
- if (this._lastTopLevelEvent && this._lastTopLevelEvent.endTime > event.startTime) |
- return null; |
- this._lastTopLevelEvent = event; |
- } |
- this._events.push(event); |
- return event; |
- }, |
- |
- /** |
- * @param {!WebInspector.TracingModel.AsyncEvent} asyncEvent |
- */ |
- _addAsyncEvent: function(asyncEvent) |
- { |
- this._asyncEvents.push(asyncEvent); |
- }, |
- |
- /** |
- * @override |
- * @param {string} name |
- */ |
- _setName: function(name) |
- { |
- WebInspector.TracingModel.NamedObject.prototype._setName.call(this, name); |
- this._process._setThreadByName(name, this); |
- }, |
- |
- /** |
- * @return {number} |
- */ |
- id: function() |
- { |
- return this._id; |
- }, |
- |
- /** |
- * @return {!WebInspector.TracingModel.Process} |
- */ |
- process: function() |
- { |
- return this._process; |
- }, |
- |
- /** |
- * @return {!Array.<!WebInspector.TracingModel.Event>} |
- */ |
- events: function() |
- { |
- return this._events; |
- }, |
- |
- /** |
- * @return {!Array.<!WebInspector.TracingModel.AsyncEvent>} |
- */ |
- asyncEvents: function() |
- { |
- return this._asyncEvents; |
- }, |
- |
- __proto__: WebInspector.TracingModel.NamedObject.prototype |
+ } |
+ |
+ tracingComplete() { |
+ this._asyncEvents.stableSort(WebInspector.TracingModel.Event.compareStartAndEndTime); |
+ this._events.stableSort(WebInspector.TracingModel.Event.compareStartTime); |
+ var phases = WebInspector.TracingModel.Phase; |
+ var stack = []; |
+ for (var i = 0; i < this._events.length; ++i) { |
+ var e = this._events[i]; |
+ e.ordinal = i; |
+ switch (e.phase) { |
+ case phases.End: |
+ this._events[i] = null; // Mark for removal. |
+ // Quietly ignore unbalanced close events, they're legit (we could have missed start one). |
+ if (!stack.length) |
+ continue; |
+ var top = stack.pop(); |
+ if (top.name !== e.name || top.categoriesString !== e.categoriesString) |
+ console.error( |
+ 'B/E events mismatch at ' + top.startTime + ' (' + top.name + ') vs. ' + e.startTime + ' (' + e.name + |
+ ')'); |
+ else |
+ top._complete(e); |
+ break; |
+ case phases.Begin: |
+ stack.push(e); |
+ break; |
+ } |
+ } |
+ while (stack.length) |
+ stack.pop().setEndTime(this._model.maximumRecordTime()); |
+ this._events.remove(null, false); |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingManager.EventPayload} payload |
+ * @return {?WebInspector.TracingModel.Event} event |
+ */ |
+ _addEvent(payload) { |
+ var event = payload.ph === WebInspector.TracingModel.Phase.SnapshotObject ? |
+ WebInspector.TracingModel.ObjectSnapshot.fromPayload(payload, this) : |
+ WebInspector.TracingModel.Event.fromPayload(payload, this); |
+ if (WebInspector.TracingModel.isTopLevelEvent(event)) { |
+ // Discard nested "top-level" events. |
+ if (this._lastTopLevelEvent && this._lastTopLevelEvent.endTime > event.startTime) |
+ return null; |
+ this._lastTopLevelEvent = event; |
+ } |
+ this._events.push(event); |
+ return event; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.TracingModel.AsyncEvent} asyncEvent |
+ */ |
+ _addAsyncEvent(asyncEvent) { |
+ this._asyncEvents.push(asyncEvent); |
+ } |
+ |
+ /** |
+ * @override |
+ * @param {string} name |
+ */ |
+ _setName(name) { |
+ super._setName(name); |
+ this._process._setThreadByName(name, this); |
+ } |
+ |
+ /** |
+ * @return {number} |
+ */ |
+ id() { |
+ return this._id; |
+ } |
+ |
+ /** |
+ * @return {!WebInspector.TracingModel.Process} |
+ */ |
+ process() { |
+ return this._process; |
+ } |
+ |
+ /** |
+ * @return {!Array.<!WebInspector.TracingModel.Event>} |
+ */ |
+ events() { |
+ return this._events; |
+ } |
+ |
+ /** |
+ * @return {!Array.<!WebInspector.TracingModel.AsyncEvent>} |
+ */ |
+ asyncEvents() { |
+ return this._asyncEvents; |
+ } |
}; |