Bug 401463 and others. Make us call InstallImplementation in more places in order to behave more like we did when InstallImplementation was called during LoadBindings. r/sr=jst

This commit is contained in:
jonas@sicking.cc 2007-10-31 16:35:51 -07:00
parent 07f4756c14
commit 7fd1b7262b
2 changed files with 53 additions and 22 deletions

View File

@ -404,7 +404,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsBindingManager)
// Constructors/Destructors
nsBindingManager::nsBindingManager(nsIDocument* aDocument)
: mProcessingAttachedStack(PR_FALSE),
mProcessOnEndUpdate(PR_FALSE),
mAttachedStackSizeOnOutermost(0),
mDocument(aDocument)
{
mContentListTable.ops = nsnull;
@ -510,7 +510,12 @@ nsBindingManager::SetBinding(nsIContent* aContent, nsXBLBinding* aBinding)
aContent->UnsetFlags(NODE_IS_INSERTION_PARENT);
}
}
mAttachedStack.RemoveElement(oldBinding);
// Don't remove items here as that could mess up an executing
// ProcessAttachedQueue
PRUint32 index = mAttachedStack.IndexOf(oldBinding);
if (index != mAttachedStack.NoIndex) {
mAttachedStack[index] = nsnull;
}
}
PRBool result = PR_TRUE;
@ -923,30 +928,46 @@ nsBindingManager::DoProcessAttachedQueue()
}
void
nsBindingManager::ProcessAttachedQueue()
nsBindingManager::ProcessAttachedQueue(PRUint32 aSkipSize)
{
if (mProcessingAttachedStack || mAttachedStack.Length() == 0)
if (mProcessingAttachedStack || mAttachedStack.Length() <= aSkipSize)
return;
mProcessingAttachedStack = PR_TRUE;
PRInt32 lastItem;
while ((lastItem = mAttachedStack.Length() - 1) >= 0) {
nsRefPtr<nsXBLBinding> binding = mAttachedStack.ElementAt(lastItem);
mAttachedStack.RemoveElementAt(lastItem);
NS_ASSERTION(binding, "null item in attached stack?");
nsresult rv = binding->EnsureScriptAPI();
if (NS_FAILED(rv)) {
return;
PRUint32 currentIndex = aSkipSize;
while (mAttachedStack.Length() > aSkipSize) {
// First install all implementations. Do this from low index to high
// since that way we'll automatically get any new bindings added in the
// process.
for (; currentIndex < mAttachedStack.Length(); ++currentIndex) {
nsRefPtr<nsXBLBinding> binding = mAttachedStack.ElementAt(currentIndex);
if (binding) {
nsresult rv = binding->EnsureScriptAPI();
if (NS_FAILED(rv)) {
mAttachedStack[currentIndex] = nsnull;
}
}
}
binding->ExecuteAttachedHandler();
// Then excute constructors. Do this from high index to low
while (currentIndex > aSkipSize && currentIndex == mAttachedStack.Length()) {
--currentIndex;
nsRefPtr<nsXBLBinding> binding = mAttachedStack.ElementAt(currentIndex);
mAttachedStack.RemoveElementAt(currentIndex);
if (binding) {
binding->ExecuteAttachedHandler();
}
}
}
mProcessingAttachedStack = PR_FALSE;
// If NodeWillBeDestroyed has run we don't want to clobber
// mProcessingAttachedStack set there.
if (mDocument) {
mProcessingAttachedStack = PR_FALSE;
}
NS_ASSERTION(mAttachedStack.Length() == 0, "How did we get here?");
NS_ASSERTION(mAttachedStack.Length() == aSkipSize, "How did we get here?");
mAttachedStack.Compact();
}
@ -1534,14 +1555,24 @@ nsBindingManager::Traverse(nsIContent *aContent,
void
nsBindingManager::BeginOutermostUpdate()
{
mProcessOnEndUpdate = (mAttachedStack.Length() == 0);
mAttachedStackSizeOnOutermost = mAttachedStack.Length();
}
void
nsBindingManager::EndOutermostUpdate()
{
if (mProcessOnEndUpdate) {
mProcessOnEndUpdate = PR_FALSE;
ProcessAttachedQueue();
if (!mProcessingAttachedStack) {
ProcessAttachedQueue(mAttachedStackSizeOnOutermost);
mAttachedStackSizeOnOutermost = 0;
}
else {
PRUint32 i = mAttachedStackSizeOnOutermost;
for (; i < mAttachedStack.Length(); ++i) {
nsRefPtr<nsXBLBinding> binding = mAttachedStack[i];
nsresult rv = binding->EnsureScriptAPI();
if (NS_FAILED(rv)) {
mAttachedStack[i] = nsnull;
}
}
}
}

View File

@ -162,7 +162,7 @@ public:
nsIPrincipal* aOriginPrincipal);
nsresult AddToAttachedQueue(nsXBLBinding* aBinding);
void ProcessAttachedQueue();
void ProcessAttachedQueue(PRUint32 aSkipSize = 0);
void ExecuteDetachedHandlers();
@ -287,7 +287,7 @@ protected:
// A queue of binding attached event handlers that are awaiting execution.
nsBindingList mAttachedStack;
PRPackedBool mProcessingAttachedStack;
PRPackedBool mProcessOnEndUpdate;
PRUint32 mAttachedStackSizeOnOutermost;
// Our posted event to process the attached queue, if any
friend class nsRunnableMethod<nsBindingManager>;