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);