forked from mirrors/gecko-dev
		
	 8b5b7ad998
			
		
	
	
		8b5b7ad998
		
	
	
	
	
		
			
			You let me know if this seems appealing to you :) Differential Revision: https://phabricator.services.mozilla.com/D175382
		
			
				
	
	
		
			201 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| /*
 | |
|  * 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"
 | |
| #include "mozilla/RefCountType.h"
 | |
| #include "nsISupports.h"
 | |
| #include "nsINode.h"
 | |
| 
 | |
| /******************************************************************************
 | |
|  * nsStubMutationObserver
 | |
|  *****************************************************************************/
 | |
| 
 | |
| NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(nsStubMutationObserver)
 | |
| NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(nsStubMutationObserver)
 | |
| 
 | |
| /******************************************************************************
 | |
|  * MutationObserverWrapper
 | |
|  *****************************************************************************/
 | |
| 
 | |
| /**
 | |
|  * @brief Wrapper class for a mutation observer that observes multiple nodes.
 | |
|  *
 | |
|  * This wrapper implements all methods of the nsIMutationObserver interface
 | |
|  * and forwards all calls to its owner, which is an instance of
 | |
|  * nsMultiMutationObserver.
 | |
|  *
 | |
|  * This class holds a reference to the owner and AddRefs/Releases its owner
 | |
|  * as well to ensure lifetime.
 | |
|  */
 | |
