Render tree teardown should be iterative
[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 "HTMLSlotElement.h"
39 #include "HTMLTableRowsCollection.h"
40 #include "InlineTextBox.h"
41 #include "JSNode.h"
42 #include "LabelsNodeList.h"
43 #include "MutationEvent.h"
44 #include "NameNodeList.h"
45 #include "NoEventDispatchAssertion.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 "RenderTreeUpdater.h"
53 #include "RenderWidget.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;
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(*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() && !is<HTMLSlotElement>(child))
104         return;
105     if (is<Element>(child))
106         RenderTreeUpdater::tearDownRenderers(downcast<Element>(child));
107     else if (is<Text>(child))
108         RenderTreeUpdater::tearDownRenderer(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);
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, const Node* refChild, Document::AcceptChildOperation operation)
180 {
181     // Use common case fast path if possible.
182     if ((newChild.isElementNode() || newChild.isTextNode()) && newParent.isElementNode()) {
183         ASSERT(!newParent.isDocumentTypeNode());
184         ASSERT(isChildTypeAllowed(newParent, newChild));
185         if (containsConsideringHostElements(newChild, newParent))
186             return HIERARCHY_REQUEST_ERR;
187         return 0;
188     }
189
190     // This should never happen, but also protect release builds from tree corruption.
191     ASSERT(!newChild.isPseudoElement());
192     if (newChild.isPseudoElement())
193         return HIERARCHY_REQUEST_ERR;
194
195     if (containsConsideringHostElements(newChild, newParent))
196         return HIERARCHY_REQUEST_ERR;
197
198     if (is<Document>(newParent)) {
199         if (!downcast<Document>(newParent).canAcceptChild(newChild, refChild, operation))
200             return HIERARCHY_REQUEST_ERR;
201     } else if (!isChildTypeAllowed(newParent, newChild))
202         return HIERARCHY_REQUEST_ERR;
203
204     return 0;
205 }
206
207 static inline bool checkAcceptChildGuaranteedNodeTypes(ContainerNode& newParent, Node& newChild, ExceptionCode& ec)
208 {
209     ASSERT(!newParent.isDocumentTypeNode());
210     ASSERT(isChildTypeAllowed(newParent, newChild));
211     if (newChild.contains(&newParent)) {
212         ec = HIERARCHY_REQUEST_ERR;
213         return false;
214     }
215
216     return true;
217 }
218
219 // https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
220 bool ContainerNode::ensurePreInsertionValidity(Node& newChild, Node* refChild, ExceptionCode& ec)
221 {
222     ec = checkAcceptChild(*this, newChild, refChild, Document::AcceptChildOperation::InsertOrAdd);
223     return !ec;
224 }
225
226 // https://dom.spec.whatwg.org/#concept-node-replace
227 static inline bool checkPreReplacementValidity(ContainerNode& newParent, Node& newChild, Node& oldChild, ExceptionCode& ec)
228 {
229     ec = checkAcceptChild(newParent, newChild, &oldChild, Document::AcceptChildOperation::Replace);
230     return !ec;
231 }
232
233 bool ContainerNode::insertBefore(Ref<Node>&& newChild, Node* refChild, ExceptionCode& ec)
234 {
235     // Check that this node is not "floating".
236     // If it is, it can be deleted as a side effect of sending mutation events.
237     ASSERT(refCount() || parentOrShadowHostNode());
238
239     Ref<ContainerNode> protect(*this);
240
241     ec = 0;
242
243     // insertBefore(node, 0) is equivalent to appendChild(node)
244     if (!refChild)
245         return appendChild(WTFMove(newChild), ec);
246
247     // Make sure adding the new child is OK.
248     if (!ensurePreInsertionValidity(newChild, refChild, ec))
249         return false;
250
251     // NOT_FOUND_ERR: Raised if refChild is not a child of this node
252     if (refChild->parentNode() != this) {
253         ec = NOT_FOUND_ERR;
254         return false;
255     }
256
257     if (refChild->previousSibling() == newChild.ptr() || refChild == newChild.ptr()) // nothing to do
258         return true;
259
260     Ref<Node> next(*refChild);
261
262     NodeVector targets;
263     collectChildrenAndRemoveFromOldParent(newChild, targets, ec);
264     if (ec)
265         return false;
266     if (targets.isEmpty())
267         return true;
268
269     // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
270     if (!checkAcceptChildGuaranteedNodeTypes(*this, newChild, ec))
271         return false;
272
273     InspectorInstrumentation::willInsertDOMNode(document(), *this);
274
275     ChildListMutationScope mutation(*this);
276     for (auto& child : targets) {
277         // Due to arbitrary code running in response to a DOM mutation event it's
278         // possible that "next" is no longer a child of "this".
279         // It's also possible that "child" has been inserted elsewhere.
280         // In either of those cases, we'll just stop.
281         if (next->parentNode() != this)
282             break;
283         if (child->parentNode())
284             break;
285
286         treeScope().adoptIfNeeded(child.ptr());
287
288         insertBeforeCommon(next, child);
289
290         updateTreeAfterInsertion(child);
291     }
292
293     dispatchSubtreeModifiedEvent();
294     return true;
295 }
296
297 void ContainerNode::insertBeforeCommon(Node& nextChild, Node& newChild)
298 {
299     NoEventDispatchAssertion assertNoEventDispatch;
300
301     ASSERT(!newChild.parentNode()); // Use insertBefore if you need to handle reparenting (and want DOM mutation events).
302     ASSERT(!newChild.nextSibling());
303     ASSERT(!newChild.previousSibling());
304     ASSERT(!newChild.isShadowRoot());
305
306     Node* prev = nextChild.previousSibling();
307     ASSERT(m_lastChild != prev);
308     nextChild.setPreviousSibling(&newChild);
309     if (prev) {
310         ASSERT(m_firstChild != &nextChild);
311         ASSERT(prev->nextSibling() == &nextChild);
312         prev->setNextSibling(&newChild);
313     } else {
314         ASSERT(m_firstChild == &nextChild);
315         m_firstChild = &newChild;
316     }
317     newChild.setParentNode(this);
318     newChild.setPreviousSibling(prev);
319     newChild.setNextSibling(&nextChild);
320 }
321
322 void ContainerNode::appendChildCommon(Node& child)
323 {
324     child.setParentNode(this);
325
326     if (m_lastChild) {
327         child.setPreviousSibling(m_lastChild);
328         m_lastChild->setNextSibling(&child);
329     } else
330         m_firstChild = &child;
331
332     m_lastChild = &child;
333 }
334
335 void ContainerNode::notifyChildInserted(Node& child, ChildChangeSource source)
336 {
337     ChildListMutationScope(*this).childAdded(child);
338
339     NodeVector postInsertionNotificationTargets;
340     notifyChildNodeInserted(*this, child, postInsertionNotificationTargets);
341
342     ChildChange change;
343     change.type = child.isElementNode() ? ElementInserted : child.isTextNode() ? TextInserted : NonContentsChildChanged;
344     change.previousSiblingElement = ElementTraversal::previousSibling(child);
345     change.nextSiblingElement = ElementTraversal::nextSibling(child);
346     change.source = source;
347
348     childrenChanged(change);
349
350     for (auto& target : postInsertionNotificationTargets)
351         target->finishedInsertingSubtree();
352 }
353
354 void ContainerNode::notifyChildRemoved(Node& child, Node* previousSibling, Node* nextSibling, ChildChangeSource source)
355 {
356     notifyChildNodeRemoved(*this, child);
357
358     ChildChange change;
359     change.type = is<Element>(child) ? ElementRemoved : is<Text>(child) ? TextRemoved : NonContentsChildChanged;
360     change.previousSiblingElement = (!previousSibling || is<Element>(*previousSibling)) ? downcast<Element>(previousSibling) : ElementTraversal::previousSibling(*previousSibling);
361     change.nextSiblingElement = (!nextSibling || is<Element>(*nextSibling)) ? downcast<Element>(nextSibling) : ElementTraversal::nextSibling(*nextSibling);
362     change.source = source;
363
364     childrenChanged(change);
365 }
366
367 void ContainerNode::parserInsertBefore(Ref<Node>&& newChild, Node& nextChild)
368 {
369     ASSERT(nextChild.parentNode() == this);
370     ASSERT(!newChild->isDocumentFragment());
371 #if ENABLE(TEMPLATE_ELEMENT)
372     ASSERT(!hasTagName(HTMLNames::templateTag));
373 #endif
374
375     if (nextChild.previousSibling() == newChild.ptr() || &nextChild == newChild.ptr()) // nothing to do
376         return;
377
378     if (&document() != &newChild->document())
379         document().adoptNode(newChild.ptr(), ASSERT_NO_EXCEPTION);
380
381     insertBeforeCommon(nextChild, newChild);
382
383     newChild->updateAncestorConnectedSubframeCountForInsertion();
384
385     notifyChildInserted(newChild, ChildChangeSourceParser);
386
387     newChild->setNeedsStyleRecalc(ReconstructRenderTree);
388 }
389
390 bool ContainerNode::replaceChild(Ref<Node>&& newChild, Node& oldChild, ExceptionCode& ec)
391 {
392     // Check that this node is not "floating".
393     // If it is, it can be deleted as a side effect of sending mutation events.
394     ASSERT(refCount() || parentOrShadowHostNode());
395
396     Ref<ContainerNode> protect(*this);
397
398     ec = 0;
399
400     if (&oldChild == newChild.ptr()) // nothing to do
401         return true;
402
403     // Make sure replacing the old child with the new is ok
404     if (!checkPreReplacementValidity(*this, newChild, oldChild, ec))
405         return false;
406
407     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
408     if (oldChild.parentNode() != this) {
409         ec = NOT_FOUND_ERR;
410         return false;
411     }
412
413     ChildListMutationScope mutation(*this);
414
415     RefPtr<Node> refChild = oldChild.nextSibling();
416     if (refChild.get() == newChild.ptr())
417         refChild = refChild->nextSibling();
418
419     NodeVector targets;
420     collectChildrenAndRemoveFromOldParent(newChild, targets, ec);
421     if (ec)
422         return false;
423
424     // Does this one more time because collectChildrenAndRemoveFromOldParent() fires a MutationEvent.
425     if (!checkPreReplacementValidity(*this, newChild, oldChild, ec))
426         return false;
427
428     // Remove the node we're replacing.
429     Ref<Node> protectOldChild(oldChild);
430     removeChild(oldChild, ec);
431     if (ec)
432         return false;
433
434     // Does this one more time because removeChild() fires a MutationEvent.
435     if (!checkPreReplacementValidity(*this, newChild, oldChild, ec))
436         return false;
437
438     InspectorInstrumentation::willInsertDOMNode(document(), *this);
439
440     // Add the new child(ren).
441     for (auto& child : targets) {
442         // Due to arbitrary code running in response to a DOM mutation event it's
443         // possible that "refChild" is no longer a child of "this".
444         // It's also possible that "child" has been inserted elsewhere.
445         // In either of those cases, we'll just stop.
446         if (refChild && refChild->parentNode() != this)
447             break;
448         if (child->parentNode())
449             break;
450
451         treeScope().adoptIfNeeded(child.ptr());
452
453         {
454             NoEventDispatchAssertion assertNoEventDispatch;
455             if (refChild)
456                 insertBeforeCommon(*refChild, child.get());
457             else
458                 appendChildCommon(child);
459         }
460
461         updateTreeAfterInsertion(child.get());
462     }
463
464     dispatchSubtreeModifiedEvent();
465     return true;
466 }
467
468 void ContainerNode::willRemoveChild(Node& child)
469 {
470     ASSERT(child.parentNode());
471
472     ChildListMutationScope(*child.parentNode()).willRemoveChild(child);
473     child.notifyMutationObserversNodeWillDetach();
474     dispatchChildRemovalEvents(child);
475
476     if (child.parentNode() != this)
477         return;
478
479     child.document().nodeWillBeRemoved(child); // e.g. mutation event listener can create a new range.
480     if (is<ContainerNode>(child))
481         disconnectSubframesIfNeeded(downcast<ContainerNode>(child), RootAndDescendants);
482 }
483
484 static void willRemoveChildren(ContainerNode& container)
485 {
486     NodeVector children;
487     getChildNodes(container, children);
488
489     ChildListMutationScope mutation(container);
490     for (auto& child : children) {
491         mutation.willRemoveChild(child.get());
492         child->notifyMutationObserversNodeWillDetach();
493
494         // fire removed from document mutation events.
495         dispatchChildRemovalEvents(child.get());
496     }
497
498     container.document().nodeChildrenWillBeRemoved(container);
499
500     disconnectSubframesIfNeeded(container, DescendantsOnly);
501 }
502
503 void ContainerNode::disconnectDescendantFrames()
504 {
505     disconnectSubframesIfNeeded(*this, RootAndDescendants);
506 }
507
508 bool ContainerNode::removeChild(Node& oldChild, ExceptionCode& ec)
509 {
510     // Check that this node is not "floating".
511     // If it is, it can be deleted as a side effect of sending mutation events.
512     ASSERT(refCount() || parentOrShadowHostNode());
513
514     Ref<ContainerNode> protect(*this);
515
516     ec = 0;
517
518     // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
519     if (oldChild.parentNode() != this) {
520         ec = NOT_FOUND_ERR;
521         return false;
522     }
523
524     Ref<Node> child(oldChild);
525
526     document().removeFocusedNodeOfSubtree(child.ptr());
527
528 #if ENABLE(FULLSCREEN_API)
529     document().removeFullScreenElementOfSubtree(&child.get());
530 #endif
531
532     // Events fired when blurring currently focused node might have moved this
533     // child into a different parent.
534     if (child->parentNode() != this) {
535         ec = NOT_FOUND_ERR;
536         return false;
537     }
538
539     willRemoveChild(child);
540
541     // Mutation events might have moved this child into a different parent.
542     if (child->parentNode() != this) {
543         ec = NOT_FOUND_ERR;
544         return false;
545     }
546
547     {
548         WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
549
550         Node* prev = child->previousSibling();
551         Node* next = child->nextSibling();
552         removeBetween(prev, next, child);
553
554         notifyChildRemoved(child, prev, next, ChildChangeSourceAPI);
555     }
556
557
558     if (document().svgExtensions()) {
559         Element* shadowHost = this->shadowHost();
560         if (!shadowHost || !shadowHost->hasTagName(SVGNames::useTag))
561             document().accessSVGExtensions().rebuildElements();
562     }
563
564     dispatchSubtreeModifiedEvent();
565
566     return true;
567 }
568
569 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& oldChild)
570 {
571     InspectorInstrumentation::didRemoveDOMNode(oldChild.document(), oldChild);
572
573     NoEventDispatchAssertion assertNoEventDispatch;
574
575     ASSERT(oldChild.parentNode() == this);
576
577     destroyRenderTreeIfNeeded(oldChild);
578
579     if (nextChild)
580         nextChild->setPreviousSibling(previousChild);
581     if (previousChild)
582         previousChild->setNextSibling(nextChild);
583     if (m_firstChild == &oldChild)
584         m_firstChild = nextChild;
585     if (m_lastChild == &oldChild)
586         m_lastChild = previousChild;
587
588     oldChild.setPreviousSibling(nullptr);
589     oldChild.setNextSibling(nullptr);
590     oldChild.setParentNode(nullptr);
591
592     document().adoptIfNeeded(&oldChild);
593 }
594
595 void ContainerNode::parserRemoveChild(Node& oldChild)
596 {
597     ASSERT(oldChild.parentNode() == this);
598     ASSERT(!oldChild.isDocumentFragment());
599
600     Node* prev = oldChild.previousSibling();
601     Node* next = oldChild.nextSibling();
602
603     oldChild.updateAncestorConnectedSubframeCountForRemoval();
604
605     ChildListMutationScope(*this).willRemoveChild(oldChild);
606     oldChild.notifyMutationObserversNodeWillDetach();
607
608     removeBetween(prev, next, oldChild);
609
610     notifyChildRemoved(oldChild, prev, next, ChildChangeSourceParser);
611 }
612
613 // this differs from other remove functions because it forcibly removes all the children,
614 // regardless of read-only status or event exceptions, e.g.
615 void ContainerNode::removeChildren()
616 {
617     if (!m_firstChild)
618         return;
619
620     // The container node can be removed from event handlers.
621     Ref<ContainerNode> protect(*this);
622
623     // exclude this node when looking for removed focusedNode since only children will be removed
624     document().removeFocusedNodeOfSubtree(this, true);
625
626 #if ENABLE(FULLSCREEN_API)
627     document().removeFullScreenElementOfSubtree(this, true);
628 #endif
629
630     // Do any prep work needed before actually starting to detach
631     // and remove... e.g. stop loading frames, fire unload events.
632     willRemoveChildren(*this);
633
634     {
635         WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
636         {
637             NoEventDispatchAssertion assertNoEventDispatch;
638             while (RefPtr<Node> child = m_firstChild) {
639                 removeBetween(0, child->nextSibling(), *child);
640                 notifyChildNodeRemoved(*this, *child);
641             }
642         }
643
644         ChildChange change = { AllChildrenRemoved, nullptr, nullptr, ChildChangeSourceAPI };
645         childrenChanged(change);
646     }
647
648     if (document().svgExtensions()) {
649         Element* shadowHost = this->shadowHost();
650         if (!shadowHost || !shadowHost->hasTagName(SVGNames::useTag))
651             document().accessSVGExtensions().rebuildElements();
652     }
653
654     dispatchSubtreeModifiedEvent();
655 }
656
657 bool ContainerNode::appendChild(Ref<Node>&& newChild, ExceptionCode& ec)
658 {
659     Ref<ContainerNode> protect(*this);
660
661     // Check that this node is not "floating".
662     // If it is, it can be deleted as a side effect of sending mutation events.
663     ASSERT(refCount() || parentOrShadowHostNode());
664
665     ec = 0;
666
667     // Make sure adding the new child is ok
668     if (!ensurePreInsertionValidity(newChild, nullptr, ec))
669         return false;
670
671     if (newChild.ptr() == m_lastChild) // nothing to do
672         return true;
673
674     NodeVector targets;
675     collectChildrenAndRemoveFromOldParent(newChild, targets, ec);
676     if (ec)
677         return false;
678
679     if (targets.isEmpty())
680         return true;
681
682     // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
683     if (!checkAcceptChildGuaranteedNodeTypes(*this, newChild, ec))
684         return false;
685
686     InspectorInstrumentation::willInsertDOMNode(document(), *this);
687
688     // Now actually add the child(ren)
689     ChildListMutationScope mutation(*this);
690     for (auto& child : targets) {
691         // If the child has a parent again, just stop what we're doing, because
692         // that means someone is doing something with DOM mutation -- can't re-parent
693         // a child that already has a parent.
694         if (child->parentNode())
695             break;
696
697         treeScope().adoptIfNeeded(child.ptr());
698
699         // Append child to the end of the list
700         {
701             NoEventDispatchAssertion assertNoEventDispatch;
702             appendChildCommon(child);
703         }
704
705         updateTreeAfterInsertion(child.get());
706     }
707
708     dispatchSubtreeModifiedEvent();
709     return true;
710 }
711
712 void ContainerNode::parserAppendChild(Ref<Node>&& newChild)
713 {
714     ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events).
715     ASSERT(!newChild->isDocumentFragment());
716 #if ENABLE(TEMPLATE_ELEMENT)
717     ASSERT(!hasTagName(HTMLNames::templateTag));
718 #endif
719
720     if (&document() != &newChild->document())
721         document().adoptNode(newChild.ptr(), ASSERT_NO_EXCEPTION);
722
723     {
724         NoEventDispatchAssertion assertNoEventDispatch;
725         // FIXME: This method should take a PassRefPtr.
726         appendChildCommon(newChild);
727         treeScope().adoptIfNeeded(newChild.ptr());
728     }
729
730     newChild->updateAncestorConnectedSubframeCountForInsertion();
731
732     notifyChildInserted(newChild, ChildChangeSourceParser);
733
734     newChild->setNeedsStyleRecalc(ReconstructRenderTree);
735 }
736
737 void ContainerNode::childrenChanged(const ChildChange& change)
738 {
739     document().incDOMTreeVersion();
740     if (change.source == ChildChangeSourceAPI && change.type != TextChanged)
741         document().updateRangesAfterChildrenChanged(*this);
742     invalidateNodeListAndCollectionCachesInAncestors();
743 }
744
745 void ContainerNode::cloneChildNodes(ContainerNode& clone)
746 {
747     ExceptionCode ec = 0;
748     Document& targetDocument = clone.document();
749     for (Node* child = firstChild(); child && !ec; child = child->nextSibling()) {
750         Ref<Node> clonedChild = child->cloneNodeInternal(targetDocument, CloningOperation::SelfWithTemplateContent);
751         clone.appendChild(clonedChild.copyRef(), ec);
752
753         if (!ec && is<ContainerNode>(*child))
754             downcast<ContainerNode>(*child).cloneChildNodes(downcast<ContainerNode>(clonedChild.get()));
755     }
756 }
757
758 unsigned ContainerNode::countChildNodes() const
759 {
760     unsigned count = 0;
761     for (Node* child = firstChild(); child; child = child->nextSibling())
762         ++count;
763     return count;
764 }
765
766 Node* ContainerNode::traverseToChildAt(unsigned index) const
767 {
768     Node* child = firstChild();
769     for (; child && index > 0; --index)
770         child = child->nextSibling();
771     return child;
772 }
773
774 static void dispatchChildInsertionEvents(Node& child)
775 {
776     if (child.isInShadowTree())
777         return;
778
779     ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
780
781     RefPtr<Node> c = &child;
782     Ref<Document> document(child.document());
783
784     if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
785         c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedEvent, true, c->parentNode()));
786
787     // dispatch the DOMNodeInsertedIntoDocument event to all descendants
788     if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) {
789         for (; c; c = NodeTraversal::next(*c, &child))
790             c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeInsertedIntoDocumentEvent, false));
791     }
792 }
793
794 static void dispatchChildRemovalEvents(Node& child)
795 {
796     if (child.isInShadowTree()) {
797         InspectorInstrumentation::willRemoveDOMNode(child.document(), child);
798         return;
799     }
800
801     ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden());
802
803     willCreatePossiblyOrphanedTreeByRemoval(&child);
804     InspectorInstrumentation::willRemoveDOMNode(child.document(), child);
805
806     RefPtr<Node> c = &child;
807     Ref<Document> document(child.document());
808
809     // dispatch pre-removal mutation events
810     if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER))
811         c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedEvent, true, c->parentNode()));
812
813     // dispatch the DOMNodeRemovedFromDocument event to all descendants
814     if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) {
815         for (; c; c = NodeTraversal::next(*c, &child))
816             c->dispatchScopedEvent(MutationEvent::create(eventNames().DOMNodeRemovedFromDocumentEvent, false));
817     }
818 }
819
820 void ContainerNode::updateTreeAfterInsertion(Node& child)
821 {
822     ASSERT(child.refCount());
823
824     notifyChildInserted(child, ChildChangeSourceAPI);
825
826     child.setNeedsStyleRecalc(ReconstructRenderTree);
827
828     dispatchChildInsertionEvents(child);
829 }
830
831 Element* ContainerNode::querySelector(const String& selectors, ExceptionCode& ec)
832 {
833     if (SelectorQuery* selectorQuery = document().selectorQueryForString(selectors, ec))
834         return selectorQuery->queryFirst(*this);
835     return nullptr;
836 }
837
838 RefPtr<NodeList> ContainerNode::querySelectorAll(const String& selectors, ExceptionCode& ec)
839 {
840     if (SelectorQuery* selectorQuery = document().selectorQueryForString(selectors, ec))
841         return selectorQuery->queryAll(*this);
842     return nullptr;
843 }
844
845 Ref<HTMLCollection> ContainerNode::getElementsByTagName(const AtomicString& localName)
846 {
847     ASSERT(!localName.isNull());
848
849     if (document().isHTMLDocument())
850         return ensureRareData().ensureNodeLists().addCachedCollection<HTMLTagCollection>(*this, ByHTMLTag, localName);
851     return ensureRareData().ensureNodeLists().addCachedCollection<TagCollection>(*this, ByTag, localName);
852 }
853
854 RefPtr<NodeList> ContainerNode::getElementsByTagNameForObjC(const AtomicString& localName)
855 {
856     if (localName.isNull())
857         return nullptr;
858
859     return getElementsByTagName(localName);
860 }
861
862 Ref<HTMLCollection> ContainerNode::getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName)
863 {
864     ASSERT(!localName.isNull());
865
866     if (namespaceURI == starAtom)
867         return getElementsByTagName(localName);
868
869     return ensureRareData().ensureNodeLists().addCachedCollectionWithQualifiedName(*this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localName);
870 }
871
872 RefPtr<NodeList> ContainerNode::getElementsByTagNameNSForObjC(const AtomicString& namespaceURI, const AtomicString& localName)
873 {
874     if (localName.isNull())
875         return nullptr;
876
877     return getElementsByTagNameNS(namespaceURI, localName);
878 }
879
880 Ref<NodeList> ContainerNode::getElementsByName(const String& elementName)
881 {
882     return ensureRareData().ensureNodeLists().addCacheWithAtomicName<NameNodeList>(*this, elementName);
883 }
884
885 Ref<HTMLCollection> ContainerNode::getElementsByClassName(const AtomicString& classNames)
886 {
887     return ensureRareData().ensureNodeLists().addCachedCollection<ClassCollection>(*this, ByClass, classNames);
888 }
889
890 Ref<NodeList> ContainerNode::getElementsByClassNameForObjC(const AtomicString& classNames)
891 {
892     return getElementsByClassName(classNames);
893 }
894
895 Ref<RadioNodeList> ContainerNode::radioNodeList(const AtomicString& name)
896 {
897     ASSERT(hasTagName(HTMLNames::formTag) || hasTagName(HTMLNames::fieldsetTag));
898     return ensureRareData().ensureNodeLists().addCacheWithAtomicName<RadioNodeList>(*this, name);
899 }
900
901 Ref<HTMLCollection> ContainerNode::children()
902 {
903     return ensureRareData().ensureNodeLists().addCachedCollection<GenericCachedHTMLCollection<CollectionTypeTraits<NodeChildren>::traversalType>>(*this, NodeChildren);
904 }
905
906 Element* ContainerNode::firstElementChild() const
907 {
908     return ElementTraversal::firstChild(*this);
909 }
910
911 Element* ContainerNode::lastElementChild() const
912 {
913     return ElementTraversal::lastChild(*this);
914 }
915
916 unsigned ContainerNode::childElementCount() const
917 {
918     auto children = childrenOfType<Element>(*this);
919     return std::distance(children.begin(), children.end());
920 }
921
922 void ContainerNode::append(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
923 {
924     RefPtr<Node> node = convertNodesOrStringsIntoNode(*this, WTFMove(nodeOrStringVector), ec);
925     if (ec || !node)
926         return;
927
928     appendChild(node.releaseNonNull(), ec);
929 }
930
931 void ContainerNode::prepend(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
932 {
933     RefPtr<Node> node = convertNodesOrStringsIntoNode(*this, WTFMove(nodeOrStringVector), ec);
934     if (ec || !node)
935         return;
936
937     insertBefore(node.releaseNonNull(), firstChild(), ec);
938 }
939
940 HTMLCollection* ContainerNode::cachedHTMLCollection(CollectionType type)
941 {
942     return hasRareData() && rareData()->nodeLists() ? rareData()->nodeLists()->cachedCollection<HTMLCollection>(type) : nullptr;
943 }
944
945 } // namespace WebCore