blob: 585eb0bc03023a2a6c2d490e8dde49cc5ee13f7d [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2015 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/base/base.html">
<link rel="import" href="/base/range_utils.html">
<link rel="import" href="/core/auditor.html">
<link rel="import" href="/extras/rail/animation_interaction_record.html">
<link rel="import" href="/extras/rail/response_interaction_record.html">
<link rel="import" href="/model/event_info.html">
<script>
'use strict';
/**
* @fileoverview An intermediate data format between InputLatencyAsyncSlices
* and RAILIRs.
*/
tr.exportTo('tr.e.rail', function() {
// This is an intermediate data format between InputLatencyAsyncSlices and
// Response and Animation IRs.
function ProtoIR(irType) {
this.irType = irType;
this.start = Infinity;
this.end = -Infinity;
this.associatedEvents = new tr.model.EventSet();
}
ProtoIR.RESPONSE_TYPE = 'r';
ProtoIR.ANIMATION_TYPE = 'a';
// Explicitly ignore some input events to allow
// RAILIRFinder.checkAllInputEventsHandled() to determine which events were
// unintentionally ignored due to a bug.
ProtoIR.IGNORED_TYPE = 'ignored';
ProtoIR.prototype = {
get isValid() {
return this.end > this.start;
},
// Return true if any associatedEvent's typeName is in typeNames.
containsTypeNames: function(typeNames) {
for (var i = 0; i < this.associatedEvents.length; ++i) {
if (typeNames.indexOf(this.associatedEvents[i].typeName) >= 0)
return true;
}
return false;
},
getIRConstructor: function() {
switch (this.irType) {
case ProtoIR.RESPONSE_TYPE:
return tr.e.rail.ResponseInteractionRecord;
case ProtoIR.ANIMATION_TYPE:
return tr.e.rail.AnimationInteractionRecord;
}
return undefined;
},
createInteractionRecord: function() {
if (!this.isValid) {
console.error('Invalid ProtoIR: ' + this.debug() +
' File a bug with this trace!');
return undefined;
}
var constructor = this.getIRConstructor();
if (constructor === undefined)
return undefined;
var ir = new constructor(this.start, this.end - this.start);
function pushAssociatedEvents(event) {
ir.associatedEvents.push(event);
// |event| is either an InputLatencyAsyncSlice (which collects all of
// its associated events transitively) or a CSS Animation (which doesn't
// have any associated events). So this does not need to recurse.
if (event.associatedEvents)
ir.associatedEvents.addEventSet(event.associatedEvents);
}
this.associatedEvents.forEach(function(event) {
pushAssociatedEvents(event);
// Old-style InputLatencyAsyncSlices have subSlices.
if (event.subSlices)
event.subSlices.forEach(pushAssociatedEvents);
});
return ir;
},
// Merge the other ProtoIR into this one.
merge: function(other) {
if (this.irType !== other.irType)
console.error('Merging', this.debug(), other.debug());
// Don't use pushEvent(), which would lose special start, end.
this.associatedEvents.addEventSet(other.associatedEvents);
this.start = Math.min(this.start, other.start);
this.end = Math.max(this.end, other.end);
},
// Include |event| in this ProtoIR, expanding start/end to include it.
pushEvent: function(event) {
// Usually, this method will be called while iterating over a list of
// events sorted by start time, so this method won't usually change
// this.start. However, this will sometimes be called for ProtoIRs created
// by previous handlers, in which case event.start could possibly be
// before this.start.
this.start = Math.min(this.start, event.start);
this.end = Math.max(this.end, event.end);
this.associatedEvents.push(event);
},
// Returns true if timestamp is contained in this ProtoIR.
containsTimestampInclusive: function(timestamp) {
return (this.start <= timestamp) && (timestamp <= this.end);
},
// Return true if the other event intersects this ProtoIR.
intersects: function(other) {
// http://stackoverflow.com/questions/325933
return (other.start < this.end) && (other.end > this.start);
},
isNear: function(event, threshold) {
return (this.end + threshold) > event.start;
},
// Return a string describing this ProtoIR for debugging.
debug: function() {
var debugString = this.irType + '(';
debugString += parseInt(this.start) + ' ';
debugString += parseInt(this.end);
this.associatedEvents.forEach(function(event) {
debugString += ' ' + event.typeName;
});
return debugString + ')';
}
};
return {
ProtoIR: ProtoIR
};
});
</script>