Bug 342062: Add nsIMutationObserver which has the ability to get notifications for just mutations happening in a subtree under a given node. r/sr=bz

This commit is contained in:
cvshook%sicking.cc 2006-07-02 07:23:10 +00:00
Родитель 837ba0868b
Коммит 2c39937d84
62 изменённых файлов: 1292 добавлений и 1023 удалений

Просмотреть файл

@ -125,6 +125,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocAccessible)
NS_INTERFACE_MAP_ENTRY(nsIAccessibleDocument)
NS_INTERFACE_MAP_ENTRY(nsPIAccessibleDocument)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY(nsIScrollPositionListener)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessibleDocument)

Просмотреть файл

@ -56,6 +56,7 @@ nsContentUtils.h \
nsIDocument.h \
nsIDocumentObserver.h \
nsIDOMGCParticipant.h \
nsIMutationObserver.h \
nsINameSpaceManager.h \
nsINode.h \
nsINodeInfo.h \

Просмотреть файл

@ -46,8 +46,8 @@ class nsDOMAttributeMap;
class nsIContent;
#define NS_IATTRIBUTE_IID \
{ 0xb65ca480, 0xca76, 0x495c, \
{ 0x95, 0xe4, 0x8c, 0xd0, 0x55, 0x5d, 0xd3, 0x13 } }
{ 0x5a3fa236, 0x9249, 0x4949, \
{ 0x86, 0xb4, 0x98, 0xc1, 0x86, 0xb3, 0xe5, 0x50 } }
class nsIAttribute : public nsINode
{

Просмотреть файл

@ -91,8 +91,8 @@ class nsIDocumentObserver;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{ 0xffa1f165, 0x8b0e, 0x4010, \
{ 0xb6, 0xec, 0x6f, 0x49, 0x6b, 0x1b, 0x30, 0x3a } }
{ 0xd14c81b1, 0x029e, 0x4c01, \
{ 0x8f, 0xfc, 0x42, 0xc1, 0xe1, 0x34, 0x0f, 0xe4 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -529,27 +529,11 @@ public:
virtual void EndUpdate(nsUpdateType aUpdateType) = 0;
virtual void BeginLoad() = 0;
virtual void EndLoad() = 0;
virtual void CharacterDataChanged(nsIContent* aContent, PRBool aAppend) = 0;
// notify that one or two content nodes changed state
// either may be nsnull, but not both
virtual void ContentStatesChanged(nsIContent* aContent1,
nsIContent* aContent2,
PRInt32 aStateMask) = 0;
virtual void AttributeWillChange(nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute) = 0;
virtual void AttributeChanged(nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType) = 0;
virtual void ContentAppended(nsIContent* aContainer,
PRInt32 aNewIndexInContainer) = 0;
virtual void ContentInserted(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer) = 0;
virtual void ContentRemoved(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer) = 0;
// Observation hooks for style data to propagate notifications
// to document observers
@ -561,6 +545,13 @@ public:
virtual void StyleRuleRemoved(nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule) = 0;
/**
* Notify document of pending attribute change
*/
virtual void AttributeWillChange(nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute) = 0;
/**
* Flush notifications for this document and its parent documents
* (since those may affect the layout of this one).

Просмотреть файл

@ -38,6 +38,7 @@
#define nsIDocumentObserver_h___
#include "nsISupports.h"
#include "nsIMutationObserver.h"
class nsIAtom;
class nsIContent;
@ -48,8 +49,8 @@ class nsString;
class nsIDocument;
#define NS_IDOCUMENT_OBSERVER_IID \
{ 0x589761bb, 0x9856, 0x42fe, \
{ 0x9b, 0xf9, 0x6a, 0xdf, 0xf4, 0x92, 0x17, 0x05 } }
{ 0x4e14e321, 0xa4bb, 0x49f8, \
{ 0xa5, 0x7a, 0x23, 0x63, 0x66, 0x8d, 0x14, 0xd0 } }
typedef PRUint32 nsUpdateType;
@ -59,7 +60,7 @@ typedef PRUint32 nsUpdateType;
#define UPDATE_ALL (UPDATE_CONTENT_MODEL | UPDATE_STYLE | UPDATE_CONTENT_STATE)
// Document observer interface
class nsIDocumentObserver : public nsISupports
class nsIDocumentObserver : public nsIMutationObserver
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_OBSERVER_IID)
@ -89,26 +90,6 @@ public:
*/
virtual void EndLoad(nsIDocument *aDocument) = 0;
/**
* Notification that the content model has changed. This method is
* called automatically by content objects when their state is changed
* (therefore there is normally no need to invoke this method
* directly). The notification is passed to any
* IDocumentObservers. The notification is passed on to all of the
* document observers. <p>
*
* This notification is not sent when a piece of content is
* added/removed from the document (the other notifications are used
* for that).
*
* @param aDocument The document being observed
* @param aContent the piece of content that changed
* @param aAppend Whether the change was an append
*/
virtual void CharacterDataChanged(nsIDocument *aDocument,
nsIContent* aContent,
PRBool aAppend) = 0;
/**
* Notification that the state of a content node has changed.
* (ie: gained or lost focus, became active or hovered over)
@ -137,76 +118,6 @@ public:
nsIContent* aContent2,
PRInt32 aStateMask) = 0;
/**
* Notification that the content model has changed. This method is called
* automatically by content objects when an attribute's value has changed
* (therefore there is normally no need to invoke this method directly). The
* notification is passed to any IDocumentObservers document observers. <p>
*
* @param aDocument The document being observed
* @param aContent the piece of content whose attribute changed
* @param aAttribute the atom name of the attribute
* @param aModType Whether or not the attribute was added, changed, or removed.
* The constants are defined in nsIDOMMutationEvent.h.
*/
virtual void AttributeChanged(nsIDocument* aDocument,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType) = 0;
/**
* Notifcation that the content model has had data appended to the
* given content object. This method is called automatically by the
* content container objects when a new content object is appended to
* the container (therefore there is normally no need to invoke this
* method directly). The notification is passed on to all of the
* document observers.
*
* @param aDocument The document being observed
* @param aContainer the container that had a new child appended
* @param aNewIndexInContainer the index in the container of the first
* new child
*/
virtual void ContentAppended(nsIDocument *aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer) = 0;
/**
* Notification that content has been inserted. This method is called
* automatically by the content container objects when a new content
* object is inserted in the container (therefore there is normally no
* need to invoke this method directly). The notification is passed on
* to all of the document observers.
*
* @param aDocument The document being observed
* @param aContainer the container that now contains aChild
* @param aChild the child that was inserted
* @param aIndexInContainer the index of the child in the container
*/
virtual void ContentInserted(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer) = 0;
/**
* Content has just been removed. This method is called automatically
* by content container objects when a content object has just been
* removed from the container (therefore there is normally no need to
* invoke this method directly). The notification is passed on to all
* of the document observers.
*
* @param aDocument The document being observed
* @param aContainer the container that had a child removed
* @param aChild the child that was just removed
* @param aIndexInContainer the index of the child in the container
* before it was removed
*/
virtual void ContentRemoved(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer) = 0;
/**
* A StyleSheet has just been added to the document. This method is
* called automatically when a StyleSheet gets added to the
@ -310,15 +221,6 @@ public:
virtual void StyleRuleRemoved(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule) = 0;
/**
* The document is in the process of being destroyed.
* This method is called automatically during document
* destruction.
*
* @param aDocument The document being observed
*/
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
@ -328,29 +230,10 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
virtual void EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType);\
virtual void BeginLoad(nsIDocument* aDocument); \
virtual void EndLoad(nsIDocument* aDocument); \
virtual void CharacterDataChanged(nsIDocument* aDocument, \
nsIContent* aContent, \
PRBool aAppend); \
virtual void ContentStatesChanged(nsIDocument* aDocument, \
nsIContent* aContent1, \
nsIContent* aContent2, \
PRInt32 aStateMask); \
virtual void AttributeChanged(nsIDocument* aDocument, \
nsIContent* aContent, \
PRInt32 aNameSpaceID, \
nsIAtom* aAttribute, \
PRInt32 aModType); \
virtual void ContentAppended(nsIDocument* aDocument, \
nsIContent* aContainer, \
PRInt32 aNewIndexInContainer); \
virtual void ContentInserted(nsIDocument* aDocument, \
nsIContent* aContainer, \
nsIContent* aChild, \
PRInt32 aIndexInContainer); \
virtual void ContentRemoved(nsIDocument* aDocument, \
nsIContent* aContainer, \
nsIContent* aChild, \
PRInt32 aIndexInContainer); \
virtual void StyleSheetAdded(nsIDocument* aDocument, \
nsIStyleSheet* aStyleSheet, \
PRBool aDocumentSheet); \
@ -370,7 +253,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
virtual void StyleRuleRemoved(nsIDocument* aDocument, \
nsIStyleSheet* aStyleSheet, \
nsIStyleRule* aStyleRule); \
virtual void DocumentWillBeDestroyed(nsIDocument* aDocument); \
NS_DECL_NSIMUTATIONOBSERVER
#define NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(_class) \
@ -382,10 +265,7 @@ void \
_class::EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) \
{ \
} \
void \
_class::DocumentWillBeDestroyed(nsIDocument* aDocument) \
{ \
}
NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(_class)
#define NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(_class) \
void \
@ -407,40 +287,7 @@ _class::ContentStatesChanged(nsIDocument* aDocument, \
}
#define NS_IMPL_NSIDOCUMENTOBSERVER_CONTENT(_class) \
void \
_class::CharacterDataChanged(nsIDocument* aDocument, \
nsIContent* aContent, \
PRBool aAppend) \
{ \
} \
void \
_class::AttributeChanged(nsIDocument* aDocument, \
nsIContent* aContent, \
PRInt32 aNameSpaceID, \
nsIAtom* aAttribute, \
PRInt32 aModType) \
{ \
} \
void \
_class::ContentAppended(nsIDocument* aDocument, \
nsIContent* aContainer, \
PRInt32 aNewIndexInContainer) \
{ \
} \
void \
_class::ContentInserted(nsIDocument* aDocument, \
nsIContent* aContainer, \
nsIContent* aChild, \
PRInt32 aIndexInContainer) \
{ \
} \
void \
_class::ContentRemoved(nsIDocument* aDocument, \
nsIContent* aContainer, \
nsIContent* aChild, \
PRInt32 aIndexInContainer) \
{ \
}
NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(_class)
#define NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(_class) \
void \

Просмотреть файл

@ -0,0 +1,224 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsIMutationObserver_h___
#define nsIMutationObserver_h___
#include "nsISupports.h"
class nsIAtom;
class nsIContent;
class nsIDocument;
class nsINode;
#define NS_IMUTATION_OBSERVER_IID \
{ 0x0864a23d, 0x824b, 0x48be, \
{ 0x9d, 0x50, 0xff, 0x30, 0x2f, 0xf2, 0x79, 0xfe } }
// Mutation observer interface
class nsIMutationObserver : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMUTATION_OBSERVER_IID)
/**
* Notification that the node value of a data node (text, cdata, pi, comment)
* has changed.
*
* This notification is not sent when a piece of content is
* added/removed from the document (the other notifications are used
* for that).
*
* @param aDocument The owner-document of aContent. Can be null.
* @param aContent The piece of content that changed. Is never null.
* @param aAppend Whether the change was an append
*/
virtual void CharacterDataChanged(nsIDocument *aDocument,
nsIContent* aContent,
PRBool aAppend) = 0;
/**
* Notification that an attribute of an element has changed.
*
* @param aDocument The owner-document of aContent. Can be null.
* @param aContent The element whose attribute changed
* @param aNameSpaceID The namespace id of the changed attribute
* @param aAttribute The name of the changed attribute
* @param aModType Whether or not the attribute was added, changed, or
* removed. The constants are defined in
* nsIDOMMutationEvent.h.
*/
virtual void AttributeChanged(nsIDocument* aDocument,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType) = 0;
/**
* Notification that one or more content nodes have been appended to the
* child list of another node in the tree.
*
* @param aDocument The owner-document of aContent. Can be null.
* @param aContainer The container that had new children appended. Is never
* null.
* @param aNewIndexInContainer the index in the container of the first
* new child
*/
virtual void ContentAppended(nsIDocument *aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer) = 0;
/**
* Notification that a content node has been inserted as child to another
* node in the tree.
*
* @param aDocument The owner-document of aContent, or, when aContainer
* is null, the container that had the child inserted.
* Can be null.
* @param aContainer The container that had new a child inserted. Can be
* null to indicate that the child was inserted into
* aDocument
* @param aChild The newly inserted child.
* @param aIndexInContainer The index in the container of the new child.
*/
virtual void ContentInserted(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer) = 0;
/**
* Notification that a content node has been removed from the child list of
* another node in the tree.
*
* @param aDocument The owner-document of aContent, or, when aContainer
* is null, the container that had the child removed.
* Can be null.
* @param aContainer The container that had new a child removed. Can be
* null to indicate that the child was removed from
* aDocument.
* @param aChild The child that was removed.
* @param aIndexInContainer The index in the container which the child used
* to have.
*/
virtual void ContentRemoved(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer) = 0;
/**
* The node is in the process of being destroyed. Calling QI on the node is
* not supported, however it is possible to get children and flags through
* nsINode as well as calling IsNodeOfType(eCONTENT) and casting to
* nsIContent to get attributes.
*
* NOTE: This notification is only called on observers registered directly
* on the node. This is because when the node is destroyed it can not have
* any ancestors. If you want to know when a descendant node is being
* removed from the observed node, use the ContentRemoved notification.
*
* @param aNode The node being destroyed.
*/
virtual void NodeWillBeDestroyed(const nsINode *aNode) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIMutationObserver, NS_IMUTATION_OBSERVER_IID)
#define NS_DECL_NSIMUTATIONOBSERVER \
virtual void CharacterDataChanged(nsIDocument* aDocument, \
nsIContent* aContent, \
PRBool aAppend); \
virtual void AttributeChanged(nsIDocument* aDocument, \
nsIContent* aContent, \
PRInt32 aNameSpaceID, \
nsIAtom* aAttribute, \
PRInt32 aModType); \
virtual void ContentAppended(nsIDocument* aDocument, \
nsIContent* aContainer, \
PRInt32 aNewIndexInContainer); \
virtual void ContentInserted(nsIDocument* aDocument, \
nsIContent* aContainer, \
nsIContent* aChild, \
PRInt32 aIndexInContainer); \
virtual void ContentRemoved(nsIDocument* aDocument, \
nsIContent* aContainer, \
nsIContent* aChild, \
PRInt32 aIndexInContainer); \
virtual void NodeWillBeDestroyed(const nsINode* aNode);
#define NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(_class) \
void \
_class::NodeWillBeDestroyed(const nsINode* aNode) \
{ \
}
#define NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(_class) \
void \
_class::CharacterDataChanged(nsIDocument* aDocument, \
nsIContent* aContent, \
PRBool aAppend) \
{ \
} \
void \
_class::AttributeChanged(nsIDocument* aDocument, \
nsIContent* aContent, \
PRInt32 aNameSpaceID, \
nsIAtom* aAttribute, \
PRInt32 aModType) \
{ \
} \
void \
_class::ContentAppended(nsIDocument* aDocument, \
nsIContent* aContainer, \
PRInt32 aNewIndexInContainer) \
{ \
} \
void \
_class::ContentInserted(nsIDocument* aDocument, \
nsIContent* aContainer, \
nsIContent* aChild, \
PRInt32 aIndexInContainer) \
{ \
} \
void \
_class::ContentRemoved(nsIDocument* aDocument, \
nsIContent* aContainer, \
nsIContent* aChild, \
PRInt32 aIndexInContainer) \
{ \
}
#endif /* nsIMutationObserver_h___ */

Просмотреть файл

