Chromium Code Reviews| 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..0ab379388b9536e31b9b4d89360b4e7e184e43a6 100644 |
| --- a/Source/devtools/front_end/timeline/TracingTimelineUIUtils.js |
| +++ b/Source/devtools/front_end/timeline/TracingTimelineUIUtils.js |
| @@ -486,14 +486,16 @@ WebInspector.TracingTimelineUIUtils.buildTraceEventDetails = function(event, mod |
| var target = event.thread.target(); |
| var relatedNode = null; |
| var barrier = new CallbackBarrier(); |
| - if (!event.previewElement && target) { |
| + if (!event.previewElement) { |
| if (event.imageURL) |
| WebInspector.DOMPresentationUtils.buildImagePreviewContents(target, event.imageURL, false, barrier.createCallback(saveImage)); |
| else if (event.picture) |
| WebInspector.TracingTimelineUIUtils.buildPicturePreviewContent(event, barrier.createCallback(saveImage)); |
| } |
| - if (event.backendNodeId && target) |
| + if (event.backendNodeId) |
| target.domModel.pushNodesByBackendIdsToFrontend([event.backendNodeId], barrier.createCallback(setRelatedNode)); |
| + if (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,7 +669,7 @@ WebInspector.TracingTimelineUIUtils._buildTraceEventDetailsSynchronously = funct |
| if (event.previewElement) |
| contentHelper.appendElementRow(WebInspector.UIString("Preview"), event.previewElement); |
| - if (event.stackTrace || (event.initiator && event.initiator.stackTrace)) |
| + if (event.stackTrace || (event.initiator && event.initiator.stackTrace) || event.invalidationTrackingEvents) |
| WebInspector.TracingTimelineUIUtils._generateCauses(event, contentHelper); |
| fragment.appendChild(contentHelper.element); |
| @@ -679,6 +686,7 @@ WebInspector.TracingTimelineUIUtils._generateCauses = function(event, contentHel |
| var callSiteStackLabel; |
| var stackLabel; |
| + var initiator = event.initiator; |
| switch (event.name) { |
| case recordTypes.TimerFire: |
| @@ -700,10 +708,132 @@ 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, 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.TimelineDetailsContentHelper} contentHelper |
| + */ |
| +WebInspector.TracingTimelineUIUtils._generateInvalidations = function(event, contentHelper) |
| +{ |
| + if (!event.invalidationTrackingEvents) |
| + return; |
| + |
| + var target = event.thread.target(); |
| + var invalidations = {}; |
| + event.invalidationTrackingEvents.forEach(function(invalidation) { |
| + if (invalidations[invalidation.type] === undefined) |
| + invalidations[invalidation.type] = [invalidation]; |
| + else |
| + invalidations[invalidation.type].push(invalidation); |
| + }); |
| + |
| + Object.keys(invalidations).forEach(function(type) { |
| + var title; |
| + switch (type) { |
| + case WebInspector.TracingTimelineModel.RecordType.StyleRecalcInvalidationTracking: |
| + title = WebInspector.UIString("Style invalidations"); |
| + break; |
| + case WebInspector.TracingTimelineModel.RecordType.LayoutInvalidationTracking: |
| + title = WebInspector.UIString("Layout invalidations"); |
| + break; |
| + default: |
| + title = WebInspector.UIString("Other invalidations"); |
| + break; |
| + } |
| + |
| + WebInspector.TracingTimelineUIUtils._generateInvalidation( |
| + title, target, invalidations[type], contentHelper); |
| + }); |
| +} |
| + |
| +/** |
| + * @param {string} title |
| + * @param {?WebInspector.Target} target |
| + * @param {!Object} invalidationEvents |
| + * @param {!WebInspector.TimelineDetailsContentHelper} contentHelper |
| + */ |
| +WebInspector.TracingTimelineUIUtils._generateInvalidation = function(title, target, invalidationEvents, contentHelper) |
| +{ |
| + var detailsNode = document.createElement("div"); |
| + detailsNode.className = "timeline-details-view-row"; |
| + var titleElement = detailsNode.createChild("span", "timeline-details-view-row-title"); |
| + titleElement.textContent = WebInspector.UIString("%s: ", title); |
| + var eventsList = detailsNode.createChild("ol"); |
| + |
| + invalidationEvents.forEach(function(invalidation, idx) { |
| + var row = eventsList.createChild("li"); |
| + var nodeRow = row.createChild("div"); |
| + var node = target.domModel.nodeForId(invalidation.frontendNodeId); |
| + if (node) |
| + nodeRow.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(node)); |
| + else if (invalidation.nodeName) |
| + nodeRow.textContent = WebInspector.UIString("[ %s ]", invalidation.nodeName); |
| + else |
| + nodeRow.textContent = WebInspector.UIString("[ unknown node ]"); |
| + |
| + if (invalidation.reason) { |
| + var reasonRow = row.createChild("div"); |
| + var reason = invalidation.reason + (invalidation.reason.endsWith('.') ? '' : '.'); |
|
caseq
2014/10/16 17:08:01
s/'/"/g, though it would be perhaps nice to just m
pdr.
2014/10/17 05:07:04
Done, filed crbug.com/424451 to clean these up, an
|
| + reasonRow.textContent = WebInspector.UIString("Reason: %s", reason); |
| + } |
| + |
| + var callstack = invalidation.callstack ? JSON.parse(invalidation.callstack) : []; |
| + if (callstack.length) |
| + contentHelper.createChildStackTraceElement(row, callstack); |
| + }); |
| + |
| + contentHelper.element.appendChild(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.'); |
|
caseq
2014/10/16 17:08:01
s/'/"/g
pdr.
2014/10/17 05:07:04
Done
|
| + 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]; |
| + }); |
| + } |
| } |
| /** |