Make it possible for document observers who need to worry about XBL to observe
the binding manager and make presshell do that. Bug 348573, r+sr=sicking
This commit is contained in:
@@ -825,18 +825,19 @@ nsDocument::Init()
|
|||||||
NS_ENSURE_TRUE(bindingManager, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(bindingManager, NS_ERROR_OUT_OF_MEMORY);
|
||||||
mBindingManager = bindingManager;
|
mBindingManager = bindingManager;
|
||||||
|
|
||||||
// The binding manager must always be the first observer of the document.
|
if (!mObservers.PrependObserver(bindingManager)) {
|
||||||
mObservers.PrependObserver(bindingManager);
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
nsINode::nsSlots* slots = GetSlots();
|
nsINode::nsSlots* slots = GetSlots();
|
||||||
NS_ENSURE_TRUE(slots &&
|
NS_ENSURE_TRUE(slots &&
|
||||||
slots->mMutationObservers.PrependObserver(bindingManager),
|
slots->mMutationObservers.PrependObserver(bindingManager),
|
||||||
NS_ERROR_OUT_OF_MEMORY);
|
NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
// Prepend self as mutation-observer whether we need it or not (some
|
// Prepend self as mutation-observer whether we need it or not (some
|
||||||
// subclasses currently do, other don't). This is because the code in
|
// subclasses currently do, other don't). This is because the code in
|
||||||
// nsNodeUtils always notifies the first observer first, even when going
|
// nsNodeUtils always notifies the first observer first, expecting the
|
||||||
// backwards, expecting the first observer to be the document.
|
// 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_ENSURE_TRUE(slots->mMutationObservers.PrependObserver(this),
|
||||||
NS_ERROR_OUT_OF_MEMORY);
|
NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
|
|||||||
@@ -672,27 +672,9 @@ protected:
|
|||||||
// Dispatch an event to the ScriptGlobalObject for this document
|
// Dispatch an event to the ScriptGlobalObject for this document
|
||||||
void DispatchEventToWindow(nsEvent *aEvent);
|
void DispatchEventToWindow(nsEvent *aEvent);
|
||||||
|
|
||||||
// NS_DOCUMENT_NOTIFY_OBSERVERS goes backwards for now for backwards compat.
|
|
||||||
// If you change this, update ContentAppended/Inserted/Removed accordingly.
|
|
||||||
#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_) \
|
#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_) \
|
||||||
do { \
|
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(mObservers, nsIDocumentObserver, \
|
||||||
nsTObserverArray<nsIDocumentObserver>::ReverseIterator \
|
func_, params_);
|
||||||
iter_(mObservers); \
|
|
||||||
nsCOMPtr<nsIDocumentObserver> obs_; \
|
|
||||||
while ((obs_ = iter_.GetNext())) { \
|
|
||||||
obs_ -> func_ params_ ; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define NS_DOCUMENT_FORWARD_NOTIFY_OBSERVERS(func_, params_) \
|
|
||||||
do { \
|
|
||||||
nsTObserverArray<nsIDocumentObserver>::ForwardIterator \
|
|
||||||
iter_(mObservers); \
|
|
||||||
nsCOMPtr<nsIDocumentObserver> obs_; \
|
|
||||||
while ((obs_ = iter_.GetNext())) { \
|
|
||||||
obs_ -> func_ params_ ; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void VerifyRootContentState();
|
void VerifyRootContentState();
|
||||||
|
|||||||
@@ -403,7 +403,6 @@ nsGenericDOMDataNode::AppendData(const nsAString& aData)
|
|||||||
// Apparently this is called often enough that we don't want to just simply
|
// Apparently this is called often enough that we don't want to just simply
|
||||||
// call SetText like ReplaceData does. See bug 77585 and comment in
|
// call SetText like ReplaceData does. See bug 77585 and comment in
|
||||||
// ReplaceData.
|
// ReplaceData.
|
||||||
nsIDocument *document = GetCurrentDoc();
|
|
||||||
|
|
||||||
// FIXME, but 330872: We can't call BeginUpdate here because it confuses the
|
// FIXME, but 330872: We can't call BeginUpdate here because it confuses the
|
||||||
// poor little nsHTMLContentSink.
|
// poor little nsHTMLContentSink.
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
#include "nsIMutationObserver.h"
|
#include "nsIMutationObserver.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
|
|
||||||
#define IMPL_MUTATION_NOTIFICATION_FW(func_, content_, params_) \
|
#define IMPL_MUTATION_NOTIFICATION(func_, content_, params_) \
|
||||||
|
PR_BEGIN_MACRO \
|
||||||
nsINode* node = content_; \
|
nsINode* node = content_; \
|
||||||
nsINode* prev; \
|
nsINode* prev; \
|
||||||
do { \
|
do { \
|
||||||
@@ -50,12 +51,9 @@
|
|||||||
if (slots && !slots->mMutationObservers.IsEmpty()) { \
|
if (slots && !slots->mMutationObservers.IsEmpty()) { \
|
||||||
/* No need to explicitly notify the first observer first \
|
/* No need to explicitly notify the first observer first \
|
||||||
since that'll happen anyway. */ \
|
since that'll happen anyway. */ \
|
||||||
nsTObserverArray<nsIMutationObserver>::ForwardIterator \
|
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS( \
|
||||||
iter_(slots->mMutationObservers); \
|
slots->mMutationObservers, nsIMutationObserver, \
|
||||||
nsCOMPtr<nsIMutationObserver> obs_; \
|
func_, params_); \
|
||||||
while ((obs_ = iter_.GetNext())) { \
|
|
||||||
obs_-> func_ params_; \
|
|
||||||
} \
|
|
||||||
} \
|
} \
|
||||||
prev = node; \
|
prev = node; \
|
||||||
node = node->GetNodeParent(); \
|
node = node->GetNodeParent(); \
|
||||||
@@ -66,50 +64,15 @@
|
|||||||
need to notify the document */ \
|
need to notify the document */ \
|
||||||
node = NS_STATIC_CAST(nsIContent*, prev)->GetCurrentDoc(); \
|
node = NS_STATIC_CAST(nsIContent*, prev)->GetCurrentDoc(); \
|
||||||
} \
|
} \
|
||||||
} while (node);
|
} while (node); \
|
||||||
|
PR_END_MACRO
|
||||||
|
|
||||||
|
|
||||||
#define IMPL_MUTATION_NOTIFICATION_BW(func_, content_, params_) \
|
|
||||||
nsINode* node = content_; \
|
|
||||||
nsINode* prev; \
|
|
||||||
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
|
void
|
||||||
nsNodeUtils::CharacterDataChanged(nsIContent* aContent, PRBool aAppend)
|
nsNodeUtils::CharacterDataChanged(nsIContent* aContent, PRBool aAppend)
|
||||||
{
|
{
|
||||||
nsIDocument* doc = aContent->GetOwnerDoc();
|
nsIDocument* doc = aContent->GetOwnerDoc();
|
||||||
IMPL_MUTATION_NOTIFICATION_BW(CharacterDataChanged, aContent,
|
IMPL_MUTATION_NOTIFICATION(CharacterDataChanged, aContent,
|
||||||
(doc, aContent, aAppend));
|
(doc, aContent, aAppend));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +83,7 @@ nsNodeUtils::AttributeChanged(nsIContent* aContent,
|
|||||||
PRInt32 aModType)
|
PRInt32 aModType)
|
||||||
{
|
{
|
||||||
nsIDocument* doc = aContent->GetOwnerDoc();
|
nsIDocument* doc = aContent->GetOwnerDoc();
|
||||||
IMPL_MUTATION_NOTIFICATION_BW(AttributeChanged, aContent,
|
IMPL_MUTATION_NOTIFICATION(AttributeChanged, aContent,
|
||||||
(doc, aContent, aNameSpaceID, aAttribute,
|
(doc, aContent, aNameSpaceID, aAttribute,
|
||||||
aModType));
|
aModType));
|
||||||
}
|
}
|
||||||
@@ -131,13 +94,7 @@ nsNodeUtils::ContentAppended(nsIContent* aContainer,
|
|||||||
{
|
{
|
||||||
nsIDocument* document = aContainer->GetOwnerDoc();
|
nsIDocument* document = aContainer->GetOwnerDoc();
|
||||||
|
|
||||||
// XXXdwh There is a hacky ordering dependency between the binding
|
IMPL_MUTATION_NOTIFICATION(ContentAppended, aContainer,
|
||||||
// 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));
|
(document, aContainer, aNewIndexInContainer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,13 +117,7 @@ nsNodeUtils::ContentInserted(nsINode* aContainer,
|
|||||||
document = NS_STATIC_CAST(nsIDocument*, aContainer);
|
document = NS_STATIC_CAST(nsIDocument*, aContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXXdwh There is a hacky ordering dependency between the binding manager
|
IMPL_MUTATION_NOTIFICATION(ContentInserted, aContainer,
|
||||||
// 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));
|
(document, container, aChild, aIndexInContainer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,14 +140,7 @@ nsNodeUtils::ContentRemoved(nsINode* aContainer,
|
|||||||
document = NS_STATIC_CAST(nsIDocument*, aContainer);
|
document = NS_STATIC_CAST(nsIDocument*, aContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXXdwh There is a hacky ordering dependency between the binding
|
IMPL_MUTATION_NOTIFICATION(ContentRemoved, aContainer,
|
||||||
// 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));
|
(document, container, aChild, aIndexInContainer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,12 +150,9 @@ nsNodeUtils::NodeWillBeDestroyed(nsINode* aNode)
|
|||||||
nsINode::nsSlots* slots = aNode->GetExistingSlots();
|
nsINode::nsSlots* slots = aNode->GetExistingSlots();
|
||||||
if (slots) {
|
if (slots) {
|
||||||
if (!slots->mMutationObservers.IsEmpty()) {
|
if (!slots->mMutationObservers.IsEmpty()) {
|
||||||
nsTObserverArray<nsIMutationObserver>::ForwardIterator
|
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(slots->mMutationObservers,
|
||||||
iter(slots->mMutationObservers);
|
nsIMutationObserver,
|
||||||
nsCOMPtr<nsIMutationObserver> obs;
|
NodeWillBeDestroyed, (aNode));
|
||||||
while ((obs = iter.GetNext())) {
|
|
||||||
obs->NodeWillBeDestroyed(aNode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PtrBits flags = slots->mFlags | NODE_DOESNT_HAVE_SLOTS;
|
PtrBits flags = slots->mFlags | NODE_DOESNT_HAVE_SLOTS;
|
||||||
|
|||||||
@@ -196,29 +196,17 @@ class nsTObserverArray : public nsTObserverArray_base {
|
|||||||
return NS_STATIC_CAST(T*, GetSafeElementAt(mPosition++));
|
return NS_STATIC_CAST(T*, GetSafeElementAt(mPosition++));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ReverseIterator;
|
|
||||||
friend class ReverseIterator;
|
|
||||||
|
|
||||||
// Iterates the array backwards from end to beginning
|
|
||||||
// mPosition points to the element that was returned from last call to
|
|
||||||
// GetNext
|
|
||||||
class ReverseIterator : public nsTObserverArray_base::Iterator_base {
|
|
||||||
public:
|
|
||||||
ReverseIterator(nsTObserverArray<T>& aArray)
|
|
||||||
: Iterator_base(aArray.mObservers.Count(), aArray) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the next element and steps one step.
|
|
||||||
* Returns null if there are no more observers. Once null is returned
|
|
||||||
* the iterator becomes invalid and GetNext must not be called any more.
|
|
||||||
* @return The next observer.
|
|
||||||
*/
|
|
||||||
T* GetNext() {
|
|
||||||
return NS_STATIC_CAST(T*, GetSafeElementAt(--mPosition));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// XXXbz I wish I didn't have to pass in the observer type, but I
|
||||||
|
// don't see a way to get it out of array_.
|
||||||
|
#define NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(array_, obstype_, func_, params_) \
|
||||||
|
PR_BEGIN_MACRO \
|
||||||
|
nsTObserverArray<obstype_>::ForwardIterator iter_(array_); \
|
||||||
|
nsCOMPtr<obstype_> obs_; \
|
||||||
|
while ((obs_ = iter_.GetNext())) { \
|
||||||
|
obs_ -> func_ params_ ; \
|
||||||
|
} \
|
||||||
|
PR_END_MACRO
|
||||||
|
|
||||||
#endif // nsTObserverArray_h___
|
#endif // nsTObserverArray_h___
|
||||||
|
|||||||
@@ -57,9 +57,11 @@ class nsIURI;
|
|||||||
class nsIXPConnectWrappedJS;
|
class nsIXPConnectWrappedJS;
|
||||||
class nsIDOMNodeList;
|
class nsIDOMNodeList;
|
||||||
class nsVoidArray;
|
class nsVoidArray;
|
||||||
|
class nsIDocumentObserver;
|
||||||
|
|
||||||
#define NS_IBINDING_MANAGER_IID \
|
#define NS_IBINDING_MANAGER_IID \
|
||||||
{ 0x92281eaa, 0x89c4, 0x4457, { 0x8f, 0x8d, 0xca, 0x92, 0xbf, 0xbe, 0x0f, 0x50 } }
|
{ 0x8186980b, 0x35b8, 0x469f, \
|
||||||
|
{ 0x8b, 0xc5, 0x33, 0xad, 0x3c, 0x35, 0x90, 0x98 } }
|
||||||
|
|
||||||
class nsIBindingManager : public nsISupports
|
class nsIBindingManager : public nsISupports
|
||||||
{
|
{
|
||||||
@@ -176,6 +178,22 @@ public:
|
|||||||
NS_IMETHOD GetBindingImplementation(nsIContent* aContent, REFNSIID aIID, void** aResult)=0;
|
NS_IMETHOD GetBindingImplementation(nsIContent* aContent, REFNSIID aIID, void** aResult)=0;
|
||||||
|
|
||||||
NS_IMETHOD ShouldBuildChildFrames(nsIContent* aContent, PRBool* aResult) = 0;
|
NS_IMETHOD ShouldBuildChildFrames(nsIContent* aContent, PRBool* aResult) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new observer of document change notifications. Whenever content is
|
||||||
|
* changed, appended, inserted or removed the observers are informed. This
|
||||||
|
* is like nsIDocument::AddObserver, but these observers will be notified
|
||||||
|
* after the XBL data structures are updated for
|
||||||
|
* ContentInserted/ContentAppended and before they're updated for
|
||||||
|
* ContentRemoved.
|
||||||
|
*/
|
||||||
|
virtual void AddObserver(nsIDocumentObserver* aObserver) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an observer of document change notifications. This will
|
||||||
|
* return false if the observer cannot be found.
|
||||||
|
*/
|
||||||
|
virtual PRBool RemoveObserver(nsIDocumentObserver* aObserver) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIBindingManager, NS_IBINDING_MANAGER_IID)
|
NS_DEFINE_STATIC_IID_ACCESSOR(nsIBindingManager, NS_IBINDING_MANAGER_IID)
|
||||||
|
|||||||
@@ -1138,16 +1138,85 @@ nsBindingManager::GetNestedInsertionPoint(nsIContent* aParent, nsIContent* aChil
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: We don't hold a reference to the document observer; we assume
|
||||||
|
// that it has a live reference to the document.
|
||||||
|
void
|
||||||
|
nsBindingManager::AddObserver(nsIDocumentObserver* aObserver)
|
||||||
|
{
|
||||||
|
// The array makes sure the observer isn't already in the list
|
||||||
|
mObservers.AppendObserver(aObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsBindingManager::RemoveObserver(nsIDocumentObserver* aObserver)
|
||||||
|
{
|
||||||
|
return mObservers.RemoveObserver(aObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(BeginUpdate, (aDocument, aUpdateType));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(EndUpdate, (aDocument, aUpdateType));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::BeginLoad(nsIDocument* aDocument)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(BeginLoad, (aDocument));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::EndLoad(nsIDocument* aDocument)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(EndLoad, (aDocument));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::CharacterDataChanged(nsIDocument* aDocument,
|
||||||
|
nsIContent* aContent,
|
||||||
|
PRBool aAppend)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(CharacterDataChanged,
|
||||||
|
(aDocument, aContent, aAppend));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::ContentStatesChanged(nsIDocument* aDocument,
|
||||||
|
nsIContent* aContent1,
|
||||||
|
nsIContent* aContent2,
|
||||||
|
PRInt32 aStateMask)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(ContentStatesChanged,
|
||||||
|
(aDocument, aContent1, aContent2,
|
||||||
|
aStateMask));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::AttributeChanged(nsIDocument* aDocument,
|
||||||
|
nsIContent* aContent,
|
||||||
|
PRInt32 aNameSpaceID,
|
||||||
|
nsIAtom* aAttribute,
|
||||||
|
PRInt32 aModType)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(AttributeChanged,
|
||||||
|
(aDocument, aContent, aNameSpaceID,
|
||||||
|
aAttribute, aModType));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsBindingManager::ContentAppended(nsIDocument* aDocument,
|
nsBindingManager::ContentAppended(nsIDocument* aDocument,
|
||||||
nsIContent* aContainer,
|
nsIContent* aContainer,
|
||||||
PRInt32 aNewIndexInContainer)
|
PRInt32 aNewIndexInContainer)
|
||||||
{
|
{
|
||||||
// XXX This is hacked and not quite correct. See below.
|
// XXX This is hacked and not quite correct. See below.
|
||||||
if (aNewIndexInContainer == -1 || !mContentListTable.ops)
|
if (aNewIndexInContainer != -1 && mContentListTable.ops) {
|
||||||
// It's anonymous.
|
// It's not anonymous.
|
||||||
return;
|
|
||||||
|
|
||||||
PRInt32 childCount = aContainer->GetChildCount();
|
PRInt32 childCount = aContainer->GetChildCount();
|
||||||
|
|
||||||
nsIContent *child = aContainer->GetChildAt(aNewIndexInContainer);
|
nsIContent *child = aContainer->GetChildAt(aNewIndexInContainer);
|
||||||
@@ -1164,7 +1233,9 @@ nsBindingManager::ContentAppended(nsIDocument* aDocument,
|
|||||||
if (nodeList && isAnonymousContentList) {
|
if (nodeList && isAnonymousContentList) {
|
||||||
// Find a non-pseudo-insertion point and just jam ourselves in.
|
// Find a non-pseudo-insertion point and just jam ourselves in.
|
||||||
// This is not 100% correct. Hack city, baby.
|
// This is not 100% correct. Hack city, baby.
|
||||||
nsAnonymousContentList* contentList = NS_STATIC_CAST(nsAnonymousContentList*, NS_STATIC_CAST(nsIDOMNodeList*, nodeList.get()));
|
nsAnonymousContentList* contentList =
|
||||||
|
NS_STATIC_CAST(nsAnonymousContentList*,
|
||||||
|
NS_STATIC_CAST(nsIDOMNodeList*, nodeList.get()));
|
||||||
|
|
||||||
PRInt32 count = contentList->GetInsertionPointCount();
|
PRInt32 count = contentList->GetInsertionPointCount();
|
||||||
for (PRInt32 i = 0; i < count; i++) {
|
for (PRInt32 i = 0; i < count; i++) {
|
||||||
@@ -1183,6 +1254,11 @@ nsBindingManager::ContentAppended(nsIDocument* aDocument,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(ContentAppended,
|
||||||
|
(aDocument, aContainer,
|
||||||
|
aNewIndexInContainer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1191,11 +1267,9 @@ nsBindingManager::ContentInserted(nsIDocument* aDocument,
|
|||||||
nsIContent* aChild,
|
nsIContent* aChild,
|
||||||
PRInt32 aIndexInContainer)
|
PRInt32 aIndexInContainer)
|
||||||
{
|
{
|
||||||
// XXX This is hacked just to make menus work again.
|
// XXX This is hacked just to make menus work again.
|
||||||
if (aIndexInContainer == -1 || !mContentListTable.ops)
|
if (aIndexInContainer != -1 && mContentListTable.ops) {
|
||||||
// It's anonymous.
|
// It's not anonymous.
|
||||||
return;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> ins;
|
nsCOMPtr<nsIContent> ins;
|
||||||
GetNestedInsertionPoint(aContainer, aChild, getter_AddRefs(ins));
|
GetNestedInsertionPoint(aContainer, aChild, getter_AddRefs(ins));
|
||||||
|
|
||||||
@@ -1208,7 +1282,9 @@ nsBindingManager::ContentInserted(nsIDocument* aDocument,
|
|||||||
if (nodeList && isAnonymousContentList) {
|
if (nodeList && isAnonymousContentList) {
|
||||||
// Find a non-pseudo-insertion point and just jam ourselves in.
|
// Find a non-pseudo-insertion point and just jam ourselves in.
|
||||||
// This is not 100% correct. Hack city, baby.
|
// This is not 100% correct. Hack city, baby.
|
||||||
nsAnonymousContentList* contentList = NS_STATIC_CAST(nsAnonymousContentList*, NS_STATIC_CAST(nsIDOMNodeList*, nodeList.get()));
|
nsAnonymousContentList* contentList =
|
||||||
|
NS_STATIC_CAST(nsAnonymousContentList*,
|
||||||
|
NS_STATIC_CAST(nsIDOMNodeList*, nodeList.get()));
|
||||||
|
|
||||||
PRInt32 count = contentList->GetInsertionPointCount();
|
PRInt32 count = contentList->GetInsertionPointCount();
|
||||||
for (PRInt32 i = 0; i < count; i++) {
|
for (PRInt32 i = 0; i < count; i++) {
|
||||||
@@ -1251,6 +1327,11 @@ nsBindingManager::ContentInserted(nsIDocument* aDocument,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(ContentInserted,
|
||||||
|
(aDocument, aContainer, aChild,
|
||||||
|
aIndexInContainer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1259,6 +1340,10 @@ nsBindingManager::ContentRemoved(nsIDocument* aDocument,
|
|||||||
nsIContent* aChild,
|
nsIContent* aChild,
|
||||||
PRInt32 aIndexInContainer)
|
PRInt32 aIndexInContainer)
|
||||||
{
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(ContentRemoved,
|
||||||
|
(aDocument, aContainer, aChild,
|
||||||
|
aIndexInContainer));
|
||||||
|
|
||||||
if (aIndexInContainer == -1 || !mContentListTable.ops)
|
if (aIndexInContainer == -1 || !mContentListTable.ops)
|
||||||
// It's anonymous.
|
// It's anonymous.
|
||||||
return;
|
return;
|
||||||
@@ -1285,3 +1370,66 @@ nsBindingManager::ContentRemoved(nsIDocument* aDocument,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::NodeWillBeDestroyed(const nsINode *aNode)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(NodeWillBeDestroyed, (aNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::StyleSheetAdded(nsIDocument* aDocument,
|
||||||
|
nsIStyleSheet* aStyleSheet,
|
||||||
|
PRBool aDocumentSheet)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(StyleSheetAdded,
|
||||||
|
(aDocument, aStyleSheet, aDocumentSheet));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::StyleSheetRemoved(nsIDocument* aDocument,
|
||||||
|
nsIStyleSheet* aStyleSheet,
|
||||||
|
PRBool aDocumentSheet)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(StyleSheetRemoved,
|
||||||
|
(aDocument, aStyleSheet, aDocumentSheet));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::StyleSheetApplicableStateChanged(nsIDocument* aDocument,
|
||||||
|
nsIStyleSheet* aStyleSheet,
|
||||||
|
PRBool aApplicable)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(StyleSheetApplicableStateChanged,
|
||||||
|
(aDocument, aStyleSheet, aApplicable));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::StyleRuleChanged(nsIDocument* aDocument,
|
||||||
|
nsIStyleSheet* aStyleSheet,
|
||||||
|
nsIStyleRule* aOldStyleRule,
|
||||||
|
nsIStyleRule* aNewStyleRule)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(StyleRuleChanged,
|
||||||
|
(aDocument, aStyleSheet, aOldStyleRule,
|
||||||
|
aNewStyleRule));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::StyleRuleAdded(nsIDocument* aDocument,
|
||||||
|
nsIStyleSheet* aStyleSheet,
|
||||||
|
nsIStyleRule* aStyleRule)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(StyleRuleAdded,
|
||||||
|
(aDocument, aStyleSheet, aStyleRule));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsBindingManager::StyleRuleRemoved(nsIDocument* aDocument,
|
||||||
|
nsIStyleSheet* aStyleSheet,
|
||||||
|
nsIStyleRule* aStyleRule)
|
||||||
|
{
|
||||||
|
NS_BINDINGMANAGER_NOTIFY_OBSERVERS(StyleRuleRemoved,
|
||||||
|
(aDocument, aStyleSheet, aStyleRule));
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,11 +61,12 @@ class nsStyleSet;
|
|||||||
|
|
||||||
class nsBindingManager : public nsIBindingManager,
|
class nsBindingManager : public nsIBindingManager,
|
||||||
public nsIStyleRuleSupplier,
|
public nsIStyleRuleSupplier,
|
||||||
public nsStubDocumentObserver
|
public nsIDocumentObserver
|
||||||
{
|
{
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIDOCUMENTOBSERVER
|
||||||
|
|
||||||
nsBindingManager();
|
nsBindingManager();
|
||||||
~nsBindingManager();
|
~nsBindingManager();
|
||||||
|
|
||||||
@@ -123,25 +124,16 @@ public:
|
|||||||
|
|
||||||
NS_IMETHOD ShouldBuildChildFrames(nsIContent* aContent, PRBool* aResult);
|
NS_IMETHOD ShouldBuildChildFrames(nsIContent* aContent, PRBool* aResult);
|
||||||
|
|
||||||
|
virtual NS_HIDDEN_(void) AddObserver(nsIDocumentObserver* aObserver);
|
||||||
|
|
||||||
|
virtual NS_HIDDEN_(PRBool) RemoveObserver(nsIDocumentObserver* aObserver);
|
||||||
|
|
||||||
// nsIStyleRuleSupplier
|
// nsIStyleRuleSupplier
|
||||||
NS_IMETHOD WalkRules(nsStyleSet* aStyleSet,
|
NS_IMETHOD WalkRules(nsStyleSet* aStyleSet,
|
||||||
nsIStyleRuleProcessor::EnumFunc aFunc,
|
nsIStyleRuleProcessor::EnumFunc aFunc,
|
||||||
RuleProcessorData* aData,
|
RuleProcessorData* aData,
|
||||||
PRBool* aCutOffInheritance);
|
PRBool* aCutOffInheritance);
|
||||||
|
|
||||||
// nsIDocumentObserver
|
|
||||||
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);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsresult GetXBLChildNodesInternal(nsIContent* aContent,
|
nsresult GetXBLChildNodesInternal(nsIContent* aContent,
|
||||||
nsIDOMNodeList** aResult,
|
nsIDOMNodeList** aResult,
|
||||||
@@ -156,6 +148,10 @@ protected:
|
|||||||
|
|
||||||
nsresult GetNestedInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult);
|
nsresult GetNestedInsertionPoint(nsIContent* aParent, nsIContent* aChild, nsIContent** aResult);
|
||||||
|
|
||||||
|
#define NS_BINDINGMANAGER_NOTIFY_OBSERVERS(func_, params_) \
|
||||||
|
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(mObservers, nsIDocumentObserver, \
|
||||||
|
func_, params_);
|
||||||
|
|
||||||
// MEMBER VARIABLES
|
// MEMBER VARIABLES
|
||||||
protected:
|
protected:
|
||||||
// A mapping from nsIContent* to the nsXBLBinding* that is
|
// A mapping from nsIContent* to the nsXBLBinding* that is
|
||||||
@@ -201,6 +197,11 @@ protected:
|
|||||||
// table, they have not yet finished loading.
|
// table, they have not yet finished loading.
|
||||||
nsInterfaceHashtable<nsURIHashKey,nsIStreamListener> mLoadingDocTable;
|
nsInterfaceHashtable<nsURIHashKey,nsIStreamListener> mLoadingDocTable;
|
||||||
|
|
||||||
|
// Array of document observers who would like to be notified of content
|
||||||
|
// appends/inserts after we update our data structures and of content removes
|
||||||
|
// before we do so.
|
||||||
|
nsTObserverArray<nsIDocumentObserver> mObservers;
|
||||||
|
|
||||||
// A queue of binding attached event handlers that are awaiting execution.
|
// A queue of binding attached event handlers that are awaiting execution.
|
||||||
nsVoidArray mAttachedStack;
|
nsVoidArray mAttachedStack;
|
||||||
PRBool mProcessingAttachedStack;
|
PRBool mProcessingAttachedStack;
|
||||||
|
|||||||
@@ -2700,7 +2700,7 @@ NS_IMETHODIMP
|
|||||||
PresShell::BeginObservingDocument()
|
PresShell::BeginObservingDocument()
|
||||||
{
|
{
|
||||||
if (mDocument) {
|
if (mDocument) {
|
||||||
mDocument->AddObserver(this);
|
mDocument->BindingManager()->AddObserver(this);
|
||||||
if (mIsDocumentGone) {
|
if (mIsDocumentGone) {
|
||||||
NS_WARNING("Adding a presshell that was disconnected from the document "
|
NS_WARNING("Adding a presshell that was disconnected from the document "
|
||||||
"as a document observer? Sounds wrong...");
|
"as a document observer? Sounds wrong...");
|
||||||
@@ -2718,7 +2718,7 @@ PresShell::EndObservingDocument()
|
|||||||
// is gone, perhaps? Except for printing it's NOT gone, sometimes.
|
// is gone, perhaps? Except for printing it's NOT gone, sometimes.
|
||||||
mIsDocumentGone = PR_TRUE;
|
mIsDocumentGone = PR_TRUE;
|
||||||
if (mDocument) {
|
if (mDocument) {
|
||||||
mDocument->RemoveObserver(this);
|
mDocument->BindingManager()->RemoveObserver(this);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user