Commit caa8db68 authored by Fredrik Söderquist's avatar Fredrik Söderquist Committed by Commit Bot

Make SVGSMILElement::ResolveInterval robuster

Track the entry to start the (next) search in the 'begin' list from, and
make sure we advance to the next one for each subsequent iteration of
the loop. This should ensure forward progress is made.

Bug: 1029573
Change-Id: I7a3d7564527667cec397a1431b0757674ce75469
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1946477Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#721128}
parent af2542bf
...@@ -764,17 +764,16 @@ SMILTime SVGSMILElement::ResolveActiveEnd(SMILTime resolved_begin) const { ...@@ -764,17 +764,16 @@ SMILTime SVGSMILElement::ResolveActiveEnd(SMILTime resolved_begin) const {
SMILInterval SVGSMILElement::ResolveInterval(SMILTime begin_after, SMILInterval SVGSMILElement::ResolveInterval(SMILTime begin_after,
SMILTime end_after) const { SMILTime end_after) const {
if (begin_times_.IsEmpty())
return SMILInterval::Unresolved();
// Simplified version of the pseudocode in // Simplified version of the pseudocode in
// http://www.w3.org/TR/SMIL3/smil-timing.html#q90. // http://www.w3.org/TR/SMIL3/smil-timing.html#q90.
const size_t kMaxIterations = std::max(begin_times_.size() * 4, 1000000u); const size_t kMaxIterations = std::max(begin_times_.size() * 4, 1000000u);
size_t current_iteration = 0; size_t current_iteration = 0;
while (true) { for (auto* search_start = begin_times_.begin();
search_start != begin_times_.end(); ++search_start) {
// Find the (next) instance time in the 'begin' list that is greater or // Find the (next) instance time in the 'begin' list that is greater or
// equal to |begin_after|. // equal to |begin_after|.
auto* begin_item = std::lower_bound( auto* begin_item = std::lower_bound(
begin_times_.begin(), begin_times_.end(), begin_after, search_start, begin_times_.end(), begin_after,
[](const SMILTimeWithOrigin& instance_time, const SMILTime& time) { [](const SMILTimeWithOrigin& instance_time, const SMILTime& time) {
return instance_time.Time() < time; return instance_time.Time() < time;
}); });
...@@ -789,9 +788,9 @@ SMILInterval SVGSMILElement::ResolveInterval(SMILTime begin_after, ...@@ -789,9 +788,9 @@ SMILInterval SVGSMILElement::ResolveInterval(SMILTime begin_after,
// Don't allow the interval to end in the past. // Don't allow the interval to end in the past.
if (temp_end > end_after) if (temp_end > end_after)
return SMILInterval(begin_item->Time(), temp_end); return SMILInterval(begin_item->Time(), temp_end);
// Ensure forward progress. // Ensure forward progress by only considering the part of the 'begin' list
if (begin_after == temp_end) // after |begin_item| for the next iteration.
temp_end = begin_after + SMILTime::Epsilon(); search_start = begin_item;
begin_after = temp_end; begin_after = temp_end;
// Debugging signal for crbug.com/1021630. // Debugging signal for crbug.com/1021630.
CHECK_LT(current_iteration++, kMaxIterations); CHECK_LT(current_iteration++, kMaxIterations);
......
<!DOCTYPE html>
<title>SVGSVGElement.prototype.setCurrentTime: Large time argument</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<svg>
<rect width="100" height="100" fill="green">
<set attributeName="fill" to="red"
begin="9223372036854775807" dur="10ms"/>
</rect>
</svg>
<script>
async_test(function(t) {
onload = t.step_func(function() {
document.querySelector("svg").setCurrentTime(9223372036854775807);
requestAnimationFrame(t.step_func(function() {
t.step_timeout(function() {
let rect = document.querySelector('rect');
assert_equals(getComputedStyle(rect).fill, 'rgb(0, 128, 0)');
t.done();
}, 11);
}));
});
});
</script>
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