| Index: Source/devtools/front_end/timeline/TracingTimelineUIUtils.js
|
| diff --git a/Source/devtools/front_end/timeline/TracingTimelineUIUtils.js b/Source/devtools/front_end/timeline/TracingTimelineUIUtils.js
|
| index 10c2d302e40e8f4a960ef1fdcec6bf741eb88015..acc5d9ec9b22e716d65186d554f005e98cea9023 100644
|
| --- a/Source/devtools/front_end/timeline/TracingTimelineUIUtils.js
|
| +++ b/Source/devtools/front_end/timeline/TracingTimelineUIUtils.js
|
| @@ -485,6 +485,8 @@ WebInspector.TracingTimelineUIUtils.buildTraceEventDetails = function(event, mod
|
| {
|
| var target = event.thread.target();
|
| var relatedNode = null;
|
| + var invalidationBackendNodeIds = [];
|
| + var invalidationEvent = event;
|
| var barrier = new CallbackBarrier();
|
| if (!event.previewElement && target) {
|
| if (event.imageURL)
|
| @@ -492,8 +494,34 @@ WebInspector.TracingTimelineUIUtils.buildTraceEventDetails = function(event, mod
|
| else if (event.picture)
|
| WebInspector.TracingTimelineUIUtils.buildPicturePreviewContent(target, event.picture, barrier.createCallback(saveImage));
|
| }
|
| +
|
| + if (target) {
|
| + var invalidationNodeIdMap = {};
|
| +
|
| + if (event.nodeId)
|
| + invalidationNodeIdMap[event.nodeId] = true;
|
| + if (event.styleInvalidationTrackingEvents && event.styleInvalidationTrackingEvents.length) {
|
| + event.styleInvalidationTrackingEvents.forEach(function(invalidationEvent) {
|
| + if (invalidationEvent.nodeId)
|
| + invalidationNodeIdMap[invalidationEvent.nodeId] = true;
|
| + });
|
| + }
|
| + if (event.layoutInvalidationTrackingEvents && event.layoutInvalidationTrackingEvents.length) {
|
| + event.layoutInvalidationTrackingEvents.forEach(function(invalidationEvent) {
|
| + if (invalidationEvent.nodeId)
|
| + invalidationNodeIdMap[invalidationEvent.nodeId] = true;
|
| + });
|
| + }
|
| +
|
| + var keys = Object.keys(invalidationNodeIdMap);
|
| + for (var i = 0; i < keys.length; i++)
|
| + invalidationBackendNodeIds.push(parseInt(keys[i]));
|
| + target.domModel.pushNodesByBackendIdsToFrontend(invalidationBackendNodeIds, barrier.createCallback(updateInvalidationNodeIds));
|
| + }
|
| +
|
| if (event.backendNodeId && target)
|
| target.domModel.pushNodesByBackendIdsToFrontend([event.backendNodeId], barrier.createCallback(setRelatedNode));
|
| +
|
| barrier.callWhenDone(callbackWrapper);
|
|
|
| /**
|
| @@ -513,6 +541,34 @@ WebInspector.TracingTimelineUIUtils.buildTraceEventDetails = function(event, mod
|
| relatedNode = target.domModel.nodeForId(nodeIds[0]);
|
| }
|
|
|
| + function updateInvalidationNodeIds(frontendNodeIds)
|
| + {
|
| + if (!frontendNodeIds)
|
| + return;
|
| + if (frontendNodeIds.length != invalidationBackendNodeIds.length) {
|
| + console.error('Did not resolve the correct number of frontend node ids.');
|
| + return;
|
| + }
|
| +
|
| + // FIXME: Use a map here instead of an O(n^2) loop.
|
| + invalidationBackendNodeIds.forEach(function(backendNodeId, index) {
|
| + if (invalidationEvent.nodeId == backendNodeId)
|
| + invalidationEvent.frontendNodeId = frontendNodeIds[index];
|
| + if (invalidationEvent.styleInvalidationTrackingEvents && invalidationEvent.styleInvalidationTrackingEvents.length) {
|
| + invalidationEvent.styleInvalidationTrackingEvents.forEach(function(invalidationEvent) {
|
| + if (invalidationEvent.nodeId == backendNodeId)
|
| + invalidationEvent.frontendNodeId = frontendNodeIds[index];
|
| + });
|
| + }
|
| + if (invalidationEvent.layoutInvalidationTrackingEvents && invalidationEvent.layoutInvalidationTrackingEvents.length) {
|
| + invalidationEvent.layoutInvalidationTrackingEvents.forEach(function(invalidationEvent) {
|
| + if (invalidationEvent.nodeId == backendNodeId)
|
| + invalidationEvent.frontendNodeId = frontendNodeIds[index];
|
| + });
|
| + }
|
| + });
|
| + }
|
| +
|
| function callbackWrapper()
|
| {
|
| callback(WebInspector.TracingTimelineUIUtils._buildTraceEventDetailsSynchronously(event, model, linkifier, relatedNode));
|
| @@ -620,6 +676,7 @@ WebInspector.TracingTimelineUIUtils._buildTraceEventDetailsSynchronously = funct
|
| case recordTypes.RecalculateStyles: // We don't want to see default details.
|
| contentHelper.appendTextRow(WebInspector.UIString("Elements affected"), event.args["elementCount"]);
|
| callStackLabel = WebInspector.UIString("Styles recalculation forced");
|
| + // FIXME: Show invalidation tracking for updating style.
|
| break;
|
| case recordTypes.Layout:
|
| var beginData = event.args["beginData"];
|
| @@ -630,6 +687,10 @@ WebInspector.TracingTimelineUIUtils._buildTraceEventDetailsSynchronously = funct
|
| callSiteStackTraceLabel = WebInspector.UIString("Layout invalidated");
|
| callStackLabel = WebInspector.UIString("Layout forced");
|
| relatedNodeLabel = WebInspector.UIString("Layout root");
|
| + // FIXME: Show invalidation tracking for updating layout.
|
| + break;
|
| + case recordTypes.UpdateLayerTree:
|
| + // FIXME: Show invalidation tracking for updating the layer tree.
|
| break;
|
| case recordTypes.ConsoleTime:
|
| contentHelper.appendTextRow(WebInspector.UIString("Message"), event.name);
|
| @@ -679,6 +740,19 @@ WebInspector.TracingTimelineUIUtils._buildTraceEventDetailsSynchronously = funct
|
| }
|
| if (event.previewElement)
|
| contentHelper.appendElementRow(WebInspector.UIString("Preview"), event.previewElement);
|
| +
|
| + // Show invalidation tracking.
|
| + if (event.styleInvalidationTrackingEvents && event.styleInvalidationTrackingEvents.length) {
|
| + contentHelper.element.appendChild(
|
| + this._buildInvalidationDetailsNode(WebInspector.UIString("Style invalidations"),
|
| + linkifier, event, event.styleInvalidationTrackingEvents));
|
| + }
|
| + if (event.layoutInvalidationTrackingEvents && event.layoutInvalidationTrackingEvents.length) {
|
| + contentHelper.element.appendChild(
|
| + this._buildInvalidationDetailsNode(WebInspector.UIString("Layout invalidations"),
|
| + linkifier, event, event.layoutInvalidationTrackingEvents));
|
| + }
|
| +
|
| fragment.appendChild(contentHelper.element);
|
| return fragment;
|
| }
|
| @@ -791,6 +865,53 @@ WebInspector.TracingTimelineUIUtils._createEventDivider = function(recordType, t
|
| }
|
|
|
| /**
|
| + * TODO: write me
|
| + */
|
| +WebInspector.TracingTimelineUIUtils._buildInvalidationDetailsNode = function(title, linkifier, event, invalidationEvents)
|
| +{
|
| + var detailsNode = document.createElement("div");
|
| + detailsNode.className = "timeline-details-view-row";
|
| + var titleElement = document.createElement("span");
|
| + titleElement.className = "timeline-details-view-row-title";
|
| + titleElement.textContent = WebInspector.UIString("%s: ", title);
|
| + detailsNode.appendChild(titleElement);
|
| + var eventsList = document.createElement("ol");
|
| + detailsNode.appendChild(eventsList);
|
| +
|
| + invalidationEvents.forEach(function(invalidationEvent, idx) {
|
| + var row = document.createElement("li");
|
| + eventsList.appendChild(row);
|
| +
|
| + var nodeRow = document.createElement("div");
|
| + row.appendChild(nodeRow);
|
| + var target = event.thread.target();
|
| + var node = target.domModel.nodeForId(invalidationEvent.frontendNodeId);
|
| + if (node)
|
| + nodeRow.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(node));
|
| + else if (invalidationEvent.nodeName)
|
| + nodeRow.textContent = '[' + invalidationEvent.nodeName + ']';
|
| + else
|
| + nodeRow.textContent = '[ unknown node ]';
|
| +
|
| + var callstack = invalidationEvent.callstack ? JSON.parse(invalidationEvent.callstack) : [];
|
| + if (callstack.length > 0) {
|
| + var callstackRow = document.createElement("div");
|
| + row.appendChild(callstackRow);
|
| + callstack.forEach(function(stackFrame) {
|
| + var frameRow = document.createElement("div");
|
| + frameRow.className = "timeline-details-view-row monospace";
|
| + callstackRow.appendChild(frameRow);
|
| + frameRow.textContent = stackFrame.functionName || WebInspector.UIString("(anonymous function)");
|
| + frameRow.textContent += " @ ";
|
| + var urlElement = linkifier.linkifyScriptLocation(target, stackFrame.scriptId, stackFrame.url, stackFrame.lineNumber - 1, stackFrame.columnNumber - 1);
|
| + frameRow.appendChild(urlElement);
|
| + });
|
| + }
|
| + });
|
| + return detailsNode;
|
| +}
|
| +
|
| +/**
|
| * @return {!Array.<string>}
|
| */
|
| WebInspector.TracingTimelineUIUtils._visibleTypes = function()
|
|
|