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-2017 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/)
8 *
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.
13 *
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.
18 *
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.
23 */
24
25#include "config.h"
26#include "Node.h"
27
28#include "AXObjectCache.h"
29#include "Attr.h"
30#include "BeforeLoadEvent.h"
31#include "ChildListMutationScope.h"
32#include "CommonVM.h"
33#include "ComposedTreeAncestorIterator.h"
34#include "ContainerNodeAlgorithms.h"
35#include "ContextMenuController.h"
36#include "DOMWindow.h"
37#include "DataTransfer.h"
38#include "DocumentType.h"
39#include "ElementIterator.h"
40#include "ElementRareData.h"
41#include "ElementTraversal.h"
42#include "EventDispatcher.h"
43#include "EventHandler.h"
44#include "FrameView.h"
45#include "HTMLAreaElement.h"
46#include "HTMLBodyElement.h"
47#include "HTMLCollection.h"
48#include "HTMLElement.h"
49#include "HTMLImageElement.h"
50#include "HTMLSlotElement.h"
51#include "HTMLStyleElement.h"
52#include "InputEvent.h"
53#include "InspectorController.h"
54#include "KeyboardEvent.h"
55#include "Logging.h"
56#include "MutationEvent.h"
57#include "NodeRenderStyle.h"
58#include "ProcessingInstruction.h"
59#include "ProgressEvent.h"
60#include "Range.h"
61#include "RenderBlock.h"
62#include "RenderBox.h"
63#include "RenderTextControl.h"
64#include "RenderView.h"
65#include "SVGElement.h"
66#include "ScopedEventQueue.h"
67#include "ScriptDisallowedScope.h"
68#include "StorageEvent.h"
69#include "StyleResolver.h"
70#include "StyleSheetContents.h"
71#include "TemplateContentDocumentFragment.h"
72#include "TextEvent.h"
73#include "TouchEvent.h"
74#include "WheelEvent.h"
75#include "XMLNSNames.h"
76#include "XMLNames.h"
77#include <wtf/IsoMallocInlines.h>
78#include <wtf/RefCountedLeakCounter.h>
79#include <wtf/SHA1.h>
80#include <wtf/Variant.h>
81#include <wtf/text/CString.h>
82#include <wtf/text/StringBuilder.h>
83
84namespace WebCore {
85
86WTF_MAKE_ISO_ALLOCATED_IMPL(Node);
87
88using namespace HTMLNames;
89
90#if DUMP_NODE_STATISTICS
91static HashSet<Node*>& liveNodeSet()
92{
93 static NeverDestroyed<HashSet<Node*>> liveNodes;
94 return liveNodes;
95}
96
97static const char* stringForRareDataUseType(NodeRareData::UseType useType)
98{
99 switch (useType) {
100 case NodeRareData::UseType::ConnectedFrameCount:
101 return "ConnectedFrameCount";
102 case NodeRareData::UseType::NodeList:
103 return "NodeList";
104 case NodeRareData::UseType::MutationObserver:
105 return "MutationObserver";
106 case NodeRareData::UseType::TabIndex:
107 return "TabIndex";
108 case NodeRareData::UseType::StyleFlags:
109 return "StyleFlags";
110 case NodeRareData::UseType::MinimumSize:
111 return "MinimumSize";
112 case NodeRareData::UseType::ScrollingPosition:
113 return "ScrollingPosition";
114 case NodeRareData::UseType::ComputedStyle:
115 return "ComputedStyle";
116 case NodeRareData::UseType::Dataset:
117 return "Dataset";
118 case NodeRareData::UseType::ClassList:
119 return "ClassList";
120 case NodeRareData::UseType::ShadowRoot:
121 return "ShadowRoot";
122 case NodeRareData::UseType::CustomElementQueue:
123 return "CustomElementQueue";
124 case NodeRareData::UseType::AttributeMap:
125 return "AttributeMap";
126 case NodeRareData::UseType::InteractionObserver:
127 return "InteractionObserver";
128 case NodeRareData::UseType::PseudoElements:
129 return "PseudoElements";
130 }
131 return nullptr;
132}
133
134#endif
135
136void Node::dumpStatistics()
137{
138#if DUMP_NODE_STATISTICS
139 size_t nodesWithRareData = 0;
140
141 size_t elementNodes = 0;
142 size_t attrNodes = 0;
143 size_t textNodes = 0;
144 size_t cdataNodes = 0;
145 size_t commentNodes = 0;
146 size_t piNodes = 0;
147 size_t documentNodes = 0;
148 size_t docTypeNodes = 0;
149 size_t fragmentNodes = 0;
150 size_t shadowRootNodes = 0;
151
152 HashMap<String, size_t> perTagCount;
153
154 size_t attributes = 0;
155 size_t attributesWithAttr = 0;
156 size_t elementsWithAttributeStorage = 0;
157 size_t elementsWithRareData = 0;
158 size_t elementsWithNamedNodeMap = 0;
159
160 HashMap<uint16_t, size_t> rareDataSingleUseTypeCounts;
161 size_t mixedRareDataUseCount = 0;
162
163 for (auto* node : liveNodeSet()) {
164 if (node->hasRareData()) {
165 ++nodesWithRareData;
166 if (is<Element>(*node)) {
167 ++elementsWithRareData;
168 if (downcast<Element>(*node).hasNamedNodeMap())
169 ++elementsWithNamedNodeMap;
170 }
171 auto* rareData = node->rareData();
172 auto useTypes = is<Element>(node) ? static_cast<ElementRareData*>(rareData)->useTypes() : rareData->useTypes();
173 unsigned useTypeCount = 0;
174 for (auto type : useTypes) {
175 UNUSED_PARAM(type);
176 useTypeCount++;
177 }
178 if (useTypeCount == 1) {
179 auto result = rareDataSingleUseTypeCounts.add(static_cast<uint16_t>(*useTypes.begin()), 0);
180 result.iterator->value++;
181 } else
182 mixedRareDataUseCount++;
183 }
184
185 switch (node->nodeType()) {
186 case ELEMENT_NODE: {
187 ++elementNodes;
188
189 // Tag stats
190 Element& element = downcast<Element>(*node);
191 HashMap<String, size_t>::AddResult result = perTagCount.add(element.tagName(), 1);
192 if (!result.isNewEntry)
193 result.iterator->value++;
194
195 if (const ElementData* elementData = element.elementData()) {
196 unsigned length = elementData->length();
197 attributes += length;
198 ++elementsWithAttributeStorage;
199 for (unsigned i = 0; i < length; ++i) {
200 const Attribute& attr = elementData->attributeAt(i);
201 if (element.attrIfExists(attr.name()))
202 ++attributesWithAttr;
203 }
204 }
205 break;
206 }
207 case ATTRIBUTE_NODE: {
208 ++attrNodes;
209 break;
210 }
211 case TEXT_NODE: {
212 ++textNodes;
213 break;
214 }
215 case CDATA_SECTION_NODE: {
216 ++cdataNodes;
217 break;
218 }
219 case PROCESSING_INSTRUCTION_NODE: {
220 ++piNodes;
221 break;
222 }
223 case COMMENT_NODE: {
224 ++commentNodes;
225 break;
226 }
227 case DOCUMENT_NODE: {
228 ++documentNodes;
229 break;
230 }
231 case DOCUMENT_TYPE_NODE: {
232 ++docTypeNodes;
233 break;
234 }
235 case DOCUMENT_FRAGMENT_NODE: {
236 if (node->isShadowRoot())
237 ++shadowRootNodes;
238 else
239 ++fragmentNodes;
240 break;
241 }
242 }
243 }
244
245 printf("Number of Nodes: %d\n\n", liveNodeSet().size());
246 printf("Number of Nodes with RareData: %zu\n", nodesWithRareData);
247 printf(" Mixed use: %zu\n", mixedRareDataUseCount);
248 for (auto it : rareDataSingleUseTypeCounts)
249 printf(" %s: %zu\n", stringForRareDataUseType(static_cast<NodeRareData::UseType>(it.key)), it.value);
250 printf("\n");
251
252
253 printf("NodeType distribution:\n");
254 printf(" Number of Element nodes: %zu\n", elementNodes);
255 printf(" Number of Attribute nodes: %zu\n", attrNodes);
256 printf(" Number of Text nodes: %zu\n", textNodes);
257 printf(" Number of CDATASection nodes: %zu\n", cdataNodes);
258 printf(" Number of Comment nodes: %zu\n", commentNodes);
259 printf(" Number of ProcessingInstruction nodes: %zu\n", piNodes);
260 printf(" Number of Document nodes: %zu\n", documentNodes);
261 printf(" Number of DocumentType nodes: %zu\n", docTypeNodes);
262 printf(" Number of DocumentFragment nodes: %zu\n", fragmentNodes);
263 printf(" Number of ShadowRoot nodes: %zu\n", shadowRootNodes);
264
265 printf("Element tag name distibution:\n");
266 for (auto& stringSizePair : perTagCount)
267 printf(" Number of <%s> tags: %zu\n", stringSizePair.key.utf8().data(), stringSizePair.value);
268
269 printf("Attributes:\n");
270 printf(" Number of Attributes (non-Node and Node): %zu [%zu]\n", attributes, sizeof(Attribute));
271 printf(" Number of Attributes with an Attr: %zu\n", attributesWithAttr);
272 printf(" Number of Elements with attribute storage: %zu [%zu]\n", elementsWithAttributeStorage, sizeof(ElementData));
273 printf(" Number of Elements with RareData: %zu\n", elementsWithRareData);
274 printf(" Number of Elements with NamedNodeMap: %zu [%zu]\n", elementsWithNamedNodeMap, sizeof(NamedNodeMap));
275#endif
276}
277
278DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, nodeCounter, ("WebCoreNode"));
279
280#ifndef NDEBUG
281static bool shouldIgnoreLeaks = false;
282
283static HashSet<Node*>& ignoreSet()
284{
285 static NeverDestroyed<HashSet<Node*>> ignore;
286
287 return ignore;
288}
289
290#endif
291
292void Node::startIgnoringLeaks()
293{
294#ifndef NDEBUG
295 shouldIgnoreLeaks = true;
296#endif
297}
298
299void Node::stopIgnoringLeaks()
300{
301#ifndef NDEBUG
302 shouldIgnoreLeaks = false;
303#endif
304}
305
306void Node::trackForDebugging()
307{
308#ifndef NDEBUG
309 if (shouldIgnoreLeaks)
310 ignoreSet().add(this);
311 else
312 nodeCounter.increment();
313#endif
314
315#if DUMP_NODE_STATISTICS
316 liveNodeSet().add(this);
317#endif
318}
319
320Node::Node(Document& document, ConstructionType type)
321 : m_nodeFlags(type)
322 , m_treeScope(&document)
323{
324 ASSERT(isMainThread());
325
326 document.incrementReferencingNodeCount();
327
328#if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
329 trackForDebugging();
330#endif
331}
332
333Node::~Node()
334{
335 ASSERT(isMainThread());
336 ASSERT(m_refCountAndParentBit == s_refCountIncrement);
337 ASSERT(m_deletionHasBegun);
338 ASSERT(!m_adoptionIsRequired);
339
340#ifndef NDEBUG
341 if (!ignoreSet().remove(this))
342 nodeCounter.decrement();
343#endif
344
345#if DUMP_NODE_STATISTICS
346 liveNodeSet().remove(this);
347#endif
348
349 RELEASE_ASSERT(!renderer());
350 ASSERT(!parentNode());
351 ASSERT(!m_previous);
352 ASSERT(!m_next);
353
354 if (hasRareData())
355 clearRareData();
356
357 if (!isContainerNode())
358 willBeDeletedFrom(document());
359
360 if (hasEventTargetData())
361 clearEventTargetData();
362
363 document().decrementReferencingNodeCount();
364
365#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) && (!ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS))
366 for (auto* document : Document::allDocuments()) {
367 ASSERT_WITH_SECURITY_IMPLICATION(!document->touchEventListenersContain(*this));
368 ASSERT_WITH_SECURITY_IMPLICATION(!document->touchEventHandlersContain(*this));
369 ASSERT_WITH_SECURITY_IMPLICATION(!document->touchEventTargetsContain(*this));
370 }
371#endif
372}
373
374void Node::willBeDeletedFrom(Document& document)
375{
376 if (hasEventTargetData()) {
377 document.didRemoveWheelEventHandler(*this, EventHandlerRemoval::All);
378#if ENABLE(TOUCH_EVENTS)
379#if PLATFORM(IOS_FAMILY)
380 document.removeTouchEventListener(*this, EventHandlerRemoval::All);
381#endif
382 document.didRemoveTouchEventHandler(*this, EventHandlerRemoval::All);
383#endif
384 }
385
386#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
387 document.removeTouchEventHandler(*this, EventHandlerRemoval::All);
388#endif
389
390 if (auto* cache = document.existingAXObjectCache())
391 cache->remove(*this);
392}
393
394void Node::materializeRareData()
395{
396 NodeRareData* data;
397 if (is<Element>(*this))
398 data = std::make_unique<ElementRareData>(downcast<RenderElement>(m_data.m_renderer)).release();
399 else
400 data = std::make_unique<NodeRareData>(m_data.m_renderer).release();
401 ASSERT(data);
402
403 m_data.m_rareData = data;
404 setFlag(HasRareDataFlag);
405}
406
407void Node::clearRareData()
408{
409 ASSERT(hasRareData());
410 ASSERT(!transientMutationObserverRegistry() || transientMutationObserverRegistry()->isEmpty());
411
412 RenderObject* renderer = m_data.m_rareData->renderer();
413 if (isElementNode())
414 delete static_cast<ElementRareData*>(m_data.m_rareData);
415 else
416 delete static_cast<NodeRareData*>(m_data.m_rareData);
417 m_data.m_renderer = renderer;
418 clearFlag(HasRareDataFlag);
419}
420
421bool Node::isNode() const
422{
423 return true;
424}
425
426String Node::nodeValue() const
427{
428 return String();
429}
430
431ExceptionOr<void> Node::setNodeValue(const String&)
432{
433 // By default, setting nodeValue has no effect.
434 return { };
435}
436
437RefPtr<NodeList> Node::childNodes()
438{
439 if (is<ContainerNode>(*this))
440 return ensureRareData().ensureNodeLists().ensureChildNodeList(downcast<ContainerNode>(*this));
441 return ensureRareData().ensureNodeLists().ensureEmptyChildNodeList(*this);
442}
443
444Node *Node::lastDescendant() const
445{
446 Node *n = const_cast<Node *>(this);
447 while (n && n->lastChild())
448 n = n->lastChild();
449 return n;
450}
451
452Node* Node::firstDescendant() const
453{
454 Node *n = const_cast<Node *>(this);
455 while (n && n->firstChild())
456 n = n->firstChild();
457 return n;
458}
459
460Element* Node::previousElementSibling() const
461{
462 return ElementTraversal::previousSibling(*this);
463}
464
465Element* Node::nextElementSibling() const
466{
467 return ElementTraversal::nextSibling(*this);
468}
469
470ExceptionOr<void> Node::insertBefore(Node& newChild, Node* refChild)
471{
472 if (!is<ContainerNode>(*this))
473 return Exception { HierarchyRequestError };
474 return downcast<ContainerNode>(*this).insertBefore(newChild, refChild);
475}
476
477ExceptionOr<void> Node::replaceChild(Node& newChild, Node& oldChild)
478{
479 if (!is<ContainerNode>(*this))
480 return Exception { HierarchyRequestError };
481 return downcast<ContainerNode>(*this).replaceChild(newChild, oldChild);
482}
483
484ExceptionOr<void> Node::removeChild(Node& oldChild)
485{
486 if (!is<ContainerNode>(*this))
487 return Exception { NotFoundError };
488 return downcast<ContainerNode>(*this).removeChild(oldChild);
489}
490
491ExceptionOr<void> Node::appendChild(Node& newChild)
492{
493 if (!is<ContainerNode>(*this))
494 return Exception { HierarchyRequestError };
495 return downcast<ContainerNode>(*this).appendChild(newChild);
496}
497
498static HashSet<RefPtr<Node>> nodeSetPreTransformedFromNodeOrStringVector(const Vector<NodeOrString>& vector)
499{
500 HashSet<RefPtr<Node>> nodeSet;
501 for (const auto& variant : vector) {
502 WTF::switchOn(variant,
503 [&] (const RefPtr<Node>& node) { nodeSet.add(const_cast<Node*>(node.get())); },
504 [] (const String&) { }
505 );
506 }
507 return nodeSet;
508}
509
510static RefPtr<Node> firstPrecedingSiblingNotInNodeSet(Node& context, const HashSet<RefPtr<Node>>& nodeSet)
511{
512 for (auto* sibling = context.previousSibling(); sibling; sibling = sibling->previousSibling()) {
513 if (!nodeSet.contains(sibling))
514 return sibling;
515 }
516 return nullptr;
517}
518
519static RefPtr<Node> firstFollowingSiblingNotInNodeSet(Node& context, const HashSet<RefPtr<Node>>& nodeSet)
520{
521 for (auto* sibling = context.nextSibling(); sibling; sibling = sibling->nextSibling()) {
522 if (!nodeSet.contains(sibling))
523 return sibling;
524 }
525 return nullptr;
526}
527
528ExceptionOr<RefPtr<Node>> Node::convertNodesOrStringsIntoNode(Vector<NodeOrString>&& nodeOrStringVector)
529{
530 if (nodeOrStringVector.isEmpty())
531 return nullptr;
532
533 Vector<Ref<Node>> nodes;
534 nodes.reserveInitialCapacity(nodeOrStringVector.size());
535 for (auto& variant : nodeOrStringVector) {
536 WTF::switchOn(variant,
537 [&](RefPtr<Node>& node) { nodes.uncheckedAppend(*node.get()); },
538 [&](String& string) { nodes.uncheckedAppend(Text::create(document(), string)); }
539 );
540 }
541
542 if (nodes.size() == 1)
543 return RefPtr<Node> { WTFMove(nodes.first()) };
544
545 auto nodeToReturn = DocumentFragment::create(document());
546 for (auto& node : nodes) {
547 auto appendResult = nodeToReturn->appendChild(node);
548 if (appendResult.hasException())
549 return appendResult.releaseException();
550 }
551 return RefPtr<Node> { WTFMove(nodeToReturn) };
552}
553
554ExceptionOr<void> Node::before(Vector<NodeOrString>&& nodeOrStringVector)
555{
556 RefPtr<ContainerNode> parent = parentNode();
557 if (!parent)
558 return { };
559
560 auto nodeSet = nodeSetPreTransformedFromNodeOrStringVector(nodeOrStringVector);
561 auto viablePreviousSibling = firstPrecedingSiblingNotInNodeSet(*this, nodeSet);
562
563 auto result = convertNodesOrStringsIntoNode(WTFMove(nodeOrStringVector));
564 if (result.hasException())
565 return result.releaseException();
566 auto node = result.releaseReturnValue();
567 if (!node)
568 return { };
569
570 if (viablePreviousSibling)
571 viablePreviousSibling = viablePreviousSibling->nextSibling();
572 else
573 viablePreviousSibling = parent->firstChild();
574
575 return parent->insertBefore(*node, viablePreviousSibling.get());
576}
577
578ExceptionOr<void> Node::after(Vector<NodeOrString>&& nodeOrStringVector)
579{
580 RefPtr<ContainerNode> parent = parentNode();
581 if (!parent)
582 return { };
583
584 auto nodeSet = nodeSetPreTransformedFromNodeOrStringVector(nodeOrStringVector);
585 auto viableNextSibling = firstFollowingSiblingNotInNodeSet(*this, nodeSet);
586
587 auto result = convertNodesOrStringsIntoNode(WTFMove(nodeOrStringVector));
588 if (result.hasException())
589 return result.releaseException();
590 auto node = result.releaseReturnValue();
591 if (!node)
592 return { };
593
594 return parent->insertBefore(*node, viableNextSibling.get());
595}
596
597ExceptionOr<void> Node::replaceWith(Vector<NodeOrString>&& nodeOrStringVector)
598{
599 RefPtr<ContainerNode> parent = parentNode();
600 if (!parent)
601 return { };
602
603 auto nodeSet = nodeSetPreTransformedFromNodeOrStringVector(nodeOrStringVector);
604 auto viableNextSibling = firstFollowingSiblingNotInNodeSet(*this, nodeSet);
605
606 auto result = convertNodesOrStringsIntoNode(WTFMove(nodeOrStringVector));
607 if (result.hasException())
608 return result.releaseException();
609
610 if (parentNode() == parent) {
611 if (auto node = result.releaseReturnValue())
612 return parent->replaceChild(*node, *this);
613 return parent->removeChild(*this);
614 }
615
616 if (auto node = result.releaseReturnValue())
617 return parent->insertBefore(*node, viableNextSibling.get());
618 return { };
619}
620
621ExceptionOr<void> Node::remove()
622{
623 auto* parent = parentNode();
624 if (!parent)
625 return { };
626 return parent->removeChild(*this);
627}
628
629void Node::normalize()
630{
631 // Go through the subtree beneath us, normalizing all nodes. This means that
632 // any two adjacent text nodes are merged and any empty text nodes are removed.
633
634 RefPtr<Node> node = this;
635 while (Node* firstChild = node->firstChild())
636 node = firstChild;
637 while (node) {
638 NodeType type = node->nodeType();
639 if (type == ELEMENT_NODE)
640 downcast<Element>(*node).normalizeAttributes();
641
642 if (node == this)
643 break;
644
645 if (type != TEXT_NODE) {
646 node = NodeTraversal::nextPostOrder(*node);
647 continue;
648 }
649
650 RefPtr<Text> text = downcast<Text>(node.get());
651
652 // Remove empty text nodes.
653 if (!text->length()) {
654 // Care must be taken to get the next node before removing the current node.
655 node = NodeTraversal::nextPostOrder(*node);
656 text->remove();
657 continue;
658 }
659
660 // Merge text nodes.
661 while (Node* nextSibling = node->nextSibling()) {
662 if (nextSibling->nodeType() != TEXT_NODE)
663 break;
664 Ref<Text> nextText = downcast<Text>(*nextSibling);
665
666 // Remove empty text nodes.
667 if (!nextText->length()) {
668 nextText->remove();
669 continue;
670 }
671
672 // Both non-empty text nodes. Merge them.
673 unsigned offset = text->length();
674 text->appendData(nextText->data());
675 document().textNodesMerged(nextText, offset);
676 nextText->remove();
677 }
678
679 node = NodeTraversal::nextPostOrder(*node);
680 }
681}
682
683ExceptionOr<Ref<Node>> Node::cloneNodeForBindings(bool deep)
684{
685 if (UNLIKELY(isShadowRoot()))
686 return Exception { NotSupportedError };
687 return cloneNode(deep);
688}
689
690const AtomString& Node::prefix() const
691{
692 // For nodes other than elements and attributes, the prefix is always null
693 return nullAtom();
694}
695
696ExceptionOr<void> Node::setPrefix(const AtomString&)
697{
698 // The spec says that for nodes other than elements and attributes, prefix is always null.
699 // It does not say what to do when the user tries to set the prefix on another type of
700 // node, however Mozilla throws a NamespaceError exception.
701 return Exception { NamespaceError };
702}
703
704const AtomString& Node::localName() const
705{
706 return nullAtom();
707}
708
709const AtomString& Node::namespaceURI() const
710{
711 return nullAtom();
712}
713
714bool Node::isContentEditable()
715{
716 return computeEditability(UserSelectAllDoesNotAffectEditability, ShouldUpdateStyle::Update) != Editability::ReadOnly;
717}
718
719bool Node::isContentRichlyEditable()
720{
721 return computeEditability(UserSelectAllIsAlwaysNonEditable, ShouldUpdateStyle::Update) == Editability::CanEditRichly;
722}
723
724void Node::inspect()
725{
726 if (document().page())
727 document().page()->inspectorController().inspect(this);
728}
729
730static Node::Editability computeEditabilityFromComputedStyle(const Node& startNode, Node::UserSelectAllTreatment treatment)
731{
732 // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but
733 // ContainerNode::setFocus() calls invalidateStyleForSubtree(), so the assertion
734 // would fire in the middle of Document::setFocusedElement().
735
736 for (const Node* node = &startNode; node; node = node->parentNode()) {
737 auto* style = node->isDocumentNode() ? node->renderStyle() : const_cast<Node*>(node)->computedStyle();
738 if (!style)
739 continue;
740 if (style->display() == DisplayType::None)
741 continue;
742#if ENABLE(USERSELECT_ALL)
743 // Elements with user-select: all style are considered atomic
744 // therefore non editable.
745 if (treatment == Node::UserSelectAllIsAlwaysNonEditable && style->userSelect() == UserSelect::All)
746 return Node::Editability::ReadOnly;
747#else
748 UNUSED_PARAM(treatment);
749#endif
750 switch (style->userModify()) {
751 case UserModify::ReadOnly:
752 return Node::Editability::ReadOnly;
753 case UserModify::ReadWrite:
754 return Node::Editability::CanEditRichly;
755 case UserModify::ReadWritePlaintextOnly:
756 return Node::Editability::CanEditPlainText;
757 }
758 ASSERT_NOT_REACHED();
759 return Node::Editability::ReadOnly;
760 }
761 return Node::Editability::ReadOnly;
762}
763
764Node::Editability Node::computeEditability(UserSelectAllTreatment treatment, ShouldUpdateStyle shouldUpdateStyle) const
765{
766 if (!document().hasLivingRenderTree() || isPseudoElement())
767 return Editability::ReadOnly;
768
769 if (isInShadowTree())
770 return HTMLElement::editabilityFromContentEditableAttr(*this);
771
772 if (document().frame() && document().frame()->page() && document().frame()->page()->isEditable())
773 return Editability::CanEditRichly;
774
775 if (shouldUpdateStyle == ShouldUpdateStyle::Update && document().needsStyleRecalc()) {
776 if (!document().usesStyleBasedEditability())
777 return HTMLElement::editabilityFromContentEditableAttr(*this);
778 document().updateStyleIfNeeded();
779 }
780 return computeEditabilityFromComputedStyle(*this, treatment);
781}
782
783RenderBox* Node::renderBox() const
784{
785 RenderObject* renderer = this->renderer();
786 return is<RenderBox>(renderer) ? downcast<RenderBox>(renderer) : nullptr;
787}
788
789RenderBoxModelObject* Node::renderBoxModelObject() const
790{
791 RenderObject* renderer = this->renderer();
792 return is<RenderBoxModelObject>(renderer) ? downcast<RenderBoxModelObject>(renderer) : nullptr;
793}
794
795LayoutRect Node::renderRect(bool* isReplaced)
796{
797 RenderObject* hitRenderer = this->renderer();
798 if (!hitRenderer && is<HTMLAreaElement>(*this)) {
799 auto& area = downcast<HTMLAreaElement>(*this);
800 if (auto* imageElement = area.imageElement())
801 hitRenderer = imageElement->renderer();
802 }
803 RenderObject* renderer = hitRenderer;
804 while (renderer && !renderer->isBody() && !renderer->isDocumentElementRenderer()) {
805 if (renderer->isRenderBlock() || renderer->isInlineBlockOrInlineTable() || renderer->isReplaced()) {
806 *isReplaced = renderer->isReplaced();
807 return renderer->absoluteBoundingBoxRect();
808 }
809 renderer = renderer->parent();
810 }
811 return LayoutRect();
812}
813
814void Node::refEventTarget()
815{
816 ref();
817}
818
819void Node::derefEventTarget()
820{
821 deref();
822}
823
824void Node::adjustStyleValidity(Style::Validity validity, Style::InvalidationMode mode)
825{
826 if (validity > styleValidity()) {
827 m_nodeFlags &= ~StyleValidityMask;
828 m_nodeFlags |= static_cast<unsigned>(validity) << StyleValidityShift;
829 }
830 if (mode == Style::InvalidationMode::RecompositeLayer)
831 setFlag(StyleResolutionShouldRecompositeLayerFlag);
832}
833
834inline void Node::updateAncestorsForStyleRecalc()
835{
836 auto composedAncestors = composedTreeAncestors(*this);
837 auto it = composedAncestors.begin();
838 auto end = composedAncestors.end();
839 if (it != end) {
840 it->setDirectChildNeedsStyleRecalc();
841
842 for (; it != end; ++it) {
843 // Iterator skips over shadow roots.
844 if (auto* shadowRoot = it->shadowRoot())
845 shadowRoot->setChildNeedsStyleRecalc();
846 if (it->childNeedsStyleRecalc())
847 break;
848 it->setChildNeedsStyleRecalc();
849 }
850 }
851
852 auto* documentElement = document().documentElement();
853 if (!documentElement)
854 return;
855 if (!documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
856 return;
857 document().setChildNeedsStyleRecalc();
858 document().scheduleStyleRecalc();
859}
860
861void Node::invalidateStyle(Style::Validity validity, Style::InvalidationMode mode)
862{
863 ASSERT(validity != Style::Validity::Valid);
864 if (!inRenderedDocument())
865 return;
866
867 // FIXME: This should eventually be an ASSERT.
868 if (document().inRenderTreeUpdate())
869 return;
870
871 // FIXME: Why the second condition?
872 bool markAncestors = styleValidity() == Style::Validity::Valid || validity == Style::Validity::SubtreeAndRenderersInvalid;
873
874 adjustStyleValidity(validity, mode);
875
876 if (markAncestors)
877 updateAncestorsForStyleRecalc();
878}
879
880unsigned Node::computeNodeIndex() const
881{
882 unsigned count = 0;
883 for (Node* sibling = previousSibling(); sibling; sibling = sibling->previousSibling())
884 ++count;
885 return count;
886}
887
888template<unsigned type>
889bool shouldInvalidateNodeListCachesForAttr(const unsigned nodeListCounts[], const QualifiedName& attrName)
890{
891 if (nodeListCounts[type] && shouldInvalidateTypeOnAttributeChange(static_cast<NodeListInvalidationType>(type), attrName))
892 return true;
893 return shouldInvalidateNodeListCachesForAttr<type + 1>(nodeListCounts, attrName);
894}
895
896template<>
897bool shouldInvalidateNodeListCachesForAttr<numNodeListInvalidationTypes>(const unsigned[], const QualifiedName&)
898{
899 return false;
900}
901
902inline bool Document::shouldInvalidateNodeListAndCollectionCaches() const
903{
904 for (int type = 0; type < numNodeListInvalidationTypes; ++type) {
905 if (m_nodeListAndCollectionCounts[type])
906 return true;
907 }
908 return false;
909}
910
911inline bool Document::shouldInvalidateNodeListAndCollectionCachesForAttribute(const QualifiedName& attrName) const
912{
913 return shouldInvalidateNodeListCachesForAttr<DoNotInvalidateOnAttributeChanges + 1>(m_nodeListAndCollectionCounts, attrName);
914}
915
916template <typename InvalidationFunction>
917void Document::invalidateNodeListAndCollectionCaches(InvalidationFunction invalidate)
918{
919 for (auto* list : copyToVectorSpecialization<Vector<LiveNodeList*, 8>>(m_listsInvalidatedAtDocument))
920 invalidate(*list);
921
922 for (auto* collection : copyToVectorSpecialization<Vector<HTMLCollection*, 8>>(m_collectionsInvalidatedAtDocument))
923 invalidate(*collection);
924}
925
926void Node::invalidateNodeListAndCollectionCachesInAncestors()
927{
928 if (hasRareData()) {
929 if (auto* lists = rareData()->nodeLists())
930 lists->clearChildNodeListCache();
931 }
932
933 if (!document().shouldInvalidateNodeListAndCollectionCaches())
934 return;
935
936 document().invalidateNodeListAndCollectionCaches([](auto& list) {
937 list.invalidateCache();
938 });
939
940 for (auto* node = this; node; node = node->parentNode()) {
941 if (!node->hasRareData())
942 continue;
943
944 if (auto* lists = node->rareData()->nodeLists())
945 lists->invalidateCaches();
946 }
947}
948
949void Node::invalidateNodeListAndCollectionCachesInAncestorsForAttribute(const QualifiedName& attrName)
950{
951 ASSERT(is<Element>(*this));
952
953 if (!document().shouldInvalidateNodeListAndCollectionCachesForAttribute(attrName))
954 return;
955
956 document().invalidateNodeListAndCollectionCaches([&attrName](auto& list) {
957 list.invalidateCacheForAttribute(attrName);
958 });
959
960 for (auto* node = this; node; node = node->parentNode()) {
961 if (!node->hasRareData())
962 continue;
963
964 if (auto* lists = node->rareData()->nodeLists())
965 lists->invalidateCachesForAttribute(attrName);
966 }
967}
968
969NodeListsNodeData* Node::nodeLists()
970{
971 return hasRareData() ? rareData()->nodeLists() : nullptr;
972}
973
974void Node::clearNodeLists()
975{
976 rareData()->clearNodeLists();
977}
978
979ExceptionOr<void> Node::checkSetPrefix(const AtomString& prefix)
980{
981 // Perform error checking as required by spec for setting Node.prefix. Used by
982 // Element::setPrefix() and Attr::setPrefix()
983
984 if (!prefix.isEmpty() && !Document::isValidName(prefix))
985 return Exception { InvalidCharacterError };
986
987 // FIXME: Raise NamespaceError if prefix is malformed per the Namespaces in XML specification.
988
989 auto& namespaceURI = this->namespaceURI();
990 if (namespaceURI.isEmpty() && !prefix.isEmpty())
991 return Exception { NamespaceError };
992 if (prefix == xmlAtom() && namespaceURI != XMLNames::xmlNamespaceURI)
993 return Exception { NamespaceError };
994
995 // Attribute-specific checks are in Attr::setPrefix().
996
997 return { };
998}
999
1000bool Node::isDescendantOf(const Node& other) const
1001{
1002 // Return true if other is an ancestor of this, otherwise false
1003 if (!other.hasChildNodes() || isConnected() != other.isConnected())
1004 return false;
1005 if (other.isDocumentNode())
1006 return &document() == &other && !isDocumentNode() && isConnected();
1007 for (const auto* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
1008 if (ancestor == &other)
1009 return true;
1010 }
1011 return false;
1012}
1013
1014bool Node::isDescendantOrShadowDescendantOf(const Node* other) const
1015{
1016 // FIXME: This element's shadow tree's host could be inside another shadow tree.
1017 // This function doesn't handle that case correctly. Maybe share code with
1018 // the containsIncludingShadowDOM function?
1019 return other && (isDescendantOf(*other) || other->contains(shadowHost()));
1020}
1021
1022bool Node::contains(const Node* node) const
1023{
1024 return this == node || (node && node->isDescendantOf(*this));
1025}
1026
1027bool Node::containsIncludingShadowDOM(const Node* node) const
1028{
1029 for (; node; node = node->parentOrShadowHostNode()) {
1030 if (node == this)
1031 return true;
1032 }
1033 return false;
1034}
1035
1036Node* Node::pseudoAwarePreviousSibling() const
1037{
1038 Element* parentOrHost = is<PseudoElement>(*this) ? downcast<PseudoElement>(*this).hostElement() : parentElement();
1039 if (parentOrHost && !previousSibling()) {
1040 if (isAfterPseudoElement() && parentOrHost->lastChild())
1041 return parentOrHost->lastChild();
1042 if (!isBeforePseudoElement())
1043 return parentOrHost->beforePseudoElement();
1044 }
1045 return previousSibling();
1046}
1047
1048Node* Node::pseudoAwareNextSibling() const
1049{
1050 Element* parentOrHost = is<PseudoElement>(*this) ? downcast<PseudoElement>(*this).hostElement() : parentElement();
1051 if (parentOrHost && !nextSibling()) {
1052 if (isBeforePseudoElement() && parentOrHost->firstChild())
1053 return parentOrHost->firstChild();
1054 if (!isAfterPseudoElement())
1055 return parentOrHost->afterPseudoElement();
1056 }
1057 return nextSibling();
1058}
1059
1060Node* Node::pseudoAwareFirstChild() const
1061{
1062 if (is<Element>(*this)) {
1063 const Element& currentElement = downcast<Element>(*this);
1064 Node* first = currentElement.beforePseudoElement();
1065 if (first)
1066 return first;
1067 first = currentElement.firstChild();
1068 if (!first)
1069 first = currentElement.afterPseudoElement();
1070 return first;
1071 }
1072 return firstChild();
1073}
1074
1075Node* Node::pseudoAwareLastChild() const
1076{
1077 if (is<Element>(*this)) {
1078 const Element& currentElement = downcast<Element>(*this);
1079 Node* last = currentElement.afterPseudoElement();
1080 if (last)
1081 return last;
1082 last = currentElement.lastChild();
1083 if (!last)
1084 last = currentElement.beforePseudoElement();
1085 return last;
1086 }
1087 return lastChild();
1088}
1089
1090const RenderStyle* Node::computedStyle(PseudoId pseudoElementSpecifier)
1091{
1092 auto* composedParent = composedTreeAncestors(*this).first();
1093 if (!composedParent)
1094 return nullptr;
1095 return composedParent->computedStyle(pseudoElementSpecifier);
1096}
1097
1098int Node::maxCharacterOffset() const
1099{
1100 ASSERT_NOT_REACHED();
1101 return 0;
1102}
1103
1104// FIXME: Shouldn't these functions be in the editing code? Code that asks questions about HTML in the core DOM class
1105// is obviously misplaced.
1106bool Node::canStartSelection() const
1107{
1108 if (hasEditableStyle())
1109 return true;
1110
1111 if (renderer()) {
1112 const RenderStyle& style = renderer()->style();
1113 // We allow selections to begin within an element that has -webkit-user-select: none set,
1114 // but if the element is draggable then dragging should take priority over selection.
1115 if (style.userDrag() == UserDrag::Element && style.userSelect() == UserSelect::None)
1116 return false;
1117 }
1118 return parentOrShadowHostNode() ? parentOrShadowHostNode()->canStartSelection() : true;
1119}
1120
1121Element* Node::shadowHost() const
1122{
1123 if (ShadowRoot* root = containingShadowRoot())
1124 return root->host();
1125 return nullptr;
1126}
1127
1128ShadowRoot* Node::containingShadowRoot() const
1129{
1130 ContainerNode& root = treeScope().rootNode();
1131 return is<ShadowRoot>(root) ? downcast<ShadowRoot>(&root) : nullptr;
1132}
1133
1134#if !ASSERT_DISABLED
1135// https://dom.spec.whatwg.org/#concept-closed-shadow-hidden
1136static bool isClosedShadowHiddenUsingSpecDefinition(const Node& A, const Node& B)
1137{
1138 return A.isInShadowTree()
1139 && !A.rootNode().containsIncludingShadowDOM(&B)
1140 && (A.containingShadowRoot()->mode() != ShadowRootMode::Open || isClosedShadowHiddenUsingSpecDefinition(*A.shadowHost(), B));
1141}
1142#endif
1143
1144// http://w3c.github.io/webcomponents/spec/shadow/#dfn-unclosed-node
1145bool Node::isClosedShadowHidden(const Node& otherNode) const
1146{
1147 // Use Vector instead of HashSet since we expect the number of ancestor tree scopes to be small.
1148 Vector<TreeScope*, 8> ancestorScopesOfThisNode;
1149
1150 for (auto* scope = &treeScope(); scope; scope = scope->parentTreeScope())
1151 ancestorScopesOfThisNode.append(scope);
1152
1153 for (auto* treeScopeThatCanAccessOtherNode = &otherNode.treeScope(); treeScopeThatCanAccessOtherNode; treeScopeThatCanAccessOtherNode = treeScopeThatCanAccessOtherNode->parentTreeScope()) {
1154 for (auto* scope : ancestorScopesOfThisNode) {
1155 if (scope == treeScopeThatCanAccessOtherNode) {
1156 ASSERT(!isClosedShadowHiddenUsingSpecDefinition(otherNode, *this));
1157 return false; // treeScopeThatCanAccessOtherNode is a shadow-including inclusive ancestor of this node.
1158 }
1159 }
1160 auto& root = treeScopeThatCanAccessOtherNode->rootNode();
1161 if (is<ShadowRoot>(root) && downcast<ShadowRoot>(root).mode() != ShadowRootMode::Open)
1162 break;
1163 }
1164
1165 ASSERT(isClosedShadowHiddenUsingSpecDefinition(otherNode, *this));
1166 return true;
1167}
1168
1169static inline ShadowRoot* parentShadowRoot(const Node& node)
1170{
1171 if (auto* parent = node.parentElement())
1172 return parent->shadowRoot();
1173 return nullptr;
1174}
1175
1176HTMLSlotElement* Node::assignedSlot() const
1177{
1178 if (auto* shadowRoot = parentShadowRoot(*this))
1179 return shadowRoot->findAssignedSlot(*this);
1180 return nullptr;
1181}
1182
1183HTMLSlotElement* Node::assignedSlotForBindings() const
1184{
1185 auto* shadowRoot = parentShadowRoot(*this);
1186 if (shadowRoot && shadowRoot->mode() == ShadowRootMode::Open)
1187 return shadowRoot->findAssignedSlot(*this);
1188 return nullptr;
1189}
1190
1191ContainerNode* Node::parentInComposedTree() const
1192{
1193 ASSERT(isMainThreadOrGCThread());
1194 if (auto* slot = assignedSlot())
1195 return slot;
1196 if (is<ShadowRoot>(*this))
1197 return downcast<ShadowRoot>(*this).host();
1198 return parentNode();
1199}
1200
1201Element* Node::parentElementInComposedTree() const
1202{
1203 if (auto* slot = assignedSlot())
1204 return slot;
1205 if (is<PseudoElement>(*this))
1206 return downcast<PseudoElement>(*this).hostElement();
1207 if (auto* parent = parentNode()) {
1208 if (is<ShadowRoot>(*parent))
1209 return downcast<ShadowRoot>(*parent).host();
1210 if (is<Element>(*parent))
1211 return downcast<Element>(parent);
1212 }
1213 return nullptr;
1214}
1215
1216bool Node::isInUserAgentShadowTree() const
1217{
1218 auto* shadowRoot = containingShadowRoot();
1219 return shadowRoot && shadowRoot->mode() == ShadowRootMode::UserAgent;
1220}
1221
1222Node* Node::nonBoundaryShadowTreeRootNode()
1223{
1224 ASSERT(!isShadowRoot());
1225 Node* root = this;
1226 while (root) {
1227 if (root->isShadowRoot())
1228 return root;
1229 Node* parent = root->parentNodeGuaranteedHostFree();
1230 if (parent && parent->isShadowRoot())
1231 return root;
1232 root = parent;
1233 }
1234 return 0;
1235}
1236
1237ContainerNode* Node::nonShadowBoundaryParentNode() const
1238{
1239 ContainerNode* parent = parentNode();
1240 return parent && !parent->isShadowRoot() ? parent : nullptr;
1241}
1242
1243Element* Node::parentOrShadowHostElement() const
1244{
1245 ContainerNode* parent = parentOrShadowHostNode();
1246 if (!parent)
1247 return nullptr;
1248
1249 if (is<ShadowRoot>(*parent))
1250 return downcast<ShadowRoot>(*parent).host();
1251
1252 if (!is<Element>(*parent))
1253 return nullptr;
1254
1255 return downcast<Element>(parent);
1256}
1257
1258Node& Node::traverseToRootNode() const
1259{
1260 Node* node = const_cast<Node*>(this);
1261 Node* highest = node;
1262 for (; node; node = node->parentNode())
1263 highest = node;
1264 return *highest;
1265}
1266
1267// https://dom.spec.whatwg.org/#concept-shadow-including-root
1268Node& Node::shadowIncludingRoot() const
1269{
1270 auto& root = rootNode();
1271 if (!is<ShadowRoot>(root))
1272 return root;
1273 auto* host = downcast<ShadowRoot>(root).host();
1274 return host ? host->shadowIncludingRoot() : root;
1275}
1276
1277Node& Node::getRootNode(const GetRootNodeOptions& options) const
1278{
1279 return options.composed ? shadowIncludingRoot() : rootNode();
1280}
1281
1282Node::InsertedIntoAncestorResult Node::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
1283{
1284 if (insertionType.connectedToDocument)
1285 setFlag(IsConnectedFlag);
1286 if (parentOfInsertedTree.isInShadowTree())
1287 setFlag(IsInShadowTreeFlag);
1288
1289 invalidateStyle(Style::Validity::SubtreeAndRenderersInvalid);
1290
1291 return InsertedIntoAncestorResult::Done;
1292}
1293
1294void Node::removedFromAncestor(RemovalType removalType, ContainerNode&)
1295{
1296 if (removalType.disconnectedFromDocument)
1297 clearFlag(IsConnectedFlag);
1298 if (isInShadowTree() && !treeScope().rootNode().isShadowRoot())
1299 clearFlag(IsInShadowTreeFlag);
1300}
1301
1302bool Node::isRootEditableElement() const
1303{
1304 return hasEditableStyle() && isElementNode() && (!parentNode() || !parentNode()->hasEditableStyle()
1305 || !parentNode()->isElementNode() || hasTagName(bodyTag));
1306}
1307
1308Element* Node::rootEditableElement() const
1309{
1310 Element* result = nullptr;
1311 for (Node* node = const_cast<Node*>(this); node && node->hasEditableStyle(); node = node->parentNode()) {
1312 if (is<Element>(*node))
1313 result = downcast<Element>(node);
1314 if (is<HTMLBodyElement>(*node))
1315 break;
1316 }
1317 return result;
1318}
1319
1320// FIXME: End of obviously misplaced HTML editing functions. Try to move these out of Node.
1321
1322Document* Node::ownerDocument() const
1323{
1324 Document* document = &this->document();
1325 return document == this ? nullptr : document;
1326}
1327
1328const URL& Node::baseURI() const
1329{
1330 auto& url = document().baseURL();
1331 return url.isNull() ? WTF::blankURL() : url;
1332}
1333
1334bool Node::isEqualNode(Node* other) const
1335{
1336 if (!other)
1337 return false;
1338
1339 NodeType nodeType = this->nodeType();
1340 if (nodeType != other->nodeType())
1341 return false;
1342
1343 switch (nodeType) {
1344 case Node::DOCUMENT_TYPE_NODE: {
1345 auto& thisDocType = downcast<DocumentType>(*this);
1346 auto& otherDocType = downcast<DocumentType>(*other);
1347 if (thisDocType.name() != otherDocType.name())
1348 return false;
1349 if (thisDocType.publicId() != otherDocType.publicId())
1350 return false;
1351 if (thisDocType.systemId() != otherDocType.systemId())
1352 return false;
1353 break;
1354 }
1355 case Node::ELEMENT_NODE: {
1356 auto& thisElement = downcast<Element>(*this);
1357 auto& otherElement = downcast<Element>(*other);
1358 if (thisElement.tagQName() != otherElement.tagQName())
1359 return false;
1360 if (!thisElement.hasEquivalentAttributes(otherElement))
1361 return false;
1362 break;
1363 }
1364 case Node::PROCESSING_INSTRUCTION_NODE: {
1365 auto& thisProcessingInstruction = downcast<ProcessingInstruction>(*this);
1366 auto& otherProcessingInstruction = downcast<ProcessingInstruction>(*other);
1367 if (thisProcessingInstruction.target() != otherProcessingInstruction.target())
1368 return false;
1369 if (thisProcessingInstruction.data() != otherProcessingInstruction.data())
1370 return false;
1371 break;
1372 }
1373 case Node::CDATA_SECTION_NODE:
1374 case Node::TEXT_NODE:
1375 case Node::COMMENT_NODE: {
1376 auto& thisCharacterData = downcast<CharacterData>(*this);
1377 auto& otherCharacterData = downcast<CharacterData>(*other);
1378 if (thisCharacterData.data() != otherCharacterData.data())
1379 return false;
1380 break;
1381 }
1382 case Node::ATTRIBUTE_NODE: {
1383 auto& thisAttribute = downcast<Attr>(*this);
1384 auto& otherAttribute = downcast<Attr>(*other);
1385 if (thisAttribute.qualifiedName() != otherAttribute.qualifiedName())
1386 return false;
1387 if (thisAttribute.value() != otherAttribute.value())
1388 return false;
1389 break;
1390 }
1391 case Node::DOCUMENT_NODE:
1392 case Node::DOCUMENT_FRAGMENT_NODE:
1393 break;
1394 }
1395
1396 Node* child = firstChild();
1397 Node* otherChild = other->firstChild();
1398
1399 while (child) {
1400 if (!child->isEqualNode(otherChild))
1401 return false;
1402
1403 child = child->nextSibling();
1404 otherChild = otherChild->nextSibling();
1405 }
1406
1407 if (otherChild)
1408 return false;
1409
1410 return true;
1411}
1412
1413// https://dom.spec.whatwg.org/#locate-a-namespace
1414static const AtomString& locateDefaultNamespace(const Node& node, const AtomString& prefix)
1415{
1416 switch (node.nodeType()) {
1417 case Node::ELEMENT_NODE: {
1418 auto& element = downcast<Element>(node);
1419 auto& namespaceURI = element.namespaceURI();
1420 if (!namespaceURI.isNull() && element.prefix() == prefix)
1421 return namespaceURI;
1422
1423 if (element.hasAttributes()) {
1424 for (auto& attribute : element.attributesIterator()) {
1425 if (attribute.namespaceURI() != XMLNSNames::xmlnsNamespaceURI)
1426 continue;
1427
1428 if ((prefix.isNull() && attribute.prefix().isNull() && attribute.localName() == xmlnsAtom()) || (attribute.prefix() == xmlnsAtom() && attribute.localName() == prefix)) {
1429 auto& result = attribute.value();
1430 return result.isEmpty() ? nullAtom() : result;
1431 }
1432 }
1433 }
1434 auto* parent = node.parentElement();
1435 return parent ? locateDefaultNamespace(*parent, prefix) : nullAtom();
1436 }
1437 case Node::DOCUMENT_NODE:
1438 if (auto* documentElement = downcast<Document>(node).documentElement())
1439 return locateDefaultNamespace(*documentElement, prefix);
1440 return nullAtom();
1441 case Node::DOCUMENT_TYPE_NODE:
1442 case Node::DOCUMENT_FRAGMENT_NODE:
1443 return nullAtom();
1444 case Node::ATTRIBUTE_NODE:
1445 if (auto* ownerElement = downcast<Attr>(node).ownerElement())
1446 return locateDefaultNamespace(*ownerElement, prefix);
1447 return nullAtom();
1448 default:
1449 if (auto* parent = node.parentElement())
1450 return locateDefaultNamespace(*parent, prefix);
1451 return nullAtom();
1452 }
1453}
1454
1455// https://dom.spec.whatwg.org/#dom-node-isdefaultnamespace
1456bool Node::isDefaultNamespace(const AtomString& potentiallyEmptyNamespace) const
1457{
1458 const AtomString& namespaceURI = potentiallyEmptyNamespace.isEmpty() ? nullAtom() : potentiallyEmptyNamespace;
1459 return locateDefaultNamespace(*this, nullAtom()) == namespaceURI;
1460}
1461
1462// https://dom.spec.whatwg.org/#dom-node-lookupnamespaceuri
1463const AtomString& Node::lookupNamespaceURI(const AtomString& potentiallyEmptyPrefix) const
1464{
1465 const AtomString& prefix = potentiallyEmptyPrefix.isEmpty() ? nullAtom() : potentiallyEmptyPrefix;
1466 return locateDefaultNamespace(*this, prefix);
1467}
1468
1469// https://dom.spec.whatwg.org/#locate-a-namespace-prefix
1470static const AtomString& locateNamespacePrefix(const Element& element, const AtomString& namespaceURI)
1471{
1472 if (element.namespaceURI() == namespaceURI)
1473 return element.prefix();
1474
1475 if (element.hasAttributes()) {
1476 for (auto& attribute : element.attributesIterator()) {
1477 if (attribute.prefix() == xmlnsAtom() && attribute.value() == namespaceURI)
1478 return attribute.localName();
1479 }
1480 }
1481 auto* parent = element.parentElement();
1482 return parent ? locateNamespacePrefix(*parent, namespaceURI) : nullAtom();
1483}
1484
1485// https://dom.spec.whatwg.org/#dom-node-lookupprefix
1486const AtomString& Node::lookupPrefix(const AtomString& namespaceURI) const
1487{
1488 if (namespaceURI.isEmpty())
1489 return nullAtom();
1490
1491 switch (nodeType()) {
1492 case ELEMENT_NODE:
1493 return locateNamespacePrefix(downcast<Element>(*this), namespaceURI);
1494 case DOCUMENT_NODE:
1495 if (auto* documentElement = downcast<Document>(*this).documentElement())
1496 return locateNamespacePrefix(*documentElement, namespaceURI);
1497 return nullAtom();
1498 case DOCUMENT_FRAGMENT_NODE:
1499 case DOCUMENT_TYPE_NODE:
1500 return nullAtom();
1501 case ATTRIBUTE_NODE:
1502 if (auto* ownerElement = downcast<Attr>(*this).ownerElement())
1503 return locateNamespacePrefix(*ownerElement, namespaceURI);
1504 return nullAtom();
1505 default:
1506 if (auto* parent = parentElement())
1507 return locateNamespacePrefix(*parent, namespaceURI);
1508 return nullAtom();
1509 }
1510}
1511
1512static void appendTextContent(const Node* node, bool convertBRsToNewlines, bool& isNullString, StringBuilder& content)
1513{
1514 switch (node->nodeType()) {
1515 case Node::TEXT_NODE:
1516 case Node::CDATA_SECTION_NODE:
1517 case Node::COMMENT_NODE:
1518 isNullString = false;
1519 content.append(downcast<CharacterData>(*node).data());
1520 break;
1521
1522 case Node::PROCESSING_INSTRUCTION_NODE:
1523 isNullString = false;
1524 content.append(downcast<ProcessingInstruction>(*node).data());
1525 break;
1526
1527 case Node::ATTRIBUTE_NODE:
1528 isNullString = false;
1529 content.append(downcast<Attr>(*node).value());
1530 break;
1531
1532 case Node::ELEMENT_NODE:
1533 if (node->hasTagName(brTag) && convertBRsToNewlines) {
1534 isNullString = false;
1535 content.append('\n');
1536 break;
1537 }
1538 FALLTHROUGH;
1539 case Node::DOCUMENT_FRAGMENT_NODE:
1540 isNullString = false;
1541 for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
1542 if (child->nodeType() == Node::COMMENT_NODE || child->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
1543 continue;
1544 appendTextContent(child, convertBRsToNewlines, isNullString, content);
1545 }
1546 break;
1547
1548 case Node::DOCUMENT_NODE:
1549 case Node::DOCUMENT_TYPE_NODE:
1550 break;
1551 }
1552}
1553
1554String Node::textContent(bool convertBRsToNewlines) const
1555{
1556 StringBuilder content;
1557 bool isNullString = true;
1558 appendTextContent(this, convertBRsToNewlines, isNullString, content);
1559 return isNullString ? String() : content.toString();
1560}
1561
1562ExceptionOr<void> Node::setTextContent(const String& text)
1563{
1564 switch (nodeType()) {
1565 case ATTRIBUTE_NODE:
1566 case TEXT_NODE:
1567 case CDATA_SECTION_NODE:
1568 case COMMENT_NODE:
1569 case PROCESSING_INSTRUCTION_NODE:
1570 return setNodeValue(text);
1571 case ELEMENT_NODE:
1572 case DOCUMENT_FRAGMENT_NODE: {
1573 auto& container = downcast<ContainerNode>(*this);
1574 if (text.isEmpty())
1575 container.replaceAllChildren(nullptr);
1576 else
1577 container.replaceAllChildren(document().createTextNode(text));
1578 return { };
1579 }
1580 case DOCUMENT_NODE:
1581 case DOCUMENT_TYPE_NODE:
1582 // Do nothing.
1583 return { };
1584 }
1585 ASSERT_NOT_REACHED();
1586 return { };
1587}
1588
1589static SHA1::Digest hashPointer(void* pointer)
1590{
1591 SHA1 sha1;
1592 sha1.addBytes(reinterpret_cast<const uint8_t*>(&pointer), sizeof(pointer));
1593 SHA1::Digest digest;
1594 sha1.computeHash(digest);
1595 return digest;
1596}
1597
1598static inline unsigned short compareDetachedElementsPosition(Node& firstNode, Node& secondNode)
1599{
1600 // If the 2 nodes are not in the same tree, return the result of adding DOCUMENT_POSITION_DISCONNECTED,
1601 // DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC, and either DOCUMENT_POSITION_PRECEDING or
1602 // DOCUMENT_POSITION_FOLLOWING, with the constraint that this is to be consistent. Whether to return
1603 // DOCUMENT_POSITION_PRECEDING or DOCUMENT_POSITION_FOLLOWING is implemented by comparing cryptographic
1604 // hashes of Node pointers.
1605 // See step 3 in https://dom.spec.whatwg.org/#dom-node-comparedocumentposition
1606 SHA1::Digest firstHash = hashPointer(&firstNode);
1607 SHA1::Digest secondHash = hashPointer(&secondNode);
1608
1609 unsigned short direction = memcmp(firstHash.data(), secondHash.data(), SHA1::hashSize) > 0 ? Node::DOCUMENT_POSITION_PRECEDING : Node::DOCUMENT_POSITION_FOLLOWING;
1610
1611 return Node::DOCUMENT_POSITION_DISCONNECTED | Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction;
1612}
1613
1614unsigned short Node::compareDocumentPosition(Node& otherNode)
1615{
1616 if (&otherNode == this)
1617 return DOCUMENT_POSITION_EQUIVALENT;
1618
1619 Attr* attr1 = is<Attr>(*this) ? downcast<Attr>(this) : nullptr;
1620 Attr* attr2 = is<Attr>(otherNode) ? &downcast<Attr>(otherNode) : nullptr;
1621
1622 Node* start1 = attr1 ? attr1->ownerElement() : this;
1623 Node* start2 = attr2 ? attr2->ownerElement() : &otherNode;
1624
1625 // If either of start1 or start2 is null, then we are disconnected, since one of the nodes is
1626 // an orphaned attribute node.
1627 if (!start1 || !start2)
1628 return compareDetachedElementsPosition(*this, otherNode);
1629
1630 Vector<Node*, 16> chain1;
1631 Vector<Node*, 16> chain2;
1632 if (attr1)
1633 chain1.append(attr1);
1634 if (attr2)
1635 chain2.append(attr2);
1636
1637 if (attr1 && attr2 && start1 == start2 && start1) {
1638 // We are comparing two attributes on the same node. Crawl our attribute map and see which one we hit first.
1639 Element* owner1 = attr1->ownerElement();
1640 owner1->synchronizeAllAttributes();
1641 for (const Attribute& attribute : owner1->attributesIterator()) {
1642 // If neither of the two determining nodes is a child node and nodeType is the same for both determining nodes, then an
1643 // implementation-dependent order between the determining nodes is returned. This order is stable as long as no nodes of
1644 // the same nodeType are inserted into or removed from the direct container. This would be the case, for example,
1645 // when comparing two attributes of the same element, and inserting or removing additional attributes might change
1646 // the order between existing attributes.
1647 if (attr1->qualifiedName() == attribute.name())
1648 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING;
1649 if (attr2->qualifiedName() == attribute.name())
1650 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_PRECEDING;
1651 }
1652
1653 ASSERT_NOT_REACHED();
1654 return DOCUMENT_POSITION_DISCONNECTED;
1655 }
1656
1657 // If one node is in the document and the other is not, we must be disconnected.
1658 // If the nodes have different owning documents, they must be disconnected. Note that we avoid
1659 // comparing Attr nodes here, since they return false from isConnected() all the time (which seems like a bug).
1660 if (start1->isConnected() != start2->isConnected() || &start1->treeScope() != &start2->treeScope())
1661 return compareDetachedElementsPosition(*this, otherNode);
1662
1663 // We need to find a common ancestor container, and then compare the indices of the two immediate children.
1664 Node* current;
1665 for (current = start1; current; current = current->parentNode())
1666 chain1.append(current);
1667 for (current = start2; current; current = current->parentNode())
1668 chain2.append(current);
1669
1670 unsigned index1 = chain1.size();
1671 unsigned index2 = chain2.size();
1672
1673 // If the two elements don't have a common root, they're not in the same tree.
1674 if (chain1[index1 - 1] != chain2[index2 - 1])
1675 return compareDetachedElementsPosition(*this, otherNode);
1676
1677 // Walk the two chains backwards and look for the first difference.
1678 for (unsigned i = std::min(index1, index2); i; --i) {
1679 Node* child1 = chain1[--index1];
1680 Node* child2 = chain2[--index2];
1681 if (child1 != child2) {
1682 // If one of the children is an attribute, it wins.
1683 if (child1->nodeType() == ATTRIBUTE_NODE)
1684 return DOCUMENT_POSITION_FOLLOWING;
1685 if (child2->nodeType() == ATTRIBUTE_NODE)
1686 return DOCUMENT_POSITION_PRECEDING;
1687
1688 if (!child2->nextSibling())
1689 return DOCUMENT_POSITION_FOLLOWING;
1690 if (!child1->nextSibling())
1691 return DOCUMENT_POSITION_PRECEDING;
1692
1693 // Otherwise we need to see which node occurs first. Crawl backwards from child2 looking for child1.
1694 for (Node* child = child2->previousSibling(); child; child = child->previousSibling()) {
1695 if (child == child1)
1696 return DOCUMENT_POSITION_FOLLOWING;
1697 }
1698 return DOCUMENT_POSITION_PRECEDING;
1699 }
1700 }
1701
1702 // There was no difference between the two parent chains, i.e., one was a subset of the other. The shorter
1703 // chain is the ancestor.
1704 return index1 < index2 ?
1705 DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_CONTAINED_BY :
1706 DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_CONTAINS;
1707}
1708
1709FloatPoint Node::convertToPage(const FloatPoint& p) const
1710{
1711 // If there is a renderer, just ask it to do the conversion
1712 if (renderer())
1713 return renderer()->localToAbsolute(p, UseTransforms);
1714
1715 // Otherwise go up the tree looking for a renderer
1716 if (auto* parent = parentElement())
1717 return parent->convertToPage(p);
1718
1719 // No parent - no conversion needed
1720 return p;
1721}
1722
1723FloatPoint Node::convertFromPage(const FloatPoint& p) const
1724{
1725 // If there is a renderer, just ask it to do the conversion
1726 if (renderer())
1727 return renderer()->absoluteToLocal(p, UseTransforms);
1728
1729 // Otherwise go up the tree looking for a renderer
1730 if (auto* parent = parentElement())
1731 return parent->convertFromPage(p);
1732
1733 // No parent - no conversion needed
1734 return p;
1735}
1736
1737#if ENABLE(TREE_DEBUGGING)
1738
1739static void appendAttributeDesc(const Node* node, StringBuilder& stringBuilder, const QualifiedName& name, const char* attrDesc)
1740{
1741 if (!is<Element>(*node))
1742 return;
1743
1744 const AtomString& attr = downcast<Element>(*node).getAttribute(name);
1745 if (attr.isEmpty())
1746 return;
1747
1748 stringBuilder.append(attrDesc);
1749 stringBuilder.append(attr);
1750}
1751
1752void Node::showNode(const char* prefix) const
1753{
1754 if (!prefix)
1755 prefix = "";
1756 if (isTextNode()) {
1757 String value = nodeValue();
1758 value.replaceWithLiteral('\\', "\\\\");
1759 value.replaceWithLiteral('\n', "\\n");
1760 fprintf(stderr, "%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this, value.utf8().data());
1761 } else {
1762 StringBuilder attrs;
1763 appendAttributeDesc(this, attrs, classAttr, " CLASS=");
1764 appendAttributeDesc(this, attrs, styleAttr, " STYLE=");
1765 fprintf(stderr, "%s%s\t%p (renderer %p) %s%s%s\n", prefix, nodeName().utf8().data(), this, renderer(), attrs.toString().utf8().data(), needsStyleRecalc() ? " (needs style recalc)" : "", childNeedsStyleRecalc() ? " (child needs style recalc)" : "");
1766 }
1767}
1768
1769void Node::showTreeForThis() const
1770{
1771 showTreeAndMark(this, "*");
1772}
1773
1774void Node::showNodePathForThis() const
1775{
1776 Vector<const Node*, 16> chain;
1777 const Node* node = this;
1778 while (node->parentOrShadowHostNode()) {
1779 chain.append(node);
1780 node = node->parentOrShadowHostNode();
1781 }
1782 for (unsigned index = chain.size(); index > 0; --index) {
1783 const Node* node = chain[index - 1];
1784 if (is<ShadowRoot>(*node)) {
1785 int count = 0;
1786 for (const ShadowRoot* shadowRoot = downcast<ShadowRoot>(node); shadowRoot && shadowRoot != node; shadowRoot = shadowRoot->shadowRoot())
1787 ++count;
1788 fprintf(stderr, "/#shadow-root[%d]", count);
1789 continue;
1790 }
1791
1792 switch (node->nodeType()) {
1793 case ELEMENT_NODE: {
1794 fprintf(stderr, "/%s", node->nodeName().utf8().data());
1795
1796 const Element& element = downcast<Element>(*node);
1797 const AtomString& idattr = element.getIdAttribute();
1798 bool hasIdAttr = !idattr.isNull() && !idattr.isEmpty();
1799 if (node->previousSibling() || node->nextSibling()) {
1800 int count = 0;
1801 for (Node* previous = node->previousSibling(); previous; previous = previous->previousSibling())
1802 if (previous->nodeName() == node->nodeName())
1803 ++count;
1804 if (hasIdAttr)
1805 fprintf(stderr, "[@id=\"%s\" and position()=%d]", idattr.string().utf8().data(), count);
1806 else
1807 fprintf(stderr, "[%d]", count);
1808 } else if (hasIdAttr)
1809 fprintf(stderr, "[@id=\"%s\"]", idattr.string().utf8().data());
1810 break;
1811 }
1812 case TEXT_NODE:
1813 fprintf(stderr, "/text()");
1814 break;
1815 case ATTRIBUTE_NODE:
1816 fprintf(stderr, "/@%s", node->nodeName().utf8().data());
1817 break;
1818 default:
1819 break;
1820 }
1821 }
1822 fprintf(stderr, "\n");
1823}
1824
1825static void traverseTreeAndMark(const String& baseIndent, const Node* rootNode, const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2)
1826{
1827 for (const Node* node = rootNode; node; node = NodeTraversal::next(*node)) {
1828 if (node == markedNode1)
1829 fprintf(stderr, "%s", markedLabel1);
1830 if (node == markedNode2)
1831 fprintf(stderr, "%s", markedLabel2);
1832
1833 StringBuilder indent;
1834 indent.append(baseIndent);
1835 for (const Node* tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentOrShadowHostNode())
1836 indent.append('\t');
1837 fprintf(stderr, "%s", indent.toString().utf8().data());
1838 node->showNode();
1839 indent.append('\t');
1840 if (!node->isShadowRoot()) {
1841 if (ShadowRoot* shadowRoot = node->shadowRoot())
1842 traverseTreeAndMark(indent.toString(), shadowRoot, markedNode1, markedLabel1, markedNode2, markedLabel2);
1843 }
1844 }
1845}
1846
1847void Node::showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2) const
1848{
1849 const Node* rootNode;
1850 const Node* node = this;
1851 while (node->parentOrShadowHostNode() && !node->hasTagName(bodyTag))
1852 node = node->parentOrShadowHostNode();
1853 rootNode = node;
1854
1855 String startingIndent;
1856 traverseTreeAndMark(startingIndent, rootNode, markedNode1, markedLabel1, markedNode2, markedLabel2);
1857}
1858
1859void Node::formatForDebugger(char* buffer, unsigned length) const
1860{
1861 String result;
1862 String s;
1863
1864 s = nodeName();
1865 if (s.isEmpty())
1866 result = "<none>";
1867 else
1868 result = s;
1869
1870 strncpy(buffer, result.utf8().data(), length - 1);
1871}
1872
1873static ContainerNode* parentOrShadowHostOrFrameOwner(const Node* node)
1874{
1875 ContainerNode* parent = node->parentOrShadowHostNode();
1876 if (!parent && node->document().frame())
1877 parent = node->document().frame()->ownerElement();
1878 return parent;
1879}
1880
1881static void showSubTreeAcrossFrame(const Node* node, const Node* markedNode, const String& indent)
1882{
1883 if (node == markedNode)
1884 fputs("*", stderr);
1885 fputs(indent.utf8().data(), stderr);
1886 node->showNode();
1887 if (!node->isShadowRoot()) {
1888 if (node->isFrameOwnerElement())
1889 showSubTreeAcrossFrame(static_cast<const HTMLFrameOwnerElement*>(node)->contentDocument(), markedNode, indent + "\t");
1890 if (ShadowRoot* shadowRoot = node->shadowRoot())
1891 showSubTreeAcrossFrame(shadowRoot, markedNode, indent + "\t");
1892 }
1893 for (Node* child = node->firstChild(); child; child = child->nextSibling())
1894 showSubTreeAcrossFrame(child, markedNode, indent + "\t");
1895}
1896
1897void Node::showTreeForThisAcrossFrame() const
1898{
1899 Node* rootNode = const_cast<Node*>(this);
1900 while (parentOrShadowHostOrFrameOwner(rootNode))
1901 rootNode = parentOrShadowHostOrFrameOwner(rootNode);
1902 showSubTreeAcrossFrame(rootNode, this, "");
1903}
1904
1905#endif // ENABLE(TREE_DEBUGGING)
1906
1907// --------
1908
1909void NodeListsNodeData::invalidateCaches()
1910{
1911 for (auto& atomicName : m_atomicNameCaches)
1912 atomicName.value->invalidateCache();
1913
1914 for (auto& collection : m_cachedCollections)
1915 collection.value->invalidateCache();
1916
1917 for (auto& tagCollection : m_tagCollectionNSCache)
1918 tagCollection.value->invalidateCache();
1919}
1920
1921void NodeListsNodeData::invalidateCachesForAttribute(const QualifiedName& attrName)
1922{
1923 for (auto& atomicName : m_atomicNameCaches)
1924 atomicName.value->invalidateCacheForAttribute(attrName);
1925
1926 for (auto& collection : m_cachedCollections)
1927 collection.value->invalidateCacheForAttribute(attrName);
1928}
1929
1930void Node::getSubresourceURLs(ListHashSet<URL>& urls) const
1931{
1932 addSubresourceAttributeURLs(urls);
1933}
1934
1935Element* Node::enclosingLinkEventParentOrSelf()
1936{
1937 for (Node* node = this; node; node = node->parentInComposedTree()) {
1938 // For imagemaps, the enclosing link element is the associated area element not the image itself.
1939 // So we don't let images be the enclosing link element, even though isLink sometimes returns
1940 // true for them.
1941 if (node->isLink() && !is<HTMLImageElement>(*node))
1942 return downcast<Element>(node);
1943 }
1944
1945 return nullptr;
1946}
1947
1948EventTargetInterface Node::eventTargetInterface() const
1949{
1950 return NodeEventTargetInterfaceType;
1951}
1952
1953template <typename MoveNodeFunction, typename MoveShadowRootFunction>
1954static void traverseSubtreeToUpdateTreeScope(Node& root, MoveNodeFunction moveNode, MoveShadowRootFunction moveShadowRoot)
1955{
1956 for (Node* node = &root; node; node = NodeTraversal::next(*node, &root)) {
1957 moveNode(*node);
1958
1959 if (!is<Element>(*node))
1960 continue;
1961 Element& element = downcast<Element>(*node);
1962
1963 if (element.hasSyntheticAttrChildNodes()) {
1964 for (auto& attr : element.attrNodeList())
1965 moveNode(*attr);
1966 }
1967
1968 if (auto* shadow = element.shadowRoot())
1969 moveShadowRoot(*shadow);
1970 }
1971}
1972
1973inline void Node::moveShadowTreeToNewDocument(ShadowRoot& shadowRoot, Document& oldDocument, Document& newDocument)
1974{
1975 traverseSubtreeToUpdateTreeScope(shadowRoot, [&oldDocument, &newDocument](Node& node) {
1976 node.moveNodeToNewDocument(oldDocument, newDocument);
1977 }, [&oldDocument, &newDocument](ShadowRoot& innerShadowRoot) {
1978 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(&innerShadowRoot.document() == &oldDocument);
1979 innerShadowRoot.moveShadowRootToNewDocument(newDocument);
1980 moveShadowTreeToNewDocument(innerShadowRoot, oldDocument, newDocument);
1981 });
1982}
1983
1984void Node::moveTreeToNewScope(Node& root, TreeScope& oldScope, TreeScope& newScope)
1985{
1986 ASSERT(&oldScope != &newScope);
1987
1988 Document& oldDocument = oldScope.documentScope();
1989 Document& newDocument = newScope.documentScope();
1990 if (&oldDocument != &newDocument) {
1991 oldDocument.incrementReferencingNodeCount();
1992 traverseSubtreeToUpdateTreeScope(root, [&](Node& node) {
1993 ASSERT(!node.isTreeScope());
1994 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(&node.treeScope() == &oldScope);
1995 node.setTreeScope(newScope);
1996 node.moveNodeToNewDocument(oldDocument, newDocument);
1997 }, [&](ShadowRoot& shadowRoot) {
1998 ASSERT_WITH_SECURITY_IMPLICATION(&shadowRoot.document() == &oldDocument);
1999 shadowRoot.moveShadowRootToNewParentScope(newScope, newDocument);
2000 moveShadowTreeToNewDocument(shadowRoot, oldDocument, newDocument);
2001 });
2002 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(&oldScope.documentScope() == &oldDocument && &newScope.documentScope() == &newDocument);
2003 oldDocument.decrementReferencingNodeCount();
2004 } else {
2005 traverseSubtreeToUpdateTreeScope(root, [&](Node& node) {
2006 ASSERT(!node.isTreeScope());
2007 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(&node.treeScope() == &oldScope);
2008 node.setTreeScope(newScope);
2009 if (UNLIKELY(!node.hasRareData()))
2010 return;
2011 if (auto* nodeLists = node.rareData()->nodeLists())
2012 nodeLists->adoptTreeScope();
2013 }, [&newScope](ShadowRoot& shadowRoot) {
2014 shadowRoot.setParentTreeScope(newScope);
2015 });
2016 }
2017}
2018
2019void Node::moveNodeToNewDocument(Document& oldDocument, Document& newDocument)
2020{
2021 newDocument.incrementReferencingNodeCount();
2022 oldDocument.decrementReferencingNodeCount();
2023
2024 if (hasRareData()) {
2025 if (auto* nodeLists = rareData()->nodeLists())
2026 nodeLists->adoptDocument(oldDocument, newDocument);
2027 if (auto* registry = mutationObserverRegistry()) {
2028 for (auto& registration : *registry)
2029 newDocument.addMutationObserverTypes(registration->mutationTypes());
2030 }
2031 if (auto* transientRegistry = transientMutationObserverRegistry()) {
2032 for (auto& registration : *transientRegistry)
2033 newDocument.addMutationObserverTypes(registration->mutationTypes());
2034 }
2035 } else {
2036 ASSERT(!mutationObserverRegistry());
2037 ASSERT(!transientMutationObserverRegistry());
2038 }
2039
2040 oldDocument.moveNodeIteratorsToNewDocument(*this, newDocument);
2041
2042 if (AXObjectCache::accessibilityEnabled()) {
2043 if (auto* cache = oldDocument.existingAXObjectCache())
2044 cache->remove(*this);
2045 }
2046
2047 if (auto* eventTargetData = this->eventTargetData()) {
2048 if (!eventTargetData->eventListenerMap.isEmpty()) {
2049 for (auto& type : eventTargetData->eventListenerMap.eventTypes())
2050 newDocument.addListenerTypeIfNeeded(type);
2051 }
2052
2053 unsigned numWheelEventHandlers = eventListeners(eventNames().mousewheelEvent).size() + eventListeners(eventNames().wheelEvent).size();
2054 for (unsigned i = 0; i < numWheelEventHandlers; ++i) {
2055 oldDocument.didRemoveWheelEventHandler(*this);
2056 newDocument.didAddWheelEventHandler(*this);
2057 }
2058
2059 unsigned numTouchEventListeners = 0;
2060#if ENABLE(TOUCH_EVENTS)
2061 if (newDocument.quirks().shouldDispatchSimulatedMouseEvents() || RuntimeEnabledFeatures::sharedFeatures().mouseEventsSimulationEnabled()) {
2062 for (auto& name : eventNames().extendedTouchRelatedEventNames())
2063 numTouchEventListeners += eventListeners(name).size();
2064 } else {
2065#endif
2066 for (auto& name : eventNames().touchRelatedEventNames())
2067 numTouchEventListeners += eventListeners(name).size();
2068#if ENABLE(TOUCH_EVENTS)
2069 }
2070#endif
2071
2072 for (unsigned i = 0; i < numTouchEventListeners; ++i) {
2073 oldDocument.didRemoveTouchEventHandler(*this);
2074 newDocument.didAddTouchEventHandler(*this);
2075#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
2076 oldDocument.removeTouchEventListener(*this);
2077 newDocument.addTouchEventListener(*this);
2078#endif
2079 }
2080
2081#if ENABLE(TOUCH_EVENTS) && ENABLE(IOS_GESTURE_EVENTS)
2082 unsigned numGestureEventListeners = 0;
2083 for (auto& name : eventNames().gestureEventNames())
2084 numGestureEventListeners += eventListeners(name).size();
2085
2086 for (unsigned i = 0; i < numGestureEventListeners; ++i) {
2087 oldDocument.removeTouchEventHandler(*this);
2088 newDocument.addTouchEventHandler(*this);
2089 }
2090#endif
2091 }
2092
2093#if !ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS)
2094#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
2095 ASSERT_WITH_SECURITY_IMPLICATION(!oldDocument.touchEventListenersContain(*this));
2096 ASSERT_WITH_SECURITY_IMPLICATION(!oldDocument.touchEventHandlersContain(*this));
2097#endif
2098#if ENABLE(TOUCH_EVENTS) && ENABLE(IOS_GESTURE_EVENTS)
2099 ASSERT_WITH_SECURITY_IMPLICATION(!oldDocument.touchEventTargetsContain(*this));
2100#endif
2101#endif
2102
2103 if (is<Element>(*this))
2104 downcast<Element>(*this).didMoveToNewDocument(oldDocument, newDocument);
2105}
2106
2107static inline bool tryAddEventListener(Node* targetNode, const AtomString& eventType, Ref<EventListener>&& listener, const EventTarget::AddEventListenerOptions& options)
2108{
2109 if (!targetNode->EventTarget::addEventListener(eventType, listener.copyRef(), options))
2110 return false;
2111
2112 targetNode->document().addListenerTypeIfNeeded(eventType);
2113 if (eventNames().isWheelEventType(eventType))
2114 targetNode->document().didAddWheelEventHandler(*targetNode);
2115 else if (eventNames().isTouchRelatedEventType(targetNode->document(), eventType))
2116 targetNode->document().didAddTouchEventHandler(*targetNode);
2117
2118#if PLATFORM(IOS_FAMILY)
2119 if (targetNode == &targetNode->document() && eventType == eventNames().scrollEvent)
2120 targetNode->document().domWindow()->incrementScrollEventListenersCount();
2121
2122#if ENABLE(TOUCH_EVENTS)
2123 if (eventNames().isTouchRelatedEventType(targetNode->document(), eventType))
2124 targetNode->document().addTouchEventListener(*targetNode);
2125#endif
2126#endif // PLATFORM(IOS_FAMILY)
2127
2128#if ENABLE(IOS_GESTURE_EVENTS) && ENABLE(TOUCH_EVENTS)
2129 if (eventNames().isGestureEventType(eventType))
2130 targetNode->document().addTouchEventHandler(*targetNode);
2131#endif
2132
2133 return true;
2134}
2135
2136bool Node::addEventListener(const AtomString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
2137{
2138 return tryAddEventListener(this, eventType, WTFMove(listener), options);
2139}
2140
2141static inline bool tryRemoveEventListener(Node* targetNode, const AtomString& eventType, EventListener& listener, const EventTarget::ListenerOptions& options)
2142{
2143 if (!targetNode->EventTarget::removeEventListener(eventType, listener, options))
2144 return false;
2145
2146 // FIXME: Notify Document that the listener has vanished. We need to keep track of a number of
2147 // listeners for each type, not just a bool - see https://bugs.webkit.org/show_bug.cgi?id=33861
2148 if (eventNames().isWheelEventType(eventType))
2149 targetNode->document().didRemoveWheelEventHandler(*targetNode);
2150 else if (eventNames().isTouchRelatedEventType(targetNode->document(), eventType))
2151 targetNode->document().didRemoveTouchEventHandler(*targetNode);
2152
2153#if PLATFORM(IOS_FAMILY)
2154 if (targetNode == &targetNode->document() && eventType == eventNames().scrollEvent)
2155 targetNode->document().domWindow()->decrementScrollEventListenersCount();
2156
2157#if ENABLE(TOUCH_EVENTS)
2158 if (eventNames().isTouchRelatedEventType(targetNode->document(), eventType))
2159 targetNode->document().removeTouchEventListener(*targetNode);
2160#endif
2161#endif // PLATFORM(IOS_FAMILY)
2162
2163#if ENABLE(IOS_GESTURE_EVENTS) && ENABLE(TOUCH_EVENTS)
2164 if (eventNames().isGestureEventType(eventType))
2165 targetNode->document().removeTouchEventHandler(*targetNode);
2166#endif
2167
2168 return true;
2169}
2170
2171bool Node::removeEventListener(const AtomString& eventType, EventListener& listener, const ListenerOptions& options)
2172{
2173 return tryRemoveEventListener(this, eventType, listener, options);
2174}
2175
2176typedef HashMap<Node*, std::unique_ptr<EventTargetData>> EventTargetDataMap;
2177
2178static EventTargetDataMap& eventTargetDataMap()
2179{
2180 static NeverDestroyed<EventTargetDataMap> map;
2181
2182 return map;
2183}
2184
2185static Lock s_eventTargetDataMapLock;
2186
2187EventTargetData* Node::eventTargetData()
2188{
2189 return hasEventTargetData() ? eventTargetDataMap().get(this) : nullptr;
2190}
2191
2192EventTargetData* Node::eventTargetDataConcurrently()
2193{
2194 // Not holding the lock when the world is stopped accelerates parallel constraint solving, which
2195 // calls this function from many threads. Parallel constraint solving can happen with the world
2196 // running or stopped, but if we do it with a running world, then we're usually mixing constraint
2197 // solving with other work. Therefore, the most likely time for contention on this lock is when the
2198 // world is stopped. We don't have to hold the lock when the world is stopped, because a stopped world
2199 // means that we will never mutate the event target data map.
2200 JSC::VM* vm = commonVMOrNull();
2201 auto locker = holdLockIf(s_eventTargetDataMapLock, vm && vm->heap.worldIsRunning());
2202 return hasEventTargetData() ? eventTargetDataMap().get(this) : nullptr;
2203}
2204
2205EventTargetData& Node::ensureEventTargetData()
2206{
2207 if (hasEventTargetData())
2208 return *eventTargetDataMap().get(this);
2209
2210 JSC::VM* vm = commonVMOrNull();
2211 RELEASE_ASSERT(!vm || vm->heap.worldIsRunning());
2212
2213 auto locker = holdLock(s_eventTargetDataMapLock);
2214 setHasEventTargetData(true);
2215 return *eventTargetDataMap().add(this, std::make_unique<EventTargetData>()).iterator->value;
2216}
2217
2218void Node::clearEventTargetData()
2219{
2220 JSC::VM* vm = commonVMOrNull();
2221 RELEASE_ASSERT(!vm || vm->heap.worldIsRunning());
2222 auto locker = holdLock(s_eventTargetDataMapLock);
2223 eventTargetDataMap().remove(this);
2224}
2225
2226Vector<std::unique_ptr<MutationObserverRegistration>>* Node::mutationObserverRegistry()
2227{
2228 if (!hasRareData())
2229 return nullptr;
2230 auto* data = rareData()->mutationObserverData();
2231 if (!data)
2232 return nullptr;
2233 return &data->registry;
2234}
2235
2236HashSet<MutationObserverRegistration*>* Node::transientMutationObserverRegistry()
2237{
2238 if (!hasRareData())
2239 return nullptr;
2240 auto* data = rareData()->mutationObserverData();
2241 if (!data)
2242 return nullptr;
2243 return &data->transientRegistry;
2244}
2245
2246template<typename Registry> static inline void collectMatchingObserversForMutation(HashMap<Ref<MutationObserver>, MutationRecordDeliveryOptions>& observers, Registry* registry, Node& target, MutationObserver::MutationType type, const QualifiedName* attributeName)
2247{
2248 if (!registry)
2249 return;
2250
2251 for (auto& registration : *registry) {
2252 if (registration->shouldReceiveMutationFrom(target, type, attributeName)) {
2253 auto deliveryOptions = registration->deliveryOptions();
2254 auto result = observers.add(registration->observer(), deliveryOptions);
2255 if (!result.isNewEntry)
2256 result.iterator->value |= deliveryOptions;
2257 }
2258 }
2259}
2260
2261HashMap<Ref<MutationObserver>, MutationRecordDeliveryOptions> Node::registeredMutationObservers(MutationObserver::MutationType type, const QualifiedName* attributeName)
2262{
2263 HashMap<Ref<MutationObserver>, MutationRecordDeliveryOptions> result;
2264 ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName);
2265 collectMatchingObserversForMutation(result, mutationObserverRegistry(), *this, type, attributeName);
2266 collectMatchingObserversForMutation(result, transientMutationObserverRegistry(), *this, type, attributeName);
2267 for (Node* node = parentNode(); node; node = node->parentNode()) {
2268 collectMatchingObserversForMutation(result, node->mutationObserverRegistry(), *this, type, attributeName);
2269 collectMatchingObserversForMutation(result, node->transientMutationObserverRegistry(), *this, type, attributeName);
2270 }
2271 return result;
2272}
2273
2274void Node::registerMutationObserver(MutationObserver& observer, MutationObserverOptions options, const HashSet<AtomString>& attributeFilter)
2275{
2276 MutationObserverRegistration* registration = nullptr;
2277 auto& registry = ensureRareData().ensureMutationObserverData().registry;
2278
2279 for (auto& candidateRegistration : registry) {
2280 if (&candidateRegistration->observer() == &observer) {
2281 registration = candidateRegistration.get();
2282 registration->resetObservation(options, attributeFilter);
2283 }
2284 }
2285
2286 if (!registration) {
2287 registry.append(std::make_unique<MutationObserverRegistration>(observer, *this, options, attributeFilter));
2288 registration = registry.last().get();
2289 }
2290
2291 document().addMutationObserverTypes(registration->mutationTypes());
2292}
2293
2294void Node::unregisterMutationObserver(MutationObserverRegistration& registration)
2295{
2296 auto* registry = mutationObserverRegistry();
2297 ASSERT(registry);
2298 if (!registry)
2299 return;
2300
2301 registry->removeFirstMatching([&registration] (auto& current) {
2302 return current.get() == &registration;
2303 });
2304}
2305
2306void Node::registerTransientMutationObserver(MutationObserverRegistration& registration)
2307{
2308 ensureRareData().ensureMutationObserverData().transientRegistry.add(&registration);
2309}
2310
2311void Node::unregisterTransientMutationObserver(MutationObserverRegistration& registration)
2312{
2313 auto* transientRegistry = transientMutationObserverRegistry();
2314 ASSERT(transientRegistry);
2315 if (!transientRegistry)
2316 return;
2317
2318 ASSERT(transientRegistry->contains(&registration));
2319 transientRegistry->remove(&registration);
2320}
2321
2322void Node::notifyMutationObserversNodeWillDetach()
2323{
2324 if (!document().hasMutationObservers())
2325 return;
2326
2327 for (Node* node = parentNode(); node; node = node->parentNode()) {
2328 if (auto* registry = node->mutationObserverRegistry()) {
2329 for (auto& registration : *registry)
2330 registration->observedSubtreeNodeWillDetach(*this);
2331 }
2332 if (auto* transientRegistry = node->transientMutationObserverRegistry()) {
2333 for (auto* registration : *transientRegistry)
2334 registration->observedSubtreeNodeWillDetach(*this);
2335 }
2336 }
2337}
2338
2339void Node::handleLocalEvents(Event& event, EventInvokePhase phase)
2340{
2341 if (!hasEventTargetData())
2342 return;
2343
2344 // FIXME: Should we deliver wheel events to disabled form controls or not?
2345 if (is<Element>(*this) && downcast<Element>(*this).isDisabledFormControl() && event.isMouseEvent() && !event.isWheelEvent())
2346 return;
2347
2348 fireEventListeners(event, phase);
2349}
2350
2351void Node::dispatchScopedEvent(Event& event)
2352{
2353 EventDispatcher::dispatchScopedEvent(*this, event);
2354}
2355
2356void Node::dispatchEvent(Event& event)
2357{
2358 EventDispatcher::dispatchEvent(*this, event);
2359}
2360
2361void Node::dispatchSubtreeModifiedEvent()
2362{
2363 if (isInShadowTree())
2364 return;
2365
2366 ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isEventDispatchAllowedInSubtree(*this));
2367
2368 if (!document().hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER))
2369 return;
2370 const AtomString& subtreeModifiedEventName = eventNames().DOMSubtreeModifiedEvent;
2371 if (!parentNode() && !hasEventListeners(subtreeModifiedEventName))
2372 return;
2373
2374 dispatchScopedEvent(MutationEvent::create(subtreeModifiedEventName, Event::CanBubble::Yes));
2375}
2376
2377void Node::dispatchDOMActivateEvent(Event& underlyingClickEvent)
2378{
2379 ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed());
2380 int detail = is<UIEvent>(underlyingClickEvent) ? downcast<UIEvent>(underlyingClickEvent).detail() : 0;
2381 auto event = UIEvent::create(eventNames().DOMActivateEvent, Event::CanBubble::Yes, Event::IsCancelable::Yes, Event::IsComposed::Yes, document().windowProxy(), detail);
2382 event->setUnderlyingEvent(&underlyingClickEvent);
2383 dispatchScopedEvent(event);
2384 if (event->defaultHandled())
2385 underlyingClickEvent.setDefaultHandled();
2386}
2387
2388bool Node::dispatchBeforeLoadEvent(const String& sourceURL)
2389{
2390 if (!document().hasListenerType(Document::BEFORELOAD_LISTENER))
2391 return true;
2392
2393 Ref<Node> protectedThis(*this);
2394 auto event = BeforeLoadEvent::create(sourceURL);
2395 dispatchEvent(event);
2396 return !event->defaultPrevented();
2397}
2398
2399void Node::dispatchInputEvent()
2400{
2401 dispatchScopedEvent(Event::create(eventNames().inputEvent, Event::CanBubble::Yes, Event::IsCancelable::No, Event::IsComposed::Yes));
2402}
2403
2404void Node::defaultEventHandler(Event& event)
2405{
2406 if (event.target() != this)
2407 return;
2408 const AtomString& eventType = event.type();
2409 if (eventType == eventNames().keydownEvent || eventType == eventNames().keypressEvent) {
2410 if (is<KeyboardEvent>(event)) {
2411 if (Frame* frame = document().frame())
2412 frame->eventHandler().defaultKeyboardEventHandler(downcast<KeyboardEvent>(event));
2413 }
2414 } else if (eventType == eventNames().clickEvent) {
2415 dispatchDOMActivateEvent(event);
2416#if ENABLE(CONTEXT_MENUS)
2417 } else if (eventType == eventNames().contextmenuEvent) {
2418 if (Frame* frame = document().frame())
2419 if (Page* page = frame->page())
2420 page->contextMenuController().handleContextMenuEvent(event);
2421#endif
2422 } else if (eventType == eventNames().textInputEvent) {
2423 if (is<TextEvent>(event)) {
2424 if (Frame* frame = document().frame())
2425 frame->eventHandler().defaultTextInputEventHandler(downcast<TextEvent>(event));
2426 }
2427#if ENABLE(PAN_SCROLLING)
2428 } else if (eventType == eventNames().mousedownEvent && is<MouseEvent>(event)) {
2429 if (downcast<MouseEvent>(event).button() == MiddleButton) {
2430 if (enclosingLinkEventParentOrSelf())
2431 return;
2432
2433 RenderObject* renderer = this->renderer();
2434 while (renderer && (!is<RenderBox>(*renderer) || !downcast<RenderBox>(*renderer).canBeScrolledAndHasScrollableArea()))
2435 renderer = renderer->parent();
2436
2437 if (renderer) {
2438 if (Frame* frame = document().frame())
2439 frame->eventHandler().startPanScrolling(downcast<RenderBox>(*renderer));
2440 }
2441 }
2442#endif
2443 } else if (eventNames().isWheelEventType(eventType) && is<WheelEvent>(event)) {
2444 // If we don't have a renderer, send the wheel event to the first node we find with a renderer.
2445 // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll.
2446 Node* startNode = this;
2447 while (startNode && !startNode->renderer())
2448 startNode = startNode->parentOrShadowHostNode();
2449
2450 if (startNode && startNode->renderer())
2451 if (Frame* frame = document().frame())
2452 frame->eventHandler().defaultWheelEventHandler(startNode, downcast<WheelEvent>(event));
2453#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
2454 } else if (is<TouchEvent>(event) && eventNames().isTouchRelatedEventType(document(), eventType)) {
2455 RenderObject* renderer = this->renderer();
2456 while (renderer && (!is<RenderBox>(*renderer) || !downcast<RenderBox>(*renderer).canBeScrolledAndHasScrollableArea()))
2457 renderer = renderer->parent();
2458
2459 if (renderer && renderer->node()) {
2460 if (Frame* frame = document().frame())
2461 frame->eventHandler().defaultTouchEventHandler(*renderer->node(), downcast<TouchEvent>(event));
2462 }
2463#endif
2464 }
2465}
2466
2467bool Node::willRespondToMouseMoveEvents()
2468{
2469 // FIXME: Why is the iOS code path different from the non-iOS code path?
2470#if !PLATFORM(IOS_FAMILY)
2471 if (!is<Element>(*this))
2472 return false;
2473 if (downcast<Element>(*this).isDisabledFormControl())
2474 return false;
2475#endif
2476 return hasEventListeners(eventNames().mousemoveEvent) || hasEventListeners(eventNames().mouseoverEvent) || hasEventListeners(eventNames().mouseoutEvent);
2477}
2478
2479bool Node::willRespondToMouseClickEvents()
2480{
2481 // FIXME: Why is the iOS code path different from the non-iOS code path?
2482#if PLATFORM(IOS_FAMILY)
2483 return isContentEditable() || hasEventListeners(eventNames().mouseupEvent) || hasEventListeners(eventNames().mousedownEvent) || hasEventListeners(eventNames().clickEvent);
2484#else
2485 if (!is<Element>(*this))
2486 return false;
2487 if (downcast<Element>(*this).isDisabledFormControl())
2488 return false;
2489 return computeEditability(UserSelectAllIsAlwaysNonEditable, ShouldUpdateStyle::Update) != Editability::ReadOnly
2490 || hasEventListeners(eventNames().mouseupEvent) || hasEventListeners(eventNames().mousedownEvent) || hasEventListeners(eventNames().clickEvent) || hasEventListeners(eventNames().DOMActivateEvent);
2491#endif
2492}
2493
2494bool Node::willRespondToMouseWheelEvents()
2495{
2496 return hasEventListeners(eventNames().mousewheelEvent);
2497}
2498
2499// It's important not to inline removedLastRef, because we don't want to inline the code to
2500// delete a Node at each deref call site.
2501void Node::removedLastRef()
2502{
2503 ASSERT(m_refCountAndParentBit == s_refCountIncrement);
2504
2505 // An explicit check for Document here is better than a virtual function since it is
2506 // faster for non-Document nodes, and because the call to removedLastRef that is inlined
2507 // at all deref call sites is smaller if it's a non-virtual function.
2508 if (is<Document>(*this)) {
2509 downcast<Document>(*this).removedLastRef();
2510 return;
2511 }
2512
2513 // Now it is time to detach the SVGElement from all its properties. These properties
2514 // may outlive the SVGElement. The only difference after the detach is no commit will
2515 // be carried out unless these properties are attached to another owner.
2516 if (is<SVGElement>(*this))
2517 downcast<SVGElement>(*this).detachAllProperties();
2518
2519#ifndef NDEBUG
2520 m_deletionHasBegun = true;
2521#endif
2522 delete this;
2523}
2524
2525void Node::textRects(Vector<IntRect>& rects) const
2526{
2527 auto range = Range::create(document());
2528 range->selectNodeContents(const_cast<Node&>(*this));
2529 range->absoluteTextRects(rects);
2530}
2531
2532unsigned Node::connectedSubframeCount() const
2533{
2534 return hasRareData() ? rareData()->connectedSubframeCount() : 0;
2535}
2536
2537void Node::incrementConnectedSubframeCount(unsigned amount)
2538{
2539 ASSERT(isContainerNode());
2540 ensureRareData().incrementConnectedSubframeCount(amount);
2541}
2542
2543void Node::decrementConnectedSubframeCount(unsigned amount)
2544{
2545 rareData()->decrementConnectedSubframeCount(amount);
2546}
2547
2548void Node::updateAncestorConnectedSubframeCountForRemoval() const
2549{
2550 unsigned count = connectedSubframeCount();
2551
2552 if (!count)
2553 return;
2554
2555 for (Node* node = parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode())
2556 node->decrementConnectedSubframeCount(count);
2557}
2558
2559void Node::updateAncestorConnectedSubframeCountForInsertion() const
2560{
2561 unsigned count = connectedSubframeCount();
2562
2563 if (!count)
2564 return;
2565
2566 for (Node* node = parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode())
2567 node->incrementConnectedSubframeCount(count);
2568}
2569
2570bool Node::inRenderedDocument() const
2571{
2572 return isConnected() && document().hasLivingRenderTree();
2573}
2574
2575void* Node::opaqueRootSlow() const
2576{
2577 const Node* node = this;
2578 for (;;) {
2579 const Node* nextNode = node->parentOrShadowHostNode();
2580 if (!nextNode)
2581 break;
2582 node = nextNode;
2583 }
2584 return const_cast<void*>(static_cast<const void*>(node));
2585}
2586
2587} // namespace WebCore
2588
2589#if ENABLE(TREE_DEBUGGING)
2590
2591void showTree(const WebCore::Node* node)
2592{
2593 if (node)
2594 node->showTreeForThis();
2595}
2596
2597void showNodePath(const WebCore::Node* node)
2598{
2599 if (node)
2600 node->showNodePathForThis();
2601}
2602
2603#endif // ENABLE(TREE_DEBUGGING)
2604