Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / 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, 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 "core/dom/ContainerNode.h"
25
26 #include "bindings/core/v8/ExceptionState.h"
27 #include "core/dom/ChildFrameDisconnector.h"
28 #include "core/dom/ChildListMutationScope.h"
29 #include "core/dom/ClassCollection.h"
30 #include "core/dom/ElementTraversal.h"
31 #include "core/dom/ExceptionCode.h"
32 #include "core/dom/NameNodeList.h"
33 #include "core/dom/NodeChildRemovalTracker.h"
34 #include "core/dom/NodeRareData.h"
35 #include "core/dom/NodeRenderStyle.h"
36 #include "core/dom/NodeTraversal.h"
37 #include "core/dom/SelectorQuery.h"
38 #include "core/dom/StaticNodeList.h"
39 #include "core/dom/StyleEngine.h"
40 #include "core/dom/shadow/ElementShadow.h"
41 #include "core/dom/shadow/ShadowRoot.h"
42 #include "core/events/MutationEvent.h"
43 #include "core/html/HTMLCollection.h"
44 #include "core/html/HTMLFrameOwnerElement.h"
45 #include "core/html/HTMLTagCollection.h"
46 #include "core/html/RadioNodeList.h"
47 #include "core/inspector/InspectorInstrumentation.h"
48 #include "core/rendering/InlineTextBox.h"
49 #include "core/rendering/RenderText.h"
50 #include "core/rendering/RenderTheme.h"
51 #include "core/rendering/RenderView.h"
52 #include "platform/EventDispatchForbiddenScope.h"
53 #include "platform/ScriptForbiddenScope.h"
54
55 namespace blink {
56
57 using namespace HTMLNames;
58
59 static void dispatchChildInsertionEvents(Node&);
60 static void dispatchChildRemovalEvents(Node&);
61
62 #if ENABLE(ASSERT)
63 unsigned EventDispatchForbiddenScope::s_count = 0;
64 #endif
65
66 static void collectChildrenAndRemoveFromOldParent(Node& node, NodeVector& nodes, ExceptionState& exceptionState)
67 {
68     if (node.isDocumentFragment()) {
69         DocumentFragment& fragment = toDocumentFragment(node);
70         getChildNodes(fragment, nodes);
71         fragment.removeChildren();
72         return;
73     }
74     nodes.append(&node);
75     if (ContainerNode* oldParent = node.parentNode())
76         oldParent->removeChild(&node, exceptionState);
77 }
78
79 #if !ENABLE(OILPAN)
80 void ContainerNode::removeDetachedChildren()
81 {
82     ASSERT(!connectedSubframeCount());
83     ASSERT(needsAttach());
84     removeDetachedChildrenInContainer(*this);
85 }
86 #endif
87
88 void ContainerNode::parserTakeAllChildrenFrom(ContainerNode& oldParent)
89 {
90     while (RefPtrWillBeRawPtr<Node> child = oldParent.firstChild()) {
91         oldParent.parserRemoveChild(*child);
92         treeScope().adoptIfNeeded(*child);
93         parserAppendChild(child.get());
94     }
95 }
96
97 ContainerNode::~ContainerNode()
98 {
99     ASSERT(needsAttach());
100 #if !ENABLE(OILPAN)
101     willBeDeletedFromDocument();
102     removeDetachedChildren();
103 #endif
104 }
105
106 bool ContainerNode::isChildTypeAllowed(const Node& child) const
107 {
108     if (!child.isDocumentFragment())
109         return childTypeAllowed(child.nodeType());
110
111     for (Node* node = toDocumentFragment(child).firstChild(); node; node = node->nextSibling()) {
112         if (!childTypeAllowed(node->nodeType()))
113             return false;
114     }
115     return true;
116 }
117
118 bool ContainerNode::containsConsideringHostElements(const Node& newChild) const
119 {
120     if (isInShadowTree() || document().isTemplateDocument())
121         return newChild.containsIncludingHostElements(*this);
122     return newChild.contains(this);
123 }
124
125 bool ContainerNode::checkAcceptChild(const Node* newChild, const Node* oldChild, ExceptionState& exceptionState) const
126 {
127     // Not mentioned in spec: throw NotFoundError if newChild is null
128     if (!newChild) {
129         exceptionState.throwDOMException(NotFoundError, "The new child element is null.");
130         return false;
131     }
132
133     // Use common case fast path if possible.
134     if ((newChild->isElementNode() || newChild->isTextNode()) && isElementNode()) {
135         ASSERT(isChildTypeAllowed(*newChild));
136         if (containsConsideringHostElements(*newChild)) {
137             exceptionState.throwDOMException(HierarchyRequestError, "The new child element contains the parent.");
138             return false;
139         }
140         return true;
141     }
142
143     // This should never happen, but also protect release builds from tree corruption.
144     ASSERT(!newChild->isPseudoElement());
145     if (newChild->isPseudoElement()) {
146         exceptionState.throwDOMException(HierarchyRequestError, "The new child element is a pseudo-element.");
147         return false;
148     }
149
150     if (containsConsideringHostElements(*newChild)) {
151         exceptionState.throwDOMException(HierarchyRequestError, "The new child element contains the parent.");
152         return false;
153     }
154
155     if (oldChild && isDocumentNode()) {
156         if (!toDocument(this)->canReplaceChild(*newChild, *oldChild)) {
157             // FIXME: Adjust 'Document::canReplaceChild' to return some additional detail (or an error message).
158             exceptionState.throwDOMException(HierarchyRequestError, "Failed to replace child.");
159             return false;
160         }
161     } else if (!isChildTypeAllowed(*newChild)) {
162         exceptionState.throwDOMException(HierarchyRequestError, "Nodes of type '" + newChild->nodeName() + "' may not be inserted inside nodes of type '" + nodeName() + "'.");
163         return false;
164     }
165
166     return true;
167 }
168
169 bool ContainerNode::checkAcceptChildGuaranteedNodeTypes(const Node& newChild, ExceptionState& exceptionState) const
170 {
171     ASSERT(isChildTypeAllowed(newChild));
172     if (newChild.contains(this)) {
173         exceptionState.throwDOMException(HierarchyRequestError, "The new child element contains the parent.");
174         return false;
175     }
176     return true;
177 }
178
179 PassRefPtrWillBeRawPtr<Node> ContainerNode::insertBefore(PassRefPtrWillBeRawPtr<Node> newChild, Node* refChild, ExceptionState& exceptionState)
180 {
181 #if !ENABLE(OILPAN)
182     // Check that this node is not "floating".
183     // If it is, it can be deleted as a side effect of sending mutation events.
184     ASSERT(refCount() || parentOrShadowHostNode());
185 #endif
186
187     RefPtrWillBeRawPtr<Node> protect(this);
188
189     // insertBefore(node, 0) is equivalent to appendChild(node)
190     if (!refChild) {
191         return appendChild(newChild, exceptionState);
192     }
193
194     // Make sure adding the new child is OK.
195     if (!checkAcceptChild(newChild.get(), 0, exceptionState)) {
196         if (exceptionState.hadException())
197             return nullptr;
198         return newChild;
199     }
200     ASSERT(newChild);
201
202     // NotFoundError: Raised if refChild is not a child of this node
203     if (refChild->parentNode() != this) {
204         exceptionState.throwDOMException(NotFoundError, "The node before which the new node is to be inserted is not a child of this node.");
205         return nullptr;
206     }
207
208     // nothing to do
209     if (refChild->previousSibling() == newChild || refChild == newChild)
210         return newChild;
211
212     RefPtrWillBeRawPtr<Node> next = refChild;
213
214     NodeVector targets;
215     collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState);
216     if (exceptionState.hadException())
217         return nullptr;
218     if (targets.isEmpty())
219         return newChild;
220
221     // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
222     if (!checkAcceptChildGuaranteedNodeTypes(*newChild, exceptionState)) {
223         if (exceptionState.hadException())
224             return nullptr;
225         return newChild;
226     }
227
228     InspectorInstrumentation::willInsertDOMNode(this);
229
230     ChildListMutationScope mutation(*this);
231     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
232         ASSERT(*it);
233         Node& child = **it;
234
235         // Due to arbitrary code running in response to a DOM mutation event it's
236         // possible that "next" is no longer a child of "this".
237         // It's also possible that "child" has been inserted elsewhere.
238         // In either of those cases, we'll just stop.
239         if (next->parentNode() != this)
240             break;
241         if (child.parentNode())
242             break;
243
244         treeScope().adoptIfNeeded(child);
245
246         insertBeforeCommon(*next, child);
247
248         updateTreeAfterInsertion(child);
249     }
250
251     dispatchSubtreeModifiedEvent();
252
253     return newChild;
254 }
255
256 void ContainerNode::insertBeforeCommon(Node& nextChild, Node& newChild)
257 {
258     EventDispatchForbiddenScope assertNoEventDispatch;
259     ScriptForbiddenScope forbidScript;
260
261     ASSERT(!newChild.parentNode()); // Use insertBefore if you need to handle reparenting (and want DOM mutation events).
262     ASSERT(!newChild.nextSibling());
263     ASSERT(!newChild.previousSibling());
264     ASSERT(!newChild.isShadowRoot());
265
266     Node* prev = nextChild.previousSibling();
267     ASSERT(m_lastChild != prev);
268     nextChild.setPreviousSibling(&newChild);
269     if (prev) {
270         ASSERT(firstChild() != nextChild);
271         ASSERT(prev->nextSibling() == nextChild);
272         prev->setNextSibling(&newChild);
273     } else {
274         ASSERT(firstChild() == nextChild);
275         m_firstChild = &newChild;
276     }
277     newChild.setParentOrShadowHostNode(this);
278     newChild.setPreviousSibling(prev);
279     newChild.setNextSibling(&nextChild);
280 }
281
282 void ContainerNode::appendChildCommon(Node& child)
283 {
284     child.setParentOrShadowHostNode(this);
285
286     if (m_lastChild) {
287         child.setPreviousSibling(m_lastChild);
288         m_lastChild->setNextSibling(&child);
289     } else {
290         setFirstChild(&child);
291     }
292
293     setLastChild(&child);
294 }
295
296 void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node> newChild, Node& nextChild)
297 {
298     ASSERT(newChild);
299     ASSERT(nextChild.parentNode() == this);
300     ASSERT(!newChild->isDocumentFragment());
301     ASSERT(!isHTMLTemplateElement(this));
302
303     if (nextChild.previousSibling() == newChild || &nextChild == newChild) // nothing to do
304         return;
305
306     RefPtrWillBeRawPtr<Node> protect(this);
307
308     if (document() != newChild->document())
309         document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
310
311     insertBeforeCommon(nextChild, *newChild);
312
313     newChild->updateAncestorConnectedSubframeCountForInsertion();
314
315     ChildListMutationScope(*this).childAdded(*newChild);
316
317     notifyNodeInserted(*newChild, ChildrenChangeSourceParser);
318 }
319
320 PassRefPtrWillBeRawPtr<Node> ContainerNode::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, PassRefPtrWillBeRawPtr<Node> oldChild, ExceptionState& exceptionState)
321 {
322 #if !ENABLE(OILPAN)
323     // Check that this node is not "floating".
324     // If it is, it can be deleted as a side effect of sending mutation events.
325     ASSERT(refCount() || parentOrShadowHostNode());
326 #endif
327
328     RefPtrWillBeRawPtr<Node> protect(this);
329
330     if (oldChild == newChild) // nothing to do
331         return oldChild;
332
333     if (!oldChild) {
334         exceptionState.throwDOMException(NotFoundError, "The node to be replaced is null.");
335         return nullptr;
336     }
337
338     RefPtrWillBeRawPtr<Node> child = oldChild;
339
340     // Make sure replacing the old child with the new is ok
341     if (!checkAcceptChild(newChild.get(), child.get(), exceptionState)) {
342         if (exceptionState.hadException())
343             return nullptr;
344         return child;
345     }
346
347     // NotFoundError: Raised if oldChild is not a child of this node.
348     if (child->parentNode() != this) {
349         exceptionState.throwDOMException(NotFoundError, "The node to be replaced is not a child of this node.");
350         return nullptr;
351     }
352
353     ChildListMutationScope mutation(*this);
354
355     RefPtrWillBeRawPtr<Node> next = child->nextSibling();
356
357     // Remove the node we're replacing
358     removeChild(child, exceptionState);
359     if (exceptionState.hadException())
360         return nullptr;
361
362     if (next && (next->previousSibling() == newChild || next == newChild)) // nothing to do
363         return child;
364
365     // Does this one more time because removeChild() fires a MutationEvent.
366     if (!checkAcceptChild(newChild.get(), child.get(), exceptionState)) {
367         if (exceptionState.hadException())
368             return nullptr;
369         return child;
370     }
371
372     NodeVector targets;
373     collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState);
374     if (exceptionState.hadException())
375         return nullptr;
376
377     // Does this yet another check because collectChildrenAndRemoveFromOldParent() fires a MutationEvent.
378     if (!checkAcceptChild(newChild.get(), child.get(), exceptionState)) {
379         if (exceptionState.hadException())
380             return nullptr;
381         return child;
382     }
383
384     InspectorInstrumentation::willInsertDOMNode(this);
385
386     // Add the new child(ren)
387     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
388         ASSERT(*it);
389         Node& child = **it;
390
391         // Due to arbitrary code running in response to a DOM mutation event it's
392         // possible that "next" is no longer a child of "this".
393         // It's also possible that "child" has been inserted elsewhere.
394         // In either of those cases, we'll just stop.
395         if (next && next->parentNode() != this)
396             break;
397         if (child.parentNode())
398             break;
399
400         treeScope().adoptIfNeeded(child);
401
402         // Add child before "next".
403         {
404             EventDispatchForbiddenScope assertNoEventDispatch;
405             if (next)
406                 insertBeforeCommon(*next, child);
407             else
408                 appendChildCommon(child);
409         }
410
411         updateTreeAfterInsertion(child);
412     }
413
414     dispatchSubtreeModifiedEvent();
415     return child;
416 }
417
418 void ContainerNode::willRemoveChild(Node& child)
419 {
420     ASSERT(child.parentNode() == this);
421     ChildListMutationScope(*this).willRemoveChild(child);
422     child.notifyMutationObserversNodeWillDetach();
423     dispatchChildRemovalEvents(child);
424     document().nodeWillBeRemoved(child); // e.g. mutation event listener can create a new range.
425     ChildFrameDisconnector(child).disconnect();
426 }
427
428 void ContainerNode::willRemoveChildren()
429 {
430     NodeVector children;
431     getChildNodes(*this, children);
432
433     ChildListMutationScope mutation(*this);
434     for (NodeVector::const_iterator it = children.begin(); it != children.end(); ++it) {
435         ASSERT(*it);
436         Node& child = **it;
437         mutation.willRemoveChild(child);
438         child.notifyMutationObserversNodeWillDetach();
439         dispatchChildRemovalEvents(child);
440     }
441
442     ChildFrameDisconnector(*this).disconnect(ChildFrameDisconnector::DescendantsOnly);
443 }
444
445 #if !ENABLE(OILPAN)
446 void ContainerNode::removeDetachedChildrenInContainer(ContainerNode& container)
447 {
448     // List of nodes to be deleted.
449     Node* head = 0;
450     Node* tail = 0;
451
452     addChildNodesToDeletionQueue(head, tail, container);
453
454     Node* n;
455     Node* next;
456     while ((n = head) != 0) {
457         ASSERT_WITH_SECURITY_IMPLICATION(n->m_deletionHasBegun);
458
459         next = n->nextSibling();
460         n->setNextSibling(0);
461
462         head = next;
463         if (next == 0)
464             tail = 0;
465
466         if (n->hasChildren())
467             addChildNodesToDeletionQueue(head, tail, toContainerNode(*n));
468
469         delete n;
470     }
471 }
472
473 void ContainerNode::addChildNodesToDeletionQueue(Node*& head, Node*& tail, ContainerNode& container)
474 {
475     // We have to tell all children that their parent has died.
476     Node* next = 0;
477     for (Node* n = container.firstChild(); n; n = next) {
478         ASSERT_WITH_SECURITY_IMPLICATION(!n->m_deletionHasBegun);
479
480         next = n->nextSibling();
481         n->setNextSibling(0);
482         n->setParentOrShadowHostNode(0);
483         container.setFirstChild(next);
484         if (next)
485             next->setPreviousSibling(0);
486
487         if (!n->refCount()) {
488 #if ENABLE(SECURITY_ASSERT)
489             n->m_deletionHasBegun = true;
490 #endif
491             // Add the node to the list of nodes to be deleted.
492             // Reuse the nextSibling pointer for this purpose.
493             if (tail)
494                 tail->setNextSibling(n);
495             else
496                 head = n;
497
498             tail = n;
499         } else {
500             RefPtrWillBeRawPtr<Node> protect(n); // removedFromDocument may remove all references to this node.
501             container.document().adoptIfNeeded(*n);
502             if (n->inDocument())
503                 container.notifyNodeRemoved(*n);
504         }
505     }
506
507     container.setLastChild(0);
508 }
509 #endif
510
511 void ContainerNode::disconnectDescendantFrames()
512 {
513     ChildFrameDisconnector(*this).disconnect();
514 }
515
516 void ContainerNode::trace(Visitor* visitor)
517 {
518     visitor->trace(m_firstChild);
519     visitor->trace(m_lastChild);
520     Node::trace(visitor);
521 }
522
523 PassRefPtrWillBeRawPtr<Node> ContainerNode::removeChild(PassRefPtrWillBeRawPtr<Node> oldChild, ExceptionState& exceptionState)
524 {
525 #if !ENABLE(OILPAN)
526     // Check that this node is not "floating".
527     // If it is, it can be deleted as a side effect of sending mutation events.
528     ASSERT(refCount() || parentOrShadowHostNode());
529 #endif
530
531     RefPtrWillBeRawPtr<Node> protect(this);
532
533     // NotFoundError: Raised if oldChild is not a child of this node.
534     // FIXME: We should never really get PseudoElements in here, but editing will sometimes
535     // attempt to remove them still. We should fix that and enable this ASSERT.
536     // ASSERT(!oldChild->isPseudoElement())
537     if (!oldChild || oldChild->parentNode() != this || oldChild->isPseudoElement()) {
538         exceptionState.throwDOMException(NotFoundError, "The node to be removed is not a child of this node.");
539         return nullptr;
540     }
541
542     RefPtrWillBeRawPtr<Node> child = oldChild;
543
544     document().removeFocusedElementOfSubtree(child.get());
545
546     // Events fired when blurring currently focused node might have moved this
547     // child into a different parent.
548     if (child->parentNode() != this) {
549         exceptionState.throwDOMException(NotFoundError, "The node to be removed is no longer a child of this node. Perhaps it was moved in a 'blur' event handler?");
550         return nullptr;
551     }
552
553     willRemoveChild(*child);
554
555     // Mutation events might have moved this child into a different parent.
556     if (child->parentNode() != this) {
557         exceptionState.throwDOMException(NotFoundError, "The node to be removed is no longer a child of this node. Perhaps it was moved in response to a mutation?");
558         return nullptr;
559     }
560
561     {
562         HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates;
563
564         Node* prev = child->previousSibling();
565         Node* next = child->nextSibling();
566         removeBetween(prev, next, *child);
567         notifyNodeRemoved(*child);
568         childrenChanged(ChildrenChange::forRemoval(*child, prev, next, ChildrenChangeSourceAPI));
569     }
570     dispatchSubtreeModifiedEvent();
571     return child;
572 }
573
574 void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node& oldChild)
575 {
576     EventDispatchForbiddenScope assertNoEventDispatch;
577
578     ASSERT(oldChild.parentNode() == this);
579
580     if (!oldChild.needsAttach())
581         oldChild.detach();
582
583     if (nextChild)
584         nextChild->setPreviousSibling(previousChild);
585     if (previousChild)
586         previousChild->setNextSibling(nextChild);
587     if (m_firstChild == &oldChild)
588         m_firstChild = nextChild;
589     if (m_lastChild == &oldChild)
590         m_lastChild = previousChild;
591
592     oldChild.setPreviousSibling(0);
593     oldChild.setNextSibling(0);
594     oldChild.setParentOrShadowHostNode(0);
595
596     document().adoptIfNeeded(oldChild);
597 }
598
599 void ContainerNode::parserRemoveChild(Node& oldChild)
600 {
601     ASSERT(oldChild.parentNode() == this);
602     ASSERT(!oldChild.isDocumentFragment());
603
604     Node* prev = oldChild.previousSibling();
605     Node* next = oldChild.nextSibling();
606
607     oldChild.updateAncestorConnectedSubframeCountForRemoval();
608
609     ChildListMutationScope(*this).willRemoveChild(oldChild);
610     oldChild.notifyMutationObserversNodeWillDetach();
611
612     removeBetween(prev, next, oldChild);
613
614     notifyNodeRemoved(oldChild);
615     childrenChanged(ChildrenChange::forRemoval(oldChild, prev, next, ChildrenChangeSourceParser));
616 }
617
618 // this differs from other remove functions because it forcibly removes all the children,
619 // regardless of read-only status or event exceptions, e.g.
620 void ContainerNode::removeChildren()
621 {
622     if (!m_firstChild)
623         return;
624
625     // The container node can be removed from event handlers.
626     RefPtrWillBeRawPtr<ContainerNode> protect(this);
627
628     // Do any prep work needed before actually starting to detach
629     // and remove... e.g. stop loading frames, fire unload events.
630     willRemoveChildren();
631
632     {
633         // Removing focus can cause frames to load, either via events (focusout, blur)
634         // or widget updates (e.g., for <embed>).
635         SubframeLoadingDisabler disabler(*this);
636
637         // Exclude this node when looking for removed focusedElement since only
638         // children will be removed.
639         // This must be later than willRemoveChildren, which might change focus
640         // state of a child.
641         document().removeFocusedElementOfSubtree(this, true);
642
643         // Removing a node from a selection can cause widget updates.
644         document().nodeChildrenWillBeRemoved(*this);
645     }
646
647     // FIXME: Remove this NodeVector. Right now WebPluginContainerImpl::m_element is a
648     // raw ptr which means the code below can drop the last ref to a plugin element and
649     // then the code in UpdateSuspendScope::performDeferredWidgetTreeOperations will
650     // try to destroy the plugin which will be a use-after-free. We should use a RefPtr
651     // in the WebPluginContainerImpl instead.
652     NodeVector removedChildren;
653     {
654         HTMLFrameOwnerElement::UpdateSuspendScope suspendWidgetHierarchyUpdates;
655
656         {
657             EventDispatchForbiddenScope assertNoEventDispatch;
658             ScriptForbiddenScope forbidScript;
659
660             removedChildren.reserveInitialCapacity(countChildren());
661
662             while (RefPtrWillBeRawPtr<Node> child = m_firstChild) {
663                 removeBetween(0, child->nextSibling(), *child);
664                 removedChildren.append(child.get());
665                 notifyNodeRemoved(*child);
666             }
667         }
668
669         ChildrenChange change = {AllChildrenRemoved, nullptr, nullptr, ChildrenChangeSourceAPI};
670         childrenChanged(change);
671     }
672
673     // We don't fire the DOMSubtreeModified event for Attr Nodes. This matches the behavior
674     // of IE and Firefox. This event is fired synchronously and is a source of trouble for
675     // attributes as the JS callback could alter the attributes and leave us in a bad state.
676     if (!isAttributeNode())
677         dispatchSubtreeModifiedEvent();
678 }
679
680 PassRefPtrWillBeRawPtr<Node> ContainerNode::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, ExceptionState& exceptionState)
681 {
682     RefPtrWillBeRawPtr<ContainerNode> protect(this);
683
684 #if !ENABLE(OILPAN)
685     // Check that this node is not "floating".
686     // If it is, it can be deleted as a side effect of sending mutation events.
687     ASSERT(refCount() || parentOrShadowHostNode());
688 #endif
689
690     // Make sure adding the new child is ok
691     if (!checkAcceptChild(newChild.get(), 0, exceptionState)) {
692         if (exceptionState.hadException())
693             return nullptr;
694         return newChild;
695     }
696     ASSERT(newChild);
697
698     if (newChild == m_lastChild) // nothing to do
699         return newChild;
700
701     NodeVector targets;
702     collectChildrenAndRemoveFromOldParent(*newChild, targets, exceptionState);
703     if (exceptionState.hadException())
704         return nullptr;
705
706     if (targets.isEmpty())
707         return newChild;
708
709     // We need this extra check because collectChildrenAndRemoveFromOldParent() can fire mutation events.
710     if (!checkAcceptChildGuaranteedNodeTypes(*newChild, exceptionState)) {
711         if (exceptionState.hadException())
712             return nullptr;
713         return newChild;
714     }
715
716     InspectorInstrumentation::willInsertDOMNode(this);
717
718     // Now actually add the child(ren)
719     ChildListMutationScope mutation(*this);
720     for (NodeVector::const_iterator it = targets.begin(); it != targets.end(); ++it) {
721         ASSERT(*it);
722         Node& child = **it;
723
724         // If the child has a parent again, just stop what we're doing, because
725         // that means someone is doing something with DOM mutation -- can't re-parent
726         // a child that already has a parent.
727         if (child.parentNode())
728             break;
729
730         {
731             EventDispatchForbiddenScope assertNoEventDispatch;
732             ScriptForbiddenScope forbidScript;
733
734             treeScope().adoptIfNeeded(child);
735             appendChildCommon(child);
736         }
737
738         updateTreeAfterInsertion(child);
739     }
740
741     dispatchSubtreeModifiedEvent();
742     return newChild;
743 }
744
745 void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node> newChild)
746 {
747     ASSERT(newChild);
748     ASSERT(!newChild->parentNode()); // Use appendChild if you need to handle reparenting (and want DOM mutation events).
749     ASSERT(!newChild->isDocumentFragment());
750     ASSERT(!isHTMLTemplateElement(this));
751
752     RefPtrWillBeRawPtr<Node> protect(this);
753
754     if (document() != newChild->document())
755         document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);
756
757     {
758         EventDispatchForbiddenScope assertNoEventDispatch;
759         ScriptForbiddenScope forbidScript;
760
761         treeScope().adoptIfNeeded(*newChild);
762         appendChildCommon(*newChild);
763         newChild->updateAncestorConnectedSubframeCountForInsertion();
764         ChildListMutationScope(*this).childAdded(*newChild);
765     }
766
767     notifyNodeInserted(*newChild, ChildrenChangeSourceParser);
768 }
769
770 void ContainerNode::notifyNodeInserted(Node& root, ChildrenChangeSource source)
771 {
772     ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
773     ASSERT(!root.isShadowRoot());
774
775     InspectorInstrumentation::didInsertDOMNode(&root);
776
777     RefPtrWillBeRawPtr<Node> protect(this);
778     RefPtrWillBeRawPtr<Node> protectNode(root);
779
780     NodeVector postInsertionNotificationTargets;
781     notifyNodeInsertedInternal(root, postInsertionNotificationTargets);
782
783     childrenChanged(ChildrenChange::forInsertion(root, source));
784
785     for (size_t i = 0; i < postInsertionNotificationTargets.size(); ++i) {
786         Node* targetNode = postInsertionNotificationTargets[i].get();
787         if (targetNode->inDocument())
788             targetNode->didNotifySubtreeInsertionsToDocument();
789     }
790 }
791
792 void ContainerNode::notifyNodeInsertedInternal(Node& root, NodeVector& postInsertionNotificationTargets)
793 {
794     EventDispatchForbiddenScope assertNoEventDispatch;
795     ScriptForbiddenScope forbidScript;
796
797     for (Node* node = &root; node; node = NodeTraversal::next(*node, &root)) {
798         // As an optimization we don't notify leaf nodes when when inserting
799         // into detached subtrees.
800         if (!inDocument() && !node->isContainerNode())
801             continue;
802         if (Node::InsertionShouldCallDidNotifySubtreeInsertions == node->insertedInto(this))
803             postInsertionNotificationTargets.append(node);
804         for (ShadowRoot* shadowRoot = node->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot())
805             notifyNodeInsertedInternal(*shadowRoot, postInsertionNotificationTargets);
806     }
807 }
808
809 void ContainerNode::notifyNodeRemoved(Node& root)
810 {
811     ScriptForbiddenScope forbidScript;
812     EventDispatchForbiddenScope assertNoEventDispatch;
813
814     Document& document = root.document();
815     for (Node* node = &root; node; node = NodeTraversal::next(*node, &root)) {
816         // As an optimization we skip notifying Text nodes and other leaf nodes
817         // of removal when they're not in the Document tree since the virtual
818         // call to removedFrom is not needed.
819         if (!node->inDocument() && !node->isContainerNode())
820             continue;
821         if (document.cssTarget() == node)
822             document.setCSSTarget(nullptr);
823         node->removedFrom(this);
824         for (ShadowRoot* shadowRoot = node->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot())
825             notifyNodeRemoved(*shadowRoot);
826     }
827 }
828
829 void ContainerNode::attach(const AttachContext& context)
830 {
831     attachChildren(context);
832     clearChildNeedsStyleRecalc();
833     Node::attach(context);
834 }
835
836 void ContainerNode::detach(const AttachContext& context)
837 {
838     detachChildren(context);
839     clearChildNeedsStyleRecalc();
840     Node::detach(context);
841 }
842
843 void ContainerNode::childrenChanged(const ChildrenChange& change)
844 {
845     document().incDOMTreeVersion();
846     if (!change.byParser && change.type != TextChanged)
847         document().updateRangesAfterChildrenChanged(this);
848     invalidateNodeListCachesInAncestors();
849     if (change.isChildInsertion() && !childNeedsStyleRecalc()) {
850         setChildNeedsStyleRecalc();
851         markAncestorsWithChildNeedsStyleRecalc();
852     }
853 }
854
855 void ContainerNode::cloneChildNodes(ContainerNode *clone)
856 {
857     TrackExceptionState exceptionState;
858     for (Node* n = firstChild(); n && !exceptionState.hadException(); n = n->nextSibling())
859         clone->appendChild(n->cloneNode(true), exceptionState);
860 }
861
862
863 bool ContainerNode::getUpperLeftCorner(FloatPoint& point) const
864 {
865     if (!renderer())
866         return false;
867     // What is this code really trying to do?
868     RenderObject* o = renderer();
869
870     if (!o->isInline() || o->isReplaced()) {
871         point = o->localToAbsolute(FloatPoint(), UseTransforms);
872         return true;
873     }
874
875     // find the next text/image child, to get a position
876     while (o) {
877         RenderObject* p = o;
878         if (RenderObject* oFirstChild = o->slowFirstChild()) {
879             o = oFirstChild;
880         } else if (o->nextSibling()) {
881             o = o->nextSibling();
882         } else {
883             RenderObject* next = 0;
884             while (!next && o->parent()) {
885                 o = o->parent();
886                 next = o->nextSibling();
887             }
888             o = next;
889
890             if (!o)
891                 break;
892         }
893         ASSERT(o);
894
895         if (!o->isInline() || o->isReplaced()) {
896             point = o->localToAbsolute(FloatPoint(), UseTransforms);
897             return true;
898         }
899
900         if (p->node() && p->node() == this && o->isText() && !o->isBR() && !toRenderText(o)->firstTextBox()) {
901             // do nothing - skip unrendered whitespace that is a child or next sibling of the anchor
902         } else if ((o->isText() && !o->isBR()) || o->isReplaced()) {
903             point = FloatPoint();
904             if (o->isText() && toRenderText(o)->firstTextBox()) {
905                 point.move(toRenderText(o)->linesBoundingBox().x(), toRenderText(o)->firstTextBox()->root().lineTop().toFloat());
906             } else if (o->isBox()) {
907                 RenderBox* box = toRenderBox(o);
908                 point.moveBy(box->location());
909             }
910             point = o->container()->localToAbsolute(point, UseTransforms);
911             return true;
912         }
913     }
914
915     // If the target doesn't have any children or siblings that could be used to calculate the scroll position, we must be
916     // at the end of the document. Scroll to the bottom. FIXME: who said anything about scrolling?
917     if (!o && document().view()) {
918         point = FloatPoint(0, document().view()->contentsHeight());
919         return true;
920     }
921     return false;
922 }
923
924 bool ContainerNode::getLowerRightCorner(FloatPoint& point) const
925 {
926     if (!renderer())
927         return false;
928
929     RenderObject* o = renderer();
930     if (!o->isInline() || o->isReplaced()) {
931         RenderBox* box = toRenderBox(o);
932         point = o->localToAbsolute(LayoutPoint(box->size()), UseTransforms);
933         return true;
934     }
935
936     // find the last text/image child, to get a position
937     while (o) {
938         if (RenderObject* oLastChild = o->slowLastChild()) {
939             o = oLastChild;
940         } else if (o->previousSibling()) {
941             o = o->previousSibling();
942         } else {
943             RenderObject* prev = 0;
944         while (!prev) {
945             o = o->parent();
946             if (!o)
947                 return false;
948             prev = o->previousSibling();
949         }
950         o = prev;
951         }
952         ASSERT(o);
953         if (o->isText() || o->isReplaced()) {
954             point = FloatPoint();
955             if (o->isText()) {
956                 RenderText* text = toRenderText(o);
957                 IntRect linesBox = text->linesBoundingBox();
958                 if (!linesBox.maxX() && !linesBox.maxY())
959                     continue;
960                 point.moveBy(linesBox.maxXMaxYCorner());
961             } else {
962                 RenderBox* box = toRenderBox(o);
963                 point.moveBy(box->frameRect().maxXMaxYCorner());
964             }
965             point = o->container()->localToAbsolute(point, UseTransforms);
966             return true;
967         }
968     }
969     return true;
970 }
971
972 // FIXME: This override is only needed for inline anchors without an
973 // InlineBox and it does not belong in ContainerNode as it reaches into
974 // the render and line box trees.
975 // https://code.google.com/p/chromium/issues/detail?id=248354
976 LayoutRect ContainerNode::boundingBox() const
977 {
978     FloatPoint upperLeft, lowerRight;
979     bool foundUpperLeft = getUpperLeftCorner(upperLeft);
980     bool foundLowerRight = getLowerRightCorner(lowerRight);
981
982     // If we've found one corner, but not the other,
983     // then we should just return a point at the corner that we did find.
984     if (foundUpperLeft != foundLowerRight) {
985         if (foundUpperLeft)
986             lowerRight = upperLeft;
987         else
988             upperLeft = lowerRight;
989     }
990
991     return enclosingLayoutRect(FloatRect(upperLeft, lowerRight.expandedTo(upperLeft) - upperLeft));
992 }
993
994 // This is used by FrameSelection to denote when the active-state of the page has changed
995 // independent of the focused element changing.
996 void ContainerNode::focusStateChanged()
997 {
998     // If we're just changing the window's active state and the focused node has no
999     // renderer we can just ignore the state change.
1000     if (!renderer())
1001         return;
1002
1003     if (styleChangeType() < SubtreeStyleChange) {
1004         if (renderStyle()->affectedByFocus() && renderStyle()->hasPseudoStyle(FIRST_LETTER))
1005             setNeedsStyleRecalc(SubtreeStyleChange);
1006         else if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByFocus())
1007             document().ensureStyleResolver().ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForPseudoChange(CSSSelector::PseudoFocus, *toElement(this));
1008         else if (renderStyle()->affectedByFocus())
1009             setNeedsStyleRecalc(LocalStyleChange);
1010     }
1011
1012     if (renderer() && renderer()->style()->hasAppearance())
1013         RenderTheme::theme().stateChanged(renderer(), FocusControlState);
1014 }
1015
1016 void ContainerNode::setFocus(bool received)
1017 {
1018     if (focused() == received)
1019         return;
1020
1021     Node::setFocus(received);
1022
1023     focusStateChanged();
1024
1025     if (renderer() || received)
1026         return;
1027
1028     // If :focus sets display: none, we lose focus but still need to recalc our style.
1029     if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByFocus() && styleChangeType() < SubtreeStyleChange)
1030         document().ensureStyleResolver().ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForPseudoChange(CSSSelector::PseudoFocus, *toElement(this));
1031     else
1032         setNeedsStyleRecalc(LocalStyleChange);
1033 }
1034
1035 void ContainerNode::setActive(bool down)
1036 {
1037     if (down == active())
1038         return;
1039
1040     Node::setActive(down);
1041
1042     // FIXME: Why does this not need to handle the display: none transition like :hover does?
1043     if (renderer()) {
1044         if (styleChangeType() < SubtreeStyleChange) {
1045             if (renderStyle()->affectedByActive() && renderStyle()->hasPseudoStyle(FIRST_LETTER))
1046                 setNeedsStyleRecalc(SubtreeStyleChange);
1047             else if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByActive())
1048                 document().ensureStyleResolver().ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForPseudoChange(CSSSelector::PseudoActive, *toElement(this));
1049             else if (renderStyle()->affectedByActive())
1050                 setNeedsStyleRecalc(LocalStyleChange);
1051         }
1052
1053         if (renderStyle()->hasAppearance())
1054             RenderTheme::theme().stateChanged(renderer(), PressedControlState);
1055     }
1056 }
1057
1058 void ContainerNode::setHovered(bool over)
1059 {
1060     if (over == hovered())
1061         return;
1062
1063     Node::setHovered(over);
1064
1065     // If :hover sets display: none we lose our hover but still need to recalc our style.
1066     if (!renderer()) {
1067         if (over)
1068             return;
1069         if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByHover() && styleChangeType() < SubtreeStyleChange)
1070             document().ensureStyleResolver().ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForPseudoChange(CSSSelector::PseudoHover, *toElement(this));
1071         else
1072             setNeedsStyleRecalc(LocalStyleChange);
1073         return;
1074     }
1075
1076     if (styleChangeType() < SubtreeStyleChange) {
1077         if (renderStyle()->affectedByHover() && renderStyle()->hasPseudoStyle(FIRST_LETTER))
1078             setNeedsStyleRecalc(SubtreeStyleChange);
1079         else if (isElementNode() && toElement(this)->childrenOrSiblingsAffectedByHover())
1080             document().ensureStyleResolver().ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForPseudoChange(CSSSelector::PseudoHover, *toElement(this));
1081         else if (renderStyle()->affectedByHover())
1082             setNeedsStyleRecalc(LocalStyleChange);
1083     }
1084
1085     if (renderer()->style()->hasAppearance())
1086         RenderTheme::theme().stateChanged(renderer(), HoverControlState);
1087 }
1088
1089 PassRefPtrWillBeRawPtr<HTMLCollection> ContainerNode::children()
1090 {
1091     return ensureCachedCollection<HTMLCollection>(NodeChildren);
1092 }
1093
1094 unsigned ContainerNode::countChildren() const
1095 {
1096     unsigned count = 0;
1097     Node *n;
1098     for (n = firstChild(); n; n = n->nextSibling())
1099         count++;
1100     return count;
1101 }
1102
1103 PassRefPtrWillBeRawPtr<Element> ContainerNode::querySelector(const AtomicString& selectors, ExceptionState& exceptionState)
1104 {
1105     if (selectors.isEmpty()) {
1106         exceptionState.throwDOMException(SyntaxError, "The provided selector is empty.");
1107         return nullptr;
1108     }
1109
1110     SelectorQuery* selectorQuery = document().selectorQueryCache().add(selectors, document(), exceptionState);
1111     if (!selectorQuery)
1112         return nullptr;
1113     return selectorQuery->queryFirst(*this);
1114 }
1115
1116 PassRefPtrWillBeRawPtr<StaticElementList> ContainerNode::querySelectorAll(const AtomicString& selectors, ExceptionState& exceptionState)
1117 {
1118     if (selectors.isEmpty()) {
1119         exceptionState.throwDOMException(SyntaxError, "The provided selector is empty.");
1120         return nullptr;
1121     }
1122
1123     SelectorQuery* selectorQuery = document().selectorQueryCache().add(selectors, document(), exceptionState);
1124     if (!selectorQuery)
1125         return nullptr;
1126
1127     return selectorQuery->queryAll(*this);
1128 }
1129
1130 static void dispatchChildInsertionEvents(Node& child)
1131 {
1132     if (child.isInShadowTree())
1133         return;
1134
1135     ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
1136
1137     RefPtrWillBeRawPtr<Node> c(child);
1138     RefPtrWillBeRawPtr<Document> document(child.document());
1139
1140     if (c->parentNode() && document->hasListenerType(Document::DOMNODEINSERTED_LISTENER))
1141         c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNodeInserted, true, c->parentNode()));
1142
1143     // dispatch the DOMNodeInsertedIntoDocument event to all descendants
1144     if (c->inDocument() && document->hasListenerType(Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER)) {
1145         for (; c; c = NodeTraversal::next(*c, &child))
1146             c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNodeInsertedIntoDocument, false));
1147     }
1148 }
1149
1150 static void dispatchChildRemovalEvents(Node& child)
1151 {
1152     if (child.isInShadowTree()) {
1153         InspectorInstrumentation::willRemoveDOMNode(&child);
1154         return;
1155     }
1156
1157     ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
1158
1159     InspectorInstrumentation::willRemoveDOMNode(&child);
1160
1161     RefPtrWillBeRawPtr<Node> c(child);
1162     RefPtrWillBeRawPtr<Document> document(child.document());
1163
1164     // dispatch pre-removal mutation events
1165     if (c->parentNode() && document->hasListenerType(Document::DOMNODEREMOVED_LISTENER)) {
1166         NodeChildRemovalTracker scope(child);
1167         c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNodeRemoved, true, c->parentNode()));
1168     }
1169
1170     // dispatch the DOMNodeRemovedFromDocument event to all descendants
1171     if (c->inDocument() && document->hasListenerType(Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER)) {
1172         NodeChildRemovalTracker scope(child);
1173         for (; c; c = NodeTraversal::next(*c, &child))
1174             c->dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMNodeRemovedFromDocument, false));
1175     }
1176 }
1177
1178 void ContainerNode::updateTreeAfterInsertion(Node& child)
1179 {
1180 #if !ENABLE(OILPAN)
1181     ASSERT(refCount());
1182     ASSERT(child.refCount());
1183 #endif
1184
1185     ChildListMutationScope(*this).childAdded(child);
1186
1187     notifyNodeInserted(child);
1188
1189     dispatchChildInsertionEvents(child);
1190 }
1191
1192 bool ContainerNode::hasRestyleFlagInternal(DynamicRestyleFlags mask) const
1193 {
1194     return rareData()->hasRestyleFlag(mask);
1195 }
1196
1197 bool ContainerNode::hasRestyleFlagsInternal() const
1198 {
1199     return rareData()->hasRestyleFlags();
1200 }
1201
1202 void ContainerNode::setRestyleFlag(DynamicRestyleFlags mask)
1203 {
1204     ASSERT(isElementNode() || isShadowRoot());
1205     ensureRareData().setRestyleFlag(mask);
1206 }
1207
1208 void ContainerNode::recalcChildStyle(StyleRecalcChange change)
1209 {
1210     ASSERT(document().inStyleRecalc());
1211     ASSERT(change >= UpdatePseudoElements || childNeedsStyleRecalc());
1212     ASSERT(!needsStyleRecalc());
1213
1214     if (change < Force && hasRareData() && childNeedsStyleRecalc())
1215         checkForChildrenAdjacentRuleChanges();
1216
1217     // This loop is deliberately backwards because we use insertBefore in the rendering tree, and want to avoid
1218     // a potentially n^2 loop to find the insertion point while resolving style. Having us start from the last
1219     // child and work our way back means in the common case, we'll find the insertion point in O(1) time.
1220     // See crbug.com/288225
1221     StyleResolver& styleResolver = document().ensureStyleResolver();
1222     Text* lastTextNode = 0;
1223     for (Node* child = lastChild(); child; child = child->previousSibling()) {
1224         if (child->isTextNode()) {
1225             toText(child)->recalcTextStyle(change, lastTextNode);
1226             lastTextNode = toText(child);
1227         } else if (child->isElementNode()) {
1228             Element* element = toElement(child);
1229             if (element->shouldCallRecalcStyle(change))
1230                 element->recalcStyle(change, lastTextNode);
1231             else if (element->supportsStyleSharing())
1232                 styleResolver.addToStyleSharingList(*element);
1233             if (element->renderer())
1234                 lastTextNode = 0;
1235         }
1236     }
1237 }
1238
1239 void ContainerNode::checkForChildrenAdjacentRuleChanges()
1240 {
1241     bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules();
1242     bool hasIndirectAdjacentRules = childrenAffectedByIndirectAdjacentRules();
1243
1244     if (!hasDirectAdjacentRules && !hasIndirectAdjacentRules)
1245         return;
1246
1247     unsigned forceCheckOfNextElementCount = 0;
1248     bool forceCheckOfAnyElementSibling = false;
1249     Document& document = this->document();
1250
1251     for (Element* child = ElementTraversal::firstChild(*this); child; child = ElementTraversal::nextSibling(*child)) {
1252         bool childRulesChanged = child->needsStyleRecalc() && child->styleChangeType() >= SubtreeStyleChange;
1253
1254         if (forceCheckOfNextElementCount || forceCheckOfAnyElementSibling)
1255             child->setNeedsStyleRecalc(SubtreeStyleChange);
1256
1257         if (childRulesChanged && hasDirectAdjacentRules)
1258             forceCheckOfNextElementCount = document.styleEngine()->maxDirectAdjacentSelectors();
1259         else if (forceCheckOfNextElementCount)
1260             --forceCheckOfNextElementCount;
1261
1262         forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
1263     }
1264 }
1265
1266 void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Node* nodeBeforeChange, Node* nodeAfterChange)
1267 {
1268     if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || styleChangeType() >= SubtreeStyleChange)
1269         return;
1270
1271     if (needsStyleRecalc() && childrenAffectedByPositionalRules())
1272         return;
1273
1274     // Forward positional selectors include nth-child, nth-of-type, first-of-type and only-of-type.
1275     // The indirect adjacent selector is the ~ selector.
1276     // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
1277     // We have to invalidate everything following the insertion point in the forward and indirect adjacent case,
1278     // and everything before the insertion point in the backward case.
1279     // |afterChange| is 0 in the parser callback case, so we won't do any work for the forward case if we don't have to.
1280     // For performance reasons we just mark the parent node as changed, since we don't want to make childrenChanged O(n^2) by crawling all our kids
1281     // here. recalcStyle will then force a walk of the children when it sees that this has happened.
1282     if (((childrenAffectedByForwardPositionalRules() || childrenAffectedByIndirectAdjacentRules()) && nodeAfterChange)
1283         || (childrenAffectedByBackwardPositionalRules() && nodeBeforeChange)) {
1284         setNeedsStyleRecalc(SubtreeStyleChange);
1285         return;
1286     }
1287
1288     // :first-child. In the parser callback case, we don't have to check anything, since we were right the first time.
1289     // In the DOM case, we only need to do something if |afterChange| is not 0.
1290     // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
1291     if (childrenAffectedByFirstChildRules() && nodeAfterChange) {
1292         ASSERT(changeType != FinishedParsingChildren);
1293         // Find our new first child element.
1294         Element* firstChildElement = ElementTraversal::firstChild(*this);
1295         RenderStyle* firstChildElementStyle = firstChildElement ? firstChildElement->renderStyle() : 0;
1296
1297         // Find the first element after the change.
1298         Element* elementAfterChange = nodeAfterChange->isElementNode() ? toElement(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange);
1299         RenderStyle* elementAfterChangeStyle = elementAfterChange ? elementAfterChange->renderStyle() : 0;
1300
1301         // This is the element insertion as first child element case.
1302         if (firstChildElement != elementAfterChange && elementAfterChangeStyle && elementAfterChangeStyle->firstChildState()) {
1303             ASSERT(changeType == SiblingElementInserted);
1304             elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange);
1305         }
1306
1307         // This is the first child element removal case.
1308         if (changeType == SiblingElementRemoved && firstChildElement == elementAfterChange && firstChildElement && (!firstChildElementStyle || !firstChildElementStyle->firstChildState()))
1309             firstChildElement->setNeedsStyleRecalc(SubtreeStyleChange);
1310     }
1311
1312     // :last-child. In the parser callback case, we don't have to check anything, since we were right the first time.
1313     // In the DOM case, we only need to do something if |afterChange| is not 0.
1314     if (childrenAffectedByLastChildRules() && nodeBeforeChange) {
1315         // Find our new last child element.
1316         Element* lastChildElement = ElementTraversal::lastChild(*this);
1317         RenderStyle* lastChildElementStyle = lastChildElement ? lastChildElement->renderStyle() : 0;
1318
1319         // Find the last element before the change.
1320         Element* elementBeforeChange = nodeBeforeChange->isElementNode() ? toElement(nodeBeforeChange) : ElementTraversal::previousSibling(*nodeBeforeChange);
1321         RenderStyle* elementBeforeChangeStyle = elementBeforeChange ? elementBeforeChange->renderStyle() : 0;
1322
1323         // This is the element insertion as last child element case.
1324         if (lastChildElement != elementBeforeChange && elementBeforeChangeStyle && elementBeforeChangeStyle->lastChildState()) {
1325             ASSERT(SiblingElementInserted);
1326             elementBeforeChange->setNeedsStyleRecalc(SubtreeStyleChange);
1327         }
1328
1329         // This is the last child element removal case. The parser callback case is similar to node removal as well in that we need to change the last child
1330         // to match now.
1331         if ((changeType == SiblingElementRemoved || changeType == FinishedParsingChildren) && lastChildElement == elementBeforeChange && lastChildElement && (!lastChildElementStyle || !lastChildElementStyle->lastChildState()))
1332             lastChildElement->setNeedsStyleRecalc(SubtreeStyleChange);
1333     }
1334
1335     // The + selector. We need to invalidate the first element following the change. It is the only possible element
1336     // that could be affected by this DOM change.
1337     if (childrenAffectedByDirectAdjacentRules() && nodeAfterChange) {
1338         if (Element* elementAfterChange = nodeAfterChange->isElementNode() ? toElement(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange))
1339             elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange);
1340     }
1341 }
1342
1343 void ContainerNode::invalidateNodeListCachesInAncestors(const QualifiedName* attrName, Element* attributeOwnerElement)
1344 {
1345     if (hasRareData() && (!attrName || isAttributeNode())) {
1346         if (NodeListsNodeData* lists = rareData()->nodeLists()) {
1347             if (ChildNodeList* childNodeList = lists->childNodeList(*this))
1348                 childNodeList->invalidateCache();
1349         }
1350     }
1351
1352     // Modifications to attributes that are not associated with an Element can't invalidate NodeList caches.
1353     if (attrName && !attributeOwnerElement)
1354         return;
1355
1356     if (!document().shouldInvalidateNodeListCaches(attrName))
1357         return;
1358
1359     document().invalidateNodeListCaches(attrName);
1360
1361     for (ContainerNode* node = this; node; node = node->parentNode()) {
1362         if (NodeListsNodeData* lists = node->nodeLists())
1363             lists->invalidateCaches(attrName);
1364     }
1365 }
1366
1367 PassRefPtrWillBeRawPtr<TagCollection> ContainerNode::getElementsByTagName(const AtomicString& localName)
1368 {
1369     if (localName.isNull())
1370         return nullptr;
1371
1372     if (document().isHTMLDocument())
1373         return ensureCachedCollection<HTMLTagCollection>(HTMLTagCollectionType, localName);
1374     return ensureCachedCollection<TagCollection>(TagCollectionType, localName);
1375 }
1376
1377 PassRefPtrWillBeRawPtr<TagCollection> ContainerNode::getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName)
1378 {
1379     if (localName.isNull())
1380         return nullptr;
1381
1382     if (namespaceURI == starAtom)
1383         return getElementsByTagName(localName);
1384
1385     return ensureCachedCollection<TagCollection>(TagCollectionType, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localName);
1386 }
1387
1388 // Takes an AtomicString in argument because it is common for elements to share the same name attribute.
1389 // Therefore, the NameNodeList factory function expects an AtomicString type.
1390 PassRefPtrWillBeRawPtr<NameNodeList> ContainerNode::getElementsByName(const AtomicString& elementName)
1391 {
1392     return ensureCachedCollection<NameNodeList>(NameNodeListType, elementName);
1393 }
1394
1395 // Takes an AtomicString in argument because it is common for elements to share the same set of class names.
1396 // Therefore, the ClassNodeList factory function expects an AtomicString type.
1397 PassRefPtrWillBeRawPtr<ClassCollection> ContainerNode::getElementsByClassName(const AtomicString& classNames)
1398 {
1399     return ensureCachedCollection<ClassCollection>(ClassCollectionType, classNames);
1400 }
1401
1402 PassRefPtrWillBeRawPtr<RadioNodeList> ContainerNode::radioNodeList(const AtomicString& name, bool onlyMatchImgElements)
1403 {
1404     ASSERT(isHTMLFormElement(this) || isHTMLFieldSetElement(this));
1405     CollectionType type = onlyMatchImgElements ? RadioImgNodeListType : RadioNodeListType;
1406     return ensureCachedCollection<RadioNodeList>(type, name);
1407 }
1408
1409 Element* ContainerNode::getElementById(const AtomicString& id) const
1410 {
1411     if (isInTreeScope()) {
1412         // Fast path if we are in a tree scope: call getElementById() on tree scope
1413         // and check if the matching element is in our subtree.
1414         Element* element = treeScope().getElementById(id);
1415         if (!element)
1416             return 0;
1417         if (element->isDescendantOf(this))
1418             return element;
1419     }
1420
1421     // Fall back to traversing our subtree. In case of duplicate ids, the first element found will be returned.
1422     for (Element* element = ElementTraversal::firstWithin(*this); element; element = ElementTraversal::next(*element, this)) {
1423         if (element->getIdAttribute() == id)
1424             return element;
1425     }
1426     return 0;
1427 }
1428
1429 NodeListsNodeData& ContainerNode::ensureNodeLists()
1430 {
1431     return ensureRareData().ensureNodeLists();
1432 }
1433
1434 #if ENABLE(ASSERT)
1435 bool childAttachedAllowedWhenAttachingChildren(ContainerNode* node)
1436 {
1437     if (node->isShadowRoot())
1438         return true;
1439
1440     if (node->isInsertionPoint())
1441         return true;
1442
1443     if (node->isElementNode() && toElement(node)->shadow())
1444         return true;
1445
1446     return false;
1447 }
1448 #endif
1449
1450 } // namespace blink