diff --git a/mozilla/accessible/src/base/nsDocAccessible.cpp b/mozilla/accessible/src/base/nsDocAccessible.cpp index dc21ac044c7..d1eb1be3705 100644 --- a/mozilla/accessible/src/base/nsDocAccessible.cpp +++ b/mozilla/accessible/src/base/nsDocAccessible.cpp @@ -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) diff --git a/mozilla/content/base/public/Makefile.in b/mozilla/content/base/public/Makefile.in index 80e62e83790..d881d1e9214 100644 --- a/mozilla/content/base/public/Makefile.in +++ b/mozilla/content/base/public/Makefile.in @@ -56,6 +56,7 @@ nsContentUtils.h \ nsIDocument.h \ nsIDocumentObserver.h \ nsIDOMGCParticipant.h \ +nsIMutationObserver.h \ nsINameSpaceManager.h \ nsINode.h \ nsINodeInfo.h \ diff --git a/mozilla/content/base/public/nsIAttribute.h b/mozilla/content/base/public/nsIAttribute.h index 58695ea1394..821387aedfe 100644 --- a/mozilla/content/base/public/nsIAttribute.h +++ b/mozilla/content/base/public/nsIAttribute.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 { diff --git a/mozilla/content/base/public/nsIDocument.h b/mozilla/content/base/public/nsIDocument.h index fe81d22e073..39625355265 100644 --- a/mozilla/content/base/public/nsIDocument.h +++ b/mozilla/content/base/public/nsIDocument.h @@ -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). diff --git a/mozilla/content/base/public/nsIDocumentObserver.h b/mozilla/content/base/public/nsIDocumentObserver.h index 6eb7959eca1..049201ebcde 100644 --- a/mozilla/content/base/public/nsIDocumentObserver.h +++ b/mozilla/content/base/public/nsIDocumentObserver.h @@ -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.

- * - * 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.

