void nsMutationReceiver::ContentInserted(nsIDocument* aDocument, nsIContent* aContainer, nsIContent* aChild, int32_t aIndexInContainer) { nsINode* parent = NODE_FROM(aContainer, aDocument); bool wantsChildList = ChildList() && ((Subtree() && RegisterTarget()->SubtreeRoot() == parent->SubtreeRoot()) || parent == Target()); if (!wantsChildList || !IsObservable(aChild)) { return; } if (nsAutoMutationBatch::IsBatching()) { if (parent == nsAutoMutationBatch::GetBatchTarget()) { nsAutoMutationBatch::UpdateObserver(Observer(), wantsChildList); } return; } nsDOMMutationRecord* m = Observer()->CurrentRecord(nsGkAtoms::childList); if (m->mTarget) { // Already handled case. return; } m->mTarget = parent; m->mAddedNodes = new nsSimpleContentList(parent); m->mAddedNodes->AppendElement(aChild); m->mPreviousSibling = aChild->GetPreviousSibling(); m->mNextSibling = aChild->GetNextSibling(); }
void nsMutationReceiver::CharacterDataWillChange(nsIDocument *aDocument, nsIContent* aContent, CharacterDataChangeInfo* aInfo) { if (nsAutoMutationBatch::IsBatching() || !CharacterData() || (!Subtree() && aContent != Target()) || (Subtree() && RegisterTarget()->SubtreeRoot() != aContent->SubtreeRoot()) || !IsObservable(aContent)) { return; } nsDOMMutationRecord* m = Observer()->CurrentRecord(nsGkAtoms::characterData); NS_ASSERTION(!m->mTarget || m->mTarget == aContent, "Wrong target!"); if (!m->mTarget) { m->mTarget = aContent; } if (CharacterDataOldValue() && m->mPrevValue.IsVoid()) { aContent->GetText()->AppendTo(m->mPrevValue); } }
void Attribute::AttachObserver (Attribute* attrib){ if ( !IsObservable() ) return; m_symbol_name = m_prototype->GetName()+"x"+m_name; for (unsigned int i=0; i<m_observers.size(); i++) if ( attrib == m_observers.at(i) ) return; m_observers.push_back(attrib); attrib->AttachSubject(this); }
void nsMutationReceiver::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer, nsIContent* aFirstNewContent, int32_t aNewIndexInContainer) { nsINode* parent = NODE_FROM(aContainer, aDocument); bool wantsChildList = ChildList() && ((Subtree() && RegisterTarget()->SubtreeRoot() == parent->SubtreeRoot()) || parent == Target()); if (!wantsChildList || !IsObservable(aFirstNewContent)) { return; } if (nsAutoMutationBatch::IsBatching()) { if (parent == nsAutoMutationBatch::GetBatchTarget()) { nsAutoMutationBatch::UpdateObserver(Observer(), wantsChildList); } return; } nsDOMMutationRecord* m = Observer()->CurrentRecord(nsGkAtoms::childList); NS_ASSERTION(!m->mTarget || m->mTarget == parent, "Wrong target!"); if (m->mTarget) { // Already handled case. return; } m->mTarget = parent; m->mAddedNodes = new nsSimpleContentList(parent); nsINode* n = aFirstNewContent; while (n) { m->mAddedNodes->AppendElement(static_cast<nsIContent*>(n)); n = n->GetNextSibling(); } m->mPreviousSibling = aFirstNewContent->GetPreviousSibling(); }
void nsMutationReceiver::ContentRemoved(nsIDocument* aDocument, nsIContent* aContainer, nsIContent* aChild, int32_t aIndexInContainer, nsIContent* aPreviousSibling) { if (!IsObservable(aChild)) { return; } nsINode* parent = NODE_FROM(aContainer, aDocument); if (Subtree() && parent->SubtreeRoot() != RegisterTarget()->SubtreeRoot()) { return; } if (nsAutoMutationBatch::IsBatching()) { if (nsAutoMutationBatch::IsRemovalDone()) { // This can happen for example if HTML parser parses to // context node, but needs to move elements around. return; } if (nsAutoMutationBatch::GetBatchTarget() != parent) { return; } bool wantsChildList = ChildList() && (Subtree() || parent == Target()); if (wantsChildList || Subtree()) { nsAutoMutationBatch::NodeRemoved(aChild); nsAutoMutationBatch::UpdateObserver(Observer(), wantsChildList); } return; } if (Subtree()) { // Try to avoid creating transient observer if the node // already has an observer observing the same set of nodes. nsMutationReceiver* orig = GetParent() ? GetParent() : this; if (Observer()->GetReceiverFor(aChild, false, false) != orig) { bool transientExists = false; nsCOMArray<nsMutationReceiver>* transientReceivers = nullptr; Observer()->mTransientReceivers.Get(aChild, &transientReceivers); if (!transientReceivers) { transientReceivers = new nsCOMArray<nsMutationReceiver>(); Observer()->mTransientReceivers.Put(aChild, transientReceivers); } else { for (int32_t i = 0; i < transientReceivers->Count(); ++i) { nsMutationReceiver* r = transientReceivers->ObjectAt(i); if (r->GetParent() == orig) { transientExists = true; } } } if (!transientExists) { // Make sure the elements which are removed from the // subtree are kept in the same observation set. nsMutationReceiver* tr; if (orig->Animations()) { tr = nsAnimationReceiver::Create(aChild, orig); } else { tr = nsMutationReceiver::Create(aChild, orig); } transientReceivers->AppendObject(tr); } } } if (ChildList() && (Subtree() || parent == Target())) { nsDOMMutationRecord* m = Observer()->CurrentRecord(nsGkAtoms::childList); if (m->mTarget) { // Already handled case. return; } m->mTarget = parent; m->mRemovedNodes = new nsSimpleContentList(parent); m->mRemovedNodes->AppendElement(aChild); m->mPreviousSibling = aPreviousSibling; m->mNextSibling = parent->GetChildAt(aIndexInContainer); } // We need to schedule always, so that after microtask mTransientReceivers // can be cleared correctly. Observer()->ScheduleForRun(); }