2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
6 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
26 #include "core/dom/Node.h"
28 #include "bindings/core/v8/ExceptionState.h"
29 #include "bindings/core/v8/ScriptCallStackFactory.h"
30 #include "core/HTMLNames.h"
31 #include "core/XMLNames.h"
32 #include "core/accessibility/AXObjectCache.h"
33 #include "core/css/resolver/StyleResolver.h"
34 #include "core/dom/Attr.h"
35 #include "core/dom/Attribute.h"
36 #include "core/dom/ChildListMutationScope.h"
37 #include "core/dom/ChildNodeList.h"
38 #include "core/dom/DOMImplementation.h"
39 #include "core/dom/Document.h"
40 #include "core/dom/DocumentFragment.h"
41 #include "core/dom/DocumentMarkerController.h"
42 #include "core/dom/DocumentType.h"
43 #include "core/dom/Element.h"
44 #include "core/dom/ElementRareData.h"
45 #include "core/dom/ElementTraversal.h"
46 #include "core/dom/ExceptionCode.h"
47 #include "core/dom/LiveNodeList.h"
48 #include "core/dom/NodeRareData.h"
49 #include "core/dom/NodeRenderingTraversal.h"
50 #include "core/dom/NodeTraversal.h"
51 #include "core/dom/ProcessingInstruction.h"
52 #include "core/dom/Range.h"
53 #include "core/dom/StaticNodeList.h"
54 #include "core/dom/TemplateContentDocumentFragment.h"
55 #include "core/dom/Text.h"
56 #include "core/dom/TreeScopeAdopter.h"
57 #include "core/dom/UserActionElementSet.h"
58 #include "core/dom/WeakNodeMap.h"
59 #include "core/dom/shadow/ElementShadow.h"
60 #include "core/dom/shadow/InsertionPoint.h"
61 #include "core/dom/shadow/ShadowRoot.h"
62 #include "core/editing/htmlediting.h"
63 #include "core/editing/markup.h"
64 #include "core/events/Event.h"
65 #include "core/events/EventDispatchMediator.h"
66 #include "core/events/EventDispatcher.h"
67 #include "core/events/EventListener.h"
68 #include "core/events/GestureEvent.h"
69 #include "core/events/KeyboardEvent.h"
70 #include "core/events/MouseEvent.h"
71 #include "core/events/MutationEvent.h"
72 #include "core/events/TextEvent.h"
73 #include "core/events/TouchEvent.h"
74 #include "core/events/UIEvent.h"
75 #include "core/events/WheelEvent.h"
76 #include "core/frame/EventHandlerRegistry.h"
77 #include "core/frame/LocalFrame.h"
78 #include "core/html/HTMLAnchorElement.h"
79 #include "core/html/HTMLDialogElement.h"
80 #include "core/html/HTMLFrameOwnerElement.h"
81 #include "core/html/HTMLStyleElement.h"
82 #include "core/page/ContextMenuController.h"
83 #include "core/page/EventHandler.h"
84 #include "core/page/Page.h"
85 #include "core/frame/Settings.h"
86 #include "core/rendering/FlowThreadController.h"
87 #include "core/rendering/RenderBox.h"
88 #include "core/svg/graphics/SVGImage.h"
89 #include "platform/EventDispatchForbiddenScope.h"
90 #include "platform/Partitions.h"
91 #include "platform/TraceEvent.h"
92 #include "platform/TracedValue.h"
93 #include "wtf/HashSet.h"
94 #include "wtf/PassOwnPtr.h"
95 #include "wtf/RefCountedLeakCounter.h"
96 #include "wtf/Vector.h"
97 #include "wtf/text/CString.h"
98 #include "wtf/text/StringBuilder.h"
102 using namespace HTMLNames;
104 struct SameSizeAsNode : NODE_BASE_CLASSES {
105 uint32_t m_nodeFlags;
109 COMPILE_ASSERT(sizeof(Node) <= sizeof(SameSizeAsNode), Node_should_stay_small);
112 void* Node::operator new(size_t size)
114 ASSERT(isMainThread());
115 return partitionAlloc(Partitions::getObjectModelPartition(), size);
118 void Node::operator delete(void* ptr)
120 ASSERT(isMainThread());
125 #if DUMP_NODE_STATISTICS
126 typedef WillBeHeapHashSet<RawPtrWillBeWeakMember<Node> > WeakNodeSet;
127 static WeakNodeSet& liveNodeSet()
129 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<WeakNodeSet>, set, (adoptPtrWillBeNoop(new WeakNodeSet())));
134 void Node::dumpStatistics()
136 #if DUMP_NODE_STATISTICS
137 size_t nodesWithRareData = 0;
139 size_t elementNodes = 0;
140 size_t attrNodes = 0;
141 size_t textNodes = 0;
142 size_t cdataNodes = 0;
143 size_t commentNodes = 0;
145 size_t documentNodes = 0;
146 size_t docTypeNodes = 0;
147 size_t fragmentNodes = 0;
148 size_t shadowRootNodes = 0;
150 HashMap<String, size_t> perTagCount;
152 size_t attributes = 0;
153 size_t elementsWithAttributeStorage = 0;
154 size_t elementsWithRareData = 0;
155 size_t elementsWithNamedNodeMap = 0;
157 for (WeakNodeSet::iterator it = liveNodeSet().begin(); it != liveNodeSet().end(); ++it) {
160 if (node->hasRareData()) {
162 if (node->isElementNode()) {
163 ++elementsWithRareData;
164 if (toElement(node)->hasNamedNodeMap())
165 ++elementsWithNamedNodeMap;
169 switch (node->nodeType()) {
174 Element* element = toElement(node);
175 HashMap<String, size_t>::AddResult result = perTagCount.add(element->tagName(), 1);
176 if (!result.isNewEntry)
177 result.storedValue->value++;
179 if (const ElementData* elementData = element->elementData()) {
180 attributes += elementData->attributes().size();
181 ++elementsWithAttributeStorage;
185 case ATTRIBUTE_NODE: {
193 case CDATA_SECTION_NODE: {
201 case PROCESSING_INSTRUCTION_NODE: {
205 case DOCUMENT_NODE: {
209 case DOCUMENT_TYPE_NODE: {
213 case DOCUMENT_FRAGMENT_NODE: {
214 if (node->isShadowRoot())
223 printf("Number of Nodes: %d\n\n", liveNodeSet().size());
224 printf("Number of Nodes with RareData: %zu\n\n", nodesWithRareData);
226 printf("NodeType distribution:\n");
227 printf(" Number of Element nodes: %zu\n", elementNodes);
228 printf(" Number of Attribute nodes: %zu\n", attrNodes);
229 printf(" Number of Text nodes: %zu\n", textNodes);
230 printf(" Number of CDATASection nodes: %zu\n", cdataNodes);
231 printf(" Number of Comment nodes: %zu\n", commentNodes);
232 printf(" Number of ProcessingInstruction nodes: %zu\n", piNodes);
233 printf(" Number of Document nodes: %zu\n", documentNodes);
234 printf(" Number of DocumentType nodes: %zu\n", docTypeNodes);
235 printf(" Number of DocumentFragment nodes: %zu\n", fragmentNodes);
236 printf(" Number of ShadowRoot nodes: %zu\n", shadowRootNodes);
238 printf("Element tag name distibution:\n");
239 for (HashMap<String, size_t>::iterator it = perTagCount.begin(); it != perTagCount.end(); ++it)
240 printf(" Number of <%s> tags: %zu\n", it->key.utf8().data(), it->value);
242 printf("Attributes:\n");
243 printf(" Number of Attributes (non-Node and Node): %zu [%zu]\n", attributes, sizeof(Attribute));
244 printf(" Number of Elements with attribute storage: %zu [%zu]\n", elementsWithAttributeStorage, sizeof(ElementData));
245 printf(" Number of Elements with RareData: %zu\n", elementsWithRareData);
246 printf(" Number of Elements with NamedNodeMap: %zu [%zu]\n", elementsWithNamedNodeMap, sizeof(NamedNodeMap));
250 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, nodeCounter, ("WebCoreNode"));
252 void Node::trackForDebugging()
255 nodeCounter.increment();
258 #if DUMP_NODE_STATISTICS
259 liveNodeSet().add(this);
263 Node::Node(TreeScope* treeScope, ConstructionType type)
265 , m_parentOrShadowHostNode(nullptr)
266 , m_treeScope(treeScope)
267 , m_previous(nullptr)
270 ASSERT(m_treeScope || type == CreateDocument || type == CreateShadowRoot);
271 ScriptWrappable::init(this);
274 m_treeScope->guardRef();
277 #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
280 InspectorCounters::incrementCounter(InspectorCounters::NodeCounter);
286 nodeCounter.decrement();
290 #if DUMP_NODE_STATISTICS
291 liveNodeSet().remove(this);
297 RELEASE_ASSERT(!renderer());
299 if (!isContainerNode())
300 willBeDeletedFromDocument();
303 m_previous->setNextSibling(0);
305 m_next->setPreviousSibling(0);
308 m_treeScope->guardDeref();
310 if (getFlag(HasWeakReferencesFlag))
311 WeakNodeMap::notifyNodeDestroyed(this);
313 // With Oilpan, the rare data finalizer also asserts for
314 // this condition (we cannot directly access it here.)
315 RELEASE_ASSERT(hasRareData() || !renderer());
318 InspectorCounters::decrementCounter(InspectorCounters::NodeCounter);
322 // With Oilpan all of this is handled with weak processing of the document.
323 void Node::willBeDeletedFromDocument()
325 if (!isTreeScopeInitialized())
328 Document& document = this->document();
330 if (hasEventTargetData())
331 clearEventTargetData();
333 if (document.frameHost())
334 document.frameHost()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);
336 if (AXObjectCache* cache = document.existingAXObjectCache())
339 document.markers().removeMarkers(this);
343 NodeRareData* Node::rareData() const
345 ASSERT_WITH_SECURITY_IMPLICATION(hasRareData());
346 return static_cast<NodeRareData*>(m_data.m_rareData);
349 NodeRareData& Node::ensureRareData()
355 m_data.m_rareData = ElementRareData::create(m_data.m_renderer);
357 m_data.m_rareData = NodeRareData::create(m_data.m_renderer);
359 ASSERT(m_data.m_rareData);
361 setFlag(HasRareDataFlag);
366 void Node::clearRareData()
368 ASSERT(hasRareData());
369 ASSERT(!transientMutationObserverRegistry() || transientMutationObserverRegistry()->isEmpty());
371 RenderObject* renderer = m_data.m_rareData->renderer();
373 delete static_cast<ElementRareData*>(m_data.m_rareData);
375 delete static_cast<NodeRareData*>(m_data.m_rareData);
376 m_data.m_renderer = renderer;
377 clearFlag(HasRareDataFlag);
386 short Node::tabIndex() const
391 String Node::nodeValue() const
396 void Node::setNodeValue(const String&)
398 // By default, setting nodeValue has no effect.
401 PassRefPtrWillBeRawPtr<NodeList> Node::childNodes()
403 if (isContainerNode())
404 return ensureRareData().ensureNodeLists().ensureChildNodeList(toContainerNode(*this));
405 return ensureRareData().ensureNodeLists().ensureEmptyChildNodeList(*this);
408 Node* Node::pseudoAwarePreviousSibling() const
410 if (parentElement() && !previousSibling()) {
411 Element* parent = parentElement();
412 if (isAfterPseudoElement() && parent->lastChild())
413 return parent->lastChild();
414 if (!isBeforePseudoElement())
415 return parent->pseudoElement(BEFORE);
417 return previousSibling();
420 Node* Node::pseudoAwareNextSibling() const
422 if (parentElement() && !nextSibling()) {
423 Element* parent = parentElement();
424 if (isBeforePseudoElement() && parent->hasChildren())
425 return parent->firstChild();
426 if (!isAfterPseudoElement())
427 return parent->pseudoElement(AFTER);
429 return nextSibling();
432 Node* Node::pseudoAwareFirstChild() const
434 if (isElementNode()) {
435 const Element* currentElement = toElement(this);
436 Node* first = currentElement->pseudoElement(BEFORE);
439 first = currentElement->firstChild();
441 first = currentElement->pseudoElement(AFTER);
448 Node* Node::pseudoAwareLastChild() const
450 if (isElementNode()) {
451 const Element* currentElement = toElement(this);
452 Node* last = currentElement->pseudoElement(AFTER);
455 last = currentElement->lastChild();
457 last = currentElement->pseudoElement(BEFORE);
464 PassRefPtrWillBeRawPtr<Node> Node::insertBefore(PassRefPtrWillBeRawPtr<Node> newChild, Node* refChild, ExceptionState& exceptionState)
466 if (isContainerNode())
467 return toContainerNode(this)->insertBefore(newChild, refChild, exceptionState);
469 exceptionState.throwDOMException(HierarchyRequestError, "This node type does not support this method.");
473 PassRefPtrWillBeRawPtr<Node> Node::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, PassRefPtrWillBeRawPtr<Node> oldChild, ExceptionState& exceptionState)
475 if (isContainerNode())
476 return toContainerNode(this)->replaceChild(newChild, oldChild, exceptionState);
478 exceptionState.throwDOMException(HierarchyRequestError, "This node type does not support this method.");
482 PassRefPtrWillBeRawPtr<Node> Node::removeChild(PassRefPtrWillBeRawPtr<Node> oldChild, ExceptionState& exceptionState)
484 if (isContainerNode())
485 return toContainerNode(this)->removeChild(oldChild, exceptionState);
487 exceptionState.throwDOMException(NotFoundError, "This node type does not support this method.");
491 PassRefPtrWillBeRawPtr<Node> Node::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, ExceptionState& exceptionState)
493 if (isContainerNode())
494 return toContainerNode(this)->appendChild(newChild, exceptionState);
496 exceptionState.throwDOMException(HierarchyRequestError, "This node type does not support this method.");
500 void Node::remove(ExceptionState& exceptionState)
502 if (ContainerNode* parent = parentNode())
503 parent->removeChild(this, exceptionState);
506 void Node::normalize()
508 // Go through the subtree beneath us, normalizing all nodes. This means that
509 // any two adjacent text nodes are merged and any empty text nodes are removed.
511 RefPtrWillBeRawPtr<Node> node = this;
512 while (Node* firstChild = node->firstChild())
515 if (node->isElementNode())
516 toElement(node)->normalizeAttributes();
521 if (node->nodeType() == TEXT_NODE)
522 node = toText(node)->mergeNextSiblingNodesIfPossible();
524 node = NodeTraversal::nextPostOrder(*node);
528 const AtomicString& Node::localName() const
533 const AtomicString& Node::namespaceURI() const
538 bool Node::isContentEditable(UserSelectAllTreatment treatment)
540 document().updateRenderTreeIfNeeded();
541 return hasEditableStyle(Editable, treatment);
544 bool Node::isContentRichlyEditable()
546 document().updateRenderTreeIfNeeded();
547 return hasEditableStyle(RichlyEditable, UserSelectAllIsAlwaysNonEditable);
550 bool Node::hasEditableStyle(EditableLevel editableLevel, UserSelectAllTreatment treatment) const
552 if (isPseudoElement())
555 // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but
556 // ContainerNode::setFocus() calls setNeedsStyleRecalc(), so the assertion
557 // would fire in the middle of Document::setFocusedNode().
559 for (const Node* node = this; node; node = node->parentNode()) {
560 if ((node->isHTMLElement() || node->isDocumentNode()) && node->renderer()) {
561 // Elements with user-select: all style are considered atomic
562 // therefore non editable.
563 if (Position::nodeIsUserSelectAll(node) && treatment == UserSelectAllIsAlwaysNonEditable)
565 switch (node->renderer()->style()->userModify()) {
570 case READ_WRITE_PLAINTEXT_ONLY:
571 return editableLevel != RichlyEditable;
573 ASSERT_NOT_REACHED();
581 bool Node::isEditableToAccessibility(EditableLevel editableLevel) const
583 if (hasEditableStyle(editableLevel))
586 // FIXME: Respect editableLevel for ARIA editable elements.
587 if (editableLevel == RichlyEditable)
590 ASSERT(AXObjectCache::accessibilityEnabled());
591 ASSERT(document().existingAXObjectCache());
593 if (AXObjectCache* cache = document().existingAXObjectCache())
594 return cache->rootAXEditableElement(this);
599 RenderBox* Node::renderBox() const
601 RenderObject* renderer = this->renderer();
602 return renderer && renderer->isBox() ? toRenderBox(renderer) : 0;
605 RenderBoxModelObject* Node::renderBoxModelObject() const
607 RenderObject* renderer = this->renderer();
608 return renderer && renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
611 LayoutRect Node::boundingBox() const
614 return renderer()->absoluteBoundingBoxRect();
618 bool Node::hasNonEmptyBoundingBox() const
620 // Before calling absoluteRects, check for the common case where the renderer
621 // is non-empty, since this is a faster check and almost always returns true.
622 RenderBoxModelObject* box = renderBoxModelObject();
625 if (!box->borderBoundingBox().isEmpty())
628 Vector<IntRect> rects;
629 FloatPoint absPos = renderer()->localToAbsolute();
630 renderer()->absoluteRects(rects, flooredLayoutPoint(absPos));
631 size_t n = rects.size();
632 for (size_t i = 0; i < n; ++i)
633 if (!rects[i].isEmpty())
640 inline static ShadowRoot* oldestShadowRootFor(const Node* node)
642 if (!node->isElementNode())
644 if (ElementShadow* shadow = toElement(node)->shadow())
645 return shadow->oldestShadowRoot();
650 void Node::recalcDistribution()
652 if (isElementNode()) {
653 if (ElementShadow* shadow = toElement(this)->shadow())
654 shadow->distributeIfNeeded();
657 for (Node* child = firstChild(); child; child = child->nextSibling()) {
658 if (child->childNeedsDistributionRecalc())
659 child->recalcDistribution();
662 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
663 if (root->childNeedsDistributionRecalc())
664 root->recalcDistribution();
667 clearChildNeedsDistributionRecalc();
670 void Node::setIsLink(bool isLink)
672 setFlag(isLink && !SVGImage::isInSVGImage(toElement(this)), IsLinkFlag);
675 void Node::setNeedsStyleInvalidation()
677 setFlag(NeedsStyleInvalidationFlag);
678 markAncestorsWithChildNeedsStyleInvalidation();
681 void Node::markAncestorsWithChildNeedsStyleInvalidation()
683 for (Node* node = parentOrShadowHostNode(); node && !node->childNeedsStyleInvalidation(); node = node->parentOrShadowHostNode())
684 node->setChildNeedsStyleInvalidation();
685 document().scheduleRenderTreeUpdateIfNeeded();
688 void Node::markAncestorsWithChildNeedsDistributionRecalc()
690 for (Node* node = this; node && !node->childNeedsDistributionRecalc(); node = node->parentOrShadowHostNode())
691 node->setChildNeedsDistributionRecalc();
692 document().scheduleRenderTreeUpdateIfNeeded();
697 void addJsStack(TracedValue* stackFrames)
699 RefPtrWillBeRawPtr<ScriptCallStack> stack = createScriptCallStack(10);
702 for (size_t i = 0; i < stack->size(); i++)
703 stackFrames->pushString(stack->at(i).functionName());
706 PassRefPtr<TraceEvent::ConvertableToTraceFormat> jsonObjectForStyleInvalidation(unsigned nodeCount, const Node* rootNode)
708 RefPtr<TracedValue> value = TracedValue::create();
709 value->setInteger("node_count", nodeCount);
710 value->setString("root_node", rootNode->debugName());
711 value->beginArray("js_stack");
712 addJsStack(value.get());
717 } // anonymous namespace'd functions supporting traceStyleChange
719 unsigned Node::styledSubtreeSize() const
721 unsigned nodeCount = 0;
723 for (const Node* node = this; node; node = NodeTraversal::next(*node, this)) {
724 if (node->isTextNode() || node->isElementNode())
726 for (ShadowRoot* root = node->youngestShadowRoot(); root; root = root->olderShadowRoot())
727 nodeCount += root->styledSubtreeSize();
733 void Node::traceStyleChange(StyleChangeType changeType)
735 static const unsigned kMinLoggedSize = 100;
736 unsigned nodeCount = styledSubtreeSize();
737 if (nodeCount < kMinLoggedSize)
740 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("style.debug"),
741 "Node::setNeedsStyleRecalc",
742 "data", jsonObjectForStyleInvalidation(nodeCount, this)
746 void Node::traceStyleChangeIfNeeded(StyleChangeType changeType)
748 // TRACE_EVENT_CATEGORY_GROUP_ENABLED macro loads a global static bool into our local bool.
749 bool styleTracingEnabled;
750 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("style.debug"), &styleTracingEnabled);
751 if (UNLIKELY(styleTracingEnabled))
752 traceStyleChange(changeType);
755 inline void Node::setStyleChange(StyleChangeType changeType)
757 m_nodeFlags = (m_nodeFlags & ~StyleChangeMask) | changeType;
760 void Node::markAncestorsWithChildNeedsStyleRecalc()
762 for (ContainerNode* p = parentOrShadowHostNode(); p && !p->childNeedsStyleRecalc(); p = p->parentOrShadowHostNode())
763 p->setChildNeedsStyleRecalc();
764 document().scheduleRenderTreeUpdateIfNeeded();
767 void Node::setNeedsStyleRecalc(StyleChangeType changeType)
769 ASSERT(changeType != NoStyleChange);
770 if (!inActiveDocument())
773 StyleChangeType existingChangeType = styleChangeType();
774 if (changeType > existingChangeType) {
775 setStyleChange(changeType);
776 if (changeType >= SubtreeStyleChange)
777 traceStyleChangeIfNeeded(changeType);
780 if (existingChangeType == NoStyleChange)
781 markAncestorsWithChildNeedsStyleRecalc();
783 if (isElementNode() && hasRareData())
784 toElement(*this).setAnimationStyleChange(false);
787 void Node::clearNeedsStyleRecalc()
789 m_nodeFlags &= ~StyleChangeMask;
791 clearSVGFilterNeedsLayerUpdate();
793 if (isElementNode() && hasRareData())
794 toElement(*this).setAnimationStyleChange(false);
797 bool Node::inActiveDocument() const
799 return inDocument() && document().isActive();
802 Node* Node::focusDelegate()
807 bool Node::shouldHaveFocusAppearance() const
813 bool Node::isInert() const
815 const HTMLDialogElement* dialog = document().activeModalDialog();
816 if (dialog && this != document() && !NodeRenderingTraversal::contains(dialog, this))
818 return document().ownerElement() && document().ownerElement()->isInert();
821 unsigned Node::nodeIndex() const
823 Node *_tempNode = previousSibling();
825 for ( count=0; _tempNode; count++ )
826 _tempNode = _tempNode->previousSibling();
830 NodeListsNodeData* Node::nodeLists()
832 return hasRareData() ? rareData()->nodeLists() : 0;
835 void Node::clearNodeLists()
837 rareData()->clearNodeLists();
840 bool Node::isDescendantOf(const Node *other) const
842 // Return true if other is an ancestor of this, otherwise false
843 if (!other || !other->hasChildren() || inDocument() != other->inDocument())
845 if (other->treeScope() != treeScope())
847 if (other->isTreeScope())
848 return !isTreeScope();
849 for (const ContainerNode* n = parentNode(); n; n = n->parentNode()) {
856 bool Node::contains(const Node* node) const
860 return this == node || node->isDescendantOf(this);
863 bool Node::containsIncludingShadowDOM(const Node* node) const
871 if (document() != node->document())
874 if (inDocument() != node->inDocument())
877 bool hasChildren = isContainerNode() && toContainerNode(this)->hasChildren();
878 bool hasShadow = isElementNode() && toElement(this)->shadow();
879 if (!hasChildren && !hasShadow)
882 for (; node; node = node->shadowHost()) {
883 if (treeScope() == node->treeScope())
884 return contains(node);
890 bool Node::containsIncludingHostElements(const Node& node) const
892 const Node* current = &node;
896 if (current->isDocumentFragment() && toDocumentFragment(current)->isTemplateContent())
897 current = static_cast<const TemplateContentDocumentFragment*>(current)->host();
899 current = current->parentOrShadowHostNode();
904 Node* Node::commonAncestor(const Node& other, Node* (*parent)(const Node&))
908 if (document() != other.document())
911 for (Node* node = this; node; node = parent(*node)) {
917 for (const Node* node = &other; node; node = parent(*node)) {
922 Node* thisIterator = this;
923 const Node* otherIterator = &other;
924 if (thisDepth > otherDepth) {
925 for (int i = thisDepth; i > otherDepth; --i)
926 thisIterator = parent(*thisIterator);
927 } else if (otherDepth > thisDepth) {
928 for (int i = otherDepth; i > thisDepth; --i)
929 otherIterator = parent(*otherIterator);
931 while (thisIterator) {
932 if (thisIterator == otherIterator)
934 thisIterator = parent(*thisIterator);
935 otherIterator = parent(*otherIterator);
937 ASSERT(!otherIterator);
941 void Node::reattach(const AttachContext& context)
943 AttachContext reattachContext(context);
944 reattachContext.performingReattach = true;
946 // We only need to detach if the node has already been through attach().
947 if (styleChangeType() < NeedsReattachStyleChange)
948 detach(reattachContext);
949 attach(reattachContext);
952 void Node::attach(const AttachContext&)
954 ASSERT(document().inStyleRecalc() || isDocumentNode());
955 ASSERT(needsAttach());
956 ASSERT(!renderer() || (renderer()->style() && (renderer()->parent() || renderer()->isRenderView())));
958 clearNeedsStyleRecalc();
960 if (AXObjectCache* cache = document().axObjectCache())
961 cache->updateCacheAfterNodeIsAttached(this);
965 static Node* detachingNode;
967 bool Node::inDetach() const
969 return detachingNode == this;
973 void Node::detach(const AttachContext& context)
975 ASSERT(document().lifecycle().stateAllowsDetach());
976 DocumentLifecycle::DetachScope willDetach(document().lifecycle());
979 ASSERT(!detachingNode);
980 detachingNode = this;
984 renderer()->destroyAndCleanupAnonymousWrappers();
987 // Do not remove the element's hovered and active status
988 // if performing a reattach.
989 if (!context.performingReattach) {
990 Document& doc = document();
991 if (isUserActionElement()) {
993 doc.hoveredNodeDetached(this);
995 doc.activeChainNodeDetached(this);
996 doc.userActionElements().didDetach(this);
1000 setStyleChange(NeedsReattachStyleChange);
1001 setChildNeedsStyleRecalc();
1003 if (StyleResolver* resolver = document().styleResolver())
1004 resolver->ruleFeatureSet().styleInvalidator().clearInvalidation(*this);
1005 clearChildNeedsStyleInvalidation();
1006 clearNeedsStyleInvalidation();
1013 void Node::reattachWhitespaceSiblings(Text* start)
1015 for (Node* sibling = start; sibling; sibling = sibling->nextSibling()) {
1016 if (sibling->isTextNode() && toText(sibling)->containsOnlyWhitespace()) {
1017 bool hadRenderer = !!sibling->renderer();
1018 sibling->reattach();
1019 // If the reattach didn't toggle the visibility of the whitespace we don't
1020 // need to continue reattaching siblings since they won't toggle visibility
1022 if (hadRenderer == !!sibling->renderer())
1024 } else if (sibling->renderer()) {
1030 // FIXME: This code is used by editing. Seems like it could move over there and not pollute Node.
1031 Node *Node::previousNodeConsideringAtomicNodes() const
1033 if (previousSibling()) {
1034 Node *n = previousSibling();
1035 while (!isAtomicNode(n) && n->lastChild())
1039 else if (parentNode()) {
1040 return parentNode();
1047 Node *Node::nextNodeConsideringAtomicNodes() const
1049 if (!isAtomicNode(this) && hasChildren())
1050 return firstChild();
1052 return nextSibling();
1053 const Node *n = this;
1054 while (n && !n->nextSibling())
1055 n = n->parentNode();
1057 return n->nextSibling();
1061 Node *Node::previousLeafNode() const
1063 Node *node = previousNodeConsideringAtomicNodes();
1065 if (isAtomicNode(node))
1067 node = node->previousNodeConsideringAtomicNodes();
1072 Node *Node::nextLeafNode() const
1074 Node *node = nextNodeConsideringAtomicNodes();
1076 if (isAtomicNode(node))
1078 node = node->nextNodeConsideringAtomicNodes();
1083 RenderStyle* Node::virtualComputedStyle(PseudoId pseudoElementSpecifier)
1085 return parentOrShadowHostNode() ? parentOrShadowHostNode()->computedStyle(pseudoElementSpecifier) : 0;
1088 int Node::maxCharacterOffset() const
1090 ASSERT_NOT_REACHED();
1094 // FIXME: Shouldn't these functions be in the editing code? Code that asks questions about HTML in the core DOM class
1095 // is obviously misplaced.
1096 bool Node::canStartSelection() const
1098 if (hasEditableStyle())
1102 RenderStyle* style = renderer()->style();
1103 // We allow selections to begin within an element that has -webkit-user-select: none set,
1104 // but if the element is draggable then dragging should take priority over selection.
1105 if (style->userDrag() == DRAG_ELEMENT && style->userSelect() == SELECT_NONE)
1108 return parentOrShadowHostNode() ? parentOrShadowHostNode()->canStartSelection() : true;
1111 Element* Node::shadowHost() const
1113 if (ShadowRoot* root = containingShadowRoot())
1114 return root->host();
1118 ShadowRoot* Node::containingShadowRoot() const
1120 Node& root = treeScope().rootNode();
1121 return root.isShadowRoot() ? toShadowRoot(&root) : 0;
1124 Node* Node::nonBoundaryShadowTreeRootNode()
1126 ASSERT(!isShadowRoot());
1129 if (root->isShadowRoot())
1131 Node* parent = root->parentOrShadowHostNode();
1132 if (parent && parent->isShadowRoot())
1139 ContainerNode* Node::nonShadowBoundaryParentNode() const
1141 ContainerNode* parent = parentNode();
1142 return parent && !parent->isShadowRoot() ? parent : 0;
1145 Element* Node::parentOrShadowHostElement() const
1147 ContainerNode* parent = parentOrShadowHostNode();
1151 if (parent->isShadowRoot())
1152 return toShadowRoot(parent)->host();
1154 if (!parent->isElementNode())
1157 return toElement(parent);
1160 ContainerNode* Node::parentOrShadowHostOrTemplateHostNode() const
1162 if (isDocumentFragment() && toDocumentFragment(this)->isTemplateContent())
1163 return static_cast<const TemplateContentDocumentFragment*>(this)->host();
1164 return parentOrShadowHostNode();
1167 bool Node::isRootEditableElement() const
1169 return hasEditableStyle() && isElementNode() && (!parentNode() || !parentNode()->hasEditableStyle()
1170 || !parentNode()->isElementNode() || isHTMLBodyElement((*this)));
1173 Element* Node::rootEditableElement(EditableType editableType) const
1175 if (editableType == HasEditableAXRole) {
1176 if (AXObjectCache* cache = document().existingAXObjectCache())
1177 return const_cast<Element*>(cache->rootAXEditableElement(this));
1180 return rootEditableElement();
1183 Element* Node::rootEditableElement() const
1185 Element* result = 0;
1186 for (Node* n = const_cast<Node*>(this); n && n->hasEditableStyle(); n = n->parentNode()) {
1187 if (n->isElementNode())
1188 result = toElement(n);
1189 if (isHTMLBodyElement(*n))
1195 // FIXME: End of obviously misplaced HTML editing functions. Try to move these out of Node.
1197 Document* Node::ownerDocument() const
1199 Document* doc = &document();
1200 return doc == this ? 0 : doc;
1203 KURL Node::baseURI() const
1205 return parentNode() ? parentNode()->baseURI() : KURL();
1208 bool Node::isEqualNode(Node* other) const
1213 NodeType nodeType = this->nodeType();
1214 if (nodeType != other->nodeType())
1217 if (nodeName() != other->nodeName())
1220 if (localName() != other->localName())
1223 if (namespaceURI() != other->namespaceURI())
1226 if (nodeValue() != other->nodeValue())
1229 if (isElementNode() && !toElement(this)->hasEquivalentAttributes(toElement(other)))
1232 Node* child = firstChild();
1233 Node* otherChild = other->firstChild();
1236 if (!child->isEqualNode(otherChild))
1239 child = child->nextSibling();
1240 otherChild = otherChild->nextSibling();
1246 if (isDocumentTypeNode()) {
1247 const DocumentType* documentTypeThis = toDocumentType(this);
1248 const DocumentType* documentTypeOther = toDocumentType(other);
1250 if (documentTypeThis->publicId() != documentTypeOther->publicId())
1253 if (documentTypeThis->systemId() != documentTypeOther->systemId())
1260 bool Node::isDefaultNamespace(const AtomicString& namespaceURIMaybeEmpty) const
1262 const AtomicString& namespaceURI = namespaceURIMaybeEmpty.isEmpty() ? nullAtom : namespaceURIMaybeEmpty;
1264 switch (nodeType()) {
1265 case ELEMENT_NODE: {
1266 const Element& element = toElement(*this);
1268 if (element.prefix().isNull())
1269 return element.namespaceURI() == namespaceURI;
1271 AttributeCollection attributes = element.attributes();
1272 AttributeCollection::iterator end = attributes.end();
1273 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) {
1274 if (it->localName() == xmlnsAtom)
1275 return it->value() == namespaceURI;
1278 if (Element* parent = parentElement())
1279 return parent->isDefaultNamespace(namespaceURI);
1284 if (Element* de = toDocument(this)->documentElement())
1285 return de->isDefaultNamespace(namespaceURI);
1287 case DOCUMENT_TYPE_NODE:
1288 case DOCUMENT_FRAGMENT_NODE:
1290 case ATTRIBUTE_NODE: {
1291 const Attr* attr = toAttr(this);
1292 if (attr->ownerElement())
1293 return attr->ownerElement()->isDefaultNamespace(namespaceURI);
1297 if (Element* parent = parentElement())
1298 return parent->isDefaultNamespace(namespaceURI);
1303 const AtomicString& Node::lookupPrefix(const AtomicString& namespaceURI) const
1305 // Implemented according to
1306 // http://dom.spec.whatwg.org/#dom-node-lookupprefix
1308 if (namespaceURI.isEmpty() || namespaceURI.isNull())
1311 const Element* context;
1313 switch (nodeType()) {
1315 context = toElement(this);
1318 context = toDocument(this)->documentElement();
1320 case DOCUMENT_FRAGMENT_NODE:
1321 case DOCUMENT_TYPE_NODE:
1324 // FIXME: Remove this when Attr no longer extends Node (CR305105)
1325 case ATTRIBUTE_NODE:
1326 context = toAttr(this)->ownerElement();
1329 context = parentElement();
1336 return context->locateNamespacePrefix(namespaceURI);
1339 const AtomicString& Node::lookupNamespaceURI(const String& prefix) const
1341 // Implemented according to
1342 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespaceURIAlgo
1344 if (!prefix.isNull() && prefix.isEmpty())
1347 switch (nodeType()) {
1348 case ELEMENT_NODE: {
1349 const Element& element = toElement(*this);
1351 if (!element.namespaceURI().isNull() && element.prefix() == prefix)
1352 return element.namespaceURI();
1354 AttributeCollection attributes = element.attributes();
1355 AttributeCollection::iterator end = attributes.end();
1356 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) {
1357 if (it->prefix() == xmlnsAtom && it->localName() == prefix) {
1358 if (!it->value().isEmpty())
1362 if (it->localName() == xmlnsAtom && prefix.isNull()) {
1363 if (!it->value().isEmpty())
1369 if (Element* parent = parentElement())
1370 return parent->lookupNamespaceURI(prefix);
1374 if (Element* de = toDocument(this)->documentElement())
1375 return de->lookupNamespaceURI(prefix);
1377 case DOCUMENT_TYPE_NODE:
1378 case DOCUMENT_FRAGMENT_NODE:
1380 case ATTRIBUTE_NODE: {
1381 const Attr *attr = toAttr(this);
1382 if (attr->ownerElement())
1383 return attr->ownerElement()->lookupNamespaceURI(prefix);
1388 if (Element* parent = parentElement())
1389 return parent->lookupNamespaceURI(prefix);
1394 static void appendTextContent(const Node* node, bool convertBRsToNewlines, bool& isNullString, StringBuilder& content)
1396 switch (node->nodeType()) {
1397 case Node::TEXT_NODE:
1398 case Node::CDATA_SECTION_NODE:
1399 case Node::COMMENT_NODE:
1400 isNullString = false;
1401 content.append(toCharacterData(node)->data());
1404 case Node::PROCESSING_INSTRUCTION_NODE:
1405 isNullString = false;
1406 content.append(toProcessingInstruction(node)->data());
1409 case Node::ELEMENT_NODE:
1410 if (isHTMLBRElement(*node) && convertBRsToNewlines) {
1411 isNullString = false;
1412 content.append('\n');
1416 case Node::ATTRIBUTE_NODE:
1417 case Node::DOCUMENT_FRAGMENT_NODE:
1418 isNullString = false;
1419 for (Node* child = toContainerNode(node)->firstChild(); child; child = child->nextSibling()) {
1420 Node::NodeType childNodeType = child->nodeType();
1421 if (childNodeType == Node::COMMENT_NODE || childNodeType == Node::PROCESSING_INSTRUCTION_NODE)
1423 appendTextContent(child, convertBRsToNewlines, isNullString, content);
1427 case Node::DOCUMENT_NODE:
1428 case Node::DOCUMENT_TYPE_NODE:
1433 String Node::textContent(bool convertBRsToNewlines) const
1435 StringBuilder content;
1436 bool isNullString = true;
1437 appendTextContent(this, convertBRsToNewlines, isNullString, content);
1438 return isNullString ? String() : content.toString();
1441 void Node::setTextContent(const String& text)
1443 switch (nodeType()) {
1445 case CDATA_SECTION_NODE:
1447 case PROCESSING_INSTRUCTION_NODE:
1451 case ATTRIBUTE_NODE:
1452 case DOCUMENT_FRAGMENT_NODE: {
1453 // FIXME: Merge this logic into replaceChildrenWithText.
1454 RefPtrWillBeRawPtr<ContainerNode> container = toContainerNode(this);
1456 // Note: This is an intentional optimization.
1457 // See crbug.com/352836 also.
1458 // No need to do anything if the text is identical.
1459 if (container->hasOneTextChild() && toText(container->firstChild())->data() == text)
1462 ChildListMutationScope mutation(*this);
1463 container->removeChildren();
1464 // Note: This API will not insert empty text nodes:
1465 // http://dom.spec.whatwg.org/#dom-node-textcontent
1466 if (!text.isEmpty())
1467 container->appendChild(document().createTextNode(text), ASSERT_NO_EXCEPTION);
1471 case DOCUMENT_TYPE_NODE:
1475 ASSERT_NOT_REACHED();
1478 bool Node::offsetInCharacters() const
1483 unsigned short Node::compareDocumentPosition(const Node* otherNode, ShadowTreesTreatment treatment) const
1485 // It is not clear what should be done if |otherNode| is 0.
1487 return DOCUMENT_POSITION_DISCONNECTED;
1489 if (otherNode == this)
1490 return DOCUMENT_POSITION_EQUIVALENT;
1492 const Attr* attr1 = nodeType() == ATTRIBUTE_NODE ? toAttr(this) : 0;
1493 const Attr* attr2 = otherNode->nodeType() == ATTRIBUTE_NODE ? toAttr(otherNode) : 0;
1495 const Node* start1 = attr1 ? attr1->ownerElement() : this;
1496 const Node* start2 = attr2 ? attr2->ownerElement() : otherNode;
1498 // If either of start1 or start2 is null, then we are disconnected, since one of the nodes is
1499 // an orphaned attribute node.
1500 if (!start1 || !start2) {
1501 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING;
1502 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction;
1505 Vector<const Node*, 16> chain1;
1506 Vector<const Node*, 16> chain2;
1508 chain1.append(attr1);
1510 chain2.append(attr2);
1512 if (attr1 && attr2 && start1 == start2 && start1) {
1513 // We are comparing two attributes on the same node. Crawl our attribute map and see which one we hit first.
1514 const Element* owner1 = attr1->ownerElement();
1515 AttributeCollection attributes = owner1->attributes();
1516 AttributeCollection::iterator end = attributes.end();
1517 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) {
1518 // If neither of the two determining nodes is a child node and nodeType is the same for both determining nodes, then an
1519 // implementation-dependent order between the determining nodes is returned. This order is stable as long as no nodes of
1520 // the same nodeType are inserted into or removed from the direct container. This would be the case, for example,
1521 // when comparing two attributes of the same element, and inserting or removing additional attributes might change
1522 // the order between existing attributes.
1523 if (attr1->qualifiedName() == it->name())
1524 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING;
1525 if (attr2->qualifiedName() == it->name())
1526 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_PRECEDING;
1529 ASSERT_NOT_REACHED();
1530 return DOCUMENT_POSITION_DISCONNECTED;
1533 // If one node is in the document and the other is not, we must be disconnected.
1534 // If the nodes have different owning documents, they must be disconnected. Note that we avoid
1535 // comparing Attr nodes here, since they return false from inDocument() all the time (which seems like a bug).
1536 if (start1->inDocument() != start2->inDocument() || (treatment == TreatShadowTreesAsDisconnected && start1->treeScope() != start2->treeScope())) {
1537 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING;
1538 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction;
1541 // We need to find a common ancestor container, and then compare the indices of the two immediate children.
1542 const Node* current;
1543 for (current = start1; current; current = current->parentOrShadowHostNode())
1544 chain1.append(current);
1545 for (current = start2; current; current = current->parentOrShadowHostNode())
1546 chain2.append(current);
1548 unsigned index1 = chain1.size();
1549 unsigned index2 = chain2.size();
1551 // If the two elements don't have a common root, they're not in the same tree.
1552 if (chain1[index1 - 1] != chain2[index2 - 1]) {
1553 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING;
1554 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction;
1557 unsigned connection = start1->treeScope() != start2->treeScope() ? DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 0;
1559 // Walk the two chains backwards and look for the first difference.
1560 for (unsigned i = std::min(index1, index2); i; --i) {
1561 const Node* child1 = chain1[--index1];
1562 const Node* child2 = chain2[--index2];
1563 if (child1 != child2) {
1564 // If one of the children is an attribute, it wins.
1565 if (child1->nodeType() == ATTRIBUTE_NODE)
1566 return DOCUMENT_POSITION_FOLLOWING | connection;
1567 if (child2->nodeType() == ATTRIBUTE_NODE)
1568 return DOCUMENT_POSITION_PRECEDING | connection;
1570 // If one of the children is a shadow root,
1571 if (child1->isShadowRoot() || child2->isShadowRoot()) {
1572 if (!child2->isShadowRoot())
1573 return Node::DOCUMENT_POSITION_FOLLOWING | connection;
1574 if (!child1->isShadowRoot())
1575 return Node::DOCUMENT_POSITION_PRECEDING | connection;
1577 for (ShadowRoot* child = toShadowRoot(child2)->olderShadowRoot(); child; child = child->olderShadowRoot())
1578 if (child == child1)
1579 return Node::DOCUMENT_POSITION_FOLLOWING | connection;
1581 return Node::DOCUMENT_POSITION_PRECEDING | connection;
1584 if (!child2->nextSibling())
1585 return DOCUMENT_POSITION_FOLLOWING | connection;
1586 if (!child1->nextSibling())
1587 return DOCUMENT_POSITION_PRECEDING | connection;
1589 // Otherwise we need to see which node occurs first. Crawl backwards from child2 looking for child1.
1590 for (Node* child = child2->previousSibling(); child; child = child->previousSibling()) {
1591 if (child == child1)
1592 return DOCUMENT_POSITION_FOLLOWING | connection;
1594 return DOCUMENT_POSITION_PRECEDING | connection;
1598 // There was no difference between the two parent chains, i.e., one was a subset of the other. The shorter
1599 // chain is the ancestor.
1600 return index1 < index2 ?
1601 DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_CONTAINED_BY | connection :
1602 DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_CONTAINS | connection;
1605 FloatPoint Node::convertToPage(const FloatPoint& p) const
1607 // If there is a renderer, just ask it to do the conversion
1609 return renderer()->localToAbsolute(p, UseTransforms);
1611 // Otherwise go up the tree looking for a renderer
1612 if (Element* parent = parentElement())
1613 return parent->convertToPage(p);
1615 // No parent - no conversion needed
1619 FloatPoint Node::convertFromPage(const FloatPoint& p) const
1621 // If there is a renderer, just ask it to do the conversion
1623 return renderer()->absoluteToLocal(p, UseTransforms);
1625 // Otherwise go up the tree looking for a renderer
1626 if (Element* parent = parentElement())
1627 return parent->convertFromPage(p);
1629 // No parent - no conversion needed
1633 String Node::debugName() const
1636 name.append(nodeName());
1638 if (isElementNode()) {
1639 const Element& thisElement = toElement(*this);
1640 if (thisElement.hasID()) {
1641 name.appendLiteral(" id=\'");
1642 name.append(thisElement.getIdAttribute());
1646 if (thisElement.hasClass()) {
1647 name.appendLiteral(" class=\'");
1648 for (size_t i = 0; i < thisElement.classNames().size(); ++i) {
1651 name.append(thisElement.classNames()[i]);
1657 return name.toString();
1662 static void appendAttributeDesc(const Node* node, StringBuilder& stringBuilder, const QualifiedName& name, const char* attrDesc)
1664 if (!node->isElementNode())
1667 String attr = toElement(node)->getAttribute(name);
1671 stringBuilder.append(attrDesc);
1672 stringBuilder.append("=\"");
1673 stringBuilder.append(attr);
1674 stringBuilder.append("\"");
1677 void Node::showNode(const char* prefix) const
1682 String value = nodeValue();
1683 value.replaceWithLiteral('\\', "\\\\");
1684 value.replaceWithLiteral('\n', "\\n");
1685 fprintf(stderr, "%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this, value.utf8().data());
1687 StringBuilder attrs;
1688 appendAttributeDesc(this, attrs, idAttr, " ID");
1689 appendAttributeDesc(this, attrs, classAttr, " CLASS");
1690 appendAttributeDesc(this, attrs, styleAttr, " STYLE");
1691 fprintf(stderr, "%s%s\t%p%s\n", prefix, nodeName().utf8().data(), this, attrs.toString().utf8().data());
1695 void Node::showTreeForThis() const
1697 showTreeAndMark(this, "*");
1700 void Node::showNodePathForThis() const
1702 Vector<const Node*, 16> chain;
1703 const Node* node = this;
1704 while (node->parentOrShadowHostNode()) {
1706 node = node->parentOrShadowHostNode();
1708 for (unsigned index = chain.size(); index > 0; --index) {
1709 const Node* node = chain[index - 1];
1710 if (node->isShadowRoot()) {
1712 for (ShadowRoot* shadowRoot = toShadowRoot(node)->olderShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot())
1714 fprintf(stderr, "/#shadow-root[%d]", count);
1718 switch (node->nodeType()) {
1719 case ELEMENT_NODE: {
1720 fprintf(stderr, "/%s", node->nodeName().utf8().data());
1722 const Element* element = toElement(node);
1723 const AtomicString& idattr = element->getIdAttribute();
1724 bool hasIdAttr = !idattr.isNull() && !idattr.isEmpty();
1725 if (node->previousSibling() || node->nextSibling()) {
1727 for (Node* previous = node->previousSibling(); previous; previous = previous->previousSibling())
1728 if (previous->nodeName() == node->nodeName())
1731 fprintf(stderr, "[@id=\"%s\" and position()=%d]", idattr.utf8().data(), count);
1733 fprintf(stderr, "[%d]", count);
1734 } else if (hasIdAttr) {
1735 fprintf(stderr, "[@id=\"%s\"]", idattr.utf8().data());
1740 fprintf(stderr, "/text()");
1742 case ATTRIBUTE_NODE:
1743 fprintf(stderr, "/@%s", node->nodeName().utf8().data());
1749 fprintf(stderr, "\n");
1752 static void traverseTreeAndMark(const String& baseIndent, const Node* rootNode, const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2)
1754 for (const Node* node = rootNode; node; node = NodeTraversal::next(*node)) {
1755 if (node == markedNode1)
1756 fprintf(stderr, "%s", markedLabel1);
1757 if (node == markedNode2)
1758 fprintf(stderr, "%s", markedLabel2);
1760 StringBuilder indent;
1761 indent.append(baseIndent);
1762 for (const Node* tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentOrShadowHostNode())
1763 indent.append('\t');
1764 fprintf(stderr, "%s", indent.toString().utf8().data());
1766 indent.append('\t');
1767 if (node->isShadowRoot()) {
1768 if (ShadowRoot* youngerShadowRoot = toShadowRoot(node)->youngerShadowRoot())
1769 traverseTreeAndMark(indent.toString(), youngerShadowRoot, markedNode1, markedLabel1, markedNode2, markedLabel2);
1770 } else if (ShadowRoot* oldestShadowRoot = oldestShadowRootFor(node))
1771 traverseTreeAndMark(indent.toString(), oldestShadowRoot, markedNode1, markedLabel1, markedNode2, markedLabel2);
1775 void Node::showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2) const
1777 const Node* rootNode;
1778 const Node* node = this;
1779 while (node->parentOrShadowHostNode() && !isHTMLBodyElement(*node))
1780 node = node->parentOrShadowHostNode();
1783 String startingIndent;
1784 traverseTreeAndMark(startingIndent, rootNode, markedNode1, markedLabel1, markedNode2, markedLabel2);
1787 void Node::formatForDebugger(char* buffer, unsigned length) const
1798 strncpy(buffer, result.utf8().data(), length - 1);
1801 static ContainerNode* parentOrShadowHostOrFrameOwner(const Node* node)
1803 ContainerNode* parent = node->parentOrShadowHostNode();
1804 if (!parent && node->document().frame())
1805 parent = node->document().frame()->deprecatedLocalOwner();
1809 static void showSubTreeAcrossFrame(const Node* node, const Node* markedNode, const String& indent)
1811 if (node == markedNode)
1813 fputs(indent.utf8().data(), stderr);
1815 if (node->isShadowRoot()) {
1816 if (ShadowRoot* youngerShadowRoot = toShadowRoot(node)->youngerShadowRoot())
1817 showSubTreeAcrossFrame(youngerShadowRoot, markedNode, indent + "\t");
1819 if (node->isFrameOwnerElement())
1820 showSubTreeAcrossFrame(toHTMLFrameOwnerElement(node)->contentDocument(), markedNode, indent + "\t");
1821 if (ShadowRoot* oldestShadowRoot = oldestShadowRootFor(node))
1822 showSubTreeAcrossFrame(oldestShadowRoot, markedNode, indent + "\t");
1824 for (Node* child = node->firstChild(); child; child = child->nextSibling())
1825 showSubTreeAcrossFrame(child, markedNode, indent + "\t");
1828 void Node::showTreeForThisAcrossFrame() const
1830 Node* rootNode = const_cast<Node*>(this);
1831 while (parentOrShadowHostOrFrameOwner(rootNode))
1832 rootNode = parentOrShadowHostOrFrameOwner(rootNode);
1833 showSubTreeAcrossFrame(rootNode, this, "");
1840 Element* Node::enclosingLinkEventParentOrSelf()
1842 for (Node* node = this; node; node = NodeRenderingTraversal::parent(node)) {
1843 // For imagemaps, the enclosing link node is the associated area element not the image itself.
1844 // So we don't let images be the enclosingLinkNode, even though isLink sometimes returns true
1846 if (node->isLink() && !isHTMLImageElement(*node)) {
1847 // Casting to Element is safe because only HTMLAnchorElement, HTMLImageElement and
1848 // SVGAElement can return true for isLink().
1849 return toElement(node);
1856 const AtomicString& Node::interfaceName() const
1858 return EventTargetNames::Node;
1861 ExecutionContext* Node::executionContext() const
1863 return document().contextDocument().get();
1866 void Node::didMoveToNewDocument(Document& oldDocument)
1868 TreeScopeAdopter::ensureDidMoveToNewDocumentWasCalled(oldDocument);
1870 if (const EventTargetData* eventTargetData = this->eventTargetData()) {
1871 const EventListenerMap& listenerMap = eventTargetData->eventListenerMap;
1872 if (!listenerMap.isEmpty()) {
1873 Vector<AtomicString> types = listenerMap.eventTypes();
1874 for (unsigned i = 0; i < types.size(); ++i)
1875 document().addListenerTypeIfNeeded(types[i]);
1879 if (AXObjectCache::accessibilityEnabled()) {
1880 if (AXObjectCache* cache = oldDocument.existingAXObjectCache())
1881 cache->remove(this);
1884 oldDocument.markers().removeMarkers(this);
1885 oldDocument.updateRangesAfterNodeMovedToAnotherDocument(*this);
1886 if (oldDocument.frameHost() && !document().frameHost())
1887 oldDocument.frameHost()->eventHandlerRegistry().didMoveOutOfFrameHost(*this);
1888 else if (document().frameHost() && !oldDocument.frameHost())
1889 document().frameHost()->eventHandlerRegistry().didMoveIntoFrameHost(*this);
1890 else if (oldDocument.frameHost() != document().frameHost())
1891 EventHandlerRegistry::didMoveBetweenFrameHosts(*this, oldDocument.frameHost(), document().frameHost());
1893 if (WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* registry = mutationObserverRegistry()) {
1894 for (size_t i = 0; i < registry->size(); ++i) {
1895 document().addMutationObserverTypes(registry->at(i)->mutationTypes());
1899 if (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* transientRegistry = transientMutationObserverRegistry()) {
1900 for (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >::iterator iter = transientRegistry->begin(); iter != transientRegistry->end(); ++iter) {
1901 document().addMutationObserverTypes((*iter)->mutationTypes());
1906 static inline bool tryAddEventListener(Node* targetNode, const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1908 if (!targetNode->EventTarget::addEventListener(eventType, listener, useCapture))
1911 Document& document = targetNode->document();
1912 document.addListenerTypeIfNeeded(eventType);
1913 if (document.frameHost())
1914 document.frameHost()->eventHandlerRegistry().didAddEventHandler(*targetNode, eventType);
1919 bool Node::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1921 return tryAddEventListener(this, eventType, listener, useCapture);
1924 static inline bool tryRemoveEventListener(Node* targetNode, const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1926 if (!targetNode->EventTarget::removeEventListener(eventType, listener, useCapture))
1929 // FIXME: Notify Document that the listener has vanished. We need to keep track of a number of
1930 // listeners for each type, not just a bool - see https://bugs.webkit.org/show_bug.cgi?id=33861
1931 Document& document = targetNode->document();
1932 if (document.frameHost())
1933 document.frameHost()->eventHandlerRegistry().didRemoveEventHandler(*targetNode, eventType);
1938 bool Node::removeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1940 return tryRemoveEventListener(this, eventType, listener, useCapture);
1943 void Node::removeAllEventListeners()
1945 if (hasEventListeners() && document().frameHost())
1946 document().frameHost()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);
1947 EventTarget::removeAllEventListeners();
1950 void Node::removeAllEventListenersRecursively()
1952 for (Node* node = this; node; node = NodeTraversal::next(*node)) {
1953 node->removeAllEventListeners();
1954 for (ShadowRoot* root = node->youngestShadowRoot(); root; root = root->olderShadowRoot())
1955 root->removeAllEventListenersRecursively();
1959 typedef WillBeHeapHashMap<RawPtrWillBeWeakMember<Node>, OwnPtr<EventTargetData> > EventTargetDataMap;
1961 static EventTargetDataMap& eventTargetDataMap()
1963 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<EventTargetDataMap>, map, (adoptPtrWillBeNoop(new EventTargetDataMap())));
1967 EventTargetData* Node::eventTargetData()
1969 return hasEventTargetData() ? eventTargetDataMap().get(this) : 0;
1972 EventTargetData& Node::ensureEventTargetData()
1974 if (hasEventTargetData())
1975 return *eventTargetDataMap().get(this);
1976 setHasEventTargetData(true);
1977 EventTargetData* data = new EventTargetData;
1978 eventTargetDataMap().set(this, adoptPtr(data));
1983 void Node::clearEventTargetData()
1985 eventTargetDataMap().remove(this);
1989 WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* Node::mutationObserverRegistry()
1993 NodeMutationObserverData* data = rareData()->mutationObserverData();
1996 return &data->registry;
1999 WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* Node::transientMutationObserverRegistry()
2003 NodeMutationObserverData* data = rareData()->mutationObserverData();
2006 return &data->transientRegistry;
2009 template<typename Registry>
2010 static inline void collectMatchingObserversForMutation(WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>& observers, Registry* registry, Node& target, MutationObserver::MutationType type, const QualifiedName* attributeName)
2014 for (typename Registry::iterator iter = registry->begin(); iter != registry->end(); ++iter) {
2015 const MutationObserverRegistration& registration = **iter;
2016 if (registration.shouldReceiveMutationFrom(target, type, attributeName)) {
2017 MutationRecordDeliveryOptions deliveryOptions = registration.deliveryOptions();
2018 WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>::AddResult result = observers.add(®istration.observer(), deliveryOptions);
2019 if (!result.isNewEntry)
2020 result.storedValue->value |= deliveryOptions;
2025 void Node::getRegisteredMutationObserversOfType(WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>& observers, MutationObserver::MutationType type, const QualifiedName* attributeName)
2027 ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName);
2028 collectMatchingObserversForMutation(observers, mutationObserverRegistry(), *this, type, attributeName);
2029 collectMatchingObserversForMutation(observers, transientMutationObserverRegistry(), *this, type, attributeName);
2030 for (Node* node = parentNode(); node; node = node->parentNode()) {
2031 collectMatchingObserversForMutation(observers, node->mutationObserverRegistry(), *this, type, attributeName);
2032 collectMatchingObserversForMutation(observers, node->transientMutationObserverRegistry(), *this, type, attributeName);
2036 void Node::registerMutationObserver(MutationObserver& observer, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
2038 MutationObserverRegistration* registration = 0;
2039 WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >& registry = ensureRareData().ensureMutationObserverData().registry;
2040 for (size_t i = 0; i < registry.size(); ++i) {
2041 if (®istry[i]->observer() == &observer) {
2042 registration = registry[i].get();
2043 registration->resetObservation(options, attributeFilter);
2047 if (!registration) {
2048 registry.append(MutationObserverRegistration::create(observer, this, options, attributeFilter));
2049 registration = registry.last().get();
2052 document().addMutationObserverTypes(registration->mutationTypes());
2055 void Node::unregisterMutationObserver(MutationObserverRegistration* registration)
2057 WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* registry = mutationObserverRegistry();
2062 size_t index = registry->find(registration);
2063 ASSERT(index != kNotFound);
2064 if (index == kNotFound)
2067 // Deleting the registration may cause this node to be derefed, so we must make sure the Vector operation completes
2068 // before that, in case |this| is destroyed (see MutationObserverRegistration::m_registrationNodeKeepAlive).
2069 // FIXME: Simplify the registration/transient registration logic to make this understandable by humans.
2070 RefPtrWillBeRawPtr<Node> protect(this);
2072 // The explicit dispose() is needed to have the registration
2073 // object unregister itself promptly.
2074 registration->dispose();
2076 registry->remove(index);
2079 void Node::registerTransientMutationObserver(MutationObserverRegistration* registration)
2081 ensureRareData().ensureMutationObserverData().transientRegistry.add(registration);
2084 void Node::unregisterTransientMutationObserver(MutationObserverRegistration* registration)
2086 WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* transientRegistry = transientMutationObserverRegistry();
2087 ASSERT(transientRegistry);
2088 if (!transientRegistry)
2091 ASSERT(transientRegistry->contains(registration));
2092 transientRegistry->remove(registration);
2095 void Node::notifyMutationObserversNodeWillDetach()
2097 if (!document().hasMutationObservers())
2100 for (Node* node = parentNode(); node; node = node->parentNode()) {
2101 if (WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* registry = node->mutationObserverRegistry()) {
2102 const size_t size = registry->size();
2103 for (size_t i = 0; i < size; ++i)
2104 registry->at(i)->observedSubtreeNodeWillDetach(*this);
2107 if (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* transientRegistry = node->transientMutationObserverRegistry()) {
2108 for (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >::iterator iter = transientRegistry->begin(); iter != transientRegistry->end(); ++iter)
2109 (*iter)->observedSubtreeNodeWillDetach(*this);
2114 void Node::handleLocalEvents(Event* event)
2116 if (!hasEventTargetData())
2119 if (isDisabledFormControl(this) && event->isMouseEvent())
2122 fireEventListeners(event);
2125 void Node::dispatchScopedEvent(PassRefPtrWillBeRawPtr<Event> event)
2127 dispatchScopedEventDispatchMediator(EventDispatchMediator::create(event));
2130 void Node::dispatchScopedEventDispatchMediator(PassRefPtrWillBeRawPtr<EventDispatchMediator> eventDispatchMediator)
2132 EventDispatcher::dispatchScopedEvent(this, eventDispatchMediator);
2135 bool Node::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event)
2137 if (event->isMouseEvent())
2138 return EventDispatcher::dispatchEvent(this, MouseEventDispatchMediator::create(static_pointer_cast<MouseEvent>(event), MouseEventDispatchMediator::SyntheticMouseEvent));
2139 if (event->isTouchEvent())
2140 return dispatchTouchEvent(static_pointer_cast<TouchEvent>(event));
2141 return EventDispatcher::dispatchEvent(this, EventDispatchMediator::create(event));
2144 void Node::dispatchSubtreeModifiedEvent()
2146 if (isInShadowTree())
2149 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
2151 if (!document().hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER))
2154 dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMSubtreeModified, true));
2157 bool Node::dispatchDOMActivateEvent(int detail, PassRefPtrWillBeRawPtr<Event> underlyingEvent)
2159 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
2160 RefPtrWillBeRawPtr<UIEvent> event = UIEvent::create(EventTypeNames::DOMActivate, true, true, document().domWindow(), detail);
2161 event->setUnderlyingEvent(underlyingEvent);
2162 dispatchScopedEvent(event);
2163 return event->defaultHandled();
2166 bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& event)
2168 return EventDispatcher::dispatchEvent(this, KeyboardEventDispatchMediator::create(KeyboardEvent::create(event, document().domWindow())));
2171 bool Node::dispatchMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType,
2172 int detail, Node* relatedTarget)
2174 return EventDispatcher::dispatchEvent(this, MouseEventDispatchMediator::create(MouseEvent::create(eventType, document().domWindow(), event, detail, relatedTarget)));
2177 bool Node::dispatchGestureEvent(const PlatformGestureEvent& event)
2179 RefPtrWillBeRawPtr<GestureEvent> gestureEvent = GestureEvent::create(document().domWindow(), event);
2180 if (!gestureEvent.get())
2182 return EventDispatcher::dispatchEvent(this, GestureEventDispatchMediator::create(gestureEvent));
2185 bool Node::dispatchTouchEvent(PassRefPtrWillBeRawPtr<TouchEvent> event)
2187 return EventDispatcher::dispatchEvent(this, TouchEventDispatchMediator::create(event));
2190 void Node::dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions eventOptions)
2192 EventDispatcher::dispatchSimulatedClick(this, underlyingEvent, eventOptions);
2195 bool Node::dispatchWheelEvent(const PlatformWheelEvent& event)
2197 return EventDispatcher::dispatchEvent(this, WheelEventDispatchMediator::create(event, document().domWindow()));
2200 void Node::dispatchInputEvent()
2202 dispatchScopedEvent(Event::createBubble(EventTypeNames::input));
2205 void Node::defaultEventHandler(Event* event)
2207 if (event->target() != this)
2209 const AtomicString& eventType = event->type();
2210 if (eventType == EventTypeNames::keydown || eventType == EventTypeNames::keypress) {
2211 if (event->isKeyboardEvent()) {
2212 if (LocalFrame* frame = document().frame())
2213 frame->eventHandler().defaultKeyboardEventHandler(toKeyboardEvent(event));
2215 } else if (eventType == EventTypeNames::click) {
2216 int detail = event->isUIEvent() ? static_cast<UIEvent*>(event)->detail() : 0;
2217 if (dispatchDOMActivateEvent(detail, event))
2218 event->setDefaultHandled();
2219 } else if (eventType == EventTypeNames::contextmenu) {
2220 if (Page* page = document().page())
2221 page->contextMenuController().handleContextMenuEvent(event);
2222 } else if (eventType == EventTypeNames::textInput) {
2223 if (event->hasInterface(EventNames::TextEvent)) {
2224 if (LocalFrame* frame = document().frame())
2225 frame->eventHandler().defaultTextInputEventHandler(toTextEvent(event));
2228 } else if (eventType == EventTypeNames::mousedown && event->isMouseEvent()) {
2229 MouseEvent* mouseEvent = toMouseEvent(event);
2230 if (mouseEvent->button() == MiddleButton) {
2231 if (enclosingLinkEventParentOrSelf())
2234 // Avoid that canBeScrolledAndHasScrollableArea changes render tree
2236 // FIXME: We should avoid synchronous layout if possible. We can
2237 // remove this synchronous layout if we avoid synchronous layout in
2238 // RenderTextControlSingleLine::scrollHeight
2239 document().updateLayoutIgnorePendingStylesheets();
2240 RenderObject* renderer = this->renderer();
2241 while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()))
2242 renderer = renderer->parent();
2245 if (LocalFrame* frame = document().frame())
2246 frame->eventHandler().startPanScrolling(renderer);
2250 } else if ((eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel) && event->hasInterface(EventNames::WheelEvent)) {
2251 WheelEvent* wheelEvent = toWheelEvent(event);
2253 // If we don't have a renderer, send the wheel event to the first node we find with a renderer.
2254 // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll.
2255 Node* startNode = this;
2256 while (startNode && !startNode->renderer())
2257 startNode = startNode->parentOrShadowHostNode();
2259 if (startNode && startNode->renderer()) {
2260 if (LocalFrame* frame = document().frame())
2261 frame->eventHandler().defaultWheelEventHandler(startNode, wheelEvent);
2263 } else if (event->type() == EventTypeNames::webkitEditableContentChanged) {
2264 dispatchInputEvent();
2268 void Node::willCallDefaultEventHandler(const Event&)
2272 bool Node::willRespondToMouseMoveEvents()
2274 if (isDisabledFormControl(this))
2276 return hasEventListeners(EventTypeNames::mousemove) || hasEventListeners(EventTypeNames::mouseover) || hasEventListeners(EventTypeNames::mouseout);
2279 bool Node::willRespondToMouseClickEvents()
2281 if (isDisabledFormControl(this))
2283 return isContentEditable(UserSelectAllIsAlwaysNonEditable) || hasEventListeners(EventTypeNames::mouseup) || hasEventListeners(EventTypeNames::mousedown) || hasEventListeners(EventTypeNames::click) || hasEventListeners(EventTypeNames::DOMActivate);
2286 bool Node::willRespondToTouchEvents()
2288 if (isDisabledFormControl(this))
2290 return hasEventListeners(EventTypeNames::touchstart) || hasEventListeners(EventTypeNames::touchmove) || hasEventListeners(EventTypeNames::touchcancel) || hasEventListeners(EventTypeNames::touchend);
2294 // This is here for inlining
2295 inline void TreeScope::removedLastRefToScope()
2297 ASSERT_WITH_SECURITY_IMPLICATION(!deletionHasBegun());
2298 if (m_guardRefCount) {
2299 // If removing a child removes the last self-only ref, we don't
2300 // want the scope to be destructed until after
2301 // removeDetachedChildren returns, so we guard ourselves with an
2302 // extra self-only ref.
2306 // We need to do this right now since guardDeref() can delete this.
2307 rootNode().m_inRemovedLastRefFunction = false;
2312 rootNode().m_inRemovedLastRefFunction = false;
2314 #if ENABLE(SECURITY_ASSERT)
2321 // It's important not to inline removedLastRef, because we don't want to inline the code to
2322 // delete a Node at each deref call site.
2323 void Node::removedLastRef()
2325 // An explicit check for Document here is better than a virtual function since it is
2326 // faster for non-Document nodes, and because the call to removedLastRef that is inlined
2327 // at all deref call sites is smaller if it's a non-virtual function.
2328 if (isTreeScope()) {
2329 treeScope().removedLastRefToScope();
2333 #if ENABLE(SECURITY_ASSERT)
2334 m_deletionHasBegun = true;
2340 unsigned Node::connectedSubframeCount() const
2342 return hasRareData() ? rareData()->connectedSubframeCount() : 0;
2345 void Node::incrementConnectedSubframeCount(unsigned amount)
2347 ASSERT(isContainerNode());
2348 ensureRareData().incrementConnectedSubframeCount(amount);
2351 void Node::decrementConnectedSubframeCount(unsigned amount)
2353 rareData()->decrementConnectedSubframeCount(amount);
2356 void Node::updateAncestorConnectedSubframeCountForRemoval() const
2358 unsigned count = connectedSubframeCount();
2363 for (Node* node = parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode())
2364 node->decrementConnectedSubframeCount(count);
2367 void Node::updateAncestorConnectedSubframeCountForInsertion() const
2369 unsigned count = connectedSubframeCount();
2374 for (Node* node = parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode())
2375 node->incrementConnectedSubframeCount(count);
2378 PassRefPtrWillBeRawPtr<StaticNodeList> Node::getDestinationInsertionPoints()
2380 document().updateDistributionForNodeIfNeeded(this);
2381 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
2382 collectDestinationInsertionPoints(*this, insertionPoints);
2383 WillBeHeapVector<RefPtrWillBeMember<Node> > filteredInsertionPoints;
2384 for (size_t i = 0; i < insertionPoints.size(); ++i) {
2385 InsertionPoint* insertionPoint = insertionPoints[i];
2386 ASSERT(insertionPoint->containingShadowRoot());
2387 if (insertionPoint->containingShadowRoot()->type() != ShadowRoot::UserAgentShadowRoot)
2388 filteredInsertionPoints.append(insertionPoint);
2390 return StaticNodeList::adopt(filteredInsertionPoints);
2393 void Node::setFocus(bool flag)
2395 document().userActionElements().setFocused(this, flag);
2398 void Node::setActive(bool flag)
2400 document().userActionElements().setActive(this, flag);
2403 void Node::setHovered(bool flag)
2405 document().userActionElements().setHovered(this, flag);
2408 bool Node::isUserActionElementActive() const
2410 ASSERT(isUserActionElement());
2411 return document().userActionElements().isActive(this);
2414 bool Node::isUserActionElementInActiveChain() const
2416 ASSERT(isUserActionElement());
2417 return document().userActionElements().isInActiveChain(this);
2420 bool Node::isUserActionElementHovered() const
2422 ASSERT(isUserActionElement());
2423 return document().userActionElements().isHovered(this);
2426 bool Node::isUserActionElementFocused() const
2428 ASSERT(isUserActionElement());
2429 return document().userActionElements().isFocused(this);
2432 void Node::setCustomElementState(CustomElementState newState)
2434 CustomElementState oldState = customElementState();
2437 case NotCustomElement:
2438 ASSERT_NOT_REACHED(); // Everything starts in this state
2441 case WaitingForUpgrade:
2442 ASSERT(NotCustomElement == oldState);
2446 ASSERT(WaitingForUpgrade == oldState);
2450 ASSERT(isHTMLElement() || isSVGElement());
2451 setFlag(CustomElementFlag);
2452 setFlag(newState == Upgraded, CustomElementUpgradedFlag);
2454 if (oldState == NotCustomElement || newState == Upgraded)
2455 setNeedsStyleRecalc(SubtreeStyleChange); // :unresolved has changed
2458 void Node::trace(Visitor* visitor)
2461 visitor->trace(m_parentOrShadowHostNode);
2462 visitor->trace(m_previous);
2463 visitor->trace(m_next);
2464 // rareData() and m_data.m_renderer share their storage. We have to trace
2465 // only one of them.
2467 visitor->trace(rareData());
2469 visitor->trace(m_data.m_renderer);
2470 visitor->trace(m_treeScope);
2472 EventTarget::trace(visitor);
2475 unsigned Node::lengthOfContents() const
2477 // This switch statement must be consistent with that of Range::processContentsBetweenOffsets.
2478 switch (nodeType()) {
2479 case Node::TEXT_NODE:
2480 case Node::CDATA_SECTION_NODE:
2481 case Node::COMMENT_NODE:
2482 return toCharacterData(this)->length();
2483 case Node::PROCESSING_INSTRUCTION_NODE:
2484 return toProcessingInstruction(this)->data().length();
2485 case Node::ELEMENT_NODE:
2486 case Node::ATTRIBUTE_NODE:
2487 case Node::DOCUMENT_NODE:
2488 case Node::DOCUMENT_FRAGMENT_NODE:
2489 return toContainerNode(this)->countChildren();
2490 case Node::DOCUMENT_TYPE_NODE:
2493 ASSERT_NOT_REACHED();
2497 } // namespace blink
2501 void showNode(const blink::Node* node)
2507 void showTree(const blink::Node* node)
2510 node->showTreeForThis();
2513 void showNodePath(const blink::Node* node)
2516 node->showNodePathForThis();