Give Node::didNotifySubtreeInsertions() a better name
[WebKit.git] / Source / WebCore / dom / ContainerNode.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 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 "ContainerNode.h"
25
26 #include "AXObjectCache.h"
27 #include "ChildListMutationScope.h"
28 #include "Chrome.h"
29 #include "ChromeClient.h"
30 #include "ClassNodeList.h"
31 #include "ContainerNodeAlgorithms.h"
32 #include "Editor.h"
33 #include "FloatRect.h"
34 #include "FrameView.h"
35 #include "HTMLFormControlsCollection.h"
36 #include "HTMLOptionsCollection.h"
37 #include "HTMLTableRowsCollection.h"
38 #include "InlineTextBox.h"
39 #include "InsertionPoint.h"
40 #include "JSLazyEventListener.h"
41 #include "JSNode.h"
42 #include "LabelsNodeList.h"
43 #include "MutationEvent.h"
44 #include "NameNodeList.h"
45 #include "NodeRareData.h"
46 #include "NodeRenderStyle.h"
47 #include "RadioNodeList.h"
48 #include "RenderBox.h"
49 #include "RenderTheme.h"
50 #include "RenderWidget.h"
51 #include "ResourceLoadScheduler.h"
52 #include "RootInlineBox.h"
53 #include "SVGDocumentExtensions.h"
54 #include "SVGElement.h"
55 #include "SVGNames.h"
56 #include "SelectorQuery.h"
57 #include "TemplateContentDocumentFragment.h"
58 #include <algorithm>
59 #include <wtf/CurrentTime.h>
60
61 namespace WebCore {
62
63 static void dispatchChildInsertionEvents(Node&);
64 static void dispatchChildRemovalEvents(Node&);
65
66 ChildNodesLazySnapshot* ChildNodesLazySnapshot::latestSnapshot = 0;
67
68 #ifndef NDEBUG
69 unsigned NoEventDispatchAssertion::s_count = 0;
70 #endif
71
72 static void collectChildrenAndRemoveFromOldParent(Node& node, NodeVector& nodes, ExceptionCode& ec)
73 {
74     if (!is<DocumentFragment>(node)) {
75         nodes.append(node);
76         if (ContainerNode* oldParent = node.parentNode())
77             oldParent->removeChild(&node, ec);
78         return;
79     }
80
81     getChildNodes(node, nodes);
82     downcast<DocumentFragment>(node).removeChildren();
83 }
84
85 // FIXME: This function must get a new name.
86 // It removes all children, not just a category called "detached children".
87 // So this name is terribly confusing.
88 void ContainerNode::removeDetachedChildren()
89 {
90     if (connectedSubframeCount()) {
91         for (Node* child = firstChild(); child; child = child->nextSibling())
92             child->updateAncestorConnectedSubframeCountForRemoval();
93     }
94     // FIXME: We should be able to ASSERT(!attached()) here: https://bugs.webkit.org/show_bug.cgi?id=107801
95     removeDetachedChildrenInContainer<Node, ContainerNode>(*this);
96 }
97
98 static inline void destroyRenderTreeIfNeeded(Node& child)
99 {
100     // FIXME: Get rid of the named flow test.
101     if (!child.renderer() && !child.isNamedFlowContentNode())
102         return;
103     if (is<Element>(child))
104         Style::detachRenderTree(downcast<Element>(child));
105     else if (is<Text>(child))
106         Style::detachTextRenderer(downcast<Text>(child));
107 }
108
109 void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent)
110 {
111     ASSERT(oldParent);
112
113     NodeVector children;
114     getChildNodes(*oldParent, children);
115
116     if (oldParent->document().hasMutationObserversOfType(MutationObserver::ChildList)) {
117         ChildListMutationScope mutation(*oldParent);
118         for (auto& child : children)
119             mutation.willRemoveChild(child);
120     }
121
122     // FIXME: We need to do notifyMutationObserversNodeWillDetach() for each child,
123     // probably inside removeDetachedChildrenInContainer.
124
125     oldParent->removeDetachedChildren();
126
127     for (auto& child : children) {
128         destroyRenderTreeIfNeeded(child);
129
130         // FIXME: We need a no mutation event version of adoptNode.
131         RefPtr<Node> adoptedChild = document().adoptNode(&child.get(), ASSERT_NO_EXCEPTION);
132         parserAppendChild(adoptedChild.get());
133         // FIXME: Together with adoptNode above, the tree scope might get updated recursively twice
134         // (if the document changed or oldParent was in a shadow tree, AND *this is in a shadow tree).
135         // Can we do better?
136         treeScope().adoptIfNeeded(adoptedChild.get());
137     }
138 }
139
140 ContainerNode::~ContainerNode()
141 {
142     if (!isDocumentNode())
143         willBeDeletedFrom(document());
144     removeDetachedChildren();
145 }
146
147 static inline bool isChildTypeAllowed(ContainerNode* newParent, Node* child)
148 {
149     if (!child->isDocumentFragment())
150         return newParent->childTypeAllowed(child->nodeType());
151
152     for (Node* node = child->firstChild(); node; node = node->nextSibling()) {
153         if (!newParent->childTypeAllowed(node->nodeType()))
154             return false;
155     }
156     return true;
157 }
158
159 static inline bool isInTemplateContent(const Node* node)
160 {
161 #if ENABLE(TEMPLATE_ELEMENT)
162     Document& document = node->document();
163     return &document == document.templateDocument();
164 #else
165     UNUSED_PARAM(node);
166     return false;
167 #endif
168 }
169
170 static inline bool containsConsideringHostElements(const Node* newChild, const Node* newParent)
171 {
172     return (newParent->isInShadowTree() || isInTemplateContent(newParent))
173         ? newChild->containsIncludingHostElements(newParent)
174         : newChild->contains(newParent);
175 }
176
177 static inline ExceptionCode checkAcceptChild(ContainerNode* newParent, Node* newChild, Node* oldChild)
178 {
179     // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
180     if (!newChild)
181         return NOT_FOUND_ERR;
182
183     // Use common case fast path if possible.
184     if ((newChild->isElementNode() || newChild->isTextNode()) && newParent->isElementNode()) {
185         ASSERT(!newParent->isReadOnlyNode());
186         ASSERT(!newParent->isDocumentTypeNode());
187         ASSERT(isChildTypeAllowed(newParent, newChild));
188         if (containsConsideringHostElements(newChild, newParent))
189             return HIERARCHY_REQUEST_ERR;
190         return 0;
191     }
192
193     // This should never happen, but also protect release builds from tree corruption.
194     ASSERT(!newChild->isPseudoElement());
195     if (newChild->isPseudoElement())
196         return HIERARCHY_REQUEST_ERR;
197
198     if (newParent->isReadOnlyNode())
199         return NO_MODIFICATION_ALLOWED_ERR;
200     if (containsConsideringHostElements(newChild, newParent))
201         return HIERARCHY_REQUEST_ERR;
202
203     if (oldChild && is<Document>(*newParent)) {
204         if (!downcast<Document>(*newParent).canReplaceChild(newChild, oldChild))
205             return HIERARCHY_REQUEST_ERR;
206     } else if (!isChildTypeAllowed(newParent, newChild))
207         return HIERARCHY_REQUEST_ERR;
208
209     return 0;
210 }
211
212 static inline bool checkAcceptChildGuaranteedNodeTypes(ContainerNode* newParent, Node* newChild, ExceptionCode& ec)
213 {
214     ASSERT(!newParent->isReadOnlyNode());
215     ASSERT(!newParent->isDocumentTypeNode());
216     ASSERT(isChildTypeAllowed(newParent, newChild));
217     if (newChild->contains(newParent)) {
218         ec = HIERARCHY_REQUEST_ERR;
219         return false;
220     }
221
222     return true;
223 }
224
225 static inline bool checkAddChild(ContainerNode* newParent, Node* newChild, ExceptionCode& ec)
226 {
227     ec = checkAcceptChild(newParent, newChild, 0);
228     if (ec)
229         return false;
230
231     return true;
232 }
233
234 static inline bool checkReplaceChild(ContainerNode* newParent, Node* newChild, Node* oldChild, ExceptionCode& ec)
235 {
236     ec = checkAcceptChild(newParent, newChild, oldChild);
237     if (ec)
238         return false;
239
240     return true;
241 }
242
243 bool ContainerNode::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec)
244 {
245     // Check that this node is not "floating".
246     // If it is, it can be deleted as a side effect of sending mutation events.
247     ASSERT(refCount() || parentOrShadowHostNode());
248
249     Ref<ContainerNode> protect(*this);
250
251     ec = 0;
252
253     // insertBefore(node, 0) is equivalent to appendChild(node)
254     if (!refChild)
255         return appendChild(newChild, ec);
256
257     // Make sure adding the new child is OK.
258     if (!checkAddChild(this, newChild.get(), ec))
259         return false;
260
261     // NOT_FOUND_ERR: Raised if refChild is not a child of this node
262     if (refChild->parentNode() != this) {
263         ec = NOT_FOUND_ERR;
264         return false;
265     }
266
267     if (refChild->previousSibling() == newChild || refChild == newChild) // nothing to do
268         return true;
269
270     Ref<Node> next(*refChild);
271
272     NodeVector targets;
273     collectChildrenAndRemoveFromOldParent(*newChild.get(), targets, ec);
274     if (ec)
275         return false;
276     if (targets.isEmpty())
277         return true;
278
279     // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
280     if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), ec))
281         return false;
282
283     InspectorInstrumentation::willInsertDOMNode(document(), *this);
284
285     ChildListMutationScope mutation(*this);
286     for (auto it = targets.begin(), end = targets.end(); it != end; ++it) {
287         Node& child = it->get();
288
289         // Due to arbitrary code running in response to a DOM mutation event it's
290         // possible that "next" is no longer a child of "this".
291         // It's also possible that "child" has been inserted elsewhere.
292         // In either of those cases, we'll just stop.
293         if (next->parentNode() != this)
294             break;
295         if (child.parentNode())
296             break;
297
298         treeScope().adoptIfNeeded(&child);
299
300         insertBeforeCommon(next, child);
301
302         updateTreeAfterInsertion(child);
303     }
304
305     dispatchSubtreeModifiedEvent();
306     return true;
307 }
308
309 void ContainerNode::insertBeforeCommon(Node& nextChild, Node& newChild)
310 {
311     NoEventDispatchAssertion assertNoEventDispatch;
312
313     ASSERT(!newChild.parentNode()); // Use insertBefore if you need to handle reparenting (and want DOM mutation events).
314     ASSERT(!newChild.nextSibling());
315     ASSERT(!newChild.previousSibling());
316     ASSERT(!newChild.isShadowRoot());
317
318     Node* prev = nextChild.previousSibling();
319     ASSERT(m_lastChild != prev);
320     nextChild.setPreviousSibling(&newChild);
321     if (prev) {
322         ASSERT(m_firstChild != &nextChild);
323         ASSERT(prev->nextSibling() == &nextChild);
324         prev->setNextSibling(&newChild);
325     } else {
326         ASSERT(m_firstChild == &nextChild);
327         m_firstChild = &newChild;
328     }
329     newChild.setParentNode(this);
330     newChild.setPreviousSibling(prev);
331     newChild.setNextSibling(&nextChild);
332 }
333
334 void ContainerNode::notifyChildInserted(Node& child, ChildChangeSource source)
335 {
336     ChildListMutationScope(*this).childAdded(child);
337
338     NodeVector postInsertionNotificationTargets;
339     ChildNodeInsertionNotifier(*this).notify(child, postInsertionNotificationTargets);
340
341     ChildChange change;
342     change.type = child.isElementNode() ? ElementInserted : child.isTextNode() ? TextInserted : NonContentsChildChanged;
343     change.previousSiblingElement = ElementTraversal::previousSibling(child);
344     change.nextSiblingElement = ElementTraversal::nextSibling(child);
345     change.source = source;
346
347     childrenChanged(change);
348
349     for (auto& target : postInsertionNotificationTargets)
350         target->finishedInsertingSubtree();
351 }
352
353 void ContainerNode::notifyChildRemoved(Node& child, Node* previousSibling, Node* nextSibling, ChildChangeSource source)
354 {
355     ChildNodeRemovalNotifier(*this).notify(child);
356
357     ChildChange change;
358     change.type = is<Element>(child) ? ElementRemoved : is<Text>(child) ? TextRemoved : NonContentsChildChanged;
359     change.previousSiblingElement = (!previousSibling || is<Element>(*previousSibling)) ? downcast<Element>(previousSibling) : ElementTraversal::previousSibling(*previousSibling);
360     change.nextSiblingElement = (!nextSibling || is<Element>(*nextSibling)) ? downcast<Element>(nextSibling) : ElementTraversal::nextSibling(*nextSibling);
361     change.source = source;
362
363     childrenChanged(change);
364 }
365
366 void ContainerNode::parserInsertBefore(PassRefPtr<Node> newChild, Node* nextChild)
367 {
368     ASSERT(newChild);
369     ASSERT(nextChild);
370     ASSERT(nextChild->parentNode() == this);
371     ASSERT(!newChild->isDocumentFragment());
372 #if ENABLE(TEMPLATE_ELEMENT)
373     ASSERT(!hasTagName(HTMLNames::templateTag));
374 #endif
375
376     if (nextChild->previousSibling() == newChild || nextChild == newChild) // nothing to do
377         return;
378
379     if (&document() != &newChild->document())
380         document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
381
382     insertBeforeCommon(*nextChild, *newChild.get());
383
384     newChild->updateAncestorConnectedSubframeCountForInsertion();
385
386     notifyChildInserted(*newChild, ChildChangeSourceParser);
387
388     newChild->setNeedsStyleRecalc(ReconstructRenderTree);
389 }
390
391 bool ContainerNode::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec)
392 {
393     // Check that this node is not "floating".
394     // If it is, it can be deleted as a side effect of sending mutation events.
395     ASSERT(refCount() || parentOrShadowHostNode());
396
397     Ref<ContainerNode> protect(*this);
398
399     ec = 0;
400
401     if (oldChild == newChild) // nothing to do
402         return true;
403
404     if (!oldChild) {
405         ec = NOT_FOUND_ERR;
406         return false;
407     }
408
409     // Make sure replacing the old child with the new is ok
410     if (!checkReplaceChild(this, newChild.get(), oldChild, ec))
411         return false;
412
413     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
414     if (oldChild->parentNode() != this) {
415         ec = NOT_FOUND_ERR;
416         return false;
417     }
418
419     ChildListMutationScope mutation(*this);
420
421     RefPtr<Node> next = oldChild->nextSibling();
422
423     // Remove the node we're replacing
424     Ref<Node> removedChild(*oldChild);
425     removeChild(oldChild, ec);
426     if (ec)
427         return false;
428
429     if (next && (next->previousSibling() == newChild || next == newChild)) // nothing to do
430         return true;
431
432     // Does this one more time because removeChild() fires a MutationEvent.
433     if (!checkReplaceChild(this, newChild.get(), oldChild, ec))
434         return false;
435
436     NodeVector targets;
437     collectChildrenAndRemoveFromOldParent(*newChild.get(), targets, ec);
438     if (ec)
439         return false;
440
441     // Does this yet another check because collectChildrenAndRemoveFromOldParent() fires a MutationEvent.
442     if (!checkReplaceChild(this, newChild.get(), oldChild, ec))
443         return false;
444
445     InspectorInstrumentation::willInsertDOMNode(document(), *this);
446
447     // Add the new child(ren)
448     for (auto it = targets.begin(), end = targets.end(); it != end; ++it) {
449         Node& child = it->get();
450
451         // Due to arbitrary code running in response to a DOM mutation event it's
452         // possible that "next" is no longer a child of "this".
453         // It's also possible that "child" has been inserted elsewhere.
454         // In either of those cases, we'll just stop.
455         if (next && next->parentNode() != this)
456             break;
457         if (child.parentNode())
458             break;
459
460         treeScope().adoptIfNeeded(&child);
461
462         // Add child before "next".
463         {
464             NoEventDispatchAssertion assertNoEventDispatch;
465             if (next)
466                 insertBeforeCommon(*next, child);
467             else
468                 appendChildToContainer(&child, *this);
469         }
470
471         updateTreeAfterInsertion(child);
472     }
473
474     dispatchSubtreeModifiedEvent();
475     return true;
476 }
477
478 void ContainerNode::willRemoveChild(Node& child)
479 {
480     ASSERT(child.parentNode());
481
482     ChildListMutationScope(*child.parentNode()).willRemoveChild(child);
483     child.notifyMutationObserversNodeWillDetach();
484     dispatchChildRemovalEvents(child);
485
486     if (child.parentNode() != this)
487         return;
488
489     child.document().nodeWillBeRemoved(child); // e.g. mutation event listener can create a new range.
490     if (is<ContainerNode>(child))
491         disconnectSubframesIfNeeded(downcast<ContainerNode>(child), RootAndDescendants);
492 }
493
494 static void willRemoveChildren(ContainerNode& container)
495 {
496     NodeVector children;
497     getChildNodes(container, children);
498
499     ChildListMutationScope mutation(container);
500     for (auto it = children.begin(); it != children.end(); ++it) {
501         Node& child = it->get();
502         mutation.willRemoveChild(child);
503         child.notifyMutationObserversNodeWillDetach();
504
505         // fire removed from document mutation events.
506         dispatchChildRemovalEvents(child);
507     }
508
509     container.document().nodeChildrenWillBeRemoved(container);
510
511     disconnectSubframesIfNeeded(container, DescendantsOnly);
512 }
513
514 void ContainerNode::disconnectDescendantFrames()
515 {
516     disconnectSubframesIfNeeded(*this, RootAndDescendants);
517 }
518
519 bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec)
520 {
521     // Check that this node is not "floating".
522     // If it is, it can be deleted as a side effect of sending mutation events.
523     ASSERT(refCount() || parentOrShadowHostNode());
524
525     Ref<ContainerNode> protect(*this);
526
527     ec = 0;
528
529     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
530     if (isReadOnlyNode()) {
531         ec = NO_MODIFICATION_ALLOWED_ERR;
532         return false;
533     }
534
535     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
536     if (!oldChild || oldChild->parentNode() != this) {
537         ec = NOT_FOUND_ERR;
538         return false;
539     }
540
541     Ref<Node> child(*oldChild);
542
543     document().removeFocusedNodeOfSubtree(child.ptr());
544
545 #if ENABLE(FULLSCREEN_API)
546     document().removeFullScreenElementOfSubtree(&child.get());
547 #endif
548
549     // Events fired when blurring currently focused node might have moved this
550     // child into a different parent.
551     if (child->parentNode() != this) {
552         ec = NOT_FOUND_ERR;
553         return false;
554     }
555
556     willRemoveChild(child);
557
558     // Mutation events might have moved this child into a different parent.
559     if (child->parentNode() != this) {
560         ec = NOT_FOUND_ERR;
561         return false;
562     }
563
564     {
565         WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
566
567         Node* prev = child->previousSibling();
568         Node* next = child->nextSibling();
569         removeBetween(prev, next, child);
570
571         notifyChildRemoved(child, prev, next, ChildChangeSourceAPI);
572     }
573
574
575     if (document().svgExtensions()) {
576         Element* shadowHost = this->shadowHost();
577         if (!shadowHost || !shadowHost->hasTagName(SVGNames::useTag))
578             document().accessSVGExtensions().rebuildElements();
579     }
580
581     dispatchSubtreeModifiedEvent();
582
583     return true;
584 }
585
586 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& oldChild)
587 {
588     InspectorInstrumentation::didRemoveDOMNode(oldChild.document(), oldChild);
589
590     NoEventDispatchAssertion assertNoEventDispatch;
591
592     ASSERT(oldChild.parentNode() == this);
593
594     destroyRenderTreeIfNeeded(oldChild);
595
596     if (nextChild)
597         nextChild->setPreviousSibling(previousChild);
598     if (previousChild)
599         previousChild->setNextSibling(nextChild);
600     if (m_firstChild == &oldChild)
601         m_firstChild = nextChild;
602     if (m_lastChild == &oldChild)
603         m_lastChild = previousChild;
604
605     oldChild.setPreviousSibling(0);
606     oldChild.setNextSibling(0);
607     oldChild.setParentNode(0);
608
609     document().adoptIfNeeded(&oldChild);
610 }
611
612 void ContainerNode::parserRemoveChild(Node& oldChild)
613 {
614     ASSERT(oldChild.parentNode() == this);
615     ASSERT(!oldChild.isDocumentFragment());
616
617     Node* prev = oldChild.previousSibling();
618     Node* next = oldChild.nextSibling();
619
620     oldChild.updateAncestorConnectedSubframeCountForRemoval();
621
622     ChildListMutationScope(*this).willRemoveChild(oldChild);
623     oldChild.notifyMutationObserversNodeWillDetach();
624
625     removeBetween(prev, next, oldChild);
626
627     notifyChildRemoved(oldChild, prev, next, ChildChangeSourceParser);
628 }
629
630 // this differs from other remove functions because it forcibly removes all the children,
631 // regardless of read-only status or event exceptions, e.g.
632 void ContainerNode::removeChildren()
633 {
634     if (!m_firstChild)
635         return;
636
637     // The container node can be removed from event handlers.
638     Ref<ContainerNode> protect(*this);
639
640     // exclude this node when looking for removed focusedNode since only children will be removed
641     document().removeFocusedNodeOfSubtree(this, true);
642
643 #if ENABLE(FULLSCREEN_API)
644     document().removeFullScreenElementOfSubtree(this, true);
645 #endif
646
647     // Do any prep work needed before actually starting to detach
648     // and remove... e.g. stop loading frames, fire unload events.
649     willRemoveChildren(*this);
650
651     {
652         WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
653         {
654             NoEventDispatchAssertion assertNoEventDispatch;
655             while (RefPtr<Node> n = m_firstChild) {
656                 removeBetween(0, m_firstChild->nextSibling(), *m_firstChild);
657                 ChildNodeRemovalNotifier(*this).notify(*n);
658             }
659         }
660
661         ChildChange change = { AllChildrenRemoved, nullptr, nullptr, ChildChangeSourceAPI };
662         childrenChanged(change);
663     }
664
665     if (document().svgExtensions()) {
666         Element* shadowHost = this->shadowHost();
667         if (!shadowHost || !shadowHost->hasTagName(SVGNames::useTag))
668             document().accessSVGExtensions().rebuildElements();
669     }
670
671     dispatchSubtreeModifiedEvent();
672 }
673
674 bool ContainerNode::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec)
675 {
676     Ref<ContainerNode> protect(*this);
677
678     // Check that this node is not "floating".
679     // If it is, it can be deleted as a side effect of sending mutation events.
680     ASSERT(refCount() || parentOrShadowHostNode());
681
682     ec = 0;
683
684     // Make sure adding the new child is ok
685     if (!checkAddChild(this, newChild.get(), ec))
686         return false;
687
688     if (newChild == m_lastChild) // nothing to do
689         return newChild;
690
691     NodeVector targets;
692     collectChildrenAndRemoveFromOldParent(*newChild.get(), targets, ec);
693     if (ec)
694         return false;
695
696     if (targets.isEmpty())
697         return true;
698
699     // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
700     if (!checkAcceptChildGuaranteedNodeTypes(this, newChild.get(), ec))
701         return false;
702
703     InspectorInstrumentation::willInsertDOMNode(document(), *this);
704
705     // Now actually add the child(ren)
706     ChildListMutationScope mutation(*this);
707     for (auto it = targets.begin(), end = targets.end(); it != end; ++it) {
708         Node& child = it->get();
709
710         // If the child has a parent again, just stop what we're doing, because
711         // that means someone is doing something with DOM mutation -- can't re-parent
712         // a child that already has a parent.
713         if (child.parentNode())
714             break;
715
716         treeScope().adoptIfNeeded(&child);
717
718         // Append child to the end of the list
719         {
720             NoEventDispatchAssertion assertNoEventDispatch;
721             appendChildToContainer(&child, *this);
722         }
723
724         updateTreeAfterInsertion(child);
725     }
726
727     dispatchSubtreeModifiedEvent();
728     return true;
729 }
730
731 void ContainerNode::parserAppendChild(PassRefPtr<Node> newChild)
732 {
733     ASSERT(newChild);
734     ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events).
735     ASSERT(!newChild->isDocumentFragment());
736 #if ENABLE(TEMPLATE_ELEMENT)
737     ASSERT(!hasTagName(HTMLNames::templateTag));
738 #endif
739
740     if (&document() != &newChild->document())
741         document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
742
743     {
744         NoEventDispatchAssertion assertNoEventDispatch;
745         // FIXME: This method should take a PassRefPtr.
746         appendChildToContainer(newChild.get(), *this);
747         treeScope().adoptIfNeeded(newChild.get());
748     }
749
750     newChild->updateAncestorConnectedSubframeCountForInsertion();
751
752     notifyChildInserted(*newChild, ChildChangeSourceParser);
753
754     newChild->setNeedsStyleRecalc(ReconstructRenderTree);
755 }
756
757 void ContainerNode::childrenChanged(const ChildChange& change)
758 {
759     document().incDOMTreeVersion();
760     if (change.source == ChildChangeSourceAPI && change.type != TextChanged)
761         document().updateRangesAfterChildrenChanged(*this);
762     invalidateNodeListAndCollectionCachesInAncestors();
763 }
764
765 void ContainerNode::cloneChildNodes(ContainerNode* clone)
766 {
767     ExceptionCode ec = 0;
768     Document& targetDocument = clone->document();
769     for (Node* child = firstChild(); child && !ec; child = child->nextSibling()) {
770         RefPtr<Node> clonedChild = child->cloneNodeInternal(targetDocument, CloningOperation::SelfWithTemplateContent);
771         clone->appendChild(clonedChild, ec);
772
773         if (!ec && is<ContainerNode>(child))
774             downcast<ContainerNode>(child)->cloneChildNodes(downcast<ContainerNode>(clonedChild.get()));
775     }
776 }
777
778 unsigned ContainerNode::countChildNodes() const
779 {
780     unsigned count = 0;
781     for (Node* child = firstChild(); child; child = child->nextSibling())
782         ++count;
783     return count;
784 }
785
786 Node* ContainerNode::traverseToChildAt(unsigned index) const
787 {
788     Node* child = firstChild();
789     for (; child && index > 0; --index)
790         child = child->nextSibling();
791     return child;
792 }
793
794 static void dispatchChildInsertionEvents(Node& child)
795 {
796     if (child.isInShadowTree())
797         return;
798
799     ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
800
801     RefPtr<Node> c = &child;
802     Ref<Document> document(child.document());
803
804     if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
805         c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
806
807     // dispatch the DOMNodeInsertedIntoDocument event to all descendants
808     if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) {
809         for (; c; c = NodeTraversal::next(*c, &child))
810             c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
811     }
812 }
813
814 static void dispatchChildRemovalEvents(Node& child)
815 {
816     if (child.isInShadowTree()) {
817         InspectorInstrumentation::willRemoveDOMNode(child.document(), child);
818         return;
819     }
820
821     ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
822
823     willCreatePossiblyOrphanedTreeByRemoval(&child);
824     InspectorInstrumentation::willRemoveDOMNode(child.document(), child);
825
826     RefPtr<Node> c = &child;
827     Ref<Document> document(child.document());
828
829     // dispatch pre-removal mutation events
830     if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER))
831         c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
832
833     // dispatch the DOMNodeRemovedFromDocument event to all descendants
834     if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) {
835         for (; c; c = NodeTraversal::next(*c, &child))
836             c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
837     }
838 }
839
840 void ContainerNode::updateTreeAfterInsertion(Node& child)
841 {
842     ASSERT(child.refCount());
843
844     notifyChildInserted(child, ChildChangeSourceAPI);
845
846     child.setNeedsStyleRecalc(ReconstructRenderTree);
847
848     dispatchChildInsertionEvents(child);
849 }
850
851 void ContainerNode::setAttributeEventListener(const AtomicString& eventType, const QualifiedName& attributeName, const AtomicString& attributeValue)
852 {
853     setAttributeEventListener(eventType, JSLazyEventListener::createForNode(*this, attributeName, attributeValue));
854 }
855
856 Element* ContainerNode::querySelector(const String& selectors, ExceptionCode& ec)
857 {
858     if (SelectorQuery* selectorQuery = document().selectorQueryForString(selectors, ec))
859         return selectorQuery->queryFirst(*this);
860     return nullptr;
861 }
862
863 RefPtr<NodeList> ContainerNode::querySelectorAll(const String& selectors, ExceptionCode& ec)
864 {
865     if (SelectorQuery* selectorQuery = document().selectorQueryForString(selectors, ec))
866         return selectorQuery->queryAll(*this);
867     return nullptr;
868 }
869
870 RefPtr<NodeList> ContainerNode::getElementsByTagName(const AtomicString& localName)
871 {
872     if (localName.isNull())
873         return 0;
874
875     if (document().isHTMLDocument())
876         return ensureRareData().ensureNodeLists().addCacheWithAtomicName<HTMLTagNodeList>(*this, localName);
877     return ensureRareData().ensureNodeLists().addCacheWithAtomicName<TagNodeList>(*this, localName);
878 }
879
880 RefPtr<NodeList> ContainerNode::getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName)
881 {
882     if (localName.isNull())
883         return 0;
884
885     if (namespaceURI == starAtom)
886         return getElementsByTagName(localName);
887
888     return ensureRareData().ensureNodeLists().addCacheWithQualifiedName(*this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localName);
889 }
890
891 RefPtr<NodeList> ContainerNode::getElementsByName(const String& elementName)
892 {
893     return ensureRareData().ensureNodeLists().addCacheWithAtomicName<NameNodeList>(*this, elementName);
894 }
895
896 RefPtr<NodeList> ContainerNode::getElementsByClassName(const AtomicString& classNames)
897 {
898     return ensureRareData().ensureNodeLists().addCacheWithAtomicName<ClassNodeList>(*this, classNames);
899 }
900
901 RefPtr<RadioNodeList> ContainerNode::radioNodeList(const AtomicString& name)
902 {
903     ASSERT(hasTagName(HTMLNames::formTag) || hasTagName(HTMLNames::fieldsetTag));
904     return ensureRareData().ensureNodeLists().addCacheWithAtomicName<RadioNodeList>(*this, name);
905 }
906
907 Ref<HTMLCollection> ContainerNode::children()
908 {
909     return ensureCachedHTMLCollection(NodeChildren);
910 }
911
912 Element* ContainerNode::firstElementChild() const
913 {
914     return ElementTraversal::firstChild(*this);
915 }
916
917 Element* ContainerNode::lastElementChild() const
918 {
919     return ElementTraversal::lastChild(*this);
920 }
921
922 unsigned ContainerNode::childElementCount() const
923 {
924     auto children = childrenOfType<Element>(*this);
925     return std::distance(children.begin(), children.end());
926 }
927
928 Ref<HTMLCollection> ContainerNode::ensureCachedHTMLCollection(CollectionType type)
929 {
930     if (HTMLCollection* collection = cachedHTMLCollection(type))
931         return *collection;
932
933     if (type == TableRows)
934         return ensureRareData().ensureNodeLists().addCachedCollection<HTMLTableRowsCollection>(downcast<HTMLTableElement>(*this), type);
935     else if (type == SelectOptions)
936         return ensureRareData().ensureNodeLists().addCachedCollection<HTMLOptionsCollection>(downcast<HTMLSelectElement>(*this), type);
937     else if (type == FormControls) {
938         ASSERT(hasTagName(HTMLNames::formTag) || hasTagName(HTMLNames::fieldsetTag));
939         return ensureRareData().ensureNodeLists().addCachedCollection<HTMLFormControlsCollection>(*this, type);
940     }
941     return ensureRareData().ensureNodeLists().addCachedCollection<HTMLCollection>(*this, type);
942 }
943
944 HTMLCollection* ContainerNode::cachedHTMLCollection(CollectionType type)
945 {
946     return hasRareData() && rareData()->nodeLists() ? rareData()->nodeLists()->cachedCollection<HTMLCollection>(type) : nullptr;
947 }
948
949 } // namespace WebCore