From 54fdd393405acae62e370647a2f3de721e9be52f Mon Sep 17 00:00:00 2001 From: Neil Rashbrook Date: Tue, 13 Oct 2009 11:11:17 +0100 Subject: [PATCH] Bug 519049 Wrong value broadcast when setting attribute twice while script blocker active r=smaug sr=bz --- content/xul/document/src/nsXULDocument.cpp | 53 +++++++++++----------- content/xul/document/src/nsXULDocument.h | 7 +++ 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index c126c0b19be5..3b210b30dd26 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -1030,36 +1030,35 @@ nsXULDocument::AttributeChanged(nsIDocument* aDocument, = do_QueryReferent(bl->mListener); nsCOMPtr l = do_QueryInterface(listenerEl); if (l) { - 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; + 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); + + PRUint32 index = + mDelayedAttrChangeBroadcasts.IndexOf(delayedUpdate, + 0, nsDelayedBroadcastUpdate::Comparator()); + if (index != mDelayedAttrChangeBroadcasts.NoIndex) { + if (mHandlingDelayedAttrChange) { + NS_WARNING("Broadcasting loop!"); + continue; } + mDelayedAttrChangeBroadcasts.RemoveElementAt(index); } - 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); - } + mDelayedAttrChangeBroadcasts.AppendElement(delayedUpdate); } } } diff --git a/content/xul/document/src/nsXULDocument.h b/content/xul/document/src/nsXULDocument.h index e63f3ede049f..faf50df8292f 100644 --- a/content/xul/document/src/nsXULDocument.h +++ b/content/xul/document/src/nsXULDocument.h @@ -753,6 +753,13 @@ protected: nsCOMPtr mAttrName; PRPackedBool mSetAttr; PRPackedBool mNeedsAttrChange; + + class Comparator { + public: + static PRBool Equals(const nsDelayedBroadcastUpdate& a, const nsDelayedBroadcastUpdate& b) { + return a.mBroadcaster == b.mBroadcaster && a.mListener == b.mListener && a.mAttrName == b.mAttrName; + } + }; }; nsTArray mDelayedBroadcasters;