зеркало из https://github.com/mozilla/pjs.git
Bug 386802, Mutation events always fired during setting of innerHTML, r+sr=bz
This commit is contained in:
Родитель
7269d880ea
Коммит
5d525ee576
|
@ -780,14 +780,19 @@ public:
|
|||
/**
|
||||
* Quick helper to determine whether there are any mutation listeners
|
||||
* of a given type that apply to this content or any of its ancestors.
|
||||
* The method has the side effect to call document's MayDispatchMutationEvent
|
||||
* using aTargetForSubtreeModified as the parameter.
|
||||
*
|
||||
* @param aNode The node to search for listeners
|
||||
* @param aType The type of listener (NS_EVENT_BITS_MUTATION_*)
|
||||
* @param aTargetForSubtreeModified The node which is the target of the
|
||||
* possible DOMSubtreeModified event.
|
||||
*
|
||||
* @return true if there are mutation listeners of the specified type
|
||||
*/
|
||||
static PRBool HasMutationListeners(nsINode* aNode,
|
||||
PRUint32 aType);
|
||||
PRUint32 aType,
|
||||
nsINode* aTargetForSubtreeModified);
|
||||
|
||||
/**
|
||||
* This method creates and dispatches a trusted event.
|
||||
|
|
|
@ -95,8 +95,9 @@ class mozAutoSubtreeModified;
|
|||
|
||||
// IID for the nsIDocument interface
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0x7dd5790f, 0x110d, 0x4bf6, \
|
||||
{ 0x83, 0x50, 0x4b, 0xe3, 0x5d, 0xdc, 0xe1, 0x1e } }
|
||||
{ 0x6700e22b, 0x95b8, 0x44cf, \
|
||||
{ 0x8f, 0x5a, 0x57, 0x2c, 0x14, 0x5b, 0xd1, 0xa1 } }
|
||||
|
||||
|
||||
// Flag for AddStyleSheet().
|
||||
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
|
||||
|
@ -851,9 +852,13 @@ public:
|
|||
virtual void FlushSkinBindings() = 0;
|
||||
|
||||
/**
|
||||
* Returns PR_TRUE if one or more mutation events are being dispatched.
|
||||
* To batch DOMSubtreeModified, document needs to be informed when
|
||||
* a mutation event might be dispatched, even if the event isn't actually
|
||||
* created because there are no listeners for it.
|
||||
*
|
||||
* @param aTarget is the target for the mutation event.
|
||||
*/
|
||||
virtual PRBool MutationEventBeingDispatched() = 0;
|
||||
virtual void MayDispatchMutationEvent(nsINode* aTarget) = 0;
|
||||
|
||||
/**
|
||||
* Marks as not-going-to-be-collected for the given generation of
|
||||
|
|
|
@ -2978,18 +2978,15 @@ nsContentUtils::HasNonEmptyAttr(nsIContent* aContent, PRInt32 aNameSpaceID,
|
|||
/* static */
|
||||
PRBool
|
||||
nsContentUtils::HasMutationListeners(nsINode* aNode,
|
||||
PRUint32 aType)
|
||||
PRUint32 aType,
|
||||
nsINode* aTargetForSubtreeModified)
|
||||
{
|
||||
nsIDocument* doc = aNode->GetOwnerDoc();
|
||||
if (!doc) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// To batch DOMSubtreeModified properly, all mutation events should be
|
||||
// processed if one is being processed already.
|
||||
if (doc->MutationEventBeingDispatched()) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
doc->MayDispatchMutationEvent(aTargetForSubtreeModified);
|
||||
|
||||
// global object will be null for documents that don't have windows.
|
||||
nsCOMPtr<nsPIDOMWindow> window;
|
||||
|
|
|
@ -5662,6 +5662,14 @@ nsDocument::OnPageHide(PRBool aPersisted)
|
|||
mVisible = PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::MayDispatchMutationEvent(nsINode* aTarget)
|
||||
{
|
||||
if (mSubtreeModifiedDepth > 0) {
|
||||
mSubtreeModifiedTargets.AppendObject(aTarget);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::WillDispatchMutationEvent(nsINode* aTarget)
|
||||
{
|
||||
|
@ -5670,7 +5678,12 @@ nsDocument::WillDispatchMutationEvent(nsINode* aTarget)
|
|||
"mSubtreeModifiedTargets not cleared after dispatching?");
|
||||
++mSubtreeModifiedDepth;
|
||||
if (aTarget) {
|
||||
mSubtreeModifiedTargets.AppendObject(aTarget);
|
||||
// MayDispatchMutationEvent is often called just before this method,
|
||||
// so it has already appended the node to mSubtreeModifiedTargets.
|
||||
PRInt32 count = mSubtreeModifiedTargets.Count();
|
||||
if (!count || mSubtreeModifiedTargets[count - 1] != aTarget) {
|
||||
mSubtreeModifiedTargets.AppendObject(aTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -507,12 +507,9 @@ public:
|
|||
virtual void OnPageShow(PRBool aPersisted);
|
||||
virtual void OnPageHide(PRBool aPersisted);
|
||||
|
||||
virtual void MayDispatchMutationEvent(nsINode* aTarget);
|
||||
virtual void WillDispatchMutationEvent(nsINode* aTarget);
|
||||
virtual void MutationEventDispatched(nsINode* aTarget);
|
||||
virtual PRBool MutationEventBeingDispatched()
|
||||
{
|
||||
return (mSubtreeModifiedDepth > 0);
|
||||
}
|
||||
|
||||
// nsINode
|
||||
virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
|
||||
|
|
|
@ -409,7 +409,8 @@ nsGenericDOMDataNode::SetTextInternal(PRUint32 aOffset, PRUint32 aCount,
|
|||
|
||||
PRBool haveMutationListeners = aNotify &&
|
||||
nsContentUtils::HasMutationListeners(this,
|
||||
NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED);
|
||||
NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED,
|
||||
this);
|
||||
|
||||
nsCOMPtr<nsIAtom> oldValue;
|
||||
if (haveMutationListeners) {
|
||||
|
|
|
@ -2637,7 +2637,7 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
|||
}
|
||||
|
||||
if (nsContentUtils::HasMutationListeners(aKid,
|
||||
NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
|
||||
NS_EVENT_BITS_MUTATION_NODEINSERTED, container)) {
|
||||
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEINSERTED);
|
||||
mutation.mRelatedNode = do_QueryInterface(container);
|
||||
mozAutoSubtreeModified subtree(container->GetOwnerDoc(), container);
|
||||
|
@ -2688,7 +2688,7 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
|
|||
mozAutoSubtreeModified subtree(nsnull, nsnull);
|
||||
if (aNotify &&
|
||||
nsContentUtils::HasMutationListeners(aKid,
|
||||
NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
|
||||
NS_EVENT_BITS_MUTATION_NODEREMOVED, container)) {
|
||||
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEREMOVED);
|
||||
mutation.mRelatedNode = do_QueryInterface(container);
|
||||
subtree.UpdateTarget(container->GetOwnerDoc(), container);
|
||||
|
@ -3521,7 +3521,8 @@ nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
|
|||
PRBool modification = PR_FALSE;
|
||||
PRBool hasListeners = aNotify &&
|
||||
nsContentUtils::HasMutationListeners(this,
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
|
||||
this);
|
||||
|
||||
// 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
|
||||
|
@ -3813,7 +3814,8 @@ nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
|
||||
PRBool hasMutationListeners = aNotify &&
|
||||
nsContentUtils::HasMutationListeners(this,
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
|
||||
this);
|
||||
|
||||
// Grab the attr node if needed before we remove it from the attr map
|
||||
nsCOMPtr<nsIDOMAttr> attrNode;
|
||||
|
|
|
@ -1540,7 +1540,8 @@ nsGenericHTMLElement::SetInlineStyleRule(nsICSSStyleRule* aStyleRule,
|
|||
|
||||
PRBool hasListeners = aNotify &&
|
||||
nsContentUtils::HasMutationListeners(this,
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
|
||||
this);
|
||||
|
||||
// There's no point in comparing the stylerule pointers since we're always
|
||||
// getting a new stylerule here. And we can't compare the stringvalues of
|
||||
|
|
|
@ -337,7 +337,8 @@ nsSVGElement::SetInlineStyleRule(nsICSSStyleRule* aStyleRule, PRBool aNotify)
|
|||
|
||||
PRBool hasListeners = aNotify &&
|
||||
nsContentUtils::HasMutationListeners(this,
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
|
||||
this);
|
||||
|
||||
// There's no point in comparing the stylerule pointers since we're always
|
||||
// getting a new stylerule here. And we can't compare the stringvalues of
|
||||
|
@ -639,7 +640,8 @@ nsSVGElement::DidModifySVGObservable(nsISVGValue* aObservable,
|
|||
PRBool modification = PR_FALSE;
|
||||
PRBool hasListeners =
|
||||
nsContentUtils::HasMutationListeners(this,
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
|
||||
this);
|
||||
|
||||
if (hasListeners || IsInDoc()) {
|
||||
modification = !!mAttrsAndChildren.GetAttr(attrName->LocalName(),
|
||||
|
|
|
@ -1238,7 +1238,7 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
|
|||
|
||||
PRBool hasMutationListeners = aNotify &&
|
||||
nsContentUtils::HasMutationListeners(this,
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED, this);
|
||||
|
||||
nsCOMPtr<nsIDOMAttr> attrNode;
|
||||
if (hasMutationListeners) {
|
||||
|
@ -1666,7 +1666,8 @@ nsXULElement::SetInlineStyleRule(nsICSSStyleRule* aStyleRule, PRBool aNotify)
|
|||
|
||||
PRBool hasListeners = aNotify &&
|
||||
nsContentUtils::HasMutationListeners(this,
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
|
||||
this);
|
||||
|
||||
// There's no point in comparing the stylerule pointers since we're always
|
||||
// getting a new stylerule here. And we can't compare the stringvalues of
|
||||
|
|
Загрузка…
Ссылка в новой задаче