| function wrapCallFunctionForTimeline(f) |
| { |
| var script = document.createElement("script"); |
| script.textContent = "(" + f.toString() + ")()\n//# sourceURL=wrapCallFunctionForTimeline.js"; |
| document.body.appendChild(script); |
| } |
| |
| var initialize_Timeline = function() { |
| |
| InspectorTest.preloadPanel("timeline"); |
| Bindings.TempFile = InspectorTest.TempFileMock; |
| |
| // Scrub values when printing out these properties in the record or data field. |
| InspectorTest.timelinePropertyFormatters = { |
| children: "formatAsTypeName", |
| endTime: "formatAsTypeName", |
| requestId: "formatAsTypeName", |
| startTime: "formatAsTypeName", |
| stackTrace: "formatAsTypeName", |
| url: "formatAsURL", |
| scriptName: "formatAsTypeName", |
| scriptId: "formatAsTypeName", |
| usedHeapSizeDelta: "skip", |
| mimeType: "formatAsTypeName", |
| id: "formatAsTypeName", |
| timerId: "formatAsTypeName", |
| scriptLine: "formatAsTypeName", |
| layerId: "formatAsTypeName", |
| lineNumber: "formatAsTypeName", |
| columnNumber: "formatAsTypeName", |
| frameId: "formatAsTypeName", |
| frame: "formatAsTypeName", |
| page: "formatAsTypeName", |
| encodedDataLength: "formatAsTypeName", |
| identifier: "formatAsTypeName", |
| clip: "formatAsTypeName", |
| root: "formatAsTypeName", |
| backendNodeId: "formatAsTypeName", |
| nodeId: "formatAsTypeName", |
| rootNode: "formatAsTypeName", |
| finishTime: "formatAsTypeName", |
| thread: "formatAsTypeName", |
| allottedMilliseconds: "formatAsTypeName", |
| timedOut: "formatAsTypeName" |
| }; |
| |
| InspectorTest.InvalidationFormatters = { |
| _tracingEvent: "skip", |
| cause: "formatAsInvalidationCause", |
| frame: "skip", |
| invalidatedSelectorId: "skip", |
| invalidationList: "skip", |
| invalidationSet: "skip", |
| linkedRecalcStyleEvent: "skip", |
| linkedLayoutEvent: "skip", |
| nodeId: "skip", |
| paintId: "skip", |
| startTime: "skip", |
| }; |
| |
| InspectorTest.formatters.formatAsInvalidationCause = function(cause) |
| { |
| if (!cause) |
| return "<undefined>"; |
| var stackTrace; |
| if (cause.stackTrace && cause.stackTrace.length) |
| stackTrace = InspectorTest.formatters.formatAsURL(cause.stackTrace[0].url) + ":" + (cause.stackTrace[0].lineNumber + 1); |
| return "{reason: " + cause.reason + ", stackTrace: " + stackTrace + "}"; |
| } |
| |
| InspectorTest.preloadPanel("timeline"); |
| Bindings.TempFile = InspectorTest.TempFileMock; |
| |
| InspectorTest.createTracingModel = function() |
| { |
| return new SDK.TracingModel(new Bindings.TempFileBackingStorage("tracing")); |
| } |
| |
| InspectorTest.tracingModel = function() |
| { |
| return UI.panels.timeline._tracingModel; |
| } |
| |
| InspectorTest.invokeWithTracing = function(functionName, callback, additionalCategories, enableJSSampling) |
| { |
| var categories = "-*,disabled-by-default-devtools.timeline*,devtools.timeline," + SDK.TracingModel.TopLevelEventCategory; |
| if (additionalCategories) |
| categories += "," + additionalCategories; |
| var timelinePanel = UI.panels.timeline; |
| var timelineController = InspectorTest.timelineController(); |
| timelinePanel._timelineController = timelineController; |
| timelineController._startRecordingWithCategories(categories, enableJSSampling, tracingStarted); |
| |
| function tracingStarted() |
| { |
| InspectorTest.callFunctionInPageAsync(functionName).then(onPageActionsDone); |
| } |
| |
| function onPageActionsDone() |
| { |
| InspectorTest.addSniffer(UI.panels.timeline, "loadingComplete", callback) |
| timelineController.stopRecording(); |
| } |
| } |
| |
| InspectorTest.timelineModel = function() |
| { |
| return UI.panels.timeline._model; |
| } |
| |
| InspectorTest.timelineFrameModel = function() |
| { |
| return UI.panels.timeline._frameModel; |
| } |
| |
| InspectorTest.setTraceEvents = function(timelineModel, tracingModel, events) |
| { |
| tracingModel.reset(); |
| tracingModel.addEvents(events); |
| tracingModel.tracingComplete(); |
| timelineModel.setEvents(tracingModel); |
| } |
| |
| InspectorTest.createTimelineModelWithEvents = function(events) |
| { |
| var tracingModel = new SDK.TracingModel(new Bindings.TempFileBackingStorage("tracing")); |
| var timelineModel = new TimelineModel.TimelineModel(Timeline.TimelineUIUtils.visibleEventsFilter()); |
| InspectorTest.setTraceEvents(timelineModel, tracingModel, events); |
| return timelineModel; |
| } |
| |
| InspectorTest.timelineController = function() |
| { |
| var mainTarget = SDK.targetManager.mainTarget(); |
| var timelinePanel = UI.panels.timeline; |
| return new Timeline.TimelineController(mainTarget, timelinePanel, timelinePanel._tracingModel); |
| } |
| |
| InspectorTest.startTimeline = function(callback) |
| { |
| var panel = UI.panels.timeline; |
| InspectorTest.addSniffer(panel, "recordingStarted", callback); |
| panel._toggleRecording(); |
| }; |
| |
| InspectorTest.stopTimeline = function(callback) |
| { |
| var panel = UI.panels.timeline; |
| function didStop() |
| { |
| InspectorTest.deprecatedRunAfterPendingDispatches(callback); |
| } |
| InspectorTest.addSniffer(panel, "loadingComplete", didStop); |
| panel._toggleRecording(); |
| }; |
| |
| InspectorTest.evaluateWithTimeline = function(actions, doneCallback) |
| { |
| InspectorTest.startTimeline(step1); |
| function step1() |
| { |
| InspectorTest.evaluateInPage(actions, step2); |
| } |
| |
| function step2() |
| { |
| InspectorTest.stopTimeline(doneCallback); |
| } |
| } |
| |
| InspectorTest.invokeAsyncWithTimeline = function(functionName, doneCallback) |
| { |
| InspectorTest.startTimeline(step1); |
| function step1() |
| { |
| InspectorTest.callFunctionInPageAsync(functionName).then(step2); |
| } |
| |
| function step2() |
| { |
| InspectorTest.stopTimeline(InspectorTest.safeWrap(doneCallback)); |
| } |
| } |
| |
| InspectorTest.loadTimelineRecords = function(records) |
| { |
| var model = UI.panels.timeline._model; |
| model.reset(); |
| records.forEach(model._addRecord, model); |
| } |
| |
| InspectorTest.performActionsAndPrint = function(actions, typeName, includeTimeStamps) |
| { |
| function callback() |
| { |
| InspectorTest.printTimelineRecordsWithDetails(typeName); |
| if (includeTimeStamps) { |
| InspectorTest.addResult("Timestamp records: "); |
| InspectorTest.printTimestampRecords(typeName); |
| } |
| InspectorTest.completeTest(); |
| } |
| InspectorTest.evaluateWithTimeline(actions, callback); |
| }; |
| |
| InspectorTest.printTimelineRecords = function(typeName, formatter) |
| { |
| InspectorTest.timelineModel().forAllRecords(InspectorTest._printTimlineRecord.bind(InspectorTest, typeName, formatter)); |
| }; |
| |
| InspectorTest.detailsTextForTraceEvent = function(traceEvent) |
| { |
| return Timeline.TimelineUIUtils.buildDetailsTextForTraceEvent(traceEvent, |
| SDK.targetManager.mainTarget(), |
| new Components.Linkifier()); |
| } |
| |
| InspectorTest.printTimelineRecordsWithDetails = function(typeName) |
| { |
| function detailsFormatter(recordType, record) |
| { |
| if (recordType && recordType !== record.type()) |
| return; |
| var event = record.traceEvent(); |
| InspectorTest.addResult("Text details for " + record.type() + ": " + InspectorTest.detailsTextForTraceEvent(event)); |
| if (TimelineModel.TimelineData.forEvent(event).warning) |
| InspectorTest.addResult(record.type() + " has a warning"); |
| } |
| |
| InspectorTest.timelineModel().forAllRecords(InspectorTest._printTimlineRecord.bind(InspectorTest, typeName, detailsFormatter.bind(null, typeName))); |
| }; |
| |
| InspectorTest.walkTimelineEventTree = function(callback) |
| { |
| var model = InspectorTest.timelineModel(); |
| var view = new Timeline.EventsTimelineTreeView(model, UI.panels.timeline._filters, null); |
| var selection = Timeline.TimelineSelection.fromRange(model.minimumRecordTime(), model.maximumRecordTime()); |
| view.updateContents(selection); |
| InspectorTest.walkTimelineEventTreeUnderNode(callback, view._currentTree, 0); |
| } |
| |
| InspectorTest.walkTimelineEventTreeUnderNode = function(callback, root, level) |
| { |
| var event = root.event; |
| if (event) |
| callback(event, level) |
| var children = root.children ? root.children.values() : []; |
| for (var child of children) |
| InspectorTest.walkTimelineEventTreeUnderNode(callback, child, (level || 0) + 1); |
| } |
| |
| InspectorTest.printTimestampRecords = function(typeName, formatter) |
| { |
| InspectorTest.innerPrintTimelineRecords(InspectorTest.timelineModel().eventDividerRecords(), typeName, formatter); |
| }; |
| |
| InspectorTest.innerPrintTimelineRecords = function(records, typeName, formatter) |
| { |
| for (var i = 0; i < records.length; ++i) |
| InspectorTest._printTimlineRecord(typeName, formatter, records[i]); |
| }; |
| |
| InspectorTest._printTimlineRecord = function(typeName, formatter, record) |
| { |
| if (typeName && record.type() === typeName) |
| InspectorTest.printTimelineRecordProperties(record); |
| if (formatter) |
| formatter(record); |
| }; |
| |
| // Dump just the record name, indenting output on separate lines for subrecords |
| InspectorTest.dumpTimelineRecord = function(record, detailsCallback, level, filterTypes) |
| { |
| if (typeof level !== "number") |
| level = 0; |
| var message = ""; |
| for (var i = 0; i < level ; ++i) |
| message = "----" + message; |
| if (level > 0) |
| message = message + "> "; |
| if (record.type() === TimelineModel.TimelineModel.RecordType.TimeStamp |
| || record.type() === TimelineModel.TimelineModel.RecordType.ConsoleTime) { |
| message += Timeline.TimelineUIUtils.eventTitle(record.traceEvent()); |
| } else { |
| message += record.type(); |
| } |
| if (detailsCallback) |
| message += " " + detailsCallback(record); |
| InspectorTest.addResult(message); |
| |
| var children = record.children(); |
| var numChildren = children.length; |
| for (var i = 0; i < numChildren; ++i) { |
| if (filterTypes && filterTypes.indexOf(children[i].type()) == -1) |
| continue; |
| InspectorTest.dumpTimelineRecord(children[i], detailsCallback, level + 1, filterTypes); |
| } |
| } |
| |
| InspectorTest.dumpTimelineModelRecord = function(record, level) |
| { |
| if (typeof level !== "number") |
| level = 0; |
| var prefix = ""; |
| for (var i = 0; i < level ; ++i) |
| prefix = "----" + prefix; |
| if (level > 0) |
| prefix = prefix + "> "; |
| InspectorTest.addResult(prefix + record.type() + ": " + (Timeline.TimelineUIUtils.buildDetailsTextForTraceEvent(record.traceEvent(), null) || "")); |
| |
| var numChildren = record.children() ? record.children().length : 0; |
| for (var i = 0; i < numChildren; ++i) |
| InspectorTest.dumpTimelineModelRecord(record.children()[i], level + 1); |
| } |
| |
| InspectorTest.dumpTimelineRecords = function(timelineRecords) |
| { |
| for (var i = 0; i < timelineRecords.length; ++i) |
| InspectorTest.dumpTimelineRecord(timelineRecords[i], 0); |
| }; |
| |
| InspectorTest.printTimelineRecordProperties = function(record) |
| { |
| InspectorTest.printTraceEventProperties(record.traceEvent()); |
| } |
| |
| InspectorTest.printTraceEventPropertiesIfNameMatches = function(set, traceEvent) |
| { |
| if (set.has(traceEvent.name)) |
| InspectorTest.printTraceEventProperties(traceEvent); |
| } |
| |
| InspectorTest.printTraceEventProperties = function(traceEvent) |
| { |
| InspectorTest.addResult(traceEvent.name + " Properties:"); |
| var data = traceEvent.args["beginData"] || traceEvent.args["data"]; |
| var frameId = data && data["frame"]; |
| var object = { |
| data: traceEvent.args["data"] || traceEvent.args, |
| endTime: traceEvent.endTime || traceEvent.startTime, |
| frameId: frameId, |
| stackTrace: TimelineModel.TimelineData.forEvent(traceEvent).stackTrace, |
| startTime: traceEvent.startTime, |
| type: traceEvent.name, |
| }; |
| for (var field in object) { |
| if (object[field] === null || object[field] === undefined) |
| delete object[field]; |
| } |
| InspectorTest.addObject(object, InspectorTest.timelinePropertyFormatters); |
| }; |
| |
| InspectorTest.findFirstTimelineRecord = function(type) |
| { |
| return InspectorTest.findTimelineRecord(type, 0); |
| } |
| |
| // Find the (n+1)th timeline record of a specific type. |
| InspectorTest.findTimelineRecord = function(type, n) |
| { |
| var result; |
| function findByType(record) |
| { |
| if (record.type() !== type) |
| return false; |
| if (n === 0) { |
| result = record; |
| return true; |
| } |
| n--; |
| return false; |
| } |
| InspectorTest.timelineModel().forAllRecords(findByType); |
| return result; |
| } |
| |
| InspectorTest.FakeFileReader = function(input, delegate, callback) |
| { |
| this._delegate = delegate; |
| this._callback = callback; |
| this._input = input; |
| this._loadedSize = 0; |
| this._fileSize = input.length; |
| }; |
| |
| InspectorTest.dumpFrame = function(frame) |
| { |
| var fieldsToDump = ["cpuTime", "duration", "startTime", "endTime", "id", "mainThreadFrameId", "timeByCategory", "other", "scripting", "painting", "rendering", "committedFrom", "idle"]; |
| function formatFields(object) |
| { |
| var result = {}; |
| for (var key in object) { |
| if (fieldsToDump.indexOf(key) < 0) |
| continue; |
| var value = object[key]; |
| if (typeof value === "number") |
| value = Number(value.toFixed(7)); |
| else if (typeof value === "object" && value) |
| value = formatFields(value); |
| result[key] = value; |
| } |
| return result; |
| } |
| InspectorTest.addObject(formatFields(frame)); |
| } |
| |
| InspectorTest.dumpInvalidations = function(recordType, index, comment) |
| { |
| var record = InspectorTest.findTimelineRecord(recordType, index || 0); |
| InspectorTest.addArray(TimelineModel.InvalidationTracker.invalidationEventsFor(record._event), InspectorTest.InvalidationFormatters, "", comment); |
| } |
| |
| InspectorTest.FakeFileReader.prototype = { |
| start: function(output) |
| { |
| this._delegate.onTransferStarted(this); |
| |
| var length = this._input.length; |
| var half = (length + 1) >> 1; |
| |
| var chunk = this._input.substring(0, half); |
| this._loadedSize += chunk.length; |
| output.write(chunk); |
| this._delegate.onChunkTransferred(this); |
| |
| chunk = this._input.substring(half); |
| this._loadedSize += chunk.length; |
| output.write(chunk); |
| this._delegate.onChunkTransferred(this); |
| |
| output.close(); |
| this._delegate.onTransferFinished(this); |
| |
| this._callback(); |
| }, |
| |
| cancel: function() { }, |
| |
| loadedSize: function() |
| { |
| return this._loadedSize; |
| }, |
| |
| fileSize: function() |
| { |
| return this._fileSize; |
| }, |
| |
| fileName: function() |
| { |
| return "fakeFile"; |
| } |
| }; |
| |
| InspectorTest.loadTimeline = function(timelineData) |
| { |
| var timeline = UI.panels.timeline; |
| |
| function createFileReader(file, delegate) |
| { |
| return new InspectorTest.FakeFileReader(timelineData, delegate, timeline._saveToFile.bind(timeline)); |
| } |
| |
| InspectorTest.override(Timeline.TimelineLoader, "_createFileReader", createFileReader); |
| timeline._loadFromFile({}); |
| } |
| |
| }; |
| |
| function generateFrames(count) |
| { |
| var promise = Promise.resolve(); |
| for (let i = count; i > 0; --i) |
| promise = promise.then(changeBackgroundAndWaitForFrame.bind(null, i)); |
| return promise; |
| |
| function changeBackgroundAndWaitForFrame(i) |
| { |
| document.body.style.backgroundColor = i & 1 ? "rgb(200, 200, 200)" : "rgb(240, 240, 240)"; |
| return waitForFrame(); |
| } |
| } |
| |
| function waitForFrame() |
| { |
| var callback; |
| var promise = new Promise((fulfill) => callback = fulfill); |
| if (window.testRunner) |
| testRunner.capturePixelsAsyncThen(() => window.requestAnimationFrame(callback)); |
| else |
| window.requestAnimationFrame(callback); |
| return promise; |
| } |