void nsMutationReceiver::ContentInserted(nsIDocument* aDocument, nsIContent* aContainer, nsIContent* aChild, int32_t aIndexInContainer) { nsINode* parent = NODE_FROM(aContainer, aDocument); bool wantsChildList = ChildList() && (Subtree() || parent == Target()); if (!wantsChildList || aChild->ChromeOnlyAccess()) { return; } if (nsAutoMutationBatch::IsBatching()) { if (parent == nsAutoMutationBatch::GetBatchTarget()) { nsAutoMutationBatch::UpdateObserver(Observer(), wantsChildList); } return; } nsDOMMutationRecord* m = Observer()->CurrentRecord(NS_LITERAL_STRING("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 nsTextStateManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContainer, nsIContent* aChild, PRInt32 aIndexInContainer, nsIContent* aPreviousSibling) { PRUint32 offset = 0, childOffset = 1; if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange( mRootContent, NODE_FROM(aContainer, aDocument), aIndexInContainer, &offset))) return; // get offset at the end of the deleted node if (aChild->IsNodeOfType(nsINode::eTEXT)) childOffset = aChild->TextLength(); else if (0 < aChild->GetChildCount()) childOffset = aChild->GetChildCount(); if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange( aChild, aChild, childOffset, &childOffset))) return; // fire notification if (childOffset) nsContentUtils::AddScriptRunner( new TextChangeEvent(mWidget, offset, offset + childOffset, offset)); }
void IMEContentObserver::ContentInserted(nsIDocument* aDocument, nsIContent* aContainer, nsIContent* aChild, int32_t aIndexInContainer) { NotifyContentAdded(NODE_FROM(aContainer, aDocument), aIndexInContainer, aIndexInContainer + 1); }
void nsTextStateManager::ContentInserted(nsIDocument* aDocument, nsIContent* aContainer, nsIContent* aChild, PRInt32 aIndexInContainer) { NotifyContentAdded(NODE_FROM(aContainer, aDocument), aIndexInContainer, aIndexInContainer + 1); }
void IMEContentObserver::ContentRemoved(nsIDocument* aDocument, nsIContent* aContainer, nsIContent* aChild, int32_t aIndexInContainer, nsIContent* aPreviousSibling) { mEndOfAddedTextCache.Clear(); bool causedByComposition = IsEditorHandlingEventForComposition(); if (!mTextChangeData.IsValid() && causedByComposition && !mUpdatePreference.WantChangesCausedByComposition()) { return; } nsINode* containerNode = NODE_FROM(aContainer, aDocument); uint32_t offset = 0; nsresult rv = NS_OK; if (!mStartOfRemovingTextRangeCache.Match(containerNode, aIndexInContainer)) { rv = ContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, containerNode, aIndexInContainer, &offset, LINE_BREAK_TYPE_NATIVE); if (NS_WARN_IF(NS_FAILED(rv))) { mStartOfRemovingTextRangeCache.Clear(); return; } mStartOfRemovingTextRangeCache.Cache(containerNode, aIndexInContainer, offset); } else { offset = mStartOfRemovingTextRangeCache.mFlatTextLength; } // get offset at the end of the deleted node int32_t nodeLength = aChild->IsNodeOfType(nsINode::eTEXT) ? static_cast<int32_t>(aChild->TextLength()) : std::max(static_cast<int32_t>(aChild->GetChildCount()), 1); MOZ_ASSERT(nodeLength >= 0, "The node length is out of range"); uint32_t textLength = 0; rv = ContentEventHandler::GetFlatTextOffsetOfRange(aChild, aChild, nodeLength, &textLength, LINE_BREAK_TYPE_NATIVE); if (NS_WARN_IF(NS_FAILED(rv))) { mStartOfRemovingTextRangeCache.Clear(); return; } if (!textLength) { return; } TextChangeData data(offset, offset + textLength, offset, causedByComposition); MaybeNotifyIMEOfTextChange(data); }
void nsNodeIterator::ContentRemoved(nsIDocument *aDocument, nsIContent *aContainer, nsIContent *aChild, int32_t aIndexInContainer, nsIContent *aPreviousSibling) { nsINode *container = NODE_FROM(aContainer, aDocument); mPointer.AdjustAfterRemoval(mRoot, container, aChild, aPreviousSibling); mWorkingPointer.AdjustAfterRemoval(mRoot, container, aChild, aPreviousSibling); }
nsresult nsDOMDocumentType::BindToTree(nsIDocument *aDocument, nsIContent *aParent, nsIContent *aBindingParent, PRBool aCompileEventHandlers) { if (!HasSameOwnerDoc(NODE_FROM(aParent, aDocument))) { NS_ASSERTION(!GetOwnerDoc(), "Need to adopt or import first!"); // DocumentType nodes are the only nodes that can have a null ownerDocument // according to the DOM spec, so we need to give them a new nodeinfo in that // case. // XXX We may want to move this to nsDOMImplementation::CreateDocument if // we want to rely on the nodeinfo and wrappers being right before // getting into ReplaceOrInsertBefore or doInsertChildAt. That would // break inserting DOMDocumentType nodes through other DOM methods // though. nsNodeInfoManager *nimgr = aParent ? aParent->NodeInfo()->NodeInfoManager() : aDocument->NodeInfoManager(); nsCOMPtr<nsINodeInfo> newNodeInfo; newNodeInfo = nimgr->GetNodeInfo(mNodeInfo->NameAtom(), mNodeInfo->GetPrefixAtom(), mNodeInfo->NamespaceID()); NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY); mNodeInfo.swap(newNodeInfo); JSObject *oldScope = GetWrapper(); if (oldScope) { nsIXPConnect *xpc = nsContentUtils::XPConnect(); JSContext *cx = nsnull; JSObject *newScope = nsnull; nsresult rv = nsContentUtils::GetContextAndScope(nsnull, nimgr->GetDocument(), &cx, &newScope); if (cx && xpc) { nsISupports *node = NS_ISUPPORTS_CAST(nsIContent*, this); nsCOMPtr<nsIXPConnectJSObjectHolder> oldWrapper; rv = xpc->ReparentWrappedNativeIfFound(cx, oldScope, newScope, node, getter_AddRefs(oldWrapper)); } if (NS_FAILED(rv)) { mNodeInfo.swap(newNodeInfo); return rv; } }
void nsContentList::ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer, nsIContent* aChild, PRInt32 aIndexInContainer) { // 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 && MayContainRelevantNodes(NODE_FROM(aContainer, aDocument)) && nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild) && MatchSelf(aChild)) { SetDirty(); } ASSERT_IN_SYNC; }
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 (aChild->ChromeOnlyAccess()) { return; } nsINode* parent = NODE_FROM(aContainer, aDocument); 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) != 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. transientReceivers->AppendObject(new nsMutationReceiver(aChild, orig)); } } } if (ChildList() && (Subtree() || parent == Target())) { nsDOMMutationRecord* m = Observer()->CurrentRecord(NS_LITERAL_STRING("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(); }
nsresult CharacterData::BindToTree(Document* aDocument, nsIContent* aParent, nsIContent* aBindingParent) { MOZ_ASSERT(aParent || aDocument, "Must have document if no parent!"); MOZ_ASSERT(NODE_FROM(aParent, aDocument)->OwnerDoc() == OwnerDoc(), "Must have the same owner document"); MOZ_ASSERT(!aParent || aDocument == aParent->GetUncomposedDoc(), "aDocument must be current doc of aParent"); MOZ_ASSERT(!GetUncomposedDoc() && !IsInUncomposedDoc(), "Already have a document. Unbind first!"); MOZ_ASSERT(!IsInComposedDoc(), "Already have a document. Unbind first!"); // Note that as we recurse into the kids, they'll have a non-null parent. So // only assert if our parent is _changing_ while we have a parent. MOZ_ASSERT(!GetParent() || aParent == GetParent(), "Already have a parent. Unbind first!"); MOZ_ASSERT(!GetBindingParent() || aBindingParent == GetBindingParent() || (!aBindingParent && aParent && aParent->GetBindingParent() == GetBindingParent()), "Already have a binding parent. Unbind first!"); MOZ_ASSERT(aBindingParent != this, "Content must not be its own binding parent"); MOZ_ASSERT(!IsRootOfNativeAnonymousSubtree() || aBindingParent == aParent, "Native anonymous content must have its parent as its " "own binding parent"); if (!aBindingParent && aParent) { aBindingParent = aParent->GetBindingParent(); } // First set the binding parent if (aBindingParent) { NS_ASSERTION(IsRootOfNativeAnonymousSubtree() || !HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE) || (aParent && aParent->IsInNativeAnonymousSubtree()), "Trying to re-bind content from native anonymous subtree to " "non-native anonymous parent!"); ExtendedContentSlots()->mBindingParent = aBindingParent; // Weak, so no addref happens. if (aParent->IsInNativeAnonymousSubtree()) { SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE); } if (aParent->HasFlag(NODE_HAS_BEEN_IN_UA_WIDGET)) { SetFlags(NODE_HAS_BEEN_IN_UA_WIDGET); } if (HasFlag(NODE_IS_ANONYMOUS_ROOT)) { aParent->SetMayHaveAnonymousChildren(); } } if (aParent && aParent->IsInShadowTree()) { ClearSubtreeRootPointer(); SetFlags(NODE_IS_IN_SHADOW_TREE); SetIsConnected(aParent->IsInComposedDoc()); MOZ_ASSERT(aParent->GetContainingShadow()); ExtendedContentSlots()->mContainingShadow = aParent->GetContainingShadow(); } bool hadParent = !!GetParentNode(); // Set parent if (aParent) { if (!GetParent()) { NS_ADDREF(aParent); } mParent = aParent; } else { mParent = aDocument; } SetParentIsContent(aParent); // XXXbz sXBL/XBL2 issue! // Set document if (aDocument) { // We no longer need to track the subtree pointer (and in fact we'll assert // if we do this any later). ClearSubtreeRootPointer(); // XXX See the comment in Element::BindToTree SetIsInDocument(); SetIsConnected(true); if (mText.IsBidi()) { aDocument->SetBidiEnabled(); } // Clear the lazy frame construction bits. UnsetFlags(NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES); } else if (!IsInShadowTree()) { // If we're not in the doc and not in a shadow tree, // update our subtree pointer. SetSubtreeRootPointer(aParent->SubtreeRoot()); } nsNodeUtils::ParentChainChanged(this); if (!hadParent && IsRootOfNativeAnonymousSubtree()) { nsNodeUtils::NativeAnonymousChildListChange(this, false); } UpdateEditableState(false); MOZ_ASSERT(aDocument == GetUncomposedDoc(), "Bound to wrong document"); MOZ_ASSERT(aParent == GetParent(), "Bound to wrong parent"); MOZ_ASSERT(aBindingParent == GetBindingParent(), "Bound to wrong binding parent"); return NS_OK; }