void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChild) { ASSERT(newChild); ASSERT(nextChild); ASSERT(nextChild->parentNode() == this); ASSERT(!newChild->isDocumentFragment()); #if ENABLE(TEMPLATE_ELEMENT) ASSERT(!hasTagName(HTMLNames::templateTag)); #endif if (nextChild->previousSibling() == newChild || nextChild == newChild) // nothing to do return; if (&document() != &newChild->document()) document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); insertBeforeCommon(nextChild, newChild.get()); newChild->updateAncestorConnectedSubframeCountForInsertion(); ChildListMutationScope(this).childAdded(newChild.get()); childrenChanged(true, newChild->previousSibling(), nextChild, 1); ChildNodeInsertionNotifier(this).notify(newChild.get()); }
void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChild) { ASSERT(newChild); ASSERT(nextChild); ASSERT(nextChild->parentNode() == this); NodeVector targets; collectTargetNodes(newChild.get(), targets); if (targets.isEmpty()) return; if (nextChild->previousSibling() == newChild || nextChild == newChild) // nothing to do return; RefPtr<Node> next = nextChild; RefPtr<Node> nextChildPreviousSibling = nextChild->previousSibling(); for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) { Node* child = it->get(); insertBeforeCommon(next.get(), child); childrenChanged(true, nextChildPreviousSibling.get(), nextChild, 1); ChildNodeInsertionNotifier(this).notify(child); } }
bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, AttachBehavior attachBehavior) { // Check that this node is not "floating". // If it is, it can be deleted as a side effect of sending mutation events. ASSERT(refCount() || parentOrShadowHostNode()); RefPtr<Node> protect(this); ec = 0; if (oldChild == newChild) // nothing to do return true; if (!oldChild) { ec = NOT_FOUND_ERR; return false; } // Make sure replacing the old child with the new is ok if (!checkReplaceChild(this, newChild.get(), oldChild, ec)) return false; // NOT_FOUND_ERR: Raised if oldChild is not a child of this node. if (oldChild->parentNode() != this) { ec = NOT_FOUND_ERR; return false; } ChildListMutationScope mutation(this); RefPtr<Node> next = oldChild->nextSibling(); // Remove the node we're replacing RefPtr<Node> removedChild = oldChild; removeChild(oldChild, ec); if (ec) return false; if (next && (next->previousSibling() == newChild || next == newChild)) // nothing to do return true; // Does this one more time because removeChild() fires a MutationEvent. if (!checkReplaceChild(this, newChild.get(), oldChild, ec)) return false; NodeVector targets; collectChildrenAndRemoveFromOldParent(newChild.get(), targets, ec); if (ec) return false; // Does this yet another check because collectChildrenAndRemoveFromOldParent() fires a MutationEvent. if (!checkReplaceChild(this, newChild.get(), oldChild, ec)) return false; InspectorInstrumentation::willInsertDOMNode(document(), this); // Add the new child(ren) for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) { Node* child = it->get(); // Due to arbitrary code running in response to a DOM mutation event it's // possible that "next" is no longer a child of "this". // It's also possible that "child" has been inserted elsewhere. // In either of those cases, we'll just stop. if (next && next->parentNode() != this) break; if (child->parentNode()) break; treeScope()->adoptIfNeeded(child); // Add child before "next". { NoEventDispatchAssertion assertNoEventDispatch; if (next) insertBeforeCommon(next.get(), child); else appendChildToContainer(child, this); } updateTreeAfterInsertion(this, child, attachBehavior); } dispatchSubtreeModifiedEvent(); return true; }
bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, AttachBehavior attachBehavior) { // Check that this node is not "floating". // If it is, it can be deleted as a side effect of sending mutation events. ASSERT(refCount() || parentOrShadowHostNode()); RefPtr<Node> protect(this); ec = 0; // insertBefore(node, 0) is equivalent to appendChild(node) if (!refChild) return appendChild(newChild, ec, attachBehavior); // Make sure adding the new child is OK. if (!checkAddChild(this, newChild.get(), ec)) return false; // NOT_FOUND_ERR: Raised if refChild is not a child of this node if (refChild->parentNode() != this) { ec = NOT_FOUND_ERR; return false; } if (refChild->previousSibling() == newChild || refChild == newChild) // nothing to do return true; RefPtr<Node> next = refChild; NodeVector targets; collectChildrenAndRemoveFromOldParent(newChild.get(), targets, ec); if (ec) return false; if (targets.isEmpty()) return true; // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events. if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), ec)) return false; InspectorInstrumentation::willInsertDOMNode(document(), this); ChildListMutationScope mutation(this); for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) { Node* child = it->get(); // Due to arbitrary code running in response to a DOM mutation event it's // possible that "next" is no longer a child of "this". // It's also possible that "child" has been inserted elsewhere. // In either of those cases, we'll just stop. if (next->parentNode() != this) break; if (child->parentNode()) break; treeScope()->adoptIfNeeded(child); insertBeforeCommon(next.get(), child); updateTreeAfterInsertion(this, child, attachBehavior); } dispatchSubtreeModifiedEvent(); return true; }