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