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