Commit 4e14978a authored by caseq's avatar caseq Committed by Commit bot

Timeline: move SegmentedRange into the WebInspector namespace and a file of its own

... for ease of re-used outside of front-end codebase.

Review URL: https://codereview.chromium.org/1808063002

Cr-Commit-Position: refs/heads/master@{#381789}
parent 5b50b674
...@@ -9,14 +9,13 @@ function test() ...@@ -9,14 +9,13 @@ function test()
{ {
InspectorTest.addResult("Test case: " + testName); InspectorTest.addResult("Test case: " + testName);
InspectorTest.addResult("Input Segments: " + JSON.stringify(data)); InspectorTest.addResult("Input Segments: " + JSON.stringify(data));
var range = SegmentedRange(merge);
var forwardRange = new SegmentedRange(merge); var forwardRange = new WebInspector.SegmentedRange(merge);
data.map(entry => new Segment(entry[0], entry[1], entry[2])).forEach(forwardRange.append, forwardRange); data.map(entry => new WebInspector.Segment(entry[0], entry[1], entry[2])).forEach(forwardRange.append, forwardRange);
var forward = forwardRange.segments(); var forward = forwardRange.segments();
var backwardRange = new SegmentedRange(merge); var backwardRange = new WebInspector.SegmentedRange(merge);
data.reverse().map(entry => new Segment(entry[0], entry[1], entry[2])).forEach(backwardRange.append, backwardRange); data.reverse().map(entry => new WebInspector.Segment(entry[0], entry[1], entry[2])).forEach(backwardRange.append, backwardRange);
var backward = backwardRange.segments(); var backward = backwardRange.segments();
// Only do reverse if we merge, otherwise result is order-dependent. // Only do reverse if we merge, otherwise result is order-dependent.
......
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
'front_end/common/Settings.js', 'front_end/common/Settings.js',
'front_end/common/StaticContentProvider.js', 'front_end/common/StaticContentProvider.js',
'front_end/common/OutputStream.js', 'front_end/common/OutputStream.js',
'front_end/common/SegmentedRange.js',
'front_end/common/TestBase.js', 'front_end/common/TestBase.js',
'front_end/common/Text.js', 'front_end/common/Text.js',
'front_end/common/TextDictionary.js', 'front_end/common/TextDictionary.js',
......
// Copyright 2016 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.
/**
* @constructor
* @param {number} begin
* @param {number} end
* @param {*} data
*/
WebInspector.Segment = function(begin, end, data)
{
if (begin > end)
console.assert(false, "Invalid segment");
this.begin = begin;
this.end = end;
this.data = data;
}
WebInspector.Segment.prototype = {
/**
* @param {!WebInspector.Segment} that
* @return {boolean}
*/
intersects: function(that)
{
return this.begin < that.end && that.begin < this.end;
}
};
/**
* @constructor
* @param {(function(!WebInspector.Segment, !WebInspector.Segment): ?WebInspector.Segment)=} mergeCallback
*/
WebInspector.SegmentedRange = function(mergeCallback)
{
/** @type {!Array<!WebInspector.Segment>} */
this._segments = [];
this._mergeCallback = mergeCallback;
}
WebInspector.SegmentedRange.prototype = {
/**
* @param {!WebInspector.Segment} newSegment
*/
append: function(newSegment)
{
// 1. Find the proper insertion point for new segment
var startIndex = this._segments.lowerBound(newSegment, (a, b) => a.begin - b.begin);
var endIndex = startIndex;
var merged = null;
if (startIndex > 0) {
// 2. Try mering the preceding segment
var precedingSegment = this._segments[startIndex - 1];
merged = this._tryMerge(precedingSegment, newSegment);
if (merged) {
--startIndex;
newSegment = merged;
} else if (this._segments[startIndex - 1].end >= newSegment.begin) {
// 2a. If merge failed and segments overlap, adjust preceding segment.
// If an old segment entirely contains new one, split it in two.
if (newSegment.end < precedingSegment.end)
this._segments.splice(startIndex, 0, new WebInspector.Segment(newSegment.end, precedingSegment.end, precedingSegment.data));
precedingSegment.end = newSegment.begin;
}
}
// 3. Consume all segments that are entirely covered by the new one.
while (endIndex < this._segments.length && this._segments[endIndex].end <= newSegment.end)
++endIndex;
// 4. Merge or adjust the succeeding segment if it overlaps.
if (endIndex < this._segments.length) {
merged = this._tryMerge(newSegment, this._segments[endIndex]);
if (merged) {
endIndex++;
newSegment = merged;
} else if (newSegment.intersects(this._segments[endIndex]))
this._segments[endIndex].begin = newSegment.end;
}
this._segments.splice(startIndex, endIndex - startIndex, newSegment);
},
/**
* @param {!WebInspector.SegmentedRange} that
*/
appendRange: function(that)
{
that.segments().forEach(segment => this.append(segment));
},
/**
* @return {!Array<!WebInspector.Segment>}
*/
segments: function()
{
return this._segments;
},
/**
* @param {!WebInspector.Segment} first
* @param {!WebInspector.Segment} second
* @return {?WebInspector.Segment}
*/
_tryMerge: function(first, second)
{
var merged = this._mergeCallback && this._mergeCallback(first, second);
if (!merged)
return null;
merged.begin = first.begin;
merged.end = Math.max(first.end, second.end);
return merged;
}
}
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
"Settings.js", "Settings.js",
"StaticContentProvider.js", "StaticContentProvider.js",
"OutputStream.js", "OutputStream.js",
"SegmentedRange.js",
"TestBase.js", "TestBase.js",
"Text.js", "Text.js",
"TextRange.js", "TextRange.js",
......
...@@ -1529,112 +1529,3 @@ Promise.prototype.catchException = function(defaultValue) { ...@@ -1529,112 +1529,3 @@ Promise.prototype.catchException = function(defaultValue) {
return defaultValue; return defaultValue;
}); });
} }
/**
* @constructor
* @param {(function(!Segment, !Segment): ?Segment)=} mergeCallback
*/
function SegmentedRange(mergeCallback)
{
/** @type {!Array<!Segment>} */
this._segments = [];
this._mergeCallback = mergeCallback;
}
/**
* @constructor
* @param {number} begin
* @param {number} end
* @param {*} data
*/
function Segment(begin, end, data)
{
if (begin > end)
console.assert(false, "Invalid segment");
this.begin = begin;
this.end = end;
this.data = data;
}
Segment.prototype = {
/**
* @param {!Segment} that
* @return {boolean}
*/
intersects: function(that)
{
return this.begin < that.end && that.begin < this.end;
}
};
SegmentedRange.prototype = {
/**
* @param {!Segment} newSegment
*/
append: function(newSegment)
{
// 1. Find the proper insertion point for new segment
var startIndex = this._segments.lowerBound(newSegment, (a, b) => a.begin - b.begin);
var endIndex = startIndex;
var merged = null;
if (startIndex > 0) {
// 2. Try mering the preceding segment
var precedingSegment = this._segments[startIndex - 1];
merged = this._tryMerge(precedingSegment, newSegment);
if (merged) {
--startIndex;
newSegment = merged;
} else if (this._segments[startIndex - 1].end >= newSegment.begin) {
// 2a. If merge failed and segments overlap, adjust preceding segment.
// If an old segment entirely contains new one, split it in two.
if (newSegment.end < precedingSegment.end)
this._segments.splice(startIndex, 0, new Segment(newSegment.end, precedingSegment.end, precedingSegment.data));
precedingSegment.end = newSegment.begin;
}
}
// 3. Consume all segments that are entirely covered by the new one.
while (endIndex < this._segments.length && this._segments[endIndex].end <= newSegment.end)
++endIndex;
// 4. Merge or adjust the succeeding segment if it overlaps.
if (endIndex < this._segments.length) {
merged = this._tryMerge(newSegment, this._segments[endIndex]);
if (merged) {
endIndex++;
newSegment = merged;
} else if (newSegment.intersects(this._segments[endIndex]))
this._segments[endIndex].begin = newSegment.end;
}
this._segments.splice(startIndex, endIndex - startIndex, newSegment);
},
/**
* @param {!SegmentedRange} that
*/
appendRange: function(that)
{
that.segments().forEach(segment => this.append(segment));
},
/**
* @return {!Array<!Segment>}
*/
segments: function()
{
return this._segments;
},
/**
* @param {!Segment} first
* @param {!Segment} second
* @return {?Segment}
*/
_tryMerge: function(first, second)
{
var merged = this._mergeCallback && this._mergeCallback(first, second);
if (!merged)
return null;
merged.begin = first.begin;
merged.end = Math.max(first.end, second.end);
return merged;
}
}
...@@ -837,7 +837,7 @@ WebInspector.TimelineFlameChartDataProvider.prototype = { ...@@ -837,7 +837,7 @@ WebInspector.TimelineFlameChartDataProvider.prototype = {
}, },
/** /**
* @param {!Segment} segment * @param {!WebInspector.Segment} segment
*/ */
_appendSegment: function(segment) _appendSegment: function(segment)
{ {
......
...@@ -82,7 +82,7 @@ WebInspector.TimelineIRModel.prototype = { ...@@ -82,7 +82,7 @@ WebInspector.TimelineIRModel.prototype = {
var animations = asyncEventsByGroup.get(groups.animation); var animations = asyncEventsByGroup.get(groups.animation);
if (animations) if (animations)
this._processAnimations(animations); this._processAnimations(animations);
var range = new SegmentedRange(); var range = new WebInspector.SegmentedRange();
range.appendRange(this._drags); // Drags take lower precedence than animation, as we can't detect them reliably. range.appendRange(this._drags); // Drags take lower precedence than animation, as we can't detect them reliably.
range.appendRange(this._cssAnimations); range.appendRange(this._cssAnimations);
range.appendRange(this._scrolls); range.appendRange(this._scrolls);
...@@ -129,7 +129,7 @@ WebInspector.TimelineIRModel.prototype = { ...@@ -129,7 +129,7 @@ WebInspector.TimelineIRModel.prototype = {
// FIXME: also process renderer fling events. // FIXME: also process renderer fling events.
if (!flingStart) if (!flingStart)
break; break;
this._scrolls.append(new Segment(flingStart.startTime, event.endTime, phases.Fling)); this._scrolls.append(new WebInspector.Segment(flingStart.startTime, event.endTime, phases.Fling));
flingStart = null; flingStart = null;
break; break;
...@@ -168,7 +168,7 @@ WebInspector.TimelineIRModel.prototype = { ...@@ -168,7 +168,7 @@ WebInspector.TimelineIRModel.prototype = {
this._drags.append(this._segmentForEvent(event, phases.Drag)); this._drags.append(this._segmentForEvent(event, phases.Drag));
} else if (touchStart) { } else if (touchStart) {
firstTouchMove = event; firstTouchMove = event;
this._responses.append(new Segment(touchStart.startTime, event.endTime, phases.Response)); this._responses.append(new WebInspector.Segment(touchStart.startTime, event.endTime, phases.Response));
} }
break; break;
...@@ -199,7 +199,7 @@ WebInspector.TimelineIRModel.prototype = { ...@@ -199,7 +199,7 @@ WebInspector.TimelineIRModel.prototype = {
case eventTypes.MouseWheel: case eventTypes.MouseWheel:
// Do not consider first MouseWheel as trace viewer's implementation does -- in case of MouseWheel it's not really special. // Do not consider first MouseWheel as trace viewer's implementation does -- in case of MouseWheel it's not really special.
if (mouseWheel && canMerge(thresholdsMs.mouse, mouseWheel, event)) if (mouseWheel && canMerge(thresholdsMs.mouse, mouseWheel, event))
this._scrolls.append(new Segment(mouseWheel.endTime, event.startTime, phases.Scroll)); this._scrolls.append(new WebInspector.Segment(mouseWheel.endTime, event.startTime, phases.Scroll));
this._scrolls.append(this._segmentForEvent(event, phases.Scroll)); this._scrolls.append(this._segmentForEvent(event, phases.Scroll));
mouseWheel = event; mouseWheel = event;
break; break;
...@@ -230,15 +230,15 @@ WebInspector.TimelineIRModel.prototype = { ...@@ -230,15 +230,15 @@ WebInspector.TimelineIRModel.prototype = {
/** /**
* @param {!WebInspector.TracingModel.AsyncEvent} event * @param {!WebInspector.TracingModel.AsyncEvent} event
* @param {!WebInspector.TimelineIRModel.Phases} phase * @param {!WebInspector.TimelineIRModel.Phases} phase
* @return {!Segment} * @return {!WebInspector.Segment}
*/ */
_segmentForEvent: function(event, phase) _segmentForEvent: function(event, phase)
{ {
return new Segment(event.startTime, event.endTime, phase); return new WebInspector.Segment(event.startTime, event.endTime, phase);
}, },
/** /**
* @return {!Array<!Segment>} * @return {!Array<!WebInspector.Segment>}
*/ */
interactionRecords: function() interactionRecords: function()
{ {
...@@ -250,15 +250,15 @@ WebInspector.TimelineIRModel.prototype = { ...@@ -250,15 +250,15 @@ WebInspector.TimelineIRModel.prototype = {
var thresholdsMs = WebInspector.TimelineIRModel._mergeThresholdsMs; var thresholdsMs = WebInspector.TimelineIRModel._mergeThresholdsMs;
this._segments = []; this._segments = [];
this._drags = new SegmentedRange(merge.bind(null, thresholdsMs.mouse)); this._drags = new WebInspector.SegmentedRange(merge.bind(null, thresholdsMs.mouse));
this._cssAnimations = new SegmentedRange(merge.bind(null, thresholdsMs.animation)); this._cssAnimations = new WebInspector.SegmentedRange(merge.bind(null, thresholdsMs.animation));
this._responses = new SegmentedRange(merge.bind(null, 0)); this._responses = new WebInspector.SegmentedRange(merge.bind(null, 0));
this._scrolls = new SegmentedRange(merge.bind(null, thresholdsMs.animation)); this._scrolls = new WebInspector.SegmentedRange(merge.bind(null, thresholdsMs.animation));
/** /**
* @param {number} threshold * @param {number} threshold
* @param {!Segment} first * @param {!WebInspector.Segment} first
* @param {!Segment} second * @param {!WebInspector.Segment} second
*/ */
function merge(threshold, first, second) function merge(threshold, first, second)
{ {
......
...@@ -1490,7 +1490,7 @@ WebInspector.FlameChart.prototype = { ...@@ -1490,7 +1490,7 @@ WebInspector.FlameChart.prototype = {
*/ */
_drawCollapsedOverviewForGroup: function(y, startLevel, endLevel) _drawCollapsedOverviewForGroup: function(y, startLevel, endLevel)
{ {
var range = new SegmentedRange(mergeCallback); var range = new WebInspector.SegmentedRange(mergeCallback);
var timeWindowRight = this._timeWindowRight; var timeWindowRight = this._timeWindowRight;
var timeWindowLeft = this._timeWindowLeft - this._paddingLeft / this._timeToPixel; var timeWindowLeft = this._timeWindowLeft - this._paddingLeft / this._timeToPixel;
var context = this._canvas.getContext("2d"); var context = this._canvas.getContext("2d");
...@@ -1514,7 +1514,7 @@ WebInspector.FlameChart.prototype = { ...@@ -1514,7 +1514,7 @@ WebInspector.FlameChart.prototype = {
break; break;
lastDrawOffset = startPosition; lastDrawOffset = startPosition;
var color = this._dataProvider.entryColor(entryIndex); var color = this._dataProvider.entryColor(entryIndex);
range.append(new Segment(startPosition, this._timeToPositionClipped(entryEndTime), color)); range.append(new WebInspector.Segment(startPosition, this._timeToPositionClipped(entryEndTime), color));
} }
} }
...@@ -1534,9 +1534,9 @@ WebInspector.FlameChart.prototype = { ...@@ -1534,9 +1534,9 @@ WebInspector.FlameChart.prototype = {
context.fill(); context.fill();
/** /**
* @param {!Segment} a * @param {!WebInspector.Segment} a
* @param {!Segment} b * @param {!WebInspector.Segment} b
* @return {?Segment} * @return {?WebInspector.Segment}
*/ */
function mergeCallback(a, b) function mergeCallback(a, b)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment