Bug 470687, try to prevent broadcaster loops, r=enndeakin, sr=neil

This commit is contained in:
Olli Pettay 2009-01-07 15:25:29 +02:00
Родитель 381075cef6
Коммит 53e7324549
2 изменённых файлов: 44 добавлений и 31 удалений

Просмотреть файл

@ -1021,23 +1021,36 @@ nsXULDocument::AttributeChanged(nsIDocument* aDocument,
= do_QueryReferent(bl->mListener);
nsCOMPtr<nsIContent> l = do_QueryInterface(listenerEl);
if (l) {
nsAutoString currentValue;
PRBool hasAttr = l->GetAttr(kNameSpaceID_None,
aAttribute,
currentValue);
// We need to update listener only if we're
// (1) removing an existing attribute,
// (2) adding a new attribute or
// (3) changing the value of an attribute.
PRBool needsAttrChange =
attrSet != hasAttr || !value.Equals(currentValue);
nsDelayedBroadcastUpdate delayedUpdate(domele,
listenerEl,
aAttribute,
value,
attrSet,
needsAttrChange);
mDelayedAttrChangeBroadcasts.AppendElement(delayedUpdate);
PRBool possibleCycle = PR_FALSE;
for (PRUint32 j = 0; j < mDelayedAttrChangeBroadcasts.Length(); ++j) {
if (mDelayedAttrChangeBroadcasts[j].mListener == listenerEl &&
mDelayedAttrChangeBroadcasts[j].mAttrName == aAttribute) {
possibleCycle = PR_TRUE;
break;
}
}
if (possibleCycle) {
NS_WARNING("Broadcasting loop!");
} else {
nsAutoString currentValue;
PRBool hasAttr = l->GetAttr(kNameSpaceID_None,
aAttribute,
currentValue);
// We need to update listener only if we're
// (1) removing an existing attribute,
// (2) adding a new attribute or
// (3) changing the value of an attribute.
PRBool needsAttrChange =
attrSet != hasAttr || !value.Equals(currentValue);
nsDelayedBroadcastUpdate delayedUpdate(domele,
listenerEl,
aAttribute,
value,
attrSet,
needsAttrChange);
mDelayedAttrChangeBroadcasts.AppendElement(delayedUpdate);
}
}
}
}
@ -3289,18 +3302,15 @@ nsXULDocument::EndUpdate(nsUpdateType aUpdateType)
{
nsXMLDocument::EndUpdate(aUpdateType);
if (mUpdateNestLevel == 0) {
PRUint32 length = mDelayedAttrChangeBroadcasts.Length();
if (length) {
nsTArray<nsDelayedBroadcastUpdate> delayedAttrChangeBroadcasts;
mDelayedAttrChangeBroadcasts.SwapElements(
delayedAttrChangeBroadcasts);
for (PRUint32 i = 0; i < length; ++i) {
nsIAtom* attrName = delayedAttrChangeBroadcasts[i].mAttrName;
if (delayedAttrChangeBroadcasts[i].mNeedsAttrChange) {
if (!mHandlingDelayedAttrChange) {
mHandlingDelayedAttrChange = PR_TRUE;
for (PRUint32 i = 0; i < mDelayedAttrChangeBroadcasts.Length(); ++i) {
nsIAtom* attrName = mDelayedAttrChangeBroadcasts[i].mAttrName;
if (mDelayedAttrChangeBroadcasts[i].mNeedsAttrChange) {
nsCOMPtr<nsIContent> listener =
do_QueryInterface(delayedAttrChangeBroadcasts[i].mListener);
nsString value = delayedAttrChangeBroadcasts[i].mAttr;
if (delayedAttrChangeBroadcasts[i].mSetAttr) {
do_QueryInterface(mDelayedAttrChangeBroadcasts[i].mListener);
nsString value = mDelayedAttrChangeBroadcasts[i].mAttr;
if (mDelayedAttrChangeBroadcasts[i].mSetAttr) {
listener->SetAttr(kNameSpaceID_None, attrName, value,
PR_TRUE);
} else {
@ -3309,14 +3319,16 @@ nsXULDocument::EndUpdate(nsUpdateType aUpdateType)
}
}
nsCOMPtr<nsIContent> broadcaster =
do_QueryInterface(delayedAttrChangeBroadcasts[i].mBroadcaster);
do_QueryInterface(mDelayedAttrChangeBroadcasts[i].mBroadcaster);
ExecuteOnBroadcastHandlerFor(broadcaster,
delayedAttrChangeBroadcasts[i].mListener,
mDelayedAttrChangeBroadcasts[i].mListener,
attrName);
}
mDelayedAttrChangeBroadcasts.Clear();
mHandlingDelayedAttrChange = PR_FALSE;
}
length = mDelayedBroadcasters.Length();
PRUint32 length = mDelayedBroadcasters.Length();
if (length) {
nsTArray<nsDelayedBroadcastUpdate> delayedBroadcasters;
mDelayedBroadcasters.SwapElements(delayedBroadcasters);

Просмотреть файл

@ -734,6 +734,7 @@ protected:
nsTArray<nsDelayedBroadcastUpdate> mDelayedBroadcasters;
nsTArray<nsDelayedBroadcastUpdate> mDelayedAttrChangeBroadcasts;
PRBool mHandlingDelayedAttrChange;
private:
// helpers