зеркало из https://github.com/mozilla/gecko-dev.git
Bug 342062: Add nsIMutationObserver which has the ability to get notifications for just mutations happening in a subtree under a given node. r/sr=bz
This commit is contained in:
Родитель
837ba0868b
Коммит
2c39937d84
|
@ -125,6 +125,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocAccessible)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIAccessibleDocument)
|
||||
NS_INTERFACE_MAP_ENTRY(nsPIAccessibleDocument)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScrollPositionListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessibleDocument)
|
||||
|
|
|
@ -56,6 +56,7 @@ nsContentUtils.h \
|
|||
nsIDocument.h \
|
||||
nsIDocumentObserver.h \
|
||||
nsIDOMGCParticipant.h \
|
||||
nsIMutationObserver.h \
|
||||
nsINameSpaceManager.h \
|
||||
nsINode.h \
|
||||
nsINodeInfo.h \
|
||||
|
|
|
@ -46,8 +46,8 @@ class nsDOMAttributeMap;
|
|||
class nsIContent;
|
||||
|
||||
#define NS_IATTRIBUTE_IID \
|
||||
{ 0xb65ca480, 0xca76, 0x495c, \
|
||||
{ 0x95, 0xe4, 0x8c, 0xd0, 0x55, 0x5d, 0xd3, 0x13 } }
|
||||
{ 0x5a3fa236, 0x9249, 0x4949, \
|
||||
{ 0x86, 0xb4, 0x98, 0xc1, 0x86, 0xb3, 0xe5, 0x50 } }
|
||||
|
||||
class nsIAttribute : public nsINode
|
||||
{
|
||||
|
|
|
@ -91,8 +91,8 @@ class nsIDocumentObserver;
|
|||
|
||||
// IID for the nsIDocument interface
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0xffa1f165, 0x8b0e, 0x4010, \
|
||||
{ 0xb6, 0xec, 0x6f, 0x49, 0x6b, 0x1b, 0x30, 0x3a } }
|
||||
{ 0xd14c81b1, 0x029e, 0x4c01, \
|
||||
{ 0x8f, 0xfc, 0x42, 0xc1, 0xe1, 0x34, 0x0f, 0xe4 } }
|
||||
|
||||
// Flag for AddStyleSheet().
|
||||
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
|
||||
|
@ -529,27 +529,11 @@ public:
|
|||
virtual void EndUpdate(nsUpdateType aUpdateType) = 0;
|
||||
virtual void BeginLoad() = 0;
|
||||
virtual void EndLoad() = 0;
|
||||
virtual void CharacterDataChanged(nsIContent* aContent, PRBool aAppend) = 0;
|
||||
// notify that one or two content nodes changed state
|
||||
// either may be nsnull, but not both
|
||||
virtual void ContentStatesChanged(nsIContent* aContent1,
|
||||
nsIContent* aContent2,
|
||||
PRInt32 aStateMask) = 0;
|
||||
virtual void AttributeWillChange(nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute) = 0;
|
||||
virtual void AttributeChanged(nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType) = 0;
|
||||
virtual void ContentAppended(nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer) = 0;
|
||||
virtual void ContentInserted(nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer) = 0;
|
||||
virtual void ContentRemoved(nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer) = 0;
|
||||
|
||||
// Observation hooks for style data to propagate notifications
|
||||
// to document observers
|
||||
|
@ -561,6 +545,13 @@ public:
|
|||
virtual void StyleRuleRemoved(nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule) = 0;
|
||||
|
||||
/**
|
||||
* Notify document of pending attribute change
|
||||
*/
|
||||
virtual void AttributeWillChange(nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute) = 0;
|
||||
|
||||
/**
|
||||
* Flush notifications for this document and its parent documents
|
||||
* (since those may affect the layout of this one).
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#define nsIDocumentObserver_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIMutationObserver.h"
|
||||
|
||||
class nsIAtom;
|
||||
class nsIContent;
|
||||
|
@ -48,8 +49,8 @@ class nsString;
|
|||
class nsIDocument;
|
||||
|
||||
#define NS_IDOCUMENT_OBSERVER_IID \
|
||||
{ 0x589761bb, 0x9856, 0x42fe, \
|
||||
{ 0x9b, 0xf9, 0x6a, 0xdf, 0xf4, 0x92, 0x17, 0x05 } }
|
||||
{ 0x4e14e321, 0xa4bb, 0x49f8, \
|
||||
{ 0xa5, 0x7a, 0x23, 0x63, 0x66, 0x8d, 0x14, 0xd0 } }
|
||||
|
||||
typedef PRUint32 nsUpdateType;
|
||||
|
||||
|
@ -59,7 +60,7 @@ typedef PRUint32 nsUpdateType;
|
|||
#define UPDATE_ALL (UPDATE_CONTENT_MODEL | UPDATE_STYLE | UPDATE_CONTENT_STATE)
|
||||
|
||||
// Document observer interface
|
||||
class nsIDocumentObserver : public nsISupports
|
||||
class nsIDocumentObserver : public nsIMutationObserver
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_OBSERVER_IID)
|
||||
|
@ -89,26 +90,6 @@ public:
|
|||
*/
|
||||
virtual void EndLoad(nsIDocument *aDocument) = 0;
|
||||
|
||||
/**
|
||||
* Notification that the content model has changed. This method is
|
||||
* called automatically by content objects when their state is changed
|
||||
* (therefore there is normally no need to invoke this method
|
||||
* directly). The notification is passed to any
|
||||
* IDocumentObservers. The notification is passed on to all of the
|
||||
* document observers. <p>
|
||||
*
|
||||
* This notification is not sent when a piece of content is
|
||||
* added/removed from the document (the other notifications are used
|
||||
* for that).
|
||||
*
|
||||
* @param aDocument The document being observed
|
||||
* @param aContent the piece of content that changed
|
||||
* @param aAppend Whether the change was an append
|
||||
*/
|
||||
virtual void CharacterDataChanged(nsIDocument *aDocument,
|
||||
nsIContent* aContent,
|
||||
PRBool aAppend) = 0;
|
||||
|
||||
/**
|
||||
* Notification that the state of a content node has changed.
|
||||
* (ie: gained or lost focus, became active or hovered over)
|
||||
|
@ -137,76 +118,6 @@ public:
|
|||
nsIContent* aContent2,
|
||||
PRInt32 aStateMask) = 0;
|
||||
|
||||
/**
|
||||
* Notification that the content model has changed. This method is called
|
||||
* automatically by content objects when an attribute's value has changed
|
||||
* (therefore there is normally no need to invoke this method directly). The
|
||||
* notification is passed to any IDocumentObservers document observers. <p>
|
||||
*
|
||||
* @param aDocument The document being observed
|
||||
* @param aContent the piece of content whose attribute changed
|
||||
* @param aAttribute the atom name of the attribute
|
||||
* @param aModType Whether or not the attribute was added, changed, or removed.
|
||||
* The constants are defined in nsIDOMMutationEvent.h.
|
||||
*/
|
||||
virtual void AttributeChanged(nsIDocument* aDocument,
|
||||
nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType) = 0;
|
||||
|
||||
/**
|
||||
* Notifcation that the content model has had data appended to the
|
||||
* given content object. This method is called automatically by the
|
||||
* content container objects when a new content object is appended to
|
||||
* the container (therefore there is normally no need to invoke this
|
||||
* method directly). The notification is passed on to all of the
|
||||
* document observers.
|
||||
*
|
||||
* @param aDocument The document being observed
|
||||
* @param aContainer the container that had a new child appended
|
||||
* @param aNewIndexInContainer the index in the container of the first
|
||||
* new child
|
||||
*/
|
||||
virtual void ContentAppended(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer) = 0;
|
||||
|
||||
/**
|
||||
* Notification that content has been inserted. This method is called
|
||||
* automatically by the content container objects when a new content
|
||||
* object is inserted in the container (therefore there is normally no
|
||||
* need to invoke this method directly). The notification is passed on
|
||||
* to all of the document observers.
|
||||
*
|
||||
* @param aDocument The document being observed
|
||||
* @param aContainer the container that now contains aChild
|
||||
* @param aChild the child that was inserted
|
||||
* @param aIndexInContainer the index of the child in the container
|
||||
*/
|
||||
virtual void ContentInserted(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer) = 0;
|
||||
|
||||
/**
|
||||
* Content has just been removed. This method is called automatically
|
||||
* by content container objects when a content object has just been
|
||||
* removed from the container (therefore there is normally no need to
|
||||
* invoke this method directly). The notification is passed on to all
|
||||
* of the document observers.
|
||||
*
|
||||
* @param aDocument The document being observed
|
||||
* @param aContainer the container that had a child removed
|
||||
* @param aChild the child that was just removed
|
||||
* @param aIndexInContainer the index of the child in the container
|
||||
* before it was removed
|
||||
*/
|
||||
virtual void ContentRemoved(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer) = 0;
|
||||
|
||||
/**
|
||||
* A StyleSheet has just been added to the document. This method is
|
||||
* called automatically when a StyleSheet gets added to the
|
||||
|
@ -310,15 +221,6 @@ public:
|
|||
virtual void StyleRuleRemoved(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule) = 0;
|
||||
|
||||
/**
|
||||
* The document is in the process of being destroyed.
|
||||
* This method is called automatically during document
|
||||
* destruction.
|
||||
*
|
||||
* @param aDocument The document being observed
|
||||
*/
|
||||
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
|
||||
|
@ -328,29 +230,10 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
|
|||
virtual void EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType);\
|
||||
virtual void BeginLoad(nsIDocument* aDocument); \
|
||||
virtual void EndLoad(nsIDocument* aDocument); \
|
||||
virtual void CharacterDataChanged(nsIDocument* aDocument, \
|
||||
nsIContent* aContent, \
|
||||
PRBool aAppend); \
|
||||
virtual void ContentStatesChanged(nsIDocument* aDocument, \
|
||||
nsIContent* aContent1, \
|
||||
nsIContent* aContent2, \
|
||||
PRInt32 aStateMask); \
|
||||
virtual void AttributeChanged(nsIDocument* aDocument, \
|
||||
nsIContent* aContent, \
|
||||
PRInt32 aNameSpaceID, \
|
||||
nsIAtom* aAttribute, \
|
||||
PRInt32 aModType); \
|
||||
virtual void ContentAppended(nsIDocument* aDocument, \
|
||||
nsIContent* aContainer, \
|
||||
PRInt32 aNewIndexInContainer); \
|
||||
virtual void ContentInserted(nsIDocument* aDocument, \
|
||||
nsIContent* aContainer, \
|
||||
nsIContent* aChild, \
|
||||
PRInt32 aIndexInContainer); \
|
||||
virtual void ContentRemoved(nsIDocument* aDocument, \
|
||||
nsIContent* aContainer, \
|
||||
nsIContent* aChild, \
|
||||
PRInt32 aIndexInContainer); \
|
||||
virtual void StyleSheetAdded(nsIDocument* aDocument, \
|
||||
nsIStyleSheet* aStyleSheet, \
|
||||
PRBool aDocumentSheet); \
|
||||
|
@ -370,7 +253,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
|
|||
virtual void StyleRuleRemoved(nsIDocument* aDocument, \
|
||||
nsIStyleSheet* aStyleSheet, \
|
||||
nsIStyleRule* aStyleRule); \
|
||||
virtual void DocumentWillBeDestroyed(nsIDocument* aDocument); \
|
||||
NS_DECL_NSIMUTATIONOBSERVER
|
||||
|
||||
|
||||
#define NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(_class) \
|
||||
|
@ -382,10 +265,7 @@ void \
|
|||
_class::EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::DocumentWillBeDestroyed(nsIDocument* aDocument) \
|
||||
{ \
|
||||
}
|
||||
NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(_class)
|
||||
|
||||
#define NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(_class) \
|
||||
void \
|
||||
|
@ -407,40 +287,7 @@ _class::ContentStatesChanged(nsIDocument* aDocument, \
|
|||
}
|
||||
|
||||
#define NS_IMPL_NSIDOCUMENTOBSERVER_CONTENT(_class) \
|
||||
void \
|
||||
_class::CharacterDataChanged(nsIDocument* aDocument, \
|
||||
nsIContent* aContent, \
|
||||
PRBool aAppend) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::AttributeChanged(nsIDocument* aDocument, \
|
||||
nsIContent* aContent, \
|
||||
PRInt32 aNameSpaceID, \
|
||||
nsIAtom* aAttribute, \
|
||||
PRInt32 aModType) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::ContentAppended(nsIDocument* aDocument, \
|
||||
nsIContent* aContainer, \
|
||||
PRInt32 aNewIndexInContainer) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::ContentInserted(nsIDocument* aDocument, \
|
||||
nsIContent* aContainer, \
|
||||
nsIContent* aChild, \
|
||||
PRInt32 aIndexInContainer) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::ContentRemoved(nsIDocument* aDocument, \
|
||||
nsIContent* aContainer, \
|
||||
nsIContent* aChild, \
|
||||
PRInt32 aIndexInContainer) \
|
||||
{ \
|
||||
}
|
||||
NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(_class)
|
||||
|
||||
#define NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(_class) \
|
||||
void \
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifndef nsIMutationObserver_h___
|
||||
#define nsIMutationObserver_h___
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsIAtom;
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
class nsINode;
|
||||
|
||||
#define NS_IMUTATION_OBSERVER_IID \
|
||||
{ 0x0864a23d, 0x824b, 0x48be, \
|
||||
{ 0x9d, 0x50, 0xff, 0x30, 0x2f, 0xf2, 0x79, 0xfe } }
|
||||
|
||||
// Mutation observer interface
|
||||
class nsIMutationObserver : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMUTATION_OBSERVER_IID)
|
||||
|
||||
/**
|
||||
* Notification that the node value of a data node (text, cdata, pi, comment)
|
||||
* has changed.
|
||||
*
|
||||
* This notification is not sent when a piece of content is
|
||||
* added/removed from the document (the other notifications are used
|
||||
* for that).
|
||||
*
|
||||
* @param aDocument The owner-document of aContent. Can be null.
|
||||
* @param aContent The piece of content that changed. Is never null.
|
||||
* @param aAppend Whether the change was an append
|
||||
*/
|
||||
virtual void CharacterDataChanged(nsIDocument *aDocument,
|
||||
nsIContent* aContent,
|
||||
PRBool aAppend) = 0;
|
||||
|
||||
/**
|
||||
* Notification that an attribute of an element has changed.
|
||||
*
|
||||
* @param aDocument The owner-document of aContent. Can be null.
|
||||
* @param aContent The element whose attribute changed
|
||||
* @param aNameSpaceID The namespace id of the changed attribute
|
||||
* @param aAttribute The name of the changed attribute
|
||||
* @param aModType Whether or not the attribute was added, changed, or
|
||||
* removed. The constants are defined in
|
||||
* nsIDOMMutationEvent.h.
|
||||
*/
|
||||
virtual void AttributeChanged(nsIDocument* aDocument,
|
||||
nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType) = 0;
|
||||
|
||||
/**
|
||||
* Notification that one or more content nodes have been appended to the
|
||||
* child list of another node in the tree.
|
||||
*
|
||||
* @param aDocument The owner-document of aContent. Can be null.
|
||||
* @param aContainer The container that had new children appended. Is never
|
||||
* null.
|
||||
* @param aNewIndexInContainer the index in the container of the first
|
||||
* new child
|
||||
*/
|
||||
virtual void ContentAppended(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer) = 0;
|
||||
|
||||
/**
|
||||
* Notification that a content node has been inserted as child to another
|
||||
* node in the tree.
|
||||
*
|
||||
* @param aDocument The owner-document of aContent, or, when aContainer
|
||||
* is null, the container that had the child inserted.
|
||||
* Can be null.
|
||||
* @param aContainer The container that had new a child inserted. Can be
|
||||
* null to indicate that the child was inserted into
|
||||
* aDocument
|
||||
* @param aChild The newly inserted child.
|
||||
* @param aIndexInContainer The index in the container of the new child.
|
||||
*/
|
||||
virtual void ContentInserted(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer) = 0;
|
||||
|
||||
/**
|
||||
* Notification that a content node has been removed from the child list of
|
||||
* another node in the tree.
|
||||
*
|
||||
* @param aDocument The owner-document of aContent, or, when aContainer
|
||||
* is null, the container that had the child removed.
|
||||
* Can be null.
|
||||
* @param aContainer The container that had new a child removed. Can be
|
||||
* null to indicate that the child was removed from
|
||||
* aDocument.
|
||||
* @param aChild The child that was removed.
|
||||
* @param aIndexInContainer The index in the container which the child used
|
||||
* to have.
|
||||
*/
|
||||
virtual void ContentRemoved(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer) = 0;
|
||||
|
||||
/**
|
||||
* The node is in the process of being destroyed. Calling QI on the node is
|
||||
* not supported, however it is possible to get children and flags through
|
||||
* nsINode as well as calling IsNodeOfType(eCONTENT) and casting to
|
||||
* nsIContent to get attributes.
|
||||
*
|
||||
* NOTE: This notification is only called on observers registered directly
|
||||
* on the node. This is because when the node is destroyed it can not have
|
||||
* any ancestors. If you want to know when a descendant node is being
|
||||
* removed from the observed node, use the ContentRemoved notification.
|
||||
*
|
||||
* @param aNode The node being destroyed.
|
||||
*/
|
||||
virtual void NodeWillBeDestroyed(const nsINode *aNode) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIMutationObserver, NS_IMUTATION_OBSERVER_IID)
|
||||
|
||||
#define NS_DECL_NSIMUTATIONOBSERVER \
|
||||
virtual void CharacterDataChanged(nsIDocument* aDocument, \
|
||||
nsIContent* aContent, \
|
||||
PRBool aAppend); \
|
||||
virtual void AttributeChanged(nsIDocument* aDocument, \
|
||||
nsIContent* aContent, \
|
||||
PRInt32 aNameSpaceID, \
|
||||
nsIAtom* aAttribute, \
|
||||
PRInt32 aModType); \
|
||||
virtual void ContentAppended(nsIDocument* aDocument, \
|
||||
nsIContent* aContainer, \
|
||||
PRInt32 aNewIndexInContainer); \
|
||||
virtual void ContentInserted(nsIDocument* aDocument, \
|
||||
nsIContent* aContainer, \
|
||||
nsIContent* aChild, \
|
||||
PRInt32 aIndexInContainer); \
|
||||
virtual void ContentRemoved(nsIDocument* aDocument, \
|
||||
nsIContent* aContainer, \
|
||||
nsIContent* aChild, \
|
||||
PRInt32 aIndexInContainer); \
|
||||
virtual void NodeWillBeDestroyed(const nsINode* aNode);
|
||||
|
||||
|
||||
#define NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(_class) \
|
||||
void \
|
||||
_class::NodeWillBeDestroyed(const nsINode* aNode) \
|
||||
{ \
|
||||
}
|
||||
|
||||
#define NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(_class) \
|
||||
void \
|
||||
_class::CharacterDataChanged(nsIDocument* aDocument, \
|
||||
nsIContent* aContent, \
|
||||
PRBool aAppend) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::AttributeChanged(nsIDocument* aDocument, \
|
||||
nsIContent* aContent, \
|
||||
PRInt32 aNameSpaceID, \
|
||||
nsIAtom* aAttribute, \
|
||||
PRInt32 aModType) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::ContentAppended(nsIDocument* aDocument, \
|
||||
nsIContent* aContainer, \
|
||||
PRInt32 aNewIndexInContainer) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::ContentInserted(nsIDocument* aDocument, \
|
||||
nsIContent* aContainer, \
|
||||
nsIContent* aChild, \
|
||||
PRInt32 aIndexInContainer) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
_class::ContentRemoved(nsIDocument* aDocument, \
|
||||
nsIContent* aContainer, \
|
||||
nsIContent* aChild, \
|
||||
PRInt32 aIndexInContainer) \
|
||||
{ \
|
||||
}
|
||||
|
||||
#endif /* nsIMutationObserver_h___ */
|
|
@ -41,6 +41,7 @@
|
|||
#include "nsIDOMGCParticipant.h"
|
||||
#include "nsEvent.h"
|
||||
#include "nsPropertyTable.h"
|
||||
#include "nsTObserverArray.h"
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
#include "nsINodeInfo.h"
|
||||
|
@ -57,8 +58,9 @@ class nsIEventListenerManager;
|
|||
class nsIPrincipal;
|
||||
class nsIDOMRange;
|
||||
class nsVoidArray;
|
||||
class nsIMutationObserver;
|
||||
|
||||
// This bit will be set if the node doesn't have nsDOMSlots
|
||||
// This bit will be set if the node doesn't have nsSlots
|
||||
#define NODE_DOESNT_HAVE_SLOTS 0x00000001U
|
||||
|
||||
// This bit will be set if the node has a range list in the range list hash
|
||||
|
@ -85,6 +87,14 @@ class nsVoidArray;
|
|||
// Remaining bits are node type specific.
|
||||
#define NODE_TYPE_SPECIFIC_BITS_OFFSET 0x0a
|
||||
|
||||
// Useful macro for getting a node given an nsIContent and an nsIDocument
|
||||
// Returns the first argument cast to nsINode if it is non-null, otherwise
|
||||
// returns the second (which may be null)
|
||||
#define NODE_FROM(content_, document_) \
|
||||
((content_) ? NS_STATIC_CAST(nsINode*, (content_)) : \
|
||||
NS_STATIC_CAST(nsINode*, (document_)))
|
||||
|
||||
|
||||
// IID for the nsINode interface
|
||||
#define NS_INODE_IID \
|
||||
{ 0x7b23c37c, 0x18e6, 0x4d80, \
|
||||
|
@ -107,6 +117,8 @@ public:
|
|||
// If you're using the external API, the only thing you can know about
|
||||
// nsINode is that it exists with an IID, if that....
|
||||
|
||||
friend class nsNodeUtils;
|
||||
|
||||
nsINode(nsINodeInfo* aNodeInfo)
|
||||
: mNodeInfo(aNodeInfo),
|
||||
mParentPtrBits(0),
|
||||
|
@ -510,7 +522,20 @@ public:
|
|||
return NS_REINTERPRET_CAST(nsINode*, mParentPtrBits & ~kParentBitMask);
|
||||
}
|
||||
|
||||
// This class should be extended by subclasses that wish to store more
|
||||
/**
|
||||
* Adds a mutation observer to be notified when this node, or any of its
|
||||
* descendants, are modified. The node will hold a weak reference to the
|
||||
* observer, which means that it is the responsibility of the observer to
|
||||
* remove itself in case it dies before the node.
|
||||
*/
|
||||
virtual void AddMutationObserver(nsIMutationObserver* aMutationObserver);
|
||||
|
||||
/**
|
||||
* Removes a mutation observer.
|
||||
*/
|
||||
virtual void RemoveMutationObserver(nsIMutationObserver* aMutationObserver);
|
||||
|
||||
// This class can be extended by subclasses that wish to store more
|
||||
// information in the slots.
|
||||
class nsSlots
|
||||
{
|
||||
|
@ -519,12 +544,23 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
// If needed we could remove the vtable pointer this dtor causes by
|
||||
// putting a DestroySlots function on nsINode
|
||||
virtual ~nsSlots()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Storage for flags for this node. These are the same flags as the
|
||||
* mFlagsOrSlots member, but these are used when the slots class
|
||||
* is allocated.
|
||||
*/
|
||||
PtrBits mFlags;
|
||||
|
||||
protected:
|
||||
// This is protected so that no-one accidentally deletes this rather than
|
||||
// the subclass
|
||||
~nsSlots() {}
|
||||
/**
|
||||
* A list of mutation observers
|
||||
*/
|
||||
nsTObserverArray<nsIMutationObserver> mMutationObservers;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -532,6 +568,9 @@ protected:
|
|||
* Functions for managing flags and slots
|
||||
*/
|
||||
|
||||
// Override this function to create a custom slots class.
|
||||
virtual nsINode::nsSlots* CreateSlots();
|
||||
|
||||
PRBool HasSlots() const
|
||||
{
|
||||
return !(mFlagsOrSlots & NODE_DOESNT_HAVE_SLOTS);
|
||||
|
@ -548,10 +587,18 @@ protected:
|
|||
return HasSlots() ? FlagsAsSlots() : nsnull;
|
||||
}
|
||||
|
||||
void SetSlots(nsSlots* aSlots)
|
||||
nsSlots* GetSlots()
|
||||
{
|
||||
NS_ASSERTION(!HasSlots(), "Already has slots");
|
||||
mFlagsOrSlots = NS_REINTERPRET_CAST(PtrBits, aSlots);
|
||||
if (HasSlots()) {
|
||||
return FlagsAsSlots();
|
||||
}
|
||||
|
||||
nsSlots* slots = CreateSlots();
|
||||
if (slots) {
|
||||
mFlagsOrSlots = NS_REINTERPRET_CAST(PtrBits, slots);
|
||||
}
|
||||
|
||||
return slots;
|
||||
}
|
||||
|
||||
PtrBits GetFlags() const
|
||||
|
@ -589,7 +636,7 @@ protected:
|
|||
PtrBits mParentPtrBits;
|
||||
|
||||
/**
|
||||
* Used for either storing flags for this element or a pointer to
|
||||
* Used for either storing flags for this node or a pointer to
|
||||
* this contents nsContentSlots. See the definition of the
|
||||
* NODE_* macros for the layout of the bits in this
|
||||
* member.
|
||||
|
|
|
@ -45,8 +45,8 @@ class nsTextFragment;
|
|||
// IID for the nsITextContent interface
|
||||
// e4ef843f-1061-45e6-9c81-30eac2673f41
|
||||
#define NS_ITEXT_CONTENT_IID \
|
||||
{ 0xe4ef843f, 0x1061, 0x45e6, \
|
||||
{ 0x9c, 0x81, 0x30, 0xea, 0xc2, 0x67, 0x3f, 0x41 } }
|
||||
{ 0x013da2a1, 0x6267, 0x4667, \
|
||||
{ 0x9a, 0x63, 0xc9, 0xd3, 0x02, 0xf7, 0x55, 0x8d } }
|
||||
|
||||
/**
|
||||
* Interface for textual content. This interface is used to provide
|
||||
|
|
|
@ -85,7 +85,9 @@ EXPORTS = \
|
|||
nsPropertyTable.h \
|
||||
nsStubDocumentObserver.h \
|
||||
nsStubImageDecoderObserver.h \
|
||||
nsStubMutationObserver.h \
|
||||
nsTextFragment.h \
|
||||
nsTObserverArray.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
@ -126,6 +128,7 @@ CPPSRCS = \
|
|||
nsNoDataProtocolContentPolicy.cpp \
|
||||
nsNodeInfo.cpp \
|
||||
nsNodeInfoManager.cpp \
|
||||
nsNodeUtils.cpp \
|
||||
nsObjectLoadingContent.cpp \
|
||||
nsParserUtils.cpp \
|
||||
nsPlainTextSerializer.cpp \
|
||||
|
@ -135,6 +138,7 @@ CPPSRCS = \
|
|||
nsScriptLoader.cpp \
|
||||
nsStubDocumentObserver.cpp \
|
||||
nsStubImageDecoderObserver.cpp \
|
||||
nsStubMutationObserver.cpp \
|
||||
nsStyleLinkElement.cpp \
|
||||
nsSyncLoadService.cpp \
|
||||
nsTextFragment.cpp \
|
||||
|
|
|
@ -110,7 +110,7 @@ void
|
|||
nsBaseContentList::AppendElement(nsIContent *aContent)
|
||||
{
|
||||
// Shouldn't hold a reference since we'll be told when the content
|
||||
// leaves the document or the document will be destroyed.
|
||||
// leaves the root or the root will be destroyed.
|
||||
mElements.AppendElement(aContent);
|
||||
}
|
||||
|
||||
|
@ -242,9 +242,11 @@ ContentListHashtableMatchEntry(PLDHashTable *table,
|
|||
}
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom,
|
||||
PRInt32 aMatchNameSpaceId, nsIContent* aRootContent)
|
||||
NS_GetContentList(nsINode* aRootNode, nsIAtom* aMatchAtom,
|
||||
PRInt32 aMatchNameSpaceId)
|
||||
{
|
||||
NS_ASSERTION(aRootNode, "content list has to have a root");
|
||||
|
||||
nsContentList* list = nsnull;
|
||||
|
||||
static PLDHashTableOps hash_table_ops =
|
||||
|
@ -274,8 +276,8 @@ NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom,
|
|||
ContentListHashEntry *entry = nsnull;
|
||||
// First we look in our hashtable. Then we create a content list if needed
|
||||
if (gContentListHashTable.ops) {
|
||||
nsContentListKey hashKey(aDocument, aMatchAtom,
|
||||
aMatchNameSpaceId, aRootContent);
|
||||
nsContentListKey hashKey(aRootNode, aMatchAtom,
|
||||
aMatchNameSpaceId);
|
||||
|
||||
// A PL_DHASH_ADD is equivalent to a PL_DHASH_LOOKUP for cases
|
||||
// when the entry is already in the hashtable.
|
||||
|
@ -290,8 +292,8 @@ NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom,
|
|||
if (!list) {
|
||||
// We need to create a ContentList and add it to our new entry, if
|
||||
// we have an entry
|
||||
list = new nsContentList(aDocument, aMatchAtom,
|
||||
aMatchNameSpaceId, aRootContent);
|
||||
list = new nsContentList(aRootNode, aMatchAtom,
|
||||
aMatchNameSpaceId);
|
||||
if (entry) {
|
||||
if (list)
|
||||
entry->mContentList = list;
|
||||
|
@ -309,7 +311,7 @@ NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom,
|
|||
// bumping the refcount on the list if the requested list is the one
|
||||
// that's already cached.
|
||||
|
||||
if (!aRootContent && gCachedContentList != list) {
|
||||
if (gCachedContentList != list) {
|
||||
NS_IF_RELEASE(gCachedContentList);
|
||||
|
||||
gCachedContentList = list;
|
||||
|
@ -322,39 +324,37 @@ NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom,
|
|||
|
||||
// nsContentList implementation
|
||||
|
||||
nsContentList::nsContentList(nsIDocument *aDocument,
|
||||
nsContentList::nsContentList(nsINode* aRootNode,
|
||||
nsIAtom* aMatchAtom,
|
||||
PRInt32 aMatchNameSpaceId,
|
||||
nsIContent* aRootContent,
|
||||
PRBool aDeep)
|
||||
: nsBaseContentList(),
|
||||
nsContentListKey(aDocument, aMatchAtom, aMatchNameSpaceId, aRootContent),
|
||||
nsContentListKey(aRootNode, aMatchAtom, aMatchNameSpaceId),
|
||||
mFunc(nsnull),
|
||||
mData(nsnull),
|
||||
mState(LIST_DIRTY),
|
||||
mDeep(aDeep),
|
||||
mFuncMayDependOnAttr(PR_FALSE)
|
||||
{
|
||||
NS_ASSERTION(mDeep || mRootContent, "Must have root content for non-deep list!");
|
||||
NS_ASSERTION(mRootNode, "Must have root");
|
||||
if (nsLayoutAtoms::_asterix == mMatchAtom) {
|
||||
mMatchAll = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
mMatchAll = PR_FALSE;
|
||||
}
|
||||
Init(aDocument);
|
||||
mRootNode->AddMutationObserver(this);
|
||||
}
|
||||
|
||||
nsContentList::nsContentList(nsIDocument *aDocument,
|
||||
nsContentList::nsContentList(nsINode* aRootNode,
|
||||
nsContentListMatchFunc aFunc,
|
||||
const nsAString& aData,
|
||||
nsIContent* aRootContent,
|
||||
PRBool aDeep,
|
||||
nsIAtom* aMatchAtom,
|
||||
PRInt32 aMatchNameSpaceId,
|
||||
PRBool aFuncMayDependOnAttr)
|
||||
: nsBaseContentList(),
|
||||
nsContentListKey(aDocument, aMatchAtom, aMatchNameSpaceId, aRootContent),
|
||||
nsContentListKey(aRootNode, aMatchAtom, aMatchNameSpaceId),
|
||||
mFunc(aFunc),
|
||||
mData(&EmptyString()),
|
||||
mMatchAll(PR_FALSE),
|
||||
|
@ -362,32 +362,19 @@ nsContentList::nsContentList(nsIDocument *aDocument,
|
|||
mDeep(aDeep),
|
||||
mFuncMayDependOnAttr(aFuncMayDependOnAttr)
|
||||
{
|
||||
NS_ASSERTION(mDeep || mRootContent, "Must have root content for non-deep list!");
|
||||
NS_ASSERTION(mRootNode, "Must have root");
|
||||
if (!aData.IsEmpty()) {
|
||||
mData = new nsString(aData);
|
||||
// If this fails, fail silently
|
||||
}
|
||||
Init(aDocument);
|
||||
}
|
||||
|
||||
void nsContentList::Init(nsIDocument *aDocument)
|
||||
{
|
||||
// We don't reference count the reference to the document
|
||||
// If the document goes away first, we'll be informed and we
|
||||
// can drop our reference.
|
||||
// If we go away first, we'll get rid of ourselves from the
|
||||
// document's observer list.
|
||||
mDocument = aDocument;
|
||||
if (mDocument) {
|
||||
mDocument->AddObserver(this);
|
||||
}
|
||||
mRootNode->AddMutationObserver(this);
|
||||
}
|
||||
|
||||
nsContentList::~nsContentList()
|
||||
{
|
||||
RemoveFromHashtable();
|
||||
if (mDocument) {
|
||||
mDocument->RemoveObserver(this);
|
||||
if (mRootNode) {
|
||||
mRootNode->RemoveMutationObserver(this);
|
||||
}
|
||||
|
||||
if (mData && mData != &EmptyString()) {
|
||||
|
@ -400,7 +387,7 @@ nsContentList::~nsContentList()
|
|||
// QueryInterface implementation for nsContentList
|
||||
NS_INTERFACE_MAP_BEGIN(nsContentList)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLCollection)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(ContentList)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsBaseContentList)
|
||||
|
||||
|
@ -412,17 +399,12 @@ NS_IMPL_RELEASE_INHERITED(nsContentList, nsBaseContentList)
|
|||
nsISupports *
|
||||
nsContentList::GetParentObject()
|
||||
{
|
||||
if (mRootContent) {
|
||||
return mRootContent;
|
||||
}
|
||||
|
||||
return mDocument;
|
||||
return mRootNode;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsContentList::Length(PRBool aDoFlush)
|
||||
{
|
||||
CheckDocumentExistence();
|
||||
BringSelfUpToDate(aDoFlush);
|
||||
|
||||
return mElements.Count();
|
||||
|
@ -431,17 +413,21 @@ nsContentList::Length(PRBool aDoFlush)
|
|||
nsIContent *
|
||||
nsContentList::Item(PRUint32 aIndex, PRBool aDoFlush)
|
||||
{
|
||||
CheckDocumentExistence();
|
||||
|
||||
if (mDocument && aDoFlush) {
|
||||
// Flush pending content changes Bug 4891.
|
||||
mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
|
||||
if (mRootNode && aDoFlush) {
|
||||
// XXX sXBL/XBL2 issue
|
||||
// Ideally we should call GetCurrentDoc here, i think, but that doesn't
|
||||
// live on nsINode
|
||||
nsIDocument* doc = mRootNode->GetOwnerDoc();
|
||||
if (doc) {
|
||||
// Flush pending content changes Bug 4891.
|
||||
doc->FlushPendingNotifications(Flush_ContentAndNotify);
|
||||
}
|
||||
}
|
||||
|
||||
if (mState != LIST_UP_TO_DATE)
|
||||
PopulateSelf(aIndex+1);
|
||||
|
||||
NS_ASSERTION(!mDocument || mState != LIST_DIRTY,
|
||||
NS_ASSERTION(!mRootNode || mState != LIST_DIRTY,
|
||||
"PopulateSelf left the list in a dirty (useless) state!");
|
||||
|
||||
return NS_STATIC_CAST(nsIContent *, mElements.SafeElementAt(aIndex));
|
||||
|
@ -450,8 +436,6 @@ nsContentList::Item(PRUint32 aIndex, PRBool aDoFlush)
|
|||
nsIContent *
|
||||
nsContentList::NamedItem(const nsAString& aName, PRBool aDoFlush)
|
||||
{
|
||||
CheckDocumentExistence();
|
||||
|
||||
BringSelfUpToDate(aDoFlush);
|
||||
|
||||
PRInt32 i, count = mElements.Count();
|
||||
|
@ -479,18 +463,26 @@ nsContentList::NamedItem(const nsAString& aName, PRBool aDoFlush)
|
|||
PRInt32
|
||||
nsContentList::IndexOf(nsIContent *aContent, PRBool aDoFlush)
|
||||
{
|
||||
CheckDocumentExistence();
|
||||
BringSelfUpToDate(aDoFlush);
|
||||
|
||||
return mElements.IndexOf(aContent);
|
||||
}
|
||||
|
||||
void
|
||||
nsContentList::RootDestroyed()
|
||||
nsContentList::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
// We shouldn't do anything useful from now on
|
||||
DisconnectFromDocument(); // This dirties us so we lose all state
|
||||
mRootContent = nsnull;
|
||||
|
||||
RemoveFromHashtable();
|
||||
mRootNode = nsnull;
|
||||
|
||||
// We will get no more updates, so we can never know we're up to
|
||||
// date
|
||||
mState = LIST_DIRTY;
|
||||
|
||||
// Call Reset() to prevent getting bogus (or eveng dangling) items since
|
||||
// PopulateSelf() will be a no-op after mRootNode was nulled out above
|
||||
Reset();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -537,26 +529,25 @@ nsContentList::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
|
|||
NS_PRECONDITION(aContent, "Must have a content node to work with");
|
||||
|
||||
if (!mFunc || !mFuncMayDependOnAttr || mState == LIST_DIRTY ||
|
||||
!MayContainRelevantNodes(aContent->GetNodeParent()) ||
|
||||
IsContentAnonymous(aContent)) {
|
||||
// Either we're already dirty or this notification doesn't affect
|
||||
// whether we might match aContent.
|
||||
return;
|
||||
}
|
||||
|
||||
if (MayContainRelevantNodes(aContent->GetParent())) {
|
||||
if (Match(aContent)) {
|
||||
if (mElements.IndexOf(aContent) == -1) {
|
||||
// We match aContent now, and it's not in our list already. Just dirty
|
||||
// ourselves; this is simpler than trying to figure out where to insert
|
||||
// aContent.
|
||||
mState = LIST_DIRTY;
|
||||
}
|
||||
} else {
|
||||
// We no longer match aContent. Remove it from our list. If
|
||||
// it's already not there, this is a no-op, which is fine.
|
||||
// Either way, no change of mState is required here.
|
||||
mElements.RemoveElement(aContent);
|
||||
if (Match(aContent)) {
|
||||
if (mElements.IndexOf(aContent) == -1) {
|
||||
// We match aContent now, and it's not in our list already. Just dirty
|
||||
// ourselves; this is simpler than trying to figure out where to insert
|
||||
// aContent.
|
||||
mState = LIST_DIRTY;
|
||||
}
|
||||
} else {
|
||||
// We no longer match aContent. Remove it from our list. If
|
||||
// it's already not there, this is a no-op, which is fine.
|
||||
// Either way, no change of mState is required here.
|
||||
mElements.RemoveElement(aContent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,7 +563,8 @@ nsContentList::ContentAppended(nsIDocument *aDocument, nsIContent* aContainer,
|
|||
* aContainer is anonymous from our point of view, we know that we can't
|
||||
* possibly be matching any of the kids.
|
||||
*/
|
||||
if (mState == LIST_DIRTY || IsContentAnonymous(aContainer))
|
||||
if (mState == LIST_DIRTY || IsContentAnonymous(aContainer) ||
|
||||
!MayContainRelevantNodes(aContainer))
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@ -586,7 +578,7 @@ nsContentList::ContentAppended(nsIDocument *aDocument, nsIContent* aContainer,
|
|||
|
||||
PRInt32 count = aContainer->GetChildCount();
|
||||
|
||||
if (count > 0 && MayContainRelevantNodes(aContainer)) {
|
||||
if (count > 0) {
|
||||
PRInt32 ourCount = mElements.Count();
|
||||
PRBool appendToList = PR_FALSE;
|
||||
if (ourCount == 0) {
|
||||
|
@ -636,7 +628,7 @@ nsContentList::ContentAppended(nsIDocument *aDocument, nsIContent* aContainer,
|
|||
*/
|
||||
for (i = aNewIndexInContainer; i <= count-1; ++i) {
|
||||
PRUint32 limit = PRUint32(-1);
|
||||
PopulateWith(aContainer->GetChildAt(i), PR_TRUE, limit);
|
||||
PopulateWith(aContainer->GetChildAt(i), limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -650,11 +642,12 @@ nsContentList::ContentInserted(nsIDocument *aDocument,
|
|||
// Note that aContainer can be null here if we are inserting into
|
||||
// the document itself; any attempted optimizations to this method
|
||||
// should deal with that.
|
||||
if (mState == LIST_DIRTY || IsContentAnonymous(aChild))
|
||||
return;
|
||||
|
||||
if (MayContainRelevantNodes(aContainer) && MatchSelf(aChild))
|
||||
if (mState != LIST_DIRTY &&
|
||||
MayContainRelevantNodes(NODE_FROM(aContainer, aDocument)) &&
|
||||
!IsContentAnonymous(aChild) &&
|
||||
MatchSelf(aChild)) {
|
||||
mState = LIST_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -666,28 +659,12 @@ nsContentList::ContentRemoved(nsIDocument *aDocument,
|
|||
// Note that aContainer can be null here if we are removing from
|
||||
// the document itself; any attempted optimizations to this method
|
||||
// should deal with that.
|
||||
if (mState != LIST_DIRTY) {
|
||||
if (MayContainRelevantNodes(aContainer)) {
|
||||
if (!IsContentAnonymous(aChild) && MatchSelf(aChild)) {
|
||||
mState = LIST_DIRTY;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (mState != LIST_DIRTY &&
|
||||
MayContainRelevantNodes(NODE_FROM(aContainer, aDocument)) &&
|
||||
!IsContentAnonymous(aChild) &&
|
||||
MatchSelf(aChild)) {
|
||||
mState = LIST_DIRTY;
|
||||
}
|
||||
|
||||
// Even if aChild is anonymous from our point of view, it could
|
||||
// contain our root (eg say our root is an anonymous child of
|
||||
// aChild).
|
||||
if (ContainsRoot(aChild)) {
|
||||
DisconnectFromDocument();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsContentList::DocumentWillBeDestroyed(nsIDocument *aDocument)
|
||||
{
|
||||
DisconnectFromDocument();
|
||||
Reset();
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -718,24 +695,11 @@ nsContentList::Match(nsIContent *aContent)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsContentList::CheckDocumentExistence()
|
||||
{
|
||||
if (!mDocument && mRootContent) {
|
||||
|
||||
mDocument = mRootContent->GetDocument();
|
||||
if (mDocument) {
|
||||
mDocument->AddObserver(this);
|
||||
mState = LIST_DIRTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsContentList::MatchSelf(nsIContent *aContent)
|
||||
{
|
||||
NS_PRECONDITION(aContent, "Can't match null stuff, you know");
|
||||
NS_PRECONDITION(mDeep || aContent->GetParent() == mRootContent,
|
||||
NS_PRECONDITION(mDeep || aContent->GetNodeParent() == mRootNode,
|
||||
"MatchSelf called on a node that we can't possibly match");
|
||||
|
||||
if (Match(aContent))
|
||||
|
@ -755,52 +719,45 @@ nsContentList::MatchSelf(nsIContent *aContent)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsContentList::PopulateWith(nsIContent *aContent, PRBool aIncludeRoot,
|
||||
PRUint32 & aElementsToAppend)
|
||||
void
|
||||
nsContentList::PopulateWith(nsIContent *aContent, PRUint32& aElementsToAppend)
|
||||
{
|
||||
NS_PRECONDITION(mDeep || aContent == mRootContent ||
|
||||
aContent->GetParent() == mRootContent,
|
||||
NS_PRECONDITION(mDeep || aContent->GetNodeParent() == mRootNode,
|
||||
"PopulateWith called on nodes we can't possibly match");
|
||||
NS_PRECONDITION(mDeep || aIncludeRoot || aContent == mRootContent,
|
||||
"Bogus root passed to PopulateWith in non-deep list");
|
||||
NS_PRECONDITION(!aIncludeRoot || aContent != mRootContent,
|
||||
"We should never be trying to match mRootContent");
|
||||
|
||||
if (aIncludeRoot) {
|
||||
if (Match(aContent)) {
|
||||
mElements.AppendElement(aContent);
|
||||
--aElementsToAppend;
|
||||
if (aElementsToAppend == 0)
|
||||
return;
|
||||
}
|
||||
NS_PRECONDITION(aContent != mRootNode,
|
||||
"We should never be trying to match mRootNode");
|
||||
|
||||
if (Match(aContent)) {
|
||||
mElements.AppendElement(aContent);
|
||||
--aElementsToAppend;
|
||||
if (aElementsToAppend == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't recurse down if we're not doing a deep match and we're
|
||||
// already looking at kids of the root.
|
||||
if (!mDeep && aIncludeRoot)
|
||||
// Don't recurse down if we're not doing a deep match.
|
||||
if (!mDeep)
|
||||
return;
|
||||
|
||||
PRUint32 i, count = aContent->GetChildCount();
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
PopulateWith(aContent->GetChildAt(i), PR_TRUE, aElementsToAppend);
|
||||
PopulateWith(aContent->GetChildAt(i), aElementsToAppend);
|
||||
if (aElementsToAppend == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsContentList::PopulateWithStartingAfter(nsIContent *aStartRoot,
|
||||
nsIContent *aStartChild,
|
||||
nsContentList::PopulateWithStartingAfter(nsINode *aStartRoot,
|
||||
nsINode *aStartChild,
|
||||
PRUint32 & aElementsToAppend)
|
||||
{
|
||||
NS_PRECONDITION(mDeep || aStartRoot == mRootContent ||
|
||||
(aStartRoot->GetParent() == mRootContent &&
|
||||
NS_PRECONDITION(mDeep || aStartRoot == mRootNode ||
|
||||
(aStartRoot->GetNodeParent() == mRootNode &&
|
||||
aStartChild == nsnull),
|
||||
"Bogus aStartRoot or aStartChild");
|
||||
|
||||
if (mDeep || aStartRoot == mRootContent) {
|
||||
if (mDeep || aStartRoot == mRootNode) {
|
||||
#ifdef DEBUG
|
||||
PRUint32 invariant = aElementsToAppend + mElements.Count();
|
||||
#endif
|
||||
|
@ -813,7 +770,7 @@ nsContentList::PopulateWithStartingAfter(nsIContent *aStartRoot,
|
|||
|
||||
PRUint32 childCount = aStartRoot->GetChildCount();
|
||||
for ( ; ((PRUint32)i) < childCount; ++i) {
|
||||
PopulateWith(aStartRoot->GetChildAt(i), PR_TRUE, aElementsToAppend);
|
||||
PopulateWith(aStartRoot->GetChildAt(i), aElementsToAppend);
|
||||
|
||||
NS_ASSERTION(aElementsToAppend + mElements.Count() == invariant,
|
||||
"Something is awry in PopulateWith!");
|
||||
|
@ -824,10 +781,14 @@ nsContentList::PopulateWithStartingAfter(nsIContent *aStartRoot,
|
|||
|
||||
// We want to make sure we don't move up past our root node. So if
|
||||
// we're there, don't move to the parent.
|
||||
if (aStartRoot == mRootContent)
|
||||
if (aStartRoot == mRootNode)
|
||||
return;
|
||||
|
||||
nsIContent* parent = aStartRoot->GetParent();
|
||||
// We could call GetParent() here to avoid walking children of the
|
||||
// document node. However they should be very few in number and we
|
||||
// might want to walk them in the future so it's unnecessary to have
|
||||
// this be the only thing that prevents it
|
||||
nsINode* parent = aStartRoot->GetNodeParent();
|
||||
|
||||
if (parent)
|
||||
PopulateWithStartingAfter(parent, aStartRoot, aElementsToAppend);
|
||||
|
@ -836,6 +797,10 @@ nsContentList::PopulateWithStartingAfter(nsIContent *aStartRoot,
|
|||
void
|
||||
nsContentList::PopulateSelf(PRUint32 aNeededLength)
|
||||
{
|
||||
if (!mRootNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mState == LIST_DIRTY) {
|
||||
Reset();
|
||||
}
|
||||
|
@ -848,93 +813,20 @@ nsContentList::PopulateSelf(PRUint32 aNeededLength)
|
|||
#ifdef DEBUG
|
||||
PRUint32 invariant = elementsToAppend + mElements.Count();
|
||||
#endif
|
||||
if (count != 0) {
|
||||
PopulateWithStartingAfter(NS_STATIC_CAST(nsIContent*,
|
||||
mElements.ElementAt(count - 1)),
|
||||
nsnull,
|
||||
elementsToAppend);
|
||||
NS_ASSERTION(elementsToAppend + mElements.Count() == invariant,
|
||||
"Something is awry in PopulateWithStartingAfter!");
|
||||
} else if (mRootContent) {
|
||||
PopulateWith(mRootContent, PR_FALSE, elementsToAppend);
|
||||
NS_ASSERTION(elementsToAppend + mElements.Count() == invariant,
|
||||
"Something is awry in PopulateWith!");
|
||||
}
|
||||
else if (mDocument) {
|
||||
nsIContent *root = mDocument->GetRootContent();
|
||||
if (root) {
|
||||
PopulateWith(root, PR_TRUE, elementsToAppend);
|
||||
NS_ASSERTION(elementsToAppend + mElements.Count() == invariant,
|
||||
"Something is awry in PopulateWith!");
|
||||
}
|
||||
}
|
||||
|
||||
if (mDocument) {
|
||||
if (elementsToAppend != 0)
|
||||
mState = LIST_UP_TO_DATE;
|
||||
else
|
||||
mState = LIST_LAZY;
|
||||
} else {
|
||||
// No document means we have to stay on our toes since we don't
|
||||
// get content notifications.
|
||||
mState = LIST_DIRTY;
|
||||
}
|
||||
}
|
||||
// If we already have nodes start searching at the last one, otherwise
|
||||
// start searching at the root.
|
||||
nsINode* startRoot = count == 0 ? mRootNode :
|
||||
NS_STATIC_CAST(nsIContent*, mElements.ElementAt(count - 1));
|
||||
|
||||
PRBool
|
||||
nsContentList::MayContainRelevantNodes(nsIContent* aContainer)
|
||||
{
|
||||
if (!mRootContent) {
|
||||
#ifdef DEBUG
|
||||
// aContainer can be null when ContentInserted/ContentRemoved are
|
||||
// called, but we still want to return PR_TRUE in such cases if
|
||||
// mRootContent is null. We could pass the document into this
|
||||
// method instead of trying to get it from aContainer, but that
|
||||
// seems a little pointless just to run this debug-only integrity
|
||||
// check.
|
||||
if (aContainer) {
|
||||
NS_ASSERTION(aContainer->GetDocument() == mDocument,
|
||||
"We should not get in here if aContainer is in some _other_ document!");
|
||||
}
|
||||
#endif
|
||||
return PR_TRUE;
|
||||
}
|
||||
PopulateWithStartingAfter(startRoot, nsnull, elementsToAppend);
|
||||
NS_ASSERTION(elementsToAppend + mElements.Count() == invariant,
|
||||
"Something is awry in PopulateWith!");
|
||||
|
||||
if (!aContainer) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!mDeep) {
|
||||
// We only care about cases when aContainer is our root content node.
|
||||
return aContainer == mRootContent;
|
||||
}
|
||||
|
||||
return nsContentUtils::ContentIsDescendantOf(aContainer, mRootContent);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsContentList::ContainsRoot(nsIContent* aContent)
|
||||
{
|
||||
if (!mRootContent || !aContent) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return nsContentUtils::ContentIsDescendantOf(mRootContent, aContent);
|
||||
}
|
||||
|
||||
void
|
||||
nsContentList::DisconnectFromDocument()
|
||||
{
|
||||
if (mDocument) {
|
||||
// Our key will change... Best remove ourselves before that happens.
|
||||
RemoveFromHashtable();
|
||||
mDocument->RemoveObserver(this);
|
||||
mDocument = nsnull;
|
||||
}
|
||||
|
||||
// We will get no more updates, so we can never know we're up to
|
||||
// date
|
||||
mState = LIST_DIRTY;
|
||||
if (elementsToAppend != 0)
|
||||
mState = LIST_UP_TO_DATE;
|
||||
else
|
||||
mState = LIST_LAZY;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -961,15 +853,21 @@ nsContentList::RemoveFromHashtable()
|
|||
void
|
||||
nsContentList::BringSelfUpToDate(PRBool aDoFlush)
|
||||
{
|
||||
if (mDocument && aDoFlush) {
|
||||
// Flush pending content changes Bug 4891.
|
||||
mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
|
||||
if (mRootNode && aDoFlush) {
|
||||
// XXX sXBL/XBL2 issue
|
||||
// Ideally we should call GetCurrentDoc here, i think, but that doesn't
|
||||
// live on nsINode
|
||||
nsIDocument* doc = mRootNode->GetOwnerDoc();
|
||||
if (doc) {
|
||||
// Flush pending content changes Bug 4891.
|
||||
doc->FlushPendingNotifications(Flush_ContentAndNotify);
|
||||
}
|
||||
}
|
||||
|
||||
if (mState != LIST_UP_TO_DATE)
|
||||
PopulateSelf(PRUint32(-1));
|
||||
|
||||
NS_ASSERTION(!mDocument || mState == LIST_UP_TO_DATE,
|
||||
NS_ASSERTION(!mRootNode || mState == LIST_UP_TO_DATE,
|
||||
"PopulateSelf dod not bring content list up to date!");
|
||||
}
|
||||
|
||||
|
@ -987,34 +885,35 @@ nsContentList::IsContentAnonymous(nsIContent* aContent)
|
|||
* that node that it can see are not anonymous from our point of view.
|
||||
*/
|
||||
|
||||
if (!mRootContent) {
|
||||
if (!mRootNode->IsNodeOfType(nsINode::eCONTENT)) {
|
||||
/**
|
||||
* If we have no root, that means we correspond to a list gotten off the
|
||||
* "document" object, so will always contain only nodes that the document
|
||||
* can see, which means only nodes with a null bindingParent.
|
||||
* The root isn't an nsIContent, that means we correspond to a list gotten
|
||||
* off the "document" object, so will always contain only nodes that the
|
||||
* document can see, which means only nodes with a null bindingParent.
|
||||
*/
|
||||
return aContent->GetBindingParent() != nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* If mRootContent and aContent have _different_ bindingParents, then there
|
||||
* If mRootNode and aContent have _different_ bindingParents, then there
|
||||
* are two possibilities:
|
||||
*
|
||||
* 1) aContent or one of its ancestors is an anonymous child of a descendant
|
||||
* of mRootContent (or of mRootContent itself).
|
||||
* 2) mRootContent is not an ancestor of aContent.
|
||||
* of mRootNode (or of mRootNode itself).
|
||||
* 2) mRootNode is not an ancestor of aContent.
|
||||
*
|
||||
* In either case, we don't want to be matching aContent or any of its
|
||||
* descendants.
|
||||
*
|
||||
* On the other hand, if mRootContent and aContent have the same
|
||||
* On the other hand, if mRootNode and aContent have the same
|
||||
* bindingParent then they are part of the same binding (or native anonymous
|
||||
* content chunk) and then aContent may be a descendant of mRootContent and
|
||||
* content chunk) and then aContent may be a descendant of mRootNode and
|
||||
* we may want to match it.
|
||||
*
|
||||
* So we return true if the binding parents don't match; if the binding
|
||||
* parents are the same, the checks we normally do to determine whether we
|
||||
* match a node should be done.
|
||||
*/
|
||||
return mRootContent->GetBindingParent() != aContent->GetBindingParent();
|
||||
return NS_STATIC_CAST(nsIContent*, mRootNode)->GetBindingParent() !=
|
||||
aContent->GetBindingParent();
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
#include "nsString.h"
|
||||
#include "nsIDOMHTMLCollection.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsStubDocumentObserver.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
|
||||
|
@ -112,22 +112,19 @@ public:
|
|||
class nsContentListKey
|
||||
{
|
||||
public:
|
||||
nsContentListKey(nsIDocument *aDocument,
|
||||
nsContentListKey(nsINode* aRootNode,
|
||||
nsIAtom* aMatchAtom,
|
||||
PRInt32 aMatchNameSpaceId,
|
||||
nsIContent* aRootContent)
|
||||
PRInt32 aMatchNameSpaceId)
|
||||
: mMatchAtom(aMatchAtom),
|
||||
mMatchNameSpaceId(aMatchNameSpaceId),
|
||||
mDocument(aDocument),
|
||||
mRootContent(aRootContent)
|
||||
mRootNode(aRootNode)
|
||||
{
|
||||
}
|
||||
|
||||
nsContentListKey(const nsContentListKey& aContentListKey)
|
||||
: mMatchAtom(aContentListKey.mMatchAtom),
|
||||
mMatchNameSpaceId(aContentListKey.mMatchNameSpaceId),
|
||||
mDocument(aContentListKey.mDocument),
|
||||
mRootContent(aContentListKey.mRootContent)
|
||||
mRootNode(aContentListKey.mRootNode)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -136,27 +133,20 @@ public:
|
|||
return
|
||||
mMatchAtom == aContentListKey.mMatchAtom &&
|
||||
mMatchNameSpaceId == aContentListKey.mMatchNameSpaceId &&
|
||||
mDocument == aContentListKey.mDocument &&
|
||||
mRootContent == aContentListKey.mRootContent;
|
||||
mRootNode == aContentListKey.mRootNode;
|
||||
}
|
||||
inline PRUint32 GetHash(void) const
|
||||
{
|
||||
return
|
||||
NS_PTR_TO_INT32(mMatchAtom.get()) ^
|
||||
(NS_PTR_TO_INT32(mRootContent) << 8) ^
|
||||
(NS_PTR_TO_INT32(mDocument) << 16) ^
|
||||
(NS_PTR_TO_INT32(mRootNode) << 12) ^
|
||||
(mMatchNameSpaceId << 24);
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIAtom> mMatchAtom;
|
||||
PRInt32 mMatchNameSpaceId;
|
||||
nsIDocument* mDocument; // Weak ref
|
||||
// XXX What if the mRootContent is detached from the doc and _then_
|
||||
// goes away (so we never get notified)? Note that we work around
|
||||
// that a little by not caching lists with an mRootContent in
|
||||
// gCachedContentList. If we fix this, we can remove that check.
|
||||
nsIContent* mRootContent; // Weak ref
|
||||
nsINode* mRootNode; // Weak ref
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -166,36 +156,31 @@ protected:
|
|||
class nsContentList : public nsBaseContentList,
|
||||
protected nsContentListKey,
|
||||
public nsIDOMHTMLCollection,
|
||||
public nsStubDocumentObserver
|
||||
public nsStubMutationObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
/**
|
||||
* @param aDocument the document to which to add as an nsIDocumentObserver
|
||||
* @param aRootNode The node under which to limit our search.
|
||||
* @param aMatchAtom an atom whose meaning depends on aMatchNameSpaceId
|
||||
* @param aMatchNameSpaceId if kNameSpaceID_Unknown then aMatchAtom is the
|
||||
* tagName to match. Otherwise we match nodes with
|
||||
* aMatchNameSpaceId and a localName equal to
|
||||
* aMatchAtom
|
||||
* @param aRootContent The content node under which to limit our search.
|
||||
* If not null, the root is aDocument.
|
||||
* @param aDeep If false, then look only at children of the root, nothing
|
||||
* deeper. If true, then look at the whole subtree rooted at
|
||||
* our root.
|
||||
*/
|
||||
nsContentList(nsIDocument *aDocument,
|
||||
nsContentList(nsINode* aRootNode,
|
||||
nsIAtom* aMatchAtom,
|
||||
PRInt32 aMatchNameSpaceId,
|
||||
nsIContent* aRootContent = nsnull,
|
||||
PRBool aDeep = PR_TRUE);
|
||||
|
||||
/**
|
||||
* @param aDocument the document to which to add as an nsIDocumentObserver
|
||||
* @param aRootNode The node under which to limit our search.
|
||||
* @param aFunc the function to be called to determine whether we match
|
||||
* @param aData a string that will need to be passed back to aFunc
|
||||
* @param aRootContent The content node under which to limit our search.
|
||||
* If not null, the root is aDocument.
|
||||
* @param aDeep If false, then look only at children of the root, nothing
|
||||
* deeper. If true, then look at the whole subtree rooted at
|
||||
* our root.
|
||||
|
@ -204,10 +189,9 @@ public:
|
|||
* @param aFuncMayDependOnAttr a boolean that indicates whether this list is
|
||||
* sensitive to attribute changes.
|
||||
*/
|
||||
nsContentList(nsIDocument *aDocument,
|
||||
nsContentList(nsINode* aRootNode,
|
||||
nsContentListMatchFunc aFunc,
|
||||
const nsAString& aData,
|
||||
nsIContent* aRootContent = nsnull,
|
||||
PRBool aDeep = PR_TRUE,
|
||||
nsIAtom* aMatchAtom = nsnull,
|
||||
PRInt32 aMatchNameSpaceId = kNameSpaceID_None,
|
||||
|
@ -225,14 +209,13 @@ public:
|
|||
NS_HIDDEN_(PRUint32) Length(PRBool aDoFlush);
|
||||
NS_HIDDEN_(nsIContent*) Item(PRUint32 aIndex, PRBool aDoFlush);
|
||||
NS_HIDDEN_(nsIContent*) NamedItem(const nsAString& aName, PRBool aDoFlush);
|
||||
NS_HIDDEN_(void) RootDestroyed();
|
||||
|
||||
nsContentListKey* GetKey() {
|
||||
return NS_STATIC_CAST(nsContentListKey*, this);
|
||||
}
|
||||
|
||||
|
||||
// nsIDocumentObserver
|
||||
// nsIMutationObserver
|
||||
virtual void AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
||||
PRInt32 aModType);
|
||||
|
@ -242,10 +225,9 @@ public:
|
|||
nsIContent* aChild, PRInt32 aIndexInContainer);
|
||||
virtual void ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
|
||||
nsIContent* aChild, PRInt32 aIndexInContainer);
|
||||
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument);
|
||||
virtual void NodeWillBeDestroyed(const nsINode *aNode);
|
||||
|
||||
protected:
|
||||
void Init(nsIDocument *aDocument);
|
||||
/**
|
||||
* Returns whether the content element matches our criterion
|
||||
*
|
||||
|
@ -268,13 +250,14 @@ protected:
|
|||
* elements. This function enforces the invariant that
|
||||
* |aElementsToAppend + mElements.Count()| is a constant.
|
||||
*
|
||||
* @param aContent the root of the subtree we want to traverse
|
||||
* @param aIncludeRoot whether to include the root in the traversal
|
||||
* @param aContent the root of the subtree we want to traverse. This node
|
||||
* is always included in the traversal and is thus the
|
||||
* first node tested.
|
||||
* @param aElementsToAppend how many elements to append to the list
|
||||
* before stopping
|
||||
*/
|
||||
void PopulateWith(nsIContent *aContent, PRBool aIncludeRoot,
|
||||
PRUint32 & aElementsToAppend);
|
||||
|
||||
void PopulateWith(nsIContent *aContent, PRUint32 & aElementsToAppend);
|
||||
/**
|
||||
* Populate our list starting at the child of aStartRoot that comes
|
||||
* after aStartChild (if such exists) and continuing in document
|
||||
|
@ -287,8 +270,8 @@ protected:
|
|||
* @param aElementsToAppend how many elements to append to the list
|
||||
* before stopping
|
||||
*/
|
||||
void PopulateWithStartingAfter(nsIContent *aStartRoot,
|
||||
nsIContent *aStartChild,
|
||||
void PopulateWithStartingAfter(nsINode *aStartRoot,
|
||||
nsINode *aStartChild,
|
||||
PRUint32 & aElementsToAppend);
|
||||
/**
|
||||
* Populate our list. Stop once we have at least aNeededLength
|
||||
|
@ -302,36 +285,17 @@ protected:
|
|||
void PopulateSelf(PRUint32 aNeededLength);
|
||||
|
||||
/**
|
||||
* Our root content has been disconnected from the document, so stop
|
||||
* observing. From this point on, if someone asks us something we
|
||||
* walk the tree rooted at mRootContent starting at the beginning
|
||||
* and going as far as we need to to answer the question.
|
||||
* @param aContainer a content node which must be a descendant of
|
||||
* mRootNode
|
||||
* @return PR_TRUE if children or descendants of aContainer could match our
|
||||
* criterion.
|
||||
* PR_FALSE otherwise.
|
||||
*/
|
||||
void DisconnectFromDocument();
|
||||
PRBool MayContainRelevantNodes(nsINode* aContainer)
|
||||
{
|
||||
return mDeep || aContainer == mRootNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aContainer a content node which could be a descendant of
|
||||
* mRootContent
|
||||
* @return PR_TRUE if mRootContent is null, PR_FALSE if aContainer
|
||||
* is null, PR_TRUE if aContainer is a descendant of mRootContent
|
||||
* (though if mDeep is false, only aContainer == mRootContent
|
||||
* counts), PR_FALSE otherwise
|
||||
*/
|
||||
PRBool MayContainRelevantNodes(nsIContent* aContainer);
|
||||
/**
|
||||
* Does this subtree contain our mRootContent?
|
||||
*
|
||||
* @param aContainer the root of the subtree
|
||||
* @return PR_FALSE if mRootContent is null, otherwise whether
|
||||
* mRootContent is a descendant of aContainer
|
||||
*/
|
||||
PRBool ContainsRoot(nsIContent* aContent);
|
||||
/**
|
||||
* If we have no document and we have a root content, then check if
|
||||
* our content has been added to a document. If so, we'll become an
|
||||
* observer of the document.
|
||||
*/
|
||||
void CheckDocumentExistence();
|
||||
/**
|
||||
* Remove ourselves from the hashtable that caches commonly accessed
|
||||
* content lists. Generally done on destruction.
|
||||
|
@ -368,7 +332,7 @@ protected:
|
|||
PRUint8 mState;
|
||||
/**
|
||||
* Whether to actually descend the tree. If this is false, we won't
|
||||
* consider grandkids of mRootContent.
|
||||
* consider grandkids of mRootNode.
|
||||
*/
|
||||
PRPackedBool mDeep;
|
||||
/**
|
||||
|
@ -399,7 +363,7 @@ protected:
|
|||
#define LIST_LAZY 2
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
NS_GetContentList(nsIDocument* aDocument, nsIAtom* aMatchAtom,
|
||||
PRInt32 aMatchNameSpaceId, nsIContent* aRootContent);
|
||||
NS_GetContentList(nsINode* aRootNode, nsIAtom* aMatchAtom,
|
||||
PRInt32 aMatchNameSpaceId);
|
||||
|
||||
#endif // nsContentList_h___
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "nsEventDispatcher.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsNodeUtils.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
PRBool nsDOMAttribute::sInitialized;
|
||||
|
@ -74,6 +75,8 @@ nsDOMAttribute::nsDOMAttribute(nsDOMAttributeMap *aAttrMap,
|
|||
|
||||
nsDOMAttribute::~nsDOMAttribute()
|
||||
{
|
||||
nsNodeUtils::NodeWillBeDestroyed(this);
|
||||
|
||||
if (mChildList) {
|
||||
mChildList->DropReference();
|
||||
NS_RELEASE(mChildList);
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
#include "nsIDOMCDATASection.h"
|
||||
#include "nsIDOMProcessingInstruction.h"
|
||||
#include "nsDOMString.h"
|
||||
#include "nsNodeUtils.h"
|
||||
|
||||
#include "nsRange.h"
|
||||
#include "nsIDOMText.h"
|
||||
|
@ -331,6 +332,7 @@ nsDOMStyleSheetList::~nsDOMStyleSheetList()
|
|||
NS_INTERFACE_MAP_BEGIN(nsDOMStyleSheetList)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMStyleSheetList)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMStyleSheetList)
|
||||
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(DocumentStyleSheetList)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
@ -385,12 +387,9 @@ nsDOMStyleSheetList::Item(PRUint32 aIndex, nsIDOMStyleSheet** aReturn)
|
|||
}
|
||||
|
||||
void
|
||||
nsDOMStyleSheetList::DocumentWillBeDestroyed(nsIDocument *aDocument)
|
||||
nsDOMStyleSheetList::NodeWillBeDestroyed(const nsINode *aNode)
|
||||
{
|
||||
if (nsnull != mDocument) {
|
||||
aDocument->RemoveObserver(this);
|
||||
mDocument = nsnull;
|
||||
}
|
||||
mDocument = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -679,14 +678,9 @@ nsDocument::~nsDocument()
|
|||
this, nsnull, nsnull);
|
||||
}
|
||||
|
||||
// XXX Inform any remaining observers that we are going away.
|
||||
// Note that this currently contradicts the rule that all
|
||||
// observers must hold on to live references to the document.
|
||||
// This notification will occur only after the reference has
|
||||
// been dropped.
|
||||
|
||||
PRInt32 indx;
|
||||
NS_DOCUMENT_NOTIFY_OBSERVERS(DocumentWillBeDestroyed, (this));
|
||||
nsNodeUtils::NodeWillBeDestroyed(this);
|
||||
// Clear mObservers to keep it in sync with the mutationobserver list
|
||||
mObservers.Clear();
|
||||
|
||||
mParentDocument = nsnull;
|
||||
|
||||
|
@ -698,6 +692,7 @@ nsDocument::~nsDocument()
|
|||
mSubDocuments = nsnull;
|
||||
}
|
||||
|
||||
PRInt32 indx;
|
||||
if (mRootContent) {
|
||||
if (mRootContent->GetCurrentDoc()) {
|
||||
NS_ASSERTION(mRootContent->GetCurrentDoc() == this,
|
||||
|
@ -794,6 +789,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocument)
|
|||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRadioGroupContainer)
|
||||
NS_INTERFACE_MAP_ENTRY(nsINode)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocument)
|
||||
if (aIID.Equals(NS_GET_IID(nsIDOMXPathEvaluator)) ||
|
||||
aIID.Equals(NS_GET_IID(nsIXPathEvaluatorInternal))) {
|
||||
|
@ -829,6 +825,19 @@ nsDocument::Init()
|
|||
|
||||
// The binding manager must always be the first observer of the document.
|
||||
mObservers.PrependObserver(bindingManager);
|
||||
nsINode::nsSlots* slots = GetSlots();
|
||||
NS_ENSURE_TRUE(slots &&
|
||||
slots->mMutationObservers.PrependObserver(bindingManager),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
// Prepend self as mutation-observer whether we need it or not (some
|
||||
// subclasses currently do, other don't). This is because the code in
|
||||
// nsNodeUtils always notifies the first observer first, even when going
|
||||
// backwards, expecting the first observer to be the document.
|
||||
// If we remove that hack, we can move the below registring out to the leaf
|
||||
// classes.
|
||||
NS_ENSURE_TRUE(slots->mMutationObservers.PrependObserver(this),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
|
||||
mOnloadBlocker = new nsOnloadBlocker();
|
||||
NS_ENSURE_TRUE(mOnloadBlocker, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
@ -935,7 +944,7 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup)
|
|||
for (PRInt32 i = PRInt32(count) - 1; i >= 0; i--) {
|
||||
nsCOMPtr<nsIContent> content = mChildren.ChildAt(i);
|
||||
|
||||
ContentRemoved(nsnull, content, i);
|
||||
nsNodeUtils::ContentRemoved(this, content, i);
|
||||
content->UnbindFromTree();
|
||||
mChildren.RemoveChildAt(i);
|
||||
}
|
||||
|
@ -2235,10 +2244,9 @@ nsDocument::GetScriptLoader()
|
|||
void
|
||||
nsDocument::AddObserver(nsIDocumentObserver* aObserver)
|
||||
{
|
||||
// Make sure the observer isn't already in the list
|
||||
if (!mObservers.Contains(aObserver)) {
|
||||
mObservers.AppendObserver(aObserver);
|
||||
}
|
||||
// The array makes sure the observer isn't already in the list
|
||||
mObservers.AppendObserver(aObserver);
|
||||
AddMutationObserver(aObserver);
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -2249,6 +2257,7 @@ nsDocument::RemoveObserver(nsIDocumentObserver* aObserver)
|
|||
// observers from the list. This is not a big deal, since we
|
||||
// don't hold a live reference to the observers.
|
||||
if (!mInDestructor) {
|
||||
RemoveMutationObserver(aObserver);
|
||||
return mObservers.RemoveObserver(aObserver);
|
||||
}
|
||||
|
||||
|
@ -2407,14 +2416,6 @@ nsDocument::EndLoad()
|
|||
UnblockOnload(PR_TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::CharacterDataChanged(nsIContent* aContent, PRBool aAppend)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aContent, "Null content!");
|
||||
|
||||
NS_DOCUMENT_NOTIFY_OBSERVERS(CharacterDataChanged, (this, aContent, aAppend));
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::ContentStatesChanged(nsIContent* aContent1, nsIContent* aContent2,
|
||||
PRInt32 aStateMask)
|
||||
|
@ -2423,54 +2424,6 @@ nsDocument::ContentStatesChanged(nsIContent* aContent1, nsIContent* aContent2,
|
|||
(this, aContent1, aContent2, aStateMask));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsDocument::ContentAppended(nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aContainer, "Null container!");
|
||||
|
||||
// XXXdwh There is a hacky ordering dependency between the binding
|
||||
// manager and the frame constructor that forces us to walk the
|
||||
// observer list in a forward order
|
||||
// XXXldb So one should notify the other rather than both being
|
||||
// registered.
|
||||
NS_DOCUMENT_FORWARD_NOTIFY_OBSERVERS(ContentAppended,
|
||||
(this, aContainer,
|
||||
aNewIndexInContainer));
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::ContentInserted(nsIContent* aContainer, nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aChild, "Null child!");
|
||||
|
||||
// XXXdwh There is a hacky ordering dependency between the binding manager
|
||||
// and the frame constructor that forces us to walk the observer list
|
||||
// in a forward order
|
||||
// XXXldb So one should notify the other rather than both being
|
||||
// registered.
|
||||
NS_DOCUMENT_FORWARD_NOTIFY_OBSERVERS(ContentInserted,
|
||||
(this, aContainer, aChild,
|
||||
aIndexInContainer));
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::ContentRemoved(nsIContent* aContainer, nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aChild, "Null child!");
|
||||
|
||||
// XXXdwh There is a hacky ordering dependency between the binding
|
||||
// manager and the frame constructor that forces us to walk the
|
||||
// observer list in a reverse order
|
||||
// XXXldb So one should notify the other rather than both being
|
||||
// registered.
|
||||
NS_DOCUMENT_NOTIFY_OBSERVERS(ContentRemoved,
|
||||
(this, aContainer, aChild, aIndexInContainer));
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::AttributeWillChange(nsIContent* aChild, PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute)
|
||||
|
@ -2478,17 +2431,6 @@ nsDocument::AttributeWillChange(nsIContent* aChild, PRInt32 aNameSpaceID,
|
|||
NS_ASSERTION(aChild, "Null child!");
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::AttributeChanged(nsIContent* aChild, PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute, PRInt32 aModType)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aChild, "Null child!");
|
||||
|
||||
NS_DOCUMENT_NOTIFY_OBSERVERS(AttributeChanged, (this, aChild, aNameSpaceID,
|
||||
aAttribute, aModType));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsDocument::StyleRuleChanged(nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aOldStyleRule,
|
||||
|
@ -2784,8 +2726,7 @@ nsDocument::GetElementsByTagName(const nsAString& aTagname,
|
|||
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aTagname);
|
||||
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsContentList *list = NS_GetContentList(this, nameAtom, kNameSpaceID_Unknown,
|
||||
nsnull).get();
|
||||
nsContentList *list = NS_GetContentList(this, nameAtom, kNameSpaceID_Unknown).get();
|
||||
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// transfer ref to aReturn
|
||||
|
@ -2808,7 +2749,7 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
|||
|
||||
if (nameSpaceId == kNameSpaceID_Unknown) {
|
||||
// Unknown namespace means no matches, we create an empty list...
|
||||
list = NS_GetContentList(this, nsnull, kNameSpaceID_None, nsnull).get();
|
||||
list = NS_GetContentList(this, nsnull, kNameSpaceID_None).get();
|
||||
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
@ -2817,7 +2758,7 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
|||
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLocalName);
|
||||
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
list = NS_GetContentList(this, nameAtom, nameSpaceId, nsnull).get();
|
||||
list = NS_GetContentList(this, nameAtom, nameSpaceId).get();
|
||||
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
|
@ -5079,10 +5020,9 @@ nsDocument::OnPageShow(PRBool aPersisted)
|
|||
|
||||
if (aPersisted) {
|
||||
// Send out notifications that our <link> elements are attached.
|
||||
nsRefPtr<nsContentList> links = NS_GetContentList(this,
|
||||
nsRefPtr<nsContentList> links = NS_GetContentList(mRootContent,
|
||||
nsHTMLAtoms::link,
|
||||
kNameSpaceID_Unknown,
|
||||
mRootContent);
|
||||
kNameSpaceID_Unknown);
|
||||
|
||||
if (links) {
|
||||
PRUint32 linkCount = links->Length(PR_TRUE);
|
||||
|
@ -5105,10 +5045,9 @@ nsDocument::OnPageHide(PRBool aPersisted)
|
|||
// Send out notifications that our <link> elements are detached,
|
||||
// but only if this is not a full unload.
|
||||
if (aPersisted) {
|
||||
nsRefPtr<nsContentList> links = NS_GetContentList(this,
|
||||
nsRefPtr<nsContentList> links = NS_GetContentList(mRootContent,
|
||||
nsHTMLAtoms::link,
|
||||
kNameSpaceID_Unknown,
|
||||
mRootContent);
|
||||
kNameSpaceID_Unknown);
|
||||
|
||||
if (links) {
|
||||
PRUint32 linkCount = links->Length(PR_TRUE);
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
#include "nsIRequest.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
|
||||
// Put these here so all document impls get them automatically
|
||||
#include "nsHTMLStyleSheet.h"
|
||||
|
@ -238,7 +239,7 @@ public:
|
|||
NS_DECL_NSIDOMSTYLESHEETLIST
|
||||
|
||||
// nsIDocumentObserver
|
||||
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument);
|
||||
virtual void NodeWillBeDestroyed(const nsINode *aNode);
|
||||
virtual void StyleSheetAdded(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
PRBool aDocumentSheet);
|
||||
|
@ -288,7 +289,8 @@ class nsDocument : public nsIDocument,
|
|||
public nsIDOM3EventTarget,
|
||||
public nsIDOMNSEventTarget,
|
||||
public nsIScriptObjectPrincipal,
|
||||
public nsIRadioGroupContainer
|
||||
public nsIRadioGroupContainer,
|
||||
public nsStubMutationObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -468,8 +470,6 @@ public:
|
|||
virtual void EndUpdate(nsUpdateType aUpdateType);
|
||||
virtual void BeginLoad();
|
||||
virtual void EndLoad();
|
||||
virtual void CharacterDataChanged(nsIContent* aContent,
|
||||
PRBool aAppend);
|
||||
virtual void ContentStatesChanged(nsIContent* aContent1,
|
||||
nsIContent* aContent2,
|
||||
PRInt32 aStateMask);
|
||||
|
@ -477,18 +477,6 @@ public:
|
|||
virtual void AttributeWillChange(nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute);
|
||||
virtual void AttributeChanged(nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType);
|
||||
virtual void ContentAppended(nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer);
|
||||
virtual void ContentInserted(nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer);
|
||||
virtual void ContentRemoved(nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer);
|
||||
|
||||
virtual void StyleRuleChanged(nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aOldStyleRule,
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include "nsChangeHint.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsNodeUtils.h"
|
||||
|
||||
#include "pldhash.h"
|
||||
#include "prprf.h"
|
||||
|
@ -88,12 +89,10 @@ nsGenericDOMDataNode::nsGenericDOMDataNode(nsINodeInfo *aNodeInfo)
|
|||
|
||||
nsGenericDOMDataNode::~nsGenericDOMDataNode()
|
||||
{
|
||||
if (HasSlots()) {
|
||||
nsDataSlots* slots = GetDataSlots();
|
||||
PtrBits flags = slots->mFlags | NODE_DOESNT_HAVE_SLOTS;
|
||||
delete slots;
|
||||
mFlagsOrSlots = flags;
|
||||
}
|
||||
NS_PRECONDITION(!IsInDoc(),
|
||||
"Please remove this from the document properly");
|
||||
|
||||
nsNodeUtils::NodeWillBeDestroyed(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -435,10 +434,8 @@ nsGenericDOMDataNode::AppendData(const nsAString& aData)
|
|||
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
|
||||
}
|
||||
|
||||
// Trigger a reflow
|
||||
if (document) {
|
||||
document->CharacterDataChanged(this, PR_TRUE);
|
||||
}
|
||||
// Notify observers
|
||||
nsNodeUtils::CharacterDataChanged(this, PR_TRUE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -898,6 +895,12 @@ nsGenericDOMDataNode::GetBaseURI() const
|
|||
return uri;
|
||||
}
|
||||
|
||||
nsINode::nsSlots*
|
||||
nsGenericDOMDataNode::CreateSlots()
|
||||
{
|
||||
return new nsDataSlots(mFlagsOrSlots);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Implementation of the nsIDOMText interface
|
||||
|
@ -1010,7 +1013,7 @@ nsGenericDOMDataNode::SetText(const PRUnichar* aBuffer,
|
|||
|
||||
// Trigger a reflow
|
||||
if (aNotify && document) {
|
||||
document->CharacterDataChanged(this, PR_FALSE);
|
||||
nsNodeUtils::CharacterDataChanged(this, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -271,6 +271,7 @@ public:
|
|||
void ToCString(nsAString& aBuf, PRInt32 aOffset, PRInt32 aLen) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/**
|
||||
* There are a set of DOM- and scripting-specific instance variables
|
||||
* that may only be instantiated when a content object is accessed
|
||||
|
@ -283,7 +284,7 @@ public:
|
|||
{
|
||||
public:
|
||||
nsDataSlots(PtrBits aFlags);
|
||||
~nsDataSlots();
|
||||
virtual ~nsDataSlots();
|
||||
|
||||
/**
|
||||
* An object implementing nsIDOMNodeList for this content (childNodes)
|
||||
|
@ -298,26 +299,19 @@ public:
|
|||
nsIContent* mBindingParent; // [Weak]
|
||||
};
|
||||
|
||||
// Override from nsINode
|
||||
virtual nsINode::nsSlots* CreateSlots();
|
||||
|
||||
nsDataSlots *GetDataSlots()
|
||||
{
|
||||
if (!HasSlots()) {
|
||||
nsDataSlots *slots = new nsDataSlots(mFlagsOrSlots);
|
||||
|
||||
if (!slots) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
SetSlots(slots);
|
||||
}
|
||||
|
||||
return NS_STATIC_CAST(nsDataSlots*, FlagsAsSlots());
|
||||
return NS_STATIC_CAST(nsDataSlots*, GetSlots());
|
||||
}
|
||||
|
||||
nsDataSlots *GetExistingDataSlots() const
|
||||
{
|
||||
return NS_STATIC_CAST(nsDataSlots*, GetExistingSlots());
|
||||
}
|
||||
protected:
|
||||
|
||||
nsresult SplitText(PRUint32 aOffset, nsIDOMText** aReturn);
|
||||
|
||||
/**
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIDOMMutationEvent.h"
|
||||
#include "nsMutationEvent.h"
|
||||
#include "nsNodeUtils.h"
|
||||
|
||||
#include "nsIBindingManager.h"
|
||||
#include "nsXBLBinding.h"
|
||||
|
@ -297,6 +298,30 @@ nsINode::GetListenerManager(PRBool aCreateIfNotFound,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsINode::nsSlots*
|
||||
nsINode::CreateSlots()
|
||||
{
|
||||
return new nsSlots(mFlagsOrSlots);
|
||||
}
|
||||
|
||||
void
|
||||
nsINode::AddMutationObserver(nsIMutationObserver* aMutationObserver)
|
||||
{
|
||||
nsSlots* slots = GetSlots();
|
||||
if (slots) {
|
||||
slots->mMutationObservers.AppendObserver(aMutationObserver);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsINode::RemoveMutationObserver(nsIMutationObserver* aMutationObserver)
|
||||
{
|
||||
nsSlots* slots = GetExistingSlots();
|
||||
if (slots) {
|
||||
slots->mMutationObservers.RemoveObserver(aMutationObserver);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
|
@ -990,12 +1015,6 @@ nsGenericElement::nsDOMSlots::~nsDOMSlots()
|
|||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsGenericElement::nsDOMSlots::IsEmpty()
|
||||
{
|
||||
return (!mChildNodes && !mStyle && !mAttributeMap && !mBindingParent);
|
||||
}
|
||||
|
||||
nsGenericElement::nsGenericElement(nsINodeInfo *aNodeInfo)
|
||||
: nsIXMLContent(aNodeInfo)
|
||||
{
|
||||
|
@ -1009,12 +1028,7 @@ nsGenericElement::~nsGenericElement()
|
|||
NS_PRECONDITION(!IsInDoc(),
|
||||
"Please remove this from the document properly");
|
||||
|
||||
if (HasSlots()) {
|
||||
nsDOMSlots* slots = GetDOMSlots();
|
||||
PtrBits flags = slots->mFlags | NODE_DOESNT_HAVE_SLOTS;
|
||||
delete slots;
|
||||
mFlagsOrSlots = flags;
|
||||
}
|
||||
nsNodeUtils::NodeWillBeDestroyed(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1543,8 +1557,8 @@ nsGenericElement::GetElementsByTagName(const nsAString& aTagname,
|
|||
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aTagname);
|
||||
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsContentList *list = NS_GetContentList(GetCurrentDoc(), nameAtom,
|
||||
kNameSpaceID_Unknown, this).get();
|
||||
nsContentList *list = NS_GetContentList(this, nameAtom,
|
||||
kNameSpaceID_Unknown).get();
|
||||
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// transfer ref to aReturn
|
||||
|
@ -1674,7 +1688,7 @@ nsGenericElement::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
|||
if (nameSpaceId == kNameSpaceID_Unknown) {
|
||||
// Unknown namespace means no matches, we create an empty list...
|
||||
list = NS_GetContentList(document, nsnull,
|
||||
kNameSpaceID_None, nsnull).get();
|
||||
kNameSpaceID_None).get();
|
||||
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
@ -1683,7 +1697,7 @@ nsGenericElement::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
|||
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLocalName);
|
||||
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
list = NS_GetContentList(document, nameAtom, nameSpaceId, this).get();
|
||||
list = NS_GetContentList(this, nameAtom, nameSpaceId).get();
|
||||
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
|
@ -2396,20 +2410,17 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
|||
// really need to stop running them while we're in the middle of modifying
|
||||
// the DOM....
|
||||
|
||||
nsINode* container = aParent ? NS_STATIC_CAST(nsINode*, aParent) :
|
||||
NS_STATIC_CAST(nsINode*, aDocument);
|
||||
if (aKid->GetNodeParent() == container) {
|
||||
if (aNotify && aDocument) {
|
||||
// Note that we always want to call ContentInserted when things are added
|
||||
// as kids to documents
|
||||
if (aParent && isAppend) {
|
||||
aDocument->ContentAppended(aParent, aIndex);
|
||||
} else {
|
||||
aDocument->ContentInserted(aParent, aKid, aIndex);
|
||||
}
|
||||
nsINode* container = NODE_FROM(aParent, aDocument);
|
||||
if (aNotify && aKid->GetNodeParent() == container) {
|
||||
// Note that we always want to call ContentInserted when things are added
|
||||
// as kids to documents
|
||||
if (aParent && isAppend) {
|
||||
nsNodeUtils::ContentAppended(aParent, aIndex);
|
||||
} else {
|
||||
nsNodeUtils::ContentInserted(container, aKid, aIndex);
|
||||
}
|
||||
if (aNotify &&
|
||||
nsContentUtils::HasMutationListeners(container,
|
||||
|
||||
if (nsContentUtils::HasMutationListeners(container,
|
||||
NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
|
||||
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEINSERTED);
|
||||
mutation.mRelatedNode = do_QueryInterface(container);
|
||||
|
@ -2458,10 +2469,7 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
|
|||
|
||||
nsMutationGuard::DidMutate();
|
||||
|
||||
nsINode* container = aParent;
|
||||
if (!container) {
|
||||
container = aDocument;
|
||||
}
|
||||
nsINode* container = NODE_FROM(aParent, aDocument);
|
||||
|
||||
NS_PRECONDITION(aKid && aKid->GetParent() == aParent &&
|
||||
aKid == container->GetChildAt(aIndex) &&
|
||||
|
@ -2494,8 +2502,8 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
|
|||
|
||||
aChildArray.RemoveChildAt(aIndex);
|
||||
|
||||
if (aNotify && aDocument) {
|
||||
aDocument->ContentRemoved(aParent, aKid, aIndex);
|
||||
if (aNotify) {
|
||||
nsNodeUtils::ContentRemoved(container, aKid, aIndex);
|
||||
}
|
||||
|
||||
aKid->UnbindFromTree();
|
||||
|
@ -2819,10 +2827,7 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
|
|||
nsresult res = NS_OK;
|
||||
PRInt32 insPos;
|
||||
|
||||
nsINode* container = aParent;
|
||||
if (!container) {
|
||||
container = aDocument;
|
||||
}
|
||||
nsINode* container = NODE_FROM(aParent, aDocument);
|
||||
|
||||
// Figure out which index to insert at
|
||||
if (aRefChild) {
|
||||
|
@ -3060,10 +3065,7 @@ nsGenericElement::doRemoveChild(nsIDOMNode* aOldChild, nsIContent* aParent,
|
|||
*aReturn = nsnull;
|
||||
NS_ENSURE_TRUE(aOldChild, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsINode* container = aParent;
|
||||
if (!container) {
|
||||
container = aDocument;
|
||||
}
|
||||
nsINode* container = NODE_FROM(aParent, aDocument);
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aOldChild);
|
||||
// fix children to be a passed argument
|
||||
|
@ -3424,8 +3426,8 @@ nsGenericElement::SetAttrAndNotify(PRInt32 aNamespaceID,
|
|||
nsEventDispatcher::Dispatch(this, nsnull, &mutation);
|
||||
}
|
||||
|
||||
if (document && aNotify) {
|
||||
document->AttributeChanged(this, aNamespaceID, aName, modType);
|
||||
if (aNotify) {
|
||||
nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, modType);
|
||||
}
|
||||
|
||||
if (aNamespaceID == kNameSpaceID_XMLEvents &&
|
||||
|
@ -3637,11 +3639,11 @@ nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
nsXBLBinding *binding = document->BindingManager()->GetBinding(this);
|
||||
if (binding)
|
||||
binding->AttributeChanged(aName, aNameSpaceID, PR_TRUE, aNotify);
|
||||
}
|
||||
|
||||
if (aNotify) {
|
||||
document->AttributeChanged(this, aNameSpaceID, aName,
|
||||
nsIDOMMutationEvent::REMOVAL);
|
||||
}
|
||||
if (aNotify) {
|
||||
nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
|
||||
nsIDOMMutationEvent::REMOVAL);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -3785,6 +3787,12 @@ nsGenericElement::IndexOf(nsINode* aPossibleChild) const
|
|||
return mAttrsAndChildren.IndexOfChild(aPossibleChild);
|
||||
}
|
||||
|
||||
nsINode::nsSlots*
|
||||
nsGenericElement::CreateSlots()
|
||||
{
|
||||
return new nsDOMSlots(mFlagsOrSlots);
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericElement::GetContentsAsText(nsAString& aText)
|
||||
{
|
||||
|
|
|
@ -874,9 +874,7 @@ protected:
|
|||
{
|
||||
public:
|
||||
nsDOMSlots(PtrBits aFlags);
|
||||
~nsDOMSlots();
|
||||
|
||||
PRBool IsEmpty();
|
||||
virtual ~nsDOMSlots();
|
||||
|
||||
/**
|
||||
* An object implementing nsIDOMNodeList for this content (childNodes)
|
||||
|
@ -911,19 +909,12 @@ protected:
|
|||
};
|
||||
};
|
||||
|
||||
// Override from nsINode
|
||||
virtual nsINode::nsSlots* CreateSlots();
|
||||
|
||||
nsDOMSlots *GetDOMSlots()
|
||||
{
|
||||
if (!HasSlots()) {
|
||||
nsDOMSlots *slots = new nsDOMSlots(mFlagsOrSlots);
|
||||
|
||||
if (!slots) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
SetSlots(slots);
|
||||
}
|
||||
|
||||
return NS_STATIC_CAST(nsDOMSlots*, FlagsAsSlots());
|
||||
return NS_STATIC_CAST(nsDOMSlots*, GetSlots());
|
||||
}
|
||||
|
||||
nsDOMSlots *GetExistingDOMSlots() const
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonas Sicking <jonas@sicking.cc> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsNodeUtils.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIMutationObserver.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
#define IMPL_MUTATION_NOTIFICATION_FW(func_, content_, params_) \
|
||||
nsINode* node = content_; \
|
||||
nsINode* prev; \
|
||||
nsCOMArray<nsIMutationObserver> observers; \
|
||||
do { \
|
||||
nsINode::nsSlots* slots = node->GetExistingSlots(); \
|
||||
if (slots && !slots->mMutationObservers.IsEmpty()) { \
|
||||
/* No need to explicitly notify the first observer first \
|
||||
since that'll happen anyway. */ \
|
||||
nsTObserverArray<nsIMutationObserver>::ForwardIterator \
|
||||
iter_(slots->mMutationObservers); \
|
||||
nsCOMPtr<nsIMutationObserver> obs_; \
|
||||
while ((obs_ = iter_.GetNext())) { \
|
||||
obs_-> func_ params_; \
|
||||
} \
|
||||
} \
|
||||
prev = node; \
|
||||
node = node->GetNodeParent(); \
|
||||
\
|
||||
if (!node && prev->IsNodeOfType(nsINode::eXUL)) { \
|
||||
/* XUL elements can have the in-document flag set, but \
|
||||
still be in an orphaned subtree. In this case we \
|
||||
need to notify the document */ \
|
||||
node = NS_STATIC_CAST(nsIContent*, prev)->GetCurrentDoc(); \
|
||||
} \
|
||||
} while (node);
|
||||
|
||||
|
||||
|
||||
#define IMPL_MUTATION_NOTIFICATION_BW(func_, content_, params_) \
|
||||
nsINode* node = content_; \
|
||||
nsINode* prev; \
|
||||
nsCOMArray<nsIMutationObserver> observers; \
|
||||
do { \
|
||||
nsINode::nsSlots* slots = node->GetExistingSlots(); \
|
||||
if (slots && !slots->mMutationObservers.IsEmpty()) { \
|
||||
/* \
|
||||
* Notify the first observer first even if we're doing a \
|
||||
* reverse walk. This is since we want to notify the \
|
||||
* document first when |node| is a document. \
|
||||
* This may not actually be needed, but it's safer for now. \
|
||||
* This can be removed once we always walk forward \
|
||||
*/ \
|
||||
nsIMutationObserver* first = \
|
||||
slots->mMutationObservers.SafeObserverAt(0); \
|
||||
first-> func_ params_; \
|
||||
nsTObserverArray<nsIMutationObserver>::ReverseIterator \
|
||||
iter_(slots->mMutationObservers); \
|
||||
nsCOMPtr<nsIMutationObserver> obs_; \
|
||||
while ((obs_ = iter_.GetNext()) != first) { \
|
||||
obs_-> func_ params_; \
|
||||
} \
|
||||
} \
|
||||
prev = node; \
|
||||
node = node->GetNodeParent(); \
|
||||
\
|
||||
if (!node && prev->IsNodeOfType(nsINode::eXUL)) { \
|
||||
/* XUL elements can have the in-document flag set, but \
|
||||
still be in an orphaned subtree. In this case we \
|
||||
need to notify the document */ \
|
||||
node = NS_STATIC_CAST(nsIContent*, prev)->GetCurrentDoc(); \
|
||||
} \
|
||||
} while (node);
|
||||
|
||||
|
||||
void
|
||||
nsNodeUtils::CharacterDataChanged(nsIContent* aContent, PRBool aAppend)
|
||||
{
|
||||
nsIDocument* doc = aContent->GetOwnerDoc();
|
||||
IMPL_MUTATION_NOTIFICATION_BW(CharacterDataChanged, aContent,
|
||||
(doc, aContent, aAppend));
|
||||
}
|
||||
|
||||
void
|
||||
nsNodeUtils::AttributeChanged(nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType)
|
||||
{
|
||||
nsIDocument* doc = aContent->GetOwnerDoc();
|
||||
IMPL_MUTATION_NOTIFICATION_BW(AttributeChanged, aContent,
|
||||
(doc, aContent, aNameSpaceID, aAttribute,
|
||||
aModType));
|
||||
}
|
||||
|
||||
void
|
||||
nsNodeUtils::ContentAppended(nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer)
|
||||
{
|
||||
nsIDocument* document = aContainer->GetOwnerDoc();
|
||||
|
||||
// XXXdwh There is a hacky ordering dependency between the binding
|
||||
// manager and the frame constructor that forces us to walk the
|
||||
// observer list in a forward order
|
||||
// XXXldb So one should notify the other rather than both being
|
||||
// registered.
|
||||
|
||||
IMPL_MUTATION_NOTIFICATION_FW(ContentAppended, aContainer,
|
||||
(document, aContainer, aNewIndexInContainer));
|
||||
}
|
||||
|
||||
void
|
||||
nsNodeUtils::ContentInserted(nsINode* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
NS_PRECONDITION(aContainer->IsNodeOfType(nsINode::eCONTENT) ||
|
||||
aContainer->IsNodeOfType(nsINode::eDOCUMENT),
|
||||
"container must be an nsIContent or an nsIDocument");
|
||||
nsIContent* container;
|
||||
nsIDocument* document;
|
||||
if (aContainer->IsNodeOfType(nsINode::eCONTENT)) {
|
||||
container = NS_STATIC_CAST(nsIContent*, aContainer);
|
||||
document = aContainer->GetOwnerDoc();
|
||||
}
|
||||
else {
|
||||
container = nsnull;
|
||||
document = NS_STATIC_CAST(nsIDocument*, aContainer);
|
||||
}
|
||||
|
||||
// XXXdwh There is a hacky ordering dependency between the binding manager
|
||||
// and the frame constructor that forces us to walk the observer list
|
||||
// in a forward order
|
||||
// XXXldb So one should notify the other rather than both being
|
||||
// registered.
|
||||
|
||||
IMPL_MUTATION_NOTIFICATION_FW(ContentInserted, aContainer,
|
||||
(document, container, aChild, aIndexInContainer));
|
||||
}
|
||||
|
||||
void
|
||||
nsNodeUtils::ContentRemoved(nsINode* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
NS_PRECONDITION(aContainer->IsNodeOfType(nsINode::eCONTENT) ||
|
||||
aContainer->IsNodeOfType(nsINode::eDOCUMENT),
|
||||
"container must be an nsIContent or an nsIDocument");
|
||||
nsIContent* container;
|
||||
nsIDocument* document;
|
||||
if (aContainer->IsNodeOfType(nsINode::eCONTENT)) {
|
||||
container = NS_STATIC_CAST(nsIContent*, aContainer);
|
||||
document = aContainer->GetOwnerDoc();
|
||||
}
|
||||
else {
|
||||
container = nsnull;
|
||||
document = NS_STATIC_CAST(nsIDocument*, aContainer);
|
||||
}
|
||||
|
||||
// XXXdwh There is a hacky ordering dependency between the binding
|
||||
// manager and the frame constructor that forces us to walk the
|
||||
// observer list in a reverse order
|
||||
// XXXldb So one should notify the other rather than both being
|
||||
// registered.
|
||||
|
||||
|
||||
IMPL_MUTATION_NOTIFICATION_BW(ContentRemoved, aContainer,
|
||||
(document, container, aChild, aIndexInContainer));
|
||||
}
|
||||
|
||||
void
|
||||
nsNodeUtils::NodeWillBeDestroyed(nsINode* aNode)
|
||||
{
|
||||
nsINode::nsSlots* slots = aNode->GetExistingSlots();
|
||||
if (slots) {
|
||||
if (!slots->mMutationObservers.IsEmpty()) {
|
||||
nsTObserverArray<nsIMutationObserver>::ForwardIterator
|
||||
iter(slots->mMutationObservers);
|
||||
nsCOMPtr<nsIMutationObserver> obs;
|
||||
while ((obs = iter.GetNext())) {
|
||||
obs->NodeWillBeDestroyed(aNode);
|
||||
}
|
||||
}
|
||||
|
||||
PtrBits flags = slots->mFlags | NODE_DOESNT_HAVE_SLOTS;
|
||||
delete slots;
|
||||
aNode->mFlagsOrSlots = flags;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonas Sicking <jonas@sicking.cc> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsNodeUtils_h___
|
||||
#define nsNodeUtils_h___
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
class nsINode;
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
class nsIAtom;
|
||||
|
||||
class nsNodeUtils
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Send CharacterDataChanged notifications to nsIMutationObservers.
|
||||
* @param aContent Node whose data changed
|
||||
* @param aAppend True if data was only appended
|
||||
* @see nsIMutationObserver::CharacterDataChanged
|
||||
*/
|
||||
static void CharacterDataChanged(nsIContent* aContent, PRBool aAppend);
|
||||
|
||||
/**
|
||||
* Send AttributeChanged notifications to nsIMutationObservers.
|
||||
* @param aContent Node whose data changed
|
||||
* @param aNameSpaceID Namespace of changed attribute
|
||||
* @param aAttribute Local-name of changed attribute
|
||||
* @param aModType Type of change (add/change/removal)
|
||||
* @see nsIMutationObserver::AttributeChanged
|
||||
*/
|
||||
static void AttributeChanged(nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType);
|
||||
|
||||
/**
|
||||
* Send ContentAppended notifications to nsIMutationObservers
|
||||
* @param aContainer Node into which new child/children were added
|
||||
* @param aNewIndexInContainer Index of first new child
|
||||
* @see nsIMutationObserver::ContentAppended
|
||||
*/
|
||||
static void ContentAppended(nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer);
|
||||
|
||||
/**
|
||||
* Send ContentInserted notifications to nsIMutationObservers
|
||||
* @param aContainer Node into which new child was inserted
|
||||
* @param aChild Newly inserted child
|
||||
* @param aIndexInContainer Index of new child
|
||||
* @see nsIMutationObserver::ContentInserted
|
||||
*/
|
||||
static void ContentInserted(nsINode* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer);
|
||||
/**
|
||||
* Send ContentRemoved notifications to nsIMutationObservers
|
||||
* @param aContainer Node from which child was removed
|
||||
* @param aChild Removed child
|
||||
* @param aIndexInContainer Index of removed child
|
||||
* @see nsIMutationObserver::ContentRemoved
|
||||
*/
|
||||
static void ContentRemoved(nsINode* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer);
|
||||
|
||||
/**
|
||||
* Call this before starting to tear down a node. The node should still
|
||||
* have children and attributes accessible.
|
||||
* The function will notify nsIMutationObservers as well as delete the
|
||||
* slots structure.
|
||||
* @param aNode Node that is being destroyed
|
||||
* @see nsIMutationObserver::NodeWillBeDestroyed
|
||||
*/
|
||||
static void NodeWillBeDestroyed(nsINode* aNode);
|
||||
};
|
||||
|
||||
#endif // nsNodeUtils_h___
|
|
@ -0,0 +1,48 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is nsStubMutationObserver.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonas Sicking <jonas@sicking.cc> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* nsStubMutationObserver is an implementation of the nsIMutationObserver
|
||||
* interface (except for the methods on nsISupports) that is intended to be
|
||||
* used as a base class within the content/layout library. All methods do
|
||||
* nothing.
|
||||
*/
|
||||
|
||||
#include "nsStubMutationObserver.h"
|
||||
|
||||
NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(nsStubMutationObserver)
|
||||
NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(nsStubMutationObserver)
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is nsStubMutationObserver.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@dbaron.org> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* nsStubMutationObserver is an implementation of the nsIMutationObserver
|
||||
* interface (except for the methods on nsISupports) that is intended to be
|
||||
* used as a base class within the content/layout library. All methods do
|
||||
* nothing.
|
||||
*/
|
||||
|
||||
#ifndef nsStubMutationObserver_h_
|
||||
#define nsStubMutationObserver_h_
|
||||
|
||||
#include "nsIMutationObserver.h"
|
||||
|
||||
/**
|
||||
* There are two advantages to inheriting from nsStubMutationObserver
|
||||
* rather than directly from nsIMutationObserver:
|
||||
* 1. smaller compiled code size (since there's no need for the code
|
||||
* for the empty virtual function implementations for every
|
||||
* nsIMutationObserver implementation)
|
||||
* 2. the performance of document's loop over observers benefits from
|
||||
* the fact that more of the functions called are the same (which
|
||||
* can reduce instruction cache misses and perhaps improve branch
|
||||
* prediction)
|
||||
*/
|
||||
class nsStubMutationObserver : public nsIMutationObserver {
|
||||
NS_DECL_NSIMUTATIONOBSERVER
|
||||
};
|
||||
|
||||
#endif /* !defined(nsStubMutationObserver_h_) */
|
|
@ -35,7 +35,9 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsTArray.h"
|
||||
#ifndef nsTObserverArray_h___
|
||||
#define nsTObserverArray_h___
|
||||
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
class nsTObserverArray_base {
|
||||
|
@ -122,6 +124,9 @@ class nsTObserverArray : public nsTObserverArray_base {
|
|||
* @param aObserver Observer to add
|
||||
*/
|
||||
PRBool PrependObserver(T* aObserver) {
|
||||
NS_PRECONDITION(!Contains(aObserver),
|
||||
"Don't prepend if the observer is already in the list");
|
||||
|
||||
PRBool res = mObservers.InsertElementAt(aObserver, 0);
|
||||
if (res) {
|
||||
AdjustIterators(0, 1);
|
||||
|
@ -130,12 +135,13 @@ class nsTObserverArray : public nsTObserverArray_base {
|
|||
}
|
||||
|
||||
/**
|
||||
* Adds an observer to the end of the array
|
||||
* Adds an observer to the end of the array unless it already exists in
|
||||
* the array.
|
||||
* @param aObserver Observer to add
|
||||
* @return True on success, false otherwise
|
||||
*/
|
||||
PRBool AppendObserver(T* aObserver) {
|
||||
return mObservers.AppendElement(aObserver);
|
||||
return Contains(aObserver) || mObservers.AppendElement(aObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,6 +165,14 @@ class nsTObserverArray : public nsTObserverArray_base {
|
|||
return mObservers.IndexOf(aObserver) >= 0;
|
||||
}
|
||||
|
||||
PRBool IsEmpty() const {
|
||||
return mObservers.Count() == 0;
|
||||
}
|
||||
|
||||
T* SafeObserverAt(PRInt32 aIndex) {
|
||||
return NS_STATIC_CAST(T*, mObservers.SafeElementAt(aIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterators
|
||||
*/
|
||||
|
@ -206,3 +220,5 @@ class nsTObserverArray : public nsTObserverArray_base {
|
|||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif // nsTObserverArray_h___
|
||||
|
|
|
@ -285,7 +285,7 @@ nsXMLEventsManager::~nsXMLEventsManager()
|
|||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXMLEventsManager, nsIDocumentObserver)
|
||||
NS_IMPL_ISUPPORTS2(nsXMLEventsManager, nsIDocumentObserver, nsIMutationObserver)
|
||||
|
||||
void nsXMLEventsManager::AddXMLEventsContent(nsIContent * aContent)
|
||||
{
|
||||
|
@ -332,11 +332,11 @@ nsXMLEventsManager::BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType
|
|||
void
|
||||
nsXMLEventsManager::EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) {}
|
||||
void
|
||||
nsXMLEventsManager::DocumentWillBeDestroyed(nsIDocument* aDocument){
|
||||
nsXMLEventsManager::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
mIncomplete.Clear();
|
||||
mListeners.Enumerate(EnumAndUnregisterListener, this);
|
||||
mListeners.Clear();
|
||||
aDocument->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -51,7 +51,6 @@ class nsHTMLMapElement : public nsGenericHTMLElement,
|
|||
{
|
||||
public:
|
||||
nsHTMLMapElement(nsINodeInfo *aNodeInfo);
|
||||
virtual ~nsHTMLMapElement();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -86,14 +85,6 @@ nsHTMLMapElement::nsHTMLMapElement(nsINodeInfo *aNodeInfo)
|
|||
{
|
||||
}
|
||||
|
||||
nsHTMLMapElement::~nsHTMLMapElement()
|
||||
{
|
||||
if (mAreas) {
|
||||
mAreas->RootDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsHTMLMapElement, nsGenericElement)
|
||||
NS_IMPL_RELEASE_INHERITED(nsHTMLMapElement, nsGenericElement)
|
||||
|
||||
|
@ -146,10 +137,9 @@ nsHTMLMapElement::GetAreas(nsIDOMHTMLCollection** aAreas)
|
|||
|
||||
if (!mAreas) {
|
||||
// Not using NS_GetContentList because this should not be cached
|
||||
mAreas = new nsContentList(GetDocument(),
|
||||
mAreas = new nsContentList(this,
|
||||
nsHTMLAtoms::area,
|
||||
mNodeInfo->NamespaceID(),
|
||||
this,
|
||||
PR_FALSE);
|
||||
|
||||
if (!mAreas) {
|
||||
|
|
|
@ -140,10 +140,9 @@ TableRowsCollection::~TableRowsCollection()
|
|||
nsresult
|
||||
TableRowsCollection::Init()
|
||||
{
|
||||
mOrphanRows = new nsContentList(mParent->GetDocument(),
|
||||
mOrphanRows = new nsContentList(mParent,
|
||||
nsHTMLAtoms::tr,
|
||||
mParent->NodeInfo()->NamespaceID(),
|
||||
mParent,
|
||||
PR_FALSE);
|
||||
return mOrphanRows ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -326,10 +325,6 @@ nsHTMLTableElement::nsHTMLTableElement(nsINodeInfo *aNodeInfo)
|
|||
|
||||
nsHTMLTableElement::~nsHTMLTableElement()
|
||||
{
|
||||
if (mTBodies) {
|
||||
mTBodies->RootDestroyed();
|
||||
}
|
||||
|
||||
if (mRows) {
|
||||
mRows->ParentDestroyed();
|
||||
}
|
||||
|
@ -519,10 +514,9 @@ nsHTMLTableElement::GetTBodies(nsIDOMHTMLCollection** aValue)
|
|||
{
|
||||
if (!mTBodies) {
|
||||
// Not using NS_GetContentList because this should not be cached
|
||||
mTBodies = new nsContentList(GetDocument(),
|
||||
mTBodies = new nsContentList(this,
|
||||
nsHTMLAtoms::tbody,
|
||||
mNodeInfo->NamespaceID(),
|
||||
this,
|
||||
PR_FALSE);
|
||||
|
||||
NS_ENSURE_TRUE(mTBodies, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
|
|
@ -59,7 +59,6 @@ class nsHTMLTableRowElement : public nsGenericHTMLElement,
|
|||
{
|
||||
public:
|
||||
nsHTMLTableRowElement(nsINodeInfo *aNodeInfo);
|
||||
virtual ~nsHTMLTableRowElement();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -123,14 +122,6 @@ nsHTMLTableRowElement::nsHTMLTableRowElement(nsINodeInfo *aNodeInfo)
|
|||
{
|
||||
}
|
||||
|
||||
nsHTMLTableRowElement::~nsHTMLTableRowElement()
|
||||
{
|
||||
if (mCells) {
|
||||
mCells->RootDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsHTMLTableRowElement, nsGenericElement)
|
||||
NS_IMPL_RELEASE_INHERITED(nsHTMLTableRowElement, nsGenericElement)
|
||||
|
||||
|
@ -270,10 +261,9 @@ NS_IMETHODIMP
|
|||
nsHTMLTableRowElement::GetCells(nsIDOMHTMLCollection** aValue)
|
||||
{
|
||||
if (!mCells) {
|
||||
mCells = new nsContentList(GetDocument(),
|
||||
mCells = new nsContentList(this,
|
||||
IsCell,
|
||||
EmptyString(),
|
||||
this,
|
||||
PR_FALSE,
|
||||
nsnull,
|
||||
kNameSpaceID_None,
|
||||
|
|
|
@ -54,7 +54,6 @@ class nsHTMLTableSectionElement : public nsGenericHTMLElement,
|
|||
{
|
||||
public:
|
||||
nsHTMLTableSectionElement(nsINodeInfo *aNodeInfo);
|
||||
virtual ~nsHTMLTableSectionElement();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -91,14 +90,6 @@ nsHTMLTableSectionElement::nsHTMLTableSectionElement(nsINodeInfo *aNodeInfo)
|
|||
{
|
||||
}
|
||||
|
||||
nsHTMLTableSectionElement::~nsHTMLTableSectionElement()
|
||||
{
|
||||
if (mRows) {
|
||||
mRows->RootDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsHTMLTableSectionElement, nsGenericElement)
|
||||
NS_IMPL_RELEASE_INHERITED(nsHTMLTableSectionElement, nsGenericElement)
|
||||
|
||||
|
@ -126,10 +117,9 @@ nsHTMLTableSectionElement::GetRows(nsIDOMHTMLCollection** aValue)
|
|||
*aValue = nsnull;
|
||||
|
||||
if (!mRows) {
|
||||
mRows = new nsContentList(GetDocument(),
|
||||
mRows = new nsContentList(this,
|
||||
nsHTMLAtoms::tr,
|
||||
mNodeInfo->NamespaceID(),
|
||||
this,
|
||||
PR_FALSE);
|
||||
|
||||
NS_ENSURE_TRUE(mRows, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
|
|
@ -64,6 +64,8 @@
|
|||
#include "prtime.h"
|
||||
#include "prlog.h"
|
||||
#include "nsInt64.h"
|
||||
#include "nsNodeUtils.h"
|
||||
#include "nsIContent.h"
|
||||
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsITextContent.h"
|
||||
|
@ -1852,20 +1854,22 @@ HTMLContentSink::~HTMLContentSink()
|
|||
}
|
||||
|
||||
#if DEBUG
|
||||
NS_IMPL_ISUPPORTS_INHERITED6(HTMLContentSink,
|
||||
nsContentSink,
|
||||
nsIContentSink,
|
||||
nsIHTMLContentSink,
|
||||
nsITimerCallback,
|
||||
nsIDocumentObserver,
|
||||
nsIMutationObserver,
|
||||
nsIDebugDumpContent)
|
||||
#else
|
||||
NS_IMPL_ISUPPORTS_INHERITED5(HTMLContentSink,
|
||||
nsContentSink,
|
||||
nsIContentSink,
|
||||
nsIHTMLContentSink,
|
||||
nsITimerCallback,
|
||||
nsIDocumentObserver,
|
||||
nsIDebugDumpContent)
|
||||
#else
|
||||
NS_IMPL_ISUPPORTS_INHERITED4(HTMLContentSink,
|
||||
nsContentSink,
|
||||
nsIContentSink,
|
||||
nsIHTMLContentSink,
|
||||
nsITimerCallback,
|
||||
nsIDocumentObserver)
|
||||
nsIMutationObserver)
|
||||
#endif
|
||||
|
||||
static PRBool
|
||||
|
@ -3615,7 +3619,7 @@ HTMLContentSink::NotifyAppend(nsIContent* aContainer, PRUint32 aStartIndex)
|
|||
MOZ_TIMER_SAVE(mWatch)
|
||||
MOZ_TIMER_STOP(mWatch);
|
||||
|
||||
mDocument->ContentAppended(aContainer, aStartIndex);
|
||||
nsNodeUtils::ContentAppended(aContainer, aStartIndex);
|
||||
mLastNotificationTime = PR_Now();
|
||||
|
||||
MOZ_TIMER_DEBUGLOG(("Restore: nsHTMLContentSink::NotifyAppend()\n"));
|
||||
|
@ -3641,7 +3645,8 @@ HTMLContentSink::NotifyInsert(nsIContent* aContent,
|
|||
MOZ_TIMER_SAVE(mWatch)
|
||||
MOZ_TIMER_STOP(mWatch);
|
||||
|
||||
mDocument->ContentInserted(aContent, aChildContent, aIndexInContainer);
|
||||
nsNodeUtils::ContentInserted(NODE_FROM(aContent, mDocument),
|
||||
aChildContent, aIndexInContainer);
|
||||
mLastNotificationTime = PR_Now();
|
||||
|
||||
MOZ_TIMER_DEBUGLOG(("Restore: nsHTMLContentSink::NotifyInsert()\n"));
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsAttrName.h"
|
||||
#include "nsNodeUtils.h"
|
||||
|
||||
#include "nsNetCID.h"
|
||||
#include "nsIIOService.h"
|
||||
|
@ -1196,42 +1197,40 @@ nsHTMLDocument::SetCompatibilityMode(nsCompatibility aMode)
|
|||
}
|
||||
|
||||
void
|
||||
nsHTMLDocument::ContentAppended(nsIContent* aContainer,
|
||||
nsHTMLDocument::ContentAppended(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aContainer, "Null container!");
|
||||
NS_ASSERTION(aDocument == this, "unexpected doc");
|
||||
|
||||
// Register new content. That is the content numbered from
|
||||
// aNewIndexInContainer and upwards.
|
||||
PRUint32 count = aContainer->GetChildCount();
|
||||
|
||||
for (PRUint32 i = aNewIndexInContainer; i < count; ++i) {
|
||||
RegisterNamedItems(aContainer->GetChildAt(i));
|
||||
}
|
||||
|
||||
nsDocument::ContentAppended(aContainer, aNewIndexInContainer);
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLDocument::ContentInserted(nsIContent* aContainer, nsIContent* aContent,
|
||||
nsHTMLDocument::ContentInserted(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aContent,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
NS_ASSERTION(aDocument == this, "unexpected doc");
|
||||
|
||||
NS_ABORT_IF_FALSE(aContent, "Null content!");
|
||||
|
||||
nsresult rv = RegisterNamedItems(aContent);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsDocument::ContentInserted(aContainer, aContent, aIndexInContainer);
|
||||
RegisterNamedItems(aContent);
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLDocument::ContentRemoved(nsIContent* aContainer, nsIContent* aContent,
|
||||
nsHTMLDocument::ContentRemoved(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aContent, "Null content!");
|
||||
NS_ASSERTION(aDocument == this, "unexpected doc");
|
||||
|
||||
NS_ABORT_IF_FALSE(aChild, "Null content!");
|
||||
|
||||
if (aContainer == mRootContent) {
|
||||
// Reset mBodyContent in case we got a new body.
|
||||
|
@ -1239,13 +1238,7 @@ nsHTMLDocument::ContentRemoved(nsIContent* aContainer, nsIContent* aContent,
|
|||
mBodyContent = nsnull;
|
||||
}
|
||||
|
||||
nsresult rv = UnregisterNamedItems(aContent);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsDocument::ContentRemoved(aContainer, aContent, aIndexInContainer);
|
||||
UnregisterNamedItems(aChild);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1278,9 +1271,12 @@ nsHTMLDocument::AttributeWillChange(nsIContent* aContent, PRInt32 aNameSpaceID,
|
|||
}
|
||||
|
||||
void
|
||||
nsHTMLDocument::AttributeChanged(nsIContent* aContent, PRInt32 aNameSpaceID,
|
||||
nsHTMLDocument::AttributeChanged(nsIDocument* aDocument,
|
||||
nsIContent* aContent, PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute, PRInt32 aModType)
|
||||
{
|
||||
NS_ASSERTION(aDocument == this, "unexpected doc");
|
||||
|
||||
NS_ABORT_IF_FALSE(aContent, "Null content!");
|
||||
NS_PRECONDITION(aAttribute, "Must have an attribute that's changing!");
|
||||
|
||||
|
@ -1289,25 +1285,15 @@ nsHTMLDocument::AttributeChanged(nsIContent* aContent, PRInt32 aNameSpaceID,
|
|||
|
||||
nsIAtom* name = IsNamedItem(aContent);
|
||||
if (name) {
|
||||
nsresult rv = UpdateNameTableEntry(name, aContent);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
UpdateNameTableEntry(name, aContent);
|
||||
}
|
||||
} else if (aAttribute == aContent->GetIDAttributeName() &&
|
||||
aNameSpaceID == kNameSpaceID_None) {
|
||||
nsIAtom* id = aContent->GetID();
|
||||
if (id) {
|
||||
nsresult rv = UpdateIdTableEntry(id, aContent);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
UpdateIdTableEntry(id, aContent);
|
||||
}
|
||||
}
|
||||
|
||||
nsDocument::AttributeChanged(aContent, aNameSpaceID, aAttribute, aModType);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2078,7 +2064,7 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
|
|||
|
||||
if (root) {
|
||||
// Tear down the frames for the root element.
|
||||
ContentRemoved(nsnull, root, 0);
|
||||
nsNodeUtils::ContentRemoved(this, root, 0);
|
||||
|
||||
// Put the root element back into the document, we don't notify
|
||||
// the document about this insertion since the sink will do that
|
||||
|
|
|
@ -124,18 +124,6 @@ public:
|
|||
|
||||
virtual NS_HIDDEN_(nsContentList*) GetFormControls();
|
||||
|
||||
virtual void ContentAppended(nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer);
|
||||
virtual void ContentInserted(nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer);
|
||||
virtual void ContentRemoved(nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer);
|
||||
virtual void AttributeChanged(nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType);
|
||||
virtual void AttributeWillChange(nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute);
|
||||
|
@ -144,6 +132,23 @@ public:
|
|||
|
||||
virtual PRBool IsCaseSensitive();
|
||||
|
||||
// nsIMutationObserver
|
||||
virtual void ContentAppended(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer);
|
||||
virtual void ContentInserted(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer);
|
||||
virtual void ContentRemoved(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer);
|
||||
virtual void AttributeChanged(nsIDocument* aDocument,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType);
|
||||
// nsIDOMDocument interface
|
||||
NS_DECL_NSIDOMDOCUMENT
|
||||
|
||||
|
|
|
@ -289,7 +289,8 @@ SetOrRemoveObject(PLDHashTable& table, nsISupports* aKey, nsISupports* aValue)
|
|||
// Static member variable initialization
|
||||
|
||||
// Implement our nsISupports methods
|
||||
NS_IMPL_ISUPPORTS3(nsBindingManager, nsIBindingManager, nsIStyleRuleSupplier, nsIDocumentObserver)
|
||||
NS_IMPL_ISUPPORTS4(nsBindingManager, nsIBindingManager, nsIStyleRuleSupplier,
|
||||
nsIDocumentObserver, nsIMutationObserver)
|
||||
|
||||
// Constructors/Destructors
|
||||
nsBindingManager::nsBindingManager(void)
|
||||
|
|
|
@ -97,6 +97,7 @@
|
|||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsContentErrors.h"
|
||||
#include "nsIDOMProcessingInstruction.h"
|
||||
#include "nsNodeUtils.h"
|
||||
|
||||
#ifdef MOZ_SVG
|
||||
#include "nsSVGAtoms.h"
|
||||
|
@ -315,10 +316,8 @@ nsXMLContentSink::DidBuildModel()
|
|||
"mDocElement not in doc?");
|
||||
|
||||
mozAutoDocUpdate docUpdate(mDocument, UPDATE_CONTENT_MODEL, PR_TRUE);
|
||||
mDocument->ContentInserted(nsnull, mDocElement,
|
||||
// XXXbz is this last arg relevant if
|
||||
// the container is null?
|
||||
mDocument->IndexOf(mDocElement));
|
||||
nsNodeUtils::ContentInserted(mDocument, mDocElement,
|
||||
mDocument->IndexOf(mDocElement));
|
||||
}
|
||||
|
||||
// Check if we want to prettyprint
|
||||
|
@ -405,10 +404,8 @@ nsXMLContentSink::OnTransformDone(nsresult aResult,
|
|||
NS_ASSERTION(mDocument->IndexOf(rootContent) != -1,
|
||||
"rootContent not in doc?");
|
||||
mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
|
||||
mDocument->ContentInserted(nsnull, rootContent,
|
||||
// XXXbz is this last arg relevant if
|
||||
// the container is null?
|
||||
mDocument->IndexOf(rootContent));
|
||||
nsNodeUtils::ContentInserted(mDocument, rootContent,
|
||||
mDocument->IndexOf(rootContent));
|
||||
mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,8 +55,9 @@
|
|||
#include "nsIContent.h"
|
||||
#include "nsIDOMDocumentFragment.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXMLPrettyPrinter,
|
||||
nsIDocumentObserver)
|
||||
NS_IMPL_ISUPPORTS2(nsXMLPrettyPrinter,
|
||||
nsIDocumentObserver,
|
||||
nsIMutationObserver)
|
||||
|
||||
nsXMLPrettyPrinter::nsXMLPrettyPrinter() : mDocument(nsnull),
|
||||
mUpdateDepth(0),
|
||||
|
@ -267,7 +268,7 @@ nsXMLPrettyPrinter::ContentRemoved(nsIDocument* aDocument,
|
|||
}
|
||||
|
||||
void
|
||||
nsXMLPrettyPrinter::DocumentWillBeDestroyed(nsIDocument* aDocument)
|
||||
nsXMLPrettyPrinter::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
mDocument = nsnull;
|
||||
NS_RELEASE_THIS();
|
||||
|
|
|
@ -65,7 +65,7 @@ public:
|
|||
PRInt32 aIndexInContainer);
|
||||
virtual void ContentRemoved(nsIDocument* aDocument, nsIContent* aContainer,
|
||||
nsIContent* aChild, PRInt32 aIndexInContainer);
|
||||
virtual void DocumentWillBeDestroyed(nsIDocument* aDocument);
|
||||
virtual void NodeWillBeDestroyed(const nsINode* aNode);
|
||||
|
||||
/**
|
||||
* This will prettyprint the document if the document is loaded in a
|
||||
|
|
|
@ -45,6 +45,7 @@ class nsIDOMNode;
|
|||
class nsILoadGroup;
|
||||
class nsIURI;
|
||||
class nsIPrincipal;
|
||||
class nsString;
|
||||
|
||||
#define NS_ITRANSFORMOBSERVER_IID \
|
||||
{0xcce88481, 0x6eb3, 0x11d6, \
|
||||
|
|
|
@ -57,7 +57,7 @@ nsXPathResult::nsXPathResult() : mDocument(nsnull),
|
|||
nsXPathResult::~nsXPathResult()
|
||||
{
|
||||
if (mDocument) {
|
||||
mDocument->RemoveObserver(this);
|
||||
mDocument->RemoveMutationObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ NS_IMPL_ADDREF(nsXPathResult)
|
|||
NS_IMPL_RELEASE(nsXPathResult)
|
||||
NS_INTERFACE_MAP_BEGIN(nsXPathResult)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMXPathResult)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXPathResult)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMXPathResult)
|
||||
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XPathResult)
|
||||
|
@ -199,10 +199,13 @@ nsXPathResult::SnapshotItem(PRUint32 aIndex, nsIDOMNode **aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(nsXPathResult)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsXPathResult)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsXPathResult)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsXPathResult)
|
||||
void
|
||||
nsXPathResult::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
// Set to null to avoid unregistring unnecessarily
|
||||
mDocument = nsnull;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void
|
||||
nsXPathResult::CharacterDataChanged(nsIDocument* aDocument,
|
||||
|
@ -259,7 +262,7 @@ nsXPathResult::SetExprResult(txAExprResult* aExprResult, PRUint16 aResultType)
|
|||
}
|
||||
|
||||
if (mDocument) {
|
||||
mDocument->RemoveObserver(this);
|
||||
mDocument->RemoveMutationObserver(this);
|
||||
mDocument = nsnull;
|
||||
}
|
||||
|
||||
|
@ -291,7 +294,7 @@ nsXPathResult::SetExprResult(txAExprResult* aExprResult, PRUint16 aResultType)
|
|||
|
||||
NS_ASSERTION(mDocument, "We need a document!");
|
||||
if (mDocument) {
|
||||
mDocument->AddObserver(this);
|
||||
mDocument->AddMutationObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,7 +305,7 @@ void
|
|||
nsXPathResult::Invalidate()
|
||||
{
|
||||
if (mDocument) {
|
||||
mDocument->RemoveObserver(this);
|
||||
mDocument->RemoveMutationObserver(this);
|
||||
mDocument = nsnull;
|
||||
}
|
||||
mInvalidIteratorState = PR_TRUE;
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "txExprResult.h"
|
||||
#include "nsIDOMXPathResult.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIMutationObserver.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
|
@ -90,7 +90,7 @@ private:
|
|||
* A class for evaluating an XPath expression string
|
||||
*/
|
||||
class nsXPathResult : public nsIDOMXPathResult,
|
||||
public nsIDocumentObserver,
|
||||
public nsIMutationObserver,
|
||||
public nsIXPathResult
|
||||
{
|
||||
public:
|
||||
|
@ -103,8 +103,8 @@ public:
|
|||
// nsIDOMXPathResult interface
|
||||
NS_DECL_NSIDOMXPATHRESULT
|
||||
|
||||
// nsIDocumentObserver interface
|
||||
NS_DECL_NSIDOCUMENTOBSERVER
|
||||
// nsIMutationObserver interface
|
||||
NS_DECL_NSIMUTATIONOBSERVER
|
||||
|
||||
// nsIXPathResult interface
|
||||
nsresult SetExprResult(txAExprResult *aExprResult, PRUint16 aResultType);
|
||||
|
|
|
@ -301,7 +301,7 @@ NS_INTERFACE_MAP_BEGIN(txMozillaXSLTProcessor)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIXSLTProcessor)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXSLTProcessorObsolete)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocumentTransformer)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXSLTProcessor)
|
||||
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XSLTProcessor)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
@ -316,7 +316,7 @@ txMozillaXSLTProcessor::txMozillaXSLTProcessor() : mStylesheetDocument(nsnull),
|
|||
txMozillaXSLTProcessor::~txMozillaXSLTProcessor()
|
||||
{
|
||||
if (mStylesheetDocument) {
|
||||
mStylesheetDocument->RemoveObserver(this);
|
||||
mStylesheetDocument->RemoveMutationObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -612,7 +612,7 @@ txMozillaXSLTProcessor::ImportStylesheet(nsIDOMNode *aStyle)
|
|||
mStylesheetDocument = styleDoc;
|
||||
}
|
||||
|
||||
mStylesheetDocument->AddObserver(this);
|
||||
mStylesheetDocument->AddMutationObserver(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -973,7 +973,7 @@ NS_IMETHODIMP
|
|||
txMozillaXSLTProcessor::Reset()
|
||||
{
|
||||
if (mStylesheetDocument) {
|
||||
mStylesheetDocument->RemoveObserver(this);
|
||||
mStylesheetDocument->RemoveMutationObserver(this);
|
||||
}
|
||||
mStylesheet = nsnull;
|
||||
mStylesheetDocument = nsnull;
|
||||
|
@ -1149,24 +1149,8 @@ txMozillaXSLTProcessor::ensureStylesheet()
|
|||
return TX_CompileStylesheet(style, getter_AddRefs(mStylesheet));
|
||||
}
|
||||
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(txMozillaXSLTProcessor)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(txMozillaXSLTProcessor)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(txMozillaXSLTProcessor)
|
||||
|
||||
void
|
||||
txMozillaXSLTProcessor::BeginUpdate(nsIDocument* aDocument,
|
||||
nsUpdateType aUpdateType)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
txMozillaXSLTProcessor::EndUpdate(nsIDocument* aDocument,
|
||||
nsUpdateType aUpdateType)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
txMozillaXSLTProcessor::DocumentWillBeDestroyed(nsIDocument* aDocument)
|
||||
txMozillaXSLTProcessor::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
if (NS_FAILED(mCompileResult)) {
|
||||
return;
|
||||
|
@ -1175,11 +1159,6 @@ txMozillaXSLTProcessor::DocumentWillBeDestroyed(nsIDocument* aDocument)
|
|||
mCompileResult = ensureStylesheet();
|
||||
mStylesheetDocument = nsnull;
|
||||
mEmbeddedStylesheetRoot = nsnull;
|
||||
|
||||
// This might not be necessary, but just in case some element ends up
|
||||
// causing a notification as the document goes away we don't want to
|
||||
// invalidate the stylesheet.
|
||||
aDocument->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#define TRANSFRMX_TXMOZILLAXSLTPROCESSOR_H
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIMutationObserver.h"
|
||||
#include "nsIDocumentTransformer.h"
|
||||
#include "nsIXSLTProcessor.h"
|
||||
#include "nsIXSLTProcessorObsolete.h"
|
||||
|
@ -69,7 +69,7 @@ class txResultRecycler;
|
|||
class txMozillaXSLTProcessor : public nsIXSLTProcessor,
|
||||
public nsIXSLTProcessorObsolete,
|
||||
public nsIDocumentTransformer,
|
||||
public nsIDocumentObserver
|
||||
public nsIMutationObserver
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
@ -105,8 +105,8 @@ public:
|
|||
const nsString& aValue,
|
||||
nsIDOMNode* aContext);
|
||||
|
||||
// nsIDocumentObserver interface
|
||||
NS_DECL_NSIDOCUMENTOBSERVER
|
||||
// nsIMutationObserver interface
|
||||
NS_DECL_NSIMUTATIONOBSERVER
|
||||
|
||||
nsresult setStylesheet(txStylesheet* aStylesheet);
|
||||
void reportError(nsresult aResult, const PRUnichar *aErrorText,
|
||||
|
|
|
@ -137,6 +137,7 @@
|
|||
#include "nsHTMLAtoms.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "nsNodeUtils.h"
|
||||
|
||||
#include "prlog.h"
|
||||
#include "rdf.h"
|
||||
|
@ -499,10 +500,9 @@ nsXULElement::GetElementsByAttribute(const nsAString& aAttribute,
|
|||
NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsContentList *list =
|
||||
new nsContentList(GetDocument(),
|
||||
new nsContentList(this,
|
||||
nsXULDocument::MatchAttribute,
|
||||
aValue,
|
||||
this,
|
||||
PR_TRUE,
|
||||
attrAtom,
|
||||
kNameSpaceID_Unknown);
|
||||
|
@ -1472,10 +1472,11 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
|
|||
if (binding)
|
||||
binding->AttributeChanged(aName, aNameSpaceID, PR_TRUE, aNotify);
|
||||
|
||||
if (aNotify) {
|
||||
doc->AttributeChanged(this, aNameSpaceID, aName,
|
||||
nsIDOMMutationEvent::REMOVAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (aNotify) {
|
||||
nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
|
||||
nsIDOMMutationEvent::REMOVAL);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -122,6 +122,7 @@
|
|||
#include "nsEventDispatcher.h"
|
||||
#include "nsContentErrors.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsNodeUtils.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
|
@ -212,10 +213,11 @@ nsXULDocument::~nsXULDocument()
|
|||
NS_ASSERTION(mNextSrcLoadWaiter == nsnull,
|
||||
"unreferenced document still waiting for script source to load?");
|
||||
|
||||
// Notify our observers here, we can't let the nsDocument
|
||||
// Notify our observers here, we can't let the nsINode
|
||||
// destructor do that for us since some of the observers are
|
||||
// deleted by the time we get there.
|
||||
NS_DOCUMENT_NOTIFY_OBSERVERS(DocumentWillBeDestroyed, (this));
|
||||
nsNodeUtils::NodeWillBeDestroyed(this);
|
||||
// Clear mObservers to keep it in sync with the mutationobserver list
|
||||
mObservers.Clear();
|
||||
|
||||
// In case we failed somewhere early on and the forward observer
|
||||
|
@ -886,9 +888,12 @@ nsXULDocument::ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster,
|
|||
}
|
||||
|
||||
void
|
||||
nsXULDocument::AttributeChanged(nsIContent* aElement, PRInt32 aNameSpaceID,
|
||||
nsXULDocument::AttributeChanged(nsIDocument* aDocument,
|
||||
nsIContent* aElement, PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute, PRInt32 aModType)
|
||||
{
|
||||
NS_ASSERTION(aDocument == this, "unexpected doc");
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// XXXbz check aNameSpaceID, dammit!
|
||||
|
@ -966,46 +971,42 @@ nsXULDocument::AttributeChanged(nsIContent* aElement, PRInt32 aNameSpaceID,
|
|||
}
|
||||
|
||||
void
|
||||
nsXULDocument::ContentAppended(nsIContent* aContainer,
|
||||
nsXULDocument::ContentAppended(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer)
|
||||
{
|
||||
// First update our element map
|
||||
NS_ASSERTION(aDocument == this, "unexpected doc");
|
||||
|
||||
// Update our element map
|
||||
PRUint32 count = aContainer->GetChildCount();
|
||||
|
||||
for (PRUint32 i = aNewIndexInContainer; i < count; ++i) {
|
||||
nsresult rv = AddSubtreeToDocument(aContainer->GetChildAt(i));
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
nsresult rv = NS_OK;
|
||||
for (PRUint32 i = aNewIndexInContainer; i < count && NS_SUCCEEDED(rv);
|
||||
++i) {
|
||||
rv = AddSubtreeToDocument(aContainer->GetChildAt(i));
|
||||
}
|
||||
|
||||
nsXMLDocument::ContentAppended(aContainer, aNewIndexInContainer);
|
||||
}
|
||||
|
||||
void
|
||||
nsXULDocument::ContentInserted(nsIContent* aContainer,
|
||||
nsXULDocument::ContentInserted(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
nsresult rv = AddSubtreeToDocument(aChild);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
NS_ASSERTION(aDocument == this, "unexpected doc");
|
||||
|
||||
nsXMLDocument::ContentInserted(aContainer, aChild,
|
||||
aIndexInContainer);
|
||||
AddSubtreeToDocument(aChild);
|
||||
}
|
||||
|
||||
void
|
||||
nsXULDocument::ContentRemoved(nsIContent* aContainer,
|
||||
nsXULDocument::ContentRemoved(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
nsresult rv;
|
||||
rv = RemoveSubtreeFromDocument(aChild);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
NS_ASSERTION(aDocument == this, "unexpected doc");
|
||||
|
||||
nsXMLDocument::ContentRemoved(aContainer, aChild,
|
||||
aIndexInContainer);
|
||||
RemoveSubtreeFromDocument(aChild);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -1150,7 +1151,6 @@ nsXULDocument::GetElementsByAttribute(const nsAString& aAttribute,
|
|||
nsContentList *list = new nsContentList(this,
|
||||
MatchAttribute,
|
||||
aValue,
|
||||
nsnull,
|
||||
PR_TRUE,
|
||||
attrAtom,
|
||||
kNameSpaceID_Unknown);
|
||||
|
|
|
@ -109,19 +109,21 @@ public:
|
|||
|
||||
virtual void EndLoad();
|
||||
|
||||
virtual void ContentAppended(nsIContent* aContainer,
|
||||
// nsIMutationObserver interface
|
||||
virtual void ContentAppended(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer);
|
||||
|
||||
virtual void ContentInserted(nsIContent* aContainer,
|
||||
virtual void ContentInserted(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer);
|
||||
|
||||
virtual void ContentRemoved(nsIContent* aContainer,
|
||||
virtual void ContentRemoved(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer);
|
||||
|
||||
virtual void AttributeChanged(nsIContent* aElement, PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute, PRInt32 aModType);
|
||||
virtual void AttributeChanged(nsIDocument* aDocument, nsIContent* aElement,
|
||||
PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
||||
PRInt32 aModType);
|
||||
|
||||
// nsIXULDocument interface
|
||||
NS_IMETHOD AddElementForID(const nsAString& aID, nsIContent* aElement);
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include "nsContentCreatorFunctions.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsAttrName.h"
|
||||
#include "nsNodeUtils.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "pldhash.h"
|
||||
|
@ -147,7 +148,7 @@ public:
|
|||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType);
|
||||
|
||||
void DocumentWillBeDestroyed(nsIDocument* aDocument);
|
||||
void NodeWillBeDestroyed(const nsINode* aNode);
|
||||
|
||||
protected:
|
||||
friend NS_IMETHODIMP
|
||||
|
@ -1770,12 +1771,12 @@ nsXULContentBuilder::AttributeChanged(nsIDocument* aDocument,
|
|||
}
|
||||
|
||||
void
|
||||
nsXULContentBuilder::DocumentWillBeDestroyed(nsIDocument *aDocument)
|
||||
nsXULContentBuilder::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
// Break circular references
|
||||
mContentSupportMap.Clear();
|
||||
|
||||
nsXULTemplateBuilder::DocumentWillBeDestroyed(aDocument);
|
||||
nsXULTemplateBuilder::NodeWillBeDestroyed(aNode);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2005,11 +2006,7 @@ nsXULContentBuilder::OpenContainer(nsIContent* aElement)
|
|||
if (container && IsLazyWidgetItem(aElement)) {
|
||||
// The tree widget is special, and has to be spanked every
|
||||
// time we add content to a container.
|
||||
nsCOMPtr<nsIDocument> doc = mRoot->GetDocument();
|
||||
if (! doc)
|
||||
return NS_OK;
|
||||
|
||||
doc->ContentAppended(container, newIndex);
|
||||
nsNodeUtils::ContentAppended(container, newIndex);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2075,12 +2072,7 @@ nsXULContentBuilder::RebuildAll()
|
|||
CreateTemplateAndContainerContents(mRoot, getter_AddRefs(container), &newIndex);
|
||||
|
||||
if (container) {
|
||||
nsCOMPtr<nsIDocument> doc = mRoot->GetDocument();
|
||||
NS_ASSERTION(doc, "root element has no document");
|
||||
if (! doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
doc->ContentAppended(container, newIndex);
|
||||
nsNodeUtils::ContentAppended(container, newIndex);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -237,6 +237,7 @@ NS_IMPL_RELEASE(nsXULTemplateBuilder)
|
|||
NS_INTERFACE_MAP_BEGIN(nsXULTemplateBuilder)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXULTemplateBuilder)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULTemplateBuilder)
|
||||
NS_INTERFACE_MAP_ENTRY_DOM_CLASSINFO(XULTemplateBuilder)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
@ -918,7 +919,7 @@ nsXULTemplateBuilder::ContentRemoved(nsIDocument* aDocument,
|
|||
}
|
||||
|
||||
void
|
||||
nsXULTemplateBuilder::DocumentWillBeDestroyed(nsIDocument *aDocument)
|
||||
nsXULTemplateBuilder::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
// The call to RemoveObserver could release the last reference to
|
||||
// |this|, so hold another reference.
|
||||
|
|
|
@ -104,7 +104,7 @@ public:
|
|||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer);
|
||||
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument);
|
||||
virtual void NodeWillBeDestroyed(const nsINode* aNode);
|
||||
|
||||
/**
|
||||
* Remove an old result and/or add a new result. This method will retrieve
|
||||
|
|
|
@ -88,7 +88,7 @@ public:
|
|||
// nsINativeTreeView: Untrusted code can use us
|
||||
NS_IMETHOD EnsureNative() { return NS_OK; }
|
||||
|
||||
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument);
|
||||
virtual void NodeWillBeDestroyed(const nsINode* aNode);
|
||||
|
||||
protected:
|
||||
friend NS_IMETHODIMP
|
||||
|
@ -1099,12 +1099,12 @@ nsXULTreeBuilder::PerformActionOnCell(const PRUnichar* aAction, PRInt32 aRow, ns
|
|||
|
||||
|
||||
void
|
||||
nsXULTreeBuilder::DocumentWillBeDestroyed(nsIDocument* aDocument)
|
||||
nsXULTreeBuilder::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
if (mObservers)
|
||||
mObservers->Clear();
|
||||
|
||||
nsXULTemplateBuilder::DocumentWillBeDestroyed(aDocument);
|
||||
nsXULTemplateBuilder::NodeWillBeDestroyed(aNode);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -126,7 +126,7 @@ nsSHEntry::~nsSHEntry()
|
|||
//*****************************************************************************
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsSHEntry, nsISHContainer, nsISHEntry, nsIHistoryEntry,
|
||||
nsIDocumentObserver)
|
||||
nsIMutationObserver)
|
||||
|
||||
//*****************************************************************************
|
||||
// nsSHEntry: nsISHEntry
|
||||
|
@ -191,7 +191,7 @@ nsSHEntry::SetContentViewer(nsIContentViewer *aViewer)
|
|||
mDocument = do_QueryInterface(domDoc);
|
||||
if (mDocument) {
|
||||
mDocument->SetShellsHidden(PR_TRUE);
|
||||
mDocument->AddObserver(this);
|
||||
mDocument->AddMutationObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -624,7 +624,7 @@ nsSHEntry::DropPresentationState()
|
|||
|
||||
if (mDocument) {
|
||||
mDocument->SetShellsHidden(PR_FALSE);
|
||||
mDocument->RemoveObserver(this);
|
||||
mDocument->RemoveMutationObserver(this);
|
||||
mDocument = nsnull;
|
||||
}
|
||||
if (mContentViewer)
|
||||
|
@ -639,13 +639,14 @@ nsSHEntry::DropPresentationState()
|
|||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// nsSHEntry: nsIDocumentObserver
|
||||
// nsSHEntry: nsIMutationObserver
|
||||
//*****************************************************************************
|
||||
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(nsSHEntry)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsSHEntry)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsSHEntry)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsSHEntry)
|
||||
void
|
||||
nsSHEntry::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
NS_NOTREACHED("Document destroyed while we're holding a strong ref to it");
|
||||
}
|
||||
|
||||
void
|
||||
nsSHEntry::CharacterDataChanged(nsIDocument* aDocument,
|
||||
|
|
|
@ -57,11 +57,11 @@
|
|||
#include "nsIHistoryEntry.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsSupportsArray.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIMutationObserver.h"
|
||||
|
||||
class nsSHEntry : public nsISHEntry,
|
||||
public nsISHContainer,
|
||||
public nsIDocumentObserver
|
||||
public nsIMutationObserver
|
||||
{
|
||||
public:
|
||||
nsSHEntry();
|
||||
|
@ -71,13 +71,12 @@ public:
|
|||
NS_DECL_NSIHISTORYENTRY
|
||||
NS_DECL_NSISHENTRY
|
||||
NS_DECL_NSISHCONTAINER
|
||||
NS_DECL_NSIDOCUMENTOBSERVER
|
||||
NS_DECL_NSIMUTATIONOBSERVER
|
||||
|
||||
void DropPresentationState();
|
||||
|
||||
private:
|
||||
~nsSHEntry();
|
||||
void RemoveDocumentObserver();
|
||||
void DocumentMutated();
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
|
|
|
@ -226,9 +226,9 @@ nsLoadCollector::~nsLoadCollector()
|
|||
GetMemUsage_Shutdown();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsLoadCollector, nsIMetricsCollector,
|
||||
NS_IMPL_ISUPPORTS5(nsLoadCollector, nsIMetricsCollector,
|
||||
nsIWebProgressListener, nsISupportsWeakReference,
|
||||
nsIDocumentObserver)
|
||||
nsIDocumentObserver, nsIMutationObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLoadCollector::OnStateChange(nsIWebProgress *webProgress,
|
||||
|
|
|
@ -1646,9 +1646,10 @@ PresShell::PresShell()
|
|||
new (this) nsFrameManager();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS7(PresShell, nsIPresShell, nsIDocumentObserver,
|
||||
NS_IMPL_ISUPPORTS8(PresShell, nsIPresShell, nsIDocumentObserver,
|
||||
nsIViewObserver, nsISelectionController,
|
||||
nsISelectionDisplay, nsIObserver, nsISupportsWeakReference)
|
||||
nsISelectionDisplay, nsIObserver, nsISupportsWeakReference,
|
||||
nsIMutationObserver)
|
||||
|
||||
PresShell::~PresShell()
|
||||
{
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
#include "nsLayoutAtoms.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsNodeUtils.h"
|
||||
|
||||
// masks for mEdgeVisibility
|
||||
#define LEFT_VIS 0x0001
|
||||
|
@ -288,10 +289,10 @@ nsHTMLFramesetFrame::FrameResizePrefCallback(const char* aPref, void* aClosure)
|
|||
|
||||
frame->RecalculateBorderResize();
|
||||
if (doc) {
|
||||
doc->AttributeChanged(frame->GetContent(),
|
||||
kNameSpaceID_None,
|
||||
nsHTMLAtoms::frameborder,
|
||||
nsIDOMMutationEvent::MODIFICATION);
|
||||
nsNodeUtils::AttributeChanged(frame->GetContent(),
|
||||
kNameSpaceID_None,
|
||||
nsHTMLAtoms::frameborder,
|
||||
nsIDOMMutationEvent::MODIFICATION);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -722,7 +722,6 @@ void CircleArea::GetRect(nsPresContext* aCX, nsRect& aRect)
|
|||
nsImageMap::nsImageMap() :
|
||||
mPresShell(nsnull),
|
||||
mImageFrame(nsnull),
|
||||
mDocument(nsnull),
|
||||
mContainsBlockContents(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
@ -733,7 +732,7 @@ nsImageMap::~nsImageMap()
|
|||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsImageMap,
|
||||
nsIDocumentObserver,
|
||||
nsIMutationObserver,
|
||||
nsIDOMFocusListener,
|
||||
nsIDOMEventListener,
|
||||
nsIImageMap)
|
||||
|
@ -788,17 +787,12 @@ nsImageMap::Init(nsIPresShell* aPresShell, nsIFrame* aImageFrame, nsIDOMHTMLMapE
|
|||
mPresShell = aPresShell;
|
||||
mImageFrame = aImageFrame;
|
||||
|
||||
nsresult rv;
|
||||
mMap = do_QueryInterface(aMap, &rv);
|
||||
mMap = do_QueryInterface(aMap);
|
||||
NS_ASSERTION(mMap, "aMap is not an nsIContent!");
|
||||
mDocument = mMap->GetDocument();
|
||||
if (mDocument) {
|
||||
mDocument->AddObserver(this);
|
||||
}
|
||||
mMap->AddMutationObserver(this);
|
||||
|
||||
// "Compile" the areas in the map into faster access versions
|
||||
rv = UpdateAreas();
|
||||
return rv;
|
||||
return UpdateAreas();
|
||||
}
|
||||
|
||||
|
||||
|
@ -943,9 +937,7 @@ nsImageMap::Draw(nsPresContext* aCX, nsIRenderingContext& aRC)
|
|||
void
|
||||
nsImageMap::MaybeUpdateAreas(nsIContent *aContent)
|
||||
{
|
||||
if (aContent && (aContent == mMap ||
|
||||
(mContainsBlockContents &&
|
||||
nsContentUtils::ContentIsDescendantOf(aContent, mMap)))) {
|
||||
if (aContent == mMap || mContainsBlockContents) {
|
||||
UpdateAreas();
|
||||
}
|
||||
}
|
||||
|
@ -1060,7 +1052,5 @@ void
|
|||
nsImageMap::Destroy(void)
|
||||
{
|
||||
FreeAreas();
|
||||
if (mDocument) {
|
||||
mDocument->RemoveObserver(this);
|
||||
}
|
||||
mMap->RemoveMutationObserver(this);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include "nsISupports.h"
|
||||
#include "nsCoord.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsStubDocumentObserver.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
#include "nsIDOMFocusListener.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIImageMap.h"
|
||||
|
@ -56,7 +56,7 @@ class nsIURI;
|
|||
class nsString;
|
||||
class nsIDOMEvent;
|
||||
|
||||
class nsImageMap : public nsStubDocumentObserver, public nsIDOMFocusListener,
|
||||
class nsImageMap : public nsStubMutationObserver, public nsIDOMFocusListener,
|
||||
public nsIImageMap
|
||||
{
|
||||
public:
|
||||
|
@ -84,7 +84,7 @@ public:
|
|||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIDocumentObserver
|
||||
// nsIMutationObserver
|
||||
virtual void AttributeChanged(nsIDocument* aDocument, nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
||||
PRInt32 aModType);
|
||||
|
@ -122,7 +122,6 @@ protected:
|
|||
|
||||
nsIPresShell* mPresShell; // WEAK - owns the frame that owns us
|
||||
nsIFrame* mImageFrame; // the frame that owns us
|
||||
nsIDocument* mDocument; // WEAK - the imagemap will not outlive the document
|
||||
nsCOMPtr<nsIContent> mMap;
|
||||
nsAutoVoidArray mAreas; // almost always has some entries
|
||||
PRBool mContainsBlockContents;
|
||||
|
|
|
@ -155,7 +155,7 @@ inDOMView::InitAtoms()
|
|||
NS_IMPL_ISUPPORTS3(inDOMView,
|
||||
inIDOMView,
|
||||
nsITreeView,
|
||||
nsIDocumentObserver)
|
||||
nsIMutationObserver)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// inIDOMView
|
||||
|
@ -176,9 +176,9 @@ inDOMView::SetRootNode(nsIDOMNode* aNode)
|
|||
|
||||
if (mRootDocument) {
|
||||
// remove previous document observer
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(mRootDocument));
|
||||
nsCOMPtr<nsINode> doc(do_QueryInterface(mRootDocument));
|
||||
if (doc)
|
||||
doc->RemoveObserver(this);
|
||||
doc->RemoveMutationObserver(this);
|
||||
}
|
||||
|
||||
RemoveAllNodes();
|
||||
|
@ -204,9 +204,9 @@ inDOMView::SetRootNode(nsIDOMNode* aNode)
|
|||
}
|
||||
|
||||
// add document observer
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(mRootDocument));
|
||||
nsCOMPtr<nsINode> doc(do_QueryInterface(mRootDocument));
|
||||
if (doc)
|
||||
doc->AddObserver(this);
|
||||
doc->AddMutationObserver(this);
|
||||
} else {
|
||||
mRootDocument = nsnull;
|
||||
}
|
||||
|
@ -652,12 +652,13 @@ inDOMView::PerformActionOnCell(const PRUnichar* action, PRInt32 row, nsITreeColu
|
|||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// nsIDocumentObserver
|
||||
// nsIMutationObserver
|
||||
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_CORE_STUB(inDOMView)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(inDOMView)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(inDOMView)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(inDOMView)
|
||||
void
|
||||
inDOMView::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
NS_NOTREACHED("Document destroyed while we're holding a strong ref to it");
|
||||
}
|
||||
|
||||
void
|
||||
inDOMView::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
#include "nsITreeView.h"
|
||||
#include "nsITreeSelection.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIMutationObserver.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
@ -54,7 +54,7 @@ class inDOMViewNode;
|
|||
|
||||
class inDOMView : public inIDOMView,
|
||||
public nsITreeView,
|
||||
public nsIDocumentObserver
|
||||
public nsIMutationObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -64,8 +64,8 @@ public:
|
|||
inDOMView();
|
||||
virtual ~inDOMView();
|
||||
|
||||
// nsIDocumentObserver
|
||||
NS_DECL_NSIDOCUMENTOBSERVER
|
||||
// nsIMutationObserver
|
||||
NS_DECL_NSIMUTATIONOBSERVER
|
||||
|
||||
static void InitAtoms();
|
||||
|
||||
|
|
|
@ -165,6 +165,7 @@ NS_INTERFACE_MAP_BEGIN(nsTreeContentView)
|
|||
NS_INTERFACE_MAP_ENTRY(nsITreeView)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITreeContentView)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITreeContentView)
|
||||
NS_INTERFACE_MAP_ENTRY_DOM_CLASSINFO(TreeContentView)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
@ -1096,7 +1097,7 @@ nsTreeContentView::ContentRemoved(nsIDocument *aDocument,
|
|||
}
|
||||
|
||||
void
|
||||
nsTreeContentView::DocumentWillBeDestroyed(nsIDocument *aDocument)
|
||||
nsTreeContentView::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
ClearRows();
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ class nsTreeContentView : public nsINativeTreeView,
|
|||
PRInt32 aIndexInContainer);
|
||||
virtual void ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
|
||||
nsIContent* aChild, PRInt32 aIndexInContainer);
|
||||
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument);
|
||||
virtual void NodeWillBeDestroyed(const nsINode* aNode);
|
||||
|
||||
protected:
|
||||
// Recursive methods which deal with serializing of nested content.
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#include "nsIMenuBar.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIMutationObserver.h"
|
||||
#include "nsIChangeManager.h"
|
||||
#include "nsIMenuCommandDispatcher.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
@ -81,7 +81,7 @@ namespace MenuHelpersX
|
|||
|
||||
class nsMenuBarX : public nsIMenuBar,
|
||||
public nsIMenuListener,
|
||||
public nsIDocumentObserver,
|
||||
public nsIMutationObserver,
|
||||
public nsIChangeManager,
|
||||
public nsIMenuCommandDispatcher,
|
||||
public nsSupportsWeakReference
|
||||
|
@ -111,8 +111,8 @@ public:
|
|||
nsEventStatus CheckRebuild(PRBool & aMenuEvent);
|
||||
nsEventStatus SetRebuild(PRBool aMenuEvent);
|
||||
|
||||
// nsIDocumentObserver
|
||||
NS_DECL_NSIDOCUMENTOBSERVER
|
||||
// nsIMutationObserver
|
||||
NS_DECL_NSIMUTATIONOBSERVER
|
||||
|
||||
NS_IMETHOD Create(nsIWidget * aParent);
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocumentViewer.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIMutationObserver.h"
|
||||
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsWidgetAtoms.h"
|
||||
|
@ -68,7 +68,7 @@
|
|||
#include "nsWidgetsCID.h"
|
||||
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
|
||||
|
||||
NS_IMPL_ISUPPORTS6(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIDocumentObserver,
|
||||
NS_IMPL_ISUPPORTS6(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIMutationObserver,
|
||||
nsIChangeManager, nsIMenuCommandDispatcher, nsISupportsWeakReference)
|
||||
|
||||
NSMenu* nsMenuBarX::sApplicationMenu = nsnull;
|
||||
|
@ -94,8 +94,7 @@ nsMenuBarX::~nsMenuBarX()
|
|||
|
||||
// make sure we unregister ourselves as a document observer
|
||||
if (mDocument) {
|
||||
nsCOMPtr<nsIDocumentObserver> observer(do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)));
|
||||
mDocument->RemoveObserver(observer);
|
||||
mDocument->RemoveMutationObserver(this);
|
||||
}
|
||||
|
||||
[mRootMenu autorelease];
|
||||
|
@ -201,8 +200,7 @@ nsMenuBarX::RegisterAsDocumentObserver(nsIDocShell* inDocShell)
|
|||
return;
|
||||
|
||||
// register ourselves
|
||||
nsCOMPtr<nsIDocumentObserver> observer(do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)));
|
||||
doc->AddObserver(observer);
|
||||
doc->AddMutationObserver(this);
|
||||
// also get pointer to doc, just in case docshell goes away
|
||||
// we can still remove ourself as doc observer directly from doc
|
||||
mDocument = doc;
|
||||
|
@ -809,24 +807,10 @@ NS_IMETHODIMP nsMenuBarX::Paint()
|
|||
|
||||
|
||||
//
|
||||
// nsIDocumentObserver
|
||||
// nsIMutationObserver
|
||||
// this is needed for menubar changes
|
||||
//
|
||||
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsMenuBarX)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsMenuBarX)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsMenuBarX)
|
||||
|
||||
void
|
||||
nsMenuBarX::BeginUpdate(nsIDocument * aDocument, nsUpdateType aUpdateType)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuBarX::EndUpdate(nsIDocument * aDocument, nsUpdateType aUpdateType)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuBarX::CharacterDataChanged(nsIDocument * aDocument,
|
||||
nsIContent * aContent, PRBool aAppend)
|
||||
|
@ -854,7 +838,7 @@ nsMenuBarX::ContentAppended(nsIDocument * aDocument, nsIContent * aContainer,
|
|||
}
|
||||
|
||||
void
|
||||
nsMenuBarX::DocumentWillBeDestroyed(nsIDocument * aDocument)
|
||||
nsMenuBarX::NodeWillBeDestroyed(const nsINode * aNode)
|
||||
{
|
||||
mDocument = nsnull;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocumentViewer.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIMutationObserver.h"
|
||||
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsWidgetAtoms.h"
|
||||
|
@ -66,7 +66,7 @@
|
|||
#include "nsWidgetsCID.h"
|
||||
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
|
||||
|
||||
NS_IMPL_ISUPPORTS6(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIDocumentObserver,
|
||||
NS_IMPL_ISUPPORTS6(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIMutationObserver,
|
||||
nsIChangeManager, nsIMenuCommandDispatcher, nsISupportsWeakReference)
|
||||
|
||||
MenuRef nsMenuBarX::sAppleMenu = nsnull;
|
||||
|
@ -96,8 +96,7 @@ nsMenuBarX::~nsMenuBarX()
|
|||
|
||||
// make sure we unregister ourselves as a document observer
|
||||
if ( mDocument ) {
|
||||
nsCOMPtr<nsIDocumentObserver> observer ( do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)) );
|
||||
mDocument->RemoveObserver(observer);
|
||||
mDocument->RemoveMutationObserver(this);
|
||||
}
|
||||
|
||||
if ( mRootMenu )
|
||||
|
@ -204,8 +203,7 @@ nsMenuBarX :: RegisterAsDocumentObserver ( nsIDocShell* inDocShell )
|
|||
return;
|
||||
|
||||
// register ourselves
|
||||
nsCOMPtr<nsIDocumentObserver> observer ( do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)) );
|
||||
doc->AddObserver(observer);
|
||||
doc->AddMutationObserver(this);
|
||||
// also get pointer to doc, just in case docshell goes away
|
||||
// we can still remove ourself as doc observer directly from doc
|
||||
mDocument = doc;
|
||||
|
@ -657,24 +655,10 @@ NS_METHOD nsMenuBarX::Paint()
|
|||
#pragma mark -
|
||||
|
||||
//
|
||||
// nsIDocumentObserver
|
||||
// nsIMutationObserver
|
||||
// this is needed for menubar changes
|
||||
//
|
||||
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_LOAD_STUB(nsMenuBarX)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsMenuBarX)
|
||||
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsMenuBarX)
|
||||
|
||||
void
|
||||
nsMenuBarX::BeginUpdate( nsIDocument * aDocument, nsUpdateType aUpdateType )
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuBarX::EndUpdate( nsIDocument * aDocument, nsUpdateType aUpdateType )
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuBarX::CharacterDataChanged( nsIDocument * aDocument,
|
||||
nsIContent * aContent, PRBool aAppend)
|
||||
|
@ -702,7 +686,7 @@ nsMenuBarX::ContentAppended( nsIDocument * aDocument, nsIContent * aContainer,
|
|||
}
|
||||
|
||||
void
|
||||
nsMenuBarX::DocumentWillBeDestroyed( nsIDocument * aDocument )
|
||||
nsMenuBarX::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
mDocument = nsnull;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
#include "nsIMenuBar.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIMutationObserver.h"
|
||||
#include "nsIChangeManager.h"
|
||||
#include "nsIMenuCommandDispatcher.h"
|
||||
#include "nsPresContext.h"
|
||||
|
@ -71,7 +71,7 @@ namespace MenuHelpersX
|
|||
|
||||
class nsMenuBarX : public nsIMenuBar,
|
||||
public nsIMenuListener,
|
||||
public nsIDocumentObserver,
|
||||
public nsIMutationObserver,
|
||||
public nsIChangeManager,
|
||||
public nsIMenuCommandDispatcher,
|
||||
public nsSupportsWeakReference
|
||||
|
@ -96,8 +96,8 @@ public:
|
|||
nsEventStatus CheckRebuild(PRBool & aMenuEvent);
|
||||
nsEventStatus SetRebuild(PRBool aMenuEvent);
|
||||
|
||||
// nsIDocumentObserver
|
||||
NS_DECL_NSIDOCUMENTOBSERVER
|
||||
// nsIMutationObserver
|
||||
NS_DECL_NSIMUTATIONOBSERVER
|
||||
|
||||
NS_IMETHOD Create(nsIWidget * aParent);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче