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