diff --git a/content/smil/crashtests/554202-1.svg b/content/smil/crashtests/554202-1.svg new file mode 100644 index 00000000000..f3d692ca029 --- /dev/null +++ b/content/smil/crashtests/554202-1.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + diff --git a/content/smil/crashtests/554202-2.svg b/content/smil/crashtests/554202-2.svg new file mode 100644 index 00000000000..a3bbb3195cb --- /dev/null +++ b/content/smil/crashtests/554202-2.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/content/smil/crashtests/crashtests.list b/content/smil/crashtests/crashtests.list index 6d1f24401f0..25b994300df 100644 --- a/content/smil/crashtests/crashtests.list +++ b/content/smil/crashtests/crashtests.list @@ -10,6 +10,8 @@ load 537157-1.svg load 541297-1.svg load 547333-1.svg load 548899-1.svg +load 554202-1.svg +load 554202-2.svg load 554141-1.svg load 555026-1.svg load 556841-1.svg diff --git a/content/smil/nsSMILInstanceTime.cpp b/content/smil/nsSMILInstanceTime.cpp index 98b2f5a39db..f77b3d25446 100644 --- a/content/smil/nsSMILInstanceTime.cpp +++ b/content/smil/nsSMILInstanceTime.cpp @@ -163,11 +163,10 @@ nsSMILInstanceTime::HandleDeletedInterval() } PRBool -nsSMILInstanceTime::IsDependent(const nsSMILInstanceTime& aOther, - PRUint32 aRecursionDepth) const +nsSMILInstanceTime::IsDependent(const nsSMILInstanceTime& aOther) const { - NS_ABORT_IF_FALSE(aRecursionDepth < 1000, - "We seem to have created a cycle between instance times"); + if (mVisited || mChainEnd) + return PR_FALSE; const nsSMILInstanceTime* myBaseTime = GetBaseTime(); if (!myBaseTime) @@ -176,7 +175,9 @@ nsSMILInstanceTime::IsDependent(const nsSMILInstanceTime& aOther, if (myBaseTime == &aOther) return PR_TRUE; - return myBaseTime->IsDependent(aOther, ++aRecursionDepth); + // mVisited is mutable + AutoBoolSetter setVisited(const_cast(this)->mVisited); + return myBaseTime->IsDependent(aOther); } void @@ -185,8 +186,6 @@ nsSMILInstanceTime::SetBaseInterval(nsSMILInterval* aBaseInterval) NS_ABORT_IF_FALSE(!mBaseInterval, "Attempting to reassociate an instance time with a different interval."); - // Make sure we don't end up creating a cycle between the dependent time - // pointers. if (aBaseInterval) { NS_ABORT_IF_FALSE(mCreator, "Attempting to create a dependent instance time without reference " @@ -194,10 +193,6 @@ nsSMILInstanceTime::SetBaseInterval(nsSMILInterval* aBaseInterval) if (!mCreator) return; - const nsSMILInstanceTime* dependentTime = mCreator->DependsOnBegin() ? - aBaseInterval->Begin() : - aBaseInterval->End(); - dependentTime->BreakPotentialCycle(this); aBaseInterval->AddDependentTime(*this); } @@ -219,21 +214,3 @@ nsSMILInstanceTime::GetBaseTime() const return mCreator->DependsOnBegin() ? mBaseInterval->Begin() : mBaseInterval->End(); } - -void -nsSMILInstanceTime::BreakPotentialCycle( - const nsSMILInstanceTime* aNewTail) const -{ - const nsSMILInstanceTime* myBaseTime = GetBaseTime(); - if (!myBaseTime) - return; - - if (myBaseTime == aNewTail) { - // Making aNewTail the new tail of the chain would create a cycle so we - // prevent this by unlinking the pointer to aNewTail. - mBaseInterval->RemoveDependentTime(*this); - return; - } - - myBaseTime->BreakPotentialCycle(aNewTail); -} diff --git a/content/smil/nsSMILInstanceTime.h b/content/smil/nsSMILInstanceTime.h index 9a010c57c13..14e4f71a52f 100644 --- a/content/smil/nsSMILInstanceTime.h +++ b/content/smil/nsSMILInstanceTime.h @@ -109,8 +109,7 @@ public: mTime = aNewTime; } - PRBool IsDependent(const nsSMILInstanceTime& aOther, - PRUint32 aRecursionDepth = 0) const; + PRBool IsDependent(const nsSMILInstanceTime& aOther) const; PRBool SameTimeAndBase(const nsSMILInstanceTime& aOther) const { @@ -126,7 +125,6 @@ public: protected: void SetBaseInterval(nsSMILInterval* aBaseInterval); - void BreakPotentialCycle(const nsSMILInstanceTime* aNewTail) const; const nsSMILInstanceTime* GetBaseTime() const; nsSMILTimeValue mTime; @@ -155,8 +153,11 @@ protected: PRUint32 mSerial; // A serial number used by the containing class to // specify the sort order for instance times with the // same mTime. - PRPackedBool mVisited; - PRPackedBool mChainEnd; + PRPackedBool mVisited; // (mutable) Cycle tracking + PRPackedBool mChainEnd; // Flag to indicate that this instance time is part + // of some cyclic dependency and that in order to + // avoid infinite recursion the cycle should not be + // followed any further than this point. nsSMILTimeValueSpec* mCreator; // The nsSMILTimeValueSpec object that created // us. (currently only needed for syncbase diff --git a/layout/reftests/svg/smil/syncbase/reftest.list b/layout/reftests/svg/smil/syncbase/reftest.list index e9a25e851e0..effd37fa737 100644 --- a/layout/reftests/svg/smil/syncbase/reftest.list +++ b/layout/reftests/svg/smil/syncbase/reftest.list @@ -83,6 +83,7 @@ == sandwich-priority-9.svg green-box-ref.svg == sandwich-priority-10.svg green-box-ref.svg == sandwich-priority-11.svg green-box-ref.svg +== sandwich-priority-12.svg green-box-ref.svg # Cross-time container dependencies == cross-container-1.xhtml green-box-ref.xhtml diff --git a/layout/reftests/svg/smil/syncbase/sandwich-priority-12.svg b/layout/reftests/svg/smil/syncbase/sandwich-priority-12.svg new file mode 100644 index 00000000000..8164e56fa8f --- /dev/null +++ b/layout/reftests/svg/smil/syncbase/sandwich-priority-12.svg @@ -0,0 +1,24 @@ + + + + + + + +