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