Index: Source/devtools/front_end/timeline/TimelineModel.js |
diff --git a/Source/devtools/front_end/timeline/TimelineModel.js b/Source/devtools/front_end/timeline/TimelineModel.js |
index 186fede5f58e963dea110338aef98dd913c6ec57..cc81884ac5b3fafbf5199de78ae4267ea11046a3 100644 |
--- a/Source/devtools/front_end/timeline/TimelineModel.js |
+++ b/Source/devtools/front_end/timeline/TimelineModel.js |
@@ -74,7 +74,9 @@ WebInspector.TimelineModel.RecordType = { |
ScrollLayer: "ScrollLayer", |
CompositeLayers: "CompositeLayers", |
+ ScheduleStyleInvalidationTracking: "ScheduleStyleInvalidationTracking", |
StyleRecalcInvalidationTracking: "StyleRecalcInvalidationTracking", |
+ StyleInvalidatorInvalidationTracking: "StyleInvalidatorInvalidationTracking", |
LayoutInvalidationTracking: "LayoutInvalidationTracking", |
LayerInvalidationTracking: "LayerInvalidationTracking", |
PaintInvalidationTracking: "PaintInvalidationTracking", |
@@ -951,11 +953,13 @@ WebInspector.TimelineModel.prototype = { |
this._lastRecalculateStylesEvent = event; |
break; |
+ case recordTypes.ScheduleStyleInvalidationTracking: |
case recordTypes.StyleRecalcInvalidationTracking: |
+ case recordTypes.StyleInvalidatorInvalidationTracking: |
case recordTypes.LayoutInvalidationTracking: |
case recordTypes.LayerInvalidationTracking: |
case recordTypes.PaintInvalidationTracking: |
- this._invalidationTracker.addInvalidation(event); |
+ this._invalidationTracker.addInvalidation(new WebInspector.InvalidationTrackingEvent(event)); |
break; |
case recordTypes.InvalidateLayout: |
@@ -1664,20 +1668,47 @@ WebInspector.TracingTimelineSaver.prototype = { |
*/ |
WebInspector.InvalidationTrackingEvent = function(event) |
{ |
+ /** @type {string} */ |
this.type = event.name; |
- this.frameId = event.args["data"]["frame"]; |
- this.nodeId = event.args["data"]["nodeId"]; |
- this.nodeName = event.args["data"]["nodeName"]; |
- this.paintId = event.args["data"]["paintId"]; |
- |
- var reason = event.args["data"]["reason"]; |
- var stackTrace = event.args["data"]["stackTrace"]; |
- |
- if (!reason && stackTrace && this.type === WebInspector.TimelineModel.RecordType.LayoutInvalidationTracking) |
- reason = "Layout forced"; |
- |
- if (reason || stackTrace) |
- this.cause = {reason: reason, stackTrace: stackTrace}; |
+ /** @type {number} */ |
+ this.startTime = event.startTime; |
+ /** @type {!WebInspector.TracingModel.Event} */ |
+ this._tracingEvent = event; |
+ |
+ var eventData = event.args["data"]; |
+ |
+ /** @type {number} */ |
+ this.frame = eventData["frame"]; |
+ /** @type {?number} */ |
+ this.nodeId = eventData["nodeId"]; |
+ /** @type {?string} */ |
+ this.nodeName = eventData["nodeName"]; |
+ /** @type {?number} */ |
+ this.paintId = eventData["paintId"]; |
+ /** @type {?number} */ |
+ this.invalidationSet = eventData["invalidationSet"]; |
+ /** @type {?string} */ |
+ this.invalidatedSelectorId = eventData["invalidatedSelectorId"]; |
+ /** @type {?string} */ |
+ this.changedId = eventData["changedId"]; |
+ /** @type {?string} */ |
+ this.changedClass = eventData["changedClass"]; |
+ /** @type {?string} */ |
+ this.changedAttribute = eventData["changedAttribute"]; |
+ /** @type {?string} */ |
+ this.changedPseudo = eventData["changedPseudo"]; |
+ /** @type {?string} */ |
+ this.selectorPart = eventData["selectorPart"]; |
+ /** @type {?string} */ |
+ this.extraData = eventData["extraData"]; |
+ /** @type {?Array.<!Object.<string, number>>} */ |
+ this.invalidationList = eventData["invalidationList"]; |
+ /** @type {!WebInspector.InvalidationCause} */ |
+ this.cause = {reason: eventData["reason"], stackTrace: eventData["stackTrace"]}; |
+ |
+ // FIXME: Move this to TimelineUIUtils.js. |
+ if (!this.cause.reason && this.cause.stackTrace && this.type === WebInspector.TimelineModel.RecordType.LayoutInvalidationTracking) |
+ this.cause.reason = "Layout forced"; |
} |
/** @typedef {{reason: string, stackTrace: ?Array.<!ConsoleAgent.CallFrame>}} */ |
@@ -1693,11 +1724,10 @@ WebInspector.InvalidationTracker = function() |
WebInspector.InvalidationTracker.prototype = { |
/** |
- * @param {!WebInspector.TracingModel.Event} event |
+ * @param {!WebInspector.InvalidationTrackingEvent} invalidation |
*/ |
- addInvalidation: function(event) |
+ addInvalidation: function(invalidation) |
{ |
- var invalidation = new WebInspector.InvalidationTrackingEvent(event); |
this._startNewFrameIfNeeded(); |
if (!invalidation.nodeId && !invalidation.paintId) { |
@@ -1717,14 +1747,22 @@ WebInspector.InvalidationTracker.prototype = { |
return; |
} |
- // StyleRecalcInvalidationTracking events can occur before and during |
- // recalc style. didRecalcStyle handles StyleRecalcInvalidationTracking |
- // events that occur before the recalc style event but we need to handle |
- // StyleRecalcInvalidationTracking events during recalc style here. |
- if (invalidation.type === recordTypes.StyleRecalcInvalidationTracking) { |
- var duringRecalcStyle = event.startTime && this._lastRecalcStyle |
- && event.startTime >= this._lastRecalcStyle.startTime |
- && event.startTime <= this._lastRecalcStyle.endTime; |
+ // Suppress StyleInvalidator StyleRecalcInvalidationTracking invalidations because they |
+ // will be handled by StyleInvalidatorInvalidationTracking. |
+ // FIXME: Investigate if we can remove StyleInvalidator invalidations entirely. |
+ if (invalidation.type === recordTypes.StyleRecalcInvalidationTracking && invalidation.cause.reason === "StyleInvalidator") |
+ return; |
+ |
+ // Style invalidation events can occur before and during recalc style. didRecalcStyle |
+ // handles style invalidations that occur before the recalc style event but we need to |
+ // handle style recalc invalidations during recalc style here. |
+ var styleRecalcInvalidation = (invalidation.type === recordTypes.ScheduleStyleInvalidationTracking |
+ || invalidation.type === recordTypes.StyleInvalidatorInvalidationTracking |
+ || invalidation.type === recordTypes.StyleRecalcInvalidationTracking); |
+ if (styleRecalcInvalidation) { |
+ var duringRecalcStyle = invalidation.startTime && this._lastRecalcStyle |
+ && invalidation.startTime >= this._lastRecalcStyle.startTime |
+ && invalidation.startTime <= this._lastRecalcStyle.endTime; |
if (duringRecalcStyle) |
this._associateWithLastRecalcStyleEvent(invalidation); |
} |
@@ -1752,8 +1790,10 @@ WebInspector.InvalidationTracker.prototype = { |
didRecalcStyle: function(recalcStyleEvent) |
{ |
this._lastRecalcStyle = recalcStyleEvent; |
- this._forAllInvalidations(this._associateWithLastRecalcStyleEvent, |
- [WebInspector.TimelineModel.RecordType.StyleRecalcInvalidationTracking]); |
+ var types = [WebInspector.TimelineModel.RecordType.ScheduleStyleInvalidationTracking, |
+ WebInspector.TimelineModel.RecordType.StyleInvalidatorInvalidationTracking, |
+ WebInspector.TimelineModel.RecordType.StyleRecalcInvalidationTracking]; |
+ this._forAllInvalidations(this._associateWithLastRecalcStyleEvent, types); |
}, |
/** |
@@ -1763,12 +1803,77 @@ WebInspector.InvalidationTracker.prototype = { |
{ |
if (invalidation.linkedRecalcStyleEvent) |
return; |
+ |
+ var recordTypes = WebInspector.TimelineModel.RecordType; |
var recalcStyleFrameId = this._lastRecalcStyle.args["beginData"]["frame"]; |
- this._addInvalidationToEvent(this._lastRecalcStyle, recalcStyleFrameId, invalidation); |
+ if (invalidation.type === recordTypes.StyleInvalidatorInvalidationTracking) { |
+ // Instead of calling _addInvalidationToEvent directly, we create synthetic |
+ // StyleRecalcInvalidationTracking events which will be added in _addInvalidationToEvent. |
+ this._addSyntheticStyleRecalcInvalidations(this._lastRecalcStyle, recalcStyleFrameId, invalidation); |
+ } else if (invalidation.type === recordTypes.ScheduleStyleInvalidationTracking) { |
+ // ScheduleStyleInvalidationTracking events are only used for adding information to |
+ // StyleInvalidatorInvalidationTracking events. See: _addSyntheticStyleRecalcInvalidations. |
+ } else { |
+ this._addInvalidationToEvent(this._lastRecalcStyle, recalcStyleFrameId, invalidation); |
+ } |
+ |
invalidation.linkedRecalcStyleEvent = true; |
}, |
/** |
+ * @param {!WebInspector.TracingModel.Event} event |
+ * @param {number} frameId |
+ * @param {!WebInspector.InvalidationTrackingEvent} styleInvalidatorInvalidation |
+ */ |
+ _addSyntheticStyleRecalcInvalidations: function(event, frameId, styleInvalidatorInvalidation) |
+ { |
+ if (!styleInvalidatorInvalidation.invalidationList) { |
+ this._addSyntheticStyleRecalcInvalidation(styleInvalidatorInvalidation._tracingEvent, styleInvalidatorInvalidation); |
+ return; |
+ } |
+ |
+ for (var i = 0; i < styleInvalidatorInvalidation.invalidationList.length; i++) { |
+ var setId = styleInvalidatorInvalidation.invalidationList[i]["id"]; |
+ var lastScheduleStyleRecalculation; |
+ |
+ function findMatchingInvalidation(invalidation) |
+ { |
+ if (invalidation.frame !== frameId) |
+ return; |
+ if (invalidation.nodeId === styleInvalidatorInvalidation.nodeId && invalidation.invalidationSet === setId) |
+ lastScheduleStyleRecalculation = invalidation; |
+ } |
+ |
+ this._forAllInvalidations(findMatchingInvalidation, [WebInspector.TimelineModel.RecordType.ScheduleStyleInvalidationTracking]); |
+ |
+ if (!lastScheduleStyleRecalculation) { |
+ console.error("Failed to lookup the event that scheduled a style invalidator invalidation."); |
+ continue; |
+ } |
+ this._addSyntheticStyleRecalcInvalidation(lastScheduleStyleRecalculation._tracingEvent, styleInvalidatorInvalidation); |
+ } |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} baseEvent |
+ * @param {!WebInspector.InvalidationTrackingEvent} styleInvalidatorInvalidation |
+ */ |
+ _addSyntheticStyleRecalcInvalidation: function(baseEvent, styleInvalidatorInvalidation) |
+ { |
+ var invalidation = new WebInspector.InvalidationTrackingEvent(baseEvent); |
+ invalidation.type = WebInspector.TimelineModel.RecordType.StyleRecalcInvalidationTracking; |
+ invalidation.synthetic = true; |
+ if (styleInvalidatorInvalidation.cause.reason) |
+ invalidation.cause.reason = styleInvalidatorInvalidation.cause.reason; |
+ if (styleInvalidatorInvalidation.selectorPart) |
+ invalidation.selectorPart = styleInvalidatorInvalidation.selectorPart; |
+ |
+ this.addInvalidation(invalidation); |
+ if (!invalidation.linkedRecalcStyleEvent) |
+ this._associateWithLastRecalcStyleEvent(invalidation); |
+ }, |
+ |
+ /** |
* @param {!WebInspector.TracingModel.Event} layoutEvent |
*/ |
didLayout: function(layoutEvent) |
@@ -1810,7 +1915,10 @@ WebInspector.InvalidationTracker.prototype = { |
var effectivePaintId = this._lastPaintWithLayer.args["data"]["nodeId"]; |
var paintFrameId = paintEvent.args["data"]["frame"]; |
- this._forAllInvalidations(associateWithPaintEvent); |
+ var types = [WebInspector.TimelineModel.RecordType.StyleRecalcInvalidationTracking, |
+ WebInspector.TimelineModel.RecordType.LayoutInvalidationTracking, |
+ WebInspector.TimelineModel.RecordType.PaintInvalidationTracking]; |
+ this._forAllInvalidations(associateWithPaintEvent, types); |
/** |
* @param {!WebInspector.InvalidationTrackingEvent} invalidation |
@@ -1831,7 +1939,7 @@ WebInspector.InvalidationTracker.prototype = { |
*/ |
_addInvalidationToEvent: function(event, eventFrameId, invalidation) |
{ |
- if (eventFrameId !== invalidation.frameId) |
+ if (eventFrameId !== invalidation.frame) |
return; |
if (!event.invalidationTrackingEvents) |
event.invalidationTrackingEvents = [ invalidation ]; |