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