Bug 639728: Retain temporary owning references to new-style SVGxxxList DOM tearoffs where necessary. r=jwatt

This commit is contained in:
Daniel Holbert 2011-03-29 08:47:53 -07:00
parent d627c1e309
commit 141b29162d
6 changed files with 52 additions and 4 deletions

View File

@ -122,7 +122,13 @@ DOMSVGAnimatedLengthList::InternalBaseValListWillChangeTo(const SVGLengthList& a
// able to access "items" at indexes that are out of bounds (read/write to
// bad memory)!!
nsRefPtr<DOMSVGAnimatedLengthList> kungFuDeathGrip;
if (mBaseVal) {
if (!aNewValue.Length()) {
// InternalListLengthWillChange might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;
}
mBaseVal->InternalListLengthWillChange(aNewValue.Length());
}

View File

@ -121,7 +121,13 @@ DOMSVGAnimatedNumberList::InternalBaseValListWillChangeTo(const SVGNumberList& a
// able to access "items" at indexes that are out of bounds (read/write to
// bad memory)!!
nsRefPtr<DOMSVGAnimatedNumberList> kungFuDeathGrip;
if (mBaseVal) {
if (!aNewValue.Length()) {
// InternalListLengthWillChange might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;
}
mBaseVal->InternalListLengthWillChange(aNewValue.Length());
}

View File

@ -103,6 +103,13 @@ DOMSVGLengthList::InternalListLengthWillChange(PRUint32 aNewLength)
aNewLength = DOMSVGLength::MaxListIndex();
}
nsRefPtr<DOMSVGLengthList> kungFuDeathGrip;
if (oldLength && !aNewLength) {
// RemovingFromList() might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;
}
// If our length will decrease, notify the items that will be removed:
for (PRUint32 i = aNewLength; i < oldLength; ++i) {
if (mItems[i]) {
@ -393,7 +400,9 @@ DOMSVGLengthList::MaybeRemoveItemFromAnimValListAt(PRUint32 aIndex)
{
NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
DOMSVGLengthList* animVal = mAList->mAnimVal;
// This needs to be a strong reference; otherwise, the RemovingFromList call
// below might drop the last reference to animVal before we're done with it.
nsRefPtr<DOMSVGLengthList> animVal = mAList->mAnimVal;
if (!animVal || mAList->IsAnimating()) {
// No animVal list wrapper, or animVal not a clone of baseVal

View File

@ -103,6 +103,13 @@ DOMSVGNumberList::InternalListLengthWillChange(PRUint32 aNewLength)
aNewLength = DOMSVGNumber::MaxListIndex();
}
nsRefPtr<DOMSVGNumberList> kungFuDeathGrip;
if (oldLength && !aNewLength) {
// RemovingFromList() might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;
}
// If our length will decrease, notify the items that will be removed:
for (PRUint32 i = aNewLength; i < oldLength; ++i) {
if (mItems[i]) {
@ -393,7 +400,9 @@ DOMSVGNumberList::MaybeRemoveItemFromAnimValListAt(PRUint32 aIndex)
{
NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
DOMSVGNumberList* animVal = mAList->mAnimVal;
// This needs to be a strong reference; otherwise, the RemovingFromList call
// below might drop the last reference to animVal before we're done with it.
nsRefPtr<DOMSVGNumberList> animVal = mAList->mAnimVal;
if (!animVal || mAList->IsAnimating()) {
// No animVal list wrapper, or animVal not a clone of baseVal

View File

@ -140,6 +140,13 @@ DOMSVGPathSegList::InternalListWillChangeTo(const SVGPathData& aNewValue)
PRUint32 newSegType;
nsRefPtr<DOMSVGPathSegList> kungFuDeathGrip;
if (length && aNewValue.IsEmpty()) {
// RemovingFromList() might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;
}
while (index < length && dataIndex < dataLength) {
newSegType = SVGPathSegUtils::DecodeType(aNewValue.mData[dataIndex]);
if (ItemAt(index) && ItemAt(index)->Type() != newSegType) {
@ -540,7 +547,9 @@ DOMSVGPathSegList::
return;
}
DOMSVGPathSegList *animVal =
// This needs to be a strong reference; otherwise, the RemovingFromList call
// below might drop the last reference to animVal before we're done with it.
nsRefPtr<DOMSVGPathSegList> animVal =
GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
if (!animVal) {
// No animVal list wrapper

View File

@ -132,6 +132,13 @@ DOMSVGPointList::InternalListWillChangeTo(const SVGPointList& aNewValue)
newLength = DOMSVGPoint::MaxListIndex();
}
nsRefPtr<DOMSVGPointList> kungFuDeathGrip;
if (oldLength && !newLength) {
// RemovingFromList() might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;
}
// If our length will decrease, notify the items that will be removed:
for (PRUint32 i = newLength; i < oldLength; ++i) {
if (mItems[i]) {
@ -455,7 +462,9 @@ DOMSVGPointList::MaybeRemoveItemFromAnimValListAt(PRUint32 aIndex)
return;
}
DOMSVGPointList *animVal =
// This needs to be a strong reference; otherwise, the RemovingFromList call
// below might drop the last reference to animVal before we're done with it.
nsRefPtr<DOMSVGPointList> animVal =
GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
if (!animVal) {
// No animVal list wrapper