| 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 4e853e8528979a5c59fa52829d7b5c68656a904d..ec61010f8faee18714d0d8209725cc66ab2a83d9 100644
|
| --- a/Source/devtools/front_end/timeline/TracingTimelineUIUtils.js
|
| +++ b/Source/devtools/front_end/timeline/TracingTimelineUIUtils.js
|
| @@ -494,6 +494,8 @@ WebInspector.TracingTimelineUIUtils.buildTraceEventDetails = function(event, mod
|
| }
|
| if (event.backendNodeId && target)
|
| target.domModel.pushNodesByBackendIdsToFrontend([event.backendNodeId], barrier.createCallback(setRelatedNode));
|
| + if (target && event.invalidationTrackingEvents)
|
| + WebInspector.TracingTimelineUIUtils._resolveInvalidationTrackingNodeIds(event, barrier);
|
| barrier.callWhenDone(callbackWrapper);
|
|
|
| /**
|
| @@ -612,6 +614,7 @@ WebInspector.TracingTimelineUIUtils._buildTraceEventDetailsSynchronously = funct
|
| contentHelper.appendElementRow(WebInspector.UIString("Image URL"), WebInspector.linkifyResourceAsNode(event.imageURL));
|
| break;
|
| case recordTypes.RecalculateStyles: // We don't want to see default details.
|
| + // FIXME: Show invalidation tracking for updating style.
|
| contentHelper.appendTextRow(WebInspector.UIString("Elements affected"), event.args["elementCount"]);
|
| break;
|
| case recordTypes.Layout:
|
| @@ -621,6 +624,10 @@ WebInspector.TracingTimelineUIUtils._buildTraceEventDetailsSynchronously = funct
|
| contentHelper.appendTextRow(WebInspector.UIString("Layout scope"),
|
| beginData["partialLayout"] ? WebInspector.UIString("Partial") : WebInspector.UIString("Whole document"));
|
| 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);
|
| @@ -662,8 +669,8 @@ WebInspector.TracingTimelineUIUtils._buildTraceEventDetailsSynchronously = funct
|
| if (event.previewElement)
|
| contentHelper.appendElementRow(WebInspector.UIString("Preview"), event.previewElement);
|
|
|
| - if (event.stackTrace || (event.initiator && event.initiator.stackTrace))
|
| - WebInspector.TracingTimelineUIUtils._generateCauses(event, contentHelper);
|
| + if (event.stackTrace || (event.initiator && event.initiator.stackTrace) || event.invalidationTrackingEvents)
|
| + WebInspector.TracingTimelineUIUtils._generateCauses(event, linkifier, contentHelper);
|
|
|
| fragment.appendChild(contentHelper.element);
|
| return fragment;
|
| @@ -671,14 +678,16 @@ WebInspector.TracingTimelineUIUtils._buildTraceEventDetailsSynchronously = funct
|
|
|
| /**
|
| * @param {!WebInspector.TracingModel.Event} event
|
| + * @param {!WebInspector.Linkifier} linkifier
|
| * @param {!WebInspector.TimelineDetailsContentHelper} contentHelper
|
| */
|
| -WebInspector.TracingTimelineUIUtils._generateCauses = function(event, contentHelper)
|
| +WebInspector.TracingTimelineUIUtils._generateCauses = function(event, linkifier, contentHelper)
|
| {
|
| var recordTypes = WebInspector.TracingTimelineModel.RecordType;
|
|
|
| var callSiteStackLabel;
|
| var stackLabel;
|
| + var initiator = event.initiator;
|
|
|
| switch (event.name) {
|
| case recordTypes.TimerFire:
|
| @@ -700,10 +709,153 @@ WebInspector.TracingTimelineUIUtils._generateCauses = function(event, contentHel
|
| if (event.stackTrace)
|
| contentHelper.appendStackTrace(stackLabel || WebInspector.UIString("Stack when this event occurred"), event.stackTrace);
|
|
|
| - // Indirect cause / invalidation.
|
| - var initiator = event.initiator;
|
| - if (initiator && initiator.stackTrace)
|
| + // Indirect causes.
|
| + if (event.invalidationTrackingEvents) { // Full invalidation tracking (experimental).
|
| + WebInspector.TracingTimelineUIUtils._generateInvalidations(event, linkifier, contentHelper);
|
| + } else if (initiator && initiator.stackTrace) { // Partial invalidation tracking.
|
| contentHelper.appendStackTrace(callSiteStackLabel || WebInspector.UIString("Stack when first invalidated"), initiator.stackTrace);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * @param {!WebInspector.TracingModel.Event} event
|
| + * @param {!WebInspector.Linkifier} linkifier
|
| + * @param {!WebInspector.TimelineDetailsContentHelper} contentHelper
|
| + */
|
| +WebInspector.TracingTimelineUIUtils._generateInvalidations = function(event, linkifier, contentHelper)
|
| +{
|
| + if (!event.invalidationTrackingEvents)
|
| + return;
|
| +
|
| + var target = event.thread.target();
|
| + var styleInvalidations = [];
|
| + var layoutInvalidations = [];
|
| + var layerInvalidations = [];
|
| + event.invalidationTrackingEvents.forEach(function(invalidation) {
|
| + switch (invalidation.type) {
|
| + case WebInspector.TracingTimelineModel.RecordType.StyleRecalcInvalidationTracking:
|
| + styleInvalidations.push(invalidation);
|
| + break;
|
| + case WebInspector.TracingTimelineModel.RecordType.LayoutInvalidationTracking:
|
| + layoutInvalidations.push(invalidation);
|
| + break;
|
| + case WebInspector.TracingTimelineModel.RecordType.LayerInvalidationTracking:
|
| + layerInvalidations.push(invalidation);
|
| + break;
|
| + default:
|
| + console.error("Unknown invalidation tracking event.");
|
| + console.error(invalidation);
|
| + }
|
| + });
|
| + if (styleInvalidations.length)
|
| + contentHelper.element.appendChild(
|
| + WebInspector.TracingTimelineUIUtils._buildInvalidationDetailsNode(WebInspector.UIString("Style invalidations"), linkifier, target, styleInvalidations));
|
| + if (layoutInvalidations.length)
|
| + contentHelper.element.appendChild(
|
| + WebInspector.TracingTimelineUIUtils._buildInvalidationDetailsNode(WebInspector.UIString("Layout invalidations"), linkifier, target, layoutInvalidations));
|
| + if (layerInvalidations.length)
|
| + contentHelper.element.appendChild(
|
| + WebInspector.TracingTimelineUIUtils._buildInvalidationDetailsNode(WebInspector.UIString("Layer invalidations"), linkifier, target, layerInvalidations));
|
| +}
|
| +
|
| +/**
|
| + * @param {string} title
|
| + * @param {!WebInspector.Linkifier} linkifier
|
| + * @param {?WebInspector.Target} target
|
| + * @param {!WebInspector.TimelineDetailsContentHelper} contentHelper
|
| + */
|
| +WebInspector.TracingTimelineUIUtils._buildInvalidationDetailsNode = function(title, linkifier, target, 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(invalidation, idx) {
|
| + var row = document.createElement("li");
|
| + eventsList.appendChild(row);
|
| +
|
| + var nodeRow = document.createElement("div");
|
| + row.appendChild(nodeRow);
|
| + var node = target.domModel.nodeForId(invalidation.frontendNodeId);
|
| + if (node)
|
| + nodeRow.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(node));
|
| + else if (invalidation.nodeName)
|
| + nodeRow.textContent = '[' + invalidation.nodeName + ']';
|
| + else
|
| + nodeRow.textContent = '[ unknown node ]';
|
| +
|
| + if (invalidation.reason) {
|
| + var reasonRow = document.createElement("div");
|
| + reasonRow.textContent = 'Reason: ' + invalidation.reason + (invalidation.reason.endsWith('.') ? '' : '.');
|
| + row.appendChild(reasonRow);
|
| + }
|
| +
|
| + var callstack = invalidation.callstack ? JSON.parse(invalidation.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;
|
| +}
|
| +
|
| +/**
|
| + * @param {!WebInspector.TracingModel.Event} event
|
| + * @param {!CallbackBarrier} barrier
|
| + */
|
| +WebInspector.TracingTimelineUIUtils._resolveInvalidationTrackingNodeIds = function(event, barrier)
|
| +{
|
| + var backendNodeIdSet = {};
|
| + if (event.nodeId)
|
| + backendNodeIdSet[event.nodeId] = true;
|
| + event.invalidationTrackingEvents.forEach(function(invalidation) {
|
| + if (invalidation.nodeId)
|
| + backendNodeIdSet[invalidation.nodeId] = true;
|
| + });
|
| +
|
| + var backendNodeIds = [];
|
| + Object.keys(backendNodeIdSet).forEach(function(backendNodeId) {
|
| + backendNodeIds.push(parseInt(backendNodeId));
|
| + });
|
| + event.thread.target().domModel.pushNodesByBackendIdsToFrontend(
|
| + backendNodeIds, barrier.createCallback(updateInvalidationNodeIds));
|
| +
|
| + function updateInvalidationNodeIds(frontendNodeIds)
|
| + {
|
| + if (!frontendNodeIds)
|
| + return;
|
| + if (frontendNodeIds.length != backendNodeIds.length) {
|
| + console.error('Did not resolve the correct number of frontend node ids.');
|
| + return;
|
| + }
|
| +
|
| + var backendToFrontendNodeIdMap = {};
|
| + backendNodeIds.forEach(function(backendNodeId, index) {
|
| + backendToFrontendNodeIdMap[backendNodeId] = frontendNodeIds[index];
|
| + });
|
| +
|
| + if (event.nodeId)
|
| + event.frontendNodeId = backendToFrontendNodeIdMap[event.nodeId];
|
| + event.invalidationTrackingEvents.forEach(function(invalidation) {
|
| + if (invalidation.nodeId)
|
| + invalidation.frontendNodeId = backendToFrontendNodeIdMap[invalidation.nodeId];
|
| + });
|
| + }
|
| }
|
|
|
| /**
|
|
|