mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-13 18:27:35 +00:00
Bug 690994 - Check for self-dependent times when there are coincident zero-duration intervals; r=dholbert
This commit is contained in:
parent
1475029a2d
commit
28138b6333
14
content/smil/crashtests/690994-1.svg
Normal file
14
content/smil/crashtests/690994-1.svg
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait">
|
||||
<script>
|
||||
<![CDATA[
|
||||
function boom()
|
||||
{
|
||||
document.documentElement.removeChild(document.getElementById("a"));
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
<animate id="a" begin="a.end; -0.1s" end="a.begin+0.2s" onend="boom()"/>
|
||||
<animate id="a" begin="a.end; -0.1s" end="a.begin+0.2s"/>
|
||||
</svg>
|
After Width: | Height: | Size: 398 B |
@ -42,4 +42,5 @@ load 670313-1.svg
|
||||
load 678822-1.svg
|
||||
load 678847-1.svg
|
||||
load 678938-1.svg
|
||||
load 690994-1.svg
|
||||
load 699325-1.svg
|
||||
|
@ -1622,10 +1622,6 @@ nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
|
||||
beginAfter = aPrevInterval->End()->Time();
|
||||
prevIntervalWasZeroDur
|
||||
= aPrevInterval->End()->Time() == aPrevInterval->Begin()->Time();
|
||||
if (aFixedBeginTime) {
|
||||
prevIntervalWasZeroDur &=
|
||||
aPrevInterval->Begin()->Time() == aFixedBeginTime->Time();
|
||||
}
|
||||
} else {
|
||||
beginAfter.SetMillis(LL_MININT);
|
||||
}
|
||||
@ -1647,17 +1643,17 @@ nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
|
||||
tempBegin = new nsSMILInstanceTime(nsSMILTimeValue(0));
|
||||
} else {
|
||||
PRInt32 beginPos = 0;
|
||||
// If we're updating the current interval then skip any begin time that is
|
||||
// dependent on the current interval's begin time. e.g.
|
||||
// <animate id="a" begin="b.begin; a.begin+2s"...
|
||||
// If b's interval disappears whilst 'a' is in the waiting state the begin
|
||||
// time at "a.begin+2s" should be skipped since 'a' never begun.
|
||||
do {
|
||||
tempBegin =
|
||||
GetNextGreaterOrEqual(mBeginInstances, beginAfter, beginPos);
|
||||
if (!tempBegin || !tempBegin->Time().IsDefinite()) {
|
||||
return false;
|
||||
}
|
||||
// If we're updating the current interval then skip any begin time that is
|
||||
// dependent on the current interval's begin time. e.g.
|
||||
// <animate id="a" begin="b.begin; a.begin+2s"...
|
||||
// If b's interval disappears whilst 'a' is in the waiting state the begin
|
||||
// time at "a.begin+2s" should be skipped since 'a' never begun.
|
||||
} while (aReplacedInterval &&
|
||||
tempBegin->GetBaseTime() == aReplacedInterval->Begin());
|
||||
}
|
||||
@ -1668,22 +1664,24 @@ nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
|
||||
// Calculate end time
|
||||
{
|
||||
PRInt32 endPos = 0;
|
||||
// As above with begin times, avoid creating self-referential loops
|
||||
// between instance times by checking that the newly found end instance
|
||||
// time is not already dependent on the end of the current interval.
|
||||
do {
|
||||
tempEnd =
|
||||
GetNextGreaterOrEqual(mEndInstances, tempBegin->Time(), endPos);
|
||||
|
||||
// SMIL doesn't allow for coincident zero-duration intervals, so if the
|
||||
// previous interval was zero-duration, and tempEnd is going to give us
|
||||
// another zero duration interval, then look for another end to use
|
||||
// instead.
|
||||
if (tempEnd && prevIntervalWasZeroDur &&
|
||||
tempEnd->Time() == beginAfter) {
|
||||
tempEnd = GetNextGreater(mEndInstances, tempBegin->Time(), endPos);
|
||||
}
|
||||
// As above with begin times, avoid creating self-referential loops
|
||||
// between instance times by checking that the newly found end instance
|
||||
// time is not already dependent on the end of the current interval.
|
||||
} while (tempEnd && aReplacedInterval &&
|
||||
tempEnd->GetBaseTime() == aReplacedInterval->End());
|
||||
|
||||
// If the last interval ended at the same point and was zero-duration and
|
||||
// this one is too, look for another end to use instead
|
||||
if (tempEnd && tempEnd->Time() == tempBegin->Time() &&
|
||||
prevIntervalWasZeroDur) {
|
||||
tempEnd = GetNextGreater(mEndInstances, tempBegin->Time(), endPos);
|
||||
}
|
||||
|
||||
// If all the ends are before the beginning we have a bad interval UNLESS:
|
||||
// a) We never had any end attribute to begin with (and hence we should
|
||||
// just use the active duration after allowing for the possibility of
|
||||
@ -1695,8 +1693,8 @@ nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
|
||||
// loop. In any case, the interval should be allowed to be open.), OR
|
||||
// c) We have end events which leave the interval open-ended.
|
||||
bool openEndedIntervalOk = mEndSpecs.IsEmpty() ||
|
||||
!HaveDefiniteEndTimes() ||
|
||||
EndHasEventConditions();
|
||||
!HaveDefiniteEndTimes() ||
|
||||
EndHasEventConditions();
|
||||
if (!tempEnd && !openEndedIntervalOk)
|
||||
return false; // Bad interval
|
||||
|
||||
@ -1710,17 +1708,21 @@ nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
|
||||
}
|
||||
NS_ABORT_IF_FALSE(tempEnd, "Failed to get end point for next interval");
|
||||
|
||||
// If we get two zero-length intervals in a row we will potentially have an
|
||||
// infinite loop so we break it here by searching for the next begin time
|
||||
// greater than tempEnd on the next time around.
|
||||
if (tempEnd->Time().IsDefinite() && tempBegin->Time() == tempEnd->Time()) {
|
||||
// When we choose the interval endpoints, we don't allow coincident
|
||||
// zero-duration intervals, so if we arrive here and we have a zero-duration
|
||||
// interval starting at the same point as a previous zero-duration interval,
|
||||
// then it must be because we've applied constraints to the active duration.
|
||||
// In that case, we will potentially run into an infinite loop, so we break
|
||||
// it by searching for the next interval that starts AFTER our current
|
||||
// zero-duration interval.
|
||||
if (prevIntervalWasZeroDur && tempEnd->Time() == beginAfter) {
|
||||
if (prevIntervalWasZeroDur) {
|
||||
beginAfter.SetMillis(tempEnd->Time().GetMillis() + 1);
|
||||
beginAfter.SetMillis(tempBegin->Time().GetMillis() + 1);
|
||||
prevIntervalWasZeroDur = false;
|
||||
continue;
|
||||
}
|
||||
prevIntervalWasZeroDur = true;
|
||||
}
|
||||
prevIntervalWasZeroDur = tempBegin->Time() == tempEnd->Time();
|
||||
|
||||
// Check for valid interval
|
||||
if (tempEnd->Time() > zeroTime ||
|
||||
|
Loading…
Reference in New Issue
Block a user