Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / core / dom / Node.cpp
blobe9b822670519eb469c43ac2b1ce7c0c1df94fb17
1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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.
25 #include "config.h"
26 #include "core/dom/Node.h"
28 #include "bindings/core/v8/DOMDataStore.h"
29 #include "bindings/core/v8/ExceptionState.h"
30 #include "bindings/core/v8/V8DOMWrapper.h"
31 #include "core/HTMLNames.h"
32 #include "core/css/resolver/StyleResolver.h"
33 #include "core/dom/AXObjectCache.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/DOMNodeIds.h"
39 #include "core/dom/Document.h"
40 #include "core/dom/DocumentFragment.h"
41 #include "core/dom/DocumentType.h"
42 #include "core/dom/Element.h"
43 #include "core/dom/ElementRareData.h"
44 #include "core/dom/ElementTraversal.h"
45 #include "core/dom/ExceptionCode.h"
46 #include "core/dom/LayoutTreeBuilderTraversal.h"
47 #include "core/dom/NodeRareData.h"
48 #include "core/dom/NodeTraversal.h"
49 #include "core/dom/ProcessingInstruction.h"
50 #include "core/dom/Range.h"
51 #include "core/dom/StaticNodeList.h"
52 #include "core/dom/StyleEngine.h"
53 #include "core/dom/TemplateContentDocumentFragment.h"
54 #include "core/dom/Text.h"
55 #include "core/dom/TreeScopeAdopter.h"
56 #include "core/dom/UserActionElementSet.h"
57 #include "core/dom/shadow/ComposedTreeTraversal.h"
58 #include "core/dom/shadow/ElementShadow.h"
59 #include "core/dom/shadow/InsertionPoint.h"
60 #include "core/dom/shadow/ShadowRoot.h"
61 #include "core/editing/EditingUtilities.h"
62 #include "core/editing/markers/DocumentMarkerController.h"
63 #include "core/events/Event.h"
64 #include "core/events/EventDispatchMediator.h"
65 #include "core/events/EventDispatcher.h"
66 #include "core/events/EventListener.h"
67 #include "core/events/GestureEvent.h"
68 #include "core/events/KeyboardEvent.h"
69 #include "core/events/MouseEvent.h"
70 #include "core/events/MutationEvent.h"
71 #include "core/events/PointerEvent.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/LocalDOMWindow.h"
78 #include "core/frame/LocalFrame.h"
79 #include "core/html/HTMLDialogElement.h"
80 #include "core/html/HTMLFrameOwnerElement.h"
81 #include "core/input/EventHandler.h"
82 #include "core/layout/LayoutBox.h"
83 #include "core/page/ContextMenuController.h"
84 #include "core/page/Page.h"
85 #include "core/svg/graphics/SVGImage.h"
86 #include "platform/EventDispatchForbiddenScope.h"
87 #include "platform/TraceEvent.h"
88 #include "platform/TracedValue.h"
89 #include "wtf/HashSet.h"
90 #include "wtf/Partitions.h"
91 #include "wtf/PassOwnPtr.h"
92 #include "wtf/Vector.h"
93 #include "wtf/text/CString.h"
94 #include "wtf/text/StringBuilder.h"
96 namespace blink {
98 using namespace HTMLNames;
100 struct SameSizeAsNode : NODE_BASE_CLASSES {
101 uint32_t m_nodeFlags;
102 void* m_pointer[5];
105 static_assert(sizeof(Node) <= sizeof(SameSizeAsNode), "Node should stay small");
107 #if !ENABLE(OILPAN)
108 void* Node::operator new(size_t size)
110 ASSERT(isMainThread());
111 return partitionAlloc(WTF::Partitions::nodePartition(), size);
114 void Node::operator delete(void* ptr)
116 ASSERT(isMainThread());
117 partitionFree(ptr);
119 #endif
121 #if DUMP_NODE_STATISTICS
122 using WeakNodeSet = WillBeHeapHashSet<RawPtrWillBeWeakMember<Node>>;
123 static WeakNodeSet& liveNodeSet()
125 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<WeakNodeSet>, set, (adoptPtrWillBeNoop(new WeakNodeSet())));
126 return *set;
128 #endif
130 void Node::dumpStatistics()
132 #if DUMP_NODE_STATISTICS
133 size_t nodesWithRareData = 0;
135 size_t elementNodes = 0;
136 size_t attrNodes = 0;
137 size_t textNodes = 0;
138 size_t cdataNodes = 0;
139 size_t commentNodes = 0;
140 size_t piNodes = 0;
141 size_t documentNodes = 0;
142 size_t docTypeNodes = 0;
143 size_t fragmentNodes = 0;
144 size_t shadowRootNodes = 0;
146 HashMap<String, size_t> perTagCount;
148 size_t attributes = 0;
149 size_t elementsWithAttributeStorage = 0;
150 size_t elementsWithRareData = 0;
151 size_t elementsWithNamedNodeMap = 0;
153 for (Node* node : liveNodeSet()) {
154 if (node->hasRareData()) {
155 ++nodesWithRareData;
156 if (node->isElementNode()) {
157 ++elementsWithRareData;
158 if (toElement(node)->hasNamedNodeMap())
159 ++elementsWithNamedNodeMap;
163 switch (node->nodeType()) {
164 case ELEMENT_NODE: {
165 ++elementNodes;
167 // Tag stats
168 Element* element = toElement(node);
169 HashMap<String, size_t>::AddResult result = perTagCount.add(element->tagName(), 1);
170 if (!result.isNewEntry)
171 result.storedValue->value++;
173 if (const ElementData* elementData = element->elementData()) {
174 attributes += elementData->attributes().size();
175 ++elementsWithAttributeStorage;
177 break;
179 case ATTRIBUTE_NODE: {
180 ++attrNodes;
181 break;
183 case TEXT_NODE: {
184 ++textNodes;
185 break;
187 case CDATA_SECTION_NODE: {
188 ++cdataNodes;
189 break;
191 case COMMENT_NODE: {
192 ++commentNodes;
193 break;
195 case PROCESSING_INSTRUCTION_NODE: {
196 ++piNodes;
197 break;
199 case DOCUMENT_NODE: {
200 ++documentNodes;
201 break;
203 case DOCUMENT_TYPE_NODE: {
204 ++docTypeNodes;
205 break;
207 case DOCUMENT_FRAGMENT_NODE: {
208 if (node->isShadowRoot())
209 ++shadowRootNodes;
210 else
211 ++fragmentNodes;
212 break;
217 printf("Number of Nodes: %d\n\n", liveNodeSet().size());
218 printf("Number of Nodes with RareData: %zu\n\n", nodesWithRareData);
220 printf("NodeType distribution:\n");
221 printf(" Number of Element nodes: %zu\n", elementNodes);
222 printf(" Number of Attribute nodes: %zu\n", attrNodes);
223 printf(" Number of Text nodes: %zu\n", textNodes);
224 printf(" Number of CDATASection nodes: %zu\n", cdataNodes);
225 printf(" Number of Comment nodes: %zu\n", commentNodes);
226 printf(" Number of ProcessingInstruction nodes: %zu\n", piNodes);
227 printf(" Number of Document nodes: %zu\n", documentNodes);
228 printf(" Number of DocumentType nodes: %zu\n", docTypeNodes);
229 printf(" Number of DocumentFragment nodes: %zu\n", fragmentNodes);
230 printf(" Number of ShadowRoot nodes: %zu\n", shadowRootNodes);
232 printf("Element tag name distibution:\n");
233 for (const auto& entry : perTagCount)
234 printf(" Number of <%s> tags: %zu\n", entry.key.utf8().data(), entry.value);
236 printf("Attributes:\n");
237 printf(" Number of Attributes (non-Node and Node): %zu [%zu]\n", attributes, sizeof(Attribute));
238 printf(" Number of Elements with attribute storage: %zu [%zu]\n", elementsWithAttributeStorage, sizeof(ElementData));
239 printf(" Number of Elements with RareData: %zu\n", elementsWithRareData);
240 printf(" Number of Elements with NamedNodeMap: %zu [%zu]\n", elementsWithNamedNodeMap, sizeof(NamedNodeMap));
241 #endif
244 void Node::trackForDebugging()
246 #if DUMP_NODE_STATISTICS
247 liveNodeSet().add(this);
248 #endif
251 Node::Node(TreeScope* treeScope, ConstructionType type)
252 : m_nodeFlags(type)
253 , m_parentOrShadowHostNode(nullptr)
254 , m_treeScope(treeScope)
255 , m_previous(nullptr)
256 , m_next(nullptr)
258 ASSERT(m_treeScope || type == CreateDocument || type == CreateShadowRoot);
259 #if !ENABLE(OILPAN)
260 if (m_treeScope)
261 m_treeScope->guardRef();
262 #endif
264 #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
265 trackForDebugging();
266 #endif
267 InstanceCounters::incrementCounter(InstanceCounters::NodeCounter);
270 Node::~Node()
272 #if !ENABLE(OILPAN)
273 #if DUMP_NODE_STATISTICS
274 liveNodeSet().remove(this);
275 #endif
277 if (hasRareData())
278 clearRareData();
280 RELEASE_ASSERT(!layoutObject());
282 if (!isContainerNode())
283 willBeDeletedFromDocument();
285 if (m_previous)
286 m_previous->setNextSibling(nullptr);
287 if (m_next)
288 m_next->setPreviousSibling(nullptr);
290 if (m_treeScope)
291 m_treeScope->guardDeref();
293 if (getFlag(HasWeakReferencesFlag))
294 WeakIdentifierMap<Node>::notifyObjectDestroyed(this);
296 // clearEventTargetData() must be always done,
297 // or eventTargetDataMap() may keep a raw pointer to a deleted object.
298 ASSERT(!hasEventTargetData());
299 #else
300 // With Oilpan, the rare data finalizer also asserts for
301 // this condition (we cannot directly access it here.)
302 RELEASE_ASSERT(hasRareData() || !layoutObject());
303 #endif
305 InstanceCounters::decrementCounter(InstanceCounters::NodeCounter);
308 #if !ENABLE(OILPAN)
309 // With Oilpan all of this is handled with weak processing of the document.
310 void Node::willBeDeletedFromDocument()
312 if (hasEventTargetData())
313 clearEventTargetData();
315 if (!isTreeScopeInitialized())
316 return;
318 Document& document = this->document();
320 if (document.frameHost())
321 document.frameHost()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);
323 document.markers().removeMarkers(this);
325 #endif
327 NodeRareData* Node::rareData() const
329 ASSERT_WITH_SECURITY_IMPLICATION(hasRareData());
330 return static_cast<NodeRareData*>(m_data.m_rareData);
333 NodeRareData& Node::ensureRareData()
335 if (hasRareData())
336 return *rareData();
338 if (isElementNode())
339 m_data.m_rareData = ElementRareData::create(m_data.m_layoutObject);
340 else
341 m_data.m_rareData = NodeRareData::create(m_data.m_layoutObject);
343 ASSERT(m_data.m_rareData);
345 setFlag(HasRareDataFlag);
346 return *rareData();
349 #if !ENABLE(OILPAN)
350 void Node::clearRareData()
352 ASSERT(hasRareData());
353 ASSERT(!transientMutationObserverRegistry() || transientMutationObserverRegistry()->isEmpty());
355 LayoutObject* layoutObject = m_data.m_rareData->layoutObject();
356 if (isElementNode())
357 delete static_cast<ElementRareData*>(m_data.m_rareData);
358 else
359 delete static_cast<NodeRareData*>(m_data.m_rareData);
360 m_data.m_layoutObject = layoutObject;
361 clearFlag(HasRareDataFlag);
363 #endif
365 Node* Node::toNode()
367 return this;
370 short Node::tabIndex() const
372 return 0;
375 String Node::nodeValue() const
377 return String();
380 void Node::setNodeValue(const String&)
382 // By default, setting nodeValue has no effect.
385 PassRefPtrWillBeRawPtr<NodeList> Node::childNodes()
387 if (isContainerNode())
388 return ensureRareData().ensureNodeLists().ensureChildNodeList(toContainerNode(*this));
389 return ensureRareData().ensureNodeLists().ensureEmptyChildNodeList(*this);
392 Node* Node::pseudoAwarePreviousSibling() const
394 if (parentElement() && !previousSibling()) {
395 Element* parent = parentElement();
396 if (isAfterPseudoElement() && parent->lastChild())
397 return parent->lastChild();
398 if (!isBeforePseudoElement())
399 return parent->pseudoElement(BEFORE);
401 return previousSibling();
404 Node* Node::pseudoAwareNextSibling() const
406 if (parentElement() && !nextSibling()) {
407 Element* parent = parentElement();
408 if (isBeforePseudoElement() && parent->hasChildren())
409 return parent->firstChild();
410 if (!isAfterPseudoElement())
411 return parent->pseudoElement(AFTER);
413 return nextSibling();
416 Node* Node::pseudoAwareFirstChild() const
418 if (isElementNode()) {
419 const Element* currentElement = toElement(this);
420 Node* first = currentElement->pseudoElement(BEFORE);
421 if (first)
422 return first;
423 first = currentElement->firstChild();
424 if (!first)
425 first = currentElement->pseudoElement(AFTER);
426 return first;
429 return firstChild();
432 Node* Node::pseudoAwareLastChild() const
434 if (isElementNode()) {
435 const Element* currentElement = toElement(this);
436 Node* last = currentElement->pseudoElement(AFTER);
437 if (last)
438 return last;
439 last = currentElement->lastChild();
440 if (!last)
441 last = currentElement->pseudoElement(BEFORE);
442 return last;
445 return lastChild();
448 PassRefPtrWillBeRawPtr<Node> Node::insertBefore(PassRefPtrWillBeRawPtr<Node> newChild, Node* refChild, ExceptionState& exceptionState)
450 if (isContainerNode())
451 return toContainerNode(this)->insertBefore(newChild, refChild, exceptionState);
453 exceptionState.throwDOMException(HierarchyRequestError, "This node type does not support this method.");
454 return nullptr;
457 PassRefPtrWillBeRawPtr<Node> Node::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, PassRefPtrWillBeRawPtr<Node> oldChild, ExceptionState& exceptionState)
459 if (isContainerNode())
460 return toContainerNode(this)->replaceChild(newChild, oldChild, exceptionState);
462 exceptionState.throwDOMException(HierarchyRequestError, "This node type does not support this method.");
463 return nullptr;
466 PassRefPtrWillBeRawPtr<Node> Node::removeChild(PassRefPtrWillBeRawPtr<Node> oldChild, ExceptionState& exceptionState)
468 if (isContainerNode())
469 return toContainerNode(this)->removeChild(oldChild, exceptionState);
471 exceptionState.throwDOMException(NotFoundError, "This node type does not support this method.");
472 return nullptr;
475 PassRefPtrWillBeRawPtr<Node> Node::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, ExceptionState& exceptionState)
477 if (isContainerNode())
478 return toContainerNode(this)->appendChild(newChild, exceptionState);
480 exceptionState.throwDOMException(HierarchyRequestError, "This node type does not support this method.");
481 return nullptr;
484 void Node::remove(ExceptionState& exceptionState)
486 if (ContainerNode* parent = parentNode())
487 parent->removeChild(this, exceptionState);
490 void Node::normalize()
492 updateDistribution();
494 // Go through the subtree beneath us, normalizing all nodes. This means that
495 // any two adjacent text nodes are merged and any empty text nodes are removed.
497 RefPtrWillBeRawPtr<Node> node = this;
498 while (Node* firstChild = node->firstChild())
499 node = firstChild;
500 while (node) {
501 if (node == this)
502 break;
504 if (node->nodeType() == TEXT_NODE)
505 node = toText(node)->mergeNextSiblingNodesIfPossible();
506 else
507 node = NodeTraversal::nextPostOrder(*node);
511 bool Node::isContentEditable(UserSelectAllTreatment treatment) const
513 document().updateLayoutTreeIfNeeded();
514 return hasEditableStyle(Editable, treatment);
517 bool Node::isContentRichlyEditable() const
519 document().updateLayoutTreeIfNeeded();
520 return hasEditableStyle(RichlyEditable, UserSelectAllIsAlwaysNonEditable);
523 bool Node::hasEditableStyle(EditableLevel editableLevel, UserSelectAllTreatment treatment) const
525 if (isPseudoElement())
526 return false;
528 // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but
529 // ContainerNode::setFocus() calls setNeedsStyleRecalc(), so the assertion
530 // would fire in the middle of Document::setFocusedNode().
532 for (const Node* node = this; node; node = node->parentNode()) {
533 if ((node->isHTMLElement() || node->isDocumentNode()) && node->layoutObject()) {
534 // Elements with user-select: all style are considered atomic
535 // therefore non editable.
536 if (nodeIsUserSelectAll(node) && treatment == UserSelectAllIsAlwaysNonEditable)
537 return false;
538 switch (node->layoutObject()->style()->userModify()) {
539 case READ_ONLY:
540 return false;
541 case READ_WRITE:
542 return true;
543 case READ_WRITE_PLAINTEXT_ONLY:
544 return editableLevel != RichlyEditable;
546 ASSERT_NOT_REACHED();
547 return false;
551 return false;
554 bool Node::isEditableToAccessibility(EditableLevel editableLevel) const
556 if (hasEditableStyle(editableLevel))
557 return true;
559 // FIXME: Respect editableLevel for ARIA editable elements.
560 if (editableLevel == RichlyEditable)
561 return false;
563 // FIXME(dmazzoni): support ScopedAXObjectCache (crbug/489851).
564 if (AXObjectCache* cache = document().existingAXObjectCache())
565 return cache->rootAXEditableElement(this);
567 return false;
570 LayoutBox* Node::layoutBox() const
572 LayoutObject* layoutObject = this->layoutObject();
573 return layoutObject && layoutObject->isBox() ? toLayoutBox(layoutObject) : nullptr;
576 LayoutBoxModelObject* Node::layoutBoxModelObject() const
578 LayoutObject* layoutObject = this->layoutObject();
579 return layoutObject && layoutObject->isBoxModelObject() ? toLayoutBoxModelObject(layoutObject) : nullptr;
582 LayoutRect Node::boundingBox() const
584 if (layoutObject())
585 return LayoutRect(layoutObject()->absoluteBoundingBoxRect());
586 return LayoutRect();
589 #ifndef NDEBUG
590 inline static ShadowRoot* oldestShadowRootFor(const Node* node)
592 if (!node->isElementNode())
593 return nullptr;
594 if (ElementShadow* shadow = toElement(node)->shadow())
595 return shadow->oldestShadowRoot();
596 return nullptr;
598 #endif
600 inline static Node& rootInTreeOfTrees(const Node& node)
602 if (node.inDocument())
603 return node.document();
604 Node* root = const_cast<Node*>(&node);
605 while (Node* host = root->shadowHost())
606 root = host;
607 while (Node* ancestor = root->parentNode())
608 root = ancestor;
609 ASSERT(!root->shadowHost());
610 return *root;
613 #if ENABLE(ASSERT)
614 bool Node::needsDistributionRecalc() const
616 return rootInTreeOfTrees(*this).childNeedsDistributionRecalc();
618 #endif
620 void Node::updateDistribution()
622 // Extra early out to avoid spamming traces.
623 if (inDocument() && !document().childNeedsDistributionRecalc())
624 return;
625 TRACE_EVENT0("blink", "Node::updateDistribution");
626 ScriptForbiddenScope forbidScript;
627 Node& root = rootInTreeOfTrees(*this);
628 if (root.childNeedsDistributionRecalc())
629 root.recalcDistribution();
632 void Node::recalcDistribution()
634 ASSERT(childNeedsDistributionRecalc());
636 if (isElementNode()) {
637 if (ElementShadow* shadow = toElement(this)->shadow())
638 shadow->distributeIfNeeded();
641 for (Node* child = firstChild(); child; child = child->nextSibling()) {
642 if (child->childNeedsDistributionRecalc())
643 child->recalcDistribution();
646 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
647 if (root->childNeedsDistributionRecalc())
648 root->recalcDistribution();
651 clearChildNeedsDistributionRecalc();
654 void Node::setIsLink(bool isLink)
656 setFlag(isLink && !SVGImage::isInSVGImage(toElement(this)), IsLinkFlag);
659 void Node::setNeedsStyleInvalidation()
661 ASSERT(isElementNode());
662 setFlag(NeedsStyleInvalidationFlag);
663 markAncestorsWithChildNeedsStyleInvalidation();
666 void Node::markAncestorsWithChildNeedsStyleInvalidation()
668 for (Node* node = parentOrShadowHostNode(); node && !node->childNeedsStyleInvalidation(); node = node->parentOrShadowHostNode())
669 node->setChildNeedsStyleInvalidation();
670 document().scheduleLayoutTreeUpdateIfNeeded();
673 void Node::markAncestorsWithChildNeedsDistributionRecalc()
675 for (Node* node = this; node && !node->childNeedsDistributionRecalc(); node = node->parentOrShadowHostNode())
676 node->setChildNeedsDistributionRecalc();
677 document().scheduleLayoutTreeUpdateIfNeeded();
680 inline void Node::setStyleChange(StyleChangeType changeType)
682 m_nodeFlags = (m_nodeFlags & ~StyleChangeMask) | changeType;
685 void Node::markAncestorsWithChildNeedsStyleRecalc()
687 for (ContainerNode* p = parentOrShadowHostNode(); p && !p->childNeedsStyleRecalc(); p = p->parentOrShadowHostNode())
688 p->setChildNeedsStyleRecalc();
689 document().scheduleLayoutTreeUpdateIfNeeded();
692 void Node::setNeedsStyleRecalc(StyleChangeType changeType, const StyleChangeReasonForTracing& reason)
694 ASSERT(changeType != NoStyleChange);
695 if (!inActiveDocument())
696 return;
698 TRACE_EVENT_INSTANT1(
699 TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"),
700 "StyleRecalcInvalidationTracking",
701 TRACE_EVENT_SCOPE_THREAD,
702 "data",
703 InspectorStyleRecalcInvalidationTrackingEvent::data(this, reason));
705 StyleChangeType existingChangeType = styleChangeType();
706 if (changeType > existingChangeType)
707 setStyleChange(changeType);
709 if (existingChangeType == NoStyleChange)
710 markAncestorsWithChildNeedsStyleRecalc();
712 if (isElementNode() && hasRareData())
713 toElement(*this).setAnimationStyleChange(false);
716 void Node::clearNeedsStyleRecalc()
718 m_nodeFlags &= ~StyleChangeMask;
720 clearSVGFilterNeedsLayerUpdate();
722 if (isElementNode() && hasRareData())
723 toElement(*this).setAnimationStyleChange(false);
726 bool Node::inActiveDocument() const
728 return inDocument() && document().isActive();
731 Node* Node::focusDelegate()
733 return this;
736 bool Node::shouldHaveFocusAppearance() const
738 ASSERT(focused());
739 return true;
742 bool Node::isInert() const
744 const HTMLDialogElement* dialog = document().activeModalDialog();
745 if (dialog && this != document() && (!canParticipateInComposedTree() || !ComposedTreeTraversal::containsIncludingPseudoElement(*dialog, *this)))
746 return true;
747 return document().ownerElement() && document().ownerElement()->isInert();
750 unsigned Node::nodeIndex() const
752 Node* tempNode = previousSibling();
753 unsigned count = 0;
754 for (count = 0; tempNode; count++)
755 tempNode = tempNode->previousSibling();
756 return count;
759 NodeListsNodeData* Node::nodeLists()
761 return hasRareData() ? rareData()->nodeLists() : nullptr;
764 void Node::clearNodeLists()
766 rareData()->clearNodeLists();
769 bool Node::isDescendantOf(const Node *other) const
771 // Return true if other is an ancestor of this, otherwise false
772 if (!other || !other->hasChildren() || inDocument() != other->inDocument())
773 return false;
774 if (other->treeScope() != treeScope())
775 return false;
776 if (other->isTreeScope())
777 return !isTreeScope();
778 for (const ContainerNode* n = parentNode(); n; n = n->parentNode()) {
779 if (n == other)
780 return true;
782 return false;
785 bool Node::contains(const Node* node) const
787 if (!node)
788 return false;
789 return this == node || node->isDescendantOf(this);
792 bool Node::containsIncludingShadowDOM(const Node* node) const
794 if (!node)
795 return false;
797 if (this == node)
798 return true;
800 if (document() != node->document())
801 return false;
803 if (inDocument() != node->inDocument())
804 return false;
806 bool hasChildren = isContainerNode() && toContainerNode(this)->hasChildren();
807 bool hasShadow = isElementNode() && toElement(this)->shadow();
808 if (!hasChildren && !hasShadow)
809 return false;
811 for (; node; node = node->shadowHost()) {
812 if (treeScope() == node->treeScope())
813 return contains(node);
816 return false;
819 bool Node::containsIncludingHostElements(const Node& node) const
821 const Node* current = &node;
822 do {
823 if (current == this)
824 return true;
825 if (current->isDocumentFragment() && toDocumentFragment(current)->isTemplateContent())
826 current = static_cast<const TemplateContentDocumentFragment*>(current)->host();
827 else
828 current = current->parentOrShadowHostNode();
829 } while (current);
830 return false;
833 Node* Node::commonAncestor(const Node& other, ContainerNode* (*parent)(const Node&)) const
835 if (this == other)
836 return const_cast<Node*>(this);
837 if (document() != other.document())
838 return nullptr;
839 int thisDepth = 0;
840 for (const Node* node = this; node; node = parent(*node)) {
841 if (node == &other)
842 return const_cast<Node*>(node);
843 thisDepth++;
845 int otherDepth = 0;
846 for (const Node* node = &other; node; node = parent(*node)) {
847 if (node == this)
848 return const_cast<Node*>(this);
849 otherDepth++;
851 const Node* thisIterator = this;
852 const Node* otherIterator = &other;
853 if (thisDepth > otherDepth) {
854 for (int i = thisDepth; i > otherDepth; --i)
855 thisIterator = parent(*thisIterator);
856 } else if (otherDepth > thisDepth) {
857 for (int i = otherDepth; i > thisDepth; --i)
858 otherIterator = parent(*otherIterator);
860 while (thisIterator) {
861 if (thisIterator == otherIterator)
862 return const_cast<Node*>(thisIterator);
863 thisIterator = parent(*thisIterator);
864 otherIterator = parent(*otherIterator);
866 ASSERT(!otherIterator);
867 return nullptr;
870 void Node::reattach(const AttachContext& context)
872 AttachContext reattachContext(context);
873 reattachContext.performingReattach = true;
875 // We only need to detach if the node has already been through attach().
876 if (styleChangeType() < NeedsReattachStyleChange)
877 detach(reattachContext);
878 attach(reattachContext);
881 void Node::attach(const AttachContext&)
883 ASSERT(document().inStyleRecalc() || isDocumentNode());
884 ASSERT(!document().lifecycle().inDetach());
885 ASSERT(needsAttach());
886 ASSERT(!layoutObject() || (layoutObject()->style() && (layoutObject()->parent() || layoutObject()->isLayoutView())));
888 clearNeedsStyleRecalc();
890 if (AXObjectCache* cache = document().axObjectCache())
891 cache->updateCacheAfterNodeIsAttached(this);
894 void Node::detach(const AttachContext& context)
896 ASSERT(document().lifecycle().stateAllowsDetach());
897 DocumentLifecycle::DetachScope willDetach(document().lifecycle());
899 if (layoutObject())
900 layoutObject()->destroyAndCleanupAnonymousWrappers();
901 setLayoutObject(nullptr);
903 setStyleChange(NeedsReattachStyleChange);
904 clearChildNeedsStyleInvalidation();
907 void Node::reattachWhitespaceSiblingsIfNeeded(Text* start)
909 for (Node* sibling = start; sibling; sibling = sibling->nextSibling()) {
910 if (sibling->isTextNode() && toText(sibling)->containsOnlyWhitespace()) {
911 bool hadLayoutObject = !!sibling->layoutObject();
912 toText(sibling)->reattachIfNeeded();
913 // If sibling's layout object status didn't change we don't need to continue checking
914 // other siblings since their layout object status won't change either.
915 if (!!sibling->layoutObject() == hadLayoutObject)
916 return;
917 } else if (sibling->layoutObject()) {
918 return;
923 const ComputedStyle* Node::virtualEnsureComputedStyle(PseudoId pseudoElementSpecifier)
925 return parentOrShadowHostNode() ? parentOrShadowHostNode()->ensureComputedStyle(pseudoElementSpecifier) : nullptr;
928 int Node::maxCharacterOffset() const
930 ASSERT_NOT_REACHED();
931 return 0;
934 // FIXME: Shouldn't these functions be in the editing code? Code that asks questions about HTML in the core DOM class
935 // is obviously misplaced.
936 bool Node::canStartSelection() const
938 if (hasEditableStyle())
939 return true;
941 if (layoutObject()) {
942 const ComputedStyle& style = layoutObject()->styleRef();
943 // We allow selections to begin within an element that has -webkit-user-select: none set,
944 // but if the element is draggable then dragging should take priority over selection.
945 if (style.userDrag() == DRAG_ELEMENT && style.userSelect() == SELECT_NONE)
946 return false;
948 return parentOrShadowHostNode() ? parentOrShadowHostNode()->canStartSelection() : true;
951 bool Node::canParticipateInComposedTree() const
953 return !isShadowRoot() && !isActiveInsertionPoint(*this);
956 Element* Node::shadowHost() const
958 if (ShadowRoot* root = containingShadowRoot())
959 return root->host();
960 return nullptr;
963 ShadowRoot* Node::containingShadowRoot() const
965 Node& root = treeScope().rootNode();
966 return root.isShadowRoot() ? toShadowRoot(&root) : nullptr;
969 Node* Node::nonBoundaryShadowTreeRootNode()
971 ASSERT(!isShadowRoot());
972 Node* root = this;
973 while (root) {
974 if (root->isShadowRoot())
975 return root;
976 Node* parent = root->parentOrShadowHostNode();
977 if (parent && parent->isShadowRoot())
978 return root;
979 root = parent;
981 return nullptr;
984 ContainerNode* Node::nonShadowBoundaryParentNode() const
986 ContainerNode* parent = parentNode();
987 return parent && !parent->isShadowRoot() ? parent : nullptr;
990 Element* Node::parentOrShadowHostElement() const
992 ContainerNode* parent = parentOrShadowHostNode();
993 if (!parent)
994 return nullptr;
996 if (parent->isShadowRoot())
997 return toShadowRoot(parent)->host();
999 if (!parent->isElementNode())
1000 return nullptr;
1002 return toElement(parent);
1005 ContainerNode* Node::parentOrShadowHostOrTemplateHostNode() const
1007 if (isDocumentFragment() && toDocumentFragment(this)->isTemplateContent())
1008 return static_cast<const TemplateContentDocumentFragment*>(this)->host();
1009 return parentOrShadowHostNode();
1012 bool Node::isRootEditableElement() const
1014 return hasEditableStyle() && isElementNode() && (!parentNode() || !parentNode()->hasEditableStyle()
1015 || !parentNode()->isElementNode() || isHTMLBodyElement((*this)));
1018 Element* Node::rootEditableElement(EditableType editableType) const
1020 if (editableType == HasEditableAXRole) {
1021 if (AXObjectCache* cache = document().existingAXObjectCache())
1022 return const_cast<Element*>(cache->rootAXEditableElement(this));
1025 return rootEditableElement();
1028 Element* Node::rootEditableElement() const
1030 Element* result = nullptr;
1031 for (Node* n = const_cast<Node*>(this); n && n->hasEditableStyle(); n = n->parentNode()) {
1032 if (n->isElementNode())
1033 result = toElement(n);
1034 if (isHTMLBodyElement(*n))
1035 break;
1037 return result;
1040 // FIXME: End of obviously misplaced HTML editing functions. Try to move these out of Node.
1042 Document* Node::ownerDocument() const
1044 Document* doc = &document();
1045 return doc == this ? nullptr : doc;
1048 KURL Node::baseURI() const
1050 return parentNode() ? parentNode()->baseURI() : KURL();
1053 bool Node::isEqualNode(Node* other) const
1055 if (!other)
1056 return false;
1058 NodeType nodeType = this->nodeType();
1059 if (nodeType != other->nodeType())
1060 return false;
1062 if (nodeName() != other->nodeName())
1063 return false;
1065 if (nodeValue() != other->nodeValue())
1066 return false;
1068 if (isAttributeNode()) {
1069 if (toAttr(this)->localName() != toAttr(other)->localName())
1070 return false;
1072 if (toAttr(this)->namespaceURI() != toAttr(other)->namespaceURI())
1073 return false;
1074 } else if (isElementNode()) {
1075 if (toElement(this)->localName() != toElement(other)->localName())
1076 return false;
1078 if (toElement(this)->namespaceURI() != toElement(other)->namespaceURI())
1079 return false;
1081 if (!toElement(this)->hasEquivalentAttributes(toElement(other)))
1082 return false;
1085 Node* child = firstChild();
1086 Node* otherChild = other->firstChild();
1088 while (child) {
1089 if (!child->isEqualNode(otherChild))
1090 return false;
1092 child = child->nextSibling();
1093 otherChild = otherChild->nextSibling();
1096 if (otherChild)
1097 return false;
1099 if (isDocumentTypeNode()) {
1100 const DocumentType* documentTypeThis = toDocumentType(this);
1101 const DocumentType* documentTypeOther = toDocumentType(other);
1103 if (documentTypeThis->publicId() != documentTypeOther->publicId())
1104 return false;
1106 if (documentTypeThis->systemId() != documentTypeOther->systemId())
1107 return false;
1110 return true;
1113 bool Node::isDefaultNamespace(const AtomicString& namespaceURIMaybeEmpty) const
1115 const AtomicString& namespaceURI = namespaceURIMaybeEmpty.isEmpty() ? nullAtom : namespaceURIMaybeEmpty;
1117 switch (nodeType()) {
1118 case ELEMENT_NODE: {
1119 const Element& element = toElement(*this);
1121 if (element.prefix().isNull())
1122 return element.namespaceURI() == namespaceURI;
1124 AttributeCollection attributes = element.attributes();
1125 for (const Attribute& attr : attributes) {
1126 if (attr.localName() == xmlnsAtom)
1127 return attr.value() == namespaceURI;
1130 if (Element* parent = parentElement())
1131 return parent->isDefaultNamespace(namespaceURI);
1133 return false;
1135 case DOCUMENT_NODE:
1136 if (Element* de = toDocument(this)->documentElement())
1137 return de->isDefaultNamespace(namespaceURI);
1138 return false;
1139 case DOCUMENT_TYPE_NODE:
1140 case DOCUMENT_FRAGMENT_NODE:
1141 return false;
1142 case ATTRIBUTE_NODE: {
1143 const Attr* attr = toAttr(this);
1144 if (attr->ownerElement())
1145 return attr->ownerElement()->isDefaultNamespace(namespaceURI);
1146 return false;
1148 default:
1149 if (Element* parent = parentElement())
1150 return parent->isDefaultNamespace(namespaceURI);
1151 return false;
1155 const AtomicString& Node::lookupPrefix(const AtomicString& namespaceURI) const
1157 // Implemented according to
1158 // http://dom.spec.whatwg.org/#dom-node-lookupprefix
1160 if (namespaceURI.isEmpty() || namespaceURI.isNull())
1161 return nullAtom;
1163 const Element* context;
1165 switch (nodeType()) {
1166 case ELEMENT_NODE:
1167 context = toElement(this);
1168 break;
1169 case DOCUMENT_NODE:
1170 context = toDocument(this)->documentElement();
1171 break;
1172 case DOCUMENT_FRAGMENT_NODE:
1173 case DOCUMENT_TYPE_NODE:
1174 context = nullptr;
1175 break;
1176 // FIXME: Remove this when Attr no longer extends Node (CR305105)
1177 case ATTRIBUTE_NODE:
1178 context = toAttr(this)->ownerElement();
1179 break;
1180 default:
1181 context = parentElement();
1182 break;
1185 if (!context)
1186 return nullAtom;
1188 return context->locateNamespacePrefix(namespaceURI);
1191 const AtomicString& Node::lookupNamespaceURI(const String& prefix) const
1193 // Implemented according to
1194 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespaceURIAlgo
1196 if (!prefix.isNull() && prefix.isEmpty())
1197 return nullAtom;
1199 switch (nodeType()) {
1200 case ELEMENT_NODE: {
1201 const Element& element = toElement(*this);
1203 if (!element.namespaceURI().isNull() && element.prefix() == prefix)
1204 return element.namespaceURI();
1206 AttributeCollection attributes = element.attributes();
1207 for (const Attribute& attr : attributes) {
1208 if (attr.prefix() == xmlnsAtom && attr.localName() == prefix) {
1209 if (!attr.value().isEmpty())
1210 return attr.value();
1211 return nullAtom;
1213 if (attr.localName() == xmlnsAtom && prefix.isNull()) {
1214 if (!attr.value().isEmpty())
1215 return attr.value();
1216 return nullAtom;
1220 if (Element* parent = parentElement())
1221 return parent->lookupNamespaceURI(prefix);
1222 return nullAtom;
1224 case DOCUMENT_NODE:
1225 if (Element* de = toDocument(this)->documentElement())
1226 return de->lookupNamespaceURI(prefix);
1227 return nullAtom;
1228 case DOCUMENT_TYPE_NODE:
1229 case DOCUMENT_FRAGMENT_NODE:
1230 return nullAtom;
1231 case ATTRIBUTE_NODE: {
1232 const Attr *attr = toAttr(this);
1233 if (attr->ownerElement())
1234 return attr->ownerElement()->lookupNamespaceURI(prefix);
1235 return nullAtom;
1237 default:
1238 if (Element* parent = parentElement())
1239 return parent->lookupNamespaceURI(prefix);
1240 return nullAtom;
1244 String Node::textContent(bool convertBRsToNewlines) const
1246 // This covers ProcessingInstruction and Comment that should return their
1247 // value when .textContent is accessed on them, but should be ignored when
1248 // iterated over as a descendant of a ContainerNode.
1249 if (isCharacterDataNode())
1250 return toCharacterData(this)->data();
1252 // Documents and non-container nodes (that are not CharacterData)
1253 // have null textContent.
1254 if (isDocumentNode() || !isContainerNode())
1255 return String();
1257 StringBuilder content;
1258 for (Node& node : NodeTraversal::inclusiveDescendantsOf(*this)) {
1259 if (isHTMLBRElement(node) && convertBRsToNewlines) {
1260 content.append('\n');
1261 } else if (node.isTextNode()) {
1262 content.append(toText(node).data());
1265 return content.toString();
1268 void Node::setTextContent(const String& text)
1270 switch (nodeType()) {
1271 case TEXT_NODE:
1272 case CDATA_SECTION_NODE:
1273 case COMMENT_NODE:
1274 case PROCESSING_INSTRUCTION_NODE:
1275 setNodeValue(text);
1276 return;
1277 case ELEMENT_NODE:
1278 case DOCUMENT_FRAGMENT_NODE: {
1279 // FIXME: Merge this logic into replaceChildrenWithText.
1280 RefPtrWillBeRawPtr<ContainerNode> container = toContainerNode(this);
1282 // Note: This is an intentional optimization.
1283 // See crbug.com/352836 also.
1284 // No need to do anything if the text is identical.
1285 if (container->hasOneTextChild() && toText(container->firstChild())->data() == text)
1286 return;
1288 ChildListMutationScope mutation(*this);
1289 // Note: This API will not insert empty text nodes:
1290 // http://dom.spec.whatwg.org/#dom-node-textcontent
1291 if (text.isEmpty()) {
1292 container->removeChildren(DispatchSubtreeModifiedEvent);
1293 } else {
1294 container->removeChildren(OmitSubtreeModifiedEvent);
1295 container->appendChild(document().createTextNode(text), ASSERT_NO_EXCEPTION);
1297 return;
1299 case ATTRIBUTE_NODE:
1300 case DOCUMENT_NODE:
1301 case DOCUMENT_TYPE_NODE:
1302 // Do nothing.
1303 return;
1305 ASSERT_NOT_REACHED();
1308 bool Node::offsetInCharacters() const
1310 return isCharacterDataNode();
1313 unsigned short Node::compareDocumentPosition(const Node* otherNode, ShadowTreesTreatment treatment) const
1315 if (otherNode == this)
1316 return DOCUMENT_POSITION_EQUIVALENT;
1318 const Attr* attr1 = nodeType() == ATTRIBUTE_NODE ? toAttr(this) : nullptr;
1319 const Attr* attr2 = otherNode->nodeType() == ATTRIBUTE_NODE ? toAttr(otherNode) : nullptr;
1321 const Node* start1 = attr1 ? attr1->ownerElement() : this;
1322 const Node* start2 = attr2 ? attr2->ownerElement() : otherNode;
1324 // If either of start1 or start2 is null, then we are disconnected, since one of the nodes is
1325 // an orphaned attribute node.
1326 if (!start1 || !start2) {
1327 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING;
1328 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction;
1331 Vector<const Node*, 16> chain1;
1332 Vector<const Node*, 16> chain2;
1333 if (attr1)
1334 chain1.append(attr1);
1335 if (attr2)
1336 chain2.append(attr2);
1338 if (attr1 && attr2 && start1 == start2 && start1) {
1339 // We are comparing two attributes on the same node. Crawl our attribute map and see which one we hit first.
1340 const Element* owner1 = attr1->ownerElement();
1341 AttributeCollection attributes = owner1->attributes();
1342 for (const Attribute& attr : attributes) {
1343 // If neither of the two determining nodes is a child node and nodeType is the same for both determining nodes, then an
1344 // implementation-dependent order between the determining nodes is returned. This order is stable as long as no nodes of
1345 // the same nodeType are inserted into or removed from the direct container. This would be the case, for example,
1346 // when comparing two attributes of the same element, and inserting or removing additional attributes might change
1347 // the order between existing attributes.
1348 if (attr1->qualifiedName() == attr.name())
1349 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING;
1350 if (attr2->qualifiedName() == attr.name())
1351 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_PRECEDING;
1354 ASSERT_NOT_REACHED();
1355 return DOCUMENT_POSITION_DISCONNECTED;
1358 // If one node is in the document and the other is not, we must be disconnected.
1359 // If the nodes have different owning documents, they must be disconnected. Note that we avoid
1360 // comparing Attr nodes here, since they return false from inDocument() all the time (which seems like a bug).
1361 if (start1->inDocument() != start2->inDocument() || (treatment == TreatShadowTreesAsDisconnected && start1->treeScope() != start2->treeScope())) {
1362 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING;
1363 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction;
1366 // We need to find a common ancestor container, and then compare the indices of the two immediate children.
1367 const Node* current;
1368 for (current = start1; current; current = current->parentOrShadowHostNode())
1369 chain1.append(current);
1370 for (current = start2; current; current = current->parentOrShadowHostNode())
1371 chain2.append(current);
1373 unsigned index1 = chain1.size();
1374 unsigned index2 = chain2.size();
1376 // If the two elements don't have a common root, they're not in the same tree.
1377 if (chain1[index1 - 1] != chain2[index2 - 1]) {
1378 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING;
1379 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction;
1382 unsigned connection = start1->treeScope() != start2->treeScope() ? DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 0;
1384 // Walk the two chains backwards and look for the first difference.
1385 for (unsigned i = std::min(index1, index2); i; --i) {
1386 const Node* child1 = chain1[--index1];
1387 const Node* child2 = chain2[--index2];
1388 if (child1 != child2) {
1389 // If one of the children is an attribute, it wins.
1390 if (child1->nodeType() == ATTRIBUTE_NODE)
1391 return DOCUMENT_POSITION_FOLLOWING | connection;
1392 if (child2->nodeType() == ATTRIBUTE_NODE)
1393 return DOCUMENT_POSITION_PRECEDING | connection;
1395 // If one of the children is a shadow root,
1396 if (child1->isShadowRoot() || child2->isShadowRoot()) {
1397 if (!child2->isShadowRoot())
1398 return Node::DOCUMENT_POSITION_FOLLOWING | connection;
1399 if (!child1->isShadowRoot())
1400 return Node::DOCUMENT_POSITION_PRECEDING | connection;
1402 for (ShadowRoot* child = toShadowRoot(child2)->olderShadowRoot(); child; child = child->olderShadowRoot()) {
1403 if (child == child1) {
1404 return Node::DOCUMENT_POSITION_FOLLOWING | connection;
1408 return Node::DOCUMENT_POSITION_PRECEDING | connection;
1411 if (!child2->nextSibling())
1412 return DOCUMENT_POSITION_FOLLOWING | connection;
1413 if (!child1->nextSibling())
1414 return DOCUMENT_POSITION_PRECEDING | connection;
1416 // Otherwise we need to see which node occurs first. Crawl backwards from child2 looking for child1.
1417 for (Node* child = child2->previousSibling(); child; child = child->previousSibling()) {
1418 if (child == child1)
1419 return DOCUMENT_POSITION_FOLLOWING | connection;
1421 return DOCUMENT_POSITION_PRECEDING | connection;
1425 // There was no difference between the two parent chains, i.e., one was a subset of the other. The shorter
1426 // chain is the ancestor.
1427 return index1 < index2 ?
1428 DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_CONTAINED_BY | connection :
1429 DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_CONTAINS | connection;
1432 String Node::debugName() const
1434 StringBuilder name;
1435 name.append(nodeName());
1437 if (isElementNode()) {
1438 const Element& thisElement = toElement(*this);
1439 if (thisElement.hasID()) {
1440 name.appendLiteral(" id=\'");
1441 name.append(thisElement.getIdAttribute());
1442 name.append('\'');
1445 if (thisElement.hasClass()) {
1446 name.appendLiteral(" class=\'");
1447 for (size_t i = 0; i < thisElement.classNames().size(); ++i) {
1448 if (i > 0)
1449 name.append(' ');
1450 name.append(thisElement.classNames()[i]);
1452 name.append('\'');
1456 return name.toString();
1459 #ifndef NDEBUG
1461 static void appendAttributeDesc(const Node* node, StringBuilder& stringBuilder, const QualifiedName& name, const char* attrDesc)
1463 if (!node->isElementNode())
1464 return;
1466 String attr = toElement(node)->getAttribute(name);
1467 if (attr.isEmpty())
1468 return;
1470 stringBuilder.append(attrDesc);
1471 stringBuilder.appendLiteral("=\"");
1472 stringBuilder.append(attr);
1473 stringBuilder.appendLiteral("\"");
1476 void Node::showNode(const char* prefix) const
1478 if (!prefix)
1479 prefix = "";
1480 if (isTextNode()) {
1481 String value = nodeValue();
1482 value.replaceWithLiteral('\\', "\\\\");
1483 value.replaceWithLiteral('\n', "\\n");
1484 WTFLogAlways("%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this, value.utf8().data());
1485 } else {
1486 StringBuilder attrs;
1487 appendAttributeDesc(this, attrs, idAttr, " ID");
1488 appendAttributeDesc(this, attrs, classAttr, " CLASS");
1489 appendAttributeDesc(this, attrs, styleAttr, " STYLE");
1490 WTFLogAlways("%s%s\t%p%s\n", prefix, nodeName().utf8().data(), this, attrs.toString().utf8().data());
1494 void Node::showTreeForThis() const
1496 showTreeAndMark(this, "*");
1499 void Node::showTreeForThisInComposedTree() const
1501 showTreeAndMarkInComposedTree(this, "*");
1504 void Node::showNodePathForThis() const
1506 Vector<const Node*, 16> chain;
1507 const Node* node = this;
1508 while (node->parentOrShadowHostNode()) {
1509 chain.append(node);
1510 node = node->parentOrShadowHostNode();
1512 for (unsigned index = chain.size(); index > 0; --index) {
1513 const Node* node = chain[index - 1];
1514 if (node->isShadowRoot()) {
1515 int count = 0;
1516 for (ShadowRoot* shadowRoot = toShadowRoot(node)->olderShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot())
1517 ++count;
1518 WTFLogAlways("/#shadow-root[%d]", count);
1519 continue;
1522 switch (node->nodeType()) {
1523 case ELEMENT_NODE: {
1524 WTFLogAlways("/%s", node->nodeName().utf8().data());
1526 const Element* element = toElement(node);
1527 const AtomicString& idattr = element->getIdAttribute();
1528 bool hasIdAttr = !idattr.isNull() && !idattr.isEmpty();
1529 if (node->previousSibling() || node->nextSibling()) {
1530 int count = 0;
1531 for (Node* previous = node->previousSibling(); previous; previous = previous->previousSibling()) {
1532 if (previous->nodeName() == node->nodeName()) {
1533 ++count;
1536 if (hasIdAttr)
1537 WTFLogAlways("[@id=\"%s\" and position()=%d]", idattr.utf8().data(), count);
1538 else
1539 WTFLogAlways("[%d]", count);
1540 } else if (hasIdAttr) {
1541 WTFLogAlways("[@id=\"%s\"]", idattr.utf8().data());
1543 break;
1545 case TEXT_NODE:
1546 WTFLogAlways("/text()");
1547 break;
1548 case ATTRIBUTE_NODE:
1549 WTFLogAlways("/@%s", node->nodeName().utf8().data());
1550 break;
1551 default:
1552 break;
1555 WTFLogAlways("\n");
1558 static void traverseTreeAndMark(const String& baseIndent, const Node* rootNode, const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2)
1560 for (Node& node : NodeTraversal::inclusiveDescendantsOf(*rootNode)) {
1561 StringBuilder indent;
1562 if (node == markedNode1)
1563 indent.append(markedLabel1);
1564 if (node == markedNode2)
1565 indent.append(markedLabel2);
1566 indent.append(baseIndent);
1567 for (const Node* tmpNode = &node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentOrShadowHostNode())
1568 indent.append('\t');
1569 node.showNode(indent.toString().utf8().data());
1570 indent.append('\t');
1572 if (node.isElementNode()) {
1573 const Element& element = toElement(node);
1574 if (Element* pseudo = element.pseudoElement(BEFORE))
1575 traverseTreeAndMark(indent.toString(), pseudo, markedNode1, markedLabel1, markedNode2, markedLabel2);
1576 if (Element* pseudo = element.pseudoElement(AFTER))
1577 traverseTreeAndMark(indent.toString(), pseudo, markedNode1, markedLabel1, markedNode2, markedLabel2);
1578 if (Element* pseudo = element.pseudoElement(FIRST_LETTER))
1579 traverseTreeAndMark(indent.toString(), pseudo, markedNode1, markedLabel1, markedNode2, markedLabel2);
1580 if (Element* pseudo = element.pseudoElement(BACKDROP))
1581 traverseTreeAndMark(indent.toString(), pseudo, markedNode1, markedLabel1, markedNode2, markedLabel2);
1584 if (node.isShadowRoot()) {
1585 if (ShadowRoot* youngerShadowRoot = toShadowRoot(node).youngerShadowRoot())
1586 traverseTreeAndMark(indent.toString(), youngerShadowRoot, markedNode1, markedLabel1, markedNode2, markedLabel2);
1587 } else if (ShadowRoot* oldestShadowRoot = oldestShadowRootFor(&node)) {
1588 traverseTreeAndMark(indent.toString(), oldestShadowRoot, markedNode1, markedLabel1, markedNode2, markedLabel2);
1593 static void traverseTreeAndMarkInComposedTree(const String& baseIndent, const Node* rootNode, const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2)
1595 for (const Node* node = rootNode; node; node = ComposedTreeTraversal::nextSibling(*node)) {
1596 StringBuilder indent;
1597 if (node == markedNode1)
1598 indent.append(markedLabel1);
1599 if (node == markedNode2)
1600 indent.append(markedLabel2);
1601 indent.append(baseIndent);
1602 node->showNode(indent.toString().utf8().data());
1603 indent.append('\t');
1605 Node* child = ComposedTreeTraversal::firstChild(*node);
1606 if (child)
1607 traverseTreeAndMarkInComposedTree(indent.toString(), child, markedNode1, markedLabel1, markedNode2, markedLabel2);
1611 void Node::showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2) const
1613 const Node* rootNode;
1614 const Node* node = this;
1615 while (node->parentOrShadowHostNode() && !isHTMLBodyElement(*node))
1616 node = node->parentOrShadowHostNode();
1617 rootNode = node;
1619 String startingIndent;
1620 traverseTreeAndMark(startingIndent, rootNode, markedNode1, markedLabel1, markedNode2, markedLabel2);
1623 void Node::showTreeAndMarkInComposedTree(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2) const
1625 const Node* rootNode;
1626 const Node* node = this;
1627 while (node->parentOrShadowHostNode() && !isHTMLBodyElement(*node))
1628 node = node->parentOrShadowHostNode();
1629 rootNode = node;
1631 String startingIndent;
1632 traverseTreeAndMarkInComposedTree(startingIndent, rootNode, markedNode1, markedLabel1, markedNode2, markedLabel2);
1635 void Node::formatForDebugger(char* buffer, unsigned length) const
1637 String result;
1638 String s;
1640 s = nodeName();
1641 if (s.isEmpty())
1642 result = "<none>";
1643 else
1644 result = s;
1646 strncpy(buffer, result.utf8().data(), length - 1);
1649 static ContainerNode* parentOrShadowHostOrFrameOwner(const Node* node)
1651 ContainerNode* parent = node->parentOrShadowHostNode();
1652 if (!parent && node->document().frame())
1653 parent = node->document().frame()->deprecatedLocalOwner();
1654 return parent;
1657 static void showSubTreeAcrossFrame(const Node* node, const Node* markedNode, const String& indent)
1659 if (node == markedNode)
1660 fputs("*", stderr);
1661 fputs(indent.utf8().data(), stderr);
1662 node->showNode();
1663 if (node->isShadowRoot()) {
1664 if (ShadowRoot* youngerShadowRoot = toShadowRoot(node)->youngerShadowRoot())
1665 showSubTreeAcrossFrame(youngerShadowRoot, markedNode, indent + "\t");
1666 } else {
1667 if (node->isFrameOwnerElement())
1668 showSubTreeAcrossFrame(toHTMLFrameOwnerElement(node)->contentDocument(), markedNode, indent + "\t");
1669 if (ShadowRoot* oldestShadowRoot = oldestShadowRootFor(node))
1670 showSubTreeAcrossFrame(oldestShadowRoot, markedNode, indent + "\t");
1672 for (Node* child = node->firstChild(); child; child = child->nextSibling())
1673 showSubTreeAcrossFrame(child, markedNode, indent + "\t");
1676 void Node::showTreeForThisAcrossFrame() const
1678 Node* rootNode = const_cast<Node*>(this);
1679 while (parentOrShadowHostOrFrameOwner(rootNode))
1680 rootNode = parentOrShadowHostOrFrameOwner(rootNode);
1681 showSubTreeAcrossFrame(rootNode, this, "");
1684 #endif
1686 // --------
1688 Element* Node::enclosingLinkEventParentOrSelf() const
1690 for (Node* node = const_cast<Node*>(this); node; node = ComposedTreeTraversal::parent(*node)) {
1691 // For imagemaps, the enclosing link node is the associated area element not the image itself.
1692 // So we don't let images be the enclosingLinkNode, even though isLink sometimes returns true
1693 // for them.
1694 if (node->isLink() && !isHTMLImageElement(*node)) {
1695 // Casting to Element is safe because only HTMLAnchorElement, HTMLImageElement and
1696 // SVGAElement can return true for isLink().
1697 return toElement(node);
1701 return nullptr;
1704 const AtomicString& Node::interfaceName() const
1706 return EventTargetNames::Node;
1709 ExecutionContext* Node::executionContext() const
1711 return document().contextDocument().get();
1714 void Node::didMoveToNewDocument(Document& oldDocument)
1716 TreeScopeAdopter::ensureDidMoveToNewDocumentWasCalled(oldDocument);
1718 if (const EventTargetData* eventTargetData = this->eventTargetData()) {
1719 const EventListenerMap& listenerMap = eventTargetData->eventListenerMap;
1720 if (!listenerMap.isEmpty()) {
1721 Vector<AtomicString> types = listenerMap.eventTypes();
1722 for (unsigned i = 0; i < types.size(); ++i)
1723 document().addListenerTypeIfNeeded(types[i]);
1727 oldDocument.markers().removeMarkers(this);
1728 oldDocument.updateRangesAfterNodeMovedToAnotherDocument(*this);
1729 if (oldDocument.frameHost() && !document().frameHost())
1730 oldDocument.frameHost()->eventHandlerRegistry().didMoveOutOfFrameHost(*this);
1731 else if (document().frameHost() && !oldDocument.frameHost())
1732 document().frameHost()->eventHandlerRegistry().didMoveIntoFrameHost(*this);
1733 else if (oldDocument.frameHost() != document().frameHost())
1734 EventHandlerRegistry::didMoveBetweenFrameHosts(*this, oldDocument.frameHost(), document().frameHost());
1736 if (WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration>>* registry = mutationObserverRegistry()) {
1737 for (size_t i = 0; i < registry->size(); ++i) {
1738 document().addMutationObserverTypes(registry->at(i)->mutationTypes());
1742 if (transientMutationObserverRegistry()) {
1743 for (MutationObserverRegistration* registration : *transientMutationObserverRegistry())
1744 document().addMutationObserverTypes(registration->mutationTypes());
1748 static inline bool tryAddEventListener(Node* targetNode, const AtomicString& eventType, PassRefPtrWillBeRawPtr<EventListener> listener, bool useCapture)
1750 if (!targetNode->EventTarget::addEventListener(eventType, listener, useCapture))
1751 return false;
1753 Document& document = targetNode->document();
1754 document.addListenerTypeIfNeeded(eventType);
1755 if (document.frameHost())
1756 document.frameHost()->eventHandlerRegistry().didAddEventHandler(*targetNode, eventType);
1758 return true;
1761 bool Node::addEventListener(const AtomicString& eventType, PassRefPtrWillBeRawPtr<EventListener> listener, bool useCapture)
1763 return tryAddEventListener(this, eventType, listener, useCapture);
1766 static inline bool tryRemoveEventListener(Node* targetNode, const AtomicString& eventType, PassRefPtrWillBeRawPtr<EventListener> listener, bool useCapture)
1768 if (!targetNode->EventTarget::removeEventListener(eventType, listener, useCapture))
1769 return false;
1771 // FIXME: Notify Document that the listener has vanished. We need to keep track of a number of
1772 // listeners for each type, not just a bool - see https://bugs.webkit.org/show_bug.cgi?id=33861
1773 Document& document = targetNode->document();
1774 if (document.frameHost())
1775 document.frameHost()->eventHandlerRegistry().didRemoveEventHandler(*targetNode, eventType);
1777 return true;
1780 bool Node::removeEventListener(const AtomicString& eventType, PassRefPtrWillBeRawPtr<EventListener> listener, bool useCapture)
1782 return tryRemoveEventListener(this, eventType, listener, useCapture);
1785 void Node::removeAllEventListeners()
1787 if (hasEventListeners() && document().frameHost())
1788 document().frameHost()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);
1789 EventTarget::removeAllEventListeners();
1792 void Node::removeAllEventListenersRecursively()
1794 for (Node& node : NodeTraversal::startsAt(this)) {
1795 node.removeAllEventListeners();
1796 for (ShadowRoot* root = node.youngestShadowRoot(); root; root = root->olderShadowRoot())
1797 root->removeAllEventListenersRecursively();
1801 using EventTargetDataMap = WillBeHeapHashMap<RawPtrWillBeWeakMember<Node>, OwnPtrWillBeMember<EventTargetData>>;
1802 static EventTargetDataMap& eventTargetDataMap()
1804 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<EventTargetDataMap>, map, (adoptPtrWillBeNoop(new EventTargetDataMap())));
1805 return *map;
1808 EventTargetData* Node::eventTargetData()
1810 return hasEventTargetData() ? eventTargetDataMap().get(this) : nullptr;
1813 EventTargetData& Node::ensureEventTargetData()
1815 if (hasEventTargetData())
1816 return *eventTargetDataMap().get(this);
1817 ASSERT(!eventTargetDataMap().contains(this));
1818 setHasEventTargetData(true);
1819 OwnPtrWillBeRawPtr<EventTargetData> data = adoptPtrWillBeNoop(new EventTargetData);
1820 EventTargetData* dataPtr = data.get();
1821 eventTargetDataMap().set(this, data.release());
1822 return *dataPtr;
1825 #if !ENABLE(OILPAN)
1826 void Node::clearEventTargetData()
1828 eventTargetDataMap().remove(this);
1829 #if ENABLE(ASSERT)
1830 setHasEventTargetData(false);
1831 #endif
1833 #endif
1835 WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration>>* Node::mutationObserverRegistry()
1837 if (!hasRareData())
1838 return nullptr;
1839 NodeMutationObserverData* data = rareData()->mutationObserverData();
1840 if (!data)
1841 return nullptr;
1842 return &data->registry;
1845 WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration>>* Node::transientMutationObserverRegistry()
1847 if (!hasRareData())
1848 return nullptr;
1849 NodeMutationObserverData* data = rareData()->mutationObserverData();
1850 if (!data)
1851 return nullptr;
1852 return &data->transientRegistry;
1855 template<typename Registry>
1856 static inline void collectMatchingObserversForMutation(WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>& observers, Registry* registry, Node& target, MutationObserver::MutationType type, const QualifiedName* attributeName)
1858 if (!registry)
1859 return;
1861 for (const auto& registration : *registry) {
1862 if (registration->shouldReceiveMutationFrom(target, type, attributeName)) {
1863 MutationRecordDeliveryOptions deliveryOptions = registration->deliveryOptions();
1864 WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>::AddResult result = observers.add(&registration->observer(), deliveryOptions);
1865 if (!result.isNewEntry)
1866 result.storedValue->value |= deliveryOptions;
1871 void Node::getRegisteredMutationObserversOfType(WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>& observers, MutationObserver::MutationType type, const QualifiedName* attributeName)
1873 ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName);
1874 collectMatchingObserversForMutation(observers, mutationObserverRegistry(), *this, type, attributeName);
1875 collectMatchingObserversForMutation(observers, transientMutationObserverRegistry(), *this, type, attributeName);
1876 for (Node* node = parentNode(); node; node = node->parentNode()) {
1877 collectMatchingObserversForMutation(observers, node->mutationObserverRegistry(), *this, type, attributeName);
1878 collectMatchingObserversForMutation(observers, node->transientMutationObserverRegistry(), *this, type, attributeName);
1882 void Node::registerMutationObserver(MutationObserver& observer, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
1884 MutationObserverRegistration* registration = nullptr;
1885 WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration>>& registry = ensureRareData().ensureMutationObserverData().registry;
1886 for (size_t i = 0; i < registry.size(); ++i) {
1887 if (&registry[i]->observer() == &observer) {
1888 registration = registry[i].get();
1889 registration->resetObservation(options, attributeFilter);
1893 if (!registration) {
1894 registry.append(MutationObserverRegistration::create(observer, this, options, attributeFilter));
1895 registration = registry.last().get();
1898 document().addMutationObserverTypes(registration->mutationTypes());
1901 void Node::unregisterMutationObserver(MutationObserverRegistration* registration)
1903 WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration>>* registry = mutationObserverRegistry();
1904 ASSERT(registry);
1905 if (!registry)
1906 return;
1908 size_t index = registry->find(registration);
1909 ASSERT(index != kNotFound);
1910 if (index == kNotFound)
1911 return;
1913 // Deleting the registration may cause this node to be derefed, so we must make sure the Vector operation completes
1914 // before that, in case |this| is destroyed (see MutationObserverRegistration::m_registrationNodeKeepAlive).
1915 // FIXME: Simplify the registration/transient registration logic to make this understandable by humans.
1916 RefPtrWillBeRawPtr<Node> protect(this);
1917 #if ENABLE(OILPAN)
1918 // The explicit dispose() is needed to have the registration
1919 // object unregister itself promptly.
1920 registration->dispose();
1921 #endif
1922 registry->remove(index);
1925 void Node::registerTransientMutationObserver(MutationObserverRegistration* registration)
1927 ensureRareData().ensureMutationObserverData().transientRegistry.add(registration);
1930 void Node::unregisterTransientMutationObserver(MutationObserverRegistration* registration)
1932 WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration>>* transientRegistry = transientMutationObserverRegistry();
1933 ASSERT(transientRegistry);
1934 if (!transientRegistry)
1935 return;
1937 ASSERT(transientRegistry->contains(registration));
1938 transientRegistry->remove(registration);
1941 void Node::notifyMutationObserversNodeWillDetach()
1943 if (!document().hasMutationObservers())
1944 return;
1946 for (Node* node = parentNode(); node; node = node->parentNode()) {
1947 if (WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration>>* registry = node->mutationObserverRegistry()) {
1948 const size_t size = registry->size();
1949 for (size_t i = 0; i < size; ++i)
1950 registry->at(i)->observedSubtreeNodeWillDetach(*this);
1953 if (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration>>* transientRegistry = node->transientMutationObserverRegistry()) {
1954 for (auto& registration : *transientRegistry)
1955 registration->observedSubtreeNodeWillDetach(*this);
1960 void Node::handleLocalEvents(Event& event)
1962 if (!hasEventTargetData())
1963 return;
1965 if (isDisabledFormControl(this) && event.isMouseEvent())
1966 return;
1968 fireEventListeners(&event);
1971 void Node::dispatchScopedEvent(PassRefPtrWillBeRawPtr<Event> event)
1973 event->setTrusted(true);
1974 EventDispatcher::dispatchScopedEvent(*this, event->createMediator());
1977 bool Node::dispatchEventInternal(PassRefPtrWillBeRawPtr<Event> event)
1979 return EventDispatcher::dispatchEvent(*this, event->createMediator());
1982 void Node::dispatchSubtreeModifiedEvent()
1984 if (isInShadowTree())
1985 return;
1987 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
1989 if (!document().hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER))
1990 return;
1992 dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMSubtreeModified, true));
1995 bool Node::dispatchDOMActivateEvent(int detail, PassRefPtrWillBeRawPtr<Event> underlyingEvent)
1997 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
1998 RefPtrWillBeRawPtr<UIEvent> event = UIEvent::create(EventTypeNames::DOMActivate, true, true, document().domWindow(), detail);
1999 event->setUnderlyingEvent(underlyingEvent);
2000 dispatchScopedEvent(event);
2001 return event->defaultHandled();
2004 bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& nativeEvent)
2006 return dispatchEvent(KeyboardEvent::create(nativeEvent, document().domWindow()));
2009 bool Node::dispatchMouseEvent(const PlatformMouseEvent& nativeEvent, const AtomicString& eventType,
2010 int detail, Node* relatedTarget)
2012 RefPtrWillBeRawPtr<MouseEvent> event = MouseEvent::create(eventType, document().domWindow(), nativeEvent, detail, relatedTarget);
2013 return dispatchEvent(event);
2016 bool Node::dispatchGestureEvent(const PlatformGestureEvent& event)
2018 RefPtrWillBeRawPtr<GestureEvent> gestureEvent = GestureEvent::create(document().domWindow(), event);
2019 if (!gestureEvent.get())
2020 return false;
2021 return dispatchEvent(gestureEvent);
2024 void Node::dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions eventOptions, SimulatedClickCreationScope scope)
2026 EventDispatcher::dispatchSimulatedClick(*this, underlyingEvent, eventOptions, scope);
2029 bool Node::dispatchWheelEvent(const PlatformWheelEvent& event)
2031 return dispatchEvent(WheelEvent::create(event, document().domWindow()));
2034 void Node::dispatchInputEvent()
2036 dispatchScopedEvent(Event::createBubble(EventTypeNames::input));
2039 void Node::defaultEventHandler(Event* event)
2041 if (event->target() != this)
2042 return;
2043 const AtomicString& eventType = event->type();
2044 if (eventType == EventTypeNames::keydown || eventType == EventTypeNames::keypress) {
2045 if (event->isKeyboardEvent()) {
2046 if (LocalFrame* frame = document().frame())
2047 frame->eventHandler().defaultKeyboardEventHandler(toKeyboardEvent(event));
2049 } else if (eventType == EventTypeNames::click) {
2050 int detail = event->isUIEvent() ? static_cast<UIEvent*>(event)->detail() : 0;
2051 if (dispatchDOMActivateEvent(detail, event))
2052 event->setDefaultHandled();
2053 } else if (eventType == EventTypeNames::contextmenu) {
2054 if (Page* page = document().page())
2055 page->contextMenuController().handleContextMenuEvent(event);
2056 } else if (eventType == EventTypeNames::textInput) {
2057 if (event->hasInterface(EventNames::TextEvent)) {
2058 if (LocalFrame* frame = document().frame())
2059 frame->eventHandler().defaultTextInputEventHandler(toTextEvent(event));
2061 #if OS(WIN)
2062 } else if (eventType == EventTypeNames::mousedown && event->isMouseEvent()) {
2063 MouseEvent* mouseEvent = toMouseEvent(event);
2064 if (mouseEvent->button() == MiddleButton) {
2065 if (enclosingLinkEventParentOrSelf())
2066 return;
2068 // Avoid that canBeScrolledAndHasScrollableArea changes layout tree
2069 // structure.
2070 // FIXME: We should avoid synchronous layout if possible. We can
2071 // remove this synchronous layout if we avoid synchronous layout in
2072 // LayoutTextControlSingleLine::scrollHeight
2073 document().updateLayoutIgnorePendingStylesheets();
2074 LayoutObject* layoutObject = this->layoutObject();
2075 while (layoutObject && (!layoutObject->isBox() || !toLayoutBox(layoutObject)->canBeScrolledAndHasScrollableArea()))
2076 layoutObject = layoutObject->parent();
2078 if (layoutObject) {
2079 if (LocalFrame* frame = document().frame())
2080 frame->eventHandler().startPanScrolling(layoutObject);
2083 #endif
2084 } else if ((eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel) && event->hasInterface(EventNames::WheelEvent)) {
2085 WheelEvent* wheelEvent = toWheelEvent(event);
2087 // If we don't have a layoutObject, send the wheel event to the first node we find with a layoutObject.
2088 // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll.
2089 Node* startNode = this;
2090 while (startNode && !startNode->layoutObject())
2091 startNode = startNode->parentOrShadowHostNode();
2093 if (startNode && startNode->layoutObject()) {
2094 if (LocalFrame* frame = document().frame())
2095 frame->eventHandler().defaultWheelEventHandler(startNode, wheelEvent);
2097 } else if (event->type() == EventTypeNames::webkitEditableContentChanged) {
2098 dispatchInputEvent();
2102 void Node::willCallDefaultEventHandler(const Event&)
2106 bool Node::willRespondToMouseMoveEvents()
2108 if (isDisabledFormControl(this))
2109 return false;
2110 return hasEventListeners(EventTypeNames::mousemove) || hasEventListeners(EventTypeNames::mouseover) || hasEventListeners(EventTypeNames::mouseout);
2113 bool Node::willRespondToMouseClickEvents()
2115 if (isDisabledFormControl(this))
2116 return false;
2117 return isContentEditable(UserSelectAllIsAlwaysNonEditable) || hasEventListeners(EventTypeNames::mouseup) || hasEventListeners(EventTypeNames::mousedown) || hasEventListeners(EventTypeNames::click) || hasEventListeners(EventTypeNames::DOMActivate);
2120 bool Node::willRespondToTouchEvents()
2122 if (isDisabledFormControl(this))
2123 return false;
2124 return hasEventListeners(EventTypeNames::touchstart) || hasEventListeners(EventTypeNames::touchmove) || hasEventListeners(EventTypeNames::touchcancel) || hasEventListeners(EventTypeNames::touchend);
2127 #if !ENABLE(OILPAN)
2128 // This is here for inlining
2129 inline void TreeScope::removedLastRefToScope()
2131 ASSERT_WITH_SECURITY_IMPLICATION(!deletionHasBegun());
2132 if (m_guardRefCount) {
2133 // If removing a child removes the last self-only ref, we don't
2134 // want the scope to be destructed until after
2135 // removeDetachedChildren returns, so we guard ourselves with an
2136 // extra self-only ref.
2137 guardRef();
2138 dispose();
2139 #if ENABLE(ASSERT)
2140 // We need to do this right now since guardDeref() can delete this.
2141 rootNode().m_inRemovedLastRefFunction = false;
2142 #endif
2143 guardDeref();
2144 } else {
2145 #if ENABLE(ASSERT)
2146 rootNode().m_inRemovedLastRefFunction = false;
2147 #endif
2148 #if ENABLE(SECURITY_ASSERT)
2149 beginDeletion();
2150 #endif
2151 delete this;
2155 // It's important not to inline removedLastRef, because we don't want to inline the code to
2156 // delete a Node at each deref call site.
2157 void Node::removedLastRef()
2159 // An explicit check for Document here is better than a virtual function since it is
2160 // faster for non-Document nodes, and because the call to removedLastRef that is inlined
2161 // at all deref call sites is smaller if it's a non-virtual function.
2162 if (isTreeScope()) {
2163 treeScope().removedLastRefToScope();
2164 return;
2167 #if ENABLE(SECURITY_ASSERT)
2168 m_deletionHasBegun = true;
2169 #endif
2170 delete this;
2172 #endif
2174 unsigned Node::connectedSubframeCount() const
2176 return hasRareData() ? rareData()->connectedSubframeCount() : 0;
2179 void Node::incrementConnectedSubframeCount(unsigned amount)
2181 ASSERT(isContainerNode());
2182 ensureRareData().incrementConnectedSubframeCount(amount);
2185 void Node::decrementConnectedSubframeCount(unsigned amount)
2187 rareData()->decrementConnectedSubframeCount(amount);
2190 void Node::updateAncestorConnectedSubframeCountForInsertion() const
2192 unsigned count = connectedSubframeCount();
2194 if (!count)
2195 return;
2197 for (Node* node = parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode())
2198 node->incrementConnectedSubframeCount(count);
2201 PassRefPtrWillBeRawPtr<StaticNodeList> Node::getDestinationInsertionPoints()
2203 updateDistribution();
2204 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
2205 collectDestinationInsertionPoints(*this, insertionPoints);
2206 WillBeHeapVector<RefPtrWillBeMember<Node>> filteredInsertionPoints;
2207 for (size_t i = 0; i < insertionPoints.size(); ++i) {
2208 InsertionPoint* insertionPoint = insertionPoints[i];
2209 ASSERT(insertionPoint->containingShadowRoot());
2210 if (!insertionPoint->containingShadowRoot()->isOpen())
2211 break;
2212 filteredInsertionPoints.append(insertionPoint);
2214 return StaticNodeList::adopt(filteredInsertionPoints);
2217 void Node::setFocus(bool flag)
2219 document().userActionElements().setFocused(this, flag);
2222 void Node::setActive(bool flag)
2224 document().userActionElements().setActive(this, flag);
2227 void Node::setHovered(bool flag)
2229 document().userActionElements().setHovered(this, flag);
2232 bool Node::isUserActionElementActive() const
2234 ASSERT(isUserActionElement());
2235 return document().userActionElements().isActive(this);
2238 bool Node::isUserActionElementInActiveChain() const
2240 ASSERT(isUserActionElement());
2241 return document().userActionElements().isInActiveChain(this);
2244 bool Node::isUserActionElementHovered() const
2246 ASSERT(isUserActionElement());
2247 return document().userActionElements().isHovered(this);
2250 bool Node::isUserActionElementFocused() const
2252 ASSERT(isUserActionElement());
2253 return document().userActionElements().isFocused(this);
2256 void Node::setCustomElementState(CustomElementState newState)
2258 CustomElementState oldState = customElementState();
2260 switch (newState) {
2261 case NotCustomElement:
2262 ASSERT_NOT_REACHED(); // Everything starts in this state
2263 return;
2265 case WaitingForUpgrade:
2266 ASSERT(NotCustomElement == oldState);
2267 break;
2269 case Upgraded:
2270 ASSERT(WaitingForUpgrade == oldState);
2271 break;
2274 ASSERT(isHTMLElement() || isSVGElement());
2275 setFlag(CustomElementFlag);
2276 setFlag(newState == Upgraded, CustomElementUpgradedFlag);
2278 if (oldState == NotCustomElement || newState == Upgraded)
2279 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::createWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Unresolved)); // :unresolved has changed
2282 DEFINE_TRACE(Node)
2284 #if ENABLE(OILPAN)
2285 visitor->trace(m_parentOrShadowHostNode);
2286 visitor->trace(m_previous);
2287 visitor->trace(m_next);
2288 // rareData() and m_data.m_layoutObject share their storage. We have to trace
2289 // only one of them.
2290 if (hasRareData())
2291 visitor->trace(rareData());
2293 visitor->trace(m_treeScope);
2294 #endif
2295 EventTarget::trace(visitor);
2298 unsigned Node::lengthOfContents() const
2300 // This switch statement must be consistent with that of Range::processContentsBetweenOffsets.
2301 switch (nodeType()) {
2302 case Node::TEXT_NODE:
2303 case Node::CDATA_SECTION_NODE:
2304 case Node::COMMENT_NODE:
2305 return toCharacterData(this)->length();
2306 case Node::PROCESSING_INSTRUCTION_NODE:
2307 return toProcessingInstruction(this)->data().length();
2308 case Node::ELEMENT_NODE:
2309 case Node::DOCUMENT_NODE:
2310 case Node::DOCUMENT_FRAGMENT_NODE:
2311 return toContainerNode(this)->countChildren();
2312 case Node::ATTRIBUTE_NODE:
2313 case Node::DOCUMENT_TYPE_NODE:
2314 return 0;
2316 ASSERT_NOT_REACHED();
2317 return 0;
2320 v8::Local<v8::Object> Node::wrap(v8::Isolate* isolate, v8::Local<v8::Object> creationContext)
2322 // It's possible that no one except for the new wrapper owns this object at
2323 // this moment, so we have to prevent GC to collect this object until the
2324 // object gets associated with the wrapper.
2325 RefPtrWillBeRawPtr<Node> protect(this);
2327 ASSERT(!DOMDataStore::containsWrapper(this, isolate));
2329 const WrapperTypeInfo* wrapperType = wrapperTypeInfo();
2331 v8::Local<v8::Object> wrapper = V8DOMWrapper::createWrapper(isolate, creationContext, wrapperType, this);
2332 if (UNLIKELY(wrapper.IsEmpty()))
2333 return wrapper;
2335 wrapperType->installConditionallyEnabledProperties(wrapper, isolate);
2336 return associateWithWrapper(isolate, wrapperType, wrapper);
2339 v8::Local<v8::Object> Node::associateWithWrapper(v8::Isolate* isolate, const WrapperTypeInfo* wrapperType, v8::Local<v8::Object> wrapper)
2341 return V8DOMWrapper::associateObjectWithWrapper(isolate, this, wrapperType, wrapper);
2344 } // namespace blink
2346 #ifndef NDEBUG
2348 void showNode(const blink::Node* node)
2350 if (node)
2351 node->showNode("");
2352 else
2353 fprintf(stderr, "Cannot showNode for (nil)\n");
2356 void showTree(const blink::Node* node)
2358 if (node)
2359 node->showTreeForThis();
2360 else
2361 fprintf(stderr, "Cannot showTree for (nil)\n");
2364 void showNodePath(const blink::Node* node)
2366 if (node)
2367 node->showNodePathForThis();
2368 else
2369 fprintf(stderr, "Cannot showNodePath for (nil)\n");
2372 #endif