| Index: third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
|
| diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
|
| index 451ce21a5e49668bdfd4236acb6c378f0aeeb402..e8d3c027785eea9eb82cf847009b1761e85ae610 100644
|
| --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
|
| +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineEventOverview.js
|
| @@ -27,801 +27,758 @@
|
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| */
|
| -
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.TimelineOverviewBase}
|
| - * @param {string} id
|
| - * @param {?string} title
|
| - * @param {!WebInspector.TimelineModel} model
|
| + * @unrestricted
|
| */
|
| -WebInspector.TimelineEventOverview = function(id, title, model)
|
| -{
|
| - WebInspector.TimelineOverviewBase.call(this);
|
| - this.element.id = "timeline-overview-" + id;
|
| - this.element.classList.add("overview-strip");
|
| +WebInspector.TimelineEventOverview = class extends WebInspector.TimelineOverviewBase {
|
| + /**
|
| + * @param {string} id
|
| + * @param {?string} title
|
| + * @param {!WebInspector.TimelineModel} model
|
| + */
|
| + constructor(id, title, model) {
|
| + super();
|
| + this.element.id = 'timeline-overview-' + id;
|
| + this.element.classList.add('overview-strip');
|
| if (title)
|
| - this.element.createChild("div", "timeline-overview-strip-title").textContent = title;
|
| + this.element.createChild('div', 'timeline-overview-strip-title').textContent = title;
|
| this._model = model;
|
| -};
|
| -
|
| -WebInspector.TimelineEventOverview.prototype = {
|
| - /**
|
| - * @param {number} begin
|
| - * @param {number} end
|
| - * @param {number} position
|
| - * @param {number} height
|
| - * @param {string} color
|
| - */
|
| - _renderBar: function(begin, end, position, height, color)
|
| - {
|
| - var x = begin;
|
| - var width = end - begin;
|
| - this._context.fillStyle = color;
|
| - this._context.fillRect(x, position, width, height);
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {number} windowLeft
|
| - * @param {number} windowRight
|
| - * @return {!{startTime: number, endTime: number}}
|
| - */
|
| - windowTimes: function(windowLeft, windowRight)
|
| - {
|
| - var absoluteMin = this._model.minimumRecordTime();
|
| - var timeSpan = this._model.maximumRecordTime() - absoluteMin;
|
| - return {
|
| - startTime: absoluteMin + timeSpan * windowLeft,
|
| - endTime: absoluteMin + timeSpan * windowRight
|
| - };
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {number} startTime
|
| - * @param {number} endTime
|
| - * @return {!{left: number, right: number}}
|
| - */
|
| - windowBoundaries: function(startTime, endTime)
|
| - {
|
| - var absoluteMin = this._model.minimumRecordTime();
|
| - var timeSpan = this._model.maximumRecordTime() - absoluteMin;
|
| - var haveRecords = absoluteMin > 0;
|
| - return {
|
| - left: haveRecords && startTime ? Math.min((startTime - absoluteMin) / timeSpan, 1) : 0,
|
| - right: haveRecords && endTime < Infinity ? (endTime - absoluteMin) / timeSpan : 1
|
| - };
|
| - },
|
| -
|
| - __proto__: WebInspector.TimelineOverviewBase.prototype
|
| + }
|
| +
|
| + /**
|
| + * @param {number} begin
|
| + * @param {number} end
|
| + * @param {number} position
|
| + * @param {number} height
|
| + * @param {string} color
|
| + */
|
| + _renderBar(begin, end, position, height, color) {
|
| + var x = begin;
|
| + var width = end - begin;
|
| + this._context.fillStyle = color;
|
| + this._context.fillRect(x, position, width, height);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {number} windowLeft
|
| + * @param {number} windowRight
|
| + * @return {!{startTime: number, endTime: number}}
|
| + */
|
| + windowTimes(windowLeft, windowRight) {
|
| + var absoluteMin = this._model.minimumRecordTime();
|
| + var timeSpan = this._model.maximumRecordTime() - absoluteMin;
|
| + return {startTime: absoluteMin + timeSpan * windowLeft, endTime: absoluteMin + timeSpan * windowRight};
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {number} startTime
|
| + * @param {number} endTime
|
| + * @return {!{left: number, right: number}}
|
| + */
|
| + windowBoundaries(startTime, endTime) {
|
| + var absoluteMin = this._model.minimumRecordTime();
|
| + var timeSpan = this._model.maximumRecordTime() - absoluteMin;
|
| + var haveRecords = absoluteMin > 0;
|
| + return {
|
| + left: haveRecords && startTime ? Math.min((startTime - absoluteMin) / timeSpan, 1) : 0,
|
| + right: haveRecords && endTime < Infinity ? (endTime - absoluteMin) / timeSpan : 1
|
| + };
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.TimelineEventOverview}
|
| - * @param {!WebInspector.TimelineModel} model
|
| + * @unrestricted
|
| */
|
| -WebInspector.TimelineEventOverview.Input = function(model)
|
| -{
|
| - WebInspector.TimelineEventOverview.call(this, "input", null, model);
|
| -};
|
| -
|
| -WebInspector.TimelineEventOverview.Input.prototype = {
|
| - /**
|
| - * @override
|
| - */
|
| - update: function()
|
| - {
|
| - WebInspector.TimelineEventOverview.prototype.update.call(this);
|
| - var events = this._model.mainThreadEvents();
|
| - var height = this._canvas.height;
|
| - var descriptors = WebInspector.TimelineUIUtils.eventDispatchDesciptors();
|
| - /** @type {!Map.<string,!WebInspector.TimelineUIUtils.EventDispatchTypeDescriptor>} */
|
| - var descriptorsByType = new Map();
|
| - var maxPriority = -1;
|
| - for (var descriptor of descriptors) {
|
| - for (var type of descriptor.eventTypes)
|
| - descriptorsByType.set(type, descriptor);
|
| - maxPriority = Math.max(maxPriority, descriptor.priority);
|
| - }
|
| -
|
| - var /** @const */ minWidth = 2 * window.devicePixelRatio;
|
| - var timeOffset = this._model.minimumRecordTime();
|
| - var timeSpan = this._model.maximumRecordTime() - timeOffset;
|
| - var canvasWidth = this._canvas.width;
|
| - var scale = canvasWidth / timeSpan;
|
| -
|
| - for (var priority = 0; priority <= maxPriority; ++priority) {
|
| - for (var i = 0; i < events.length; ++i) {
|
| - var event = events[i];
|
| - if (event.name !== WebInspector.TimelineModel.RecordType.EventDispatch)
|
| - continue;
|
| - var descriptor = descriptorsByType.get(event.args["data"]["type"]);
|
| - if (!descriptor || descriptor.priority !== priority)
|
| - continue;
|
| - var start = Number.constrain(Math.floor((event.startTime - timeOffset) * scale), 0, canvasWidth);
|
| - var end = Number.constrain(Math.ceil((event.endTime - timeOffset) * scale), 0, canvasWidth);
|
| - var width = Math.max(end - start, minWidth);
|
| - this._renderBar(start, start + width, 0, height, descriptor.color);
|
| - }
|
| - }
|
| - },
|
| +WebInspector.TimelineEventOverviewInput = class extends WebInspector.TimelineEventOverview {
|
| + /**
|
| + * @param {!WebInspector.TimelineModel} model
|
| + */
|
| + constructor(model) {
|
| + super('input', null, model);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + update() {
|
| + super.update();
|
| + var events = this._model.mainThreadEvents();
|
| + var height = this._canvas.height;
|
| + var descriptors = WebInspector.TimelineUIUtils.eventDispatchDesciptors();
|
| + /** @type {!Map.<string,!WebInspector.TimelineUIUtils.EventDispatchTypeDescriptor>} */
|
| + var descriptorsByType = new Map();
|
| + var maxPriority = -1;
|
| + for (var descriptor of descriptors) {
|
| + for (var type of descriptor.eventTypes)
|
| + descriptorsByType.set(type, descriptor);
|
| + maxPriority = Math.max(maxPriority, descriptor.priority);
|
| + }
|
|
|
| - __proto__: WebInspector.TimelineEventOverview.prototype
|
| + var /** @const */ minWidth = 2 * window.devicePixelRatio;
|
| + var timeOffset = this._model.minimumRecordTime();
|
| + var timeSpan = this._model.maximumRecordTime() - timeOffset;
|
| + var canvasWidth = this._canvas.width;
|
| + var scale = canvasWidth / timeSpan;
|
| +
|
| + for (var priority = 0; priority <= maxPriority; ++priority) {
|
| + for (var i = 0; i < events.length; ++i) {
|
| + var event = events[i];
|
| + if (event.name !== WebInspector.TimelineModel.RecordType.EventDispatch)
|
| + continue;
|
| + var descriptor = descriptorsByType.get(event.args['data']['type']);
|
| + if (!descriptor || descriptor.priority !== priority)
|
| + continue;
|
| + var start = Number.constrain(Math.floor((event.startTime - timeOffset) * scale), 0, canvasWidth);
|
| + var end = Number.constrain(Math.ceil((event.endTime - timeOffset) * scale), 0, canvasWidth);
|
| + var width = Math.max(end - start, minWidth);
|
| + this._renderBar(start, start + width, 0, height, descriptor.color);
|
| + }
|
| + }
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.TimelineEventOverview}
|
| - * @param {!WebInspector.TimelineModel} model
|
| + * @unrestricted
|
| */
|
| -WebInspector.TimelineEventOverview.Network = function(model)
|
| -{
|
| - WebInspector.TimelineEventOverview.call(this, "network", WebInspector.UIString("NET"), model);
|
| -};
|
| +WebInspector.TimelineEventOverviewNetwork = class extends WebInspector.TimelineEventOverview {
|
| + /**
|
| + * @param {!WebInspector.TimelineModel} model
|
| + */
|
| + constructor(model) {
|
| + super('network', WebInspector.UIString('NET'), model);
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + update() {
|
| + super.update();
|
| + var height = this._canvas.height;
|
| + var numBands = categoryBand(WebInspector.TimelineUIUtils.NetworkCategory.Other) + 1;
|
| + var bandHeight = Math.floor(height / numBands);
|
| + var devicePixelRatio = window.devicePixelRatio;
|
| + var timeOffset = this._model.minimumRecordTime();
|
| + var timeSpan = this._model.maximumRecordTime() - timeOffset;
|
| + var canvasWidth = this._canvas.width;
|
| + var scale = canvasWidth / timeSpan;
|
| + var ctx = this._context;
|
| + var requests = this._model.networkRequests();
|
| + /** @type {!Map<string,!{waiting:!Path2D,transfer:!Path2D}>} */
|
| + var paths = new Map();
|
| + requests.forEach(drawRequest);
|
| + for (var path of paths) {
|
| + ctx.fillStyle = path[0];
|
| + ctx.globalAlpha = 0.3;
|
| + ctx.fill(path[1]['waiting']);
|
| + ctx.globalAlpha = 1;
|
| + ctx.fill(path[1]['transfer']);
|
| + }
|
|
|
| -WebInspector.TimelineEventOverview.Network.prototype = {
|
| /**
|
| - * @override
|
| + * @param {!WebInspector.TimelineUIUtils.NetworkCategory} category
|
| + * @return {number}
|
| */
|
| - update: function()
|
| - {
|
| - WebInspector.TimelineEventOverview.prototype.update.call(this);
|
| - var height = this._canvas.height;
|
| - var numBands = categoryBand(WebInspector.TimelineUIUtils.NetworkCategory.Other) + 1;
|
| - var bandHeight = Math.floor(height / numBands);
|
| - var devicePixelRatio = window.devicePixelRatio;
|
| - var timeOffset = this._model.minimumRecordTime();
|
| - var timeSpan = this._model.maximumRecordTime() - timeOffset;
|
| - var canvasWidth = this._canvas.width;
|
| - var scale = canvasWidth / timeSpan;
|
| - var ctx = this._context;
|
| - var requests = this._model.networkRequests();
|
| - /** @type {!Map<string,!{waiting:!Path2D,transfer:!Path2D}>} */
|
| - var paths = new Map();
|
| - requests.forEach(drawRequest);
|
| - for (var path of paths) {
|
| - ctx.fillStyle = path[0];
|
| - ctx.globalAlpha = 0.3;
|
| - ctx.fill(path[1]["waiting"]);
|
| - ctx.globalAlpha = 1;
|
| - ctx.fill(path[1]["transfer"]);
|
| - }
|
| -
|
| - /**
|
| - * @param {!WebInspector.TimelineUIUtils.NetworkCategory} category
|
| - * @return {number}
|
| - */
|
| - function categoryBand(category)
|
| - {
|
| - var categories = WebInspector.TimelineUIUtils.NetworkCategory;
|
| - switch (category) {
|
| - case categories.HTML: return 0;
|
| - case categories.Script: return 1;
|
| - case categories.Style: return 2;
|
| - case categories.Media: return 3;
|
| - default: return 4;
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @param {!WebInspector.TimelineModel.NetworkRequest} request
|
| - */
|
| - function drawRequest(request)
|
| - {
|
| - var tickWidth = 2 * devicePixelRatio;
|
| - var category = WebInspector.TimelineUIUtils.networkRequestCategory(request);
|
| - var style = WebInspector.TimelineUIUtils.networkCategoryColor(category);
|
| - var band = categoryBand(category);
|
| - var y = band * bandHeight;
|
| - var path = paths.get(style);
|
| - if (!path) {
|
| - path = { waiting: new Path2D(), transfer: new Path2D() };
|
| - paths.set(style, path);
|
| - }
|
| - var s = Math.max(Math.floor((request.startTime - timeOffset) * scale), 0);
|
| - var e = Math.min(Math.ceil((request.endTime - timeOffset) * scale), canvasWidth);
|
| - path["waiting"].rect(s, y, e - s, bandHeight - 1);
|
| - path["transfer"].rect(e - tickWidth / 2, y, tickWidth, bandHeight - 1);
|
| - if (!request.responseTime)
|
| - return;
|
| - var r = Math.ceil((request.responseTime - timeOffset) * scale);
|
| - path["transfer"].rect(r - tickWidth / 2, y, tickWidth, bandHeight - 1);
|
| - }
|
| - },
|
| + function categoryBand(category) {
|
| + var categories = WebInspector.TimelineUIUtils.NetworkCategory;
|
| + switch (category) {
|
| + case categories.HTML:
|
| + return 0;
|
| + case categories.Script:
|
| + return 1;
|
| + case categories.Style:
|
| + return 2;
|
| + case categories.Media:
|
| + return 3;
|
| + default:
|
| + return 4;
|
| + }
|
| + }
|
|
|
| - __proto__: WebInspector.TimelineEventOverview.prototype
|
| + /**
|
| + * @param {!WebInspector.TimelineModel.NetworkRequest} request
|
| + */
|
| + function drawRequest(request) {
|
| + var tickWidth = 2 * devicePixelRatio;
|
| + var category = WebInspector.TimelineUIUtils.networkRequestCategory(request);
|
| + var style = WebInspector.TimelineUIUtils.networkCategoryColor(category);
|
| + var band = categoryBand(category);
|
| + var y = band * bandHeight;
|
| + var path = paths.get(style);
|
| + if (!path) {
|
| + path = {waiting: new Path2D(), transfer: new Path2D()};
|
| + paths.set(style, path);
|
| + }
|
| + var s = Math.max(Math.floor((request.startTime - timeOffset) * scale), 0);
|
| + var e = Math.min(Math.ceil((request.endTime - timeOffset) * scale), canvasWidth);
|
| + path['waiting'].rect(s, y, e - s, bandHeight - 1);
|
| + path['transfer'].rect(e - tickWidth / 2, y, tickWidth, bandHeight - 1);
|
| + if (!request.responseTime)
|
| + return;
|
| + var r = Math.ceil((request.responseTime - timeOffset) * scale);
|
| + path['transfer'].rect(r - tickWidth / 2, y, tickWidth, bandHeight - 1);
|
| + }
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.TimelineEventOverview}
|
| - * @param {!WebInspector.TimelineModel} model
|
| + * @unrestricted
|
| */
|
| -WebInspector.TimelineEventOverview.CPUActivity = function(model)
|
| -{
|
| - WebInspector.TimelineEventOverview.call(this, "cpu-activity", WebInspector.UIString("CPU"), model);
|
| - this._backgroundCanvas = this.element.createChild("canvas", "fill background");
|
| -};
|
| +WebInspector.TimelineEventOverviewCPUActivity = class extends WebInspector.TimelineEventOverview {
|
| + /**
|
| + * @param {!WebInspector.TimelineModel} model
|
| + */
|
| + constructor(model) {
|
| + super('cpu-activity', WebInspector.UIString('CPU'), model);
|
| + this._backgroundCanvas = this.element.createChild('canvas', 'fill background');
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + resetCanvas() {
|
| + super.resetCanvas();
|
| + this._backgroundCanvas.width = this.element.clientWidth * window.devicePixelRatio;
|
| + this._backgroundCanvas.height = this.element.clientHeight * window.devicePixelRatio;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + update() {
|
| + super.update();
|
| + var /** @const */ quantSizePx = 4 * window.devicePixelRatio;
|
| + var width = this._canvas.width;
|
| + var height = this._canvas.height;
|
| + var baseLine = height;
|
| + var timeOffset = this._model.minimumRecordTime();
|
| + var timeSpan = this._model.maximumRecordTime() - timeOffset;
|
| + var scale = width / timeSpan;
|
| + var quantTime = quantSizePx / scale;
|
| + var categories = WebInspector.TimelineUIUtils.categories();
|
| + var categoryOrder = ['idle', 'loading', 'painting', 'rendering', 'scripting', 'other'];
|
| + var otherIndex = categoryOrder.indexOf('other');
|
| + var idleIndex = 0;
|
| + console.assert(idleIndex === categoryOrder.indexOf('idle'));
|
| + for (var i = idleIndex + 1; i < categoryOrder.length; ++i)
|
| + categories[categoryOrder[i]]._overviewIndex = i;
|
| +
|
| + var backgroundContext = this._backgroundCanvas.getContext('2d');
|
| + for (var thread of this._model.virtualThreads())
|
| + drawThreadEvents(backgroundContext, thread.events);
|
| + applyPattern(backgroundContext);
|
| + drawThreadEvents(this._context, this._model.mainThreadEvents());
|
|
|
| -WebInspector.TimelineEventOverview.CPUActivity.prototype = {
|
| /**
|
| - * @override
|
| + * @param {!CanvasRenderingContext2D} ctx
|
| + * @param {!Array<!WebInspector.TracingModel.Event>} events
|
| */
|
| - resetCanvas: function()
|
| - {
|
| - WebInspector.TimelineEventOverview.prototype.resetCanvas.call(this);
|
| - this._backgroundCanvas.width = this.element.clientWidth * window.devicePixelRatio;
|
| - this._backgroundCanvas.height = this.element.clientHeight * window.devicePixelRatio;
|
| - },
|
| + function drawThreadEvents(ctx, events) {
|
| + var quantizer = new WebInspector.Quantizer(timeOffset, quantTime, drawSample);
|
| + var x = 0;
|
| + var categoryIndexStack = [];
|
| + var paths = [];
|
| + var lastY = [];
|
| + for (var i = 0; i < categoryOrder.length; ++i) {
|
| + paths[i] = new Path2D();
|
| + paths[i].moveTo(0, height);
|
| + lastY[i] = height;
|
| + }
|
| +
|
| + /**
|
| + * @param {!Array<number>} counters
|
| + */
|
| + function drawSample(counters) {
|
| + var y = baseLine;
|
| + for (var i = idleIndex + 1; i < categoryOrder.length; ++i) {
|
| + var h = (counters[i] || 0) / quantTime * height;
|
| + y -= h;
|
| + paths[i].bezierCurveTo(x, lastY[i], x, y, x + quantSizePx / 2, y);
|
| + lastY[i] = y;
|
| + }
|
| + x += quantSizePx;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.TracingModel.Event} e
|
| + */
|
| + function onEventStart(e) {
|
| + var index = categoryIndexStack.length ? categoryIndexStack.peekLast() : idleIndex;
|
| + quantizer.appendInterval(e.startTime, index);
|
| + categoryIndexStack.push(WebInspector.TimelineUIUtils.eventStyle(e).category._overviewIndex || otherIndex);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.TracingModel.Event} e
|
| + */
|
| + function onEventEnd(e) {
|
| + quantizer.appendInterval(e.endTime, categoryIndexStack.pop());
|
| + }
|
| +
|
| + WebInspector.TimelineModel.forEachEvent(events, onEventStart, onEventEnd);
|
| + quantizer.appendInterval(timeOffset + timeSpan + quantTime, idleIndex); // Kick drawing the last bucket.
|
| + for (var i = categoryOrder.length - 1; i > 0; --i) {
|
| + paths[i].lineTo(width, height);
|
| + ctx.fillStyle = categories[categoryOrder[i]].color;
|
| + ctx.fill(paths[i]);
|
| + }
|
| + }
|
|
|
| /**
|
| - * @override
|
| + * @param {!CanvasRenderingContext2D} ctx
|
| */
|
| - update: function()
|
| - {
|
| - WebInspector.TimelineEventOverview.prototype.update.call(this);
|
| - var /** @const */ quantSizePx = 4 * window.devicePixelRatio;
|
| - var width = this._canvas.width;
|
| - var height = this._canvas.height;
|
| - var baseLine = height;
|
| - var timeOffset = this._model.minimumRecordTime();
|
| - var timeSpan = this._model.maximumRecordTime() - timeOffset;
|
| - var scale = width / timeSpan;
|
| - var quantTime = quantSizePx / scale;
|
| - var categories = WebInspector.TimelineUIUtils.categories();
|
| - var categoryOrder = ["idle", "loading", "painting", "rendering", "scripting", "other"];
|
| - var otherIndex = categoryOrder.indexOf("other");
|
| - var idleIndex = 0;
|
| - console.assert(idleIndex === categoryOrder.indexOf("idle"));
|
| - for (var i = idleIndex + 1; i < categoryOrder.length; ++i)
|
| - categories[categoryOrder[i]]._overviewIndex = i;
|
| -
|
| - var backgroundContext = this._backgroundCanvas.getContext("2d");
|
| - for (var thread of this._model.virtualThreads())
|
| - drawThreadEvents(backgroundContext, thread.events);
|
| - applyPattern(backgroundContext);
|
| - drawThreadEvents(this._context, this._model.mainThreadEvents());
|
| -
|
| - /**
|
| - * @param {!CanvasRenderingContext2D} ctx
|
| - * @param {!Array<!WebInspector.TracingModel.Event>} events
|
| - */
|
| - function drawThreadEvents(ctx, events)
|
| - {
|
| - var quantizer = new WebInspector.Quantizer(timeOffset, quantTime, drawSample);
|
| - var x = 0;
|
| - var categoryIndexStack = [];
|
| - var paths = [];
|
| - var lastY = [];
|
| - for (var i = 0; i < categoryOrder.length; ++i) {
|
| - paths[i] = new Path2D();
|
| - paths[i].moveTo(0, height);
|
| - lastY[i] = height;
|
| - }
|
| -
|
| - /**
|
| - * @param {!Array<number>} counters
|
| - */
|
| - function drawSample(counters)
|
| - {
|
| - var y = baseLine;
|
| - for (var i = idleIndex + 1; i < categoryOrder.length; ++i) {
|
| - var h = (counters[i] || 0) / quantTime * height;
|
| - y -= h;
|
| - paths[i].bezierCurveTo(x, lastY[i], x, y, x + quantSizePx / 2, y);
|
| - lastY[i] = y;
|
| - }
|
| - x += quantSizePx;
|
| - }
|
| -
|
| - /**
|
| - * @param {!WebInspector.TracingModel.Event} e
|
| - */
|
| - function onEventStart(e)
|
| - {
|
| - var index = categoryIndexStack.length ? categoryIndexStack.peekLast() : idleIndex;
|
| - quantizer.appendInterval(e.startTime, index);
|
| - categoryIndexStack.push(WebInspector.TimelineUIUtils.eventStyle(e).category._overviewIndex || otherIndex);
|
| - }
|
| -
|
| - /**
|
| - * @param {!WebInspector.TracingModel.Event} e
|
| - */
|
| - function onEventEnd(e)
|
| - {
|
| - quantizer.appendInterval(e.endTime, categoryIndexStack.pop());
|
| - }
|
| -
|
| - WebInspector.TimelineModel.forEachEvent(events, onEventStart, onEventEnd);
|
| - quantizer.appendInterval(timeOffset + timeSpan + quantTime, idleIndex); // Kick drawing the last bucket.
|
| - for (var i = categoryOrder.length - 1; i > 0; --i) {
|
| - paths[i].lineTo(width, height);
|
| - ctx.fillStyle = categories[categoryOrder[i]].color;
|
| - ctx.fill(paths[i]);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @param {!CanvasRenderingContext2D} ctx
|
| - */
|
| - function applyPattern(ctx)
|
| - {
|
| - var step = 4 * window.devicePixelRatio;
|
| - ctx.save();
|
| - ctx.lineWidth = step / Math.sqrt(8);
|
| - for (var x = 0.5; x < width + height; x += step) {
|
| - ctx.moveTo(x, 0);
|
| - ctx.lineTo(x - height, height);
|
| - }
|
| - ctx.globalCompositeOperation = "destination-out";
|
| - ctx.stroke();
|
| - ctx.restore();
|
| - }
|
| - },
|
| -
|
| - __proto__: WebInspector.TimelineEventOverview.prototype
|
| + function applyPattern(ctx) {
|
| + var step = 4 * window.devicePixelRatio;
|
| + ctx.save();
|
| + ctx.lineWidth = step / Math.sqrt(8);
|
| + for (var x = 0.5; x < width + height; x += step) {
|
| + ctx.moveTo(x, 0);
|
| + ctx.lineTo(x - height, height);
|
| + }
|
| + ctx.globalCompositeOperation = 'destination-out';
|
| + ctx.stroke();
|
| + ctx.restore();
|
| + }
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.TimelineEventOverview}
|
| - * @param {!WebInspector.TimelineModel} model
|
| - * @param {!WebInspector.TimelineFrameModel} frameModel
|
| + * @unrestricted
|
| */
|
| -WebInspector.TimelineEventOverview.Responsiveness = function(model, frameModel)
|
| -{
|
| - WebInspector.TimelineEventOverview.call(this, "responsiveness", null, model);
|
| +WebInspector.TimelineEventOverviewResponsiveness = class extends WebInspector.TimelineEventOverview {
|
| + /**
|
| + * @param {!WebInspector.TimelineModel} model
|
| + * @param {!WebInspector.TimelineFrameModel} frameModel
|
| + */
|
| + constructor(model, frameModel) {
|
| + super('responsiveness', null, model);
|
| this._frameModel = frameModel;
|
| -};
|
| -
|
| -WebInspector.TimelineEventOverview.Responsiveness.prototype = {
|
| - /**
|
| - * @override
|
| - */
|
| - update: function()
|
| - {
|
| - WebInspector.TimelineEventOverview.prototype.update.call(this);
|
| - var height = this._canvas.height;
|
| - var timeOffset = this._model.minimumRecordTime();
|
| - var timeSpan = this._model.maximumRecordTime() - timeOffset;
|
| - var scale = this._canvas.width / timeSpan;
|
| - var frames = this._frameModel.frames();
|
| - var ctx = this._context;
|
| - var fillPath = new Path2D();
|
| - var markersPath = new Path2D();
|
| - for (var i = 0; i < frames.length; ++i) {
|
| - var frame = frames[i];
|
| - if (!frame.hasWarnings())
|
| - continue;
|
| - paintWarningDecoration(frame.startTime, frame.duration);
|
| - }
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + update() {
|
| + super.update();
|
| + var height = this._canvas.height;
|
| + var timeOffset = this._model.minimumRecordTime();
|
| + var timeSpan = this._model.maximumRecordTime() - timeOffset;
|
| + var scale = this._canvas.width / timeSpan;
|
| + var frames = this._frameModel.frames();
|
| + var ctx = this._context;
|
| + var fillPath = new Path2D();
|
| + var markersPath = new Path2D();
|
| + for (var i = 0; i < frames.length; ++i) {
|
| + var frame = frames[i];
|
| + if (!frame.hasWarnings())
|
| + continue;
|
| + paintWarningDecoration(frame.startTime, frame.duration);
|
| + }
|
|
|
| - var events = this._model.mainThreadEvents();
|
| - for (var i = 0; i < events.length; ++i) {
|
| - if (!events[i].warning)
|
| - continue;
|
| - paintWarningDecoration(events[i].startTime, events[i].duration);
|
| - }
|
| + var events = this._model.mainThreadEvents();
|
| + for (var i = 0; i < events.length; ++i) {
|
| + if (!events[i].warning)
|
| + continue;
|
| + paintWarningDecoration(events[i].startTime, events[i].duration);
|
| + }
|
|
|
| - ctx.fillStyle = "hsl(0, 80%, 90%)";
|
| - ctx.strokeStyle = "red";
|
| - ctx.lineWidth = 2 * window.devicePixelRatio;
|
| - ctx.fill(fillPath);
|
| - ctx.stroke(markersPath);
|
| -
|
| - /**
|
| - * @param {number} time
|
| - * @param {number} duration
|
| - */
|
| - function paintWarningDecoration(time, duration)
|
| - {
|
| - var x = Math.round(scale * (time - timeOffset));
|
| - var w = Math.round(scale * duration);
|
| - fillPath.rect(x, 0, w, height);
|
| - markersPath.moveTo(x + w, 0);
|
| - markersPath.lineTo(x + w, height);
|
| - }
|
| - },
|
| + ctx.fillStyle = 'hsl(0, 80%, 90%)';
|
| + ctx.strokeStyle = 'red';
|
| + ctx.lineWidth = 2 * window.devicePixelRatio;
|
| + ctx.fill(fillPath);
|
| + ctx.stroke(markersPath);
|
|
|
| - __proto__: WebInspector.TimelineEventOverview.prototype
|
| + /**
|
| + * @param {number} time
|
| + * @param {number} duration
|
| + */
|
| + function paintWarningDecoration(time, duration) {
|
| + var x = Math.round(scale * (time - timeOffset));
|
| + var w = Math.round(scale * duration);
|
| + fillPath.rect(x, 0, w, height);
|
| + markersPath.moveTo(x + w, 0);
|
| + markersPath.lineTo(x + w, height);
|
| + }
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.TimelineEventOverview}
|
| - * @param {!WebInspector.TimelineModel} model
|
| - * @param {!WebInspector.FilmStripModel} filmStripModel
|
| + * @unrestricted
|
| */
|
| -WebInspector.TimelineFilmStripOverview = function(model, filmStripModel)
|
| -{
|
| - WebInspector.TimelineEventOverview.call(this, "filmstrip", null, model);
|
| +WebInspector.TimelineFilmStripOverview = class extends WebInspector.TimelineEventOverview {
|
| + /**
|
| + * @param {!WebInspector.TimelineModel} model
|
| + * @param {!WebInspector.FilmStripModel} filmStripModel
|
| + */
|
| + constructor(model, filmStripModel) {
|
| + super('filmstrip', null, model);
|
| this._filmStripModel = filmStripModel;
|
| this.reset();
|
| -};
|
| -
|
| -WebInspector.TimelineFilmStripOverview.Padding = 2;
|
| -
|
| -WebInspector.TimelineFilmStripOverview.prototype = {
|
| - /**
|
| - * @override
|
| - */
|
| - update: function()
|
| - {
|
| - WebInspector.TimelineEventOverview.prototype.update.call(this);
|
| - var frames = this._filmStripModel.frames();
|
| - if (!frames.length)
|
| - return;
|
| -
|
| - var drawGeneration = Symbol("drawGeneration");
|
| - this._drawGeneration = drawGeneration;
|
| - this._imageByFrame(frames[0]).then(image => {
|
| - if (this._drawGeneration !== drawGeneration)
|
| - return;
|
| - if (!image.naturalWidth || !image.naturalHeight)
|
| - return;
|
| - var imageHeight = this._canvas.height - 2 * WebInspector.TimelineFilmStripOverview.Padding;
|
| - var imageWidth = Math.ceil(imageHeight * image.naturalWidth / image.naturalHeight);
|
| - var popoverScale = Math.min(200 / image.naturalWidth, 1);
|
| - this._emptyImage = new Image(image.naturalWidth * popoverScale, image.naturalHeight * popoverScale);
|
| - this._drawFrames(imageWidth, imageHeight);
|
| - });
|
| - },
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + update() {
|
| + super.update();
|
| + var frames = this._filmStripModel.frames();
|
| + if (!frames.length)
|
| + return;
|
| +
|
| + var drawGeneration = Symbol('drawGeneration');
|
| + this._drawGeneration = drawGeneration;
|
| + this._imageByFrame(frames[0]).then(image => {
|
| + if (this._drawGeneration !== drawGeneration)
|
| + return;
|
| + if (!image.naturalWidth || !image.naturalHeight)
|
| + return;
|
| + var imageHeight = this._canvas.height - 2 * WebInspector.TimelineFilmStripOverview.Padding;
|
| + var imageWidth = Math.ceil(imageHeight * image.naturalWidth / image.naturalHeight);
|
| + var popoverScale = Math.min(200 / image.naturalWidth, 1);
|
| + this._emptyImage = new Image(image.naturalWidth * popoverScale, image.naturalHeight * popoverScale);
|
| + this._drawFrames(imageWidth, imageHeight);
|
| + });
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.FilmStripModel.Frame} frame
|
| + * @return {!Promise<!HTMLImageElement>}
|
| + */
|
| + _imageByFrame(frame) {
|
| + var imagePromise = this._frameToImagePromise.get(frame);
|
| + if (!imagePromise) {
|
| + imagePromise = frame.imageDataPromise().then(createImage);
|
| + this._frameToImagePromise.set(frame, imagePromise);
|
| + }
|
| + return imagePromise;
|
|
|
| /**
|
| - * @param {!WebInspector.FilmStripModel.Frame} frame
|
| + * @param {?string} data
|
| * @return {!Promise<!HTMLImageElement>}
|
| */
|
| - _imageByFrame: function(frame)
|
| - {
|
| - var imagePromise = this._frameToImagePromise.get(frame);
|
| - if (!imagePromise) {
|
| - imagePromise = frame.imageDataPromise().then(createImage);
|
| - this._frameToImagePromise.set(frame, imagePromise);
|
| - }
|
| - return imagePromise;
|
| -
|
| - /**
|
| - * @param {?string} data
|
| - * @return {!Promise<!HTMLImageElement>}
|
| - */
|
| - function createImage(data)
|
| - {
|
| - var fulfill;
|
| - var promise = new Promise(f => fulfill = f);
|
| -
|
| - var image = /** @type {!HTMLImageElement} */ (createElement("img"));
|
| - if (data)
|
| - image.src = "data:image/jpg;base64," + data;
|
| - if (image.complete) {
|
| - fulfill(image);
|
| - } else {
|
| - image.addEventListener("load", () => fulfill(image));
|
| - image.addEventListener("error", () => fulfill(image));
|
| - }
|
| - return promise;
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * @param {number} imageWidth
|
| - * @param {number} imageHeight
|
| - */
|
| - _drawFrames: function(imageWidth, imageHeight)
|
| - {
|
| - if (!imageWidth)
|
| - return;
|
| - if (!this._filmStripModel.frames().length)
|
| - return;
|
| - var padding = WebInspector.TimelineFilmStripOverview.Padding;
|
| - var width = this._canvas.width;
|
| - var zeroTime = this._filmStripModel.zeroTime();
|
| - var spanTime = this._filmStripModel.spanTime();
|
| - var scale = spanTime / width;
|
| - var context = this._canvas.getContext("2d");
|
| - var drawGeneration = this._drawGeneration;
|
| -
|
| - context.beginPath();
|
| - for (var x = padding; x < width; x += imageWidth + 2 * padding) {
|
| - var time = zeroTime + (x + imageWidth / 2) * scale;
|
| - var frame = this._filmStripModel.frameByTimestamp(time);
|
| - if (!frame)
|
| - continue;
|
| - context.rect(x - 0.5, 0.5, imageWidth + 1, imageHeight + 1);
|
| - this._imageByFrame(frame).then(drawFrameImage.bind(this, x));
|
| - }
|
| - context.strokeStyle = "#ddd";
|
| - context.stroke();
|
| -
|
| - /**
|
| - * @param {number} x
|
| - * @param {!HTMLImageElement} image
|
| - * @this {WebInspector.TimelineFilmStripOverview}
|
| - */
|
| - function drawFrameImage(x, image)
|
| - {
|
| - // Ignore draws deferred from a previous update call.
|
| - if (this._drawGeneration !== drawGeneration)
|
| - return;
|
| - context.drawImage(image, x, 1, imageWidth, imageHeight);
|
| - }
|
| - },
|
| + function createImage(data) {
|
| + var fulfill;
|
| + var promise = new Promise(f => fulfill = f);
|
| +
|
| + var image = /** @type {!HTMLImageElement} */ (createElement('img'));
|
| + if (data)
|
| + image.src = 'data:image/jpg;base64,' + data;
|
| + if (image.complete) {
|
| + fulfill(image);
|
| + } else {
|
| + image.addEventListener('load', () => fulfill(image));
|
| + image.addEventListener('error', () => fulfill(image));
|
| + }
|
| + return promise;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @param {number} imageWidth
|
| + * @param {number} imageHeight
|
| + */
|
| + _drawFrames(imageWidth, imageHeight) {
|
| + if (!imageWidth)
|
| + return;
|
| + if (!this._filmStripModel.frames().length)
|
| + return;
|
| + var padding = WebInspector.TimelineFilmStripOverview.Padding;
|
| + var width = this._canvas.width;
|
| + var zeroTime = this._filmStripModel.zeroTime();
|
| + var spanTime = this._filmStripModel.spanTime();
|
| + var scale = spanTime / width;
|
| + var context = this._canvas.getContext('2d');
|
| + var drawGeneration = this._drawGeneration;
|
| +
|
| + context.beginPath();
|
| + for (var x = padding; x < width; x += imageWidth + 2 * padding) {
|
| + var time = zeroTime + (x + imageWidth / 2) * scale;
|
| + var frame = this._filmStripModel.frameByTimestamp(time);
|
| + if (!frame)
|
| + continue;
|
| + context.rect(x - 0.5, 0.5, imageWidth + 1, imageHeight + 1);
|
| + this._imageByFrame(frame).then(drawFrameImage.bind(this, x));
|
| + }
|
| + context.strokeStyle = '#ddd';
|
| + context.stroke();
|
|
|
| /**
|
| - * @override
|
| * @param {number} x
|
| - * @return {!Promise<?Element>}
|
| + * @param {!HTMLImageElement} image
|
| + * @this {WebInspector.TimelineFilmStripOverview}
|
| */
|
| - popoverElementPromise: function(x)
|
| - {
|
| - if (!this._filmStripModel.frames().length)
|
| - return Promise.resolve(/** @type {?Element} */ (null));
|
| -
|
| - var time = this._calculator.positionToTime(x);
|
| - var frame = this._filmStripModel.frameByTimestamp(time);
|
| - if (frame === this._lastFrame)
|
| - return Promise.resolve(this._lastElement);
|
| - var imagePromise = frame ? this._imageByFrame(frame) : Promise.resolve(this._emptyImage);
|
| - return imagePromise.then(createFrameElement.bind(this));
|
| -
|
| - /**
|
| - * @this {WebInspector.TimelineFilmStripOverview}
|
| - * @param {!HTMLImageElement} image
|
| - * @return {?Element}
|
| - */
|
| - function createFrameElement(image)
|
| - {
|
| - var element = createElementWithClass("div", "frame");
|
| - element.createChild("div", "thumbnail").appendChild(image);
|
| - WebInspector.appendStyle(element, "timeline/timelinePanel.css");
|
| - this._lastFrame = frame;
|
| - this._lastElement = element;
|
| - return element;
|
| - }
|
| - },
|
| + function drawFrameImage(x, image) {
|
| + // Ignore draws deferred from a previous update call.
|
| + if (this._drawGeneration !== drawGeneration)
|
| + return;
|
| + context.drawImage(image, x, 1, imageWidth, imageHeight);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {number} x
|
| + * @return {!Promise<?Element>}
|
| + */
|
| + popoverElementPromise(x) {
|
| + if (!this._filmStripModel.frames().length)
|
| + return Promise.resolve(/** @type {?Element} */ (null));
|
| +
|
| + var time = this._calculator.positionToTime(x);
|
| + var frame = this._filmStripModel.frameByTimestamp(time);
|
| + if (frame === this._lastFrame)
|
| + return Promise.resolve(this._lastElement);
|
| + var imagePromise = frame ? this._imageByFrame(frame) : Promise.resolve(this._emptyImage);
|
| + return imagePromise.then(createFrameElement.bind(this));
|
|
|
| /**
|
| - * @override
|
| + * @this {WebInspector.TimelineFilmStripOverview}
|
| + * @param {!HTMLImageElement} image
|
| + * @return {?Element}
|
| */
|
| - reset: function()
|
| - {
|
| - this._lastFrame = undefined;
|
| - this._lastElement = null;
|
| - /** @type {!Map<!WebInspector.FilmStripModel.Frame,!Promise<!HTMLImageElement>>} */
|
| - this._frameToImagePromise = new Map();
|
| - this._imageWidth = 0;
|
| - },
|
| -
|
| - __proto__: WebInspector.TimelineEventOverview.prototype
|
| + function createFrameElement(image) {
|
| + var element = createElementWithClass('div', 'frame');
|
| + element.createChild('div', 'thumbnail').appendChild(image);
|
| + WebInspector.appendStyle(element, 'timeline/timelinePanel.css');
|
| + this._lastFrame = frame;
|
| + this._lastElement = element;
|
| + return element;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + reset() {
|
| + this._lastFrame = undefined;
|
| + this._lastElement = null;
|
| + /** @type {!Map<!WebInspector.FilmStripModel.Frame,!Promise<!HTMLImageElement>>} */
|
| + this._frameToImagePromise = new Map();
|
| + this._imageWidth = 0;
|
| + }
|
| };
|
|
|
| +WebInspector.TimelineFilmStripOverview.Padding = 2;
|
| +
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.TimelineEventOverview}
|
| - * @param {!WebInspector.TimelineModel} model
|
| - * @param {!WebInspector.TimelineFrameModel} frameModel
|
| + * @unrestricted
|
| */
|
| -WebInspector.TimelineEventOverview.Frames = function(model, frameModel)
|
| -{
|
| - WebInspector.TimelineEventOverview.call(this, "framerate", WebInspector.UIString("FPS"), model);
|
| +WebInspector.TimelineEventOverviewFrames = class extends WebInspector.TimelineEventOverview {
|
| + /**
|
| + * @param {!WebInspector.TimelineModel} model
|
| + * @param {!WebInspector.TimelineFrameModel} frameModel
|
| + */
|
| + constructor(model, frameModel) {
|
| + super('framerate', WebInspector.UIString('FPS'), model);
|
| this._frameModel = frameModel;
|
| -};
|
| -
|
| -WebInspector.TimelineEventOverview.Frames.prototype = {
|
| - /**
|
| - * @override
|
| - */
|
| - update: function()
|
| - {
|
| - WebInspector.TimelineEventOverview.prototype.update.call(this);
|
| - var height = this._canvas.height;
|
| - var /** @const */ padding = 1 * window.devicePixelRatio;
|
| - var /** @const */ baseFrameDurationMs = 1e3 / 60;
|
| - var visualHeight = height - 2 * padding;
|
| - var timeOffset = this._model.minimumRecordTime();
|
| - var timeSpan = this._model.maximumRecordTime() - timeOffset;
|
| - var scale = this._canvas.width / timeSpan;
|
| - var frames = this._frameModel.frames();
|
| - var baseY = height - padding;
|
| - var ctx = this._context;
|
| - var bottomY = baseY + 10 * window.devicePixelRatio;
|
| - var y = bottomY;
|
| - if (!frames.length)
|
| - return;
|
| -
|
| - var lineWidth = window.devicePixelRatio;
|
| - var offset = lineWidth & 1 ? 0.5 : 0;
|
| - var tickDepth = 1.5 * window.devicePixelRatio;
|
| - ctx.beginPath();
|
| - ctx.moveTo(0, y);
|
| - for (var i = 0; i < frames.length; ++i) {
|
| - var frame = frames[i];
|
| - var x = Math.round((frame.startTime - timeOffset) * scale) + offset;
|
| - ctx.lineTo(x, y);
|
| - ctx.lineTo(x, y + tickDepth);
|
| - y = frame.idle ? bottomY : Math.round(baseY - visualHeight * Math.min(baseFrameDurationMs / frame.duration, 1)) - offset;
|
| - ctx.lineTo(x, y + tickDepth);
|
| - ctx.lineTo(x, y);
|
| - }
|
| - if (frames.length) {
|
| - var lastFrame = frames.peekLast();
|
| - var x = Math.round((lastFrame.startTime + lastFrame.duration - timeOffset) * scale) + offset;
|
| - ctx.lineTo(x, y);
|
| - }
|
| - ctx.lineTo(x, bottomY);
|
| - ctx.fillStyle = "hsl(110, 50%, 88%)";
|
| - ctx.strokeStyle = "hsl(110, 50%, 60%)";
|
| - ctx.lineWidth = lineWidth;
|
| - ctx.fill();
|
| - ctx.stroke();
|
| - },
|
| -
|
| - __proto__: WebInspector.TimelineEventOverview.prototype
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + update() {
|
| + super.update();
|
| + var height = this._canvas.height;
|
| + var /** @const */ padding = 1 * window.devicePixelRatio;
|
| + var /** @const */ baseFrameDurationMs = 1e3 / 60;
|
| + var visualHeight = height - 2 * padding;
|
| + var timeOffset = this._model.minimumRecordTime();
|
| + var timeSpan = this._model.maximumRecordTime() - timeOffset;
|
| + var scale = this._canvas.width / timeSpan;
|
| + var frames = this._frameModel.frames();
|
| + var baseY = height - padding;
|
| + var ctx = this._context;
|
| + var bottomY = baseY + 10 * window.devicePixelRatio;
|
| + var y = bottomY;
|
| + if (!frames.length)
|
| + return;
|
| +
|
| + var lineWidth = window.devicePixelRatio;
|
| + var offset = lineWidth & 1 ? 0.5 : 0;
|
| + var tickDepth = 1.5 * window.devicePixelRatio;
|
| + ctx.beginPath();
|
| + ctx.moveTo(0, y);
|
| + for (var i = 0; i < frames.length; ++i) {
|
| + var frame = frames[i];
|
| + var x = Math.round((frame.startTime - timeOffset) * scale) + offset;
|
| + ctx.lineTo(x, y);
|
| + ctx.lineTo(x, y + tickDepth);
|
| + y = frame.idle ? bottomY :
|
| + Math.round(baseY - visualHeight * Math.min(baseFrameDurationMs / frame.duration, 1)) - offset;
|
| + ctx.lineTo(x, y + tickDepth);
|
| + ctx.lineTo(x, y);
|
| + }
|
| + if (frames.length) {
|
| + var lastFrame = frames.peekLast();
|
| + var x = Math.round((lastFrame.startTime + lastFrame.duration - timeOffset) * scale) + offset;
|
| + ctx.lineTo(x, y);
|
| + }
|
| + ctx.lineTo(x, bottomY);
|
| + ctx.fillStyle = 'hsl(110, 50%, 88%)';
|
| + ctx.strokeStyle = 'hsl(110, 50%, 60%)';
|
| + ctx.lineWidth = lineWidth;
|
| + ctx.fill();
|
| + ctx.stroke();
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {WebInspector.TimelineEventOverview}
|
| - * @param {!WebInspector.TimelineModel} model
|
| + * @unrestricted
|
| */
|
| -WebInspector.TimelineEventOverview.Memory = function(model)
|
| -{
|
| - WebInspector.TimelineEventOverview.call(this, "memory", WebInspector.UIString("HEAP"), model);
|
| - this._heapSizeLabel = this.element.createChild("div", "memory-graph-label");
|
| -};
|
| -
|
| -WebInspector.TimelineEventOverview.Memory.prototype = {
|
| - resetHeapSizeLabels: function()
|
| - {
|
| - this._heapSizeLabel.textContent = "";
|
| - },
|
| +WebInspector.TimelineEventOverviewMemory = class extends WebInspector.TimelineEventOverview {
|
| + /**
|
| + * @param {!WebInspector.TimelineModel} model
|
| + */
|
| + constructor(model) {
|
| + super('memory', WebInspector.UIString('HEAP'), model);
|
| + this._heapSizeLabel = this.element.createChild('div', 'memory-graph-label');
|
| + }
|
| +
|
| + resetHeapSizeLabels() {
|
| + this._heapSizeLabel.textContent = '';
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + update() {
|
| + super.update();
|
| + var ratio = window.devicePixelRatio;
|
| +
|
| + var events = this._model.mainThreadEvents();
|
| + if (!events.length) {
|
| + this.resetHeapSizeLabels();
|
| + return;
|
| + }
|
|
|
| + var lowerOffset = 3 * ratio;
|
| + var maxUsedHeapSize = 0;
|
| + var minUsedHeapSize = 100000000000;
|
| + var minTime = this._model.minimumRecordTime();
|
| + var maxTime = this._model.maximumRecordTime();
|
| /**
|
| - * @override
|
| + * @param {!WebInspector.TracingModel.Event} event
|
| + * @return {boolean}
|
| */
|
| - update: function()
|
| - {
|
| - WebInspector.TimelineEventOverview.prototype.update.call(this);
|
| - var ratio = window.devicePixelRatio;
|
| -
|
| - var events = this._model.mainThreadEvents();
|
| - if (!events.length) {
|
| - this.resetHeapSizeLabels();
|
| - return;
|
| - }
|
| -
|
| - var lowerOffset = 3 * ratio;
|
| - var maxUsedHeapSize = 0;
|
| - var minUsedHeapSize = 100000000000;
|
| - var minTime = this._model.minimumRecordTime();
|
| - var maxTime = this._model.maximumRecordTime();
|
| - /**
|
| - * @param {!WebInspector.TracingModel.Event} event
|
| - * @return {boolean}
|
| - */
|
| - function isUpdateCountersEvent(event)
|
| - {
|
| - return event.name === WebInspector.TimelineModel.RecordType.UpdateCounters;
|
| - }
|
| - events = events.filter(isUpdateCountersEvent);
|
| - /**
|
| - * @param {!WebInspector.TracingModel.Event} event
|
| - */
|
| - function calculateMinMaxSizes(event)
|
| - {
|
| - var counters = event.args.data;
|
| - if (!counters || !counters.jsHeapSizeUsed)
|
| - return;
|
| - maxUsedHeapSize = Math.max(maxUsedHeapSize, counters.jsHeapSizeUsed);
|
| - minUsedHeapSize = Math.min(minUsedHeapSize, counters.jsHeapSizeUsed);
|
| - }
|
| - events.forEach(calculateMinMaxSizes);
|
| - minUsedHeapSize = Math.min(minUsedHeapSize, maxUsedHeapSize);
|
| -
|
| - var lineWidth = 1;
|
| - var width = this._canvas.width;
|
| - var height = this._canvas.height - lowerOffset;
|
| - var xFactor = width / (maxTime - minTime);
|
| - var yFactor = (height - lineWidth) / Math.max(maxUsedHeapSize - minUsedHeapSize, 1);
|
| -
|
| - var histogram = new Array(width);
|
| -
|
| - /**
|
| - * @param {!WebInspector.TracingModel.Event} event
|
| - */
|
| - function buildHistogram(event)
|
| - {
|
| - var counters = event.args.data;
|
| - if (!counters || !counters.jsHeapSizeUsed)
|
| - return;
|
| - var x = Math.round((event.startTime - minTime) * xFactor);
|
| - var y = Math.round((counters.jsHeapSizeUsed - minUsedHeapSize) * yFactor);
|
| - histogram[x] = Math.max(histogram[x] || 0, y);
|
| - }
|
| - events.forEach(buildHistogram);
|
| -
|
| - var ctx = this._context;
|
| - var heightBeyondView = height + lowerOffset + lineWidth;
|
| -
|
| - ctx.translate(0.5, 0.5);
|
| - ctx.beginPath();
|
| - ctx.moveTo(-lineWidth, heightBeyondView);
|
| - var y = 0;
|
| - var isFirstPoint = true;
|
| - var lastX = 0;
|
| - for (var x = 0; x < histogram.length; x++) {
|
| - if (typeof histogram[x] === "undefined")
|
| - continue;
|
| - if (isFirstPoint) {
|
| - isFirstPoint = false;
|
| - y = histogram[x];
|
| - ctx.lineTo(-lineWidth, height - y);
|
| - }
|
| - var nextY = histogram[x];
|
| - if (Math.abs(nextY - y) > 2 && Math.abs(x - lastX) > 1)
|
| - ctx.lineTo(x, height - y);
|
| - y = nextY;
|
| - ctx.lineTo(x, height - y);
|
| - lastX = x;
|
| - }
|
| - ctx.lineTo(width + lineWidth, height - y);
|
| - ctx.lineTo(width + lineWidth, heightBeyondView);
|
| - ctx.closePath();
|
| + function isUpdateCountersEvent(event) {
|
| + return event.name === WebInspector.TimelineModel.RecordType.UpdateCounters;
|
| + }
|
| + events = events.filter(isUpdateCountersEvent);
|
| + /**
|
| + * @param {!WebInspector.TracingModel.Event} event
|
| + */
|
| + function calculateMinMaxSizes(event) {
|
| + var counters = event.args.data;
|
| + if (!counters || !counters.jsHeapSizeUsed)
|
| + return;
|
| + maxUsedHeapSize = Math.max(maxUsedHeapSize, counters.jsHeapSizeUsed);
|
| + minUsedHeapSize = Math.min(minUsedHeapSize, counters.jsHeapSizeUsed);
|
| + }
|
| + events.forEach(calculateMinMaxSizes);
|
| + minUsedHeapSize = Math.min(minUsedHeapSize, maxUsedHeapSize);
|
|
|
| - ctx.fillStyle = "hsla(220, 90%, 70%, 0.2)";
|
| - ctx.fill();
|
| - ctx.lineWidth = lineWidth;
|
| - ctx.strokeStyle = "hsl(220, 90%, 70%)";
|
| - ctx.stroke();
|
| + var lineWidth = 1;
|
| + var width = this._canvas.width;
|
| + var height = this._canvas.height - lowerOffset;
|
| + var xFactor = width / (maxTime - minTime);
|
| + var yFactor = (height - lineWidth) / Math.max(maxUsedHeapSize - minUsedHeapSize, 1);
|
|
|
| - this._heapSizeLabel.textContent = WebInspector.UIString("%s \u2013 %s", Number.bytesToString(minUsedHeapSize), Number.bytesToString(maxUsedHeapSize));
|
| - },
|
| + var histogram = new Array(width);
|
|
|
| - __proto__: WebInspector.TimelineEventOverview.prototype
|
| + /**
|
| + * @param {!WebInspector.TracingModel.Event} event
|
| + */
|
| + function buildHistogram(event) {
|
| + var counters = event.args.data;
|
| + if (!counters || !counters.jsHeapSizeUsed)
|
| + return;
|
| + var x = Math.round((event.startTime - minTime) * xFactor);
|
| + var y = Math.round((counters.jsHeapSizeUsed - minUsedHeapSize) * yFactor);
|
| + histogram[x] = Math.max(histogram[x] || 0, y);
|
| + }
|
| + events.forEach(buildHistogram);
|
| +
|
| + var ctx = this._context;
|
| + var heightBeyondView = height + lowerOffset + lineWidth;
|
| +
|
| + ctx.translate(0.5, 0.5);
|
| + ctx.beginPath();
|
| + ctx.moveTo(-lineWidth, heightBeyondView);
|
| + var y = 0;
|
| + var isFirstPoint = true;
|
| + var lastX = 0;
|
| + for (var x = 0; x < histogram.length; x++) {
|
| + if (typeof histogram[x] === 'undefined')
|
| + continue;
|
| + if (isFirstPoint) {
|
| + isFirstPoint = false;
|
| + y = histogram[x];
|
| + ctx.lineTo(-lineWidth, height - y);
|
| + }
|
| + var nextY = histogram[x];
|
| + if (Math.abs(nextY - y) > 2 && Math.abs(x - lastX) > 1)
|
| + ctx.lineTo(x, height - y);
|
| + y = nextY;
|
| + ctx.lineTo(x, height - y);
|
| + lastX = x;
|
| + }
|
| + ctx.lineTo(width + lineWidth, height - y);
|
| + ctx.lineTo(width + lineWidth, heightBeyondView);
|
| + ctx.closePath();
|
| +
|
| + ctx.fillStyle = 'hsla(220, 90%, 70%, 0.2)';
|
| + ctx.fill();
|
| + ctx.lineWidth = lineWidth;
|
| + ctx.strokeStyle = 'hsl(220, 90%, 70%)';
|
| + ctx.stroke();
|
| +
|
| + this._heapSizeLabel.textContent = WebInspector.UIString(
|
| + '%s \u2013 %s', Number.bytesToString(minUsedHeapSize), Number.bytesToString(maxUsedHeapSize));
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @param {number} startTime
|
| - * @param {number} quantDuration
|
| - * @param {function(!Array<number>)} callback
|
| + * @unrestricted
|
| */
|
| -WebInspector.Quantizer = function(startTime, quantDuration, callback)
|
| -{
|
| +WebInspector.Quantizer = class {
|
| + /**
|
| + * @param {number} startTime
|
| + * @param {number} quantDuration
|
| + * @param {function(!Array<number>)} callback
|
| + */
|
| + constructor(startTime, quantDuration, callback) {
|
| this._lastTime = startTime;
|
| this._quantDuration = quantDuration;
|
| this._callback = callback;
|
| this._counters = [];
|
| this._remainder = quantDuration;
|
| -};
|
| -
|
| -WebInspector.Quantizer.prototype = {
|
| - /**
|
| - * @param {number} time
|
| - * @param {number} group
|
| - */
|
| - appendInterval: function(time, group)
|
| - {
|
| - var interval = time - this._lastTime;
|
| - if (interval <= this._remainder) {
|
| - this._counters[group] = (this._counters[group] || 0) + interval;
|
| - this._remainder -= interval;
|
| - this._lastTime = time;
|
| - return;
|
| - }
|
| - this._counters[group] = (this._counters[group] || 0) + this._remainder;
|
| - this._callback(this._counters);
|
| - interval -= this._remainder;
|
| - while (interval >= this._quantDuration) {
|
| - var counters = [];
|
| - counters[group] = this._quantDuration;
|
| - this._callback(counters);
|
| - interval -= this._quantDuration;
|
| - }
|
| - this._counters = [];
|
| - this._counters[group] = interval;
|
| - this._lastTime = time;
|
| - this._remainder = this._quantDuration - interval;
|
| + }
|
| +
|
| + /**
|
| + * @param {number} time
|
| + * @param {number} group
|
| + */
|
| + appendInterval(time, group) {
|
| + var interval = time - this._lastTime;
|
| + if (interval <= this._remainder) {
|
| + this._counters[group] = (this._counters[group] || 0) + interval;
|
| + this._remainder -= interval;
|
| + this._lastTime = time;
|
| + return;
|
| + }
|
| + this._counters[group] = (this._counters[group] || 0) + this._remainder;
|
| + this._callback(this._counters);
|
| + interval -= this._remainder;
|
| + while (interval >= this._quantDuration) {
|
| + var counters = [];
|
| + counters[group] = this._quantDuration;
|
| + this._callback(counters);
|
| + interval -= this._quantDuration;
|
| }
|
| + this._counters = [];
|
| + this._counters[group] = interval;
|
| + this._lastTime = time;
|
| + this._remainder = this._quantDuration - interval;
|
| + }
|
| };
|
|
|