Bug 678847 part 2 - SMIL: Fix recursion with self-referential end conditions on open intervals; r=dholbert
authorBrian Birtles <birtles@gmail.com>
Fri, 02 Sep 2011 08:14:58 +0900
changeset 77739 246f74de583c9715c01e94e4450102078f87ff14
parent 77738 7a01e603335dc905ddda0e6690d09a1e45e1f7bb
child 77740 b6608d4de5f7f225c43cb637e324eb34f190533f
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs678847
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 678847 part 2 - SMIL: Fix recursion with self-referential end conditions on open intervals; r=dholbert
content/smil/nsSMILTimedElement.cpp
content/smil/nsSMILTimedElement.h
--- a/content/smil/nsSMILTimedElement.cpp
+++ b/content/smil/nsSMILTimedElement.cpp
@@ -1679,24 +1679,25 @@ nsSMILTimedElement::GetNextInterval(cons
           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
       //    an end instance provided by a DOM call), OR
-      // b) We have an end attribute but no end instances--this is a special
-      //    case that is needed for syncbase timing so that animations of the
-      //    following sort: <animate id="a" end="a.begin+1s" ... /> can be
-      //    resolved (see SVGT 1.2 Test Suite animate-elem-221-t.svg) by first
-      //    establishing an interval of unresolved duration, OR
+      // b) We have no resolved (not incl. indefinite) end instances
+      //    (SMIL only says "if the instance list is empty"--but if we have
+      //    indefinite/unresolved instance times then there must be a good
+      //    reason we haven't used them (since they'll be >= tempBegin) such as
+      //    avoiding creating a self-referential loop. In any case, the interval
+      //    should be allowed to be open.), OR
       // c) We have end events which leave the interval open-ended.
       PRBool openEndedIntervalOk = mEndSpecs.IsEmpty() ||
-                                   mEndInstances.IsEmpty() ||
+                                   !HaveResolvedEndTimes() ||
                                    EndHasEventConditions();
       if (!tempEnd && !openEndedIntervalOk)
         return PR_FALSE; // Bad interval
 
       nsSMILTimeValue intervalEnd = tempEnd
                                   ? tempEnd->Time() : nsSMILTimeValue();
       nsSMILTimeValue activeEnd = CalcActiveEnd(tempBegin->Time(), intervalEnd);
 
@@ -2244,16 +2245,27 @@ const nsSMILInterval*
 nsSMILTimedElement::GetPreviousInterval() const
 {
   return mOldIntervals.IsEmpty()
     ? nsnull
     : mOldIntervals[mOldIntervals.Length()-1].get();
 }
 
 PRBool
+nsSMILTimedElement::HaveResolvedEndTimes() const
+{
+  if (mEndInstances.IsEmpty())
+    return PR_FALSE;
+
+  // mEndInstances is sorted so if the first time is not resolved then none of
+  // them are
+  return mEndInstances[0]->Time().IsResolved();
+}
+
+PRBool
 nsSMILTimedElement::EndHasEventConditions() const
 {
   for (PRUint32 i = 0; i < mEndSpecs.Length(); ++i) {
     if (mEndSpecs[i]->IsEventBased())
       return PR_TRUE;
   }
   return PR_FALSE;
 }
--- a/content/smil/nsSMILTimedElement.h
+++ b/content/smil/nsSMILTimedElement.h
@@ -520,16 +520,17 @@ protected:
   void              NotifyChangedInterval(nsSMILInterval* aInterval,
                                           PRBool aBeginObjectChanged,
                                           PRBool aEndObjectChanged);
 
   void              FireTimeEventAsync(PRUint32 aMsg, PRInt32 aDetail);
   const nsSMILInstanceTime* GetEffectiveBeginInstance() const;
   const nsSMILInterval* GetPreviousInterval() const;
   PRBool            HasPlayed() const { return !mOldIntervals.IsEmpty(); }
+  PRBool            HaveResolvedEndTimes() const;
   PRBool            EndHasEventConditions() const;
 
   // Reset the current interval by first passing ownership to a temporary
   // variable so that if Unlink() results in us receiving a callback,
   // mCurrentInterval will be nsnull and we will be in a consistent state.
   void ResetCurrentInterval()
   {
     if (mCurrentInterval) {