Bug 373911, r=bz, sr=dbaron, a=1.9+

This commit is contained in:
Olli.Pettay@helsinki.fi 2007-08-21 14:45:00 -07:00
parent 7a9bf4d227
commit d023c05d44
2 changed files with 30 additions and 36 deletions

View File

@ -843,36 +843,38 @@ nsBindingManager::ProcessAttachedQueue()
mAttachedStack.Compact();
}
// Keep bindings and bound elements alive while executing detached handlers.
struct BindingTableReadClosure
{
nsCOMArray<nsIContent> mBoundElements;
nsBindingList mBindings;
};
PR_STATIC_CALLBACK(PLDHashOperator)
AccumulateBindingsToDetach(nsISupports *aKey, nsXBLBinding *aBinding,
void* aVoidArray)
{
nsVoidArray* arr = static_cast<nsVoidArray*>(aVoidArray);
// Hold an owning reference to this binding, just in case
if (arr->AppendElement(aBinding))
NS_ADDREF(aBinding);
void* aClosure)
{
BindingTableReadClosure* closure =
static_cast<BindingTableReadClosure*>(aClosure);
if (aBinding && closure->mBindings.AppendElement(aBinding)) {
if (!closure->mBoundElements.AppendObject(aBinding->GetBoundElement())) {
closure->mBindings.RemoveElementAt(closure->mBindings.Length() - 1);
}
}
return PL_DHASH_NEXT;
}
PR_STATIC_CALLBACK(PRBool)
ExecuteDetachedHandler(void* aBinding, void* aClosure)
{
NS_PRECONDITION(aBinding, "Null binding in list?");
nsXBLBinding* binding = static_cast<nsXBLBinding*>(aBinding);
binding->ExecuteDetachedHandler();
// Drop our ref to the binding now
NS_RELEASE(binding);
return PR_TRUE;
}
void
nsBindingManager::ExecuteDetachedHandlers()
{
// Walk our hashtable of bindings.
if (mBindingTable.IsInitialized()) {
nsVoidArray bindingsToDetach;
mBindingTable.EnumerateRead(AccumulateBindingsToDetach, &bindingsToDetach);
bindingsToDetach.EnumerateForwards(ExecuteDetachedHandler, nsnull);
BindingTableReadClosure closure;
mBindingTable.EnumerateRead(AccumulateBindingsToDetach, &closure);
PRUint32 i, count = closure.mBindings.Length();
for (i = 0; i < count; ++i) {
closure.mBindings[i]->ExecuteDetachedHandler();
}
}
}

View File

@ -4377,7 +4377,11 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
IsSafeToFlush(isSafeToFlush);
NS_ASSERTION(!isSafeToFlush || mViewManager, "Must have view manager");
if (isSafeToFlush && mViewManager) {
// Make sure the view manager stays alive while batching view updates.
// XXX FIXME: If viewmanager hierarchy is modified while we're in update
// batch... We need to address that somehow. See bug 369165.
nsCOMPtr<nsIViewManager> viewManager = mViewManager;
if (isSafeToFlush && viewManager) {
// Processing pending notifications can kill us, and some callers only
// hold weak refs when calling FlushPendingNotifications(). :(
nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
@ -4385,27 +4389,15 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
// Style reresolves not in conjunction with reflows can't cause
// painting or geometry changes, so don't bother with view update
// batching if we only have style reresolve
mViewManager->BeginUpdateViewBatch();
viewManager->BeginUpdateViewBatch();
if (aType & Flush_StyleReresolves) {
mFrameConstructor->ProcessPendingRestyles();
if (mIsDestroying) {
// We no longer have a view manager and all that.
// XXX FIXME: Except we're in the middle of a view update batch... We
// need to address that somehow. See bug 369165.
return NS_OK;
}
}
if (aType & Flush_OnlyReflow) {
if (aType & Flush_OnlyReflow && !mIsDestroying) {
mFrameConstructor->RecalcQuotesAndCounters();
ProcessReflowCommands(PR_FALSE);
if (mIsDestroying) {
// We no longer have a view manager and all that.
// XXX FIXME: Except we're in the middle of a view update batch... We
// need to address that somehow. See bug 369165.
return NS_OK;
}
}
PRUint32 updateFlags = NS_VMREFRESH_NO_SYNC;
@ -4420,7 +4412,7 @@ PresShell::FlushPendingNotifications(mozFlushType aType)
// at the end of this view batch.
updateFlags = NS_VMREFRESH_DEFERRED;
}
mViewManager->EndUpdateViewBatch(updateFlags);
viewManager->EndUpdateViewBatch(updateFlags);
}
return NS_OK;