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/)
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 "core/dom/Node.h"
27
28 #include "bindings/core/v8/DOMDataStore.h"
29 #include "bindings/core/v8/ExceptionState.h"
30 #include "bindings/core/v8/ScriptCallStackFactory.h"
31 #include "bindings/core/v8/V8DOMWrapper.h"
32 #include "core/HTMLNames.h"
33 #include "core/XMLNames.h"
34 #include "core/accessibility/AXObjectCache.h"
35 #include "core/css/resolver/StyleResolver.h"
36 #include "core/dom/Attr.h"
37 #include "core/dom/Attribute.h"
38 #include "core/dom/ChildListMutationScope.h"
39 #include "core/dom/ChildNodeList.h"
40 #include "core/dom/DOMImplementation.h"
41 #include "core/dom/Document.h"
42 #include "core/dom/DocumentFragment.h"
43 #include "core/dom/DocumentMarkerController.h"
44 #include "core/dom/DocumentType.h"
45 #include "core/dom/Element.h"
46 #include "core/dom/ElementRareData.h"
47 #include "core/dom/ElementTraversal.h"
48 #include "core/dom/ExceptionCode.h"
49 #include "core/dom/LiveNodeList.h"
50 #include "core/dom/NodeRareData.h"
51 #include "core/dom/NodeRenderingTraversal.h"
52 #include "core/dom/NodeTraversal.h"
53 #include "core/dom/ProcessingInstruction.h"
54 #include "core/dom/Range.h"
55 #include "core/dom/StaticNodeList.h"
56 #include "core/dom/TemplateContentDocumentFragment.h"
57 #include "core/dom/Text.h"
58 #include "core/dom/TreeScopeAdopter.h"
59 #include "core/dom/UserActionElementSet.h"
60 #include "core/dom/WeakNodeMap.h"
61 #include "core/dom/shadow/ElementShadow.h"
62 #include "core/dom/shadow/InsertionPoint.h"
63 #include "core/dom/shadow/ShadowRoot.h"
64 #include "core/editing/htmlediting.h"
65 #include "core/editing/markup.h"
66 #include "core/events/Event.h"
67 #include "core/events/EventDispatchMediator.h"
68 #include "core/events/EventDispatcher.h"
69 #include "core/events/EventListener.h"
70 #include "core/events/GestureEvent.h"
71 #include "core/events/KeyboardEvent.h"
72 #include "core/events/MouseEvent.h"
73 #include "core/events/MutationEvent.h"
74 #include "core/events/TextEvent.h"
75 #include "core/events/TouchEvent.h"
76 #include "core/events/UIEvent.h"
77 #include "core/events/WheelEvent.h"
78 #include "core/frame/EventHandlerRegistry.h"
79 #include "core/frame/LocalFrame.h"
80 #include "core/frame/Settings.h"
81 #include "core/html/HTMLAnchorElement.h"
82 #include "core/html/HTMLDialogElement.h"
83 #include "core/html/HTMLFrameOwnerElement.h"
84 #include "core/html/HTMLStyleElement.h"
85 #include "core/page/ContextMenuController.h"
86 #include "core/page/EventHandler.h"
87 #include "core/page/Page.h"
88 #include "core/rendering/FlowThreadController.h"
89 #include "core/rendering/RenderBox.h"
90 #include "core/svg/graphics/SVGImage.h"
91 #include "platform/EventDispatchForbiddenScope.h"
92 #include "platform/Partitions.h"
93 #include "platform/TraceEvent.h"
94 #include "platform/TracedValue.h"
95 #include "wtf/HashSet.h"
96 #include "wtf/PassOwnPtr.h"
97 #include "wtf/RefCountedLeakCounter.h"
98 #include "wtf/Vector.h"
99 #include "wtf/text/CString.h"
100 #include "wtf/text/StringBuilder.h"
101
102 namespace blink {
103
104 using namespace HTMLNames;
105
106 struct SameSizeAsNode : NODE_BASE_CLASSES {
107 uint32_t m_nodeFlags;
108 void* m_pointer[5];
109 };
110
111 COMPILE_ASSERT(sizeof(Node) <= sizeof(SameSizeAsNode), Node_should_stay_small);
112
113 #if !ENABLE(OILPAN)
operator new(size_t size)114 void* Node::operator new(size_t size)
115 {
116 ASSERT(isMainThread());
117 return partitionAlloc(Partitions::getObjectModelPartition(), size);
118 }
119
operator delete(void * ptr)120 void Node::operator delete(void* ptr)
121 {
122 ASSERT(isMainThread());
123 partitionFree(ptr);
124 }
125 #endif
126
127 #if DUMP_NODE_STATISTICS
128 typedef WillBeHeapHashSet<RawPtrWillBeWeakMember<Node> > WeakNodeSet;
liveNodeSet()129 static WeakNodeSet& liveNodeSet()
130 {
131 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<WeakNodeSet>, set, (adoptPtrWillBeNoop(new WeakNodeSet())));
132 return *set;
133 }
134 #endif
135
dumpStatistics()136 void 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 elementsWithAttributeStorage = 0;
156 size_t elementsWithRareData = 0;
157 size_t elementsWithNamedNodeMap = 0;
158
159 for (WeakNodeSet::iterator it = liveNodeSet().begin(); it != liveNodeSet().end(); ++it) {
160 Node* node = *it;
161
162 if (node->hasRareData()) {
163 ++nodesWithRareData;
164 if (node->isElementNode()) {
165 ++elementsWithRareData;
166 if (toElement(node)->hasNamedNodeMap())
167 ++elementsWithNamedNodeMap;
168 }
169 }
170
171 switch (node->nodeType()) {
172 case ELEMENT_NODE: {
173 ++elementNodes;
174
175 // Tag stats
176 Element* element = toElement(node);
177 HashMap<String, size_t>::AddResult result = perTagCount.add(element->tagName(), 1);
178 if (!result.isNewEntry)
179 result.storedValue->value++;
180
181 if (const ElementData* elementData = element->elementData()) {
182 attributes += elementData->attributes().size();
183 ++elementsWithAttributeStorage;
184 }
185 break;
186 }
187 case ATTRIBUTE_NODE: {
188 ++attrNodes;
189 break;
190 }
191 case TEXT_NODE: {
192 ++textNodes;
193 break;
194 }
195 case CDATA_SECTION_NODE: {
196 ++cdataNodes;
197 break;
198 }
199 case COMMENT_NODE: {
200 ++commentNodes;
201 break;
202 }
203 case PROCESSING_INSTRUCTION_NODE: {
204 ++piNodes;
205 break;
206 }
207 case DOCUMENT_NODE: {
208 ++documentNodes;
209 break;
210 }
211 case DOCUMENT_TYPE_NODE: {
212 ++docTypeNodes;
213 break;
214 }
215 case DOCUMENT_FRAGMENT_NODE: {
216 if (node->isShadowRoot())
217 ++shadowRootNodes;
218 else
219 ++fragmentNodes;
220 break;
221 }
222 }
223 }
224
225 printf("Number of Nodes: %d\n\n", liveNodeSet().size());
226 printf("Number of Nodes with RareData: %zu\n\n", nodesWithRareData);
227
228 printf("NodeType distribution:\n");
229 printf(" Number of Element nodes: %zu\n", elementNodes);
230 printf(" Number of Attribute nodes: %zu\n", attrNodes);
231 printf(" Number of Text nodes: %zu\n", textNodes);
232 printf(" Number of CDATASection nodes: %zu\n", cdataNodes);
233 printf(" Number of Comment nodes: %zu\n", commentNodes);
234 printf(" Number of ProcessingInstruction nodes: %zu\n", piNodes);
235 printf(" Number of Document nodes: %zu\n", documentNodes);
236 printf(" Number of DocumentType nodes: %zu\n", docTypeNodes);
237 printf(" Number of DocumentFragment nodes: %zu\n", fragmentNodes);
238 printf(" Number of ShadowRoot nodes: %zu\n", shadowRootNodes);
239
240 printf("Element tag name distibution:\n");
241 for (HashMap<String, size_t>::iterator it = perTagCount.begin(); it != perTagCount.end(); ++it)
242 printf(" Number of <%s> tags: %zu\n", it->key.utf8().data(), it->value);
243
244 printf("Attributes:\n");
245 printf(" Number of Attributes (non-Node and Node): %zu [%zu]\n", attributes, sizeof(Attribute));
246 printf(" Number of Elements with attribute storage: %zu [%zu]\n", elementsWithAttributeStorage, sizeof(ElementData));
247 printf(" Number of Elements with RareData: %zu\n", elementsWithRareData);
248 printf(" Number of Elements with NamedNodeMap: %zu [%zu]\n", elementsWithNamedNodeMap, sizeof(NamedNodeMap));
249 #endif
250 }
251
252 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, nodeCounter, ("WebCoreNode"));
253
trackForDebugging()254 void Node::trackForDebugging()
255 {
256 #ifndef NDEBUG
257 nodeCounter.increment();
258 #endif
259
260 #if DUMP_NODE_STATISTICS
261 liveNodeSet().add(this);
262 #endif
263 }
264
Node(TreeScope * treeScope,ConstructionType type)265 Node::Node(TreeScope* treeScope, ConstructionType type)
266 : m_nodeFlags(type)
267 , m_parentOrShadowHostNode(nullptr)
268 , m_treeScope(treeScope)
269 , m_previous(nullptr)
270 , m_next(nullptr)
271 {
272 ASSERT(m_treeScope || type == CreateDocument || type == CreateShadowRoot);
273 #if !ENABLE(OILPAN)
274 if (m_treeScope)
275 m_treeScope->guardRef();
276 #endif
277
278 #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
279 trackForDebugging();
280 #endif
281 InspectorCounters::incrementCounter(InspectorCounters::NodeCounter);
282 }
283
~Node()284 Node::~Node()
285 {
286 #ifndef NDEBUG
287 nodeCounter.decrement();
288 #endif
289
290 #if !ENABLE(OILPAN)
291 #if DUMP_NODE_STATISTICS
292 liveNodeSet().remove(this);
293 #endif
294
295 if (hasRareData())
296 clearRareData();
297
298 RELEASE_ASSERT(!renderer());
299
300 if (!isContainerNode())
301 willBeDeletedFromDocument();
302
303 if (m_previous)
304 m_previous->setNextSibling(0);
305 if (m_next)
306 m_next->setPreviousSibling(0);
307
308 if (m_treeScope)
309 m_treeScope->guardDeref();
310
311 if (getFlag(HasWeakReferencesFlag))
312 WeakNodeMap::notifyNodeDestroyed(this);
313 #else
314 // With Oilpan, the rare data finalizer also asserts for
315 // this condition (we cannot directly access it here.)
316 RELEASE_ASSERT(hasRareData() || !renderer());
317 #endif
318
319 InspectorCounters::decrementCounter(InspectorCounters::NodeCounter);
320 }
321
322 #if !ENABLE(OILPAN)
323 // With Oilpan all of this is handled with weak processing of the document.
willBeDeletedFromDocument()324 void Node::willBeDeletedFromDocument()
325 {
326 if (!isTreeScopeInitialized())
327 return;
328
329 Document& document = this->document();
330
331 if (hasEventTargetData())
332 clearEventTargetData();
333
334 if (document.frameHost())
335 document.frameHost()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);
336
337 if (AXObjectCache* cache = document.existingAXObjectCache())
338 cache->remove(this);
339
340 document.markers().removeMarkers(this);
341 }
342 #endif
343
rareData() const344 NodeRareData* Node::rareData() const
345 {
346 ASSERT_WITH_SECURITY_IMPLICATION(hasRareData());
347 return static_cast<NodeRareData*>(m_data.m_rareData);
348 }
349
ensureRareData()350 NodeRareData& Node::ensureRareData()
351 {
352 if (hasRareData())
353 return *rareData();
354
355 if (isElementNode())
356 m_data.m_rareData = ElementRareData::create(m_data.m_renderer);
357 else
358 m_data.m_rareData = NodeRareData::create(m_data.m_renderer);
359
360 ASSERT(m_data.m_rareData);
361
362 setFlag(HasRareDataFlag);
363 return *rareData();
364 }
365
366 #if !ENABLE(OILPAN)
clearRareData()367 void Node::clearRareData()
368 {
369 ASSERT(hasRareData());
370 ASSERT(!transientMutationObserverRegistry() || transientMutationObserverRegistry()->isEmpty());
371
372 RenderObject* renderer = m_data.m_rareData->renderer();
373 if (isElementNode())
374 delete static_cast<ElementRareData*>(m_data.m_rareData);
375 else
376 delete static_cast<NodeRareData*>(m_data.m_rareData);
377 m_data.m_renderer = renderer;
378 clearFlag(HasRareDataFlag);
379 }
380 #endif
381
toNode()382 Node* Node::toNode()
383 {
384 return this;
385 }
386
tabIndex() const387 short Node::tabIndex() const
388 {
389 return 0;
390 }
391
nodeValue() const392 String Node::nodeValue() const
393 {
394 return String();
395 }
396
setNodeValue(const String &)397 void Node::setNodeValue(const String&)
398 {
399 // By default, setting nodeValue has no effect.
400 }
401
childNodes()402 PassRefPtrWillBeRawPtr<NodeList> Node::childNodes()
403 {
404 if (isContainerNode())
405 return ensureRareData().ensureNodeLists().ensureChildNodeList(toContainerNode(*this));
406 return ensureRareData().ensureNodeLists().ensureEmptyChildNodeList(*this);
407 }
408
pseudoAwarePreviousSibling() const409 Node* Node::pseudoAwarePreviousSibling() const
410 {
411 if (parentElement() && !previousSibling()) {
412 Element* parent = parentElement();
413 if (isAfterPseudoElement() && parent->lastChild())
414 return parent->lastChild();
415 if (!isBeforePseudoElement())
416 return parent->pseudoElement(BEFORE);
417 }
418 return previousSibling();
419 }
420
pseudoAwareNextSibling() const421 Node* Node::pseudoAwareNextSibling() const
422 {
423 if (parentElement() && !nextSibling()) {
424 Element* parent = parentElement();
425 if (isBeforePseudoElement() && parent->hasChildren())
426 return parent->firstChild();
427 if (!isAfterPseudoElement())
428 return parent->pseudoElement(AFTER);
429 }
430 return nextSibling();
431 }
432
pseudoAwareFirstChild() const433 Node* Node::pseudoAwareFirstChild() const
434 {
435 if (isElementNode()) {
436 const Element* currentElement = toElement(this);
437 Node* first = currentElement->pseudoElement(BEFORE);
438 if (first)
439 return first;
440 first = currentElement->firstChild();
441 if (!first)
442 first = currentElement->pseudoElement(AFTER);
443 return first;
444 }
445
446 return firstChild();
447 }
448
pseudoAwareLastChild() const449 Node* Node::pseudoAwareLastChild() const
450 {
451 if (isElementNode()) {
452 const Element* currentElement = toElement(this);
453 Node* last = currentElement->pseudoElement(AFTER);
454 if (last)
455 return last;
456 last = currentElement->lastChild();
457 if (!last)
458 last = currentElement->pseudoElement(BEFORE);
459 return last;
460 }
461
462 return lastChild();
463 }
464
insertBefore(PassRefPtrWillBeRawPtr<Node> newChild,Node * refChild,ExceptionState & exceptionState)465 PassRefPtrWillBeRawPtr<Node> Node::insertBefore(PassRefPtrWillBeRawPtr<Node> newChild, Node* refChild, ExceptionState& exceptionState)
466 {
467 if (isContainerNode())
468 return toContainerNode(this)->insertBefore(newChild, refChild, exceptionState);
469
470 exceptionState.throwDOMException(HierarchyRequestError, "This node type does not support this method.");
471 return nullptr;
472 }
473
replaceChild(PassRefPtrWillBeRawPtr<Node> newChild,PassRefPtrWillBeRawPtr<Node> oldChild,ExceptionState & exceptionState)474 PassRefPtrWillBeRawPtr<Node> Node::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, PassRefPtrWillBeRawPtr<Node> oldChild, ExceptionState& exceptionState)
475 {
476 if (isContainerNode())
477 return toContainerNode(this)->replaceChild(newChild, oldChild, exceptionState);
478
479 exceptionState.throwDOMException(HierarchyRequestError, "This node type does not support this method.");
480 return nullptr;
481 }
482
removeChild(PassRefPtrWillBeRawPtr<Node> oldChild,ExceptionState & exceptionState)483 PassRefPtrWillBeRawPtr<Node> Node::removeChild(PassRefPtrWillBeRawPtr<Node> oldChild, ExceptionState& exceptionState)
484 {
485 if (isContainerNode())
486 return toContainerNode(this)->removeChild(oldChild, exceptionState);
487
488 exceptionState.throwDOMException(NotFoundError, "This node type does not support this method.");
489 return nullptr;
490 }
491
appendChild(PassRefPtrWillBeRawPtr<Node> newChild,ExceptionState & exceptionState)492 PassRefPtrWillBeRawPtr<Node> Node::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, ExceptionState& exceptionState)
493 {
494 if (isContainerNode())
495 return toContainerNode(this)->appendChild(newChild, exceptionState);
496
497 exceptionState.throwDOMException(HierarchyRequestError, "This node type does not support this method.");
498 return nullptr;
499 }
500
remove(ExceptionState & exceptionState)501 void Node::remove(ExceptionState& exceptionState)
502 {
503 if (ContainerNode* parent = parentNode())
504 parent->removeChild(this, exceptionState);
505 }
506
normalize()507 void Node::normalize()
508 {
509 document().updateDistributionForNodeIfNeeded(this);
510
511 // Go through the subtree beneath us, normalizing all nodes. This means that
512 // any two adjacent text nodes are merged and any empty text nodes are removed.
513
514 RefPtrWillBeRawPtr<Node> node = this;
515 while (Node* firstChild = node->firstChild())
516 node = firstChild;
517 while (node) {
518 if (node->isElementNode())
519 toElement(node)->normalizeAttributes();
520
521 if (node == this)
522 break;
523
524 if (node->nodeType() == TEXT_NODE)
525 node = toText(node)->mergeNextSiblingNodesIfPossible();
526 else
527 node = NodeTraversal::nextPostOrder(*node);
528 }
529 }
530
localName() const531 const AtomicString& Node::localName() const
532 {
533 return nullAtom;
534 }
535
namespaceURI() const536 const AtomicString& Node::namespaceURI() const
537 {
538 return nullAtom;
539 }
540
isContentEditable(UserSelectAllTreatment treatment)541 bool Node::isContentEditable(UserSelectAllTreatment treatment)
542 {
543 document().updateRenderTreeIfNeeded();
544 return hasEditableStyle(Editable, treatment);
545 }
546
isContentRichlyEditable()547 bool Node::isContentRichlyEditable()
548 {
549 document().updateRenderTreeIfNeeded();
550 return hasEditableStyle(RichlyEditable, UserSelectAllIsAlwaysNonEditable);
551 }
552
hasEditableStyle(EditableLevel editableLevel,UserSelectAllTreatment treatment) const553 bool Node::hasEditableStyle(EditableLevel editableLevel, UserSelectAllTreatment treatment) const
554 {
555 if (isPseudoElement())
556 return false;
557
558 // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but
559 // ContainerNode::setFocus() calls setNeedsStyleRecalc(), so the assertion
560 // would fire in the middle of Document::setFocusedNode().
561
562 for (const Node* node = this; node; node = node->parentNode()) {
563 if ((node->isHTMLElement() || node->isDocumentNode()) && node->renderer()) {
564 // Elements with user-select: all style are considered atomic
565 // therefore non editable.
566 if (Position::nodeIsUserSelectAll(node) && treatment == UserSelectAllIsAlwaysNonEditable)
567 return false;
568 switch (node->renderer()->style()->userModify()) {
569 case READ_ONLY:
570 return false;
571 case READ_WRITE:
572 return true;
573 case READ_WRITE_PLAINTEXT_ONLY:
574 return editableLevel != RichlyEditable;
575 }
576 ASSERT_NOT_REACHED();
577 return false;
578 }
579 }
580
581 return false;
582 }
583
isEditableToAccessibility(EditableLevel editableLevel) const584 bool Node::isEditableToAccessibility(EditableLevel editableLevel) const
585 {
586 if (hasEditableStyle(editableLevel))
587 return true;
588
589 // FIXME: Respect editableLevel for ARIA editable elements.
590 if (editableLevel == RichlyEditable)
591 return false;
592
593 ASSERT(document().settings() && document().settings()->accessibilityEnabled());
594 ASSERT(document().existingAXObjectCache());
595
596 if (AXObjectCache* cache = document().existingAXObjectCache())
597 return cache->rootAXEditableElement(this);
598
599 return false;
600 }
601
renderBox() const602 RenderBox* Node::renderBox() const
603 {
604 RenderObject* renderer = this->renderer();
605 return renderer && renderer->isBox() ? toRenderBox(renderer) : 0;
606 }
607
renderBoxModelObject() const608 RenderBoxModelObject* Node::renderBoxModelObject() const
609 {
610 RenderObject* renderer = this->renderer();
611 return renderer && renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
612 }
613
boundingBox() const614 LayoutRect Node::boundingBox() const
615 {
616 if (renderer())
617 return renderer()->absoluteBoundingBoxRect();
618 return LayoutRect();
619 }
620
hasNonEmptyBoundingBox() const621 bool Node::hasNonEmptyBoundingBox() const
622 {
623 // Before calling absoluteRects, check for the common case where the renderer
624 // is non-empty, since this is a faster check and almost always returns true.
625 RenderBoxModelObject* box = renderBoxModelObject();
626 if (!box)
627 return false;
628 if (!box->borderBoundingBox().isEmpty())
629 return true;
630
631 Vector<IntRect> rects;
632 FloatPoint absPos = renderer()->localToAbsolute();
633 renderer()->absoluteRects(rects, flooredLayoutPoint(absPos));
634 size_t n = rects.size();
635 for (size_t i = 0; i < n; ++i)
636 if (!rects[i].isEmpty())
637 return true;
638
639 return false;
640 }
641
642 #ifndef NDEBUG
oldestShadowRootFor(const Node * node)643 inline static ShadowRoot* oldestShadowRootFor(const Node* node)
644 {
645 if (!node->isElementNode())
646 return 0;
647 if (ElementShadow* shadow = toElement(node)->shadow())
648 return shadow->oldestShadowRoot();
649 return 0;
650 }
651 #endif
652
recalcDistribution()653 void Node::recalcDistribution()
654 {
655 if (isElementNode()) {
656 if (ElementShadow* shadow = toElement(this)->shadow())
657 shadow->distributeIfNeeded();
658 }
659
660 for (Node* child = firstChild(); child; child = child->nextSibling()) {
661 if (child->childNeedsDistributionRecalc())
662 child->recalcDistribution();
663 }
664
665 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
666 if (root->childNeedsDistributionRecalc())
667 root->recalcDistribution();
668 }
669
670 clearChildNeedsDistributionRecalc();
671 }
672
setIsLink(bool isLink)673 void Node::setIsLink(bool isLink)
674 {
675 setFlag(isLink && !SVGImage::isInSVGImage(toElement(this)), IsLinkFlag);
676 }
677
setNeedsStyleInvalidation()678 void Node::setNeedsStyleInvalidation()
679 {
680 setFlag(NeedsStyleInvalidationFlag);
681 markAncestorsWithChildNeedsStyleInvalidation();
682 }
683
markAncestorsWithChildNeedsStyleInvalidation()684 void Node::markAncestorsWithChildNeedsStyleInvalidation()
685 {
686 for (Node* node = parentOrShadowHostNode(); node && !node->childNeedsStyleInvalidation(); node = node->parentOrShadowHostNode())
687 node->setChildNeedsStyleInvalidation();
688 document().scheduleRenderTreeUpdateIfNeeded();
689 }
690
markAncestorsWithChildNeedsDistributionRecalc()691 void Node::markAncestorsWithChildNeedsDistributionRecalc()
692 {
693 for (Node* node = this; node && !node->childNeedsDistributionRecalc(); node = node->parentOrShadowHostNode())
694 node->setChildNeedsDistributionRecalc();
695 document().scheduleRenderTreeUpdateIfNeeded();
696 }
697
698 namespace {
699
addJsStack(TracedValue * stackFrames)700 void addJsStack(TracedValue* stackFrames)
701 {
702 RefPtrWillBeRawPtr<ScriptCallStack> stack = createScriptCallStack(10);
703 if (!stack)
704 return;
705 for (size_t i = 0; i < stack->size(); i++)
706 stackFrames->pushString(stack->at(i).functionName());
707 }
708
jsonObjectForStyleInvalidation(unsigned nodeCount,const Node * rootNode)709 PassRefPtr<TraceEvent::ConvertableToTraceFormat> jsonObjectForStyleInvalidation(unsigned nodeCount, const Node* rootNode)
710 {
711 RefPtr<TracedValue> value = TracedValue::create();
712 value->setInteger("node_count", nodeCount);
713 value->setString("root_node", rootNode->debugName());
714 value->beginArray("js_stack");
715 addJsStack(value.get());
716 value->endArray();
717 return value;
718 }
719
720 } // anonymous namespace'd functions supporting traceStyleChange
721
styledSubtreeSize() const722 unsigned Node::styledSubtreeSize() const
723 {
724 unsigned nodeCount = 0;
725
726 for (const Node* node = this; node; node = NodeTraversal::next(*node, this)) {
727 if (node->isTextNode() || node->isElementNode())
728 nodeCount++;
729 for (ShadowRoot* root = node->youngestShadowRoot(); root; root = root->olderShadowRoot())
730 nodeCount += root->styledSubtreeSize();
731 }
732
733 return nodeCount;
734 }
735
traceStyleChange(StyleChangeType changeType)736 void Node::traceStyleChange(StyleChangeType changeType)
737 {
738 static const unsigned kMinLoggedSize = 100;
739 unsigned nodeCount = styledSubtreeSize();
740 if (nodeCount < kMinLoggedSize)
741 return;
742
743 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("style.debug"),
744 "Node::setNeedsStyleRecalc",
745 "data", jsonObjectForStyleInvalidation(nodeCount, this)
746 );
747 }
748
traceStyleChangeIfNeeded(StyleChangeType changeType)749 void Node::traceStyleChangeIfNeeded(StyleChangeType changeType)
750 {
751 // TRACE_EVENT_CATEGORY_GROUP_ENABLED macro loads a global static bool into our local bool.
752 bool styleTracingEnabled;
753 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("style.debug"), &styleTracingEnabled);
754 if (UNLIKELY(styleTracingEnabled))
755 traceStyleChange(changeType);
756 }
757
setStyleChange(StyleChangeType changeType)758 inline void Node::setStyleChange(StyleChangeType changeType)
759 {
760 m_nodeFlags = (m_nodeFlags & ~StyleChangeMask) | changeType;
761 }
762
markAncestorsWithChildNeedsStyleRecalc()763 void Node::markAncestorsWithChildNeedsStyleRecalc()
764 {
765 for (ContainerNode* p = parentOrShadowHostNode(); p && !p->childNeedsStyleRecalc(); p = p->parentOrShadowHostNode())
766 p->setChildNeedsStyleRecalc();
767 document().scheduleRenderTreeUpdateIfNeeded();
768 }
769
setNeedsStyleRecalc(StyleChangeType changeType)770 void Node::setNeedsStyleRecalc(StyleChangeType changeType)
771 {
772 ASSERT(changeType != NoStyleChange);
773 if (!inActiveDocument())
774 return;
775
776 StyleChangeType existingChangeType = styleChangeType();
777 if (changeType > existingChangeType) {
778 setStyleChange(changeType);
779 if (changeType >= SubtreeStyleChange)
780 traceStyleChangeIfNeeded(changeType);
781 }
782
783 if (existingChangeType == NoStyleChange)
784 markAncestorsWithChildNeedsStyleRecalc();
785
786 if (isElementNode() && hasRareData())
787 toElement(*this).setAnimationStyleChange(false);
788 }
789
clearNeedsStyleRecalc()790 void Node::clearNeedsStyleRecalc()
791 {
792 m_nodeFlags &= ~StyleChangeMask;
793
794 clearSVGFilterNeedsLayerUpdate();
795
796 if (isElementNode() && hasRareData())
797 toElement(*this).setAnimationStyleChange(false);
798 }
799
inActiveDocument() const800 bool Node::inActiveDocument() const
801 {
802 return inDocument() && document().isActive();
803 }
804
focusDelegate()805 Node* Node::focusDelegate()
806 {
807 return this;
808 }
809
shouldHaveFocusAppearance() const810 bool Node::shouldHaveFocusAppearance() const
811 {
812 ASSERT(focused());
813 return true;
814 }
815
isInert() const816 bool Node::isInert() const
817 {
818 const HTMLDialogElement* dialog = document().activeModalDialog();
819 if (dialog && this != document() && !NodeRenderingTraversal::contains(dialog, this))
820 return true;
821 return document().ownerElement() && document().ownerElement()->isInert();
822 }
823
nodeIndex() const824 unsigned Node::nodeIndex() const
825 {
826 Node *_tempNode = previousSibling();
827 unsigned count=0;
828 for ( count=0; _tempNode; count++ )
829 _tempNode = _tempNode->previousSibling();
830 return count;
831 }
832
nodeLists()833 NodeListsNodeData* Node::nodeLists()
834 {
835 return hasRareData() ? rareData()->nodeLists() : 0;
836 }
837
clearNodeLists()838 void Node::clearNodeLists()
839 {
840 rareData()->clearNodeLists();
841 }
842
isDescendantOf(const Node * other) const843 bool Node::isDescendantOf(const Node *other) const
844 {
845 // Return true if other is an ancestor of this, otherwise false
846 if (!other || !other->hasChildren() || inDocument() != other->inDocument())
847 return false;
848 if (other->treeScope() != treeScope())
849 return false;
850 if (other->isTreeScope())
851 return !isTreeScope();
852 for (const ContainerNode* n = parentNode(); n; n = n->parentNode()) {
853 if (n == other)
854 return true;
855 }
856 return false;
857 }
858
contains(const Node * node) const859 bool Node::contains(const Node* node) const
860 {
861 if (!node)
862 return false;
863 return this == node || node->isDescendantOf(this);
864 }
865
containsIncludingShadowDOM(const Node * node) const866 bool Node::containsIncludingShadowDOM(const Node* node) const
867 {
868 if (!node)
869 return false;
870
871 if (this == node)
872 return true;
873
874 if (document() != node->document())
875 return false;
876
877 if (inDocument() != node->inDocument())
878 return false;
879
880 bool hasChildren = isContainerNode() && toContainerNode(this)->hasChildren();
881 bool hasShadow = isElementNode() && toElement(this)->shadow();
882 if (!hasChildren && !hasShadow)
883 return false;
884
885 for (; node; node = node->shadowHost()) {
886 if (treeScope() == node->treeScope())
887 return contains(node);
888 }
889
890 return false;
891 }
892
containsIncludingHostElements(const Node & node) const893 bool Node::containsIncludingHostElements(const Node& node) const
894 {
895 const Node* current = &node;
896 do {
897 if (current == this)
898 return true;
899 if (current->isDocumentFragment() && toDocumentFragment(current)->isTemplateContent())
900 current = static_cast<const TemplateContentDocumentFragment*>(current)->host();
901 else
902 current = current->parentOrShadowHostNode();
903 } while (current);
904 return false;
905 }
906
commonAncestor(const Node & other,Node * (* parent)(const Node &))907 Node* Node::commonAncestor(const Node& other, Node* (*parent)(const Node&))
908 {
909 if (this == other)
910 return this;
911 if (document() != other.document())
912 return 0;
913 int thisDepth = 0;
914 for (Node* node = this; node; node = parent(*node)) {
915 if (node == &other)
916 return node;
917 thisDepth++;
918 }
919 int otherDepth = 0;
920 for (const Node* node = &other; node; node = parent(*node)) {
921 if (node == this)
922 return this;
923 otherDepth++;
924 }
925 Node* thisIterator = this;
926 const Node* otherIterator = &other;
927 if (thisDepth > otherDepth) {
928 for (int i = thisDepth; i > otherDepth; --i)
929 thisIterator = parent(*thisIterator);
930 } else if (otherDepth > thisDepth) {
931 for (int i = otherDepth; i > thisDepth; --i)
932 otherIterator = parent(*otherIterator);
933 }
934 while (thisIterator) {
935 if (thisIterator == otherIterator)
936 return thisIterator;
937 thisIterator = parent(*thisIterator);
938 otherIterator = parent(*otherIterator);
939 }
940 ASSERT(!otherIterator);
941 return 0;
942 }
943
reattach(const AttachContext & context)944 void Node::reattach(const AttachContext& context)
945 {
946 AttachContext reattachContext(context);
947 reattachContext.performingReattach = true;
948
949 // We only need to detach if the node has already been through attach().
950 if (styleChangeType() < NeedsReattachStyleChange)
951 detach(reattachContext);
952 attach(reattachContext);
953 }
954
attach(const AttachContext &)955 void Node::attach(const AttachContext&)
956 {
957 ASSERT(document().inStyleRecalc() || isDocumentNode());
958 ASSERT(needsAttach());
959 ASSERT(!renderer() || (renderer()->style() && (renderer()->parent() || renderer()->isRenderView())));
960
961 clearNeedsStyleRecalc();
962
963 if (AXObjectCache* cache = document().axObjectCache())
964 cache->updateCacheAfterNodeIsAttached(this);
965 }
966
967 #if ENABLE(ASSERT)
968 static Node* detachingNode;
969
inDetach() const970 bool Node::inDetach() const
971 {
972 return detachingNode == this;
973 }
974 #endif
975
detach(const AttachContext & context)976 void Node::detach(const AttachContext& context)
977 {
978 ASSERT(document().lifecycle().stateAllowsDetach());
979 DocumentLifecycle::DetachScope willDetach(document().lifecycle());
980
981 #if ENABLE(ASSERT)
982 ASSERT(!detachingNode);
983 detachingNode = this;
984 #endif
985
986 if (renderer())
987 renderer()->destroyAndCleanupAnonymousWrappers();
988 setRenderer(0);
989
990 // Do not remove the element's hovered and active status
991 // if performing a reattach.
992 if (!context.performingReattach) {
993 Document& doc = document();
994 if (isUserActionElement()) {
995 if (hovered())
996 doc.hoveredNodeDetached(this);
997 if (inActiveChain())
998 doc.activeChainNodeDetached(this);
999 doc.userActionElements().didDetach(this);
1000 }
1001 }
1002
1003 setStyleChange(NeedsReattachStyleChange);
1004 setChildNeedsStyleRecalc();
1005
1006 if (StyleResolver* resolver = document().styleResolver())
1007 resolver->ruleFeatureSet().styleInvalidator().clearInvalidation(*this);
1008 clearChildNeedsStyleInvalidation();
1009 clearNeedsStyleInvalidation();
1010
1011 #if ENABLE(ASSERT)
1012 detachingNode = 0;
1013 #endif
1014 }
1015
reattachWhitespaceSiblings(Text * start)1016 void Node::reattachWhitespaceSiblings(Text* start)
1017 {
1018 for (Node* sibling = start; sibling; sibling = sibling->nextSibling()) {
1019 if (sibling->isTextNode() && toText(sibling)->containsOnlyWhitespace()) {
1020 bool hadRenderer = !!sibling->renderer();
1021 sibling->reattach();
1022 // If the reattach didn't toggle the visibility of the whitespace we don't
1023 // need to continue reattaching siblings since they won't toggle visibility
1024 // either.
1025 if (hadRenderer == !!sibling->renderer())
1026 return;
1027 } else if (sibling->renderer()) {
1028 return;
1029 }
1030 }
1031 }
1032
1033 // FIXME: This code is used by editing. Seems like it could move over there and not pollute Node.
previousNodeConsideringAtomicNodes() const1034 Node *Node::previousNodeConsideringAtomicNodes() const
1035 {
1036 if (previousSibling()) {
1037 Node *n = previousSibling();
1038 while (!isAtomicNode(n) && n->lastChild())
1039 n = n->lastChild();
1040 return n;
1041 }
1042 else if (parentNode()) {
1043 return parentNode();
1044 }
1045 else {
1046 return 0;
1047 }
1048 }
1049
nextNodeConsideringAtomicNodes() const1050 Node *Node::nextNodeConsideringAtomicNodes() const
1051 {
1052 if (!isAtomicNode(this) && hasChildren())
1053 return firstChild();
1054 if (nextSibling())
1055 return nextSibling();
1056 const Node *n = this;
1057 while (n && !n->nextSibling())
1058 n = n->parentNode();
1059 if (n)
1060 return n->nextSibling();
1061 return 0;
1062 }
1063
previousLeafNode() const1064 Node *Node::previousLeafNode() const
1065 {
1066 Node *node = previousNodeConsideringAtomicNodes();
1067 while (node) {
1068 if (isAtomicNode(node))
1069 return node;
1070 node = node->previousNodeConsideringAtomicNodes();
1071 }
1072 return 0;
1073 }
1074
nextLeafNode() const1075 Node *Node::nextLeafNode() const
1076 {
1077 Node *node = nextNodeConsideringAtomicNodes();
1078 while (node) {
1079 if (isAtomicNode(node))
1080 return node;
1081 node = node->nextNodeConsideringAtomicNodes();
1082 }
1083 return 0;
1084 }
1085
virtualComputedStyle(PseudoId pseudoElementSpecifier)1086 RenderStyle* Node::virtualComputedStyle(PseudoId pseudoElementSpecifier)
1087 {
1088 return parentOrShadowHostNode() ? parentOrShadowHostNode()->computedStyle(pseudoElementSpecifier) : 0;
1089 }
1090
maxCharacterOffset() const1091 int Node::maxCharacterOffset() const
1092 {
1093 ASSERT_NOT_REACHED();
1094 return 0;
1095 }
1096
1097 // FIXME: Shouldn't these functions be in the editing code? Code that asks questions about HTML in the core DOM class
1098 // is obviously misplaced.
canStartSelection() const1099 bool Node::canStartSelection() const
1100 {
1101 if (hasEditableStyle())
1102 return true;
1103
1104 if (renderer()) {
1105 RenderStyle* style = renderer()->style();
1106 // We allow selections to begin within an element that has -webkit-user-select: none set,
1107 // but if the element is draggable then dragging should take priority over selection.
1108 if (style->userDrag() == DRAG_ELEMENT && style->userSelect() == SELECT_NONE)
1109 return false;
1110 }
1111 return parentOrShadowHostNode() ? parentOrShadowHostNode()->canStartSelection() : true;
1112 }
1113
shadowHost() const1114 Element* Node::shadowHost() const
1115 {
1116 if (ShadowRoot* root = containingShadowRoot())
1117 return root->host();
1118 return 0;
1119 }
1120
containingShadowRoot() const1121 ShadowRoot* Node::containingShadowRoot() const
1122 {
1123 Node& root = treeScope().rootNode();
1124 return root.isShadowRoot() ? toShadowRoot(&root) : 0;
1125 }
1126
nonBoundaryShadowTreeRootNode()1127 Node* Node::nonBoundaryShadowTreeRootNode()
1128 {
1129 ASSERT(!isShadowRoot());
1130 Node* root = this;
1131 while (root) {
1132 if (root->isShadowRoot())
1133 return root;
1134 Node* parent = root->parentOrShadowHostNode();
1135 if (parent && parent->isShadowRoot())
1136 return root;
1137 root = parent;
1138 }
1139 return 0;
1140 }
1141
nonShadowBoundaryParentNode() const1142 ContainerNode* Node::nonShadowBoundaryParentNode() const
1143 {
1144 ContainerNode* parent = parentNode();
1145 return parent && !parent->isShadowRoot() ? parent : 0;
1146 }
1147
parentOrShadowHostElement() const1148 Element* Node::parentOrShadowHostElement() const
1149 {
1150 ContainerNode* parent = parentOrShadowHostNode();
1151 if (!parent)
1152 return 0;
1153
1154 if (parent->isShadowRoot())
1155 return toShadowRoot(parent)->host();
1156
1157 if (!parent->isElementNode())
1158 return 0;
1159
1160 return toElement(parent);
1161 }
1162
parentOrShadowHostOrTemplateHostNode() const1163 ContainerNode* Node::parentOrShadowHostOrTemplateHostNode() const
1164 {
1165 if (isDocumentFragment() && toDocumentFragment(this)->isTemplateContent())
1166 return static_cast<const TemplateContentDocumentFragment*>(this)->host();
1167 return parentOrShadowHostNode();
1168 }
1169
isRootEditableElement() const1170 bool Node::isRootEditableElement() const
1171 {
1172 return hasEditableStyle() && isElementNode() && (!parentNode() || !parentNode()->hasEditableStyle()
1173 || !parentNode()->isElementNode() || isHTMLBodyElement((*this)));
1174 }
1175
rootEditableElement(EditableType editableType) const1176 Element* Node::rootEditableElement(EditableType editableType) const
1177 {
1178 if (editableType == HasEditableAXRole) {
1179 if (AXObjectCache* cache = document().existingAXObjectCache())
1180 return const_cast<Element*>(cache->rootAXEditableElement(this));
1181 }
1182
1183 return rootEditableElement();
1184 }
1185
rootEditableElement() const1186 Element* Node::rootEditableElement() const
1187 {
1188 Element* result = 0;
1189 for (Node* n = const_cast<Node*>(this); n && n->hasEditableStyle(); n = n->parentNode()) {
1190 if (n->isElementNode())
1191 result = toElement(n);
1192 if (isHTMLBodyElement(*n))
1193 break;
1194 }
1195 return result;
1196 }
1197
1198 // FIXME: End of obviously misplaced HTML editing functions. Try to move these out of Node.
1199
ownerDocument() const1200 Document* Node::ownerDocument() const
1201 {
1202 Document* doc = &document();
1203 return doc == this ? 0 : doc;
1204 }
1205
baseURI() const1206 KURL Node::baseURI() const
1207 {
1208 return parentNode() ? parentNode()->baseURI() : KURL();
1209 }
1210
isEqualNode(Node * other) const1211 bool Node::isEqualNode(Node* other) const
1212 {
1213 if (!other)
1214 return false;
1215
1216 NodeType nodeType = this->nodeType();
1217 if (nodeType != other->nodeType())
1218 return false;
1219
1220 if (nodeName() != other->nodeName())
1221 return false;
1222
1223 if (localName() != other->localName())
1224 return false;
1225
1226 if (namespaceURI() != other->namespaceURI())
1227 return false;
1228
1229 if (nodeValue() != other->nodeValue())
1230 return false;
1231
1232 if (isElementNode() && !toElement(this)->hasEquivalentAttributes(toElement(other)))
1233 return false;
1234
1235 Node* child = firstChild();
1236 Node* otherChild = other->firstChild();
1237
1238 while (child) {
1239 if (!child->isEqualNode(otherChild))
1240 return false;
1241
1242 child = child->nextSibling();
1243 otherChild = otherChild->nextSibling();
1244 }
1245
1246 if (otherChild)
1247 return false;
1248
1249 if (isDocumentTypeNode()) {
1250 const DocumentType* documentTypeThis = toDocumentType(this);
1251 const DocumentType* documentTypeOther = toDocumentType(other);
1252
1253 if (documentTypeThis->publicId() != documentTypeOther->publicId())
1254 return false;
1255
1256 if (documentTypeThis->systemId() != documentTypeOther->systemId())
1257 return false;
1258 }
1259
1260 return true;
1261 }
1262
isDefaultNamespace(const AtomicString & namespaceURIMaybeEmpty) const1263 bool Node::isDefaultNamespace(const AtomicString& namespaceURIMaybeEmpty) const
1264 {
1265 const AtomicString& namespaceURI = namespaceURIMaybeEmpty.isEmpty() ? nullAtom : namespaceURIMaybeEmpty;
1266
1267 switch (nodeType()) {
1268 case ELEMENT_NODE: {
1269 const Element& element = toElement(*this);
1270
1271 if (element.prefix().isNull())
1272 return element.namespaceURI() == namespaceURI;
1273
1274 AttributeCollection attributes = element.attributes();
1275 AttributeCollection::iterator end = attributes.end();
1276 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) {
1277 if (it->localName() == xmlnsAtom)
1278 return it->value() == namespaceURI;
1279 }
1280
1281 if (Element* parent = parentElement())
1282 return parent->isDefaultNamespace(namespaceURI);
1283
1284 return false;
1285 }
1286 case DOCUMENT_NODE:
1287 if (Element* de = toDocument(this)->documentElement())
1288 return de->isDefaultNamespace(namespaceURI);
1289 return false;
1290 case DOCUMENT_TYPE_NODE:
1291 case DOCUMENT_FRAGMENT_NODE:
1292 return false;
1293 case ATTRIBUTE_NODE: {
1294 const Attr* attr = toAttr(this);
1295 if (attr->ownerElement())
1296 return attr->ownerElement()->isDefaultNamespace(namespaceURI);
1297 return false;
1298 }
1299 default:
1300 if (Element* parent = parentElement())
1301 return parent->isDefaultNamespace(namespaceURI);
1302 return false;
1303 }
1304 }
1305
lookupPrefix(const AtomicString & namespaceURI) const1306 const AtomicString& Node::lookupPrefix(const AtomicString& namespaceURI) const
1307 {
1308 // Implemented according to
1309 // http://dom.spec.whatwg.org/#dom-node-lookupprefix
1310
1311 if (namespaceURI.isEmpty() || namespaceURI.isNull())
1312 return nullAtom;
1313
1314 const Element* context;
1315
1316 switch (nodeType()) {
1317 case ELEMENT_NODE:
1318 context = toElement(this);
1319 break;
1320 case DOCUMENT_NODE:
1321 context = toDocument(this)->documentElement();
1322 break;
1323 case DOCUMENT_FRAGMENT_NODE:
1324 case DOCUMENT_TYPE_NODE:
1325 context = 0;
1326 break;
1327 // FIXME: Remove this when Attr no longer extends Node (CR305105)
1328 case ATTRIBUTE_NODE:
1329 context = toAttr(this)->ownerElement();
1330 break;
1331 default:
1332 context = parentElement();
1333 break;
1334 }
1335
1336 if (!context)
1337 return nullAtom;
1338
1339 return context->locateNamespacePrefix(namespaceURI);
1340 }
1341
lookupNamespaceURI(const String & prefix) const1342 const AtomicString& Node::lookupNamespaceURI(const String& prefix) const
1343 {
1344 // Implemented according to
1345 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespaceURIAlgo
1346
1347 if (!prefix.isNull() && prefix.isEmpty())
1348 return nullAtom;
1349
1350 switch (nodeType()) {
1351 case ELEMENT_NODE: {
1352 const Element& element = toElement(*this);
1353
1354 if (!element.namespaceURI().isNull() && element.prefix() == prefix)
1355 return element.namespaceURI();
1356
1357 AttributeCollection attributes = element.attributes();
1358 AttributeCollection::iterator end = attributes.end();
1359 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) {
1360 if (it->prefix() == xmlnsAtom && it->localName() == prefix) {
1361 if (!it->value().isEmpty())
1362 return it->value();
1363 return nullAtom;
1364 }
1365 if (it->localName() == xmlnsAtom && prefix.isNull()) {
1366 if (!it->value().isEmpty())
1367 return it->value();
1368 return nullAtom;
1369 }
1370 }
1371
1372 if (Element* parent = parentElement())
1373 return parent->lookupNamespaceURI(prefix);
1374 return nullAtom;
1375 }
1376 case DOCUMENT_NODE:
1377 if (Element* de = toDocument(this)->documentElement())
1378 return de->lookupNamespaceURI(prefix);
1379 return nullAtom;
1380 case DOCUMENT_TYPE_NODE:
1381 case DOCUMENT_FRAGMENT_NODE:
1382 return nullAtom;
1383 case ATTRIBUTE_NODE: {
1384 const Attr *attr = toAttr(this);
1385 if (attr->ownerElement())
1386 return attr->ownerElement()->lookupNamespaceURI(prefix);
1387 else
1388 return nullAtom;
1389 }
1390 default:
1391 if (Element* parent = parentElement())
1392 return parent->lookupNamespaceURI(prefix);
1393 return nullAtom;
1394 }
1395 }
1396
appendTextContent(const Node * node,bool convertBRsToNewlines,bool & isNullString,StringBuilder & content)1397 static void appendTextContent(const Node* node, bool convertBRsToNewlines, bool& isNullString, StringBuilder& content)
1398 {
1399 switch (node->nodeType()) {
1400 case Node::TEXT_NODE:
1401 case Node::CDATA_SECTION_NODE:
1402 case Node::COMMENT_NODE:
1403 isNullString = false;
1404 content.append(toCharacterData(node)->data());
1405 break;
1406
1407 case Node::PROCESSING_INSTRUCTION_NODE:
1408 isNullString = false;
1409 content.append(toProcessingInstruction(node)->data());
1410 break;
1411
1412 case Node::ELEMENT_NODE:
1413 if (isHTMLBRElement(*node) && convertBRsToNewlines) {
1414 isNullString = false;
1415 content.append('\n');
1416 break;
1417 }
1418 // Fall through.
1419 case Node::ATTRIBUTE_NODE:
1420 case Node::DOCUMENT_FRAGMENT_NODE:
1421 isNullString = false;
1422 for (Node* child = toContainerNode(node)->firstChild(); child; child = child->nextSibling()) {
1423 Node::NodeType childNodeType = child->nodeType();
1424 if (childNodeType == Node::COMMENT_NODE || childNodeType == Node::PROCESSING_INSTRUCTION_NODE)
1425 continue;
1426 appendTextContent(child, convertBRsToNewlines, isNullString, content);
1427 }
1428 break;
1429
1430 case Node::DOCUMENT_NODE:
1431 case Node::DOCUMENT_TYPE_NODE:
1432 break;
1433 }
1434 }
1435
textContent(bool convertBRsToNewlines) const1436 String Node::textContent(bool convertBRsToNewlines) const
1437 {
1438 StringBuilder content;
1439 bool isNullString = true;
1440 appendTextContent(this, convertBRsToNewlines, isNullString, content);
1441 return isNullString ? String() : content.toString();
1442 }
1443
setTextContent(const String & text)1444 void Node::setTextContent(const String& text)
1445 {
1446 switch (nodeType()) {
1447 case TEXT_NODE:
1448 case CDATA_SECTION_NODE:
1449 case COMMENT_NODE:
1450 case PROCESSING_INSTRUCTION_NODE:
1451 setNodeValue(text);
1452 return;
1453 case ELEMENT_NODE:
1454 case ATTRIBUTE_NODE:
1455 case DOCUMENT_FRAGMENT_NODE: {
1456 // FIXME: Merge this logic into replaceChildrenWithText.
1457 RefPtrWillBeRawPtr<ContainerNode> container = toContainerNode(this);
1458
1459 // Note: This is an intentional optimization.
1460 // See crbug.com/352836 also.
1461 // No need to do anything if the text is identical.
1462 if (container->hasOneTextChild() && toText(container->firstChild())->data() == text)
1463 return;
1464
1465 ChildListMutationScope mutation(*this);
1466 container->removeChildren();
1467 // Note: This API will not insert empty text nodes:
1468 // http://dom.spec.whatwg.org/#dom-node-textcontent
1469 if (!text.isEmpty())
1470 container->appendChild(document().createTextNode(text), ASSERT_NO_EXCEPTION);
1471 return;
1472 }
1473 case DOCUMENT_NODE:
1474 case DOCUMENT_TYPE_NODE:
1475 // Do nothing.
1476 return;
1477 }
1478 ASSERT_NOT_REACHED();
1479 }
1480
offsetInCharacters() const1481 bool Node::offsetInCharacters() const
1482 {
1483 return false;
1484 }
1485
compareDocumentPosition(const Node * otherNode,ShadowTreesTreatment treatment) const1486 unsigned short Node::compareDocumentPosition(const Node* otherNode, ShadowTreesTreatment treatment) const
1487 {
1488 // It is not clear what should be done if |otherNode| is 0.
1489 if (!otherNode)
1490 return DOCUMENT_POSITION_DISCONNECTED;
1491
1492 if (otherNode == this)
1493 return DOCUMENT_POSITION_EQUIVALENT;
1494
1495 const Attr* attr1 = nodeType() == ATTRIBUTE_NODE ? toAttr(this) : 0;
1496 const Attr* attr2 = otherNode->nodeType() == ATTRIBUTE_NODE ? toAttr(otherNode) : 0;
1497
1498 const Node* start1 = attr1 ? attr1->ownerElement() : this;
1499 const Node* start2 = attr2 ? attr2->ownerElement() : otherNode;
1500
1501 // If either of start1 or start2 is null, then we are disconnected, since one of the nodes is
1502 // an orphaned attribute node.
1503 if (!start1 || !start2) {
1504 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING;
1505 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction;
1506 }
1507
1508 Vector<const Node*, 16> chain1;
1509 Vector<const Node*, 16> chain2;
1510 if (attr1)
1511 chain1.append(attr1);
1512 if (attr2)
1513 chain2.append(attr2);
1514
1515 if (attr1 && attr2 && start1 == start2 && start1) {
1516 // We are comparing two attributes on the same node. Crawl our attribute map and see which one we hit first.
1517 const Element* owner1 = attr1->ownerElement();
1518 AttributeCollection attributes = owner1->attributes();
1519 AttributeCollection::iterator end = attributes.end();
1520 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) {
1521 // If neither of the two determining nodes is a child node and nodeType is the same for both determining nodes, then an
1522 // implementation-dependent order between the determining nodes is returned. This order is stable as long as no nodes of
1523 // the same nodeType are inserted into or removed from the direct container. This would be the case, for example,
1524 // when comparing two attributes of the same element, and inserting or removing additional attributes might change
1525 // the order between existing attributes.
1526 if (attr1->qualifiedName() == it->name())
1527 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING;
1528 if (attr2->qualifiedName() == it->name())
1529 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_PRECEDING;
1530 }
1531
1532 ASSERT_NOT_REACHED();
1533 return DOCUMENT_POSITION_DISCONNECTED;
1534 }
1535
1536 // If one node is in the document and the other is not, we must be disconnected.
1537 // If the nodes have different owning documents, they must be disconnected. Note that we avoid
1538 // comparing Attr nodes here, since they return false from inDocument() all the time (which seems like a bug).
1539 if (start1->inDocument() != start2->inDocument() || (treatment == TreatShadowTreesAsDisconnected && start1->treeScope() != start2->treeScope())) {
1540 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING;
1541 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction;
1542 }
1543
1544 // We need to find a common ancestor container, and then compare the indices of the two immediate children.
1545 const Node* current;
1546 for (current = start1; current; current = current->parentOrShadowHostNode())
1547 chain1.append(current);
1548 for (current = start2; current; current = current->parentOrShadowHostNode())
1549 chain2.append(current);
1550
1551 unsigned index1 = chain1.size();
1552 unsigned index2 = chain2.size();
1553
1554 // If the two elements don't have a common root, they're not in the same tree.
1555 if (chain1[index1 - 1] != chain2[index2 - 1]) {
1556 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING;
1557 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction;
1558 }
1559
1560 unsigned connection = start1->treeScope() != start2->treeScope() ? DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 0;
1561
1562 // Walk the two chains backwards and look for the first difference.
1563 for (unsigned i = std::min(index1, index2); i; --i) {
1564 const Node* child1 = chain1[--index1];
1565 const Node* child2 = chain2[--index2];
1566 if (child1 != child2) {
1567 // If one of the children is an attribute, it wins.
1568 if (child1->nodeType() == ATTRIBUTE_NODE)
1569 return DOCUMENT_POSITION_FOLLOWING | connection;
1570 if (child2->nodeType() == ATTRIBUTE_NODE)
1571 return DOCUMENT_POSITION_PRECEDING | connection;
1572
1573 // If one of the children is a shadow root,
1574 if (child1->isShadowRoot() || child2->isShadowRoot()) {
1575 if (!child2->isShadowRoot())
1576 return Node::DOCUMENT_POSITION_FOLLOWING | connection;
1577 if (!child1->isShadowRoot())
1578 return Node::DOCUMENT_POSITION_PRECEDING | connection;
1579
1580 for (ShadowRoot* child = toShadowRoot(child2)->olderShadowRoot(); child; child = child->olderShadowRoot())
1581 if (child == child1)
1582 return Node::DOCUMENT_POSITION_FOLLOWING | connection;
1583
1584 return Node::DOCUMENT_POSITION_PRECEDING | connection;
1585 }
1586
1587 if (!child2->nextSibling())
1588 return DOCUMENT_POSITION_FOLLOWING | connection;
1589 if (!child1->nextSibling())
1590 return DOCUMENT_POSITION_PRECEDING | connection;
1591
1592 // Otherwise we need to see which node occurs first. Crawl backwards from child2 looking for child1.
1593 for (Node* child = child2->previousSibling(); child; child = child->previousSibling()) {
1594 if (child == child1)
1595 return DOCUMENT_POSITION_FOLLOWING | connection;
1596 }
1597 return DOCUMENT_POSITION_PRECEDING | connection;
1598 }
1599 }
1600
1601 // There was no difference between the two parent chains, i.e., one was a subset of the other. The shorter
1602 // chain is the ancestor.
1603 return index1 < index2 ?
1604 DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_CONTAINED_BY | connection :
1605 DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_CONTAINS | connection;
1606 }
1607
debugName() const1608 String Node::debugName() const
1609 {
1610 StringBuilder name;
1611 name.append(nodeName());
1612
1613 if (isElementNode()) {
1614 const Element& thisElement = toElement(*this);
1615 if (thisElement.hasID()) {
1616 name.appendLiteral(" id=\'");
1617 name.append(thisElement.getIdAttribute());
1618 name.append('\'');
1619 }
1620
1621 if (thisElement.hasClass()) {
1622 name.appendLiteral(" class=\'");
1623 for (size_t i = 0; i < thisElement.classNames().size(); ++i) {
1624 if (i > 0)
1625 name.append(' ');
1626 name.append(thisElement.classNames()[i]);
1627 }
1628 name.append('\'');
1629 }
1630 }
1631
1632 return name.toString();
1633 }
1634
1635 #ifndef NDEBUG
1636
appendAttributeDesc(const Node * node,StringBuilder & stringBuilder,const QualifiedName & name,const char * attrDesc)1637 static void appendAttributeDesc(const Node* node, StringBuilder& stringBuilder, const QualifiedName& name, const char* attrDesc)
1638 {
1639 if (!node->isElementNode())
1640 return;
1641
1642 String attr = toElement(node)->getAttribute(name);
1643 if (attr.isEmpty())
1644 return;
1645
1646 stringBuilder.append(attrDesc);
1647 stringBuilder.appendLiteral("=\"");
1648 stringBuilder.append(attr);
1649 stringBuilder.appendLiteral("\"");
1650 }
1651
showNode(const char * prefix) const1652 void Node::showNode(const char* prefix) const
1653 {
1654 if (!prefix)
1655 prefix = "";
1656 if (isTextNode()) {
1657 String value = nodeValue();
1658 value.replaceWithLiteral('\\', "\\\\");
1659 value.replaceWithLiteral('\n', "\\n");
1660 fprintf(stderr, "%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this, value.utf8().data());
1661 } else {
1662 StringBuilder attrs;
1663 appendAttributeDesc(this, attrs, idAttr, " ID");
1664 appendAttributeDesc(this, attrs, classAttr, " CLASS");
1665 appendAttributeDesc(this, attrs, styleAttr, " STYLE");
1666 fprintf(stderr, "%s%s\t%p%s\n", prefix, nodeName().utf8().data(), this, attrs.toString().utf8().data());
1667 }
1668 }
1669
showTreeForThis() const1670 void Node::showTreeForThis() const
1671 {
1672 showTreeAndMark(this, "*");
1673 }
1674
showNodePathForThis() const1675 void Node::showNodePathForThis() const
1676 {
1677 Vector<const Node*, 16> chain;
1678 const Node* node = this;
1679 while (node->parentOrShadowHostNode()) {
1680 chain.append(node);
1681 node = node->parentOrShadowHostNode();
1682 }
1683 for (unsigned index = chain.size(); index > 0; --index) {
1684 const Node* node = chain[index - 1];
1685 if (node->isShadowRoot()) {
1686 int count = 0;
1687 for (ShadowRoot* shadowRoot = toShadowRoot(node)->olderShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot())
1688 ++count;
1689 fprintf(stderr, "/#shadow-root[%d]", count);
1690 continue;
1691 }
1692
1693 switch (node->nodeType()) {
1694 case ELEMENT_NODE: {
1695 fprintf(stderr, "/%s", node->nodeName().utf8().data());
1696
1697 const Element* element = toElement(node);
1698 const AtomicString& idattr = element->getIdAttribute();
1699 bool hasIdAttr = !idattr.isNull() && !idattr.isEmpty();
1700 if (node->previousSibling() || node->nextSibling()) {
1701 int count = 0;
1702 for (Node* previous = node->previousSibling(); previous; previous = previous->previousSibling())
1703 if (previous->nodeName() == node->nodeName())
1704 ++count;
1705 if (hasIdAttr)
1706 fprintf(stderr, "[@id=\"%s\" and position()=%d]", idattr.utf8().data(), count);
1707 else
1708 fprintf(stderr, "[%d]", count);
1709 } else if (hasIdAttr) {
1710 fprintf(stderr, "[@id=\"%s\"]", idattr.utf8().data());
1711 }
1712 break;
1713 }
1714 case TEXT_NODE:
1715 fprintf(stderr, "/text()");
1716 break;
1717 case ATTRIBUTE_NODE:
1718 fprintf(stderr, "/@%s", node->nodeName().utf8().data());
1719 break;
1720 default:
1721 break;
1722 }
1723 }
1724 fprintf(stderr, "\n");
1725 }
1726
traverseTreeAndMark(const String & baseIndent,const Node * rootNode,const Node * markedNode1,const char * markedLabel1,const Node * markedNode2,const char * markedLabel2)1727 static void traverseTreeAndMark(const String& baseIndent, const Node* rootNode, const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2)
1728 {
1729 for (const Node* node = rootNode; node; node = NodeTraversal::next(*node)) {
1730 if (node == markedNode1)
1731 fprintf(stderr, "%s", markedLabel1);
1732 if (node == markedNode2)
1733 fprintf(stderr, "%s", markedLabel2);
1734
1735 StringBuilder indent;
1736 indent.append(baseIndent);
1737 for (const Node* tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentOrShadowHostNode())
1738 indent.append('\t');
1739 fprintf(stderr, "%s", indent.toString().utf8().data());
1740 node->showNode();
1741 indent.append('\t');
1742 if (node->isShadowRoot()) {
1743 if (ShadowRoot* youngerShadowRoot = toShadowRoot(node)->youngerShadowRoot())
1744 traverseTreeAndMark(indent.toString(), youngerShadowRoot, markedNode1, markedLabel1, markedNode2, markedLabel2);
1745 } else if (ShadowRoot* oldestShadowRoot = oldestShadowRootFor(node))
1746 traverseTreeAndMark(indent.toString(), oldestShadowRoot, markedNode1, markedLabel1, markedNode2, markedLabel2);
1747 }
1748 }
1749
showTreeAndMark(const Node * markedNode1,const char * markedLabel1,const Node * markedNode2,const char * markedLabel2) const1750 void Node::showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2) const
1751 {
1752 const Node* rootNode;
1753 const Node* node = this;
1754 while (node->parentOrShadowHostNode() && !isHTMLBodyElement(*node))
1755 node = node->parentOrShadowHostNode();
1756 rootNode = node;
1757
1758 String startingIndent;
1759 traverseTreeAndMark(startingIndent, rootNode, markedNode1, markedLabel1, markedNode2, markedLabel2);
1760 }
1761
formatForDebugger(char * buffer,unsigned length) const1762 void Node::formatForDebugger(char* buffer, unsigned length) const
1763 {
1764 String result;
1765 String s;
1766
1767 s = nodeName();
1768 if (s.isEmpty())
1769 result = "<none>";
1770 else
1771 result = s;
1772
1773 strncpy(buffer, result.utf8().data(), length - 1);
1774 }
1775
parentOrShadowHostOrFrameOwner(const Node * node)1776 static ContainerNode* parentOrShadowHostOrFrameOwner(const Node* node)
1777 {
1778 ContainerNode* parent = node->parentOrShadowHostNode();
1779 if (!parent && node->document().frame())
1780 parent = node->document().frame()->deprecatedLocalOwner();
1781 return parent;
1782 }
1783
showSubTreeAcrossFrame(const Node * node,const Node * markedNode,const String & indent)1784 static void showSubTreeAcrossFrame(const Node* node, const Node* markedNode, const String& indent)
1785 {
1786 if (node == markedNode)
1787 fputs("*", stderr);
1788 fputs(indent.utf8().data(), stderr);
1789 node->showNode();
1790 if (node->isShadowRoot()) {
1791 if (ShadowRoot* youngerShadowRoot = toShadowRoot(node)->youngerShadowRoot())
1792 showSubTreeAcrossFrame(youngerShadowRoot, markedNode, indent + "\t");
1793 } else {
1794 if (node->isFrameOwnerElement())
1795 showSubTreeAcrossFrame(toHTMLFrameOwnerElement(node)->contentDocument(), markedNode, indent + "\t");
1796 if (ShadowRoot* oldestShadowRoot = oldestShadowRootFor(node))
1797 showSubTreeAcrossFrame(oldestShadowRoot, markedNode, indent + "\t");
1798 }
1799 for (Node* child = node->firstChild(); child; child = child->nextSibling())
1800 showSubTreeAcrossFrame(child, markedNode, indent + "\t");
1801 }
1802
showTreeForThisAcrossFrame() const1803 void Node::showTreeForThisAcrossFrame() const
1804 {
1805 Node* rootNode = const_cast<Node*>(this);
1806 while (parentOrShadowHostOrFrameOwner(rootNode))
1807 rootNode = parentOrShadowHostOrFrameOwner(rootNode);
1808 showSubTreeAcrossFrame(rootNode, this, "");
1809 }
1810
1811 #endif
1812
1813 // --------
1814
enclosingLinkEventParentOrSelf()1815 Element* Node::enclosingLinkEventParentOrSelf()
1816 {
1817 for (Node* node = this; node; node = NodeRenderingTraversal::parent(node)) {
1818 // For imagemaps, the enclosing link node is the associated area element not the image itself.
1819 // So we don't let images be the enclosingLinkNode, even though isLink sometimes returns true
1820 // for them.
1821 if (node->isLink() && !isHTMLImageElement(*node)) {
1822 // Casting to Element is safe because only HTMLAnchorElement, HTMLImageElement and
1823 // SVGAElement can return true for isLink().
1824 return toElement(node);
1825 }
1826 }
1827
1828 return 0;
1829 }
1830
interfaceName() const1831 const AtomicString& Node::interfaceName() const
1832 {
1833 return EventTargetNames::Node;
1834 }
1835
executionContext() const1836 ExecutionContext* Node::executionContext() const
1837 {
1838 return document().contextDocument().get();
1839 }
1840
didMoveToNewDocument(Document & oldDocument)1841 void Node::didMoveToNewDocument(Document& oldDocument)
1842 {
1843 TreeScopeAdopter::ensureDidMoveToNewDocumentWasCalled(oldDocument);
1844
1845 if (const EventTargetData* eventTargetData = this->eventTargetData()) {
1846 const EventListenerMap& listenerMap = eventTargetData->eventListenerMap;
1847 if (!listenerMap.isEmpty()) {
1848 Vector<AtomicString> types = listenerMap.eventTypes();
1849 for (unsigned i = 0; i < types.size(); ++i)
1850 document().addListenerTypeIfNeeded(types[i]);
1851 }
1852 }
1853
1854 Settings* settings = document().settings();
1855 if (settings && settings->accessibilityEnabled()) {
1856 if (AXObjectCache* cache = oldDocument.existingAXObjectCache())
1857 cache->remove(this);
1858 }
1859
1860 oldDocument.markers().removeMarkers(this);
1861 oldDocument.updateRangesAfterNodeMovedToAnotherDocument(*this);
1862 if (oldDocument.frameHost() && !document().frameHost())
1863 oldDocument.frameHost()->eventHandlerRegistry().didMoveOutOfFrameHost(*this);
1864 else if (document().frameHost() && !oldDocument.frameHost())
1865 document().frameHost()->eventHandlerRegistry().didMoveIntoFrameHost(*this);
1866 else if (oldDocument.frameHost() != document().frameHost())
1867 EventHandlerRegistry::didMoveBetweenFrameHosts(*this, oldDocument.frameHost(), document().frameHost());
1868
1869 if (WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* registry = mutationObserverRegistry()) {
1870 for (size_t i = 0; i < registry->size(); ++i) {
1871 document().addMutationObserverTypes(registry->at(i)->mutationTypes());
1872 }
1873 }
1874
1875 if (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* transientRegistry = transientMutationObserverRegistry()) {
1876 for (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >::iterator iter = transientRegistry->begin(); iter != transientRegistry->end(); ++iter) {
1877 document().addMutationObserverTypes((*iter)->mutationTypes());
1878 }
1879 }
1880 }
1881
tryAddEventListener(Node * targetNode,const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)1882 static inline bool tryAddEventListener(Node* targetNode, const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1883 {
1884 if (!targetNode->EventTarget::addEventListener(eventType, listener, useCapture))
1885 return false;
1886
1887 Document& document = targetNode->document();
1888 document.addListenerTypeIfNeeded(eventType);
1889 if (document.frameHost())
1890 document.frameHost()->eventHandlerRegistry().didAddEventHandler(*targetNode, eventType);
1891
1892 return true;
1893 }
1894
addEventListener(const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)1895 bool Node::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1896 {
1897 return tryAddEventListener(this, eventType, listener, useCapture);
1898 }
1899
tryRemoveEventListener(Node * targetNode,const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)1900 static inline bool tryRemoveEventListener(Node* targetNode, const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1901 {
1902 if (!targetNode->EventTarget::removeEventListener(eventType, listener, useCapture))
1903 return false;
1904
1905 // FIXME: Notify Document that the listener has vanished. We need to keep track of a number of
1906 // listeners for each type, not just a bool - see https://bugs.webkit.org/show_bug.cgi?id=33861
1907 Document& document = targetNode->document();
1908 if (document.frameHost())
1909 document.frameHost()->eventHandlerRegistry().didRemoveEventHandler(*targetNode, eventType);
1910
1911 return true;
1912 }
1913
removeEventListener(const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)1914 bool Node::removeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1915 {
1916 return tryRemoveEventListener(this, eventType, listener, useCapture);
1917 }
1918
removeAllEventListeners()1919 void Node::removeAllEventListeners()
1920 {
1921 if (hasEventListeners() && document().frameHost())
1922 document().frameHost()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);
1923 EventTarget::removeAllEventListeners();
1924 }
1925
removeAllEventListenersRecursively()1926 void Node::removeAllEventListenersRecursively()
1927 {
1928 for (Node* node = this; node; node = NodeTraversal::next(*node)) {
1929 node->removeAllEventListeners();
1930 for (ShadowRoot* root = node->youngestShadowRoot(); root; root = root->olderShadowRoot())
1931 root->removeAllEventListenersRecursively();
1932 }
1933 }
1934
1935 typedef WillBeHeapHashMap<RawPtrWillBeWeakMember<Node>, OwnPtr<EventTargetData> > EventTargetDataMap;
1936
eventTargetDataMap()1937 static EventTargetDataMap& eventTargetDataMap()
1938 {
1939 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<EventTargetDataMap>, map, (adoptPtrWillBeNoop(new EventTargetDataMap())));
1940 return *map;
1941 }
1942
eventTargetData()1943 EventTargetData* Node::eventTargetData()
1944 {
1945 return hasEventTargetData() ? eventTargetDataMap().get(this) : 0;
1946 }
1947
ensureEventTargetData()1948 EventTargetData& Node::ensureEventTargetData()
1949 {
1950 if (hasEventTargetData())
1951 return *eventTargetDataMap().get(this);
1952 setHasEventTargetData(true);
1953 EventTargetData* data = new EventTargetData;
1954 eventTargetDataMap().set(this, adoptPtr(data));
1955 return *data;
1956 }
1957
1958 #if !ENABLE(OILPAN)
clearEventTargetData()1959 void Node::clearEventTargetData()
1960 {
1961 eventTargetDataMap().remove(this);
1962 }
1963 #endif
1964
mutationObserverRegistry()1965 WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* Node::mutationObserverRegistry()
1966 {
1967 if (!hasRareData())
1968 return 0;
1969 NodeMutationObserverData* data = rareData()->mutationObserverData();
1970 if (!data)
1971 return 0;
1972 return &data->registry;
1973 }
1974
transientMutationObserverRegistry()1975 WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* Node::transientMutationObserverRegistry()
1976 {
1977 if (!hasRareData())
1978 return 0;
1979 NodeMutationObserverData* data = rareData()->mutationObserverData();
1980 if (!data)
1981 return 0;
1982 return &data->transientRegistry;
1983 }
1984
1985 template<typename Registry>
collectMatchingObserversForMutation(WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>,MutationRecordDeliveryOptions> & observers,Registry * registry,Node & target,MutationObserver::MutationType type,const QualifiedName * attributeName)1986 static inline void collectMatchingObserversForMutation(WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>& observers, Registry* registry, Node& target, MutationObserver::MutationType type, const QualifiedName* attributeName)
1987 {
1988 if (!registry)
1989 return;
1990 for (typename Registry::iterator iter = registry->begin(); iter != registry->end(); ++iter) {
1991 const MutationObserverRegistration& registration = **iter;
1992 if (registration.shouldReceiveMutationFrom(target, type, attributeName)) {
1993 MutationRecordDeliveryOptions deliveryOptions = registration.deliveryOptions();
1994 WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>::AddResult result = observers.add(®istration.observer(), deliveryOptions);
1995 if (!result.isNewEntry)
1996 result.storedValue->value |= deliveryOptions;
1997 }
1998 }
1999 }
2000
getRegisteredMutationObserversOfType(WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>,MutationRecordDeliveryOptions> & observers,MutationObserver::MutationType type,const QualifiedName * attributeName)2001 void Node::getRegisteredMutationObserversOfType(WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>& observers, MutationObserver::MutationType type, const QualifiedName* attributeName)
2002 {
2003 ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName);
2004 collectMatchingObserversForMutation(observers, mutationObserverRegistry(), *this, type, attributeName);
2005 collectMatchingObserversForMutation(observers, transientMutationObserverRegistry(), *this, type, attributeName);
2006 for (Node* node = parentNode(); node; node = node->parentNode()) {
2007 collectMatchingObserversForMutation(observers, node->mutationObserverRegistry(), *this, type, attributeName);
2008 collectMatchingObserversForMutation(observers, node->transientMutationObserverRegistry(), *this, type, attributeName);
2009 }
2010 }
2011
registerMutationObserver(MutationObserver & observer,MutationObserverOptions options,const HashSet<AtomicString> & attributeFilter)2012 void Node::registerMutationObserver(MutationObserver& observer, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter)
2013 {
2014 MutationObserverRegistration* registration = 0;
2015 WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >& registry = ensureRareData().ensureMutationObserverData().registry;
2016 for (size_t i = 0; i < registry.size(); ++i) {
2017 if (®istry[i]->observer() == &observer) {
2018 registration = registry[i].get();
2019 registration->resetObservation(options, attributeFilter);
2020 }
2021 }
2022
2023 if (!registration) {
2024 registry.append(MutationObserverRegistration::create(observer, this, options, attributeFilter));
2025 registration = registry.last().get();
2026 }
2027
2028 document().addMutationObserverTypes(registration->mutationTypes());
2029 }
2030
unregisterMutationObserver(MutationObserverRegistration * registration)2031 void Node::unregisterMutationObserver(MutationObserverRegistration* registration)
2032 {
2033 WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* registry = mutationObserverRegistry();
2034 ASSERT(registry);
2035 if (!registry)
2036 return;
2037
2038 size_t index = registry->find(registration);
2039 ASSERT(index != kNotFound);
2040 if (index == kNotFound)
2041 return;
2042
2043 // Deleting the registration may cause this node to be derefed, so we must make sure the Vector operation completes
2044 // before that, in case |this| is destroyed (see MutationObserverRegistration::m_registrationNodeKeepAlive).
2045 // FIXME: Simplify the registration/transient registration logic to make this understandable by humans.
2046 RefPtrWillBeRawPtr<Node> protect(this);
2047 #if ENABLE(OILPAN)
2048 // The explicit dispose() is needed to have the registration
2049 // object unregister itself promptly.
2050 registration->dispose();
2051 #endif
2052 registry->remove(index);
2053 }
2054
registerTransientMutationObserver(MutationObserverRegistration * registration)2055 void Node::registerTransientMutationObserver(MutationObserverRegistration* registration)
2056 {
2057 ensureRareData().ensureMutationObserverData().transientRegistry.add(registration);
2058 }
2059
unregisterTransientMutationObserver(MutationObserverRegistration * registration)2060 void Node::unregisterTransientMutationObserver(MutationObserverRegistration* registration)
2061 {
2062 WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* transientRegistry = transientMutationObserverRegistry();
2063 ASSERT(transientRegistry);
2064 if (!transientRegistry)
2065 return;
2066
2067 ASSERT(transientRegistry->contains(registration));
2068 transientRegistry->remove(registration);
2069 }
2070
notifyMutationObserversNodeWillDetach()2071 void Node::notifyMutationObserversNodeWillDetach()
2072 {
2073 if (!document().hasMutationObservers())
2074 return;
2075
2076 for (Node* node = parentNode(); node; node = node->parentNode()) {
2077 if (WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* registry = node->mutationObserverRegistry()) {
2078 const size_t size = registry->size();
2079 for (size_t i = 0; i < size; ++i)
2080 registry->at(i)->observedSubtreeNodeWillDetach(*this);
2081 }
2082
2083 if (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* transientRegistry = node->transientMutationObserverRegistry()) {
2084 for (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >::iterator iter = transientRegistry->begin(); iter != transientRegistry->end(); ++iter)
2085 (*iter)->observedSubtreeNodeWillDetach(*this);
2086 }
2087 }
2088 }
2089
handleLocalEvents(Event * event)2090 void Node::handleLocalEvents(Event* event)
2091 {
2092 if (!hasEventTargetData())
2093 return;
2094
2095 if (isDisabledFormControl(this) && event->isMouseEvent())
2096 return;
2097
2098 fireEventListeners(event);
2099 }
2100
dispatchScopedEvent(PassRefPtrWillBeRawPtr<Event> event)2101 void Node::dispatchScopedEvent(PassRefPtrWillBeRawPtr<Event> event)
2102 {
2103 dispatchScopedEventDispatchMediator(EventDispatchMediator::create(event));
2104 }
2105
dispatchScopedEventDispatchMediator(PassRefPtrWillBeRawPtr<EventDispatchMediator> eventDispatchMediator)2106 void Node::dispatchScopedEventDispatchMediator(PassRefPtrWillBeRawPtr<EventDispatchMediator> eventDispatchMediator)
2107 {
2108 EventDispatcher::dispatchScopedEvent(this, eventDispatchMediator);
2109 }
2110
dispatchEvent(PassRefPtrWillBeRawPtr<Event> event)2111 bool Node::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event)
2112 {
2113 if (event->isMouseEvent())
2114 return EventDispatcher::dispatchEvent(this, MouseEventDispatchMediator::create(static_pointer_cast<MouseEvent>(event), MouseEventDispatchMediator::SyntheticMouseEvent));
2115 if (event->isTouchEvent())
2116 return dispatchTouchEvent(static_pointer_cast<TouchEvent>(event));
2117 return EventDispatcher::dispatchEvent(this, EventDispatchMediator::create(event));
2118 }
2119
dispatchSubtreeModifiedEvent()2120 void Node::dispatchSubtreeModifiedEvent()
2121 {
2122 if (isInShadowTree())
2123 return;
2124
2125 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
2126
2127 if (!document().hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER))
2128 return;
2129
2130 dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMSubtreeModified, true));
2131 }
2132
dispatchDOMActivateEvent(int detail,PassRefPtrWillBeRawPtr<Event> underlyingEvent)2133 bool Node::dispatchDOMActivateEvent(int detail, PassRefPtrWillBeRawPtr<Event> underlyingEvent)
2134 {
2135 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
2136 RefPtrWillBeRawPtr<UIEvent> event = UIEvent::create(EventTypeNames::DOMActivate, true, true, document().domWindow(), detail);
2137 event->setUnderlyingEvent(underlyingEvent);
2138 dispatchScopedEvent(event);
2139 return event->defaultHandled();
2140 }
2141
dispatchKeyEvent(const PlatformKeyboardEvent & event)2142 bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& event)
2143 {
2144 return EventDispatcher::dispatchEvent(this, KeyboardEventDispatchMediator::create(KeyboardEvent::create(event, document().domWindow())));
2145 }
2146
dispatchMouseEvent(const PlatformMouseEvent & event,const AtomicString & eventType,int detail,Node * relatedTarget)2147 bool Node::dispatchMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType,
2148 int detail, Node* relatedTarget)
2149 {
2150 return EventDispatcher::dispatchEvent(this, MouseEventDispatchMediator::create(MouseEvent::create(eventType, document().domWindow(), event, detail, relatedTarget)));
2151 }
2152
dispatchGestureEvent(const PlatformGestureEvent & event)2153 bool Node::dispatchGestureEvent(const PlatformGestureEvent& event)
2154 {
2155 RefPtrWillBeRawPtr<GestureEvent> gestureEvent = GestureEvent::create(document().domWindow(), event);
2156 if (!gestureEvent.get())
2157 return false;
2158 return EventDispatcher::dispatchEvent(this, GestureEventDispatchMediator::create(gestureEvent));
2159 }
2160
dispatchTouchEvent(PassRefPtrWillBeRawPtr<TouchEvent> event)2161 bool Node::dispatchTouchEvent(PassRefPtrWillBeRawPtr<TouchEvent> event)
2162 {
2163 return EventDispatcher::dispatchEvent(this, TouchEventDispatchMediator::create(event));
2164 }
2165
dispatchSimulatedClick(Event * underlyingEvent,SimulatedClickMouseEventOptions eventOptions)2166 void Node::dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions eventOptions)
2167 {
2168 EventDispatcher::dispatchSimulatedClick(this, underlyingEvent, eventOptions);
2169 }
2170
dispatchWheelEvent(const PlatformWheelEvent & event)2171 bool Node::dispatchWheelEvent(const PlatformWheelEvent& event)
2172 {
2173 return EventDispatcher::dispatchEvent(this, WheelEventDispatchMediator::create(event, document().domWindow()));
2174 }
2175
dispatchInputEvent()2176 void Node::dispatchInputEvent()
2177 {
2178 dispatchScopedEvent(Event::createBubble(EventTypeNames::input));
2179 }
2180
defaultEventHandler(Event * event)2181 void Node::defaultEventHandler(Event* event)
2182 {
2183 if (event->target() != this)
2184 return;
2185 const AtomicString& eventType = event->type();
2186 if (eventType == EventTypeNames::keydown || eventType == EventTypeNames::keypress) {
2187 if (event->isKeyboardEvent()) {
2188 if (LocalFrame* frame = document().frame())
2189 frame->eventHandler().defaultKeyboardEventHandler(toKeyboardEvent(event));
2190 }
2191 } else if (eventType == EventTypeNames::click) {
2192 int detail = event->isUIEvent() ? static_cast<UIEvent*>(event)->detail() : 0;
2193 if (dispatchDOMActivateEvent(detail, event))
2194 event->setDefaultHandled();
2195 } else if (eventType == EventTypeNames::contextmenu) {
2196 if (Page* page = document().page())
2197 page->contextMenuController().handleContextMenuEvent(event);
2198 } else if (eventType == EventTypeNames::textInput) {
2199 if (event->hasInterface(EventNames::TextEvent)) {
2200 if (LocalFrame* frame = document().frame())
2201 frame->eventHandler().defaultTextInputEventHandler(toTextEvent(event));
2202 }
2203 #if OS(WIN)
2204 } else if (eventType == EventTypeNames::mousedown && event->isMouseEvent()) {
2205 MouseEvent* mouseEvent = toMouseEvent(event);
2206 if (mouseEvent->button() == MiddleButton) {
2207 if (enclosingLinkEventParentOrSelf())
2208 return;
2209
2210 // Avoid that canBeScrolledAndHasScrollableArea changes render tree
2211 // structure.
2212 // FIXME: We should avoid synchronous layout if possible. We can
2213 // remove this synchronous layout if we avoid synchronous layout in
2214 // RenderTextControlSingleLine::scrollHeight
2215 document().updateLayoutIgnorePendingStylesheets();
2216 RenderObject* renderer = this->renderer();
2217 while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()))
2218 renderer = renderer->parent();
2219
2220 if (renderer) {
2221 if (LocalFrame* frame = document().frame())
2222 frame->eventHandler().startPanScrolling(renderer);
2223 }
2224 }
2225 #endif
2226 } else if ((eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel) && event->hasInterface(EventNames::WheelEvent)) {
2227 WheelEvent* wheelEvent = toWheelEvent(event);
2228
2229 // If we don't have a renderer, send the wheel event to the first node we find with a renderer.
2230 // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll.
2231 Node* startNode = this;
2232 while (startNode && !startNode->renderer())
2233 startNode = startNode->parentOrShadowHostNode();
2234
2235 if (startNode && startNode->renderer()) {
2236 if (LocalFrame* frame = document().frame())
2237 frame->eventHandler().defaultWheelEventHandler(startNode, wheelEvent);
2238 }
2239 } else if (event->type() == EventTypeNames::webkitEditableContentChanged) {
2240 dispatchInputEvent();
2241 }
2242 }
2243
willCallDefaultEventHandler(const Event &)2244 void Node::willCallDefaultEventHandler(const Event&)
2245 {
2246 }
2247
willRespondToMouseMoveEvents()2248 bool Node::willRespondToMouseMoveEvents()
2249 {
2250 if (isDisabledFormControl(this))
2251 return false;
2252 return hasEventListeners(EventTypeNames::mousemove) || hasEventListeners(EventTypeNames::mouseover) || hasEventListeners(EventTypeNames::mouseout);
2253 }
2254
willRespondToMouseClickEvents()2255 bool Node::willRespondToMouseClickEvents()
2256 {
2257 if (isDisabledFormControl(this))
2258 return false;
2259 return isContentEditable(UserSelectAllIsAlwaysNonEditable) || hasEventListeners(EventTypeNames::mouseup) || hasEventListeners(EventTypeNames::mousedown) || hasEventListeners(EventTypeNames::click) || hasEventListeners(EventTypeNames::DOMActivate);
2260 }
2261
willRespondToTouchEvents()2262 bool Node::willRespondToTouchEvents()
2263 {
2264 if (isDisabledFormControl(this))
2265 return false;
2266 return hasEventListeners(EventTypeNames::touchstart) || hasEventListeners(EventTypeNames::touchmove) || hasEventListeners(EventTypeNames::touchcancel) || hasEventListeners(EventTypeNames::touchend);
2267 }
2268
2269 #if !ENABLE(OILPAN)
2270 // This is here for inlining
removedLastRefToScope()2271 inline void TreeScope::removedLastRefToScope()
2272 {
2273 ASSERT_WITH_SECURITY_IMPLICATION(!deletionHasBegun());
2274 if (m_guardRefCount) {
2275 // If removing a child removes the last self-only ref, we don't
2276 // want the scope to be destructed until after
2277 // removeDetachedChildren returns, so we guard ourselves with an
2278 // extra self-only ref.
2279 guardRef();
2280 dispose();
2281 #if ENABLE(ASSERT)
2282 // We need to do this right now since guardDeref() can delete this.
2283 rootNode().m_inRemovedLastRefFunction = false;
2284 #endif
2285 guardDeref();
2286 } else {
2287 #if ENABLE(ASSERT)
2288 rootNode().m_inRemovedLastRefFunction = false;
2289 #endif
2290 #if ENABLE(SECURITY_ASSERT)
2291 beginDeletion();
2292 #endif
2293 delete this;
2294 }
2295 }
2296
2297 // It's important not to inline removedLastRef, because we don't want to inline the code to
2298 // delete a Node at each deref call site.
removedLastRef()2299 void Node::removedLastRef()
2300 {
2301 // An explicit check for Document here is better than a virtual function since it is
2302 // faster for non-Document nodes, and because the call to removedLastRef that is inlined
2303 // at all deref call sites is smaller if it's a non-virtual function.
2304 if (isTreeScope()) {
2305 treeScope().removedLastRefToScope();
2306 return;
2307 }
2308
2309 #if ENABLE(SECURITY_ASSERT)
2310 m_deletionHasBegun = true;
2311 #endif
2312 delete this;
2313 }
2314 #endif
2315
connectedSubframeCount() const2316 unsigned Node::connectedSubframeCount() const
2317 {
2318 return hasRareData() ? rareData()->connectedSubframeCount() : 0;
2319 }
2320
incrementConnectedSubframeCount(unsigned amount)2321 void Node::incrementConnectedSubframeCount(unsigned amount)
2322 {
2323 ASSERT(isContainerNode());
2324 ensureRareData().incrementConnectedSubframeCount(amount);
2325 }
2326
decrementConnectedSubframeCount(unsigned amount)2327 void Node::decrementConnectedSubframeCount(unsigned amount)
2328 {
2329 rareData()->decrementConnectedSubframeCount(amount);
2330 }
2331
updateAncestorConnectedSubframeCountForRemoval() const2332 void Node::updateAncestorConnectedSubframeCountForRemoval() const
2333 {
2334 unsigned count = connectedSubframeCount();
2335
2336 if (!count)
2337 return;
2338
2339 for (Node* node = parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode())
2340 node->decrementConnectedSubframeCount(count);
2341 }
2342
updateAncestorConnectedSubframeCountForInsertion() const2343 void Node::updateAncestorConnectedSubframeCountForInsertion() const
2344 {
2345 unsigned count = connectedSubframeCount();
2346
2347 if (!count)
2348 return;
2349
2350 for (Node* node = parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode())
2351 node->incrementConnectedSubframeCount(count);
2352 }
2353
getDestinationInsertionPoints()2354 PassRefPtrWillBeRawPtr<StaticNodeList> Node::getDestinationInsertionPoints()
2355 {
2356 document().updateDistributionForNodeIfNeeded(this);
2357 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
2358 collectDestinationInsertionPoints(*this, insertionPoints);
2359 WillBeHeapVector<RefPtrWillBeMember<Node> > filteredInsertionPoints;
2360 for (size_t i = 0; i < insertionPoints.size(); ++i) {
2361 InsertionPoint* insertionPoint = insertionPoints[i];
2362 ASSERT(insertionPoint->containingShadowRoot());
2363 if (insertionPoint->containingShadowRoot()->type() != ShadowRoot::UserAgentShadowRoot)
2364 filteredInsertionPoints.append(insertionPoint);
2365 }
2366 return StaticNodeList::adopt(filteredInsertionPoints);
2367 }
2368
setFocus(bool flag)2369 void Node::setFocus(bool flag)
2370 {
2371 document().userActionElements().setFocused(this, flag);
2372 }
2373
setActive(bool flag)2374 void Node::setActive(bool flag)
2375 {
2376 document().userActionElements().setActive(this, flag);
2377 }
2378
setHovered(bool flag)2379 void Node::setHovered(bool flag)
2380 {
2381 document().userActionElements().setHovered(this, flag);
2382 }
2383
isUserActionElementActive() const2384 bool Node::isUserActionElementActive() const
2385 {
2386 ASSERT(isUserActionElement());
2387 return document().userActionElements().isActive(this);
2388 }
2389
isUserActionElementInActiveChain() const2390 bool Node::isUserActionElementInActiveChain() const
2391 {
2392 ASSERT(isUserActionElement());
2393 return document().userActionElements().isInActiveChain(this);
2394 }
2395
isUserActionElementHovered() const2396 bool Node::isUserActionElementHovered() const
2397 {
2398 ASSERT(isUserActionElement());
2399 return document().userActionElements().isHovered(this);
2400 }
2401
isUserActionElementFocused() const2402 bool Node::isUserActionElementFocused() const
2403 {
2404 ASSERT(isUserActionElement());
2405 return document().userActionElements().isFocused(this);
2406 }
2407
setCustomElementState(CustomElementState newState)2408 void Node::setCustomElementState(CustomElementState newState)
2409 {
2410 CustomElementState oldState = customElementState();
2411
2412 switch (newState) {
2413 case NotCustomElement:
2414 ASSERT_NOT_REACHED(); // Everything starts in this state
2415 return;
2416
2417 case WaitingForUpgrade:
2418 ASSERT(NotCustomElement == oldState);
2419 break;
2420
2421 case Upgraded:
2422 ASSERT(WaitingForUpgrade == oldState);
2423 break;
2424 }
2425
2426 ASSERT(isHTMLElement() || isSVGElement());
2427 setFlag(CustomElementFlag);
2428 setFlag(newState == Upgraded, CustomElementUpgradedFlag);
2429
2430 if (oldState == NotCustomElement || newState == Upgraded)
2431 setNeedsStyleRecalc(SubtreeStyleChange); // :unresolved has changed
2432 }
2433
trace(Visitor * visitor)2434 void Node::trace(Visitor* visitor)
2435 {
2436 #if ENABLE(OILPAN)
2437 visitor->trace(m_parentOrShadowHostNode);
2438 visitor->trace(m_previous);
2439 visitor->trace(m_next);
2440 // rareData() and m_data.m_renderer share their storage. We have to trace
2441 // only one of them.
2442 if (hasRareData())
2443 visitor->trace(rareData());
2444 else
2445 visitor->trace(m_data.m_renderer);
2446 visitor->trace(m_treeScope);
2447 #endif
2448 EventTarget::trace(visitor);
2449 }
2450
lengthOfContents() const2451 unsigned Node::lengthOfContents() const
2452 {
2453 // This switch statement must be consistent with that of Range::processContentsBetweenOffsets.
2454 switch (nodeType()) {
2455 case Node::TEXT_NODE:
2456 case Node::CDATA_SECTION_NODE:
2457 case Node::COMMENT_NODE:
2458 return toCharacterData(this)->length();
2459 case Node::PROCESSING_INSTRUCTION_NODE:
2460 return toProcessingInstruction(this)->data().length();
2461 case Node::ELEMENT_NODE:
2462 case Node::ATTRIBUTE_NODE:
2463 case Node::DOCUMENT_NODE:
2464 case Node::DOCUMENT_FRAGMENT_NODE:
2465 return toContainerNode(this)->countChildren();
2466 case Node::DOCUMENT_TYPE_NODE:
2467 return 0;
2468 }
2469 ASSERT_NOT_REACHED();
2470 return 0;
2471 }
2472
wrap(v8::Handle<v8::Object> creationContext,v8::Isolate * isolate)2473 v8::Handle<v8::Object> Node::wrap(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
2474 {
2475 // It's possible that no one except for the new wrapper owns this object at
2476 // this moment, so we have to prevent GC to collect this object until the
2477 // object gets associated with the wrapper.
2478 RefPtrWillBeRawPtr<Node> protect(this);
2479
2480 ASSERT(!DOMDataStore::containsWrapperNonTemplate(this, isolate));
2481
2482 const WrapperTypeInfo* wrapperType = wrapperTypeInfo();
2483
2484 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, wrapperType, toScriptWrappableBase(), isolate);
2485 if (UNLIKELY(wrapper.IsEmpty()))
2486 return wrapper;
2487
2488 wrapperType->installConditionallyEnabledProperties(wrapper, isolate);
2489 return associateWithWrapper(wrapperType, wrapper, isolate);
2490 }
2491
associateWithWrapper(const WrapperTypeInfo * wrapperType,v8::Handle<v8::Object> wrapper,v8::Isolate * isolate)2492 v8::Handle<v8::Object> Node::associateWithWrapper(const WrapperTypeInfo* wrapperType, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate)
2493 {
2494 return V8DOMWrapper::associateObjectWithWrapperNonTemplate(this, wrapperType, wrapper, isolate);
2495 }
2496
2497 } // namespace blink
2498
2499 #ifndef NDEBUG
2500
showNode(const blink::Node * node)2501 void showNode(const blink::Node* node)
2502 {
2503 if (node)
2504 node->showNode("");
2505 }
2506
showTree(const blink::Node * node)2507 void showTree(const blink::Node* node)
2508 {
2509 if (node)
2510 node->showTreeForThis();
2511 }
2512
showNodePath(const blink::Node * node)2513 void showNodePath(const blink::Node* node)
2514 {
2515 if (node)
2516 node->showNodePathForThis();
2517 }
2518
2519 #endif
2520