void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild) { ASSERT(newChild); ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events). ASSERT(!newChild->isDocumentFragment()); ASSERT(!hasTagName(HTMLNames::templateTag)); if (document() != newChild->document()) document()->adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); Node* last = m_lastChild; { NoEventDispatchAssertion assertNoEventDispatch; // FIXME: This method should take a PassRefPtr. appendChildToContainer(newChild.get(), this); treeScope()->adoptIfNeeded(newChild.get()); } newChild->updateAncestorConnectedSubframeCountForInsertion(); ChildListMutationScope(this).childAdded(newChild.get()); childrenChanged(true, last, 0, 1); ChildNodeInsertionNotifier(this).notify(newChild.get()); }
void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild) { ASSERT(newChild); ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events). ASSERT(!newChild->isDocumentFragment()); #if ENABLE(TEMPLATE_ELEMENT) ASSERT(!hasTagName(HTMLNames::templateTag)); #endif if (&document() != &newChild->document()) document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION); { NoEventDispatchAssertion assertNoEventDispatch; // FIXME: This method should take a PassRefPtr. appendChildToContainer(newChild.get(), *this); treeScope().adoptIfNeeded(newChild.get()); } newChild->updateAncestorConnectedSubframeCountForInsertion(); ChildListMutationScope(*this).childAdded(*newChild); notifyChildInserted(*newChild, ChildChangeSourceParser); ChildNodeInsertionNotifier(*this).notify(*newChild); newChild->setNeedsStyleRecalc(ReconstructRenderTree); }
bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, AttachBehavior attachBehavior) { RefPtr<ContainerNode> protect(this); // 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()); ec = 0; // Make sure adding the new child is ok if (!checkAddChild(this, newChild.get(), ec)) return false; if (newChild == m_lastChild) // nothing to do return newChild; 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); // Now actually add the child(ren) ChildListMutationScope mutation(this); for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) { Node* child = it->get(); // If the child has a parent again, just stop what we're doing, because // that means someone is doing something with DOM mutation -- can't re-parent // a child that already has a parent. if (child->parentNode()) break; treeScope()->adoptIfNeeded(child); // Append child to the end of the list { NoEventDispatchAssertion assertNoEventDispatch; appendChildToContainer(child, this); } updateTreeAfterInsertion(this, child, attachBehavior); } dispatchSubtreeModifiedEvent(); return true; }
void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild) { ASSERT(newChild); ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events). Node* last = m_lastChild; { NoEventDispatchAssertion assertNoEventDispatch; // FIXME: This method should take a PassRefPtr. appendChildToContainer(newChild.get(), this); treeScope()->adoptIfNeeded(newChild.get()); } childrenChanged(true, last, 0, 1); ChildNodeInsertionNotifier(this).notify(newChild.get()); }
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; }