Dispatch mutation events even in documents that are not rendered in a window.

Bug 201236, patch by Alex Vincent <ajvincent@gmail.com>, r=smaug, sr=peterv
This commit is contained in:
bzbarsky@mit.edu
2006-04-24 19:52:21 +00:00
parent 18ff48f43e
commit f5e004636c
8 changed files with 154 additions and 119 deletions

View File

@@ -2352,11 +2352,11 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
aDocument->ContentInserted(aParent, aKid, aIndex);
}
}
// XXXbz how come we're not firing mutation listeners for adding to
// documents?
if (aParent &&
HasMutationListeners(aParent, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
PRBool hasListeners =
nsContentUtils::HasMutationListeners(aParent,
aDocument,
NS_EVENT_BITS_MUTATION_NODEINSERTED);
if (hasListeners) {
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEINSERTED);
mutation.mRelatedNode = do_QueryInterface(aParent);
nsEventDispatcher::Dispatch(aKid, nsnull, &mutation);
@@ -2417,7 +2417,8 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
nsMutationGuard guard;
if (aParent && nsGenericElement::HasMutationListeners(aParent,
if (nsContentUtils::HasMutationListeners(aParent,
aDocument,
NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEREMOVED);
mutation.mRelatedNode = do_QueryInterface(aParent);
@@ -3316,53 +3317,6 @@ nsGenericElement::CloneChildrenTo(nsGenericElement *aDst) const
return NS_OK;
}
static PRBool
NodeHasMutationListeners(nsISupports* aNode)
{
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(aNode));
if (rec) {
nsCOMPtr<nsIEventListenerManager> manager;
rec->GetListenerManager(PR_FALSE, getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
return PR_FALSE;
}
// Static helper method
PRBool
nsGenericElement::HasMutationListeners(nsIContent* aContent, PRUint32 aType)
{
nsIDocument* doc = aContent->GetDocument();
if (!doc)
return PR_FALSE;
nsIScriptGlobalObject *global = doc->GetScriptGlobalObject();
if (!global)
return PR_FALSE;
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(global));
if (!window)
return PR_FALSE;
if (!window->HasMutationListeners(aType))
return PR_FALSE;
// We know a mutation listener is registered, but it might not
// be in our chain. Check quickly to see.
for (nsIContent* curr = aContent; curr; curr = curr->GetParent())
if (NodeHasMutationListeners(curr))
return PR_TRUE;
return NodeHasMutationListeners(doc) || NodeHasMutationListeners(window);
}
nsresult
nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
@@ -3372,6 +3326,7 @@ nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
"Don't call SetAttr with unknown namespace");
nsIDocument* doc = GetCurrentDoc();
if (kNameSpaceID_XLink == aNamespaceID && nsHTMLAtoms::href == aName) {
// XLink URI(s) might be changing. Drop the link from the map. If it
// is still style relevant it will be re-added by
@@ -3380,20 +3335,17 @@ nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
// were to get smarter and not restyling an XLink element if the href
// doesn't change in a "significant" way, we'd need to do the same
// significance check here.
nsIDocument* doc = GetCurrentDoc();
if (doc) {
doc->ForgetLink(this);
}
}
nsAutoString oldValue;
PRBool hasListeners = PR_FALSE;
PRBool modification = PR_FALSE;
if (IsInDoc()) {
hasListeners =
HasMutationListeners(this, NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
}
PRBool hasListeners =
nsContentUtils::HasMutationListeners(this,
doc,
NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
// If we have no listeners and aNotify is false, we are almost certainly
// coming from the content sink and will almost certainly have no previous
@@ -3678,7 +3630,11 @@ nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
document->AttributeWillChange(this, aNameSpaceID, aName);
}
if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
PRBool hasListeners =
nsContentUtils::HasMutationListeners(this,
document,
NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
if (hasListeners) {
nsCOMPtr<nsIDOMEventTarget> node =
do_QueryInterface(NS_STATIC_CAST(nsIContent *, this));
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_ATTRMODIFIED);