- * - * @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 \ diff --git a/mozilla/content/base/public/nsIMutationObserver.h b/mozilla/content/base/public/nsIMutationObserver.h new file mode 100755 index 00000000000..10f422a38cb --- /dev/null +++ b/mozilla/content/base/public/nsIMutationObserver.h @@ -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___ */ diff --git a/mozilla/content/base/public/nsINode.h b/mozilla/content/base/public/nsINode.h index 460b2bbf2a6..af61cd511e7 100644 --- a/mozilla/content/base/public/nsINode.h +++ b/mozilla/content/base/public/nsINode.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 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. diff --git a/mozilla/content/base/public/nsITextContent.h b/mozilla/content/base/public/nsITextContent.h index a4c117ff768..dbe6f205037 100644 --- a/mozilla/content/base/public/nsITextContent.h +++ b/mozilla/content/base/public/nsITextContent.h @@ -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 diff --git a/mozilla/content/base/src/Makefile.in b/mozilla/content/base/src/Makefile.in index ebe46da9e5f..56344cf0b89 100644 --- a/mozilla/content/base/src/Makefile.in +++ b/mozilla/content/base/src/Makefile.in @@ -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 \ diff --git a/mozilla/content/base/src/nsContentList.cpp b/mozilla/content/base/src/nsContentList.cpp index 1cf22a14ea2..e97e61dabf9 100644 --- a/mozilla/content/base/src/nsContentList.cpp +++ b/mozilla/content/base/src/nsContentList.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 -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(); } diff --git a/mozilla/content/base/src/nsContentList.h b/mozilla/content/base/src/nsContentList.h index ee0cfa8cf1a..9ad6b79fc6c 100644 --- a/mozilla/content/base/src/nsContentList.h +++ b/mozilla/content/base/src/nsContentList.h @@ -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 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 -NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom, - PRInt32 aMatchNameSpaceId, nsIContent* aRootContent); +NS_GetContentList(nsINode* aRootNode, nsIAtom* aMatchAtom, + PRInt32 aMatchNameSpaceId); #endif // nsContentList_h___ diff --git a/mozilla/content/base/src/nsDOMAttribute.cpp b/mozilla/content/base/src/nsDOMAttribute.cpp index ff300ffa07e..225194f48a9 100644 --- a/mozilla/content/base/src/nsDOMAttribute.cpp +++ b/mozilla/content/base/src/nsDOMAttribute.cpp @@ -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); diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index e90a8ba4409..40347c7cb22 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -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 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 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 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 elements are attached. - nsRefPtr links = NS_GetContentList(this, + nsRefPtr 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 elements are detached, // but only if this is not a full unload. if (aPersisted) { - nsRefPtr links = NS_GetContentList(this, + nsRefPtr links = NS_GetContentList(mRootContent, nsHTMLAtoms::link, - kNameSpaceID_Unknown, - mRootContent); + kNameSpaceID_Unknown); if (links) { PRUint32 linkCount = links->Length(PR_TRUE); diff --git a/mozilla/content/base/src/nsDocument.h b/mozilla/content/base/src/nsDocument.h index cfdb23aa751..1261ce3f55e 100644 --- a/mozilla/content/base/src/nsDocument.h +++ b/mozilla/content/base/src/nsDocument.h @@ -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, diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.cpp b/mozilla/content/base/src/nsGenericDOMDataNode.cpp index 54d54f0466a..8564c509e2f 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.cpp +++ b/mozilla/content/base/src/nsGenericDOMDataNode.cpp @@ -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); } } diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.h b/mozilla/content/base/src/nsGenericDOMDataNode.h index 48cbcf8dbf9..cea6b9d4c97 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.h +++ b/mozilla/content/base/src/nsGenericDOMDataNode.h @@ -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); /** diff --git a/mozilla/content/base/src/nsGenericElement.cpp b/mozilla/content/base/src/nsGenericElement.cpp index 5a0a395fc83..39dd6348bfc 100644 --- a/mozilla/content/base/src/nsGenericElement.cpp +++ b/mozilla/content/base/src/nsGenericElement.cpp @@ -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 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 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 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) { diff --git a/mozilla/content/base/src/nsGenericElement.h b/mozilla/content/base/src/nsGenericElement.h index 97272e0c2ac..5386791dc34 100644 --- a/mozilla/content/base/src/nsGenericElement.h +++ b/mozilla/content/base/src/nsGenericElement.h @@ -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 diff --git a/mozilla/content/base/src/nsNodeUtils.cpp b/mozilla/content/base/src/nsNodeUtils.cpp new file mode 100755 index 00000000000..b3c8f8e788b --- /dev/null +++ b/mozilla/content/base/src/nsNodeUtils.cpp @@ -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 (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 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::ForwardIterator \ + iter_(slots->mMutationObservers); \ + nsCOMPtr 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 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::ReverseIterator \ + iter_(slots->mMutationObservers); \ + nsCOMPtr 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::ForwardIterator + iter(slots->mMutationObservers); + nsCOMPtr obs; + while ((obs = iter.GetNext())) { + obs->NodeWillBeDestroyed(aNode); + } + } + + PtrBits flags = slots->mFlags | NODE_DOESNT_HAVE_SLOTS; + delete slots; + aNode->mFlagsOrSlots = flags; + } +} diff --git a/mozilla/content/base/src/nsNodeUtils.h b/mozilla/content/base/src/nsNodeUtils.h new file mode 100755 index 00000000000..5cd934f4669 --- /dev/null +++ b/mozilla/content/base/src/nsNodeUtils.h @@ -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 (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___ diff --git a/mozilla/content/base/src/nsStubMutationObserver.cpp b/mozilla/content/base/src/nsStubMutationObserver.cpp new file mode 100755 index 00000000000..8942efe0b14 --- /dev/null +++ b/mozilla/content/base/src/nsStubMutationObserver.cpp @@ -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 (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) diff --git a/mozilla/content/base/src/nsStubMutationObserver.h b/mozilla/content/base/src/nsStubMutationObserver.h new file mode 100755 index 00000000000..963e885c26a --- /dev/null +++ b/mozilla/content/base/src/nsStubMutationObserver.h @@ -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 (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_) */ diff --git a/mozilla/content/base/src/nsTObserverArray.h b/mozilla/content/base/src/nsTObserverArray.h index 13557b43a31..d70fe6a6a65 100755 --- a/mozilla/content/base/src/nsTObserverArray.h +++ b/mozilla/content/base/src/nsTObserverArray.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___ diff --git a/mozilla/content/events/src/nsXMLEventsManager.cpp b/mozilla/content/events/src/nsXMLEventsManager.cpp index 8445510d249..360a9190407 100644 --- a/mozilla/content/events/src/nsXMLEventsManager.cpp +++ b/mozilla/content/events/src/nsXMLEventsManager.cpp @@ -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 diff --git a/mozilla/content/html/content/src/nsHTMLMapElement.cpp b/mozilla/content/html/content/src/nsHTMLMapElement.cpp index e43905bed1b..868a319a8b9 100644 --- a/mozilla/content/html/content/src/nsHTMLMapElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLMapElement.cpp @@ -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) { diff --git a/mozilla/content/html/content/src/nsHTMLTableElement.cpp b/mozilla/content/html/content/src/nsHTMLTableElement.cpp index c2ea8313d24..7c029e7bc3b 100644 --- a/mozilla/content/html/content/src/nsHTMLTableElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLTableElement.cpp @@ -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); diff --git a/mozilla/content/html/content/src/nsHTMLTableRowElement.cpp b/mozilla/content/html/content/src/nsHTMLTableRowElement.cpp index 35346cce778..199d3680a44 100644 --- a/mozilla/content/html/content/src/nsHTMLTableRowElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLTableRowElement.cpp @@ -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, diff --git a/mozilla/content/html/content/src/nsHTMLTableSectionElement.cpp b/mozilla/content/html/content/src/nsHTMLTableSectionElement.cpp index 193407cb9d0..68326da1b49 100644 --- a/mozilla/content/html/content/src/nsHTMLTableSectionElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLTableSectionElement.cpp @@ -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); diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index b2316670c02..53befbae5b0 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -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")); diff --git a/mozilla/content/html/document/src/nsHTMLDocument.cpp b/mozilla/content/html/document/src/nsHTMLDocument.cpp index 4a763d2390c..37cedd44da9 100644 --- a/mozilla/content/html/document/src/nsHTMLDocument.cpp +++ b/mozilla/content/html/document/src/nsHTMLDocument.cpp @@ -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 diff --git a/mozilla/content/html/document/src/nsHTMLDocument.h b/mozilla/content/html/document/src/nsHTMLDocument.h index 7eda745eb8a..3a638a9a465 100644 --- a/mozilla/content/html/document/src/nsHTMLDocument.h +++ b/mozilla/content/html/document/src/nsHTMLDocument.h @@ -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 diff --git a/mozilla/content/xbl/src/nsBindingManager.cpp b/mozilla/content/xbl/src/nsBindingManager.cpp index 6e05cc89761..e062bd77998 100644 --- a/mozilla/content/xbl/src/nsBindingManager.cpp +++ b/mozilla/content/xbl/src/nsBindingManager.cpp @@ -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) diff --git a/mozilla/content/xml/document/src/nsXMLContentSink.cpp b/mozilla/content/xml/document/src/nsXMLContentSink.cpp index 62c1294703e..7d19f93a759 100644 --- a/mozilla/content/xml/document/src/nsXMLContentSink.cpp +++ b/mozilla/content/xml/document/src/nsXMLContentSink.cpp @@ -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); } diff --git a/mozilla/content/xml/document/src/nsXMLPrettyPrinter.cpp b/mozilla/content/xml/document/src/nsXMLPrettyPrinter.cpp index 35a5576f1b0..8c27a603885 100644 --- a/mozilla/content/xml/document/src/nsXMLPrettyPrinter.cpp +++ b/mozilla/content/xml/document/src/nsXMLPrettyPrinter.cpp @@ -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(); diff --git a/mozilla/content/xml/document/src/nsXMLPrettyPrinter.h b/mozilla/content/xml/document/src/nsXMLPrettyPrinter.h index 356ee980799..f9b6006fbbf 100644 --- a/mozilla/content/xml/document/src/nsXMLPrettyPrinter.h +++ b/mozilla/content/xml/document/src/nsXMLPrettyPrinter.h @@ -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 diff --git a/mozilla/content/xslt/public/nsIDocumentTransformer.h b/mozilla/content/xslt/public/nsIDocumentTransformer.h index 2e21f60bfee..78d1b1793bd 100644 --- a/mozilla/content/xslt/public/nsIDocumentTransformer.h +++ b/mozilla/content/xslt/public/nsIDocumentTransformer.h @@ -45,6 +45,7 @@ class nsIDOMNode; class nsILoadGroup; class nsIURI; class nsIPrincipal; +class nsString; #define NS_ITRANSFORMOBSERVER_IID \ {0xcce88481, 0x6eb3, 0x11d6, \ diff --git a/mozilla/content/xslt/src/xpath/nsXPathResult.cpp b/mozilla/content/xslt/src/xpath/nsXPathResult.cpp index 53025d6a7c4..fa94b69a119 100644 --- a/mozilla/content/xslt/src/xpath/nsXPathResult.cpp +++ b/mozilla/content/xslt/src/xpath/nsXPathResult.cpp @@ -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; diff --git a/mozilla/content/xslt/src/xpath/nsXPathResult.h b/mozilla/content/xslt/src/xpath/nsXPathResult.h index 6f6f990dc06..ec8b76d71df 100644 --- a/mozilla/content/xslt/src/xpath/nsXPathResult.h +++ b/mozilla/content/xslt/src/xpath/nsXPathResult.h @@ -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); diff --git a/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp b/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp index 93784dc949e..abdf3545fc9 100644 --- a/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp +++ b/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp @@ -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 diff --git a/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.h b/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.h index 8769d182c9c..6a20e04bf6f 100644 --- a/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.h +++ b/mozilla/content/xslt/src/xslt/txMozillaXSLTProcessor.h @@ -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, diff --git a/mozilla/content/xul/content/src/nsXULElement.cpp b/mozilla/content/xul/content/src/nsXULElement.cpp index ab3cb6fabc3..d4745c42624 100644 --- a/mozilla/content/xul/content/src/nsXULElement.cpp +++ b/mozilla/content/xul/content/src/nsXULElement.cpp @@ -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; diff --git a/mozilla/content/xul/document/src/nsXULDocument.cpp b/mozilla/content/xul/document/src/nsXULDocument.cpp index e141125da8f..a652e446010 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.cpp +++ b/mozilla/content/xul/document/src/nsXULDocument.cpp @@ -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); diff --git a/mozilla/content/xul/document/src/nsXULDocument.h b/mozilla/content/xul/document/src/nsXULDocument.h index 533f7bdd531..7b928b24897 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.h +++ b/mozilla/content/xul/document/src/nsXULDocument.h @@ -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); diff --git a/mozilla/content/xul/templates/src/nsXULContentBuilder.cpp b/mozilla/content/xul/templates/src/nsXULContentBuilder.cpp index 0701e5fc012..cd0a707ac80 100644 --- a/mozilla/content/xul/templates/src/nsXULContentBuilder.cpp +++ b/mozilla/content/xul/templates/src/nsXULContentBuilder.cpp @@ -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 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 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; diff --git a/mozilla/content/xul/templates/src/nsXULTemplateBuilder.cpp b/mozilla/content/xul/templates/src/nsXULTemplateBuilder.cpp index f557addff24..1d052b8c29a 100644 --- a/mozilla/content/xul/templates/src/nsXULTemplateBuilder.cpp +++ b/mozilla/content/xul/templates/src/nsXULTemplateBuilder.cpp @@ -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. diff --git a/mozilla/content/xul/templates/src/nsXULTemplateBuilder.h b/mozilla/content/xul/templates/src/nsXULTemplateBuilder.h index 1700fa7defd..9a7ee3a9af6 100644 --- a/mozilla/content/xul/templates/src/nsXULTemplateBuilder.h +++ b/mozilla/content/xul/templates/src/nsXULTemplateBuilder.h @@ -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 diff --git a/mozilla/content/xul/templates/src/nsXULTreeBuilder.cpp b/mozilla/content/xul/templates/src/nsXULTreeBuilder.cpp index 7f200818f68..d10c856cde9 100644 --- a/mozilla/content/xul/templates/src/nsXULTreeBuilder.cpp +++ b/mozilla/content/xul/templates/src/nsXULTreeBuilder.cpp @@ -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 diff --git a/mozilla/docshell/shistory/src/nsSHEntry.cpp b/mozilla/docshell/shistory/src/nsSHEntry.cpp index 947bcfd8f90..926f78047f3 100644 --- a/mozilla/docshell/shistory/src/nsSHEntry.cpp +++ b/mozilla/docshell/shistory/src/nsSHEntry.cpp @@ -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, diff --git a/mozilla/docshell/shistory/src/nsSHEntry.h b/mozilla/docshell/shistory/src/nsSHEntry.h index ba16e97a7bc..6819e7db663 100644 --- a/mozilla/docshell/shistory/src/nsSHEntry.h +++ b/mozilla/docshell/shistory/src/nsSHEntry.h @@ -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 mURI; diff --git a/mozilla/extensions/metrics/src/nsLoadCollector.cpp b/mozilla/extensions/metrics/src/nsLoadCollector.cpp index 0662970c2d7..eb36635f190 100644 --- a/mozilla/extensions/metrics/src/nsLoadCollector.cpp +++ b/mozilla/extensions/metrics/src/nsLoadCollector.cpp @@ -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, diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index a4fe79560ae..c0a9b1abfda 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -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() { diff --git a/mozilla/layout/generic/nsFrameSetFrame.cpp b/mozilla/layout/generic/nsFrameSetFrame.cpp index d8d2b20bd2b..2c75d2708fd 100644 --- a/mozilla/layout/generic/nsFrameSetFrame.cpp +++ b/mozilla/layout/generic/nsFrameSetFrame.cpp @@ -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; diff --git a/mozilla/layout/generic/nsImageMap.cpp b/mozilla/layout/generic/nsImageMap.cpp index 56443c2df93..16d1f091c25 100644 --- a/mozilla/layout/generic/nsImageMap.cpp +++ b/mozilla/layout/generic/nsImageMap.cpp @@ -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); } diff --git a/mozilla/layout/generic/nsImageMap.h b/mozilla/layout/generic/nsImageMap.h index 0d7de9fee1e..3cb4e4108b2 100644 --- a/mozilla/layout/generic/nsImageMap.h +++ b/mozilla/layout/generic/nsImageMap.h @@ -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 mMap; nsAutoVoidArray mAreas; // almost always has some entries PRBool mContainsBlockContents; diff --git a/mozilla/layout/inspector/src/inDOMView.cpp b/mozilla/layout/inspector/src/inDOMView.cpp index aab76c5a6a0..bcc1073f38e 100644 --- a/mozilla/layout/inspector/src/inDOMView.cpp +++ b/mozilla/layout/inspector/src/inDOMView.cpp @@ -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 doc(do_QueryInterface(mRootDocument)); + nsCOMPtr 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 doc(do_QueryInterface(mRootDocument)); + nsCOMPtr 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, diff --git a/mozilla/layout/inspector/src/inDOMView.h b/mozilla/layout/inspector/src/inDOMView.h index bde53cae76a..1b4e6173520 100644 --- a/mozilla/layout/inspector/src/inDOMView.h +++ b/mozilla/layout/inspector/src/inDOMView.h @@ -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(); diff --git a/mozilla/layout/xul/base/src/tree/src/nsTreeContentView.cpp b/mozilla/layout/xul/base/src/tree/src/nsTreeContentView.cpp index 8635db82f27..e65d9729095 100644 --- a/mozilla/layout/xul/base/src/tree/src/nsTreeContentView.cpp +++ b/mozilla/layout/xul/base/src/tree/src/nsTreeContentView.cpp @@ -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(); } diff --git a/mozilla/layout/xul/base/src/tree/src/nsTreeContentView.h b/mozilla/layout/xul/base/src/tree/src/nsTreeContentView.h index d9046f98edd..76b817e6d64 100644 --- a/mozilla/layout/xul/base/src/tree/src/nsTreeContentView.h +++ b/mozilla/layout/xul/base/src/tree/src/nsTreeContentView.h @@ -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. diff --git a/mozilla/widget/src/cocoa/nsMenuBarX.h b/mozilla/widget/src/cocoa/nsMenuBarX.h index d35ee3c5924..64ff4395d96 100644 --- a/mozilla/widget/src/cocoa/nsMenuBarX.h +++ b/mozilla/widget/src/cocoa/nsMenuBarX.h @@ -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); diff --git a/mozilla/widget/src/cocoa/nsMenuBarX.mm b/mozilla/widget/src/cocoa/nsMenuBarX.mm index 3f5da3e10b6..2447cfd0d11 100644 --- a/mozilla/widget/src/cocoa/nsMenuBarX.mm +++ b/mozilla/widget/src/cocoa/nsMenuBarX.mm @@ -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 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 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; } diff --git a/mozilla/widget/src/mac/nsMenuBarX.cpp b/mozilla/widget/src/mac/nsMenuBarX.cpp index 456b23231e6..eb98fd57970 100644 --- a/mozilla/widget/src/mac/nsMenuBarX.cpp +++ b/mozilla/widget/src/mac/nsMenuBarX.cpp @@ -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 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 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; } diff --git a/mozilla/widget/src/mac/nsMenuBarX.h b/mozilla/widget/src/mac/nsMenuBarX.h index b3cb07a57d9..68f2bee80ba 100644 --- a/mozilla/widget/src/mac/nsMenuBarX.h +++ b/mozilla/widget/src/mac/nsMenuBarX.h @@ -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);