Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2001 Dirk Mueller (mueller (at) kde.org)
      5  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Library General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Library General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Library General Public License
     18  * along with this library; see the file COPYING.LIB.  If not, write to
     19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     20  * Boston, MA 02110-1301, USA.
     21  */
     22 
     23 #include "config.h"
     24 #include "core/dom/ContainerNode.h"
     25 
     26 #include "bindings/v8/ExceptionState.h"
     27 #include "bindings/v8/ExceptionStatePlaceholder.h"
     28 #include "core/dom/ChildListMutationScope.h"
     29 #include "core/dom/ContainerNodeAlgorithms.h"
     30 #include "core/dom/EventNames.h"
     31 #include "core/dom/ExceptionCode.h"
     32 #include "core/dom/FullscreenElementStack.h"
     33 #include "core/dom/MutationEvent.h"
     34 #include "core/dom/NodeRareData.h"
     35 #include "core/dom/NodeRenderStyle.h"
     36 #include "core/dom/NodeTraversal.h"
     37 #include "core/html/HTMLCollection.h"
     38 #include "core/rendering/InlineTextBox.h"
     39 #include "core/rendering/RenderText.h"
     40 #include "core/rendering/RenderTheme.h"
     41 #include "core/rendering/RenderWidget.h"
     42 #include "wtf/Vector.h"
     43 
     44 using namespace std;
     45 
     46 namespace WebCore {
     47 
     48 static void dispatchChildInsertionEvents(Node*);
     49 static void dispatchChildRemovalEvents(Node*);
     50 static void updateTreeAfterInsertion(ContainerNode*, Node*, AttachBehavior);
     51 
     52 typedef pair<NodeCallback, RefPtr<Node> > CallbackInfo;
     53 typedef Vector<CallbackInfo> NodeCallbackQueue;
     54 
     55 static NodeCallbackQueue* s_postAttachCallbackQueue;
     56 
     57 static size_t s_attachDepth;
     58 
     59 ChildNodesLazySnapshot* ChildNodesLazySnapshot::latestSnapshot = 0;
     60 
     61 #ifndef NDEBUG
     62 unsigned NoEventDispatchAssertion::s_count = 0;
     63 #endif
     64 
     65 static void collectChildrenAndRemoveFromOldParent(Node* node, NodeVector& nodes, ExceptionState& es)
     66 {
     67     if (node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) {
     68         nodes.append(node);
     69         if (ContainerNode* oldParent = node->parentNode())
     70             oldParent->removeChild(node, es);
     71         return;
     72     }
     73     getChildNodes(node, nodes);
     74     toContainerNode(node)->removeChildren();
     75 }
     76 
     77 void ContainerNode::removeDetachedChildren()
     78 {
     79     if (connectedSubframeCount()) {
     80         for (Node* child = firstChild(); child; child = child->nextSibling())
     81             child->updateAncestorConnectedSubframeCountForRemoval();
     82     }
     83     // FIXME: We should be able to ASSERT(!attached()) here: https://bugs.webkit.org/show_bug.cgi?id=107801
     84     removeDetachedChildrenInContainer<Node, ContainerNode>(this);
     85 }
     86 
     87 void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent)
     88 {
     89     NodeVector children;
     90     getChildNodes(oldParent, children);
     91 
     92     if (oldParent->document()->hasMutationObserversOfType(MutationObserver::ChildList)) {
     93         ChildListMutationScope mutation(oldParent);
     94         for (unsigned i = 0; i < children.size(); ++i)
     95             mutation.willRemoveChild(children[i].get());
     96     }
     97 
     98     // FIXME: We need to do notifyMutationObserversNodeWillDetach() for each child,
     99     // probably inside removeDetachedChildrenInContainer.
    100 
    101     oldParent->removeDetachedChildren();
    102 
    103     for (unsigned i = 0; i < children.size(); ++i) {
    104         if (children[i]->attached())
    105             children[i]->detach();
    106         // FIXME: We need a no mutation event version of adoptNode.
    107         RefPtr<Node> child = document()->adoptNode(children[i].release(), ASSERT_NO_EXCEPTION);
    108         parserAppendChild(child.get());
    109         // FIXME: Together with adoptNode above, the tree scope might get updated recursively twice
    110         // (if the document changed or oldParent was in a shadow tree, AND *this is in a shadow tree).
    111         // Can we do better?
    112         treeScope()->adoptIfNeeded(child.get());
    113         if (attached() && !child->attached())
    114             child->attach();
    115     }
    116 }
    117 
    118 ContainerNode::~ContainerNode()
    119 {
    120     if (Document* document = documentInternal())
    121         willBeDeletedFrom(document);
    122     removeDetachedChildren();
    123 }
    124 
    125 static inline bool isChildTypeAllowed(ContainerNode* newParent, Node* child)
    126 {
    127     if (!child->isDocumentFragment())
    128         return newParent->childTypeAllowed(child->nodeType());
    129 
    130     for (Node* node = child->firstChild(); node; node = node->nextSibling()) {
    131         if (!newParent->childTypeAllowed(node->nodeType()))
    132             return false;
    133     }
    134     return true;
    135 }
    136 
    137 static inline bool isInTemplateContent(const Node* node)
    138 {
    139     Document* document = node->document();
    140     return document && document == document->templateDocument();
    141 }
    142 
    143 static inline bool containsConsideringHostElements(const Node* newChild, const Node* newParent)
    144 {
    145     return (newParent->isInShadowTree() || isInTemplateContent(newParent))
    146         ? newChild->containsIncludingHostElements(newParent)
    147         : newChild->contains(newParent);
    148 }
    149 
    150 static inline bool checkAcceptChild(ContainerNode* newParent, Node* newChild, Node* oldChild, ExceptionState& es)
    151 {
    152     // Not mentioned in spec: throw NotFoundError if newChild is null
    153     if (!newChild) {
    154         es.throwDOMException(NotFoundError);
    155         return false;
    156     }
    157 
    158     // Use common case fast path if possible.
    159     if ((newChild->isElementNode() || newChild->isTextNode()) && newParent->isElementNode()) {
    160         ASSERT(!newParent->isDocumentTypeNode());
    161         ASSERT(isChildTypeAllowed(newParent, newChild));
    162         if (containsConsideringHostElements(newChild, newParent)) {
    163             es.throwDOMException(HierarchyRequestError);
    164             return false;
    165         }
    166         return true;
    167     }
    168 
    169     // This should never happen, but also protect release builds from tree corruption.
    170     ASSERT(!newChild->isPseudoElement());
    171     if (newChild->isPseudoElement()) {
    172         es.throwDOMException(HierarchyRequestError);
    173         return false;
    174     }
    175 
    176     if (newChild->inDocument() && newChild->isDocumentTypeNode()) {
    177         es.throwDOMException(HierarchyRequestError);
    178         return false;
    179     }
    180     if (containsConsideringHostElements(newChild, newParent)) {
    181         es.throwDOMException(HierarchyRequestError);
    182         return false;
    183     }
    184 
    185     if (oldChild && newParent->isDocumentNode()) {
    186         if (!toDocument(newParent)->canReplaceChild(newChild, oldChild)) {
    187             es.throwDOMException(HierarchyRequestError);
    188             return false;
    189         }
    190     } else if (!isChildTypeAllowed(newParent, newChild)) {
    191         es.throwDOMException(HierarchyRequestError);
    192         return false;
    193     }
    194 
    195     return true;
    196 }
    197 
    198 static inline bool checkAcceptChildGuaranteedNodeTypes(ContainerNode* newParent, Node* newChild, ExceptionState& es)
    199 {
    200     ASSERT(!newParent->isDocumentTypeNode());
    201     ASSERT(isChildTypeAllowed(newParent, newChild));
    202     if (newChild->contains(newParent)) {
    203         es.throwDOMException(HierarchyRequestError);
    204         return false;
    205     }
    206 
    207     return true;
    208 }
    209 
    210 static inline bool checkAddChild(ContainerNode* newParent, Node* newChild, ExceptionState& es)
    211 {
    212     return checkAcceptChild(newParent, newChild, 0, es);
    213 }
    214 
    215 static inline bool checkReplaceChild(ContainerNode* newParent, Node* newChild, Node* oldChild, ExceptionState& es)
    216 {
    217     return checkAcceptChild(newParent, newChild, oldChild, es);
    218 }
    219 
    220 void ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionState& es, AttachBehavior attachBehavior)
    221 {
    222     // Check that this node is not "floating".
    223     // If it is, it can be deleted as a side effect of sending mutation events.
    224     ASSERT(refCount() || parentOrShadowHostNode());
    225 
    226     RefPtr<Node> protect(this);
    227 
    228     // insertBefore(node, 0) is equivalent to appendChild(node)
    229     if (!refChild) {
    230         appendChild(newChild, es, attachBehavior);
    231         return;
    232     }
    233 
    234     // Make sure adding the new child is OK.
    235     if (!checkAddChild(this, newChild.get(), es))
    236         return;
    237 
    238     // NotFoundError: Raised if refChild is not a child of this node
    239     if (refChild->parentNode() != this) {
    240         es.throwDOMException(NotFoundError);
    241         return;
    242     }
    243 
    244     if (refChild->previousSibling() == newChild || refChild == newChild) // nothing to do
    245         return;
    246 
    247     RefPtr<Node> next = refChild;
    248 
    249     NodeVector targets;
    250     collectChildrenAndRemoveFromOldParent(newChild.get(), targets, es);
    251     if (es.hadException())
    252         return;
    253     if (targets.isEmpty())
    254         return;
    255 
    256     // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
    257     if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), es))
    258         return;
    259 
    260     InspectorInstrumentation::willInsertDOMNode(document(), this);
    261 
    262     ChildListMutationScope mutation(this);
    263     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
    264         Node* child = it->get();
    265 
    266         // Due to arbitrary code running in response to a DOM mutation event it's
    267         // possible that "next" is no longer a child of "this".
    268         // It's also possible that "child" has been inserted elsewhere.
    269         // In either of those cases, we'll just stop.
    270         if (next->parentNode() != this)
    271             break;
    272         if (child->parentNode())
    273             break;
    274 
    275         treeScope()->adoptIfNeeded(child);
    276 
    277         insertBeforeCommon(next.get(), child);
    278 
    279         updateTreeAfterInsertion(this, child, attachBehavior);
    280     }
    281 
    282     dispatchSubtreeModifiedEvent();
    283 }
    284 
    285 void ContainerNode::insertBeforeCommon(Node* nextChild, Node* newChild)
    286 {
    287     NoEventDispatchAssertion assertNoEventDispatch;
    288 
    289     ASSERT(newChild);
    290     ASSERT(!newChild->parentNode()); // Use insertBefore if you need to handle reparenting (and want DOM mutation events).
    291     ASSERT(!newChild->nextSibling());
    292     ASSERT(!newChild->previousSibling());
    293     ASSERT(!newChild->isShadowRoot());
    294 
    295     Node* prev = nextChild->previousSibling();
    296     ASSERT(m_lastChild != prev);
    297     nextChild->setPreviousSibling(newChild);
    298     if (prev) {
    299         ASSERT(m_firstChild != nextChild);
    300         ASSERT(prev->nextSibling() == nextChild);
    301         prev->setNextSibling(newChild);
    302     } else {
    303         ASSERT(m_firstChild == nextChild);
    304         m_firstChild = newChild;
    305     }
    306     newChild->setParentOrShadowHostNode(this);
    307     newChild->setPreviousSibling(prev);
    308     newChild->setNextSibling(nextChild);
    309 }
    310 
    311 void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChild)
    312 {
    313     ASSERT(newChild);
    314     ASSERT(nextChild);
    315     ASSERT(nextChild->parentNode() == this);
    316     ASSERT(!newChild->isDocumentFragment());
    317     ASSERT(!hasTagName(HTMLNames::templateTag));
    318 
    319     if (nextChild->previousSibling() == newChild || nextChild == newChild) // nothing to do
    320         return;
    321 
    322     if (document() != newChild->document())
    323         document()->adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
    324 
    325     insertBeforeCommon(nextChild, newChild.get());
    326 
    327     newChild->updateAncestorConnectedSubframeCountForInsertion();
    328 
    329     ChildListMutationScope(this).childAdded(newChild.get());
    330 
    331     childrenChanged(true, newChild->previousSibling(), nextChild, 1);
    332     ChildNodeInsertionNotifier(this).notify(newChild.get());
    333 }
    334 
    335 void ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionState& es, AttachBehavior attachBehavior)
    336 {
    337     // Check that this node is not "floating".
    338     // If it is, it can be deleted as a side effect of sending mutation events.
    339     ASSERT(refCount() || parentOrShadowHostNode());
    340 
    341     RefPtr<Node> protect(this);
    342 
    343     if (oldChild == newChild) // nothing to do
    344         return;
    345 
    346     if (!oldChild) {
    347         es.throwDOMException(NotFoundError);
    348         return;
    349     }
    350 
    351     // Make sure replacing the old child with the new is ok
    352     if (!checkReplaceChild(this, newChild.get(), oldChild, es))
    353         return;
    354 
    355     // NotFoundError: Raised if oldChild is not a child of this node.
    356     if (oldChild->parentNode() != this) {
    357         es.throwDOMException(NotFoundError);
    358         return;
    359     }
    360 
    361     ChildListMutationScope mutation(this);
    362 
    363     RefPtr<Node> next = oldChild->nextSibling();
    364 
    365     // Remove the node we're replacing
    366     RefPtr<Node> removedChild = oldChild;
    367     removeChild(oldChild, es);
    368     if (es.hadException())
    369         return;
    370 
    371     if (next && (next->previousSibling() == newChild || next == newChild)) // nothing to do
    372         return;
    373 
    374     // Does this one more time because removeChild() fires a MutationEvent.
    375     if (!checkReplaceChild(this, newChild.get(), oldChild, es))
    376         return;
    377 
    378     NodeVector targets;
    379     collectChildrenAndRemoveFromOldParent(newChild.get(), targets, es);
    380     if (es.hadException())
    381         return;
    382 
    383     // Does this yet another check because collectChildrenAndRemoveFromOldParent() fires a MutationEvent.
    384     if (!checkReplaceChild(this, newChild.get(), oldChild, es))
    385         return;
    386 
    387     InspectorInstrumentation::willInsertDOMNode(document(), this);
    388 
    389     // Add the new child(ren)
    390     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
    391         Node* child = it->get();
    392 
    393         // Due to arbitrary code running in response to a DOM mutation event it's
    394         // possible that "next" is no longer a child of "this".
    395         // It's also possible that "child" has been inserted elsewhere.
    396         // In either of those cases, we'll just stop.
    397         if (next && next->parentNode() != this)
    398             break;
    399         if (child->parentNode())
    400             break;
    401 
    402         treeScope()->adoptIfNeeded(child);
    403 
    404         // Add child before "next".
    405         {
    406             NoEventDispatchAssertion assertNoEventDispatch;
    407             if (next)
    408                 insertBeforeCommon(next.get(), child);
    409             else
    410                 appendChildToContainer(child, this);
    411         }
    412 
    413         updateTreeAfterInsertion(this, child, attachBehavior);
    414     }
    415 
    416     dispatchSubtreeModifiedEvent();
    417 }
    418 
    419 static void willRemoveChild(Node* child)
    420 {
    421     ASSERT(child->parentNode());
    422     ChildListMutationScope(child->parentNode()).willRemoveChild(child);
    423     child->notifyMutationObserversNodeWillDetach();
    424     dispatchChildRemovalEvents(child);
    425     child->document()->nodeWillBeRemoved(child); // e.g. mutation event listener can create a new range.
    426     ChildFrameDisconnector(child).disconnect();
    427 }
    428 
    429 static void willRemoveChildren(ContainerNode* container)
    430 {
    431     NodeVector children;
    432     getChildNodes(container, children);
    433 
    434     ChildListMutationScope mutation(container);
    435     for (NodeVector::const_iterator it = children.begin(); it != children.end(); it++) {
    436         Node* child = it->get();
    437         mutation.willRemoveChild(child);
    438         child->notifyMutationObserversNodeWillDetach();
    439 
    440         // fire removed from document mutation events.
    441         dispatchChildRemovalEvents(child);
    442     }
    443 
    444     ChildFrameDisconnector(container).disconnect(ChildFrameDisconnector::DescendantsOnly);
    445 }
    446 
    447 void ContainerNode::disconnectDescendantFrames()
    448 {
    449     ChildFrameDisconnector(this).disconnect();
    450 }
    451 
    452 void ContainerNode::removeChild(Node* oldChild, ExceptionState& es)
    453 {
    454     // Check that this node is not "floating".
    455     // If it is, it can be deleted as a side effect of sending mutation events.
    456     ASSERT(refCount() || parentOrShadowHostNode());
    457 
    458     RefPtr<Node> protect(this);
    459 
    460     // NotFoundError: Raised if oldChild is not a child of this node.
    461     if (!oldChild || oldChild->parentNode() != this) {
    462         es.throwDOMException(NotFoundError);
    463         return;
    464     }
    465 
    466     RefPtr<Node> child = oldChild;
    467 
    468     document()->removeFocusedElementOfSubtree(child.get());
    469 
    470     if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(document()))
    471         fullscreen->removeFullScreenElementOfSubtree(child.get());
    472 
    473     // Events fired when blurring currently focused node might have moved this
    474     // child into a different parent.
    475     if (child->parentNode() != this) {
    476         es.throwDOMException(NotFoundError);
    477         return;
    478     }
    479 
    480     willRemoveChild(child.get());
    481 
    482     // Mutation events might have moved this child into a different parent.
    483     if (child->parentNode() != this) {
    484         es.throwDOMException(NotFoundError);
    485         return;
    486     }
    487 
    488     {
    489         WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
    490 
    491         Node* prev = child->previousSibling();
    492         Node* next = child->nextSibling();
    493         removeBetween(prev, next, child.get());
    494         childrenChanged(false, prev, next, -1);
    495         ChildNodeRemovalNotifier(this).notify(child.get());
    496     }
    497     dispatchSubtreeModifiedEvent();
    498 }
    499 
    500 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* oldChild)
    501 {
    502     NoEventDispatchAssertion assertNoEventDispatch;
    503 
    504     ASSERT(oldChild);
    505     ASSERT(oldChild->parentNode() == this);
    506 
    507     // Remove from rendering tree
    508     if (oldChild->attached())
    509         oldChild->detach();
    510 
    511     if (nextChild)
    512         nextChild->setPreviousSibling(previousChild);
    513     if (previousChild)
    514         previousChild->setNextSibling(nextChild);
    515     if (m_firstChild == oldChild)
    516         m_firstChild = nextChild;
    517     if (m_lastChild == oldChild)
    518         m_lastChild = previousChild;
    519 
    520     oldChild->setPreviousSibling(0);
    521     oldChild->setNextSibling(0);
    522     oldChild->setParentOrShadowHostNode(0);
    523 
    524     document()->adoptIfNeeded(oldChild);
    525 }
    526 
    527 void ContainerNode::parserRemoveChild(Node* oldChild)
    528 {
    529     ASSERT(oldChild);
    530     ASSERT(oldChild->parentNode() == this);
    531     ASSERT(!oldChild->isDocumentFragment());
    532 
    533     Node* prev = oldChild->previousSibling();
    534     Node* next = oldChild->nextSibling();
    535 
    536     oldChild->updateAncestorConnectedSubframeCountForRemoval();
    537 
    538     ChildListMutationScope(this).willRemoveChild(oldChild);
    539     oldChild->notifyMutationObserversNodeWillDetach();
    540 
    541     removeBetween(prev, next, oldChild);
    542 
    543     childrenChanged(true, prev, next, -1);
    544     ChildNodeRemovalNotifier(this).notify(oldChild);
    545 }
    546 
    547 // this differs from other remove functions because it forcibly removes all the children,
    548 // regardless of read-only status or event exceptions, e.g.
    549 void ContainerNode::removeChildren()
    550 {
    551     if (!m_firstChild)
    552         return;
    553 
    554     // The container node can be removed from event handlers.
    555     RefPtr<ContainerNode> protect(this);
    556 
    557     if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(document()))
    558         fullscreen->removeFullScreenElementOfSubtree(this, true);
    559 
    560     // Do any prep work needed before actually starting to detach
    561     // and remove... e.g. stop loading frames, fire unload events.
    562     willRemoveChildren(protect.get());
    563 
    564     {
    565         // Removing focus can cause frames to load, either via events (focusout, blur)
    566         // or widget updates (e.g., for <embed>).
    567         SubframeLoadingDisabler disabler(this);
    568 
    569         // Exclude this node when looking for removed focusedElement since only
    570         // children will be removed.
    571         // This must be later than willRemoveChildren, which might change focus
    572         // state of a child.
    573         document()->removeFocusedElementOfSubtree(this, true);
    574     }
    575 
    576     document()->nodeChildrenWillBeRemoved(this);
    577 
    578     NodeVector removedChildren;
    579     {
    580         WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
    581         {
    582             NoEventDispatchAssertion assertNoEventDispatch;
    583             removedChildren.reserveInitialCapacity(childNodeCount());
    584             while (m_firstChild) {
    585                 removedChildren.append(m_firstChild);
    586                 removeBetween(0, m_firstChild->nextSibling(), m_firstChild);
    587             }
    588         }
    589 
    590         childrenChanged(false, 0, 0, -static_cast<int>(removedChildren.size()));
    591 
    592         for (size_t i = 0; i < removedChildren.size(); ++i)
    593             ChildNodeRemovalNotifier(this).notify(removedChildren[i].get());
    594     }
    595 
    596     dispatchSubtreeModifiedEvent();
    597 }
    598 
    599 void ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionState& es, AttachBehavior attachBehavior)
    600 {
    601     RefPtr<ContainerNode> protect(this);
    602 
    603     // Check that this node is not "floating".
    604     // If it is, it can be deleted as a side effect of sending mutation events.
    605     ASSERT(refCount() || parentOrShadowHostNode());
    606 
    607     // Make sure adding the new child is ok
    608     if (!checkAddChild(this, newChild.get(), es))
    609         return;
    610 
    611     if (newChild == m_lastChild) // nothing to do
    612         return;
    613 
    614     NodeVector targets;
    615     collectChildrenAndRemoveFromOldParent(newChild.get(), targets, es);
    616     if (es.hadException())
    617         return;
    618 
    619     if (targets.isEmpty())
    620         return;
    621 
    622     // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
    623     if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), es))
    624         return;
    625 
    626     InspectorInstrumentation::willInsertDOMNode(document(), this);
    627 
    628     // Now actually add the child(ren)
    629     ChildListMutationScope mutation(this);
    630     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
    631         Node* child = it->get();
    632 
    633         // If the child has a parent again, just stop what we're doing, because
    634         // that means someone is doing something with DOM mutation -- can't re-parent
    635         // a child that already has a parent.
    636         if (child->parentNode())
    637             break;
    638 
    639         treeScope()->adoptIfNeeded(child);
    640 
    641         // Append child to the end of the list
    642         {
    643             NoEventDispatchAssertion assertNoEventDispatch;
    644             appendChildToContainer(child, this);
    645         }
    646 
    647         updateTreeAfterInsertion(this, child, attachBehavior);
    648     }
    649 
    650     dispatchSubtreeModifiedEvent();
    651 }
    652 
    653 void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild)
    654 {
    655     ASSERT(newChild);
    656     ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events).
    657     ASSERT(!newChild->isDocumentFragment());
    658     ASSERT(!hasTagName(HTMLNames::templateTag));
    659 
    660     if (document() != newChild->document())
    661         document()->adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
    662 
    663     Node* last = m_lastChild;
    664     {
    665         NoEventDispatchAssertion assertNoEventDispatch;
    666         // FIXME: This method should take a PassRefPtr.
    667         appendChildToContainer(newChild.get(), this);
    668         treeScope()->adoptIfNeeded(newChild.get());
    669     }
    670 
    671     newChild->updateAncestorConnectedSubframeCountForInsertion();
    672 
    673     ChildListMutationScope(this).childAdded(newChild.get());
    674 
    675     childrenChanged(true, last, 0, 1);
    676     ChildNodeInsertionNotifier(this).notify(newChild.get());
    677 }
    678 
    679 void ContainerNode::suspendPostAttachCallbacks()
    680 {
    681     ++s_attachDepth;
    682 }
    683 
    684 void ContainerNode::resumePostAttachCallbacks()
    685 {
    686     if (s_attachDepth == 1) {
    687         RefPtr<ContainerNode> protect(this);
    688 
    689         if (s_postAttachCallbackQueue)
    690             dispatchPostAttachCallbacks();
    691     }
    692     --s_attachDepth;
    693 }
    694 
    695 void ContainerNode::queuePostAttachCallback(NodeCallback callback, Node* node)
    696 {
    697     if (!s_postAttachCallbackQueue)
    698         s_postAttachCallbackQueue = new NodeCallbackQueue;
    699     s_postAttachCallbackQueue->append(CallbackInfo(callback, node));
    700 }
    701 
    702 bool ContainerNode::postAttachCallbacksAreSuspended()
    703 {
    704     return s_attachDepth;
    705 }
    706 
    707 void ContainerNode::dispatchPostAttachCallbacks()
    708 {
    709     // We recalculate size() each time through the loop because a callback
    710     // can add more callbacks to the end of the queue.
    711     for (size_t i = 0; i < s_postAttachCallbackQueue->size(); ++i) {
    712         const CallbackInfo& info = (*s_postAttachCallbackQueue)[i];
    713         info.first(info.second.get());
    714     }
    715     s_postAttachCallbackQueue->clear();
    716 }
    717 
    718 void ContainerNode::attach(const AttachContext& context)
    719 {
    720     attachChildren(context);
    721     clearChildNeedsStyleRecalc();
    722     Node::attach(context);
    723 }
    724 
    725 void ContainerNode::detach(const AttachContext& context)
    726 {
    727     detachChildren(context);
    728     clearChildNeedsStyleRecalc();
    729     Node::detach(context);
    730 }
    731 
    732 void ContainerNode::childrenChanged(bool changedByParser, Node*, Node*, int childCountDelta)
    733 {
    734     document()->incDOMTreeVersion();
    735     if (!changedByParser && childCountDelta)
    736         document()->updateRangesAfterChildrenChanged(this);
    737     invalidateNodeListCachesInAncestors();
    738 }
    739 
    740 void ContainerNode::cloneChildNodes(ContainerNode *clone)
    741 {
    742     TrackExceptionState es;
    743     for (Node* n = firstChild(); n && !es.hadException(); n = n->nextSibling())
    744         clone->appendChild(n->cloneNode(true), es);
    745 }
    746 
    747 
    748 bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const
    749 {
    750     if (!renderer())
    751         return false;
    752     // What is this code really trying to do?
    753     RenderObject* o = renderer();
    754     RenderObject* p = o;
    755 
    756     if (!o->isInline() || o->isReplaced()) {
    757         point = o->localToAbsolute(FloatPoint(), UseTransforms);
    758         return true;
    759     }
    760 
    761     // find the next text/image child, to get a position
    762     while (o) {
    763         p = o;
    764         if (o->firstChild()) {
    765             o = o->firstChild();
    766         } else if (o->nextSibling()) {
    767             o = o->nextSibling();
    768         } else {
    769             RenderObject* next = 0;
    770             while (!next && o->parent()) {
    771                 o = o->parent();
    772                 next = o->nextSibling();
    773             }
    774             o = next;
    775 
    776             if (!o)
    777                 break;
    778         }
    779         ASSERT(o);
    780 
    781         if (!o->isInline() || o->isReplaced()) {
    782             point = o->localToAbsolute(FloatPoint(), UseTransforms);
    783             return true;
    784         }
    785 
    786         if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toRenderText(o)->firstTextBox()) {
    787             // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor
    788         } else if ((o->isText() && !o->isBR()) || o->isReplaced()) {
    789             point = FloatPoint();
    790             if (o->isText() && toRenderText(o)->firstTextBox()) {
    791                 point.move(toRenderText(o)->linesBoundingBox().x(), toRenderText(o)->firstTextBox()->root()->lineTop());
    792             } else if (o->isBox()) {
    793                 RenderBox* box = toRenderBox(o);
    794                 point.moveBy(box->location());
    795             }
    796             point = o->container()->localToAbsolute(point, UseTransforms);
    797             return true;
    798         }
    799     }
    800 
    801     // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be
    802     // at the end of the document. Scroll to the bottom. FIXME: who said anything about scrolling?
    803     if (!o && document()->view()) {
    804         point = FloatPoint(0, document()->view()->contentsHeight());
    805         return true;
    806     }
    807     return false;
    808 }
    809 
    810 bool ContainerNode::getLowerRightCorner(FloatPoint& point) const
    811 {
    812     if (!renderer())
    813         return false;
    814 
    815     RenderObject* o = renderer();
    816     if (!o->isInline() || o->isReplaced()) {
    817         RenderBox* box = toRenderBox(o);
    818         point = o->localToAbsolute(LayoutPoint(box->size()), UseTransforms);
    819         return true;
    820     }
    821 
    822     // find the last text/image child, to get a position
    823     while (o) {
    824         if (o->lastChild()) {
    825             o = o->lastChild();
    826         } else if (o->previousSibling()) {
    827             o = o->previousSibling();
    828         } else {
    829             RenderObject* prev = 0;
    830         while (!prev) {
    831             o = o->parent();
    832             if (!o)
    833                 return false;
    834             prev = o->previousSibling();
    835         }
    836         o = prev;
    837         }
    838         ASSERT(o);
    839         if (o->isText() || o->isReplaced()) {
    840             point = FloatPoint();
    841             if (o->isText()) {
    842                 RenderText* text = toRenderText(o);
    843                 IntRect linesBox = text->linesBoundingBox();
    844                 if (!linesBox.maxX() && !linesBox.maxY())
    845                     continue;
    846                 point.moveBy(linesBox.maxXMaxYCorner());
    847             } else {
    848                 RenderBox* box = toRenderBox(o);
    849                 point.moveBy(box->frameRect().maxXMaxYCorner());
    850             }
    851             point = o->container()->localToAbsolute(point, UseTransforms);
    852             return true;
    853         }
    854     }
    855     return true;
    856 }
    857 
    858 // FIXME: This override is only needed for inline anchors without an
    859 // InlineBox and it does not belong in ContainerNode as it reaches into
    860 // the render and line box trees.
    861 // https://code.google.com/p/chromium/issues/detail?id=248354
    862 LayoutRect ContainerNode::boundingBox() const
    863 {
    864     FloatPoint upperLeft, lowerRight;
    865     bool foundUpperLeft = getUpperLeftCorner(upperLeft);
    866     bool foundLowerRight = getLowerRightCorner(lowerRight);
    867 
    868     // If we've found one corner, but not the other,
    869     // then we should just return a point at the corner that we did find.
    870     if (foundUpperLeft != foundLowerRight) {
    871         if (foundUpperLeft)
    872             lowerRight = upperLeft;
    873         else
    874             upperLeft = lowerRight;
    875     }
    876 
    877     return enclosingLayoutRect(FloatRect(upperLeft, lowerRight.expandedTo(upperLeft) - upperLeft));
    878 }
    879 
    880 void ContainerNode::setFocus(bool received)
    881 {
    882     if (focused() == received)
    883         return;
    884 
    885     Node::setFocus(received);
    886 
    887     // note that we need to recalc the style
    888     setNeedsStyleRecalc();
    889 }
    890 
    891 void ContainerNode::setActive(bool down, bool pause)
    892 {
    893     if (down == active()) return;
    894 
    895     Node::setActive(down);
    896 
    897     // note that we need to recalc the style
    898     // FIXME: Move to Element
    899     if (renderer()) {
    900         if (renderStyle()->affectedByActive() || (isElementNode() && toElement(this)->childrenAffectedByActive()))
    901             setNeedsStyleRecalc();
    902         if (renderStyle()->hasAppearance())
    903             renderer()->theme()->stateChanged(renderer(), PressedState);
    904     }
    905 }
    906 
    907 void ContainerNode::setHovered(bool over)
    908 {
    909     if (over == hovered()) return;
    910 
    911     Node::setHovered(over);
    912 
    913     if (!renderer()) {
    914         // When setting hover to false, the style needs to be recalc'd even when
    915         // there's no renderer (imagine setting display:none in the :hover class,
    916         // if a nil renderer would prevent this element from recalculating its
    917         // style, it would never go back to its normal style and remain
    918         // stuck in its hovered style).
    919         if (!over)
    920             setNeedsStyleRecalc();
    921 
    922         return;
    923     }
    924 
    925     // note that we need to recalc the style
    926     // FIXME: Move to Element
    927     if (renderer()) {
    928         if (renderStyle()->affectedByHover() || (isElementNode() && toElement(this)->childrenAffectedByHover()))
    929             setNeedsStyleRecalc();
    930         if (renderer() && renderer()->style()->hasAppearance())
    931             renderer()->theme()->stateChanged(renderer(), HoverState);
    932     }
    933 }
    934 
    935 PassRefPtr<HTMLCollection> ContainerNode::children()
    936 {
    937     return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLCollection>(this, NodeChildren);
    938 }
    939 
    940 Element* ContainerNode::firstElementChild() const
    941 {
    942     return ElementTraversal::firstWithin(this);
    943 }
    944 
    945 Element* ContainerNode::lastElementChild() const
    946 {
    947     Node* n = lastChild();
    948     while (n && !n->isElementNode())
    949         n = n->previousSibling();
    950     return toElement(n);
    951 }
    952 
    953 unsigned ContainerNode::childElementCount() const
    954 {
    955     unsigned count = 0;
    956     Node* n = firstChild();
    957     while (n) {
    958         count += n->isElementNode();
    959         n = n->nextSibling();
    960     }
    961     return count;
    962 }
    963 
    964 unsigned ContainerNode::childNodeCount() const
    965 {
    966     unsigned count = 0;
    967     Node *n;
    968     for (n = firstChild(); n; n = n->nextSibling())
    969         count++;
    970     return count;
    971 }
    972 
    973 Node *ContainerNode::childNode(unsigned index) const
    974 {
    975     unsigned i;
    976     Node *n = firstChild();
    977     for (i = 0; n != 0 && i < index; i++)
    978         n = n->nextSibling();
    979     return n;
    980 }
    981 
    982 static void dispatchChildInsertionEvents(Node* child)
    983 {
    984     if (child->isInShadowTree())
    985         return;
    986 
    987     ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
    988 
    989     RefPtr<Node> c = child;
    990     RefPtr<Document> document = child->document();
    991 
    992     if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
    993         c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
    994 
    995     // dispatch the DOMNodeInsertedIntoDocument event to all descendants
    996     if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) {
    997         for (; c; c = NodeTraversal::next(c.get(), child))
    998             c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
    999     }
   1000 }
   1001 
   1002 static void dispatchChildRemovalEvents(Node* child)
   1003 {
   1004     if (child->isInShadowTree()) {
   1005         InspectorInstrumentation::willRemoveDOMNode(child->document(), child);
   1006         return;
   1007     }
   1008 
   1009     ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden());
   1010 
   1011     InspectorInstrumentation::willRemoveDOMNode(child->document(), child);
   1012 
   1013     RefPtr<Node> c = child;
   1014     RefPtr<Document> document = child->document();
   1015 
   1016     // dispatch pre-removal mutation events
   1017     if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER))
   1018         c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
   1019 
   1020     // dispatch the DOMNodeRemovedFromDocument event to all descendants
   1021     if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) {
   1022         for (; c; c = NodeTraversal::next(c.get(), child))
   1023             c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
   1024     }
   1025 }
   1026 
   1027 static void updateTreeAfterInsertion(ContainerNode* parent, Node* child, AttachBehavior attachBehavior)
   1028 {
   1029     ASSERT(parent->refCount());
   1030     ASSERT(child->refCount());
   1031 
   1032     ChildListMutationScope(parent).childAdded(child);
   1033 
   1034     parent->childrenChanged(false, child->previousSibling(), child->nextSibling(), 1);
   1035 
   1036     ChildNodeInsertionNotifier(parent).notify(child);
   1037 
   1038     // FIXME: Attachment should be the first operation in this function, but some code
   1039     // (for example, HTMLFormControlElement's autofocus support) requires this ordering.
   1040     if (parent->attached() && !child->attached() && child->parentNode() == parent) {
   1041         if (attachBehavior == AttachLazily)
   1042             child->lazyAttach();
   1043         else
   1044             child->attach();
   1045     }
   1046 
   1047     dispatchChildInsertionEvents(child);
   1048 }
   1049 
   1050 #ifndef NDEBUG
   1051 bool childAttachedAllowedWhenAttachingChildren(ContainerNode* node)
   1052 {
   1053     if (node->isShadowRoot())
   1054         return true;
   1055 
   1056     if (node->isInsertionPoint())
   1057         return true;
   1058 
   1059     if (node->isElementNode() && toElement(node)->shadow())
   1060         return true;
   1061 
   1062     return false;
   1063 }
   1064 #endif
   1065 
   1066 } // namespace WebCore
   1067