@ -41,6 +41,7 @@
#include "nsIDOMGCParticipant.h"
#include "nsEvent.h"
#include "nsPropertyTable.h"
#include "nsTObserverArray.h"
#ifdef MOZILLA_INTERNAL_API
#include "nsINodeInfo.h"
@ -57,8 +58,9 @@ class nsIEventListenerManager;
class nsIPrincipal;
class nsIDOMRange;
class nsVoidArray;
class nsIMutationObserver;
// This bit will be set if the node doesn't have nsDOMSlots
// This bit will be set if the node doesn't have nsSlots
#define NODE_DOESNT_HAVE_SLOTS 0x00000001U
// This bit will be set if the node has a range list in the range list hash
@ -85,6 +87,14 @@ class nsVoidArray;
// Remaining bits are node type specific.
#define NODE_TYPE_SPECIFIC_BITS_OFFSET 0x0a
// Useful macro for getting a node given an nsIContent and an nsIDocument
// Returns the first argument cast to nsINode if it is non-null, otherwise
// returns the second (which may be null)
#define NODE_FROM(content_, document_) \
((content_) ? NS_STATIC_CAST(nsINode*, (content_)) : \
NS_STATIC_CAST(nsINode*, (document_)))
// IID for the nsINode interface
#define NS_INODE_IID \
{ 0x7b23c37c, 0x18e6, 0x4d80, \
@ -107,6 +117,8 @@ public:
// If you're using the external API, the only thing you can know about
// nsINode is that it exists with an IID, if that....
friend class nsNodeUtils;
nsINode(nsINodeInfo* aNodeInfo)
: mNodeInfo(aNodeInfo),
mParentPtrBits(0),
@ -510,7 +522,20 @@ public:
return NS_REINTERPRET_CAST(nsINode*, mParentPtrBits & ~kParentBitMask);
}
// This class should be extended by subclasses that wish to store more
/**
* Adds a mutation observer to be notified when this node, or any of its
* descendants, are modified. The node will hold a weak reference to the
* observer, which means that it is the responsibility of the observer to
* remove itself in case it dies before the node.
*/
virtual void AddMutationObserver(nsIMutationObserver* aMutationObserver);
/**
* Removes a mutation observer.
*/
virtual void RemoveMutationObserver(nsIMutationObserver* aMutationObserver);
// This class can be extended by subclasses that wish to store more
// information in the slots.
class nsSlots
{
@ -519,12 +544,23 @@ public:
{
}
// If needed we could remove the vtable pointer this dtor causes by
// putting a DestroySlots function on nsINode
virtual ~nsSlots()
{
}
/**
* Storage for flags for this node. These are the same flags as the
* mFlagsOrSlots member, but these are used when the slots class
* is allocated.
*/
PtrBits mFlags;
protected:
// This is protected so that no-one accidentally deletes this rather than
// the subclass
~nsSlots() {}
/**
* A list of mutation observers
*/
nsTObserverArray<nsIMutationObserver> mMutationObservers;
};
protected:
@ -532,6 +568,9 @@ protected:
* Functions for managing flags and slots
*/
// Override this function to create a custom slots class.
virtual nsINode::nsSlots* CreateSlots();
PRBool HasSlots() const
{
return !(mFlagsOrSlots & NODE_DOESNT_HAVE_SLOTS);
@ -548,10 +587,18 @@ protected:
return HasSlots() ? FlagsAsSlots() : nsnull;
}
void SetSlots(nsSlots* aSlots)
nsSlots* GetSlots()
{
NS_ASSERTION(!HasSlots(), "Already has slots");
mFlagsOrSlots = NS_REINTERPRET_CAST(PtrBits, aSlots);
if (HasSlots()) {
return FlagsAsSlots();
}
nsSlots* slots = CreateSlots();
if (slots) {
mFlagsOrSlots = NS_REINTERPRET_CAST(PtrBits, slots);
}
return slots;
}
PtrBits GetFlags() const
@ -589,7 +636,7 @@ protected:
PtrBits mParentPtrBits;
/**
* Used for either storing flags for this element or a pointer to
* Used for either storing flags for this node or a pointer to
* this contents nsContentSlots. See the definition of the
* NODE_* macros for the layout of the bits in this
* member.

Просмотреть файл

@ -45,8 +45,8 @@ class nsTextFragment;
// IID for the nsITextContent interface
// e4ef843f-1061-45e6-9c81-30eac2673f41
#define NS_ITEXT_CONTENT_IID \
{ 0xe4ef843f, 0x1061, 0x45e6, \
{ 0x9c, 0x81, 0x30, 0xea, 0xc2, 0x67, 0x3f, 0x41 } }
{ 0x013da2a1, 0x6267, 0x4667, \
{ 0x9a, 0x63, 0xc9, 0xd3, 0x02, 0xf7, 0x55, 0x8d } }
/**
* Interface for textual content. This interface is used to provide

Просмотреть файл

@ -85,7 +85,9 @@ EXPORTS = \
nsPropertyTable.h \
nsStubDocumentObserver.h \
nsStubImageDecoderObserver.h \
nsStubMutationObserver.h \
nsTextFragment.h \
nsTObserverArray.h \
$(NULL)
CPPSRCS = \
@ -126,6 +128,7 @@ CPPSRCS = \
nsNoDataProtocolContentPolicy.cpp \
nsNodeInfo.cpp \
nsNodeInfoManager.cpp \
nsNodeUtils.cpp \
nsObjectLoadingContent.cpp \
nsParserUtils.cpp \
nsPlainTextSerializer.cpp \
@ -135,6 +138,7 @@ CPPSRCS = \
nsScriptLoader.cpp \
nsStubDocumentObserver.cpp \
nsStubImageDecoderObserver.cpp \
nsStubMutationObserver.cpp \
nsStyleLinkElement.cpp \
nsSyncLoadService.cpp \
nsTextFragment.cpp \

Просмотреть файл

@ -110,7 +110,7 @@ void
nsBaseContentList::AppendElement(nsIContent *aContent)
{
// Shouldn't hold a reference since we'll be told when the content
// leaves the document or the document will be destroyed.
// leaves the root or the root will be destroyed.
mElements.AppendElement(aContent);
}
@ -242,9 +242,11 @@ ContentListHashtableMatchEntry(PLDHashTable *table,
}
already_AddRefed<nsContentList>
NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom,
PRInt32 aMatchNameSpaceId, nsIContent* aRootContent)
NS_GetContentList(nsINode* aRootNode, nsIAtom* aMatchAtom,
PRInt32 aMatchNameSpaceId)
{
NS_ASSERTION(aRootNode, "content list has to have a root");
nsContentList* list = nsnull;
static PLDHashTableOps hash_table_ops =
@ -274,8 +276,8 @@ NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom,
ContentListHashEntry *entry = nsnull;
// First we look in our hashtable. Then we create a content list if needed
if (gContentListHashTable.ops) {
nsContentListKey hashKey(aDocument, aMatchAtom,
aMatchNameSpaceId, aRootContent);
nsContentListKey hashKey(aRootNode, aMatchAtom,
aMatchNameSpaceId);
// A PL_DHASH_ADD is equivalent to a PL_DHASH_LOOKUP for cases
// when the entry is already in the hashtable.
@ -290,8 +292,8 @@ NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom,
if (!list) {
// We need to create a ContentList and add it to our new entry, if
// we have an entry
list = new nsContentList(aDocument, aMatchAtom,
aMatchNameSpaceId, aRootContent);
list = new nsContentList(aRootNode, aMatchAtom,
aMatchNameSpaceId);
if (entry) {
if (list)
entry->mContentList = list;
@ -309,7 +311,7 @@ NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom,
// bumping the refcount on the list if the requested list is the one
// that's already cached.
if (!aRootContent && gCachedContentList != list) {
if (gCachedContentList != list) {
NS_IF_RELEASE(gCachedContentList);
gCachedContentList = list;
@ -322,39 +324,37 @@ NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom,
// nsContentList implementation
nsContentList::nsContentList(nsIDocument *aDocument,
nsContentList::nsContentList(nsINode* aRootNode,
nsIAtom* aMatchAtom,
PRInt32 aMatchNameSpaceId,
nsIContent* aRootContent,
PRBool aDeep)
: nsBaseContentList(),
nsContentListKey(aDocument, aMatchAtom, aMatchNameSpaceId, aRootContent),
nsContentListKey(aRootNode, aMatchAtom, aMatchNameSpaceId),
mFunc(nsnull),
mData(nsnull),
mState(LIST_DIRTY),
mDeep(aDeep),
mFuncMayDependOnAttr(PR_FALSE)
{
NS_ASSERTION(mDeep || mRootContent, "Must have root content for non-deep list!");
NS_ASSERTION(mRootNode, "Must have root");
if (nsLayoutAtoms::_asterix == mMatchAtom) {
mMatchAll = PR_TRUE;
}
else {
mMatchAll = PR_FALSE;
}
Init(aDocument);
mRootNode->AddMutationObserver(this);
}
nsContentList::nsContentList(nsIDocument *aDocument,
nsContentList::nsContentList(nsINode* aRootNode,
nsContentListMatchFunc aFunc,
const nsAString& aData,
nsIContent* aRootContent,
PRBool aDeep,
nsIAtom* aMatchAtom,
PRInt32 aMatchNameSpaceId,
PRBool aFuncMayDependOnAttr)
: nsBaseContentList(),
nsContentListKey(aDocument, aMatchAtom, aMatchNameSpaceId, aRootContent),
nsContentListKey(aRootNode, aMatchAtom, aMatchNameSpaceId),
mFunc(aFunc),
mData(&EmptyString()),
mMatchAll(PR_FALSE),
@ -362,32 +362,19 @@ nsContentList::nsContentList(nsIDocument *aDocument,
mDeep(aDeep),
mFuncMayDependOnAttr(aFuncMayDependOnAttr)
{
NS_ASSERTION(mDeep || mRootContent, "Must have root content for non-deep list!");
NS_ASSERTION(mRootNode, "Must have root");
if (!aData.IsEmpty()) {
mData = new nsString(aData);
// If this fails, fail silently
}
Init(aDocument);
}
void nsContentList::Init(nsIDocument *aDocument)
{
// We don't reference count the reference to the document
// If the document goes away first, we'll be informed and we
// can drop our reference.
// If we go away first, we'll get rid of ourselves from the
// document's observer list.
mDocument = aDocument;
if (mDocument) {
mDocument->AddObserver(this);
}
mRootNode->AddMutationObserver(this);
}
nsContentList::~nsContentList()
{
RemoveFromHashtable();
if (mDocument) {
mDocument->RemoveObserver(this);
if (mRootNode) {
mRootNode->RemoveMutationObserver(this);
}
if (mData && mData != &EmptyString()) {
@ -400,7 +387,7 @@ nsContentList::~nsContentList()
// QueryInterface implementation for nsContentList
NS_INTERFACE_MAP_BEGIN(nsContentList)
NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLCollection)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(ContentList)
NS_INTERFACE_MAP_END_INHERITING(nsBaseContentList)
@ -412,17 +399,12 @@ NS_IMPL_RELEASE_INHERITED(nsContentList, nsBaseContentList)
nsISupports *
nsContentList::GetParentObject()
{
if (mRootContent) {
return mRootContent;
}
return mDocument;
return mRootNode;
}
PRUint32
nsContentList::Length(PRBool aDoFlush)
{
CheckDocumentExistence();
BringSelfUpToDate(aDoFlush);
return mElements.Count();
@ -431,17 +413,21 @@ nsContentList::Length(PRBool aDoFlush)
nsIContent *
nsContentList::Item(PRUint32 aIndex, PRBool aDoFlush)
{
CheckDocumentExistence();
if (mDocument && aDoFlush) {
// Flush pending content changes Bug 4891.
mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
if (mRootNode && aDoFlush) {
// XXX sXBL/XBL2 issue
// Ideally we should call GetCurrentDoc here, i think, but that doesn't
// live on nsINode
nsIDocument* doc = mRootNode->GetOwnerDoc();
if (doc) {
// Flush pending content changes Bug 4891.
doc->FlushPendingNotifications(Flush_ContentAndNotify);
}
}
if (mState != LIST_UP_TO_DATE)
PopulateSelf(aIndex+1);
NS_ASSERTION(!mDocument || mState != LIST_DIRTY,
NS_ASSERTION(!mRootNode || mState != LIST_DIRTY,
"PopulateSelf left the list in a dirty (useless) state!");
return NS_STATIC_CAST(nsIContent *, mElements.SafeElementAt(aIndex));
@ -450,8 +436,6 @@ nsContentList::Item(PRUint32 aIndex, PRBool aDoFlush)
nsIContent *
nsContentList::NamedItem(const nsAString& aName, PRBool aDoFlush)
{
CheckDocumentExistence();
BringSelfUpToDate(aDoFlush);
PRInt32 i, count = mElements.Count();
@ -479,18 +463,26 @@ nsContentList::NamedItem(const nsAString& aName, PRBool aDoFlush)
PRInt32
nsContentList::IndexOf(nsIContent *aContent, PRBool aDoFlush)
{
CheckDocumentExistence();
BringSelfUpToDate(aDoFlush);
return mElements.IndexOf(aContent);
}
void
nsContentList::RootDestroyed()
nsContentList::NodeWillBeDestroyed(const nsINode* aNode)
{
// We shouldn't do anything useful from now on
DisconnectFromDocument(); // This dirties us so we lose all state
mRootContent = nsnull;
RemoveFromHashtable();
mRootNode = nsnull;
// We will get no more updates, so we can never know we're up to
// date
mState = LIST_DIRTY;
// Call Reset() to prevent getting bogus (or eveng dangling) items since
// PopulateSelf() will be a no-op after mRootNode was nulled out above
Reset();
}
NS_IMETHODIMP
@ -537,26 +529,25 @@ nsContentList::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
NS_PRECONDITION(aContent, "Must have a content node to work with");
if (!mFunc || !mFuncMayDependOnAttr || mState == LIST_DIRTY ||
!MayContainRelevantNodes(aContent->GetNodeParent()) ||
IsContentAnonymous(aContent)) {
// Either we're already dirty or this notification doesn't affect
// whether we might match aContent.
return;
}
if (MayContainRelevantNodes(aContent->GetParent())) {
if (Match(aContent)) {
if (mElements.IndexOf(aContent) == -1) {
// We match aContent now, and it's not in our list already. Just dirty
// ourselves; this is simpler than trying to figure out where to insert
// aContent.
mState = LIST_DIRTY;
}
} else {
// We no longer match aContent. Remove it from our list. If
// it's already not there, this is a no-op, which is fine.
// Either way, no change of mState is required here.
mElements.RemoveElement(aContent);
if (Match(aContent)) {
if (mElements.IndexOf(aContent) == -1) {
// We match aContent now, and it's not in our list already. Just dirty
// ourselves; this is simpler than trying to figure out where to insert
// aContent.
mState = LIST_DIRTY;
}
} else {
// We no longer match aContent. Remove it from our list. If
// it's already not there, this is a no-op, which is fine.
// Either way, no change of mState is required here.
mElements.RemoveElement(aContent);
}
}
@ -572,7 +563,8 @@ nsContentList::ContentAppended(nsIDocument *aDocument, nsIContent* aContainer,
* aContainer is anonymous from our point of view, we know that we can't
* possibly be matching any of the kids.
*/
if (mState == LIST_DIRTY || IsContentAnonymous(aContainer))
if (mState == LIST_DIRTY || IsContentAnonymous(aContainer) ||
!MayContainRelevantNodes(aContainer))
return;
/*
@ -586,7 +578,7 @@ nsContentList::ContentAppended(nsIDocument *aDocument, nsIContent* aContainer,
PRInt32 count = aContainer->GetChildCount();
if (count > 0 && MayContainRelevantNodes(aContainer)) {
if (count > 0) {
PRInt32 ourCount = mElements.Count();
PRBool appendToList = PR_FALSE;
if (ourCount == 0) {
@ -636,7 +628,7 @@ nsContentList::ContentAppended(nsIDocument *aDocument, nsIContent* aContainer,
*/
for (i = aNewIndexInContainer; i <= count-1; ++i) {
PRUint32 limit = PRUint32(-1);
PopulateWith(aContainer->GetChildAt(i), PR_TRUE, limit);
PopulateWith(aContainer->GetChildAt(i), limit);
}
}
}
@ -650,11 +642,12 @@ nsContentList::ContentInserted(nsIDocument *aDocument,
// Note that aContainer can be null here if we are inserting into
// the document itself; any attempted optimizations to this method
// should deal with that.
if (mState == LIST_DIRTY || IsContentAnonymous(aChild))
return;
if (MayContainRelevantNodes(aContainer) && MatchSelf(aChild))
if (mState != LIST_DIRTY &&
MayContainRelevantNodes(NODE_FROM(aContainer, aDocument)) &&
!IsContentAnonymous(aChild) &&
MatchSelf(aChild)) {
mState = LIST_DIRTY;
}
}
void
@ -666,28 +659,12 @@ nsContentList::ContentRemoved(nsIDocument *aDocument,
// Note that aContainer can be null here if we are removing from
// the document itself; any attempted optimizations to this method
// should deal with that.
if (mState != LIST_DIRTY) {
if (MayContainRelevantNodes(aContainer)) {
if (!IsContentAnonymous(aChild) && MatchSelf(aChild)) {
mState = LIST_DIRTY;
}
return;
}
if (mState != LIST_DIRTY &&
MayContainRelevantNodes(NODE_FROM(aContainer, aDocument)) &&
!IsContentAnonymous(aChild) &&
MatchSelf(aChild)) {
mState = LIST_DIRTY;
}
// Even if aChild is anonymous from our point of view, it could
// contain our root (eg say our root is an anonymous child of
// aChild).
if (ContainsRoot(aChild)) {
DisconnectFromDocument();
}
}
void
nsContentList::DocumentWillBeDestroyed(nsIDocument *aDocument)
{
DisconnectFromDocument();
Reset();
}
PRBool
@ -718,24 +695,11 @@ nsContentList::Match(nsIContent *aContent)
return PR_FALSE;
}
void
nsContentList::CheckDocumentExistence()
{
if (!mDocument && mRootContent) {
mDocument = mRootContent->GetDocument();
if (mDocument) {
mDocument->AddObserver(this);
mState = LIST_DIRTY;
}
}
}
PRBool
nsContentList::MatchSelf(nsIContent *aContent)
{
NS_PRECONDITION(aContent, "Can't match null stuff, you know");
NS_PRECONDITION(mDeep || aContent->GetParent() == mRootContent,
NS_PRECONDITION(mDeep || aContent->GetNodeParent() == mRootNode,
"MatchSelf called on a node that we can't possibly match");
if (Match(aContent))
@ -755,52 +719,45 @@ nsContentList::MatchSelf(nsIContent *aContent)
return PR_FALSE;
}
void
nsContentList::PopulateWith(nsIContent *aContent, PRBool aIncludeRoot,
PRUint32 & aElementsToAppend)
void
nsContentList::PopulateWith(nsIContent *aContent, PRUint32& aElementsToAppend)
{
NS_PRECONDITION(mDeep || aContent == mRootContent ||
aContent->GetParent() == mRootContent,
NS_PRECONDITION(mDeep || aContent->GetNodeParent() == mRootNode,
"PopulateWith called on nodes we can't possibly match");
NS_PRECONDITION(mDeep || aIncludeRoot || aContent == mRootContent,
"Bogus root passed to PopulateWith in non-deep list");
NS_PRECONDITION(!aIncludeRoot || aContent != mRootContent,
"We should never be trying to match mRootContent");
if (aIncludeRoot) {
if (Match(aContent)) {
mElements.AppendElement(aContent);
--aElementsToAppend;
if (aElementsToAppend == 0)
return;
}
NS_PRECONDITION(aContent != mRootNode,
"We should never be trying to match mRootNode");
if (Match(aContent)) {
mElements.AppendElement(aContent);
--aElementsToAppend;
if (aElementsToAppend == 0)
return;
}
// Don't recurse down if we're not doing a deep match and we're
// already looking at kids of the root.
if (!mDeep && aIncludeRoot)
// Don't recurse down if we're not doing a deep match.
if (!mDeep)
return;
PRUint32 i, count = aContent->GetChildCount();
for (i = 0; i < count; i++) {
PopulateWith(aContent->GetChildAt(i), PR_TRUE, aElementsToAppend);
PopulateWith(aContent->GetChildAt(i), aElementsToAppend);
if (aElementsToAppend == 0)
return;
}
}
void
nsContentList::PopulateWithStartingAfter(nsIContent *aStartRoot,
nsIContent *aStartChild,
nsContentList::PopulateWithStartingAfter(nsINode *aStartRoot,
nsINode *aStartChild,
PRUint32 & aElementsToAppend)
{
NS_PRECONDITION(mDeep || aStartRoot == mRootContent ||
(aStartRoot->GetParent() == mRootContent &&
NS_PRECONDITION(mDeep || aStartRoot == mRootNode ||
(aStartRoot->GetNodeParent() == mRootNode &&
aStartChild == nsnull),
"Bogus aStartRoot or aStartChild");
if (mDeep || aStartRoot == mRootContent) {
if (mDeep || aStartRoot == mRootNode) {
#ifdef DEBUG
PRUint32 invariant = aElementsToAppend + mElements.Count();
#endif
@ -813,7 +770,7 @@ nsContentList::PopulateWithStartingAfter(nsIContent *aStartRoot,
PRUint32 childCount = aStartRoot->GetChildCount();
for ( ; ((PRUint32)i) < childCount; ++i) {
PopulateWith(aStartRoot->GetChildAt(i), PR_TRUE, aElementsToAppend);
PopulateWith(aStartRoot->GetChildAt(i), aElementsToAppend);
NS_ASSERTION(aElementsToAppend + mElements.Count() == invariant,
"Something is awry in PopulateWith!");
@ -824,10 +781,14 @@ nsContentList::PopulateWithStartingAfter(nsIContent *aStartRoot,
// We want to make sure we don't move up past our root node. So if
// we're there, don't move to the parent.
if (aStartRoot == mRootContent)
if (aStartRoot == mRootNode)
return;
nsIContent* parent = aStartRoot->GetParent();
// We could call GetParent() here to avoid walking children of the
// document node. However they should be very few in number and we
// might want to walk them in the future so it's unnecessary to have
// this be the only thing that prevents it
nsINode* parent = aStartRoot->GetNodeParent();
if (parent)
PopulateWithStartingAfter(parent, aStartRoot, aElementsToAppend);
@ -836,6 +797,10 @@ nsContentList::PopulateWithStartingAfter(nsIContent *aStartRoot,
void
nsContentList::PopulateSelf(PRUint32 aNeededLength)
{
if (!mRootNode) {
return;
}
if (mState == LIST_DIRTY) {
Reset();
}
@ -848,93 +813,20 @@ nsContentList::PopulateSelf(PRUint32 aNeededLength)
#ifdef DEBUG
PRUint32 invariant = elementsToAppend + mElements.Count();
#endif
if (count != 0) {
PopulateWithStartingAfter(NS_STATIC_CAST(nsIContent*,
mElements.ElementAt(count - 1)),
nsnull,
elementsToAppend);
NS_ASSERTION(elementsToAppend + mElements.Count() == invariant,
"Something is awry in PopulateWithStartingAfter!");
} else if (mRootContent) {
PopulateWith(mRootContent, PR_FALSE, elementsToAppend);
NS_ASSERTION(elementsToAppend + mElements.Count() == invariant,
"Something is awry in PopulateWith!");
}
else if (mDocument) {
nsIContent *root = mDocument->GetRootContent();
if (root) {
PopulateWith(root, PR_TRUE, elementsToAppend);
NS_ASSERTION(elementsToAppend + mElements.Count() == invariant,
"Something is awry in PopulateWith!");
}
}
if (mDocument) {
if (elementsToAppend != 0)
mState = LIST_UP_TO_DATE;
else
mState = LIST_LAZY;
} else {
// No document means we have to stay on our toes since we don't
// get content notifications.
mState = LIST_DIRTY;
}
}
// If we already have nodes start searching at the last one, otherwise
// start searching at the root.
nsINode* startRoot = count == 0 ? mRootNode :
NS_STATIC_CAST(nsIContent*, mElements.ElementAt(count - 1));
PRBool
nsContentList::MayContainRelevantNodes(nsIContent* aContainer)
{
if (!mRootContent) {
#ifdef DEBUG
// aContainer can be null when ContentInserted/ContentRemoved are
// called, but we still want to return PR_TRUE in such cases if
// mRootContent is null. We could pass the document into this
// method instead of trying to get it from aContainer, but that
// seems a little pointless just to run this debug-only integrity
// check.
if (aContainer) {
NS_ASSERTION(aContainer->GetDocument() == mDocument,
"We should not get in here if aContainer is in some _other_ document!");
}
#endif
return PR_TRUE;
}
PopulateWithStartingAfter(startRoot, nsnull, elementsToAppend);
NS_ASSERTION(elementsToAppend + mElements.Count() == invariant,
"Something is awry in PopulateWith!");
if (!aContainer) {
return PR_FALSE;
}
if (!mDeep) {
// We only care about cases when aContainer is our root content node.
return aContainer == mRootContent;
}
return nsContentUtils::ContentIsDescendantOf(aContainer, mRootContent);
}
PRBool
nsContentList::ContainsRoot(nsIContent* aContent)
{
if (!mRootContent || !aContent) {
return PR_FALSE;
}
return nsContentUtils::ContentIsDescendantOf(mRootContent, aContent);
}
void
nsContentList::DisconnectFromDocument()
{
if (mDocument) {
// Our key will change... Best remove ourselves before that happens.
RemoveFromHashtable();
mDocument->RemoveObserver(this);
mDocument = nsnull;
}
// We will get no more updates, so we can never know we're up to
// date
mState = LIST_DIRTY;
if (elementsToAppend != 0)
mState = LIST_UP_TO_DATE;
else
mState = LIST_LAZY;
}
void
@ -961,15 +853,21 @@ nsContentList::RemoveFromHashtable()
void
nsContentList::BringSelfUpToDate(PRBool aDoFlush)
{
if (mDocument && aDoFlush) {
// Flush pending content changes Bug 4891.
mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
if (mRootNode && aDoFlush) {
// XXX sXBL/XBL2 issue
// Ideally we should call GetCurrentDoc here, i think, but that doesn't
// live on nsINode
nsIDocument* doc = mRootNode->GetOwnerDoc();
if (doc) {
// Flush pending content changes Bug 4891.
doc->FlushPendingNotifications(Flush_ContentAndNotify);
}
}
if (mState != LIST_UP_TO_DATE)
PopulateSelf(PRUint32(-1));
NS_ASSERTION(!mDocument || mState == LIST_UP_TO_DATE,
NS_ASSERTION(!mRootNode || mState == LIST_UP_TO_DATE,
"PopulateSelf dod not bring content list up to date!");
}
@ -987,34 +885,35 @@ nsContentList::IsContentAnonymous(nsIContent* aContent)
* that node that it can see are not anonymous from our point of view.
*/
if (!mRootContent) {
if (!mRootNode->IsNodeOfType(nsINode::eCONTENT)) {
/**
* If we have no root, that means we correspond to a list gotten off the
* "document" object, so will always contain only nodes that the document
* can see, which means only nodes with a null bindingParent.
* The root isn't an nsIContent, that means we correspond to a list gotten
* off the "document" object, so will always contain only nodes that the
* document can see, which means only nodes with a null bindingParent.
*/
return aContent->GetBindingParent() != nsnull;
}
/**
* If mRootContent and aContent have _different_ bindingParents, then there
* If mRootNode and aContent have _different_ bindingParents, then there
* are two possibilities:
*
* 1) aContent or one of its ancestors is an anonymous child of a descendant
* of mRootContent (or of mRootContent itself).
* 2) mRootContent is not an ancestor of aContent.
* of mRootNode (or of mRootNode itself).
* 2) mRootNode is not an ancestor of aContent.
*
* In either case, we don't want to be matching aContent or any of its
* descendants.
*
* On the other hand, if mRootContent and aContent have the same
* On the other hand, if mRootNode and aContent have the same
* bindingParent then they are part of the same binding (or native anonymous
* content chunk) and then aContent may be a descendant of mRootContent and
* content chunk) and then aContent may be a descendant of mRootNode and
* we may want to match it.
*
* So we return true if the binding parents don't match; if the binding
* parents are the same, the checks we normally do to determine whether we
* match a node should be done.
*/
return mRootContent->GetBindingParent() != aContent->GetBindingParent();
return NS_STATIC_CAST(nsIContent*, mRootNode)->GetBindingParent() !=
aContent->GetBindingParent();
}

Просмотреть файл

@ -49,7 +49,7 @@
#include "nsString.h"
#include "nsIDOMHTMLCollection.h"
#include "nsIDOMNodeList.h"
#include "nsStubDocumentObserver.h"
#include "nsStubMutationObserver.h"
#include "nsIAtom.h"
#include "nsINameSpaceManager.h"
@ -112,22 +112,19 @@ public:
class nsContentListKey
{
public:
nsContentListKey(nsIDocument *aDocument,
nsContentListKey(nsINode* aRootNode,
nsIAtom* aMatchAtom,
PRInt32 aMatchNameSpaceId,
nsIContent* aRootContent)
PRInt32 aMatchNameSpaceId)
: mMatchAtom(aMatchAtom),
mMatchNameSpaceId(aMatchNameSpaceId),
mDocument(aDocument),
mRootContent(aRootContent)
mRootNode(aRootNode)
{
}
nsContentListKey(const nsContentListKey& aContentListKey)
: mMatchAtom(aContentListKey.mMatchAtom),
mMatchNameSpaceId(aContentListKey.mMatchNameSpaceId),
mDocument(aContentListKey.mDocument),
mRootContent(aContentListKey.mRootContent)
mRootNode(aContentListKey.mRootNode)
{
}
@ -136,27 +133,20 @@ public:
return
mMatchAtom == aContentListKey.mMatchAtom &&
mMatchNameSpaceId == aContentListKey.mMatchNameSpaceId &&
mDocument == aContentListKey.mDocument &&
mRootContent == aContentListKey.mRootContent;
mRootNode == aContentListKey.mRootNode;
}
inline PRUint32 GetHash(void) const
{
return
NS_PTR_TO_INT32(mMatchAtom.get()) ^
(NS_PTR_TO_INT32(mRootContent) << 8) ^
(NS_PTR_TO_INT32(mDocument) << 16) ^
(NS_PTR_TO_INT32(mRootNode) << 12) ^
(mMatchNameSpaceId << 24);
}
protected:
nsCOMPtr<nsIAtom> mMatchAtom;
PRInt32 mMatchNameSpaceId;
nsIDocument* mDocument; // Weak ref
// XXX What if the mRootContent is detached from the doc and _then_
// goes away (so we never get notified)? Note that we work around
// that a little by not caching lists with an mRootContent in
// gCachedContentList. If we fix this, we can remove that check.
nsIContent* mRootContent; // Weak ref
nsINode* mRootNode; // Weak ref
};
/**
@ -166,36 +156,31 @@ protected:
class nsContentList : public nsBaseContentList,
protected nsContentListKey,
public nsIDOMHTMLCollection,
public nsStubDocumentObserver
public nsStubMutationObserver
{
public:
NS_DECL_ISUPPORTS_INHERITED
/**
* @param aDocument the document to which to add as an nsIDocumentObserver
* @param aRootNode The node under which to limit our search.
* @param aMatchAtom an atom whose meaning depends on aMatchNameSpaceId
* @param aMatchNameSpaceId if kNameSpaceID_Unknown then aMatchAtom is the
* tagName to match. Otherwise we match nodes with
* aMatchNameSpaceId and a localName equal to
* aMatchAtom
* @param aRootContent The content node under which to limit our search.
* If not null, the root is aDocument.
* @param aDeep If false, then look only at children of the root, nothing
* deeper. If true, then look at the whole subtree rooted at
* our root.
*/
nsContentList(nsIDocument *aDocument,
nsContentList(nsINode* aRootNode,
nsIAtom* aMatchAtom,
PRInt32 aMatchNameSpaceId,
nsIContent* aRootContent = nsnull,
PRBool aDeep = PR_TRUE);
/**
* @param aDocument the document to which to add as an nsIDocumentObserver
* @param aRootNode The node under which to limit our search.
* @param aFunc the function to be called to determine whether we match
* @param aData a string that will need to be passed back to aFunc
* @param aRootContent The content node under which to limit our search.
* If not null, the root is aDocument.
* @param aDeep If false, then look only at children of the root, nothing
* deeper. If true, then look at the whole subtree rooted at
* our root.
@ -204,10 +189,9 @@ public:
* @param aFuncMayDependOnAttr a boolean that indicates whether this list is
* sensitive to attribute changes.
*/
nsContentList(nsIDocument *aDocument,
nsContentList(nsINode* aRootNode,
nsContentListMatchFunc aFunc,
const nsAString& aData,
nsIContent* aRootContent = nsnull,
PRBool aDeep = PR_TRUE,
nsIAtom* aMatchAtom = nsnull,
PRInt32 aMatchNameSpaceId = kNameSpaceID_None,
@ -225,14 +209,13 @@ public:
NS_HIDDEN_(PRUint32) Length(PRBool aDoFlush);
NS_HIDDEN_(nsIContent*) Item(PRUint32 aIndex, PRBool aDoFlush);
NS_HIDDEN_(nsIContent*) NamedItem(const nsAString& aName, PRBool aDoFlush);
NS_HIDDEN_(void) RootDestroyed();
nsContentListKey* GetKey() {
return NS_STATIC_CAST(nsContentListKey*, this);
}
// nsIDocumentObserver
// nsIMutationObserver
virtual void AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRInt32 aModType);
@ -242,10 +225,9 @@ public:
nsIContent* aChild, PRInt32 aIndexInContainer);
virtual void ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
nsIContent* aChild, PRInt32 aIndexInContainer);
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument);
virtual void NodeWillBeDestroyed(const nsINode *aNode);
protected:
void Init(nsIDocument *aDocument);
/**
* Returns whether the content element matches our criterion
*
@ -268,13 +250,14 @@ protected:
* elements. This function enforces the invariant that
* |aElementsToAppend + mElements.Count()| is a constant.
*
* @param aContent the root of the subtree we want to traverse
* @param aIncludeRoot whether to include the root in the traversal
* @param aContent the root of the subtree we want to traverse. This node
* is always included in the traversal and is thus the
* first node tested.
* @param aElementsToAppend how many elements to append to the list
* before stopping
*/
void PopulateWith(nsIContent *aContent, PRBool aIncludeRoot,
PRUint32 & aElementsToAppend);
void PopulateWith(nsIContent *aContent, PRUint32 & aElementsToAppend);
/**
* Populate our list starting at the child of aStartRoot that comes
* after aStartChild (if such exists) and continuing in document
@ -287,8 +270,8 @@ protected:
* @param aElementsToAppend how many elements to append to the list
* before stopping
*/
void PopulateWithStartingAfter(nsIContent *aStartRoot,
nsIContent *aStartChild,
void PopulateWithStartingAfter(nsINode *aStartRoot,
nsINode *aStartChild,
PRUint32 & aElementsToAppend);
/**
* Populate our list. Stop once we have at least aNeededLength
@ -302,36 +285,17 @@ protected:
void PopulateSelf(PRUint32 aNeededLength);
/**
* Our root content has been disconnected from the document, so stop
* observing. From this point on, if someone asks us something we
* walk the tree rooted at mRootContent starting at the beginning
* and going as far as we need to to answer the question.
* @param aContainer a content node which must be a descendant of
* mRootNode
* @return PR_TRUE if children or descendants of aContainer could match our
* criterion.
* PR_FALSE otherwise.
*/
void DisconnectFromDocument();
PRBool MayContainRelevantNodes(nsINode* aContainer)
{
return mDeep || aContainer == mRootNode;
}
/**
* @param aContainer a content node which could be a descendant of
* mRootContent
* @return PR_TRUE if mRootContent is null, PR_FALSE if aContainer
* is null, PR_TRUE if aContainer is a descendant of mRootContent
* (though if mDeep is false, only aContainer == mRootContent
* counts), PR_FALSE otherwise
*/
PRBool MayContainRelevantNodes(nsIContent* aContainer);
/**
* Does this subtree contain our mRootContent?
*
* @param aContainer the root of the subtree
* @return PR_FALSE if mRootContent is null, otherwise whether
* mRootContent is a descendant of aContainer
*/
PRBool ContainsRoot(nsIContent* aContent);
/**
* If we have no document and we have a root content, then check if
* our content has been added to a document. If so, we'll become an
* observer of the document.
*/
void CheckDocumentExistence();
/**
* Remove ourselves from the hashtable that caches commonly accessed
* content lists. Generally done on destruction.
@ -368,7 +332,7 @@ protected:
PRUint8 mState;
/**
* Whether to actually descend the tree. If this is false, we won't
* consider grandkids of mRootContent.
* consider grandkids of mRootNode.
*/
PRPackedBool mDeep;
/**
@ -399,7 +363,7 @@ protected:
#define LIST_LAZY 2
already_AddRefed<nsContentList>
NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom,
PRInt32 aMatchNameSpaceId, nsIContent* aRootContent);
NS_GetContentList(nsINode* aRootNode, nsIAtom* aMatchAtom,
PRInt32 aMatchNameSpaceId);
#endif // nsContentList_h___

Просмотреть файл

@ -56,6 +56,7 @@
#include "nsEventDispatcher.h"
#include "nsGkAtoms.h"
#include "nsCOMArray.h"
#include "nsNodeUtils.h"
//----------------------------------------------------------------------
PRBool nsDOMAttribute::sInitialized;
@ -74,6 +75,8 @@ nsDOMAttribute::nsDOMAttribute(nsDOMAttributeMap *aAttrMap,
nsDOMAttribute::~nsDOMAttribute()
{
nsNodeUtils::NodeWillBeDestroyed(this);
if (mChildList) {
mChildList->DropReference();
NS_RELEASE(mChildList);

Просмотреть файл

@ -75,6 +75,7 @@
#include "nsIDOMCDATASection.h"
#include "nsIDOMProcessingInstruction.h"
#include "nsDOMString.h"
#include "nsNodeUtils.h"
#include "nsRange.h"
#include "nsIDOMText.h"
@ -331,6 +332,7 @@ nsDOMStyleSheetList::~nsDOMStyleSheetList()
NS_INTERFACE_MAP_BEGIN(nsDOMStyleSheetList)
NS_INTERFACE_MAP_ENTRY(nsIDOMStyleSheetList)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMStyleSheetList)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(DocumentStyleSheetList)
NS_INTERFACE_MAP_END
@ -385,12 +387,9 @@ nsDOMStyleSheetList::Item(PRUint32 aIndex, nsIDOMStyleSheet** aReturn)
}
void
nsDOMStyleSheetList::DocumentWillBeDestroyed(nsIDocument *aDocument)
nsDOMStyleSheetList::NodeWillBeDestroyed(const nsINode *aNode)
{
if (nsnull != mDocument) {
aDocument->RemoveObserver(this);
mDocument = nsnull;
}
mDocument = nsnull;
}
void
@ -679,14 +678,9 @@ nsDocument::~nsDocument()
this, nsnull, nsnull);
}
// XXX Inform any remaining observers that we are going away.
// Note that this currently contradicts the rule that all
// observers must hold on to live references to the document.
// This notification will occur only after the reference has
// been dropped.
PRInt32 indx;
NS_DOCUMENT_NOTIFY_OBSERVERS(DocumentWillBeDestroyed, (this));
nsNodeUtils::NodeWillBeDestroyed(this);
// Clear mObservers to keep it in sync with the mutationobserver list
mObservers.Clear();
mParentDocument = nsnull;
@ -698,6 +692,7 @@ nsDocument::~nsDocument()
mSubDocuments = nsnull;
}
PRInt32 indx;
if (mRootContent) {
if (mRootContent->GetCurrentDoc()) {
NS_ASSERTION(mRootContent->GetCurrentDoc() == this,
@ -794,6 +789,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocument)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIRadioGroupContainer)
NS_INTERFACE_MAP_ENTRY(nsINode)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocument)
if (aIID.Equals(NS_GET_IID(nsIDOMXPathEvaluator)) ||
aIID.Equals(NS_GET_IID(nsIXPathEvaluatorInternal))) {
@ -829,6 +825,19 @@ nsDocument::Init()
// The binding manager must always be the first observer of the document.
mObservers.PrependObserver(bindingManager);
nsINode::nsSlots* slots = GetSlots();
NS_ENSURE_TRUE(slots &&
slots->mMutationObservers.PrependObserver(bindingManager),
NS_ERROR_OUT_OF_MEMORY);
// Prepend self as mutation-observer whether we need it or not (some
// subclasses currently do, other don't). This is because the code in
// nsNodeUtils always notifies the first observer first, even when going
// backwards, expecting the first observer to be the document.
// If we remove that hack, we can move the below registring out to the leaf
// classes.
NS_ENSURE_TRUE(slots->mMutationObservers.PrependObserver(this),
NS_ERROR_OUT_OF_MEMORY);
mOnloadBlocker = new nsOnloadBlocker();
NS_ENSURE_TRUE(mOnloadBlocker, NS_ERROR_OUT_OF_MEMORY);
@ -935,7 +944,7 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup)
for (PRInt32 i = PRInt32(count) - 1; i >= 0; i--) {
nsCOMPtr<nsIContent> content = mChildren.ChildAt(i);
ContentRemoved(nsnull, content, i);
nsNodeUtils::ContentRemoved(this, content, i);
content->UnbindFromTree();
mChildren.RemoveChildAt(i);
}
@ -2235,10 +2244,9 @@ nsDocument::GetScriptLoader()
void
nsDocument::AddObserver(nsIDocumentObserver* aObserver)
{
// Make sure the observer isn't already in the list
if (!mObservers.Contains(aObserver)) {
mObservers.AppendObserver(aObserver);
}
// The array makes sure the observer isn't already in the list
mObservers.AppendObserver(aObserver);
AddMutationObserver(aObserver);
}
PRBool
@ -2249,6 +2257,7 @@ nsDocument::RemoveObserver(nsIDocumentObserver* aObserver)
// observers from the list. This is not a big deal, since we
// don't hold a live reference to the observers.
if (!mInDestructor) {
RemoveMutationObserver(aObserver);
return mObservers.RemoveObserver(aObserver);
}
@ -2407,14 +2416,6 @@ nsDocument::EndLoad()
UnblockOnload(PR_TRUE);
}
void
nsDocument::CharacterDataChanged(nsIContent* aContent, PRBool aAppend)
{
NS_ABORT_IF_FALSE(aContent, "Null content!");
NS_DOCUMENT_NOTIFY_OBSERVERS(CharacterDataChanged, (this, aContent, aAppend));
}
void
nsDocument::ContentStatesChanged(nsIContent* aContent1, nsIContent* aContent2,
PRInt32 aStateMask)
@ -2423,54 +2424,6 @@ nsDocument::ContentStatesChanged(nsIContent* aContent1, nsIContent* aContent2,
(this, aContent1, aContent2, aStateMask));
}
void
nsDocument::ContentAppended(nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
NS_ABORT_IF_FALSE(aContainer, "Null container!");
// XXXdwh There is a hacky ordering dependency between the binding
// manager and the frame constructor that forces us to walk the
// observer list in a forward order
// XXXldb So one should notify the other rather than both being
// registered.
NS_DOCUMENT_FORWARD_NOTIFY_OBSERVERS(ContentAppended,
(this, aContainer,
aNewIndexInContainer));
}
void
nsDocument::ContentInserted(nsIContent* aContainer, nsIContent* aChild,
PRInt32 aIndexInContainer)
{
NS_ABORT_IF_FALSE(aChild, "Null child!");
// XXXdwh There is a hacky ordering dependency between the binding manager
// and the frame constructor that forces us to walk the observer list
// in a forward order
// XXXldb So one should notify the other rather than both being
// registered.
NS_DOCUMENT_FORWARD_NOTIFY_OBSERVERS(ContentInserted,
(this, aContainer, aChild,
aIndexInContainer));
}
void
nsDocument::ContentRemoved(nsIContent* aContainer, nsIContent* aChild,
PRInt32 aIndexInContainer)
{
NS_ABORT_IF_FALSE(aChild, "Null child!");
// XXXdwh There is a hacky ordering dependency between the binding
// manager and the frame constructor that forces us to walk the
// observer list in a reverse order
// XXXldb So one should notify the other rather than both being
// registered.
NS_DOCUMENT_NOTIFY_OBSERVERS(ContentRemoved,
(this, aContainer, aChild, aIndexInContainer));
}
void
nsDocument::AttributeWillChange(nsIContent* aChild, PRInt32 aNameSpaceID,
nsIAtom* aAttribute)
@ -2478,17 +2431,6 @@ nsDocument::AttributeWillChange(nsIContent* aChild, PRInt32 aNameSpaceID,
NS_ASSERTION(aChild, "Null child!");
}
void
nsDocument::AttributeChanged(nsIContent* aChild, PRInt32 aNameSpaceID,
nsIAtom* aAttribute, PRInt32 aModType)
{
NS_ABORT_IF_FALSE(aChild, "Null child!");
NS_DOCUMENT_NOTIFY_OBSERVERS(AttributeChanged, (this, aChild, aNameSpaceID,
aAttribute, aModType));
}
void
nsDocument::StyleRuleChanged(nsIStyleSheet* aStyleSheet,
nsIStyleRule* aOldStyleRule,
@ -2784,8 +2726,7 @@ nsDocument::GetElementsByTagName(const nsAString& aTagname,
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aTagname);
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
nsContentList *list = NS_GetContentList(this, nameAtom, kNameSpaceID_Unknown,
nsnull).get();
nsContentList *list = NS_GetContentList(this, nameAtom, kNameSpaceID_Unknown).get();
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
// transfer ref to aReturn
@ -2808,7 +2749,7 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
if (nameSpaceId == kNameSpaceID_Unknown) {
// Unknown namespace means no matches, we create an empty list...
list = NS_GetContentList(this, nsnull, kNameSpaceID_None, nsnull).get();
list = NS_GetContentList(this, nsnull, kNameSpaceID_None).get();
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
}
}
@ -2817,7 +2758,7 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLocalName);
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
list = NS_GetContentList(this, nameAtom, nameSpaceId, nsnull).get();
list = NS_GetContentList(this, nameAtom, nameSpaceId).get();
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
}
@ -5079,10 +5020,9 @@ nsDocument::OnPageShow(PRBool aPersisted)
if (aPersisted) {
// Send out notifications that our <link> elements are attached.
nsRefPtr<nsContentList> links = NS_GetContentList(this,
nsRefPtr<nsContentList> links = NS_GetContentList(mRootContent,
nsHTMLAtoms::link,
kNameSpaceID_Unknown,
mRootContent);
kNameSpaceID_Unknown);
if (links) {
PRUint32 linkCount = links->Length(PR_TRUE);
@ -5105,10 +5045,9 @@ nsDocument::OnPageHide(PRBool aPersisted)
// Send out notifications that our <link> elements are detached,
// but only if this is not a full unload.
if (aPersisted) {
nsRefPtr<nsContentList> links = NS_GetContentList(this,
nsRefPtr<nsContentList> links = NS_GetContentList(mRootContent,
nsHTMLAtoms::link,
kNameSpaceID_Unknown,
mRootContent);
kNameSpaceID_Unknown);
if (links) {
PRUint32 linkCount = links->Length(PR_TRUE);

Просмотреть файл

@ -89,6 +89,7 @@
#include "nsIRequest.h"
#include "nsILoadGroup.h"
#include "nsTObserverArray.h"
#include "nsStubMutationObserver.h"
// Put these here so all document impls get them automatically
#include "nsHTMLStyleSheet.h"
@ -238,7 +239,7 @@ public:
NS_DECL_NSIDOMSTYLESHEETLIST
// nsIDocumentObserver
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument);
virtual void NodeWillBeDestroyed(const nsINode *aNode);
virtual void StyleSheetAdded(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
PRBool aDocumentSheet);
@ -288,7 +289,8 @@ class nsDocument : public nsIDocument,
public nsIDOM3EventTarget,
public nsIDOMNSEventTarget,
public nsIScriptObjectPrincipal,
public nsIRadioGroupContainer
public nsIRadioGroupContainer,
public nsStubMutationObserver
{
public:
NS_DECL_ISUPPORTS
@ -468,8 +470,6 @@ public:
virtual void EndUpdate(nsUpdateType aUpdateType);
virtual void BeginLoad();
virtual void EndLoad();
virtual void CharacterDataChanged(nsIContent* aContent,
PRBool aAppend);
virtual void ContentStatesChanged(nsIContent* aContent1,
nsIContent* aContent2,
PRInt32 aStateMask);
@ -477,18 +477,6 @@ public:
virtual void AttributeWillChange(nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute);
virtual void AttributeChanged(nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
virtual void ContentAppended(nsIContent* aContainer,
PRInt32 aNewIndexInContainer);
virtual void ContentInserted(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
virtual void ContentRemoved(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
virtual void StyleRuleChanged(nsIStyleSheet* aStyleSheet,
nsIStyleRule* aOldStyleRule,

Просмотреть файл

@ -64,6 +64,7 @@
#include "nsChangeHint.h"
#include "nsEventDispatcher.h"
#include "nsCOMArray.h"
#include "nsNodeUtils.h"
#include "pldhash.h"
#include "prprf.h"
@ -88,12 +89,10 @@ nsGenericDOMDataNode::nsGenericDOMDataNode(nsINodeInfo *aNodeInfo)
nsGenericDOMDataNode::~nsGenericDOMDataNode()
{
if (HasSlots()) {
nsDataSlots* slots = GetDataSlots();
PtrBits flags = slots->mFlags | NODE_DOESNT_HAVE_SLOTS;
delete slots;
mFlagsOrSlots = flags;
}
NS_PRECONDITION(!IsInDoc(),
"Please remove this from the document properly");
nsNodeUtils::NodeWillBeDestroyed(this);
}
@ -435,10 +434,8 @@ nsGenericDOMDataNode::AppendData(const nsAString& aData)
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
}
// Trigger a reflow
if (document) {
document->CharacterDataChanged(this, PR_TRUE);
}
// Notify observers
nsNodeUtils::CharacterDataChanged(this, PR_TRUE);
return NS_OK;
}
@ -898,6 +895,12 @@ nsGenericDOMDataNode::GetBaseURI() const
return uri;
}
nsINode::nsSlots*
nsGenericDOMDataNode::CreateSlots()
{
return new nsDataSlots(mFlagsOrSlots);
}
//----------------------------------------------------------------------
// Implementation of the nsIDOMText interface
@ -1010,7 +1013,7 @@ nsGenericDOMDataNode::SetText(const PRUnichar* aBuffer,
// Trigger a reflow
if (aNotify && document) {
document->CharacterDataChanged(this, PR_FALSE);
nsNodeUtils::CharacterDataChanged(this, PR_FALSE);
}
}

Просмотреть файл

@ -271,6 +271,7 @@ public:
void ToCString(nsAString& aBuf, PRInt32 aOffset, PRInt32 aLen) const;
#endif
protected:
/**
* There are a set of DOM- and scripting-specific instance variables
* that may only be instantiated when a content object is accessed
@ -283,7 +284,7 @@ public:
{
public:
nsDataSlots(PtrBits aFlags);
~nsDataSlots();
virtual ~nsDataSlots();
/**
* An object implementing nsIDOMNodeList for this content (childNodes)
@ -298,26 +299,19 @@ public:
nsIContent* mBindingParent; // [Weak]
};
// Override from nsINode
virtual nsINode::nsSlots* CreateSlots();
nsDataSlots *GetDataSlots()
{
if (!HasSlots()) {
nsDataSlots *slots = new nsDataSlots(mFlagsOrSlots);
if (!slots) {
return nsnull;
}
SetSlots(slots);
}
return NS_STATIC_CAST(nsDataSlots*, FlagsAsSlots());
return NS_STATIC_CAST(nsDataSlots*, GetSlots());
}
nsDataSlots *GetExistingDataSlots() const
{
return NS_STATIC_CAST(nsDataSlots*, GetExistingSlots());
}
protected:
nsresult SplitText(PRUint32 aOffset, nsIDOMText** aReturn);
/**

Просмотреть файл

@ -84,6 +84,7 @@
#include "nsIScriptSecurityManager.h"
#include "nsIDOMMutationEvent.h"
#include "nsMutationEvent.h"
#include "nsNodeUtils.h"
#include "nsIBindingManager.h"
#include "nsXBLBinding.h"
@ -297,6 +298,30 @@ nsINode::GetListenerManager(PRBool aCreateIfNotFound,
return rv;
}
nsINode::nsSlots*
nsINode::CreateSlots()
{
return new nsSlots(mFlagsOrSlots);
}
void
nsINode::AddMutationObserver(nsIMutationObserver* aMutationObserver)
{
nsSlots* slots = GetSlots();
if (slots) {
slots->mMutationObservers.AppendObserver(aMutationObserver);
}
}
void
nsINode::RemoveMutationObserver(nsIMutationObserver* aMutationObserver)
{
nsSlots* slots = GetExistingSlots();
if (slots) {
slots->mMutationObservers.RemoveObserver(aMutationObserver);
}
}
//----------------------------------------------------------------------
void
@ -990,12 +1015,6 @@ nsGenericElement::nsDOMSlots::~nsDOMSlots()
}
}
PRBool
nsGenericElement::nsDOMSlots::IsEmpty()
{
return (!mChildNodes && !mStyle && !mAttributeMap && !mBindingParent);
}
nsGenericElement::nsGenericElement(nsINodeInfo *aNodeInfo)
: nsIXMLContent(aNodeInfo)
{
@ -1009,12 +1028,7 @@ nsGenericElement::~nsGenericElement()
NS_PRECONDITION(!IsInDoc(),
"Please remove this from the document properly");
if (HasSlots()) {
nsDOMSlots* slots = GetDOMSlots();
PtrBits flags = slots->mFlags | NODE_DOESNT_HAVE_SLOTS;
delete slots;
mFlagsOrSlots = flags;
}
nsNodeUtils::NodeWillBeDestroyed(this);
}
/**
@ -1543,8 +1557,8 @@ nsGenericElement::GetElementsByTagName(const nsAString& aTagname,
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aTagname);
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
nsContentList *list = NS_GetContentList(GetCurrentDoc(), nameAtom,
kNameSpaceID_Unknown, this).get();
nsContentList *list = NS_GetContentList(this, nameAtom,
kNameSpaceID_Unknown).get();
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
// transfer ref to aReturn
@ -1674,7 +1688,7 @@ nsGenericElement::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
if (nameSpaceId == kNameSpaceID_Unknown) {
// Unknown namespace means no matches, we create an empty list...
list = NS_GetContentList(document, nsnull,
kNameSpaceID_None, nsnull).get();
kNameSpaceID_None).get();
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
}
}
@ -1683,7 +1697,7 @@ nsGenericElement::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLocalName);
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
list = NS_GetContentList(document, nameAtom, nameSpaceId, this).get();
list = NS_GetContentList(this, nameAtom, nameSpaceId).get();
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
}
@ -2396,20 +2410,17 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
// really need to stop running them while we're in the middle of modifying
// the DOM....
nsINode* container = aParent ? NS_STATIC_CAST(nsINode*, aParent) :
NS_STATIC_CAST(nsINode*, aDocument);
if (aKid->GetNodeParent() == container) {
if (aNotify && aDocument) {
// Note that we always want to call ContentInserted when things are added
// as kids to documents
if (aParent && isAppend) {
aDocument->ContentAppended(aParent, aIndex);
} else {
aDocument->ContentInserted(aParent, aKid, aIndex);
}
nsINode* container = NODE_FROM(aParent, aDocument);
if (aNotify && aKid->GetNodeParent() == container) {
// Note that we always want to call ContentInserted when things are added
// as kids to documents
if (aParent && isAppend) {
nsNodeUtils::ContentAppended(aParent, aIndex);
} else {
nsNodeUtils::ContentInserted(container, aKid, aIndex);
}
if (aNotify &&
nsContentUtils::HasMutationListeners(container,
if (nsContentUtils::HasMutationListeners(container,
NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEINSERTED);
mutation.mRelatedNode = do_QueryInterface(container);
@ -2458,10 +2469,7 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
nsMutationGuard::DidMutate();
nsINode* container = aParent;
if (!container) {
container = aDocument;
}
nsINode* container = NODE_FROM(aParent, aDocument);
NS_PRECONDITION(aKid && aKid->GetParent() == aParent &&
aKid == container->GetChildAt(aIndex) &&
@ -2494,8 +2502,8 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
aChildArray.RemoveChildAt(aIndex);
if (aNotify && aDocument) {
aDocument->ContentRemoved(aParent, aKid, aIndex);
if (aNotify) {
nsNodeUtils::ContentRemoved(container, aKid, aIndex);
}
aKid->UnbindFromTree();
@ -2819,10 +2827,7 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
nsresult res = NS_OK;
PRInt32 insPos;
nsINode* container = aParent;
if (!container) {
container = aDocument;
}
nsINode* container = NODE_FROM(aParent, aDocument);
// Figure out which index to insert at
if (aRefChild) {
@ -3060,10 +3065,7 @@ nsGenericElement::doRemoveChild(nsIDOMNode* aOldChild, nsIContent* aParent,
*aReturn = nsnull;
NS_ENSURE_TRUE(aOldChild, NS_ERROR_NULL_POINTER);
nsINode* container = aParent;
if (!container) {
container = aDocument;
}
nsINode* container = NODE_FROM(aParent, aDocument);
nsCOMPtr<nsIContent> content = do_QueryInterface(aOldChild);
// fix children to be a passed argument
@ -3424,8 +3426,8 @@ nsGenericElement::SetAttrAndNotify(PRInt32 aNamespaceID,
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
}
if (document && aNotify) {
document->AttributeChanged(this, aNamespaceID, aName, modType);
if (aNotify) {
nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, modType);
}
if (aNamespaceID == kNameSpaceID_XMLEvents &&
@ -3637,11 +3639,11 @@ nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsXBLBinding *binding = document->BindingManager()->GetBinding(this);
if (binding)
binding->AttributeChanged(aName, aNameSpaceID, PR_TRUE, aNotify);
}
if (aNotify) {
document->AttributeChanged(this, aNameSpaceID, aName,
nsIDOMMutationEvent::REMOVAL);
}
if (aNotify) {
nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
nsIDOMMutationEvent::REMOVAL);
}
return NS_OK;
@ -3785,6 +3787,12 @@ nsGenericElement::IndexOf(nsINode* aPossibleChild) const
return mAttrsAndChildren.IndexOfChild(aPossibleChild);
}
nsINode::nsSlots*
nsGenericElement::CreateSlots()
{
return new nsDOMSlots(mFlagsOrSlots);
}
void
nsGenericElement::GetContentsAsText(nsAString& aText)
{

Просмотреть файл

@ -874,9 +874,7 @@ protected:
{
public:
nsDOMSlots(PtrBits aFlags);
~nsDOMSlots();
PRBool IsEmpty();
virtual ~nsDOMSlots();
/**
* An object implementing nsIDOMNodeList for this content (childNodes)
@ -911,19 +909,12 @@ protected:
};
};
// Override from nsINode
virtual nsINode::nsSlots* CreateSlots();
nsDOMSlots *GetDOMSlots()
{
if (!HasSlots()) {
nsDOMSlots *slots = new nsDOMSlots(mFlagsOrSlots);
if (!slots) {
return nsnull;
}
SetSlots(slots);
}
return NS_STATIC_CAST(nsDOMSlots*, FlagsAsSlots());
return NS_STATIC_CAST(nsDOMSlots*, GetSlots());
}
nsDOMSlots *GetExistingDOMSlots() const

224
content/base/src/nsNodeUtils.cpp Executable file
Просмотреть файл

@ -0,0 +1,224 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jonas Sicking <jonas@sicking.cc> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsNodeUtils.h"
#include "nsINode.h"
#include "nsIContent.h"
#include "nsCOMArray.h"
#include "nsTArray.h"
#include "nsIMutationObserver.h"
#include "nsIDocument.h"
#define IMPL_MUTATION_NOTIFICATION_FW(func_, content_, params_) \
nsINode* node = content_; \
nsINode* prev; \
nsCOMArray<nsIMutationObserver> observers; \
do { \
nsINode::nsSlots* slots = node->GetExistingSlots(); \
if (slots && !slots->mMutationObservers.IsEmpty()) { \
/* No need to explicitly notify the first observer first \
since that'll happen anyway. */ \
nsTObserverArray<nsIMutationObserver>::ForwardIterator \
iter_(slots->mMutationObservers); \
nsCOMPtr<nsIMutationObserver> obs_; \
while ((obs_ = iter_.GetNext())) { \
obs_-> func_ params_; \
} \
} \
prev = node; \
node = node->GetNodeParent(); \
\
if (!node && prev->IsNodeOfType(nsINode::eXUL)) { \
/* XUL elements can have the in-document flag set, but \
still be in an orphaned subtree. In this case we \
need to notify the document */ \
node = NS_STATIC_CAST(nsIContent*, prev)->GetCurrentDoc(); \
} \
} while (node);
#define IMPL_MUTATION_NOTIFICATION_BW(func_, content_, params_) \
nsINode* node = content_; \
nsINode* prev; \
nsCOMArray<nsIMutationObserver> observers; \
do { \
nsINode::nsSlots* slots = node->GetExistingSlots(); \
if (slots && !slots->mMutationObservers.IsEmpty()) { \
/* \
* Notify the first observer first even if we're doing a \
* reverse walk. This is since we want to notify the \
* document first when |node| is a document. \
* This may not actually be needed, but it's safer for now. \
* This can be removed once we always walk forward \
*/ \
nsIMutationObserver* first = \
slots->mMutationObservers.SafeObserverAt(0); \
first-> func_ params_; \
nsTObserverArray<nsIMutationObserver>::ReverseIterator \
iter_(slots->mMutationObservers); \
nsCOMPtr<nsIMutationObserver> obs_; \
while ((obs_ = iter_.GetNext()) != first) { \
obs_-> func_ params_; \
} \
} \
prev = node; \
node = node->GetNodeParent(); \
\
if (!node && prev->IsNodeOfType(nsINode::eXUL)) { \
/* XUL elements can have the in-document flag set, but \
still be in an orphaned subtree. In this case we \
need to notify the document */ \
node = NS_STATIC_CAST(nsIContent*, prev)->GetCurrentDoc(); \
} \
} while (node);
void
nsNodeUtils::CharacterDataChanged(nsIContent* aContent, PRBool aAppend)
{
nsIDocument* doc = aContent->GetOwnerDoc();
IMPL_MUTATION_NOTIFICATION_BW(CharacterDataChanged, aContent,
(doc, aContent, aAppend));
}
void
nsNodeUtils::AttributeChanged(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
nsIDocument* doc = aContent->GetOwnerDoc();
IMPL_MUTATION_NOTIFICATION_BW(AttributeChanged, aContent,
(doc, aContent, aNameSpaceID, aAttribute,
aModType));
}
void
nsNodeUtils::ContentAppended(nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
nsIDocument* document = aContainer->GetOwnerDoc();
// XXXdwh There is a hacky ordering dependency between the binding
// manager and the frame constructor that forces us to walk the
// observer list in a forward order
// XXXldb So one should notify the other rather than both being
// registered.
IMPL_MUTATION_NOTIFICATION_FW(ContentAppended, aContainer,
(document, aContainer, aNewIndexInContainer));
}
void
nsNodeUtils::ContentInserted(nsINode* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
NS_PRECONDITION(aContainer->IsNodeOfType(nsINode::eCONTENT) ||
aContainer->IsNodeOfType(nsINode::eDOCUMENT),
"container must be an nsIContent or an nsIDocument");
nsIContent* container;
nsIDocument* document;
if (aContainer->IsNodeOfType(nsINode::eCONTENT)) {
container = NS_STATIC_CAST(nsIContent*, aContainer);
document = aContainer->GetOwnerDoc();
}
else {
container = nsnull;
document = NS_STATIC_CAST(nsIDocument*, aContainer);
}
// XXXdwh There is a hacky ordering dependency between the binding manager
// and the frame constructor that forces us to walk the observer list
// in a forward order
// XXXldb So one should notify the other rather than both being
// registered.
IMPL_MUTATION_NOTIFICATION_FW(ContentInserted, aContainer,
(document, container, aChild, aIndexInContainer));
}
void
nsNodeUtils::ContentRemoved(nsINode* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
NS_PRECONDITION(aContainer->IsNodeOfType(nsINode::eCONTENT) ||
aContainer->IsNodeOfType(nsINode::eDOCUMENT),
"container must be an nsIContent or an nsIDocument");
nsIContent* container;
nsIDocument* document;
if (aContainer->IsNodeOfType(nsINode::eCONTENT)) {
container = NS_STATIC_CAST(nsIContent*, aContainer);
document = aContainer->GetOwnerDoc();
}
else {
container = nsnull;
document = NS_STATIC_CAST(nsIDocument*, aContainer);
}
// XXXdwh There is a hacky ordering dependency between the binding
// manager and the frame constructor that forces us to walk the
// observer list in a reverse order
// XXXldb So one should notify the other rather than both being
// registered.
IMPL_MUTATION_NOTIFICATION_BW(ContentRemoved, aContainer,
(document, container, aChild, aIndexInContainer));
}
void
nsNodeUtils::NodeWillBeDestroyed(nsINode* aNode)
{
nsINode::nsSlots* slots = aNode->GetExistingSlots();
if (slots) {
if (!slots->mMutationObservers.IsEmpty()) {
nsTObserverArray<nsIMutationObserver>::ForwardIterator
iter(slots->mMutationObservers);
nsCOMPtr<nsIMutationObserver> obs;
while ((obs = iter.GetNext())) {
obs->NodeWillBeDestroyed(aNode);
}
}
PtrBits flags = slots->mFlags | NODE_DOESNT_HAVE_SLOTS;
delete slots;
aNode->mFlagsOrSlots = flags;
}
}

113
content/base/src/nsNodeUtils.h Executable file
Просмотреть файл

@ -0,0 +1,113 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jonas Sicking <jonas@sicking.cc> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsNodeUtils_h___
#define nsNodeUtils_h___
#include "prtypes.h"
class nsINode;
class nsIContent;
class nsIDocument;
class nsIAtom;
class nsNodeUtils
{
public:
/**
* Send CharacterDataChanged notifications to nsIMutationObservers.
* @param aContent Node whose data changed
* @param aAppend True if data was only appended
* @see nsIMutationObserver::CharacterDataChanged
*/
static void CharacterDataChanged(nsIContent* aContent, PRBool aAppend);
/**
* Send AttributeChanged notifications to nsIMutationObservers.
* @param aContent Node whose data changed
* @param aNameSpaceID Namespace of changed attribute
* @param aAttribute Local-name of changed attribute
* @param aModType Type of change (add/change/removal)
* @see nsIMutationObserver::AttributeChanged
*/
static void AttributeChanged(nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
/**
* Send ContentAppended notifications to nsIMutationObservers
* @param aContainer Node into which new child/children were added
* @param aNewIndexInContainer Index of first new child
* @see nsIMutationObserver::ContentAppended
*/
static void ContentAppended(nsIContent* aContainer,
PRInt32 aNewIndexInContainer);
/**
* Send ContentInserted notifications to nsIMutationObservers
* @param aContainer Node into which new child was inserted
* @param aChild Newly inserted child
* @param aIndexInContainer Index of new child
* @see nsIMutationObserver::ContentInserted
*/
static void ContentInserted(nsINode* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
/**
* Send ContentRemoved notifications to nsIMutationObservers
* @param aContainer Node from which child was removed
* @param aChild Removed child
* @param aIndexInContainer Index of removed child
* @see nsIMutationObserver::ContentRemoved
*/
static void ContentRemoved(nsINode* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
/**
* Call this before starting to tear down a node. The node should still
* have children and attributes accessible.
* The function will notify nsIMutationObservers as well as delete the
* slots structure.
* @param aNode Node that is being destroyed
* @see nsIMutationObserver::NodeWillBeDestroyed
*/
static void NodeWillBeDestroyed(nsINode* aNode);
};
#endif // nsNodeUtils_h___

Просмотреть файл

@ -0,0 +1,48 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is nsStubMutationObserver.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jonas Sicking <jonas@sicking.cc> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* nsStubMutationObserver is an implementation of the nsIMutationObserver
* interface (except for the methods on nsISupports) that is intended to be
* used as a base class within the content/layout library. All methods do
* nothing.
*/
#include "nsStubMutationObserver.h"
NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(nsStubMutationObserver)
NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(nsStubMutationObserver)

Просмотреть файл

@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is nsStubMutationObserver.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* L. David Baron <dbaron@dbaron.org> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* nsStubMutationObserver is an implementation of the nsIMutationObserver
* interface (except for the methods on nsISupports) that is intended to be
* used as a base class within the content/layout library. All methods do
* nothing.
*/
#ifndef nsStubMutationObserver_h_
#define nsStubMutationObserver_h_
#include "nsIMutationObserver.h"
/**
* There are two advantages to inheriting from nsStubMutationObserver
* rather than directly from nsIMutationObserver:
* 1. smaller compiled code size (since there's no need for the code
* for the empty virtual function implementations for every
* nsIMutationObserver implementation)
* 2. the performance of document's loop over observers benefits from
* the fact that more of the functions called are the same (which
* can reduce instruction cache misses and perhaps improve branch
* prediction)
*/
class nsStubMutationObserver : public nsIMutationObserver {
NS_DECL_NSIMUTATIONOBSERVER
};
#endif /* !defined(nsStubMutationObserver_h_) */

Просмотреть файл

@ -35,7 +35,9 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsTArray.h"
#ifndef nsTObserverArray_h___
#define nsTObserverArray_h___
#include "nsVoidArray.h"
class nsTObserverArray_base {
@ -122,6 +124,9 @@ class nsTObserverArray : public nsTObserverArray_base {
* @param aObserver Observer to add
*/
PRBool PrependObserver(T* aObserver) {
NS_PRECONDITION(!Contains(aObserver),
"Don't prepend if the observer is already in the list");
PRBool res = mObservers.InsertElementAt(aObserver, 0);
if (res) {
AdjustIterators(0, 1);
@ -130,12 +135,13 @@ class nsTObserverArray : public nsTObserverArray_base {
}
/**
* Adds an observer to the end of the array
* Adds an observer to the end of the array unless it already exists in
* the array.
* @param aObserver Observer to add
* @return True on success, false otherwise
*/
PRBool AppendObserver(T* aObserver) {
return mObservers.AppendElement(aObserver);
return Contains(aObserver) || mObservers.AppendElement(aObserver);
}
/**
@ -159,6 +165,14 @@ class nsTObserverArray : public nsTObserverArray_base {
return mObservers.IndexOf(aObserver) >= 0;
}
PRBool IsEmpty() const {
return mObservers.Count() == 0;
}
T* SafeObserverAt(PRInt32 aIndex) {
return NS_STATIC_CAST(T*, mObservers.SafeElementAt(aIndex));
}
/**
* Iterators
*/
@ -206,3 +220,5 @@ class nsTObserverArray : public nsTObserverArray_base {
}
};
};
#endif // nsTObserverArray_h___

Просмотреть файл

@ -285,7 +285,7 @@ nsXMLEventsManager::~nsXMLEventsManager()
{
}
NS_IMPL_ISUPPORTS1(nsXMLEventsManager, nsIDocumentObserver)
NS_IMPL_ISUPPORTS2(nsXMLEventsManager, nsIDocumentObserver, nsIMutationObserver)
void nsXMLEventsManager::AddXMLEventsContent(nsIContent * aContent)
{
@ -332,11 +332,11 @@ nsXMLEventsManager::BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType
void
nsXMLEventsManager::EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) {}
void
nsXMLEventsManager::DocumentWillBeDestroyed(nsIDocument* aDocument){
nsXMLEventsManager::NodeWillBeDestroyed(const nsINode* aNode)
{
mIncomplete.Clear();
mListeners.Enumerate(EnumAndUnregisterListener, this);
mListeners.Clear();
aDocument->RemoveObserver(this);
}
void

Просмотреть файл

@ -51,7 +51,6 @@ class nsHTMLMapElement : public nsGenericHTMLElement,
{
public:
nsHTMLMapElement(nsINodeInfo *aNodeInfo);
virtual ~nsHTMLMapElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
@ -86,14 +85,6 @@ nsHTMLMapElement::nsHTMLMapElement(nsINodeInfo *aNodeInfo)
{
}
nsHTMLMapElement::~nsHTMLMapElement()
{
if (mAreas) {
mAreas->RootDestroyed();
}
}
NS_IMPL_ADDREF_INHERITED(nsHTMLMapElement, nsGenericElement)
NS_IMPL_RELEASE_INHERITED(nsHTMLMapElement, nsGenericElement)
@ -146,10 +137,9 @@ nsHTMLMapElement::GetAreas(nsIDOMHTMLCollection** aAreas)
if (!mAreas) {
// Not using NS_GetContentList because this should not be cached
mAreas = new nsContentList(GetDocument(),
mAreas = new nsContentList(this,
nsHTMLAtoms::area,
mNodeInfo->NamespaceID(),
this,
PR_FALSE);
if (!mAreas) {

Просмотреть файл

@ -140,10 +140,9 @@ TableRowsCollection::~TableRowsCollection()
nsresult
TableRowsCollection::Init()
{
mOrphanRows = new nsContentList(mParent->GetDocument(),
mOrphanRows = new nsContentList(mParent,
nsHTMLAtoms::tr,
mParent->NodeInfo()->NamespaceID(),
mParent,
PR_FALSE);
return mOrphanRows ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
@ -326,10 +325,6 @@ nsHTMLTableElement::nsHTMLTableElement(nsINodeInfo *aNodeInfo)
nsHTMLTableElement::~nsHTMLTableElement()
{
if (mTBodies) {
mTBodies->RootDestroyed();
}
if (mRows) {
mRows->ParentDestroyed();
}
@ -519,10 +514,9 @@ nsHTMLTableElement::GetTBodies(nsIDOMHTMLCollection** aValue)
{
if (!mTBodies) {
// Not using NS_GetContentList because this should not be cached
mTBodies = new nsContentList(GetDocument(),
mTBodies = new nsContentList(this,
nsHTMLAtoms::tbody,
mNodeInfo->NamespaceID(),
this,
PR_FALSE);
NS_ENSURE_TRUE(mTBodies, NS_ERROR_OUT_OF_MEMORY);

Просмотреть файл

@ -59,7 +59,6 @@ class nsHTMLTableRowElement : public nsGenericHTMLElement,
{
public:
nsHTMLTableRowElement(nsINodeInfo *aNodeInfo);
virtual ~nsHTMLTableRowElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
@ -123,14 +122,6 @@ nsHTMLTableRowElement::nsHTMLTableRowElement(nsINodeInfo *aNodeInfo)
{
}
nsHTMLTableRowElement::~nsHTMLTableRowElement()
{
if (mCells) {
mCells->RootDestroyed();
}
}
NS_IMPL_ADDREF_INHERITED(nsHTMLTableRowElement, nsGenericElement)
NS_IMPL_RELEASE_INHERITED(nsHTMLTableRowElement, nsGenericElement)
@ -270,10 +261,9 @@ NS_IMETHODIMP
nsHTMLTableRowElement::GetCells(nsIDOMHTMLCollection** aValue)
{
if (!mCells) {
mCells = new nsContentList(GetDocument(),
mCells = new nsContentList(this,
IsCell,
EmptyString(),
this,
PR_FALSE,
nsnull,
kNameSpaceID_None,

Просмотреть файл

@ -54,7 +54,6 @@ class nsHTMLTableSectionElement : public nsGenericHTMLElement,
{
public:
nsHTMLTableSectionElement(nsINodeInfo *aNodeInfo);
virtual ~nsHTMLTableSectionElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
@ -91,14 +90,6 @@ nsHTMLTableSectionElement::nsHTMLTableSectionElement(nsINodeInfo *aNodeInfo)
{
}
nsHTMLTableSectionElement::~nsHTMLTableSectionElement()
{
if (mRows) {
mRows->RootDestroyed();
}
}
NS_IMPL_ADDREF_INHERITED(nsHTMLTableSectionElement, nsGenericElement)
NS_IMPL_RELEASE_INHERITED(nsHTMLTableSectionElement, nsGenericElement)
@ -126,10 +117,9 @@ nsHTMLTableSectionElement::GetRows(nsIDOMHTMLCollection** aValue)
*aValue = nsnull;
if (!mRows) {
mRows = new nsContentList(GetDocument(),
mRows = new nsContentList(this,
nsHTMLAtoms::tr,
mNodeInfo->NamespaceID(),
this,
PR_FALSE);
NS_ENSURE_TRUE(mRows, NS_ERROR_OUT_OF_MEMORY);

Просмотреть файл

@ -64,6 +64,8 @@
#include "prtime.h"
#include "prlog.h"
#include "nsInt64.h"
#include "nsNodeUtils.h"
#include "nsIContent.h"
#include "nsGenericHTMLElement.h"
#include "nsITextContent.h"
@ -1852,20 +1854,22 @@ HTMLContentSink::~HTMLContentSink()
}
#if DEBUG
NS_IMPL_ISUPPORTS_INHERITED6(HTMLContentSink,
nsContentSink,
nsIContentSink,
nsIHTMLContentSink,
nsITimerCallback,
nsIDocumentObserver,
nsIMutationObserver,
nsIDebugDumpContent)
#else
NS_IMPL_ISUPPORTS_INHERITED5(HTMLContentSink,
nsContentSink,
nsIContentSink,
nsIHTMLContentSink,
nsITimerCallback,
nsIDocumentObserver,
nsIDebugDumpContent)
#else
NS_IMPL_ISUPPORTS_INHERITED4(HTMLContentSink,
nsContentSink,
nsIContentSink,
nsIHTMLContentSink,
nsITimerCallback,
nsIDocumentObserver)
nsIMutationObserver)
#endif
static PRBool
@ -3615,7 +3619,7 @@ HTMLContentSink::NotifyAppend(nsIContent* aContainer, PRUint32 aStartIndex)
MOZ_TIMER_SAVE(mWatch)
MOZ_TIMER_STOP(mWatch);
mDocument->ContentAppended(aContainer, aStartIndex);
nsNodeUtils::ContentAppended(aContainer, aStartIndex);
mLastNotificationTime = PR_Now();
MOZ_TIMER_DEBUGLOG(("Restore: nsHTMLContentSink::NotifyAppend()\n"));
@ -3641,7 +3645,8 @@ HTMLContentSink::NotifyInsert(nsIContent* aContent,
MOZ_TIMER_SAVE(mWatch)
MOZ_TIMER_STOP(mWatch);
mDocument->ContentInserted(aContent, aChildContent, aIndexInContainer);
nsNodeUtils::ContentInserted(NODE_FROM(aContent, mDocument),
aChildContent, aIndexInContainer);
mLastNotificationTime = PR_Now();
MOZ_TIMER_DEBUGLOG(("Restore: nsHTMLContentSink::NotifyInsert()\n"));

Просмотреть файл

@ -84,6 +84,7 @@
#include "nsIScriptSecurityManager.h"
#include "nsIScrollableView.h"
#include "nsAttrName.h"
#include "nsNodeUtils.h"
#include "nsNetCID.h"
#include "nsIIOService.h"
@ -1196,42 +1197,40 @@ nsHTMLDocument::SetCompatibilityMode(nsCompatibility aMode)
}
void
nsHTMLDocument::ContentAppended(nsIContent* aContainer,
nsHTMLDocument::ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
NS_ABORT_IF_FALSE(aContainer, "Null container!");
NS_ASSERTION(aDocument == this, "unexpected doc");
// Register new content. That is the content numbered from
// aNewIndexInContainer and upwards.
PRUint32 count = aContainer->GetChildCount();
for (PRUint32 i = aNewIndexInContainer; i < count; ++i) {
RegisterNamedItems(aContainer->GetChildAt(i));
}
nsDocument::ContentAppended(aContainer, aNewIndexInContainer);
}
void
nsHTMLDocument::ContentInserted(nsIContent* aContainer, nsIContent* aContent,
nsHTMLDocument::ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aContent,
PRInt32 aIndexInContainer)
{
NS_ASSERTION(aDocument == this, "unexpected doc");
NS_ABORT_IF_FALSE(aContent, "Null content!");
nsresult rv = RegisterNamedItems(aContent);
if (NS_FAILED(rv)) {
return;
}
nsDocument::ContentInserted(aContainer, aContent, aIndexInContainer);
RegisterNamedItems(aContent);
}
void
nsHTMLDocument::ContentRemoved(nsIContent* aContainer, nsIContent* aContent,
nsHTMLDocument::ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
NS_ABORT_IF_FALSE(aContent, "Null content!");
NS_ASSERTION(aDocument == this, "unexpected doc");
NS_ABORT_IF_FALSE(aChild, "Null content!");
if (aContainer == mRootContent) {
// Reset mBodyContent in case we got a new body.
@ -1239,13 +1238,7 @@ nsHTMLDocument::ContentRemoved(nsIContent* aContainer, nsIContent* aContent,
mBodyContent = nsnull;
}
nsresult rv = UnregisterNamedItems(aContent);
if (NS_FAILED(rv)) {
return;
}
nsDocument::ContentRemoved(aContainer, aContent, aIndexInContainer);
UnregisterNamedItems(aChild);
}
void
@ -1278,9 +1271,12 @@ nsHTMLDocument::AttributeWillChange(nsIContent* aContent, PRInt32 aNameSpaceID,
}
void
nsHTMLDocument::AttributeChanged(nsIContent* aContent, PRInt32 aNameSpaceID,
nsHTMLDocument::AttributeChanged(nsIDocument* aDocument,
nsIContent* aContent, PRInt32 aNameSpaceID,
nsIAtom* aAttribute, PRInt32 aModType)
{
NS_ASSERTION(aDocument == this, "unexpected doc");
NS_ABORT_IF_FALSE(aContent, "Null content!");
NS_PRECONDITION(aAttribute, "Must have an attribute that's changing!");
@ -1289,25 +1285,15 @@ nsHTMLDocument::AttributeChanged(nsIContent* aContent, PRInt32 aNameSpaceID,
nsIAtom* name = IsNamedItem(aContent);
if (name) {
nsresult rv = UpdateNameTableEntry(name, aContent);
if (NS_FAILED(rv)) {
return;
}
UpdateNameTableEntry(name, aContent);
}
} else if (aAttribute == aContent->GetIDAttributeName() &&
aNameSpaceID == kNameSpaceID_None) {
nsIAtom* id = aContent->GetID();
if (id) {
nsresult rv = UpdateIdTableEntry(id, aContent);
if (NS_FAILED(rv)) {
return;
}
UpdateIdTableEntry(id, aContent);
}
}
nsDocument::AttributeChanged(aContent, aNameSpaceID, aAttribute, aModType);
}
void
@ -2078,7 +2064,7 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
if (root) {
// Tear down the frames for the root element.
ContentRemoved(nsnull, root, 0);
nsNodeUtils::ContentRemoved(this, root, 0);
// Put the root element back into the document, we don't notify
// the document about this insertion since the sink will do that

Просмотреть файл

@ -124,18 +124,6 @@ public:
virtual NS_HIDDEN_(nsContentList*) GetFormControls();
virtual void ContentAppended(nsIContent* aContainer,
PRInt32 aNewIndexInContainer);
virtual void ContentInserted(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
virtual void ContentRemoved(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
virtual void AttributeChanged(nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
virtual void AttributeWillChange(nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute);
@ -144,6 +132,23 @@ public:
virtual PRBool IsCaseSensitive();
// nsIMutationObserver
virtual void ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer);
virtual void ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
virtual void ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
virtual void AttributeChanged(nsIDocument* aDocument,
nsIContent* aChild,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
// nsIDOMDocument interface
NS_DECL_NSIDOMDOCUMENT

Просмотреть файл

@ -289,7 +289,8 @@ SetOrRemoveObject(PLDHashTable& table, nsISupports* aKey, nsISupports* aValue)
// Static member variable initialization
// Implement our nsISupports methods
NS_IMPL_ISUPPORTS3(nsBindingManager, nsIBindingManager, nsIStyleRuleSupplier, nsIDocumentObserver)
NS_IMPL_ISUPPORTS4(nsBindingManager, nsIBindingManager, nsIStyleRuleSupplier,
nsIDocumentObserver, nsIMutationObserver)
// Constructors/Destructors
nsBindingManager::nsBindingManager(void)

Просмотреть файл

@ -97,6 +97,7 @@
#include "nsContentPolicyUtils.h"
#include "nsContentErrors.h"
#include "nsIDOMProcessingInstruction.h"
#include "nsNodeUtils.h"
#ifdef MOZ_SVG
#include "nsSVGAtoms.h"
@ -315,10 +316,8 @@ nsXMLContentSink::DidBuildModel()
"mDocElement not in doc?");
mozAutoDocUpdate docUpdate(mDocument, UPDATE_CONTENT_MODEL, PR_TRUE);
mDocument->ContentInserted(nsnull, mDocElement,
// XXXbz is this last arg relevant if
// the container is null?
mDocument->IndexOf(mDocElement));
nsNodeUtils::ContentInserted(mDocument, mDocElement,
mDocument->IndexOf(mDocElement));
}
// Check if we want to prettyprint
@ -405,10 +404,8 @@ nsXMLContentSink::OnTransformDone(nsresult aResult,
NS_ASSERTION(mDocument->IndexOf(rootContent) != -1,
"rootContent not in doc?");
mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
mDocument->ContentInserted(nsnull, rootContent,
// XXXbz is this last arg relevant if
// the container is null?
mDocument->IndexOf(rootContent));
nsNodeUtils::ContentInserted(mDocument, rootContent,
mDocument->IndexOf(rootContent));
mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
}

Просмотреть файл

@ -55,8 +55,9 @@
#include "nsIContent.h"
#include "nsIDOMDocumentFragment.h"
NS_IMPL_ISUPPORTS1(nsXMLPrettyPrinter,
nsIDocumentObserver)
NS_IMPL_ISUPPORTS2(nsXMLPrettyPrinter,
nsIDocumentObserver,
nsIMutationObserver)
nsXMLPrettyPrinter::nsXMLPrettyPrinter() : mDocument(nsnull),
mUpdateDepth(0),
@ -267,7 +268,7 @@ nsXMLPrettyPrinter::ContentRemoved(nsIDocument* aDocument,
}
void
nsXMLPrettyPrinter::DocumentWillBeDestroyed(nsIDocument* aDocument)
nsXMLPrettyPrinter::NodeWillBeDestroyed(const nsINode* aNode)
{
mDocument = nsnull;
NS_RELEASE_THIS();

Просмотреть файл

@ -65,7 +65,7 @@ public:
PRInt32 aIndexInContainer);
virtual void ContentRemoved(nsIDocument* aDocument, nsIContent* aContainer,
nsIContent* aChild, PRInt32 aIndexInContainer);
virtual void DocumentWillBeDestroyed(nsIDocument* aDocument);
virtual void NodeWillBeDestroyed(const nsINode* aNode);
/**
* This will prettyprint the document if the document is loaded in a

Просмотреть файл

@ -45,6 +45,7 @@ class nsIDOMNode;
class nsILoadGroup;
class nsIURI;
class nsIPrincipal;
class nsString;
#define NS_ITRANSFORMOBSERVER_IID \
{0xcce88481, 0x6eb3, 0x11d6, \

Просмотреть файл

@ -57,7 +57,7 @@ nsXPathResult::nsXPathResult() : mDocument(nsnull),
nsXPathResult::~nsXPathResult()
{
if (mDocument) {
mDocument->RemoveObserver(this);
mDocument->RemoveMutationObserver(this);
}
}
@ -65,7 +65,7 @@ NS_IMPL_ADDREF(nsXPathResult)
NS_IMPL_RELEASE(nsXPathResult)
NS_INTERFACE_MAP_BEGIN(nsXPathResult)
NS_INTERFACE_MAP_ENTRY(nsIDOMXPathResult)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY(nsIXPathResult)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMXPathResult)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XPathResult)
@ -199,10 +199,13 @@ nsXPathResult::SnapshotItem(PRUint32 aIndex, nsIDOMNode **aResult)
return NS_OK;
}
NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(nsXPathResult)
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsXPathResult)
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsXPathResult)
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsXPathResult)
void
nsXPathResult::NodeWillBeDestroyed(const nsINode* aNode)
{
// Set to null to avoid unregistring unnecessarily
mDocument = nsnull;
Invalidate();
}
void
nsXPathResult::CharacterDataChanged(nsIDocument* aDocument,
@ -259,7 +262,7 @@ nsXPathResult::SetExprResult(txAExprResult* aExprResult, PRUint16 aResultType)
}
if (mDocument) {
mDocument->RemoveObserver(this);
mDocument->RemoveMutationObserver(this);
mDocument = nsnull;
}
@ -291,7 +294,7 @@ nsXPathResult::SetExprResult(txAExprResult* aExprResult, PRUint16 aResultType)
NS_ASSERTION(mDocument, "We need a document!");
if (mDocument) {
mDocument->AddObserver(this);
mDocument->AddMutationObserver(this);
}
}
@ -302,7 +305,7 @@ void
nsXPathResult::Invalidate()
{
if (mDocument) {
mDocument->RemoveObserver(this);
mDocument->RemoveMutationObserver(this);
mDocument = nsnull;
}
mInvalidIteratorState = PR_TRUE;

Просмотреть файл

@ -42,7 +42,7 @@
#include "txExprResult.h"
#include "nsIDOMXPathResult.h"
#include "nsIDocument.h"
#include "nsIDocumentObserver.h"
#include "nsIMutationObserver.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
@ -90,7 +90,7 @@ private:
* A class for evaluating an XPath expression string
*/
class nsXPathResult : public nsIDOMXPathResult,
public nsIDocumentObserver,
public nsIMutationObserver,
public nsIXPathResult
{
public:
@ -103,8 +103,8 @@ public:
// nsIDOMXPathResult interface
NS_DECL_NSIDOMXPATHRESULT
// nsIDocumentObserver interface
NS_DECL_NSIDOCUMENTOBSERVER
// nsIMutationObserver interface
NS_DECL_NSIMUTATIONOBSERVER
// nsIXPathResult interface
nsresult SetExprResult(txAExprResult *aExprResult, PRUint16 aResultType);

Просмотреть файл

@ -301,7 +301,7 @@ NS_INTERFACE_MAP_BEGIN(txMozillaXSLTProcessor)
NS_INTERFACE_MAP_ENTRY(nsIXSLTProcessor)
NS_INTERFACE_MAP_ENTRY(nsIXSLTProcessorObsolete)
NS_INTERFACE_MAP_ENTRY(nsIDocumentTransformer)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXSLTProcessor)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XSLTProcessor)
NS_INTERFACE_MAP_END
@ -316,7 +316,7 @@ txMozillaXSLTProcessor::txMozillaXSLTProcessor() : mStylesheetDocument(nsnull),
txMozillaXSLTProcessor::~txMozillaXSLTProcessor()
{
if (mStylesheetDocument) {
mStylesheetDocument->RemoveObserver(this);
mStylesheetDocument->RemoveMutationObserver(this);
}
}
@ -612,7 +612,7 @@ txMozillaXSLTProcessor::ImportStylesheet(nsIDOMNode *aStyle)
mStylesheetDocument = styleDoc;
}
mStylesheetDocument->AddObserver(this);
mStylesheetDocument->AddMutationObserver(this);
return NS_OK;
}
@ -973,7 +973,7 @@ NS_IMETHODIMP
txMozillaXSLTProcessor::Reset()
{
if (mStylesheetDocument) {
mStylesheetDocument->RemoveObserver(this);
mStylesheetDocument->RemoveMutationObserver(this);
}
mStylesheet = nsnull;
mStylesheetDocument = nsnull;
@ -1149,24 +1149,8 @@ txMozillaXSLTProcessor::ensureStylesheet()
return TX_CompileStylesheet(style, getter_AddRefs(mStylesheet));
}
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(txMozillaXSLTProcessor)
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(txMozillaXSLTProcessor)
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(txMozillaXSLTProcessor)
void
txMozillaXSLTProcessor::BeginUpdate(nsIDocument* aDocument,
nsUpdateType aUpdateType)
{
}
void
txMozillaXSLTProcessor::EndUpdate(nsIDocument* aDocument,
nsUpdateType aUpdateType)
{
}
void
txMozillaXSLTProcessor::DocumentWillBeDestroyed(nsIDocument* aDocument)
txMozillaXSLTProcessor::NodeWillBeDestroyed(const nsINode* aNode)
{
if (NS_FAILED(mCompileResult)) {
return;
@ -1175,11 +1159,6 @@ txMozillaXSLTProcessor::DocumentWillBeDestroyed(nsIDocument* aDocument)
mCompileResult = ensureStylesheet();
mStylesheetDocument = nsnull;
mEmbeddedStylesheetRoot = nsnull;
// This might not be necessary, but just in case some element ends up
// causing a notification as the document goes away we don't want to
// invalidate the stylesheet.
aDocument->RemoveObserver(this);
}
void

Просмотреть файл

@ -40,7 +40,7 @@
#define TRANSFRMX_TXMOZILLAXSLTPROCESSOR_H
#include "nsAutoPtr.h"
#include "nsIDocumentObserver.h"
#include "nsIMutationObserver.h"
#include "nsIDocumentTransformer.h"
#include "nsIXSLTProcessor.h"
#include "nsIXSLTProcessorObsolete.h"
@ -69,7 +69,7 @@ class txResultRecycler;
class txMozillaXSLTProcessor : public nsIXSLTProcessor,
public nsIXSLTProcessorObsolete,
public nsIDocumentTransformer,
public nsIDocumentObserver
public nsIMutationObserver
{
public:
/**
@ -105,8 +105,8 @@ public:
const nsString& aValue,
nsIDOMNode* aContext);
// nsIDocumentObserver interface
NS_DECL_NSIDOCUMENTOBSERVER
// nsIMutationObserver interface
NS_DECL_NSIMUTATIONOBSERVER
nsresult setStylesheet(txStylesheet* aStylesheet);
void reportError(nsresult aResult, const PRUnichar *aErrorText,

Просмотреть файл

@ -137,6 +137,7 @@
#include "nsHTMLAtoms.h"
#include "nsLayoutAtoms.h"
#include "nsXULContentUtils.h"
#include "nsNodeUtils.h"
#include "prlog.h"
#include "rdf.h"
@ -499,10 +500,9 @@ nsXULElement::GetElementsByAttribute(const nsAString& aAttribute,
NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY);
nsContentList *list =
new nsContentList(GetDocument(),
new nsContentList(this,
nsXULDocument::MatchAttribute,
aValue,
this,
PR_TRUE,
attrAtom,
kNameSpaceID_Unknown);
@ -1472,10 +1472,11 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
if (binding)
binding->AttributeChanged(aName, aNameSpaceID, PR_TRUE, aNotify);
if (aNotify) {
doc->AttributeChanged(this, aNameSpaceID, aName,
nsIDOMMutationEvent::REMOVAL);
}
}
if (aNotify) {
nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
nsIDOMMutationEvent::REMOVAL);
}
return NS_OK;

Просмотреть файл

@ -122,6 +122,7 @@
#include "nsEventDispatcher.h"
#include "nsContentErrors.h"
#include "nsIObserverService.h"
#include "nsNodeUtils.h"
//----------------------------------------------------------------------
//
@ -212,10 +213,11 @@ nsXULDocument::~nsXULDocument()
NS_ASSERTION(mNextSrcLoadWaiter == nsnull,
"unreferenced document still waiting for script source to load?");
// Notify our observers here, we can't let the nsDocument
// Notify our observers here, we can't let the nsINode
// destructor do that for us since some of the observers are
// deleted by the time we get there.
NS_DOCUMENT_NOTIFY_OBSERVERS(DocumentWillBeDestroyed, (this));
nsNodeUtils::NodeWillBeDestroyed(this);
// Clear mObservers to keep it in sync with the mutationobserver list
mObservers.Clear();
// In case we failed somewhere early on and the forward observer
@ -886,9 +888,12 @@ nsXULDocument::ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster,
}
void
nsXULDocument::AttributeChanged(nsIContent* aElement, PRInt32 aNameSpaceID,
nsXULDocument::AttributeChanged(nsIDocument* aDocument,
nsIContent* aElement, PRInt32 aNameSpaceID,
nsIAtom* aAttribute, PRInt32 aModType)
{
NS_ASSERTION(aDocument == this, "unexpected doc");
nsresult rv;
// XXXbz check aNameSpaceID, dammit!
@ -966,46 +971,42 @@ nsXULDocument::AttributeChanged(nsIContent* aElement, PRInt32 aNameSpaceID,
}
void
nsXULDocument::ContentAppended(nsIContent* aContainer,
nsXULDocument::ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
// First update our element map
NS_ASSERTION(aDocument == this, "unexpected doc");
// Update our element map
PRUint32 count = aContainer->GetChildCount();
for (PRUint32 i = aNewIndexInContainer; i < count; ++i) {
nsresult rv = AddSubtreeToDocument(aContainer->GetChildAt(i));
if (NS_FAILED(rv))
return;
nsresult rv = NS_OK;
for (PRUint32 i = aNewIndexInContainer; i < count && NS_SUCCEEDED(rv);
++i) {
rv = AddSubtreeToDocument(aContainer->GetChildAt(i));
}
nsXMLDocument::ContentAppended(aContainer, aNewIndexInContainer);
}
void
nsXULDocument::ContentInserted(nsIContent* aContainer,
nsXULDocument::ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
nsresult rv = AddSubtreeToDocument(aChild);
if (NS_FAILED(rv))
return;
NS_ASSERTION(aDocument == this, "unexpected doc");
nsXMLDocument::ContentInserted(aContainer, aChild,
aIndexInContainer);
AddSubtreeToDocument(aChild);
}
void
nsXULDocument::ContentRemoved(nsIContent* aContainer,
nsXULDocument::ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
nsresult rv;
rv = RemoveSubtreeFromDocument(aChild);
if (NS_FAILED(rv))
return;
NS_ASSERTION(aDocument == this, "unexpected doc");
nsXMLDocument::ContentRemoved(aContainer, aChild,
aIndexInContainer);
RemoveSubtreeFromDocument(aChild);
}
//----------------------------------------------------------------------
@ -1150,7 +1151,6 @@ nsXULDocument::GetElementsByAttribute(const nsAString& aAttribute,
nsContentList *list = new nsContentList(this,
MatchAttribute,
aValue,
nsnull,
PR_TRUE,
attrAtom,
kNameSpaceID_Unknown);

Просмотреть файл

@ -109,19 +109,21 @@ public:
virtual void EndLoad();
virtual void ContentAppended(nsIContent* aContainer,
// nsIMutationObserver interface
virtual void ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer);
virtual void ContentInserted(nsIContent* aContainer,
virtual void ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
virtual void ContentRemoved(nsIContent* aContainer,
virtual void ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
virtual void AttributeChanged(nsIContent* aElement, PRInt32 aNameSpaceID,
nsIAtom* aAttribute, PRInt32 aModType);
virtual void AttributeChanged(nsIDocument* aDocument, nsIContent* aElement,
PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRInt32 aModType);
// nsIXULDocument interface
NS_IMETHOD AddElementForID(const nsAString& aID, nsIContent* aElement);

Просмотреть файл

@ -68,6 +68,7 @@
#include "nsContentCreatorFunctions.h"
#include "nsContentUtils.h"
#include "nsAttrName.h"
#include "nsNodeUtils.h"
#include "jsapi.h"
#include "pldhash.h"
@ -147,7 +148,7 @@ public:
nsIAtom* aAttribute,
PRInt32 aModType);
void DocumentWillBeDestroyed(nsIDocument* aDocument);
void NodeWillBeDestroyed(const nsINode* aNode);
protected:
friend NS_IMETHODIMP
@ -1770,12 +1771,12 @@ nsXULContentBuilder::AttributeChanged(nsIDocument* aDocument,
}
void
nsXULContentBuilder::DocumentWillBeDestroyed(nsIDocument *aDocument)
nsXULContentBuilder::NodeWillBeDestroyed(const nsINode* aNode)
{
// Break circular references
mContentSupportMap.Clear();
nsXULTemplateBuilder::DocumentWillBeDestroyed(aDocument);
nsXULTemplateBuilder::NodeWillBeDestroyed(aNode);
}
@ -2005,11 +2006,7 @@ nsXULContentBuilder::OpenContainer(nsIContent* aElement)
if (container && IsLazyWidgetItem(aElement)) {
// The tree widget is special, and has to be spanked every
// time we add content to a container.
nsCOMPtr<nsIDocument> doc = mRoot->GetDocument();
if (! doc)
return NS_OK;
doc->ContentAppended(container, newIndex);
nsNodeUtils::ContentAppended(container, newIndex);
}
return NS_OK;
@ -2075,12 +2072,7 @@ nsXULContentBuilder::RebuildAll()
CreateTemplateAndContainerContents(mRoot, getter_AddRefs(container), &newIndex);
if (container) {
nsCOMPtr<nsIDocument> doc = mRoot->GetDocument();
NS_ASSERTION(doc, "root element has no document");
if (! doc)
return NS_ERROR_UNEXPECTED;
doc->ContentAppended(container, newIndex);
nsNodeUtils::ContentAppended(container, newIndex);
}
return NS_OK;

Просмотреть файл

@ -237,6 +237,7 @@ NS_IMPL_RELEASE(nsXULTemplateBuilder)
NS_INTERFACE_MAP_BEGIN(nsXULTemplateBuilder)
NS_INTERFACE_MAP_ENTRY(nsIXULTemplateBuilder)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULTemplateBuilder)
NS_INTERFACE_MAP_ENTRY_DOM_CLASSINFO(XULTemplateBuilder)
NS_INTERFACE_MAP_END
@ -918,7 +919,7 @@ nsXULTemplateBuilder::ContentRemoved(nsIDocument* aDocument,
}
void
nsXULTemplateBuilder::DocumentWillBeDestroyed(nsIDocument *aDocument)
nsXULTemplateBuilder::NodeWillBeDestroyed(const nsINode* aNode)
{
// The call to RemoveObserver could release the last reference to
// |this|, so hold another reference.

Просмотреть файл

@ -104,7 +104,7 @@ public:
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument);
virtual void NodeWillBeDestroyed(const nsINode* aNode);
/**
* Remove an old result and/or add a new result. This method will retrieve

Просмотреть файл

@ -88,7 +88,7 @@ public:
// nsINativeTreeView: Untrusted code can use us
NS_IMETHOD EnsureNative() { return NS_OK; }
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument);
virtual void NodeWillBeDestroyed(const nsINode* aNode);
protected:
friend NS_IMETHODIMP
@ -1099,12 +1099,12 @@ nsXULTreeBuilder::PerformActionOnCell(const PRUnichar* aAction, PRInt32 aRow, ns
void
nsXULTreeBuilder::DocumentWillBeDestroyed(nsIDocument* aDocument)
nsXULTreeBuilder::NodeWillBeDestroyed(const nsINode* aNode)
{
if (mObservers)
mObservers->Clear();
nsXULTemplateBuilder::DocumentWillBeDestroyed(aDocument);
nsXULTemplateBuilder::NodeWillBeDestroyed(aNode);
}
NS_IMETHODIMP

Просмотреть файл

@ -126,7 +126,7 @@ nsSHEntry::~nsSHEntry()
//*****************************************************************************
NS_IMPL_ISUPPORTS4(nsSHEntry, nsISHContainer, nsISHEntry, nsIHistoryEntry,
nsIDocumentObserver)
nsIMutationObserver)
//*****************************************************************************
// nsSHEntry: nsISHEntry
@ -191,7 +191,7 @@ nsSHEntry::SetContentViewer(nsIContentViewer *aViewer)
mDocument = do_QueryInterface(domDoc);
if (mDocument) {
mDocument->SetShellsHidden(PR_TRUE);
mDocument->AddObserver(this);
mDocument->AddMutationObserver(this);
}
}
@ -624,7 +624,7 @@ nsSHEntry::DropPresentationState()
if (mDocument) {
mDocument->SetShellsHidden(PR_FALSE);
mDocument->RemoveObserver(this);
mDocument->RemoveMutationObserver(this);
mDocument = nsnull;
}
if (mContentViewer)
@ -639,13 +639,14 @@ nsSHEntry::DropPresentationState()
}
//*****************************************************************************
// nsSHEntry: nsIDocumentObserver
// nsSHEntry: nsIMutationObserver
//*****************************************************************************
NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(nsSHEntry)
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsSHEntry)
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsSHEntry)
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsSHEntry)
void
nsSHEntry::NodeWillBeDestroyed(const nsINode* aNode)
{
NS_NOTREACHED("Document destroyed while we're holding a strong ref to it");
}
void
nsSHEntry::CharacterDataChanged(nsIDocument* aDocument,

Просмотреть файл

@ -57,11 +57,11 @@
#include "nsIHistoryEntry.h"
#include "nsRect.h"
#include "nsSupportsArray.h"
#include "nsIDocumentObserver.h"
#include "nsIMutationObserver.h"
class nsSHEntry : public nsISHEntry,
public nsISHContainer,
public nsIDocumentObserver
public nsIMutationObserver
{
public:
nsSHEntry();
@ -71,13 +71,12 @@ public:
NS_DECL_NSIHISTORYENTRY
NS_DECL_NSISHENTRY
NS_DECL_NSISHCONTAINER
NS_DECL_NSIDOCUMENTOBSERVER
NS_DECL_NSIMUTATIONOBSERVER
void DropPresentationState();
private:
~nsSHEntry();
void RemoveDocumentObserver();
void DocumentMutated();
nsCOMPtr<nsIURI> mURI;

Просмотреть файл

@ -226,9 +226,9 @@ nsLoadCollector::~nsLoadCollector()
GetMemUsage_Shutdown();
}
NS_IMPL_ISUPPORTS4(nsLoadCollector, nsIMetricsCollector,
NS_IMPL_ISUPPORTS5(nsLoadCollector, nsIMetricsCollector,
nsIWebProgressListener, nsISupportsWeakReference,
nsIDocumentObserver)
nsIDocumentObserver, nsIMutationObserver)
NS_IMETHODIMP
nsLoadCollector::OnStateChange(nsIWebProgress *webProgress,

Просмотреть файл

@ -1646,9 +1646,10 @@ PresShell::PresShell()
new (this) nsFrameManager();
}
NS_IMPL_ISUPPORTS7(PresShell, nsIPresShell, nsIDocumentObserver,
NS_IMPL_ISUPPORTS8(PresShell, nsIPresShell, nsIDocumentObserver,
nsIViewObserver, nsISelectionController,
nsISelectionDisplay, nsIObserver, nsISupportsWeakReference)
nsISelectionDisplay, nsIObserver, nsISupportsWeakReference,
nsIMutationObserver)
PresShell::~PresShell()
{

Просмотреть файл

@ -75,6 +75,7 @@
#include "nsLayoutAtoms.h"
#include "nsIContent.h"
#include "nsDisplayList.h"
#include "nsNodeUtils.h"
// masks for mEdgeVisibility
#define LEFT_VIS 0x0001
@ -288,10 +289,10 @@ nsHTMLFramesetFrame::FrameResizePrefCallback(const char* aPref, void* aClosure)
frame->RecalculateBorderResize();
if (doc) {
doc->AttributeChanged(frame->GetContent(),
kNameSpaceID_None,
nsHTMLAtoms::frameborder,
nsIDOMMutationEvent::MODIFICATION);
nsNodeUtils::AttributeChanged(frame->GetContent(),
kNameSpaceID_None,
nsHTMLAtoms::frameborder,
nsIDOMMutationEvent::MODIFICATION);
}
return 0;

Просмотреть файл

@ -722,7 +722,6 @@ void CircleArea::GetRect(nsPresContext* aCX, nsRect& aRect)
nsImageMap::nsImageMap() :
mPresShell(nsnull),
mImageFrame(nsnull),
mDocument(nsnull),
mContainsBlockContents(PR_FALSE)
{
}
@ -733,7 +732,7 @@ nsImageMap::~nsImageMap()
}
NS_IMPL_ISUPPORTS4(nsImageMap,
nsIDocumentObserver,
nsIMutationObserver,
nsIDOMFocusListener,
nsIDOMEventListener,
nsIImageMap)
@ -788,17 +787,12 @@ nsImageMap::Init(nsIPresShell* aPresShell, nsIFrame* aImageFrame, nsIDOMHTMLMapE
mPresShell = aPresShell;
mImageFrame = aImageFrame;
nsresult rv;
mMap = do_QueryInterface(aMap, &rv);
mMap = do_QueryInterface(aMap);
NS_ASSERTION(mMap, "aMap is not an nsIContent!");
mDocument = mMap->GetDocument();
if (mDocument) {
mDocument->AddObserver(this);
}
mMap->AddMutationObserver(this);
// "Compile" the areas in the map into faster access versions
rv = UpdateAreas();
return rv;
return UpdateAreas();
}
@ -943,9 +937,7 @@ nsImageMap::Draw(nsPresContext* aCX, nsIRenderingContext& aRC)
void
nsImageMap::MaybeUpdateAreas(nsIContent *aContent)
{
if (aContent && (aContent == mMap ||
(mContainsBlockContents &&
nsContentUtils::ContentIsDescendantOf(aContent, mMap)))) {
if (aContent == mMap || mContainsBlockContents) {
UpdateAreas();
}
}
@ -1060,7 +1052,5 @@ void
nsImageMap::Destroy(void)
{
FreeAreas();
if (mDocument) {
mDocument->RemoveObserver(this);
}
mMap->RemoveMutationObserver(this);
}

Просмотреть файл

@ -43,7 +43,7 @@
#include "nsISupports.h"
#include "nsCoord.h"
#include "nsVoidArray.h"
#include "nsStubDocumentObserver.h"
#include "nsStubMutationObserver.h"
#include "nsIDOMFocusListener.h"
#include "nsIFrame.h"
#include "nsIImageMap.h"
@ -56,7 +56,7 @@ class nsIURI;
class nsString;
class nsIDOMEvent;
class nsImageMap : public nsStubDocumentObserver, public nsIDOMFocusListener,
class nsImageMap : public nsStubMutationObserver, public nsIDOMFocusListener,
public nsIImageMap
{
public:
@ -84,7 +84,7 @@ public:
// nsISupports
NS_DECL_ISUPPORTS
// nsIDocumentObserver
// nsIMutationObserver
virtual void AttributeChanged(nsIDocument* aDocument, nsIContent* aContent,
PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRInt32 aModType);
@ -122,7 +122,6 @@ protected:
nsIPresShell* mPresShell; // WEAK - owns the frame that owns us
nsIFrame* mImageFrame; // the frame that owns us
nsIDocument* mDocument; // WEAK - the imagemap will not outlive the document
nsCOMPtr<nsIContent> mMap;
nsAutoVoidArray mAreas; // almost always has some entries
PRBool mContainsBlockContents;

Просмотреть файл

@ -155,7 +155,7 @@ inDOMView::InitAtoms()
NS_IMPL_ISUPPORTS3(inDOMView,
inIDOMView,
nsITreeView,
nsIDocumentObserver)
nsIMutationObserver)
////////////////////////////////////////////////////////////////////////
// inIDOMView
@ -176,9 +176,9 @@ inDOMView::SetRootNode(nsIDOMNode* aNode)
if (mRootDocument) {
// remove previous document observer
nsCOMPtr<nsIDocument> doc(do_QueryInterface(mRootDocument));
nsCOMPtr<nsINode> doc(do_QueryInterface(mRootDocument));
if (doc)
doc->RemoveObserver(this);
doc->RemoveMutationObserver(this);
}
RemoveAllNodes();
@ -204,9 +204,9 @@ inDOMView::SetRootNode(nsIDOMNode* aNode)
}
// add document observer
nsCOMPtr<nsIDocument> doc(do_QueryInterface(mRootDocument));
nsCOMPtr<nsINode> doc(do_QueryInterface(mRootDocument));
if (doc)
doc->AddObserver(this);
doc->AddMutationObserver(this);
} else {
mRootDocument = nsnull;
}
@ -652,12 +652,13 @@ inDOMView::PerformActionOnCell(const PRUnichar* action, PRInt32 row, nsITreeColu
}
///////////////////////////////////////////////////////////////////////
// nsIDocumentObserver
// nsIMutationObserver
NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(inDOMView)
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(inDOMView)
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(inDOMView)
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(inDOMView)
void
inDOMView::NodeWillBeDestroyed(const nsINode* aNode)
{
NS_NOTREACHED("Document destroyed while we're holding a strong ref to it");
}
void
inDOMView::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,

Просмотреть файл

@ -43,7 +43,7 @@
#include "nsITreeView.h"
#include "nsITreeSelection.h"
#include "nsIDocumentObserver.h"
#include "nsIMutationObserver.h"
#include "nsIDOMNode.h"
#include "nsIDOMDocument.h"
#include "nsVoidArray.h"
@ -54,7 +54,7 @@ class inDOMViewNode;
class inDOMView : public inIDOMView,
public nsITreeView,
public nsIDocumentObserver
public nsIMutationObserver
{
public:
NS_DECL_ISUPPORTS
@ -64,8 +64,8 @@ public:
inDOMView();
virtual ~inDOMView();
// nsIDocumentObserver
NS_DECL_NSIDOCUMENTOBSERVER
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER
static void InitAtoms();

Просмотреть файл

@ -165,6 +165,7 @@ NS_INTERFACE_MAP_BEGIN(nsTreeContentView)
NS_INTERFACE_MAP_ENTRY(nsITreeView)
NS_INTERFACE_MAP_ENTRY(nsITreeContentView)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITreeContentView)
NS_INTERFACE_MAP_ENTRY_DOM_CLASSINFO(TreeContentView)
NS_INTERFACE_MAP_END
@ -1096,7 +1097,7 @@ nsTreeContentView::ContentRemoved(nsIDocument *aDocument,
}
void
nsTreeContentView::DocumentWillBeDestroyed(nsIDocument *aDocument)
nsTreeContentView::NodeWillBeDestroyed(const nsINode* aNode)
{
ClearRows();
}

Просмотреть файл

@ -86,7 +86,7 @@ class nsTreeContentView : public nsINativeTreeView,
PRInt32 aIndexInContainer);
virtual void ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
nsIContent* aChild, PRInt32 aIndexInContainer);
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument);
virtual void NodeWillBeDestroyed(const nsINode* aNode);
protected:
// Recursive methods which deal with serializing of nested content.

Просмотреть файл

@ -41,7 +41,7 @@
#include "nsIMenuBar.h"
#include "nsIMenuListener.h"
#include "nsIDocumentObserver.h"
#include "nsIMutationObserver.h"
#include "nsIChangeManager.h"
#include "nsIMenuCommandDispatcher.h"
#include "nsCOMArray.h"
@ -81,7 +81,7 @@ namespace MenuHelpersX
class nsMenuBarX : public nsIMenuBar,
public nsIMenuListener,
public nsIDocumentObserver,
public nsIMutationObserver,
public nsIChangeManager,
public nsIMenuCommandDispatcher,
public nsSupportsWeakReference
@ -111,8 +111,8 @@ public:
nsEventStatus CheckRebuild(PRBool & aMenuEvent);
nsEventStatus SetRebuild(PRBool aMenuEvent);
// nsIDocumentObserver
NS_DECL_NSIDOCUMENTOBSERVER
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER
NS_IMETHOD Create(nsIWidget * aParent);

Просмотреть файл

@ -55,7 +55,7 @@
#include "nsIDocument.h"
#include "nsIDocShell.h"
#include "nsIDocumentViewer.h"
#include "nsIDocumentObserver.h"
#include "nsIMutationObserver.h"
#include "nsIDOMDocument.h"
#include "nsWidgetAtoms.h"
@ -68,7 +68,7 @@
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
NS_IMPL_ISUPPORTS6(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIDocumentObserver,
NS_IMPL_ISUPPORTS6(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIMutationObserver,
nsIChangeManager, nsIMenuCommandDispatcher, nsISupportsWeakReference)
NSMenu* nsMenuBarX::sApplicationMenu = nsnull;
@ -94,8 +94,7 @@ nsMenuBarX::~nsMenuBarX()
// make sure we unregister ourselves as a document observer
if (mDocument) {
nsCOMPtr<nsIDocumentObserver> observer(do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)));
mDocument->RemoveObserver(observer);
mDocument->RemoveMutationObserver(this);
}
[mRootMenu autorelease];
@ -201,8 +200,7 @@ nsMenuBarX::RegisterAsDocumentObserver(nsIDocShell* inDocShell)
return;
// register ourselves
nsCOMPtr<nsIDocumentObserver> observer(do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)));
doc->AddObserver(observer);
doc->AddMutationObserver(this);
// also get pointer to doc, just in case docshell goes away
// we can still remove ourself as doc observer directly from doc
mDocument = doc;
@ -809,24 +807,10 @@ NS_IMETHODIMP nsMenuBarX::Paint()
//
// nsIDocumentObserver
// nsIMutationObserver
// this is needed for menubar changes
//
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsMenuBarX)
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsMenuBarX)
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsMenuBarX)
void
nsMenuBarX::BeginUpdate(nsIDocument * aDocument, nsUpdateType aUpdateType)
{
}
void
nsMenuBarX::EndUpdate(nsIDocument * aDocument, nsUpdateType aUpdateType)
{
}
void
nsMenuBarX::CharacterDataChanged(nsIDocument * aDocument,
nsIContent * aContent, PRBool aAppend)
@ -854,7 +838,7 @@ nsMenuBarX::ContentAppended(nsIDocument * aDocument, nsIContent * aContainer,
}
void
nsMenuBarX::DocumentWillBeDestroyed(nsIDocument * aDocument)
nsMenuBarX::NodeWillBeDestroyed(const nsINode * aNode)
{
mDocument = nsnull;
}

Просмотреть файл

@ -53,7 +53,7 @@
#include "nsIDocument.h"
#include "nsIDocShell.h"
#include "nsIDocumentViewer.h"
#include "nsIDocumentObserver.h"
#include "nsIMutationObserver.h"
#include "nsIDOMDocument.h"
#include "nsWidgetAtoms.h"
@ -66,7 +66,7 @@
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
NS_IMPL_ISUPPORTS6(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIDocumentObserver,
NS_IMPL_ISUPPORTS6(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIMutationObserver,
nsIChangeManager, nsIMenuCommandDispatcher, nsISupportsWeakReference)
MenuRef nsMenuBarX::sAppleMenu = nsnull;
@ -96,8 +96,7 @@ nsMenuBarX::~nsMenuBarX()
// make sure we unregister ourselves as a document observer
if ( mDocument ) {
nsCOMPtr<nsIDocumentObserver> observer ( do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)) );
mDocument->RemoveObserver(observer);
mDocument->RemoveMutationObserver(this);
}
if ( mRootMenu )
@ -204,8 +203,7 @@ nsMenuBarX :: RegisterAsDocumentObserver ( nsIDocShell* inDocShell )
return;
// register ourselves
nsCOMPtr<nsIDocumentObserver> observer ( do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)) );
doc->AddObserver(observer);
doc->AddMutationObserver(this);
// also get pointer to doc, just in case docshell goes away
// we can still remove ourself as doc observer directly from doc
mDocument = doc;
@ -657,24 +655,10 @@ NS_METHOD nsMenuBarX::Paint()
#pragma mark -
//
// nsIDocumentObserver
// nsIMutationObserver
// this is needed for menubar changes
//
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsMenuBarX)
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsMenuBarX)
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsMenuBarX)
void
nsMenuBarX::BeginUpdate( nsIDocument * aDocument, nsUpdateType aUpdateType )
{
}
void
nsMenuBarX::EndUpdate( nsIDocument * aDocument, nsUpdateType aUpdateType )
{
}
void
nsMenuBarX::CharacterDataChanged( nsIDocument * aDocument,
nsIContent * aContent, PRBool aAppend)
@ -702,7 +686,7 @@ nsMenuBarX::ContentAppended( nsIDocument * aDocument, nsIContent * aContainer,
}
void
nsMenuBarX::DocumentWillBeDestroyed( nsIDocument * aDocument )
nsMenuBarX::NodeWillBeDestroyed(const nsINode* aNode)
{
mDocument = nsnull;
}

Просмотреть файл

@ -40,7 +40,7 @@
#include "nsIMenuBar.h"
#include "nsIMenuListener.h"
#include "nsIDocumentObserver.h"
#include "nsIMutationObserver.h"
#include "nsIChangeManager.h"
#include "nsIMenuCommandDispatcher.h"
#include "nsPresContext.h"
@ -71,7 +71,7 @@ namespace MenuHelpersX
class nsMenuBarX : public nsIMenuBar,
public nsIMenuListener,
public nsIDocumentObserver,
public nsIMutationObserver,
public nsIChangeManager,
public nsIMenuCommandDispatcher,
public nsSupportsWeakReference
@ -96,8 +96,8 @@ public:
nsEventStatus CheckRebuild(PRBool & aMenuEvent);
nsEventStatus SetRebuild(PRBool aMenuEvent);
// nsIDocumentObserver
NS_DECL_NSIDOCUMENTOBSERVER
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER
NS_IMETHOD Create(nsIWidget * aParent);