Unhook event handlers on binding teardown. Bug 403162, r+sr=sicking

git-svn-id: svn://10.0.0.236/trunk@239497 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bzbarsky%mit.edu 2007-11-15 22:29:08 +00:00
parent e3b01917e4
commit c88cd8440d
3 changed files with 45 additions and 36 deletions

View File

@ -848,6 +848,8 @@ nsBindingManager::RemoveLayeredBinding(nsIContent* aContent, nsIURI* aURL)
NS_ASSERTION(doc, "No owner document?");
// Finally remove the binding...
// XXXbz this doesn't remove the implementation! Should fix! Until
// then we need the explicit UnhookEventHandlers here.
binding->UnhookEventHandlers();
binding->ChangeDocument(doc, nsnull);
SetBinding(aContent, nsnull);

View File

@ -972,42 +972,47 @@ nsXBLBinding::UnhookEventHandlers()
nsXBLPrototypeHandler* handlerChain = mPrototypeBinding->GetPrototypeHandlers();
if (handlerChain) {
nsCOMPtr<nsPIDOMEventTarget> piTarget = do_QueryInterface(mBoundElement);
nsCOMPtr<nsIDOM3EventTarget> target = do_QueryInterface(piTarget);
nsCOMPtr<nsIEventListenerManager> manager;
mBoundElement->GetListenerManager(PR_FALSE, getter_AddRefs(manager));
if (!manager) {
return;
}
nsCOMPtr<nsIDOMEventGroup> systemEventGroup;
nsXBLPrototypeHandler* curr;
for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
nsXBLEventHandler* handler = curr->GetCachedEventHandler();
if (handler) {
nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
if (!eventAtom ||
eventAtom == nsGkAtoms::keyup ||
eventAtom == nsGkAtoms::keydown ||
eventAtom == nsGkAtoms::keypress)
continue;
nsAutoString type;
eventAtom->ToString(type);
// Figure out if we're using capturing or not.
PRBool useCapture = (curr->GetPhase() == NS_PHASE_CAPTURING);
// If this is a command, remove it from the system event group, otherwise
// remove it from the standard event group.
// This is a weak ref. systemEventGroup above is already a
// strong ref, so we are guaranteed it will not go away.
nsIDOMEventGroup* eventGroup = nsnull;
if (curr->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) {
if (!systemEventGroup)
piTarget->GetSystemEventGroup(getter_AddRefs(systemEventGroup));
eventGroup = systemEventGroup;
}
target->RemoveGroupedEventListener(type, handler, useCapture,
eventGroup);
if (!handler) {
continue;
}
nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
if (!eventAtom ||
eventAtom == nsGkAtoms::keyup ||
eventAtom == nsGkAtoms::keydown ||
eventAtom == nsGkAtoms::keypress)
continue;
nsAutoString type;
eventAtom->ToString(type);
// Figure out if we're using capturing or not.
PRInt32 flags = (curr->GetPhase() == NS_PHASE_CAPTURING) ?
NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
// If this is a command, remove it from the system event group,
// otherwise remove it from the standard event group.
// This is a weak ref. systemEventGroup above is already a
// strong ref, so we are guaranteed it will not go away.
nsIDOMEventGroup* eventGroup = nsnull;
if (curr->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) {
if (!systemEventGroup)
manager->GetSystemEventGroupLM(getter_AddRefs(systemEventGroup));
eventGroup = systemEventGroup;
}
manager->RemoveEventListenerByType(handler, type, flags, eventGroup);
}
const nsCOMArray<nsXBLKeyEventHandler>* keyHandlers =
@ -1020,7 +1025,8 @@ nsXBLBinding::UnhookEventHandlers()
handler->GetEventName(type);
// Figure out if we're using capturing or not.
PRBool useCapture = (handler->GetPhase() == NS_PHASE_CAPTURING);
PRInt32 flags = (handler->GetPhase() == NS_PHASE_CAPTURING) ?
NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
// If this is a command, remove it from the system event group, otherwise
// remove it from the standard event group.
@ -1030,12 +1036,11 @@ nsXBLBinding::UnhookEventHandlers()
nsIDOMEventGroup* eventGroup = nsnull;
if (handler->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) {
if (!systemEventGroup)
piTarget->GetSystemEventGroup(getter_AddRefs(systemEventGroup));
manager->GetSystemEventGroupLM(getter_AddRefs(systemEventGroup));
eventGroup = systemEventGroup;
}
target->RemoveGroupedEventListener(type, handler, useCapture,
eventGroup);
manager->RemoveEventListenerByType(handler, type, flags, eventGroup);
}
}
}
@ -1126,6 +1131,9 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen
}
}
}
// Remove our event handlers
UnhookEventHandlers();
}
// Then do our ancestors. This reverses the construction order, so that at

View File

@ -589,7 +589,6 @@ nsXBLService::FlushStyleBindings(nsIContent* aContent)
if (styleBinding) {
// Clear out the script references.
styleBinding->UnhookEventHandlers();
styleBinding->ChangeDocument(document, nsnull);
}