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