| class MutationObserverWrapper final : public nsIMutationObserver {
 | |
|  public:
 | |
|   NS_DECL_ISUPPORTS
 | |
| 
 | |
|   explicit MutationObserverWrapper(nsMultiMutationObserver* aOwner)
 | |
|       : mOwner(aOwner) {}
 | |
| 
 | |
|   void CharacterDataWillChange(nsIContent* aContent,
 | |
|                                const CharacterDataChangeInfo& aInfo) override {
 | |
|     MOZ_ASSERT(mOwner);
 | |
|     mOwner->CharacterDataWillChange(aContent, aInfo);
 | |
|   }
 | |
| 
 | |
|   void CharacterDataChanged(nsIContent* aContent,
 | |
|                             const CharacterDataChangeInfo& aInfo) override {
 | |
|     MOZ_ASSERT(mOwner);
 | |
|     mOwner->CharacterDataChanged(aContent, aInfo);
 | |
|   }
 | |
| 
 | |
|   void AttributeWillChange(mozilla::dom::Element* aElement,
 | |
|                            int32_t aNameSpaceID, nsAtom* aAttribute,
 | |
|                            int32_t aModType) override {
 | |
|     MOZ_ASSERT(mOwner);
 | |
|     mOwner->AttributeWillChange(aElement, aNameSpaceID, aAttribute, aModType);
 | |
|   }
 | |
| 
 | |
|   void AttributeChanged(mozilla::dom::Element* aElement, int32_t aNameSpaceID,
 | |
|                         nsAtom* aAttribute, int32_t aModType,
 | |
|                         const nsAttrValue* aOldValue) override {
 | |
|     MOZ_ASSERT(mOwner);
 | |
|     mOwner->AttributeChanged(aElement, aNameSpaceID, aAttribute, aModType,
 | |
|                              aOldValue);
 | |
|   }
 | |
| 
 | |
|   void AttributeSetToCurrentValue(mozilla::dom::Element* aElement,
 | |
|                                   int32_t aNameSpaceID,
 | |
|                                   nsAtom* aAttribute) override {
 | |
|     MOZ_ASSERT(mOwner);
 | |
|     mOwner->AttributeSetToCurrentValue(aElement, aNameSpaceID, aAttribute);
 | |
|   }
 | |
| 
 | |
|   void ContentAppended(nsIContent* aFirstNewContent) override {
 | |
|     MOZ_ASSERT(mOwner);
 | |
|     mOwner->ContentAppended(aFirstNewContent);
 | |
|   }
 | |
| 
 | |
|   void ContentInserted(nsIContent* aChild) override {
 | |
|     MOZ_ASSERT(mOwner);
 | |
|     mOwner->ContentInserted(aChild);
 | |
|   }
 | |
| 
 | |
|   void ContentRemoved(nsIContent* aChild,
 | |
|                       nsIContent* aPreviousSibling) override {
 | |
|     MOZ_ASSERT(mOwner);
 | |
|     mOwner->ContentRemoved(aChild, aPreviousSibling);
 | |
|   }
 | |
| 
 | |
|   void NodeWillBeDestroyed(nsINode* aNode) override {
 | |
|     MOZ_ASSERT(mOwner);
 | |
|     AddRefWrapper();
 | |
|     RefPtr<nsMultiMutationObserver> owner = mOwner;
 | |
|     owner->NodeWillBeDestroyed(aNode);
 | |
|     owner->RemoveMutationObserverFromNode(aNode);
 | |
|     mOwner = nullptr;
 | |
|     ReleaseWrapper();
 | |
|   }
 | |
| 
 | |
|   void ParentChainChanged(nsIContent* aContent) override {
 | |
|     MOZ_ASSERT(mOwner);
 | |
|     mOwner->ParentChainChanged(aContent);
 | |
|   }
 | |
| 
 | |
|   void ARIAAttributeDefaultWillChange(mozilla::dom::Element* aElement,
 | |
|                                       nsAtom* aAttribute,
 | |
|                                       int32_t aModType) override {
 | |
|     MOZ_ASSERT(mOwner);
 | |
|     mOwner->ARIAAttributeDefaultWillChange(aElement, aAttribute, aModType);
 | |
|   }
 | |
| 
 | |
|   void ARIAAttributeDefaultChanged(mozilla::dom::Element* aElement,
 | |
|                                    nsAtom* aAttribute,
 | |
|                                    int32_t aModType) override {
 | |
|     MOZ_ASSERT(mOwner);
 | |
|     mOwner->ARIAAttributeDefaultChanged(aElement, aAttribute, aModType);
 | |
|   }
 | |
| 
 | |
|   MozExternalRefCountType AddRefWrapper() {
 | |
|     nsrefcnt count = ++mRefCnt;
 | |
|     NS_LOG_ADDREF(this, count, "MutationObserverWrapper", sizeof(*this));
 | |
|     return count;
 | |
|   }
 | |
| 
 | |
|   MozExternalRefCountType ReleaseWrapper() {
 | |
|     --mRefCnt;
 | |
|     NS_LOG_RELEASE(this, mRefCnt, "MutationObserverWrapper");
 | |
|     if (mRefCnt == 0) {
 | |
|       mRefCnt = 1;
 | |
|       delete this;
 | |
|       return MozExternalRefCountType(0);
 | |
|     }
 | |
|     return mRefCnt;
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   ~MutationObserverWrapper() = default;
 | |
|   nsMultiMutationObserver* mOwner{nullptr};
 | |
| };
 | |
| 
 | |
| NS_IMPL_QUERY_INTERFACE(MutationObserverWrapper, nsIMutationObserver);
 | |
| 
 | |
| MozExternalRefCountType MutationObserverWrapper::AddRef() {
 | |
|   MOZ_ASSERT(mOwner);
 | |
|   AddRefWrapper();
 | |
|   mOwner->AddRef();
 | |
|   return mRefCnt;
 | |
| }
 | |
| 
 | |
| MozExternalRefCountType MutationObserverWrapper::Release() {
 | |
|   MOZ_ASSERT(mOwner);
 | |
|   mOwner->Release();
 | |
|   return ReleaseWrapper();
 | |
| }
 | |
| 
 | |
| /******************************************************************************
 | |
|  * nsMultiMutationObserver
 | |
|  *****************************************************************************/
 | |
| 
 | |
| void nsMultiMutationObserver::AddMutationObserverToNode(nsINode* aNode) {
 | |
|   if (!aNode) {
 | |
|     return;
 | |
|   }
 | |
|   if (mWrapperForNode.Contains(aNode)) {
 | |
|     return;
 | |
|   }
 | |
|   auto* newWrapper = new MutationObserverWrapper{this};
 | |
|   newWrapper->AddRefWrapper();
 | |
|   mWrapperForNode.InsertOrUpdate(aNode, newWrapper);
 | |
|   aNode->AddMutationObserver(newWrapper);
 | |
| }
 | |
| 
 | |
| void nsMultiMutationObserver::RemoveMutationObserverFromNode(nsINode* aNode) {
 | |
|   if (!aNode) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (auto obs = mWrapperForNode.MaybeGet(aNode); obs.isSome()) {
 | |
|     aNode->RemoveMutationObserver(*obs);
 | |
|     mWrapperForNode.Remove(aNode);
 | |
|     (*obs)->ReleaseWrapper();
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool nsMultiMutationObserver::ContainsNode(const nsINode* aNode) const {
 | |
|   return mWrapperForNode.Contains(const_cast<nsINode*>(aNode));
 | |
| }
 | |
| 
 | |
| /******************************************************************************
 | |
|  * nsStubMultiMutationObserver
 | |
|  *****************************************************************************/
 | |
| 
 | |
| NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(nsStubMultiMutationObserver)
 | |
| NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(nsStubMultiMutationObserver)
 |