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