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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user