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 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 #ifdef ANDROID_DOM_LOGGING
29 #define LOG_TAG "webcore"
30 #include "AndroidLog.h"
31 #endif
32
33 #include "AXObjectCache.h"
34 #include "Attr.h"
35 #include "Attribute.h"
36 #include "CSSParser.h"
37 #include "CSSRule.h"
38 #include "CSSRuleList.h"
39 #include "CSSSelector.h"
40 #include "CSSSelectorList.h"
41 #include "CSSStyleRule.h"
42 #include "CSSStyleSelector.h"
43 #include "CSSStyleSheet.h"
44 #include "ChildNodeList.h"
45 #include "ClassNodeList.h"
46 #include "ContextMenuController.h"
47 #include "DOMImplementation.h"
48 #include "Document.h"
49 #include "DocumentType.h"
50 #include "DynamicNodeList.h"
51 #include "Element.h"
52 #include "Event.h"
53 #include "EventContext.h"
54 #include "EventDispatcher.h"
55 #include "EventException.h"
56 #include "EventHandler.h"
57 #include "EventListener.h"
58 #include "EventNames.h"
59 #include "ExceptionCode.h"
60 #include "Frame.h"
61 #include "FrameView.h"
62 #include "HTMLNames.h"
63 #include "InspectorInstrumentation.h"
64 #include "KeyboardEvent.h"
65 #include "LabelsNodeList.h"
66 #include "Logging.h"
67 #include "MouseEvent.h"
68 #include "MutationEvent.h"
69 #include "NameNodeList.h"
70 #include "NamedNodeMap.h"
71 #include "NodeRareData.h"
72 #include "Page.h"
73 #include "PlatformMouseEvent.h"
74 #include "PlatformWheelEvent.h"
75 #include "ProcessingInstruction.h"
76 #include "ProgressEvent.h"
77 #include "RegisteredEventListener.h"
78 #include "RenderBlock.h"
79 #include "RenderBox.h"
80 #include "RenderFullScreen.h"
81 #include "RenderView.h"
82 #include "ScopedEventQueue.h"
83 #include "ScriptController.h"
84 #include "SelectorNodeList.h"
85 #include "StaticNodeList.h"
86 #include "TagNodeList.h"
87 #include "Text.h"
88 #include "TextEvent.h"
89 #include "UIEvent.h"
90 #include "UIEventWithKeyState.h"
91 #include "WebKitAnimationEvent.h"
92 #include "WebKitTransitionEvent.h"
93 #include "WheelEvent.h"
94 #include "WindowEventContext.h"
95 #include "XMLNames.h"
96 #include "htmlediting.h"
97 #include <wtf/HashSet.h>
98 #include <wtf/PassOwnPtr.h>
99 #include <wtf/RefCountedLeakCounter.h>
100 #include <wtf/UnusedParam.h>
101 #include <wtf/text/CString.h>
102 #include <wtf/text/StringBuilder.h>
103
104 #if ENABLE(DOM_STORAGE)
105 #include "StorageEvent.h"
106 #endif
107
108 #if ENABLE(SVG)
109 #include "SVGElementInstance.h"
110 #include "SVGUseElement.h"
111 #endif
112
113 #if ENABLE(WML)
114 #include "WMLNames.h"
115 #endif
116
117 #if ENABLE(XHTMLMP)
118 #include "HTMLNoScriptElement.h"
119 #endif
120
121 #if USE(JSC)
122 #include <runtime/JSGlobalData.h>
123 #endif
124
125 #define DUMP_NODE_STATISTICS 0
126
127 using namespace std;
128
129 namespace WebCore {
130
131 using namespace HTMLNames;
132
isSupported(const String & feature,const String & version)133 bool Node::isSupported(const String& feature, const String& version)
134 {
135 return DOMImplementation::hasFeature(feature, version);
136 }
137
138 #if DUMP_NODE_STATISTICS
139 static HashSet<Node*> liveNodeSet;
140 #endif
141
dumpStatistics()142 void Node::dumpStatistics()
143 {
144 #if DUMP_NODE_STATISTICS
145 size_t nodesWithRareData = 0;
146
147 size_t elementNodes = 0;
148 size_t attrNodes = 0;
149 size_t textNodes = 0;
150 size_t cdataNodes = 0;
151 size_t commentNodes = 0;
152 size_t entityReferenceNodes = 0;
153 size_t entityNodes = 0;
154 size_t piNodes = 0;
155 size_t documentNodes = 0;
156 size_t docTypeNodes = 0;
157 size_t fragmentNodes = 0;
158 size_t notationNodes = 0;
159 size_t xpathNSNodes = 0;
160
161 HashMap<String, size_t> perTagCount;
162
163 size_t attributes = 0;
164 size_t mappedAttributes = 0;
165 size_t mappedAttributesWithStyleDecl = 0;
166 size_t attributesWithAttr = 0;
167 size_t attrMaps = 0;
168
169 for (HashSet<Node*>::iterator it = liveNodeSet.begin(); it != liveNodeSet.end(); ++it) {
170 Node* node = *it;
171
172 if (node->hasRareData())
173 ++nodesWithRareData;
174
175 switch (node->nodeType()) {
176 case ELEMENT_NODE: {
177 ++elementNodes;
178
179 // Tag stats
180 Element* element = static_cast<Element*>(node);
181 pair<HashMap<String, size_t>::iterator, bool> result = perTagCount.add(element->tagName(), 1);
182 if (!result.second)
183 result.first->second++;
184
185 // AttributeMap stats
186 if (NamedNodeMap* attrMap = element->attributes(true)) {
187 attributes += attrMap->length();
188 ++attrMaps;
189 for (unsigned i = 0; i < attrMap->length(); ++i) {
190 Attribute* attr = attrMap->attributeItem(i);
191 if (attr->attr())
192 ++attributesWithAttr;
193 if (attr->isMappedAttribute()) {
194 ++mappedAttributes;
195 if (attr->style())
196 ++mappedAttributesWithStyleDecl;
197 }
198 }
199 }
200 break;
201 }
202 case ATTRIBUTE_NODE: {
203 ++attrNodes;
204 break;
205 }
206 case TEXT_NODE: {
207 ++textNodes;
208 break;
209 }
210 case CDATA_SECTION_NODE: {
211 ++cdataNodes;
212 break;
213 }
214 case COMMENT_NODE: {
215 ++commentNodes;
216 break;
217 }
218 case ENTITY_REFERENCE_NODE: {
219 ++entityReferenceNodes;
220 break;
221 }
222 case ENTITY_NODE: {
223 ++entityNodes;
224 break;
225 }
226 case PROCESSING_INSTRUCTION_NODE: {
227 ++piNodes;
228 break;
229 }
230 case DOCUMENT_NODE: {
231 ++documentNodes;
232 break;
233 }
234 case DOCUMENT_TYPE_NODE: {
235 ++docTypeNodes;
236 break;
237 }
238 case DOCUMENT_FRAGMENT_NODE: {
239 ++fragmentNodes;
240 break;
241 }
242 case NOTATION_NODE: {
243 ++notationNodes;
244 break;
245 }
246 case XPATH_NAMESPACE_NODE: {
247 ++xpathNSNodes;
248 break;
249 }
250 }
251 }
252
253 printf("Number of Nodes: %d\n\n", liveNodeSet.size());
254 printf("Number of Nodes with RareData: %zu\n\n", nodesWithRareData);
255
256 printf("NodeType distrubution:\n");
257 printf(" Number of Element nodes: %zu\n", elementNodes);
258 printf(" Number of Attribute nodes: %zu\n", attrNodes);
259 printf(" Number of Text nodes: %zu\n", textNodes);
260 printf(" Number of CDATASection nodes: %zu\n", cdataNodes);
261 printf(" Number of Comment nodes: %zu\n", commentNodes);
262 printf(" Number of EntityReference nodes: %zu\n", entityReferenceNodes);
263 printf(" Number of Entity nodes: %zu\n", entityNodes);
264 printf(" Number of ProcessingInstruction nodes: %zu\n", piNodes);
265 printf(" Number of Document nodes: %zu\n", documentNodes);
266 printf(" Number of DocumentType nodes: %zu\n", docTypeNodes);
267 printf(" Number of DocumentFragment nodes: %zu\n", fragmentNodes);
268 printf(" Number of Notation nodes: %zu\n", notationNodes);
269 printf(" Number of XPathNS nodes: %zu\n", xpathNSNodes);
270
271 printf("Element tag name distibution:\n");
272 for (HashMap<String, size_t>::iterator it = perTagCount.begin(); it != perTagCount.end(); ++it)
273 printf(" Number of <%s> tags: %zu\n", it->first.utf8().data(), it->second);
274
275 printf("Attribute Maps:\n");
276 printf(" Number of Attributes (non-Node and Node): %zu [%zu]\n", attributes, sizeof(Attribute));
277 printf(" Number of Attributes that are mapped: %zu\n", mappedAttributes);
278 printf(" Number of Attributes with a StyleDeclaration: %zu\n", mappedAttributesWithStyleDecl);
279 printf(" Number of Attributes with an Attr: %zu\n", attributesWithAttr);
280 printf(" Number of NamedNodeMaps: %zu [%zu]\n", attrMaps, sizeof(NamedNodeMap));
281 #endif
282 }
283
284 #ifndef NDEBUG
285 static WTF::RefCountedLeakCounter nodeCounter("WebCoreNode");
286
287 static bool shouldIgnoreLeaks = false;
288 static HashSet<Node*> ignoreSet;
289 #endif
290
startIgnoringLeaks()291 void Node::startIgnoringLeaks()
292 {
293 #ifndef NDEBUG
294 shouldIgnoreLeaks = true;
295 #endif
296 }
297
stopIgnoringLeaks()298 void Node::stopIgnoringLeaks()
299 {
300 #ifndef NDEBUG
301 shouldIgnoreLeaks = false;
302 #endif
303 }
304
diff(const RenderStyle * s1,const RenderStyle * s2)305 Node::StyleChange Node::diff(const RenderStyle* s1, const RenderStyle* s2)
306 {
307 // FIXME: The behavior of this function is just totally wrong. It doesn't handle
308 // explicit inheritance of non-inherited properties and so you end up not re-resolving
309 // style in cases where you need to.
310 StyleChange ch = NoInherit;
311 EDisplay display1 = s1 ? s1->display() : NONE;
312 bool fl1 = s1 && s1->hasPseudoStyle(FIRST_LETTER);
313 EDisplay display2 = s2 ? s2->display() : NONE;
314 bool fl2 = s2 && s2->hasPseudoStyle(FIRST_LETTER);
315
316 // We just detach if a renderer acquires or loses a column-span, since spanning elements
317 // typically won't contain much content.
318 bool colSpan1 = s1 && s1->columnSpan();
319 bool colSpan2 = s2 && s2->columnSpan();
320
321 if (display1 != display2 || fl1 != fl2 || colSpan1 != colSpan2 || (s1 && s2 && !s1->contentDataEquivalent(s2)))
322 ch = Detach;
323 else if (!s1 || !s2)
324 ch = Inherit;
325 else if (*s1 == *s2)
326 ch = NoChange;
327 else if (s1->inheritedNotEqual(s2))
328 ch = Inherit;
329
330 // For nth-child and other positional rules, treat styles as different if they have
331 // changed positionally in the DOM. This way subsequent sibling resolutions won't be confused
332 // by the wrong child index and evaluate to incorrect results.
333 if (ch == NoChange && s1->childIndex() != s2->childIndex())
334 ch = NoInherit;
335
336 // If the pseudoStyles have changed, we want any StyleChange that is not NoChange
337 // because setStyle will do the right thing with anything else.
338 if (ch == NoChange && s1->hasAnyPublicPseudoStyles()) {
339 for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; ch == NoChange && pseudoId < FIRST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
340 if (s1->hasPseudoStyle(pseudoId)) {
341 RenderStyle* ps2 = s2->getCachedPseudoStyle(pseudoId);
342 if (!ps2)
343 ch = NoInherit;
344 else {
345 RenderStyle* ps1 = s1->getCachedPseudoStyle(pseudoId);
346 ch = ps1 && *ps1 == *ps2 ? NoChange : NoInherit;
347 }
348 }
349 }
350 }
351
352 // When text-combine property has been changed, we need to prepare a separate renderer object.
353 // When text-combine is on, we use RenderCombineText, otherwise RenderText.
354 // https://bugs.webkit.org/show_bug.cgi?id=55069
355 if ((s1 && s2) && (s1->hasTextCombine() != s2->hasTextCombine()))
356 ch = Detach;
357
358 return ch;
359 }
360
trackForDebugging()361 void Node::trackForDebugging()
362 {
363 #ifndef NDEBUG
364 if (shouldIgnoreLeaks)
365 ignoreSet.add(this);
366 else
367 nodeCounter.increment();
368 #endif
369
370 #if DUMP_NODE_STATISTICS
371 liveNodeSet.add(this);
372 #endif
373 }
374
~Node()375 Node::~Node()
376 {
377 #ifndef NDEBUG
378 HashSet<Node*>::iterator it = ignoreSet.find(this);
379 if (it != ignoreSet.end())
380 ignoreSet.remove(it);
381 else
382 nodeCounter.decrement();
383 #endif
384
385 #if DUMP_NODE_STATISTICS
386 liveNodeSet.remove(this);
387 #endif
388
389 if (!hasRareData())
390 ASSERT(!NodeRareData::rareDataMap().contains(this));
391 else {
392 if (m_document && rareData()->nodeLists())
393 m_document->removeNodeListCache();
394
395 NodeRareData::NodeRareDataMap& dataMap = NodeRareData::rareDataMap();
396 NodeRareData::NodeRareDataMap::iterator it = dataMap.find(this);
397 ASSERT(it != dataMap.end());
398 delete it->second;
399 dataMap.remove(it);
400 }
401
402 if (renderer())
403 detach();
404
405 if (AXObjectCache::accessibilityEnabled() && m_document && m_document->axObjectCacheExists())
406 m_document->axObjectCache()->removeNodeForUse(this);
407
408 if (m_previous)
409 m_previous->setNextSibling(0);
410 if (m_next)
411 m_next->setPreviousSibling(0);
412
413 if (m_document)
414 m_document->guardDeref();
415 }
416
417 #ifdef NDEBUG
418
setWillMoveToNewOwnerDocumentWasCalled(bool)419 static inline void setWillMoveToNewOwnerDocumentWasCalled(bool)
420 {
421 }
422
setDidMoveToNewOwnerDocumentWasCalled(bool)423 static inline void setDidMoveToNewOwnerDocumentWasCalled(bool)
424 {
425 }
426
427 #else
428
429 static bool willMoveToNewOwnerDocumentWasCalled;
430 static bool didMoveToNewOwnerDocumentWasCalled;
431
setWillMoveToNewOwnerDocumentWasCalled(bool wasCalled)432 static void setWillMoveToNewOwnerDocumentWasCalled(bool wasCalled)
433 {
434 willMoveToNewOwnerDocumentWasCalled = wasCalled;
435 }
436
setDidMoveToNewOwnerDocumentWasCalled(bool wasCalled)437 static void setDidMoveToNewOwnerDocumentWasCalled(bool wasCalled)
438 {
439 didMoveToNewOwnerDocumentWasCalled = wasCalled;
440 }
441
442 #endif
443
setDocument(Document * document)444 void Node::setDocument(Document* document)
445 {
446 ASSERT(!inDocument() || m_document == document);
447 if (inDocument() || m_document == document)
448 return;
449
450 document->guardRef();
451
452 setWillMoveToNewOwnerDocumentWasCalled(false);
453 willMoveToNewOwnerDocument();
454 ASSERT(willMoveToNewOwnerDocumentWasCalled);
455
456 if (hasRareData() && rareData()->nodeLists()) {
457 if (m_document)
458 m_document->removeNodeListCache();
459 document->addNodeListCache();
460 }
461
462 if (m_document) {
463 m_document->moveNodeIteratorsToNewDocument(this, document);
464 m_document->guardDeref();
465 }
466
467 m_document = document;
468
469 setDidMoveToNewOwnerDocumentWasCalled(false);
470 didMoveToNewOwnerDocument();
471 ASSERT(didMoveToNewOwnerDocumentWasCalled);
472 }
473
treeScope() const474 TreeScope* Node::treeScope() const
475 {
476 if (!hasRareData())
477 return document();
478 TreeScope* scope = rareData()->treeScope();
479 // FIXME: Until we land shadow scopes, there should be no non-document scopes.
480 ASSERT(!scope);
481 return scope ? scope : document();
482 }
483
setTreeScope(TreeScope * newTreeScope)484 void Node::setTreeScope(TreeScope* newTreeScope)
485 {
486 ASSERT(!isDocumentNode());
487 ASSERT(newTreeScope);
488 ASSERT(!inDocument() || treeScope() == newTreeScope);
489
490 if (newTreeScope->isDocumentNode()) {
491 if (hasRareData())
492 rareData()->setTreeScope(0);
493 // Setting the new document scope will be handled implicitly
494 // by setDocument() below.
495 } else {
496 // FIXME: Until we land shadow scopes, this branch should be inert.
497 ASSERT_NOT_REACHED();
498 ensureRareData()->setTreeScope(newTreeScope);
499 }
500
501 setDocument(newTreeScope->document());
502 }
503
setTreeScopeRecursively(TreeScope * newTreeScope)504 void Node::setTreeScopeRecursively(TreeScope* newTreeScope)
505 {
506 ASSERT(!isDocumentNode());
507 ASSERT(newTreeScope);
508 if (treeScope() == newTreeScope)
509 return;
510
511 Document* currentDocument = document();
512 Document* newDocument = newTreeScope->document();
513 // If an element is moved from a document and then eventually back again the collection cache for
514 // that element may contain stale data as changes made to it will have updated the DOMTreeVersion
515 // of the document it was moved to. By increasing the DOMTreeVersion of the donating document here
516 // we ensure that the collection cache will be invalidated as needed when the element is moved back.
517 if (currentDocument && currentDocument != newDocument)
518 currentDocument->incDOMTreeVersion();
519
520 for (Node* node = this; node; node = node->traverseNextNode(this)) {
521 node->setTreeScope(newTreeScope);
522 // FIXME: Once shadow scopes are landed, update parent scope, etc.
523 }
524 }
525
rareData() const526 NodeRareData* Node::rareData() const
527 {
528 ASSERT(hasRareData());
529 return NodeRareData::rareDataFromMap(this);
530 }
531
ensureRareData()532 NodeRareData* Node::ensureRareData()
533 {
534 if (hasRareData())
535 return rareData();
536
537 ASSERT(!NodeRareData::rareDataMap().contains(this));
538 NodeRareData* data = createRareData();
539 NodeRareData::rareDataMap().set(this, data);
540 setFlag(HasRareDataFlag);
541 return data;
542 }
543
createRareData()544 NodeRareData* Node::createRareData()
545 {
546 return new NodeRareData;
547 }
548
shadowHost() const549 Element* Node::shadowHost() const
550 {
551 return toElement(getFlag(IsShadowRootFlag) ? parent() : 0);
552 }
553
setShadowHost(Element * host)554 void Node::setShadowHost(Element* host)
555 {
556 ASSERT(!parentNode() && !isSVGShadowRoot());
557 if (host)
558 setFlag(IsShadowRootFlag);
559 else
560 clearFlag(IsShadowRootFlag);
561
562 setParent(host);
563 }
564
toInputElement()565 InputElement* Node::toInputElement()
566 {
567 // If one of the below ASSERTs trigger, you are calling this function
568 // directly or indirectly from a constructor or destructor of this object.
569 // Don't do this!
570 ASSERT(!(isHTMLElement() && hasTagName(inputTag)));
571 #if ENABLE(WML)
572 ASSERT(!(isWMLElement() && hasTagName(WMLNames::inputTag)));
573 #endif
574 return 0;
575 }
576
tabIndex() const577 short Node::tabIndex() const
578 {
579 return hasRareData() ? rareData()->tabIndex() : 0;
580 }
581
setTabIndexExplicitly(short i)582 void Node::setTabIndexExplicitly(short i)
583 {
584 ensureRareData()->setTabIndexExplicitly(i);
585 }
586
clearTabIndexExplicitly()587 void Node::clearTabIndexExplicitly()
588 {
589 ensureRareData()->clearTabIndexExplicitly();
590 }
591
nodeValue() const592 String Node::nodeValue() const
593 {
594 return String();
595 }
596
setNodeValue(const String &,ExceptionCode & ec)597 void Node::setNodeValue(const String& /*nodeValue*/, ExceptionCode& ec)
598 {
599 // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
600 if (isReadOnlyNode()) {
601 ec = NO_MODIFICATION_ALLOWED_ERR;
602 return;
603 }
604
605 // By default, setting nodeValue has no effect.
606 }
607
childNodes()608 PassRefPtr<NodeList> Node::childNodes()
609 {
610 NodeRareData* data = ensureRareData();
611 if (!data->nodeLists()) {
612 data->setNodeLists(NodeListsNodeData::create());
613 if (document())
614 document()->addNodeListCache();
615 }
616
617 return ChildNodeList::create(this, data->nodeLists()->m_childNodeListCaches.get());
618 }
619
lastDescendant() const620 Node *Node::lastDescendant() const
621 {
622 Node *n = const_cast<Node *>(this);
623 while (n && n->lastChild())
624 n = n->lastChild();
625 return n;
626 }
627
firstDescendant() const628 Node* Node::firstDescendant() const
629 {
630 Node *n = const_cast<Node *>(this);
631 while (n && n->firstChild())
632 n = n->firstChild();
633 return n;
634 }
635
insertBefore(PassRefPtr<Node> newChild,Node * refChild,ExceptionCode & ec,bool shouldLazyAttach)636 bool Node::insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& ec, bool shouldLazyAttach)
637 {
638 if (!isContainerNode()) {
639 ec = HIERARCHY_REQUEST_ERR;
640 return false;
641 }
642 return toContainerNode(this)->insertBefore(newChild, refChild, ec, shouldLazyAttach);
643 }
644
replaceChild(PassRefPtr<Node> newChild,Node * oldChild,ExceptionCode & ec,bool shouldLazyAttach)645 bool Node::replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& ec, bool shouldLazyAttach)
646 {
647 if (!isContainerNode()) {
648 ec = HIERARCHY_REQUEST_ERR;
649 return false;
650 }
651 return toContainerNode(this)->replaceChild(newChild, oldChild, ec, shouldLazyAttach);
652 }
653
removeChild(Node * oldChild,ExceptionCode & ec)654 bool Node::removeChild(Node* oldChild, ExceptionCode& ec)
655 {
656 if (!isContainerNode()) {
657 ec = NOT_FOUND_ERR;
658 return false;
659 }
660 return toContainerNode(this)->removeChild(oldChild, ec);
661 }
662
appendChild(PassRefPtr<Node> newChild,ExceptionCode & ec,bool shouldLazyAttach)663 bool Node::appendChild(PassRefPtr<Node> newChild, ExceptionCode& ec, bool shouldLazyAttach)
664 {
665 if (!isContainerNode()) {
666 ec = HIERARCHY_REQUEST_ERR;
667 return false;
668 }
669 return toContainerNode(this)->appendChild(newChild, ec, shouldLazyAttach);
670 }
671
remove(ExceptionCode & ec)672 void Node::remove(ExceptionCode& ec)
673 {
674 if (ContainerNode* parent = parentNode())
675 parent->removeChild(this, ec);
676 else
677 ec = HIERARCHY_REQUEST_ERR;
678 }
679
normalize()680 void Node::normalize()
681 {
682 // Go through the subtree beneath us, normalizing all nodes. This means that
683 // any two adjacent text nodes are merged and any empty text nodes are removed.
684
685 RefPtr<Node> node = this;
686 while (Node* firstChild = node->firstChild())
687 node = firstChild;
688 while (node) {
689 NodeType type = node->nodeType();
690 if (type == ELEMENT_NODE)
691 static_cast<Element*>(node.get())->normalizeAttributes();
692
693 if (node == this)
694 break;
695
696 if (type != TEXT_NODE) {
697 node = node->traverseNextNodePostOrder();
698 continue;
699 }
700
701 Text* text = static_cast<Text*>(node.get());
702
703 // Remove empty text nodes.
704 if (!text->length()) {
705 // Care must be taken to get the next node before removing the current node.
706 node = node->traverseNextNodePostOrder();
707 ExceptionCode ec;
708 text->remove(ec);
709 continue;
710 }
711
712 // Merge text nodes.
713 while (Node* nextSibling = node->nextSibling()) {
714 if (nextSibling->nodeType() != TEXT_NODE)
715 break;
716 RefPtr<Text> nextText = static_cast<Text*>(nextSibling);
717
718 // Remove empty text nodes.
719 if (!nextText->length()) {
720 ExceptionCode ec;
721 nextText->remove(ec);
722 continue;
723 }
724
725 // Both non-empty text nodes. Merge them.
726 unsigned offset = text->length();
727 ExceptionCode ec;
728 text->appendData(nextText->data(), ec);
729 document()->textNodesMerged(nextText.get(), offset);
730 nextText->remove(ec);
731 }
732
733 node = node->traverseNextNodePostOrder();
734 }
735 }
736
virtualPrefix() const737 const AtomicString& Node::virtualPrefix() const
738 {
739 // For nodes other than elements and attributes, the prefix is always null
740 return nullAtom;
741 }
742
setPrefix(const AtomicString &,ExceptionCode & ec)743 void Node::setPrefix(const AtomicString& /*prefix*/, ExceptionCode& ec)
744 {
745 // The spec says that for nodes other than elements and attributes, prefix is always null.
746 // It does not say what to do when the user tries to set the prefix on another type of
747 // node, however Mozilla throws a NAMESPACE_ERR exception.
748 ec = NAMESPACE_ERR;
749 }
750
virtualLocalName() const751 const AtomicString& Node::virtualLocalName() const
752 {
753 return nullAtom;
754 }
755
virtualNamespaceURI() const756 const AtomicString& Node::virtualNamespaceURI() const
757 {
758 return nullAtom;
759 }
760
deprecatedParserAddChild(PassRefPtr<Node>)761 void Node::deprecatedParserAddChild(PassRefPtr<Node>)
762 {
763 }
764
isContentEditable() const765 bool Node::isContentEditable() const
766 {
767 document()->updateLayoutIgnorePendingStylesheets();
768 return rendererIsEditable(Editable);
769 }
770
rendererIsEditable(EditableLevel editableLevel) const771 bool Node::rendererIsEditable(EditableLevel editableLevel) const
772 {
773 if (document()->frame() && document()->frame()->page() && document()->frame()->page()->isEditable())
774 return true;
775
776 // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but
777 // ContainerNode::setFocus() calls setNeedsStyleRecalc(), so the assertion
778 // would fire in the middle of Document::setFocusedNode().
779
780 for (const Node* node = this; node; node = node->parentNode()) {
781 if ((node->isHTMLElement() || node->isDocumentNode()) && node->renderer()) {
782 switch (node->renderer()->style()->userModify()) {
783 case READ_ONLY:
784 return false;
785 case READ_WRITE:
786 return true;
787 case READ_WRITE_PLAINTEXT_ONLY:
788 return editableLevel != RichlyEditable;
789 }
790 ASSERT_NOT_REACHED();
791 return false;
792 }
793 }
794
795 return false;
796 }
797
shouldUseInputMethod() const798 bool Node::shouldUseInputMethod() const
799 {
800 return isContentEditable();
801 }
802
renderBox() const803 RenderBox* Node::renderBox() const
804 {
805 return m_renderer && m_renderer->isBox() ? toRenderBox(m_renderer) : 0;
806 }
807
renderBoxModelObject() const808 RenderBoxModelObject* Node::renderBoxModelObject() const
809 {
810 return m_renderer && m_renderer->isBoxModelObject() ? toRenderBoxModelObject(m_renderer) : 0;
811 }
812
getRect() const813 IntRect Node::getRect() const
814 {
815 if (renderer())
816 return renderer()->absoluteBoundingBoxRect(true);
817 return IntRect();
818 }
819
renderRect(bool * isReplaced)820 IntRect Node::renderRect(bool* isReplaced)
821 {
822 RenderObject* hitRenderer = this->renderer();
823 ASSERT(hitRenderer);
824 RenderObject* renderer = hitRenderer;
825 while (renderer && !renderer->isBody() && !renderer->isRoot()) {
826 if (renderer->isRenderBlock() || renderer->isInlineBlockOrInlineTable() || renderer->isReplaced()) {
827 *isReplaced = renderer->isReplaced();
828 return renderer->absoluteBoundingBoxRect(true);
829 }
830 renderer = renderer->parent();
831 }
832 return IntRect();
833 }
834
hasNonEmptyBoundingBox() const835 bool Node::hasNonEmptyBoundingBox() const
836 {
837 // Before calling absoluteRects, check for the common case where the renderer
838 // is non-empty, since this is a faster check and almost always returns true.
839 RenderBoxModelObject* box = renderBoxModelObject();
840 if (!box)
841 return false;
842 if (!box->borderBoundingBox().isEmpty())
843 return true;
844
845 Vector<IntRect> rects;
846 FloatPoint absPos = renderer()->localToAbsolute();
847 renderer()->absoluteRects(rects, absPos.x(), absPos.y());
848 size_t n = rects.size();
849 for (size_t i = 0; i < n; ++i)
850 if (!rects[i].isEmpty())
851 return true;
852
853 return false;
854 }
855
shadowRoot(Node * node)856 inline static ContainerNode* shadowRoot(Node* node)
857 {
858 return node->isElementNode() ? toElement(node)->shadowRoot() : 0;
859 }
860
setDocumentRecursively(Document * newDocument)861 void Node::setDocumentRecursively(Document* newDocument)
862 {
863 ASSERT(document() != newDocument);
864
865 for (Node* node = this; node; node = node->traverseNextNode(this)) {
866 node->setDocument(newDocument);
867 if (!node->isElementNode())
868 continue;
869 if (Node* shadow = shadowRoot(node))
870 shadow->setDocumentRecursively(newDocument);
871 }
872 }
873
setStyleChange(StyleChangeType changeType)874 inline void Node::setStyleChange(StyleChangeType changeType)
875 {
876 m_nodeFlags = (m_nodeFlags & ~StyleChangeMask) | changeType;
877 }
878
markAncestorsWithChildNeedsStyleRecalc()879 inline void Node::markAncestorsWithChildNeedsStyleRecalc()
880 {
881 for (ContainerNode* p = parentOrHostNode(); p && !p->childNeedsStyleRecalc(); p = p->parentOrHostNode())
882 p->setChildNeedsStyleRecalc();
883
884 if (document()->childNeedsStyleRecalc())
885 document()->scheduleStyleRecalc();
886 }
887
refEventTarget()888 void Node::refEventTarget()
889 {
890 ref();
891 }
892
derefEventTarget()893 void Node::derefEventTarget()
894 {
895 deref();
896 }
897
setNeedsStyleRecalc(StyleChangeType changeType)898 void Node::setNeedsStyleRecalc(StyleChangeType changeType)
899 {
900 ASSERT(changeType != NoStyleChange);
901 if (!attached()) // changed compared to what?
902 return;
903
904 StyleChangeType existingChangeType = styleChangeType();
905 if (changeType > existingChangeType)
906 setStyleChange(changeType);
907
908 if (existingChangeType == NoStyleChange)
909 markAncestorsWithChildNeedsStyleRecalc();
910 }
911
lazyAttach(ShouldSetAttached shouldSetAttached)912 void Node::lazyAttach(ShouldSetAttached shouldSetAttached)
913 {
914 for (Node* n = this; n; n = n->traverseNextNode(this)) {
915 if (n->firstChild())
916 n->setChildNeedsStyleRecalc();
917 n->setStyleChange(FullStyleChange);
918 if (shouldSetAttached == SetAttached)
919 n->setAttached();
920 }
921 markAncestorsWithChildNeedsStyleRecalc();
922 }
923
setFocus(bool b)924 void Node::setFocus(bool b)
925 {
926 if (b || hasRareData())
927 ensureRareData()->setFocused(b);
928 }
929
rareDataFocused() const930 bool Node::rareDataFocused() const
931 {
932 ASSERT(hasRareData());
933 return rareData()->isFocused();
934 }
935
supportsFocus() const936 bool Node::supportsFocus() const
937 {
938 return hasRareData() && rareData()->tabIndexSetExplicitly();
939 }
940
isFocusable() const941 bool Node::isFocusable() const
942 {
943 if (!inDocument() || !supportsFocus())
944 return false;
945
946 if (renderer())
947 ASSERT(!renderer()->needsLayout());
948 else
949 // If the node is in a display:none tree it might say it needs style recalc but
950 // the whole document is actually up to date.
951 ASSERT(!document()->childNeedsStyleRecalc());
952
953 // FIXME: Even if we are not visible, we might have a child that is visible.
954 // Hyatt wants to fix that some day with a "has visible content" flag or the like.
955 if (!renderer() || renderer()->style()->visibility() != VISIBLE)
956 return false;
957
958 return true;
959 }
960
isKeyboardFocusable(KeyboardEvent *) const961 bool Node::isKeyboardFocusable(KeyboardEvent*) const
962 {
963 return isFocusable() && tabIndex() >= 0;
964 }
965
isMouseFocusable() const966 bool Node::isMouseFocusable() const
967 {
968 return isFocusable();
969 }
970
nodeIndex() const971 unsigned Node::nodeIndex() const
972 {
973 Node *_tempNode = previousSibling();
974 unsigned count=0;
975 for ( count=0; _tempNode; count++ )
976 _tempNode = _tempNode->previousSibling();
977 return count;
978 }
979
registerDynamicNodeList(DynamicNodeList * list)980 void Node::registerDynamicNodeList(DynamicNodeList* list)
981 {
982 NodeRareData* data = ensureRareData();
983 if (!data->nodeLists()) {
984 data->setNodeLists(NodeListsNodeData::create());
985 document()->addNodeListCache();
986 } else if (!m_document || !m_document->hasNodeListCaches()) {
987 // We haven't been receiving notifications while there were no registered lists, so the cache is invalid now.
988 data->nodeLists()->invalidateCaches();
989 }
990
991 if (list->hasOwnCaches())
992 data->nodeLists()->m_listsWithCaches.add(list);
993 }
994
unregisterDynamicNodeList(DynamicNodeList * list)995 void Node::unregisterDynamicNodeList(DynamicNodeList* list)
996 {
997 ASSERT(rareData());
998 ASSERT(rareData()->nodeLists());
999 if (list->hasOwnCaches()) {
1000 NodeRareData* data = rareData();
1001 data->nodeLists()->m_listsWithCaches.remove(list);
1002 if (data->nodeLists()->isEmpty()) {
1003 data->clearNodeLists();
1004 if (document())
1005 document()->removeNodeListCache();
1006 }
1007 }
1008 }
1009
notifyLocalNodeListsAttributeChanged()1010 void Node::notifyLocalNodeListsAttributeChanged()
1011 {
1012 if (!hasRareData())
1013 return;
1014 NodeRareData* data = rareData();
1015 if (!data->nodeLists())
1016 return;
1017
1018 if (!isAttributeNode())
1019 data->nodeLists()->invalidateCachesThatDependOnAttributes();
1020 else
1021 data->nodeLists()->invalidateCaches();
1022
1023 if (data->nodeLists()->isEmpty()) {
1024 data->clearNodeLists();
1025 document()->removeNodeListCache();
1026 }
1027 }
1028
notifyNodeListsAttributeChanged()1029 void Node::notifyNodeListsAttributeChanged()
1030 {
1031 for (Node *n = this; n; n = n->parentNode())
1032 n->notifyLocalNodeListsAttributeChanged();
1033 }
1034
notifyLocalNodeListsChildrenChanged()1035 void Node::notifyLocalNodeListsChildrenChanged()
1036 {
1037 if (!hasRareData())
1038 return;
1039 NodeRareData* data = rareData();
1040 if (!data->nodeLists())
1041 return;
1042
1043 data->nodeLists()->invalidateCaches();
1044
1045 NodeListsNodeData::NodeListSet::iterator end = data->nodeLists()->m_listsWithCaches.end();
1046 for (NodeListsNodeData::NodeListSet::iterator i = data->nodeLists()->m_listsWithCaches.begin(); i != end; ++i)
1047 (*i)->invalidateCache();
1048
1049 if (data->nodeLists()->isEmpty()) {
1050 data->clearNodeLists();
1051 document()->removeNodeListCache();
1052 }
1053 }
1054
notifyNodeListsChildrenChanged()1055 void Node::notifyNodeListsChildrenChanged()
1056 {
1057 for (Node* n = this; n; n = n->parentNode())
1058 n->notifyLocalNodeListsChildrenChanged();
1059 }
1060
notifyLocalNodeListsLabelChanged()1061 void Node::notifyLocalNodeListsLabelChanged()
1062 {
1063 if (!hasRareData())
1064 return;
1065 NodeRareData* data = rareData();
1066 if (!data->nodeLists())
1067 return;
1068
1069 if (data->nodeLists()->m_labelsNodeListCache)
1070 data->nodeLists()->m_labelsNodeListCache->invalidateCache();
1071 }
1072
removeCachedClassNodeList(ClassNodeList * list,const String & className)1073 void Node::removeCachedClassNodeList(ClassNodeList* list, const String& className)
1074 {
1075 ASSERT(rareData());
1076 ASSERT(rareData()->nodeLists());
1077 ASSERT_UNUSED(list, list->hasOwnCaches());
1078
1079 NodeListsNodeData* data = rareData()->nodeLists();
1080 ASSERT_UNUSED(list, list == data->m_classNodeListCache.get(className));
1081 data->m_classNodeListCache.remove(className);
1082 }
1083
removeCachedNameNodeList(NameNodeList * list,const String & nodeName)1084 void Node::removeCachedNameNodeList(NameNodeList* list, const String& nodeName)
1085 {
1086 ASSERT(rareData());
1087 ASSERT(rareData()->nodeLists());
1088 ASSERT_UNUSED(list, list->hasOwnCaches());
1089
1090 NodeListsNodeData* data = rareData()->nodeLists();
1091 ASSERT_UNUSED(list, list == data->m_nameNodeListCache.get(nodeName));
1092 data->m_nameNodeListCache.remove(nodeName);
1093 }
1094
removeCachedTagNodeList(TagNodeList * list,const QualifiedName & name)1095 void Node::removeCachedTagNodeList(TagNodeList* list, const QualifiedName& name)
1096 {
1097 ASSERT(rareData());
1098 ASSERT(rareData()->nodeLists());
1099 ASSERT_UNUSED(list, list->hasOwnCaches());
1100
1101 NodeListsNodeData* data = rareData()->nodeLists();
1102 ASSERT_UNUSED(list, list == data->m_tagNodeListCache.get(name.impl()));
1103 data->m_tagNodeListCache.remove(name.impl());
1104 }
1105
removeCachedLabelsNodeList(DynamicNodeList * list)1106 void Node::removeCachedLabelsNodeList(DynamicNodeList* list)
1107 {
1108 ASSERT(rareData());
1109 ASSERT(rareData()->nodeLists());
1110 ASSERT_UNUSED(list, list->hasOwnCaches());
1111
1112 NodeListsNodeData* data = rareData()->nodeLists();
1113 data->m_labelsNodeListCache = 0;
1114 }
1115
traverseNextNode(const Node * stayWithin) const1116 Node* Node::traverseNextNode(const Node* stayWithin) const
1117 {
1118 if (firstChild())
1119 return firstChild();
1120 if (this == stayWithin)
1121 return 0;
1122 if (nextSibling())
1123 return nextSibling();
1124 const Node *n = this;
1125 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
1126 n = n->parentNode();
1127 if (n)
1128 return n->nextSibling();
1129 return 0;
1130 }
1131
traverseNextSibling(const Node * stayWithin) const1132 Node* Node::traverseNextSibling(const Node* stayWithin) const
1133 {
1134 if (this == stayWithin)
1135 return 0;
1136 if (nextSibling())
1137 return nextSibling();
1138 const Node *n = this;
1139 while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
1140 n = n->parentNode();
1141 if (n)
1142 return n->nextSibling();
1143 return 0;
1144 }
1145
traverseNextNodePostOrder() const1146 Node* Node::traverseNextNodePostOrder() const
1147 {
1148 Node* next = nextSibling();
1149 if (!next)
1150 return parentNode();
1151 while (Node* firstChild = next->firstChild())
1152 next = firstChild;
1153 return next;
1154 }
1155
traversePreviousNode(const Node * stayWithin) const1156 Node* Node::traversePreviousNode(const Node* stayWithin) const
1157 {
1158 if (this == stayWithin)
1159 return 0;
1160 if (previousSibling()) {
1161 Node *n = previousSibling();
1162 while (n->lastChild())
1163 n = n->lastChild();
1164 return n;
1165 }
1166 return parentNode();
1167 }
1168
traversePreviousNodePostOrder(const Node * stayWithin) const1169 Node* Node::traversePreviousNodePostOrder(const Node* stayWithin) const
1170 {
1171 if (lastChild())
1172 return lastChild();
1173 if (this == stayWithin)
1174 return 0;
1175 if (previousSibling())
1176 return previousSibling();
1177 const Node *n = this;
1178 while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
1179 n = n->parentNode();
1180 if (n)
1181 return n->previousSibling();
1182 return 0;
1183 }
1184
traversePreviousSiblingPostOrder(const Node * stayWithin) const1185 Node* Node::traversePreviousSiblingPostOrder(const Node* stayWithin) const
1186 {
1187 if (this == stayWithin)
1188 return 0;
1189 if (previousSibling())
1190 return previousSibling();
1191 const Node *n = this;
1192 while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
1193 n = n->parentNode();
1194 if (n)
1195 return n->previousSibling();
1196 return 0;
1197 }
1198
checkSetPrefix(const AtomicString & prefix,ExceptionCode & ec)1199 void Node::checkSetPrefix(const AtomicString& prefix, ExceptionCode& ec)
1200 {
1201 // Perform error checking as required by spec for setting Node.prefix. Used by
1202 // Element::setPrefix() and Attr::setPrefix()
1203
1204 // FIXME: Implement support for INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
1205
1206 if (isReadOnlyNode()) {
1207 ec = NO_MODIFICATION_ALLOWED_ERR;
1208 return;
1209 }
1210
1211 // FIXME: Raise NAMESPACE_ERR if prefix is malformed per the Namespaces in XML specification.
1212
1213 const AtomicString& nodeNamespaceURI = namespaceURI();
1214 if ((nodeNamespaceURI.isEmpty() && !prefix.isEmpty())
1215 || (prefix == xmlAtom && nodeNamespaceURI != XMLNames::xmlNamespaceURI)) {
1216 ec = NAMESPACE_ERR;
1217 return;
1218 }
1219 // Attribute-specific checks are in Attr::setPrefix().
1220 }
1221
isChildTypeAllowed(Node * newParent,Node * child)1222 static bool isChildTypeAllowed(Node* newParent, Node* child)
1223 {
1224 if (child->nodeType() != Node::DOCUMENT_FRAGMENT_NODE) {
1225 if (!newParent->childTypeAllowed(child->nodeType()))
1226 return false;
1227 return true;
1228 }
1229
1230 for (Node *n = child->firstChild(); n; n = n->nextSibling()) {
1231 if (!newParent->childTypeAllowed(n->nodeType()))
1232 return false;
1233 }
1234 return true;
1235 }
1236
canReplaceChild(Node * newChild,Node *)1237 bool Node::canReplaceChild(Node* newChild, Node*)
1238 {
1239 return isChildTypeAllowed(this, newChild);
1240 }
1241
checkAcceptChild(Node * newParent,Node * newChild,ExceptionCode & ec)1242 static void checkAcceptChild(Node* newParent, Node* newChild, ExceptionCode& ec)
1243 {
1244 // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
1245 if (!newChild) {
1246 ec = NOT_FOUND_ERR;
1247 return;
1248 }
1249
1250 if (newParent->isReadOnlyNode()) {
1251 ec = NO_MODIFICATION_ALLOWED_ERR;
1252 return;
1253 }
1254
1255 if (newChild->inDocument() && newChild->nodeType() == Node::DOCUMENT_TYPE_NODE) {
1256 ec = HIERARCHY_REQUEST_ERR;
1257 return;
1258 }
1259
1260 // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
1261 // newChild node, or if the node to append is one of this node's ancestors.
1262
1263 if (newChild == newParent || newParent->isDescendantOf(newChild)) {
1264 ec = HIERARCHY_REQUEST_ERR;
1265 return;
1266 }
1267 }
1268
checkReplaceChild(Node * newChild,Node * oldChild,ExceptionCode & ec)1269 void Node::checkReplaceChild(Node* newChild, Node* oldChild, ExceptionCode& ec)
1270 {
1271 if (!oldChild) {
1272 ec = NOT_FOUND_ERR;
1273 return;
1274 }
1275
1276 checkAcceptChild(this, newChild, ec);
1277 if (ec)
1278 return;
1279
1280 if (!canReplaceChild(newChild, oldChild)) {
1281 ec = HIERARCHY_REQUEST_ERR;
1282 return;
1283 }
1284 }
1285
checkAddChild(Node * newChild,ExceptionCode & ec)1286 void Node::checkAddChild(Node *newChild, ExceptionCode& ec)
1287 {
1288 checkAcceptChild(this, newChild, ec);
1289 if (ec)
1290 return;
1291
1292 if (!isChildTypeAllowed(this, newChild)) {
1293 ec = HIERARCHY_REQUEST_ERR;
1294 return;
1295 }
1296 }
1297
isDescendantOf(const Node * other) const1298 bool Node::isDescendantOf(const Node *other) const
1299 {
1300 // Return true if other is an ancestor of this, otherwise false
1301 if (!other)
1302 return false;
1303 for (const ContainerNode* n = parentNode(); n; n = n->parentNode()) {
1304 if (n == other)
1305 return true;
1306 }
1307 return false;
1308 }
1309
contains(const Node * node) const1310 bool Node::contains(const Node* node) const
1311 {
1312 if (!node)
1313 return false;
1314 return this == node || node->isDescendantOf(this);
1315 }
1316
containsIncludingShadowDOM(Node * node)1317 bool Node::containsIncludingShadowDOM(Node* node)
1318 {
1319 if (!node)
1320 return false;
1321 for (Node* n = node; n; n = n->parentOrHostNode()) {
1322 if (n == this)
1323 return true;
1324 }
1325 return false;
1326 }
1327
attach()1328 void Node::attach()
1329 {
1330 ASSERT(!attached());
1331 ASSERT(!renderer() || (renderer()->style() && renderer()->parent()));
1332
1333 // FIXME: This is O(N^2) for the innerHTML case, where all children are replaced at once (and not attached).
1334 // If this node got a renderer it may be the previousRenderer() of sibling text nodes and thus affect the
1335 // result of Text::rendererIsNeeded() for those nodes.
1336 if (renderer()) {
1337 for (Node* next = nextSibling(); next; next = next->nextSibling()) {
1338 if (next->renderer())
1339 break;
1340 if (!next->attached())
1341 break; // Assume this means none of the following siblings are attached.
1342 if (next->isTextNode())
1343 next->createRendererIfNeeded();
1344 }
1345 }
1346
1347 setAttached();
1348 clearNeedsStyleRecalc();
1349 }
1350
willRemove()1351 void Node::willRemove()
1352 {
1353 }
1354
detach()1355 void Node::detach()
1356 {
1357 setFlag(InDetachFlag);
1358
1359 if (renderer())
1360 renderer()->destroy();
1361 setRenderer(0);
1362
1363 Document* doc = document();
1364 if (hovered())
1365 doc->hoveredNodeDetached(this);
1366 if (inActiveChain())
1367 doc->activeChainNodeDetached(this);
1368
1369 clearFlag(IsActiveFlag);
1370 clearFlag(IsHoveredFlag);
1371 clearFlag(InActiveChainFlag);
1372 clearFlag(IsAttachedFlag);
1373
1374 clearFlag(InDetachFlag);
1375 }
1376
previousRenderer()1377 RenderObject* Node::previousRenderer()
1378 {
1379 // FIXME: We should have the same O(N^2) avoidance as nextRenderer does
1380 // however, when I tried adding it, several tests failed.
1381 for (Node* n = previousSibling(); n; n = n->previousSibling()) {
1382 if (n->renderer())
1383 return n->renderer();
1384 }
1385 return 0;
1386 }
1387
nextRenderer()1388 RenderObject* Node::nextRenderer()
1389 {
1390 // Avoid an O(n^2) problem with this function by not checking for
1391 // nextRenderer() when the parent element hasn't attached yet.
1392 if (parentOrHostNode() && !parentOrHostNode()->attached())
1393 return 0;
1394
1395 for (Node* n = nextSibling(); n; n = n->nextSibling()) {
1396 if (n->renderer())
1397 return n->renderer();
1398 }
1399 return 0;
1400 }
1401
1402 // FIXME: This code is used by editing. Seems like it could move over there and not pollute Node.
previousNodeConsideringAtomicNodes() const1403 Node *Node::previousNodeConsideringAtomicNodes() const
1404 {
1405 if (previousSibling()) {
1406 Node *n = previousSibling();
1407 while (!isAtomicNode(n) && n->lastChild())
1408 n = n->lastChild();
1409 return n;
1410 }
1411 else if (parentNode()) {
1412 return parentNode();
1413 }
1414 else {
1415 return 0;
1416 }
1417 }
1418
nextNodeConsideringAtomicNodes() const1419 Node *Node::nextNodeConsideringAtomicNodes() const
1420 {
1421 if (!isAtomicNode(this) && firstChild())
1422 return firstChild();
1423 if (nextSibling())
1424 return nextSibling();
1425 const Node *n = this;
1426 while (n && !n->nextSibling())
1427 n = n->parentNode();
1428 if (n)
1429 return n->nextSibling();
1430 return 0;
1431 }
1432
previousLeafNode() const1433 Node *Node::previousLeafNode() const
1434 {
1435 Node *node = previousNodeConsideringAtomicNodes();
1436 while (node) {
1437 if (isAtomicNode(node))
1438 return node;
1439 node = node->previousNodeConsideringAtomicNodes();
1440 }
1441 return 0;
1442 }
1443
nextLeafNode() const1444 Node *Node::nextLeafNode() const
1445 {
1446 Node *node = nextNodeConsideringAtomicNodes();
1447 while (node) {
1448 if (isAtomicNode(node))
1449 return node;
1450 node = node->nextNodeConsideringAtomicNodes();
1451 }
1452 return 0;
1453 }
1454
parentNodeForRenderingAndStyle() const1455 ContainerNode* Node::parentNodeForRenderingAndStyle() const
1456 {
1457 ContainerNode* parent = parentOrHostNode();
1458 return parent && parent->isShadowBoundary() ? parent->shadowHost() : parent;
1459 }
1460
shouldCreateRendererFor(Node * node,ContainerNode * parentForRenderingAndStyle)1461 static bool shouldCreateRendererFor(Node* node, ContainerNode* parentForRenderingAndStyle)
1462 {
1463 RenderObject* parentRenderer = parentForRenderingAndStyle->renderer();
1464 if (!parentRenderer)
1465 return false;
1466
1467 bool atShadowBoundary = node->parentOrHostNode()->isShadowBoundary();
1468
1469 // FIXME: Ignoring canHaveChildren() in a case of isShadowRoot() might be wrong.
1470 // See https://bugs.webkit.org/show_bug.cgi?id=52423
1471 if (!parentRenderer->canHaveChildren() && !(node->isShadowRoot() || atShadowBoundary))
1472 return false;
1473
1474 if (shadowRoot(parentForRenderingAndStyle) && !atShadowBoundary
1475 && !parentForRenderingAndStyle->canHaveLightChildRendererWithShadow())
1476 return false;
1477
1478 if (!parentForRenderingAndStyle->childShouldCreateRenderer(node))
1479 return false;
1480
1481 return true;
1482 }
1483
createRendererAndStyle()1484 RenderObject* Node::createRendererAndStyle()
1485 {
1486 ASSERT(!renderer());
1487 ASSERT(document()->shouldCreateRenderers());
1488
1489 ContainerNode* parent = parentNodeForRenderingAndStyle();
1490 ASSERT(parent);
1491
1492 if (!shouldCreateRendererFor(this, parent))
1493 return 0;
1494
1495 RefPtr<RenderStyle> style = styleForRenderer();
1496 if (!rendererIsNeeded(style.get()))
1497 return 0;
1498
1499 RenderObject* newRenderer = createRenderer(document()->renderArena(), style.get());
1500 if (!newRenderer)
1501 return 0;
1502
1503 if (!parent->renderer()->isChildAllowed(newRenderer, style.get())) {
1504 newRenderer->destroy();
1505 return 0;
1506 }
1507 setRenderer(newRenderer);
1508 newRenderer->setAnimatableStyle(style.release()); // setAnimatableStyle() can depend on renderer() already being set.
1509 return newRenderer;
1510 }
1511
1512 #if ENABLE(FULLSCREEN_API)
wrapWithRenderFullScreen(RenderObject * object,Document * document)1513 static RenderFullScreen* wrapWithRenderFullScreen(RenderObject* object, Document* document)
1514 {
1515 RenderFullScreen* fullscreenRenderer = new (document->renderArena()) RenderFullScreen(document);
1516 fullscreenRenderer->setStyle(RenderFullScreen::createFullScreenStyle());
1517 // It's possible that we failed to create the new render and end up wrapping nothing.
1518 // We'll end up displaying a black screen, but Jer says this is expected.
1519 if (object)
1520 fullscreenRenderer->addChild(object);
1521 document->setFullScreenRenderer(fullscreenRenderer);
1522 return fullscreenRenderer;
1523 }
1524 #endif
1525
createRendererIfNeeded()1526 void Node::createRendererIfNeeded()
1527 {
1528 if (!document()->shouldCreateRenderers())
1529 return;
1530
1531 ASSERT(!renderer());
1532
1533 RenderObject* newRenderer = createRendererAndStyle();
1534
1535 #if ENABLE(FULLSCREEN_API)
1536 if (document()->webkitIsFullScreen() && document()->webkitCurrentFullScreenElement() == this)
1537 newRenderer = wrapWithRenderFullScreen(newRenderer, document());
1538 #endif
1539
1540 if (!newRenderer)
1541 return;
1542
1543 // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
1544 parentNodeForRenderingAndStyle()->renderer()->addChild(newRenderer, nextRenderer());
1545 }
1546
styleForRenderer()1547 PassRefPtr<RenderStyle> Node::styleForRenderer()
1548 {
1549 if (isElementNode()) {
1550 bool allowSharing = true;
1551 #if ENABLE(XHTMLMP)
1552 // noscript needs the display property protected - it's a special case
1553 allowSharing = localName() != HTMLNames::noscriptTag.localName();
1554 #endif
1555 return document()->styleSelector()->styleForElement(static_cast<Element*>(this), 0, allowSharing);
1556 }
1557 return parentNode() && parentNode()->renderer() ? parentNode()->renderer()->style() : 0;
1558 }
1559
rendererIsNeeded(RenderStyle * style)1560 bool Node::rendererIsNeeded(RenderStyle *style)
1561 {
1562 return (document()->documentElement() == this) || (style->display() != NONE);
1563 }
1564
createRenderer(RenderArena *,RenderStyle *)1565 RenderObject* Node::createRenderer(RenderArena*, RenderStyle*)
1566 {
1567 ASSERT(false);
1568 return 0;
1569 }
1570
nonRendererRenderStyle() const1571 RenderStyle* Node::nonRendererRenderStyle() const
1572 {
1573 return 0;
1574 }
1575
setRenderStyle(PassRefPtr<RenderStyle> s)1576 void Node::setRenderStyle(PassRefPtr<RenderStyle> s)
1577 {
1578 if (m_renderer)
1579 m_renderer->setAnimatableStyle(s);
1580 }
1581
virtualComputedStyle(PseudoId pseudoElementSpecifier)1582 RenderStyle* Node::virtualComputedStyle(PseudoId pseudoElementSpecifier)
1583 {
1584 return parentOrHostNode() ? parentOrHostNode()->computedStyle(pseudoElementSpecifier) : 0;
1585 }
1586
maxCharacterOffset() const1587 int Node::maxCharacterOffset() const
1588 {
1589 ASSERT_NOT_REACHED();
1590 return 0;
1591 }
1592
1593 // FIXME: Shouldn't these functions be in the editing code? Code that asks questions about HTML in the core DOM class
1594 // is obviously misplaced.
canStartSelection() const1595 bool Node::canStartSelection() const
1596 {
1597 if (rendererIsEditable())
1598 return true;
1599
1600 if (renderer()) {
1601 RenderStyle* style = renderer()->style();
1602 // We allow selections to begin within an element that has -webkit-user-select: none set,
1603 // but if the element is draggable then dragging should take priority over selection.
1604 if (style->userDrag() == DRAG_ELEMENT && style->userSelect() == SELECT_NONE)
1605 return false;
1606 }
1607 return parentOrHostNode() ? parentOrHostNode()->canStartSelection() : true;
1608 }
1609
1610 #if ENABLE(SVG)
svgShadowHost() const1611 SVGUseElement* Node::svgShadowHost() const
1612 {
1613 return isSVGShadowRoot() ? static_cast<SVGUseElement*>(parent()) : 0;
1614 }
1615 #endif
1616
shadowAncestorNode() const1617 Node* Node::shadowAncestorNode() const
1618 {
1619 #if ENABLE(SVG)
1620 // SVG elements living in a shadow tree only occur when <use> created them.
1621 // For these cases we do NOT want to return the shadowParentNode() here
1622 // but the actual shadow tree element - as main difference to the HTML forms
1623 // shadow tree concept. (This function _could_ be made virtual - opinions?)
1624 if (isSVGElement())
1625 return const_cast<Node*>(this);
1626 #endif
1627
1628 Node* root = shadowTreeRootNode();
1629 if (root)
1630 return root->shadowHost();
1631 return const_cast<Node*>(this);
1632 }
1633
shadowTreeRootNode() const1634 Node* Node::shadowTreeRootNode() const
1635 {
1636 Node* root = const_cast<Node*>(this);
1637 while (root) {
1638 if (root->isShadowRoot() || root->isSVGShadowRoot())
1639 return root;
1640 root = root->parentNodeGuaranteedHostFree();
1641 }
1642 return 0;
1643 }
1644
isInShadowTree()1645 bool Node::isInShadowTree()
1646 {
1647 for (Node* n = this; n; n = n->parentNode())
1648 if (n->isShadowRoot())
1649 return true;
1650 return false;
1651 }
1652
isBlockFlow() const1653 bool Node::isBlockFlow() const
1654 {
1655 return renderer() && renderer()->isBlockFlow();
1656 }
1657
isBlockFlowOrBlockTable() const1658 bool Node::isBlockFlowOrBlockTable() const
1659 {
1660 return renderer() && (renderer()->isBlockFlow() || (renderer()->isTable() && !renderer()->isInline()));
1661 }
1662
enclosingBlockFlowElement() const1663 Element *Node::enclosingBlockFlowElement() const
1664 {
1665 Node *n = const_cast<Node *>(this);
1666 if (isBlockFlow())
1667 return static_cast<Element *>(n);
1668
1669 while (1) {
1670 n = n->parentNode();
1671 if (!n)
1672 break;
1673 if (n->isBlockFlow() || n->hasTagName(bodyTag))
1674 return static_cast<Element *>(n);
1675 }
1676 return 0;
1677 }
1678
rootEditableElement() const1679 Element* Node::rootEditableElement() const
1680 {
1681 Element* result = 0;
1682 for (Node* n = const_cast<Node*>(this); n && n->rendererIsEditable(); n = n->parentNode()) {
1683 if (n->isElementNode())
1684 result = static_cast<Element*>(n);
1685 if (n->hasTagName(bodyTag))
1686 break;
1687 }
1688 return result;
1689 }
1690
inSameContainingBlockFlowElement(Node * n)1691 bool Node::inSameContainingBlockFlowElement(Node *n)
1692 {
1693 return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
1694 }
1695
1696 // FIXME: End of obviously misplaced HTML editing functions. Try to move these out of Node.
1697
getElementsByTagName(const AtomicString & name)1698 PassRefPtr<NodeList> Node::getElementsByTagName(const AtomicString& name)
1699 {
1700 return getElementsByTagNameNS(starAtom, name);
1701 }
1702
getElementsByTagNameNS(const AtomicString & namespaceURI,const AtomicString & localName)1703 PassRefPtr<NodeList> Node::getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName)
1704 {
1705 if (localName.isNull())
1706 return 0;
1707
1708 NodeRareData* data = ensureRareData();
1709 if (!data->nodeLists()) {
1710 data->setNodeLists(NodeListsNodeData::create());
1711 document()->addNodeListCache();
1712 }
1713
1714 String name = localName;
1715 if (document()->isHTMLDocument())
1716 name = localName.lower();
1717
1718 AtomicString localNameAtom = name;
1719
1720 pair<NodeListsNodeData::TagNodeListCache::iterator, bool> result = data->nodeLists()->m_tagNodeListCache.add(QualifiedName(nullAtom, localNameAtom, namespaceURI).impl(), 0);
1721 if (!result.second)
1722 return PassRefPtr<TagNodeList>(result.first->second);
1723
1724 RefPtr<TagNodeList> list = TagNodeList::create(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localNameAtom);
1725 result.first->second = list.get();
1726 return list.release();
1727 }
1728
getElementsByName(const String & elementName)1729 PassRefPtr<NodeList> Node::getElementsByName(const String& elementName)
1730 {
1731 NodeRareData* data = ensureRareData();
1732 if (!data->nodeLists()) {
1733 data->setNodeLists(NodeListsNodeData::create());
1734 document()->addNodeListCache();
1735 }
1736
1737 pair<NodeListsNodeData::NameNodeListCache::iterator, bool> result = data->nodeLists()->m_nameNodeListCache.add(elementName, 0);
1738 if (!result.second)
1739 return PassRefPtr<NodeList>(result.first->second);
1740
1741 RefPtr<NameNodeList> list = NameNodeList::create(this, elementName);
1742 result.first->second = list.get();
1743 return list.release();
1744 }
1745
getElementsByClassName(const String & classNames)1746 PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames)
1747 {
1748 NodeRareData* data = ensureRareData();
1749 if (!data->nodeLists()) {
1750 data->setNodeLists(NodeListsNodeData::create());
1751 document()->addNodeListCache();
1752 }
1753
1754 pair<NodeListsNodeData::ClassNodeListCache::iterator, bool> result = data->nodeLists()->m_classNodeListCache.add(classNames, 0);
1755 if (!result.second)
1756 return PassRefPtr<NodeList>(result.first->second);
1757
1758 RefPtr<ClassNodeList> list = ClassNodeList::create(this, classNames);
1759 result.first->second = list.get();
1760 return list.release();
1761 }
1762
querySelector(const String & selectors,ExceptionCode & ec)1763 PassRefPtr<Element> Node::querySelector(const String& selectors, ExceptionCode& ec)
1764 {
1765 if (selectors.isEmpty()) {
1766 ec = SYNTAX_ERR;
1767 return 0;
1768 }
1769 bool strictParsing = !document()->inQuirksMode();
1770 CSSParser p(strictParsing);
1771
1772 CSSSelectorList querySelectorList;
1773 p.parseSelector(selectors, document(), querySelectorList);
1774
1775 if (!querySelectorList.first() || querySelectorList.hasUnknownPseudoElements()) {
1776 ec = SYNTAX_ERR;
1777 return 0;
1778 }
1779
1780 // throw a NAMESPACE_ERR if the selector includes any namespace prefixes.
1781 if (querySelectorList.selectorsNeedNamespaceResolution()) {
1782 ec = NAMESPACE_ERR;
1783 return 0;
1784 }
1785
1786 CSSStyleSelector::SelectorChecker selectorChecker(document(), strictParsing);
1787
1788 // FIXME: we could also optimize for the the [id="foo"] case
1789 if (strictParsing && inDocument() && querySelectorList.hasOneSelector() && querySelectorList.first()->m_match == CSSSelector::Id) {
1790 Element* element = document()->getElementById(querySelectorList.first()->value());
1791 if (element && (isDocumentNode() || element->isDescendantOf(this)) && selectorChecker.checkSelector(querySelectorList.first(), element))
1792 return element;
1793 return 0;
1794 }
1795
1796 // FIXME: We can speed this up by implementing caching similar to the one use by getElementById
1797 for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
1798 if (n->isElementNode()) {
1799 Element* element = static_cast<Element*>(n);
1800 for (CSSSelector* selector = querySelectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
1801 if (selectorChecker.checkSelector(selector, element))
1802 return element;
1803 }
1804 }
1805 }
1806
1807 return 0;
1808 }
1809
querySelectorAll(const String & selectors,ExceptionCode & ec)1810 PassRefPtr<NodeList> Node::querySelectorAll(const String& selectors, ExceptionCode& ec)
1811 {
1812 if (selectors.isEmpty()) {
1813 ec = SYNTAX_ERR;
1814 return 0;
1815 }
1816 bool strictParsing = !document()->inQuirksMode();
1817 CSSParser p(strictParsing);
1818
1819 CSSSelectorList querySelectorList;
1820 p.parseSelector(selectors, document(), querySelectorList);
1821
1822 if (!querySelectorList.first() || querySelectorList.hasUnknownPseudoElements()) {
1823 ec = SYNTAX_ERR;
1824 return 0;
1825 }
1826
1827 // Throw a NAMESPACE_ERR if the selector includes any namespace prefixes.
1828 if (querySelectorList.selectorsNeedNamespaceResolution()) {
1829 ec = NAMESPACE_ERR;
1830 return 0;
1831 }
1832
1833 return createSelectorNodeList(this, querySelectorList);
1834 }
1835
ownerDocument() const1836 Document *Node::ownerDocument() const
1837 {
1838 Document *doc = document();
1839 return doc == this ? 0 : doc;
1840 }
1841
baseURI() const1842 KURL Node::baseURI() const
1843 {
1844 return parentNode() ? parentNode()->baseURI() : KURL();
1845 }
1846
isEqualNode(Node * other) const1847 bool Node::isEqualNode(Node* other) const
1848 {
1849 if (!other)
1850 return false;
1851
1852 NodeType nodeType = this->nodeType();
1853 if (nodeType != other->nodeType())
1854 return false;
1855
1856 if (nodeName() != other->nodeName())
1857 return false;
1858
1859 if (localName() != other->localName())
1860 return false;
1861
1862 if (namespaceURI() != other->namespaceURI())
1863 return false;
1864
1865 if (prefix() != other->prefix())
1866 return false;
1867
1868 if (nodeValue() != other->nodeValue())
1869 return false;
1870
1871 NamedNodeMap* attributes = this->attributes();
1872 NamedNodeMap* otherAttributes = other->attributes();
1873
1874 if (!attributes && otherAttributes)
1875 return false;
1876
1877 if (attributes && !attributes->mapsEquivalent(otherAttributes))
1878 return false;
1879
1880 Node* child = firstChild();
1881 Node* otherChild = other->firstChild();
1882
1883 while (child) {
1884 if (!child->isEqualNode(otherChild))
1885 return false;
1886
1887 child = child->nextSibling();
1888 otherChild = otherChild->nextSibling();
1889 }
1890
1891 if (otherChild)
1892 return false;
1893
1894 if (nodeType == DOCUMENT_TYPE_NODE) {
1895 const DocumentType* documentTypeThis = static_cast<const DocumentType*>(this);
1896 const DocumentType* documentTypeOther = static_cast<const DocumentType*>(other);
1897
1898 if (documentTypeThis->publicId() != documentTypeOther->publicId())
1899 return false;
1900
1901 if (documentTypeThis->systemId() != documentTypeOther->systemId())
1902 return false;
1903
1904 if (documentTypeThis->internalSubset() != documentTypeOther->internalSubset())
1905 return false;
1906
1907 NamedNodeMap* entities = documentTypeThis->entities();
1908 NamedNodeMap* otherEntities = documentTypeOther->entities();
1909 if (!entities && otherEntities)
1910 return false;
1911 if (entities && !entities->mapsEquivalent(otherEntities))
1912 return false;
1913
1914 NamedNodeMap* notations = documentTypeThis->notations();
1915 NamedNodeMap* otherNotations = documentTypeOther->notations();
1916 if (!notations && otherNotations)
1917 return false;
1918 if (notations && !notations->mapsEquivalent(otherNotations))
1919 return false;
1920 }
1921
1922 return true;
1923 }
1924
isDefaultNamespace(const AtomicString & namespaceURIMaybeEmpty) const1925 bool Node::isDefaultNamespace(const AtomicString& namespaceURIMaybeEmpty) const
1926 {
1927 const AtomicString& namespaceURI = namespaceURIMaybeEmpty.isEmpty() ? nullAtom : namespaceURIMaybeEmpty;
1928
1929 switch (nodeType()) {
1930 case ELEMENT_NODE: {
1931 const Element* elem = static_cast<const Element*>(this);
1932
1933 if (elem->prefix().isNull())
1934 return elem->namespaceURI() == namespaceURI;
1935
1936 if (elem->hasAttributes()) {
1937 NamedNodeMap* attrs = elem->attributes();
1938
1939 for (unsigned i = 0; i < attrs->length(); i++) {
1940 Attribute* attr = attrs->attributeItem(i);
1941
1942 if (attr->localName() == xmlnsAtom)
1943 return attr->value() == namespaceURI;
1944 }
1945 }
1946
1947 if (Element* ancestor = ancestorElement())
1948 return ancestor->isDefaultNamespace(namespaceURI);
1949
1950 return false;
1951 }
1952 case DOCUMENT_NODE:
1953 if (Element* de = static_cast<const Document*>(this)->documentElement())
1954 return de->isDefaultNamespace(namespaceURI);
1955 return false;
1956 case ENTITY_NODE:
1957 case NOTATION_NODE:
1958 case DOCUMENT_TYPE_NODE:
1959 case DOCUMENT_FRAGMENT_NODE:
1960 return false;
1961 case ATTRIBUTE_NODE: {
1962 const Attr* attr = static_cast<const Attr*>(this);
1963 if (attr->ownerElement())
1964 return attr->ownerElement()->isDefaultNamespace(namespaceURI);
1965 return false;
1966 }
1967 default:
1968 if (Element* ancestor = ancestorElement())
1969 return ancestor->isDefaultNamespace(namespaceURI);
1970 return false;
1971 }
1972 }
1973
lookupPrefix(const AtomicString & namespaceURI) const1974 String Node::lookupPrefix(const AtomicString &namespaceURI) const
1975 {
1976 // Implemented according to
1977 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespacePrefixAlgo
1978
1979 if (namespaceURI.isEmpty())
1980 return String();
1981
1982 switch (nodeType()) {
1983 case ELEMENT_NODE:
1984 return lookupNamespacePrefix(namespaceURI, static_cast<const Element *>(this));
1985 case DOCUMENT_NODE:
1986 if (Element* de = static_cast<const Document*>(this)->documentElement())
1987 return de->lookupPrefix(namespaceURI);
1988 return String();
1989 case ENTITY_NODE:
1990 case NOTATION_NODE:
1991 case DOCUMENT_FRAGMENT_NODE:
1992 case DOCUMENT_TYPE_NODE:
1993 return String();
1994 case ATTRIBUTE_NODE: {
1995 const Attr *attr = static_cast<const Attr *>(this);
1996 if (attr->ownerElement())
1997 return attr->ownerElement()->lookupPrefix(namespaceURI);
1998 return String();
1999 }
2000 default:
2001 if (Element* ancestor = ancestorElement())
2002 return ancestor->lookupPrefix(namespaceURI);
2003 return String();
2004 }
2005 }
2006
lookupNamespaceURI(const String & prefix) const2007 String Node::lookupNamespaceURI(const String &prefix) const
2008 {
2009 // Implemented according to
2010 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespaceURIAlgo
2011
2012 if (!prefix.isNull() && prefix.isEmpty())
2013 return String();
2014
2015 switch (nodeType()) {
2016 case ELEMENT_NODE: {
2017 const Element *elem = static_cast<const Element *>(this);
2018
2019 if (!elem->namespaceURI().isNull() && elem->prefix() == prefix)
2020 return elem->namespaceURI();
2021
2022 if (elem->hasAttributes()) {
2023 NamedNodeMap *attrs = elem->attributes();
2024
2025 for (unsigned i = 0; i < attrs->length(); i++) {
2026 Attribute *attr = attrs->attributeItem(i);
2027
2028 if (attr->prefix() == xmlnsAtom && attr->localName() == prefix) {
2029 if (!attr->value().isEmpty())
2030 return attr->value();
2031
2032 return String();
2033 } else if (attr->localName() == xmlnsAtom && prefix.isNull()) {
2034 if (!attr->value().isEmpty())
2035 return attr->value();
2036
2037 return String();
2038 }
2039 }
2040 }
2041 if (Element* ancestor = ancestorElement())
2042 return ancestor->lookupNamespaceURI(prefix);
2043 return String();
2044 }
2045 case DOCUMENT_NODE:
2046 if (Element* de = static_cast<const Document*>(this)->documentElement())
2047 return de->lookupNamespaceURI(prefix);
2048 return String();
2049 case ENTITY_NODE:
2050 case NOTATION_NODE:
2051 case DOCUMENT_TYPE_NODE:
2052 case DOCUMENT_FRAGMENT_NODE:
2053 return String();
2054 case ATTRIBUTE_NODE: {
2055 const Attr *attr = static_cast<const Attr *>(this);
2056
2057 if (attr->ownerElement())
2058 return attr->ownerElement()->lookupNamespaceURI(prefix);
2059 else
2060 return String();
2061 }
2062 default:
2063 if (Element* ancestor = ancestorElement())
2064 return ancestor->lookupNamespaceURI(prefix);
2065 return String();
2066 }
2067 }
2068
lookupNamespacePrefix(const AtomicString & _namespaceURI,const Element * originalElement) const2069 String Node::lookupNamespacePrefix(const AtomicString &_namespaceURI, const Element *originalElement) const
2070 {
2071 if (_namespaceURI.isNull())
2072 return String();
2073
2074 if (originalElement->lookupNamespaceURI(prefix()) == _namespaceURI)
2075 return prefix();
2076
2077 if (hasAttributes()) {
2078 NamedNodeMap *attrs = attributes();
2079
2080 for (unsigned i = 0; i < attrs->length(); i++) {
2081 Attribute *attr = attrs->attributeItem(i);
2082
2083 if (attr->prefix() == xmlnsAtom &&
2084 attr->value() == _namespaceURI &&
2085 originalElement->lookupNamespaceURI(attr->localName()) == _namespaceURI)
2086 return attr->localName();
2087 }
2088 }
2089
2090 if (Element* ancestor = ancestorElement())
2091 return ancestor->lookupNamespacePrefix(_namespaceURI, originalElement);
2092 return String();
2093 }
2094
appendTextContent(const Node * node,bool convertBRsToNewlines,bool & isNullString,StringBuilder & content)2095 static void appendTextContent(const Node* node, bool convertBRsToNewlines, bool& isNullString, StringBuilder& content)
2096 {
2097 switch (node->nodeType()) {
2098 case Node::TEXT_NODE:
2099 case Node::CDATA_SECTION_NODE:
2100 case Node::COMMENT_NODE:
2101 isNullString = false;
2102 content.append(static_cast<const CharacterData*>(node)->data());
2103 break;
2104
2105 case Node::PROCESSING_INSTRUCTION_NODE:
2106 isNullString = false;
2107 content.append(static_cast<const ProcessingInstruction*>(node)->data());
2108 break;
2109
2110 case Node::ELEMENT_NODE:
2111 if (node->hasTagName(brTag) && convertBRsToNewlines) {
2112 isNullString = false;
2113 content.append('\n');
2114 break;
2115 }
2116 // Fall through.
2117 case Node::ATTRIBUTE_NODE:
2118 case Node::ENTITY_NODE:
2119 case Node::ENTITY_REFERENCE_NODE:
2120 case Node::DOCUMENT_FRAGMENT_NODE:
2121 isNullString = false;
2122 for (Node* child = node->firstChild(); child; child = child->nextSibling()) {
2123 if (child->nodeType() == Node::COMMENT_NODE || child->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
2124 continue;
2125 appendTextContent(child, convertBRsToNewlines, isNullString, content);
2126 }
2127 break;
2128
2129 case Node::DOCUMENT_NODE:
2130 case Node::DOCUMENT_TYPE_NODE:
2131 case Node::NOTATION_NODE:
2132 case Node::XPATH_NAMESPACE_NODE:
2133 break;
2134 }
2135 }
2136
textContent(bool convertBRsToNewlines) const2137 String Node::textContent(bool convertBRsToNewlines) const
2138 {
2139 StringBuilder content;
2140 bool isNullString = true;
2141 appendTextContent(this, convertBRsToNewlines, isNullString, content);
2142 return isNullString ? String() : content.toString();
2143 }
2144
setTextContent(const String & text,ExceptionCode & ec)2145 void Node::setTextContent(const String& text, ExceptionCode& ec)
2146 {
2147 switch (nodeType()) {
2148 case TEXT_NODE:
2149 case CDATA_SECTION_NODE:
2150 case COMMENT_NODE:
2151 case PROCESSING_INSTRUCTION_NODE:
2152 setNodeValue(text, ec);
2153 return;
2154 case ELEMENT_NODE:
2155 case ATTRIBUTE_NODE:
2156 case ENTITY_NODE:
2157 case ENTITY_REFERENCE_NODE:
2158 case DOCUMENT_FRAGMENT_NODE: {
2159 ContainerNode* container = toContainerNode(this);
2160 container->removeChildren();
2161 if (!text.isEmpty())
2162 container->appendChild(document()->createTextNode(text), ec);
2163 return;
2164 }
2165 case DOCUMENT_NODE:
2166 case DOCUMENT_TYPE_NODE:
2167 case NOTATION_NODE:
2168 case XPATH_NAMESPACE_NODE:
2169 // Do nothing.
2170 return;
2171 }
2172 ASSERT_NOT_REACHED();
2173 }
2174
ancestorElement() const2175 Element* Node::ancestorElement() const
2176 {
2177 // In theory, there can be EntityReference nodes between elements, but this is currently not supported.
2178 for (ContainerNode* n = parentNode(); n; n = n->parentNode()) {
2179 if (n->isElementNode())
2180 return static_cast<Element*>(n);
2181 }
2182 return 0;
2183 }
2184
offsetInCharacters() const2185 bool Node::offsetInCharacters() const
2186 {
2187 return false;
2188 }
2189
compareDocumentPosition(Node * otherNode)2190 unsigned short Node::compareDocumentPosition(Node* otherNode)
2191 {
2192 // It is not clear what should be done if |otherNode| is 0.
2193 if (!otherNode)
2194 return DOCUMENT_POSITION_DISCONNECTED;
2195
2196 if (otherNode == this)
2197 return DOCUMENT_POSITION_EQUIVALENT;
2198
2199 Attr* attr1 = nodeType() == ATTRIBUTE_NODE ? static_cast<Attr*>(this) : 0;
2200 Attr* attr2 = otherNode->nodeType() == ATTRIBUTE_NODE ? static_cast<Attr*>(otherNode) : 0;
2201
2202 Node* start1 = attr1 ? attr1->ownerElement() : this;
2203 Node* start2 = attr2 ? attr2->ownerElement() : otherNode;
2204
2205 // If either of start1 or start2 is null, then we are disconnected, since one of the nodes is
2206 // an orphaned attribute node.
2207 if (!start1 || !start2)
2208 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
2209
2210 Vector<Node*, 16> chain1;
2211 Vector<Node*, 16> chain2;
2212 if (attr1)
2213 chain1.append(attr1);
2214 if (attr2)
2215 chain2.append(attr2);
2216
2217 if (attr1 && attr2 && start1 == start2 && start1) {
2218 // We are comparing two attributes on the same node. Crawl our attribute map
2219 // and see which one we hit first.
2220 NamedNodeMap* map = attr1->ownerElement()->attributes(true);
2221 unsigned length = map->length();
2222 for (unsigned i = 0; i < length; ++i) {
2223 // If neither of the two determining nodes is a child node and nodeType is the same for both determining nodes, then an
2224 // implementation-dependent order between the determining nodes is returned. This order is stable as long as no nodes of
2225 // the same nodeType are inserted into or removed from the direct container. This would be the case, for example,
2226 // when comparing two attributes of the same element, and inserting or removing additional attributes might change
2227 // the order between existing attributes.
2228 Attribute* attr = map->attributeItem(i);
2229 if (attr1->attr() == attr)
2230 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING;
2231 if (attr2->attr() == attr)
2232 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_PRECEDING;
2233 }
2234
2235 ASSERT_NOT_REACHED();
2236 return DOCUMENT_POSITION_DISCONNECTED;
2237 }
2238
2239 // If one node is in the document and the other is not, we must be disconnected.
2240 // If the nodes have different owning documents, they must be disconnected. Note that we avoid
2241 // comparing Attr nodes here, since they return false from inDocument() all the time (which seems like a bug).
2242 if (start1->inDocument() != start2->inDocument() ||
2243 start1->document() != start2->document())
2244 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
2245
2246 // We need to find a common ancestor container, and then compare the indices of the two immediate children.
2247 Node* current;
2248 for (current = start1; current; current = current->parentNode())
2249 chain1.append(current);
2250 for (current = start2; current; current = current->parentNode())
2251 chain2.append(current);
2252
2253 // Walk the two chains backwards and look for the first difference.
2254 unsigned index1 = chain1.size();
2255 unsigned index2 = chain2.size();
2256 for (unsigned i = min(index1, index2); i; --i) {
2257 Node* child1 = chain1[--index1];
2258 Node* child2 = chain2[--index2];
2259 if (child1 != child2) {
2260 // If one of the children is an attribute, it wins.
2261 if (child1->nodeType() == ATTRIBUTE_NODE)
2262 return DOCUMENT_POSITION_FOLLOWING;
2263 if (child2->nodeType() == ATTRIBUTE_NODE)
2264 return DOCUMENT_POSITION_PRECEDING;
2265
2266 if (!child2->nextSibling())
2267 return DOCUMENT_POSITION_FOLLOWING;
2268 if (!child1->nextSibling())
2269 return DOCUMENT_POSITION_PRECEDING;
2270
2271 // Otherwise we need to see which node occurs first. Crawl backwards from child2 looking for child1.
2272 for (Node* child = child2->previousSibling(); child; child = child->previousSibling()) {
2273 if (child == child1)
2274 return DOCUMENT_POSITION_FOLLOWING;
2275 }
2276 return DOCUMENT_POSITION_PRECEDING;
2277 }
2278 }
2279
2280 // There was no difference between the two parent chains, i.e., one was a subset of the other. The shorter
2281 // chain is the ancestor.
2282 return index1 < index2 ?
2283 DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_CONTAINED_BY :
2284 DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_CONTAINS;
2285 }
2286
convertToPage(const FloatPoint & p) const2287 FloatPoint Node::convertToPage(const FloatPoint& p) const
2288 {
2289 // If there is a renderer, just ask it to do the conversion
2290 if (renderer())
2291 return renderer()->localToAbsolute(p, false, true);
2292
2293 // Otherwise go up the tree looking for a renderer
2294 Element *parent = ancestorElement();
2295 if (parent)
2296 return parent->convertToPage(p);
2297
2298 // No parent - no conversion needed
2299 return p;
2300 }
2301
convertFromPage(const FloatPoint & p) const2302 FloatPoint Node::convertFromPage(const FloatPoint& p) const
2303 {
2304 // If there is a renderer, just ask it to do the conversion
2305 if (renderer())
2306 return renderer()->absoluteToLocal(p, false, true);
2307
2308 // Otherwise go up the tree looking for a renderer
2309 Element *parent = ancestorElement();
2310 if (parent)
2311 return parent->convertFromPage(p);
2312
2313 // No parent - no conversion needed
2314 return p;
2315 }
2316
2317 #if !defined(NDEBUG) || defined(ANDROID_DOM_LOGGING)
2318
appendAttributeDesc(const Node * node,String & string,const QualifiedName & name,const char * attrDesc)2319 static void appendAttributeDesc(const Node* node, String& string, const QualifiedName& name, const char* attrDesc)
2320 {
2321 if (node->isElementNode()) {
2322 String attr = static_cast<const Element*>(node)->getAttribute(name);
2323 if (!attr.isEmpty()) {
2324 string += attrDesc;
2325 string += attr;
2326 }
2327 }
2328 }
2329
showNode(const char * prefix) const2330 void Node::showNode(const char* prefix) const
2331 {
2332 if (!prefix)
2333 prefix = "";
2334 if (isTextNode()) {
2335 String value = nodeValue();
2336 #ifdef ANDROID_DOM_LOGGING
2337 bool hasNoneWhitespace = false;
2338 for (int i = value.length()-1; i >= 0; i--)
2339 if (!isSpaceOrNewline(value[i])) {
2340 hasNoneWhitespace = true;
2341 break;
2342 }
2343 #endif
2344 value.replace('\\', "\\\\");
2345 value.replace('\n', "\\n");
2346 #ifdef ANDROID_DOM_LOGGING
2347 if (hasNoneWhitespace)
2348 DUMP_DOM_LOGD("%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this, value.utf8().data());
2349 #else
2350 fprintf(stderr, "%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this, value.utf8().data());
2351 #endif
2352 } else {
2353 String attrs = "";
2354 appendAttributeDesc(this, attrs, classAttr, " CLASS=");
2355 appendAttributeDesc(this, attrs, styleAttr, " STYLE=");
2356 #ifdef ANDROID_DOM_LOGGING
2357 appendAttributeDesc(this, attrs, idAttr, " ID=");
2358 appendAttributeDesc(this, attrs, nameAttr, " NAME=");
2359 DUMP_DOM_LOGD("%s%s\t%p%s\n", prefix, nodeName().utf8().data(), this, attrs.utf8().data());
2360 #else
2361 fprintf(stderr, "%s%s\t%p%s\n", prefix, nodeName().utf8().data(), this, attrs.utf8().data());
2362 #endif
2363 }
2364 }
2365
showTreeForThis() const2366 void Node::showTreeForThis() const
2367 {
2368 showTreeAndMark(this, "*");
2369 }
2370
showTreeAndMark(const Node * markedNode1,const char * markedLabel1,const Node * markedNode2,const char * markedLabel2) const2371 void Node::showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char * markedLabel2) const
2372 {
2373 const Node* rootNode;
2374 const Node* node = this;
2375 while (node->parentNode() && !node->hasTagName(bodyTag))
2376 node = node->parentNode();
2377 rootNode = node;
2378
2379 for (node = rootNode; node; node = node->traverseNextNode()) {
2380 #ifdef ANDROID_DOM_LOGGING
2381 String prefix = "";
2382 #endif
2383 if (node == markedNode1)
2384 #ifdef ANDROID_DOM_LOGGING
2385 prefix.append(markedLabel1);
2386 #else
2387 fprintf(stderr, "%s", markedLabel1);
2388 #endif
2389 if (node == markedNode2)
2390 #ifdef ANDROID_DOM_LOGGING
2391 prefix.append(markedLabel2);
2392 #else
2393 fprintf(stderr, "%s", markedLabel2);
2394 #endif
2395
2396 #ifdef ANDROID_DOM_LOGGING
2397 for (const Node* tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentNode())
2398 prefix.append("\t");
2399 node->showNode(prefix.utf8().data());
2400 #else
2401 for (const Node* tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentNode())
2402 fprintf(stderr, "\t");
2403 node->showNode();
2404 #endif
2405 }
2406 }
2407
formatForDebugger(char * buffer,unsigned length) const2408 void Node::formatForDebugger(char* buffer, unsigned length) const
2409 {
2410 String result;
2411 String s;
2412
2413 s = nodeName();
2414 if (s.length() == 0)
2415 result += "<none>";
2416 else
2417 result += s;
2418
2419 strncpy(buffer, result.utf8().data(), length - 1);
2420 }
2421
2422 #endif
2423
2424 // --------
2425
invalidateCaches()2426 void NodeListsNodeData::invalidateCaches()
2427 {
2428 m_childNodeListCaches->reset();
2429
2430 if (m_labelsNodeListCache)
2431 m_labelsNodeListCache->invalidateCache();
2432 TagNodeListCache::const_iterator tagCacheEnd = m_tagNodeListCache.end();
2433 for (TagNodeListCache::const_iterator it = m_tagNodeListCache.begin(); it != tagCacheEnd; ++it)
2434 it->second->invalidateCache();
2435 invalidateCachesThatDependOnAttributes();
2436 }
2437
invalidateCachesThatDependOnAttributes()2438 void NodeListsNodeData::invalidateCachesThatDependOnAttributes()
2439 {
2440 ClassNodeListCache::iterator classCacheEnd = m_classNodeListCache.end();
2441 for (ClassNodeListCache::iterator it = m_classNodeListCache.begin(); it != classCacheEnd; ++it)
2442 it->second->invalidateCache();
2443
2444 NameNodeListCache::iterator nameCacheEnd = m_nameNodeListCache.end();
2445 for (NameNodeListCache::iterator it = m_nameNodeListCache.begin(); it != nameCacheEnd; ++it)
2446 it->second->invalidateCache();
2447 if (m_labelsNodeListCache)
2448 m_labelsNodeListCache->invalidateCache();
2449 }
2450
isEmpty() const2451 bool NodeListsNodeData::isEmpty() const
2452 {
2453 if (!m_listsWithCaches.isEmpty())
2454 return false;
2455
2456 if (m_childNodeListCaches->refCount())
2457 return false;
2458
2459 TagNodeListCache::const_iterator tagCacheEnd = m_tagNodeListCache.end();
2460 for (TagNodeListCache::const_iterator it = m_tagNodeListCache.begin(); it != tagCacheEnd; ++it) {
2461 if (it->second->refCount())
2462 return false;
2463 }
2464
2465 ClassNodeListCache::const_iterator classCacheEnd = m_classNodeListCache.end();
2466 for (ClassNodeListCache::const_iterator it = m_classNodeListCache.begin(); it != classCacheEnd; ++it) {
2467 if (it->second->refCount())
2468 return false;
2469 }
2470
2471 NameNodeListCache::const_iterator nameCacheEnd = m_nameNodeListCache.end();
2472 for (NameNodeListCache::const_iterator it = m_nameNodeListCache.begin(); it != nameCacheEnd; ++it) {
2473 if (it->second->refCount())
2474 return false;
2475 }
2476
2477 if (m_labelsNodeListCache)
2478 return false;
2479
2480 return true;
2481 }
2482
getSubresourceURLs(ListHashSet<KURL> & urls) const2483 void Node::getSubresourceURLs(ListHashSet<KURL>& urls) const
2484 {
2485 addSubresourceAttributeURLs(urls);
2486 }
2487
enclosingLinkEventParentOrSelf()2488 Node* Node::enclosingLinkEventParentOrSelf()
2489 {
2490 for (Node* node = this; node; node = node->parentOrHostNode()) {
2491 // For imagemaps, the enclosing link node is the associated area element not the image itself.
2492 // So we don't let images be the enclosingLinkNode, even though isLink sometimes returns true
2493 // for them.
2494 if (node->isLink() && !node->hasTagName(imgTag))
2495 return node;
2496 }
2497
2498 return 0;
2499 }
2500
2501 // --------
2502
scriptExecutionContext() const2503 ScriptExecutionContext* Node::scriptExecutionContext() const
2504 {
2505 return document();
2506 }
2507
insertedIntoDocument()2508 void Node::insertedIntoDocument()
2509 {
2510 setInDocument();
2511 }
2512
removedFromDocument()2513 void Node::removedFromDocument()
2514 {
2515 clearInDocument();
2516 }
2517
willMoveToNewOwnerDocument()2518 void Node::willMoveToNewOwnerDocument()
2519 {
2520 ASSERT(!willMoveToNewOwnerDocumentWasCalled);
2521 setWillMoveToNewOwnerDocumentWasCalled(true);
2522 }
2523
didMoveToNewOwnerDocument()2524 void Node::didMoveToNewOwnerDocument()
2525 {
2526 ASSERT(!didMoveToNewOwnerDocumentWasCalled);
2527 setDidMoveToNewOwnerDocumentWasCalled(true);
2528 }
2529
2530 #if ENABLE(SVG)
instancesForSVGElement(Node * node)2531 static inline HashSet<SVGElementInstance*> instancesForSVGElement(Node* node)
2532 {
2533 HashSet<SVGElementInstance*> instances;
2534
2535 ASSERT(node);
2536 if (!node->isSVGElement() || node->shadowTreeRootNode())
2537 return HashSet<SVGElementInstance*>();
2538
2539 SVGElement* element = static_cast<SVGElement*>(node);
2540 if (!element->isStyled())
2541 return HashSet<SVGElementInstance*>();
2542
2543 SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(element);
2544 ASSERT(!styledElement->instanceUpdatesBlocked());
2545
2546 return styledElement->instancesForElement();
2547 }
2548 #endif
2549
tryAddEventListener(Node * targetNode,const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)2550 static inline bool tryAddEventListener(Node* targetNode, const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
2551 {
2552 if (!targetNode->EventTarget::addEventListener(eventType, listener, useCapture))
2553 return false;
2554
2555 if (Document* document = targetNode->document())
2556 document->addListenerTypeIfNeeded(eventType);
2557
2558 return true;
2559 }
2560
addEventListener(const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)2561 bool Node::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
2562 {
2563 #if !ENABLE(SVG)
2564 return tryAddEventListener(this, eventType, listener, useCapture);
2565 #else
2566 if (!isSVGElement())
2567 return tryAddEventListener(this, eventType, listener, useCapture);
2568
2569 HashSet<SVGElementInstance*> instances = instancesForSVGElement(this);
2570 if (instances.isEmpty())
2571 return tryAddEventListener(this, eventType, listener, useCapture);
2572
2573 RefPtr<EventListener> listenerForRegularTree = listener;
2574 RefPtr<EventListener> listenerForShadowTree = listenerForRegularTree;
2575
2576 // Add event listener to regular DOM element
2577 if (!tryAddEventListener(this, eventType, listenerForRegularTree.release(), useCapture))
2578 return false;
2579
2580 // Add event listener to all shadow tree DOM element instances
2581 const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
2582 for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
2583 ASSERT((*it)->shadowTreeElement());
2584 ASSERT((*it)->correspondingElement() == this);
2585
2586 RefPtr<EventListener> listenerForCurrentShadowTreeElement = listenerForShadowTree;
2587 bool result = tryAddEventListener((*it)->shadowTreeElement(), eventType, listenerForCurrentShadowTreeElement.release(), useCapture);
2588 ASSERT_UNUSED(result, result);
2589 }
2590
2591 return true;
2592 #endif
2593 }
2594
tryRemoveEventListener(Node * targetNode,const AtomicString & eventType,EventListener * listener,bool useCapture)2595 static inline bool tryRemoveEventListener(Node* targetNode, const AtomicString& eventType, EventListener* listener, bool useCapture)
2596 {
2597 if (!targetNode->EventTarget::removeEventListener(eventType, listener, useCapture))
2598 return false;
2599
2600 // FIXME: Notify Document that the listener has vanished. We need to keep track of a number of
2601 // listeners for each type, not just a bool - see https://bugs.webkit.org/show_bug.cgi?id=33861
2602
2603 return true;
2604 }
2605
removeEventListener(const AtomicString & eventType,EventListener * listener,bool useCapture)2606 bool Node::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
2607 {
2608 #if !ENABLE(SVG)
2609 return tryRemoveEventListener(this, eventType, listener, useCapture);
2610 #else
2611 if (!isSVGElement())
2612 return tryRemoveEventListener(this, eventType, listener, useCapture);
2613
2614 HashSet<SVGElementInstance*> instances = instancesForSVGElement(this);
2615 if (instances.isEmpty())
2616 return tryRemoveEventListener(this, eventType, listener, useCapture);
2617
2618 // EventTarget::removeEventListener creates a PassRefPtr around the given EventListener
2619 // object when creating a temporary RegisteredEventListener object used to look up the
2620 // event listener in a cache. If we want to be able to call removeEventListener() multiple
2621 // times on different nodes, we have to delay its immediate destruction, which would happen
2622 // after the first call below.
2623 RefPtr<EventListener> protector(listener);
2624
2625 // Remove event listener from regular DOM element
2626 if (!tryRemoveEventListener(this, eventType, listener, useCapture))
2627 return false;
2628
2629 // Remove event listener from all shadow tree DOM element instances
2630 const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
2631 for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
2632 ASSERT((*it)->correspondingElement() == this);
2633
2634 SVGElement* shadowTreeElement = (*it)->shadowTreeElement();
2635 ASSERT(shadowTreeElement);
2636
2637 if (tryRemoveEventListener(shadowTreeElement, eventType, listener, useCapture))
2638 continue;
2639
2640 // This case can only be hit for event listeners created from markup
2641 ASSERT(listener->wasCreatedFromMarkup());
2642
2643 // If the event listener 'listener' has been created from markup and has been fired before
2644 // then JSLazyEventListener::parseCode() has been called and m_jsFunction of that listener
2645 // has been created (read: it's not 0 anymore). During shadow tree creation, the event
2646 // listener DOM attribute has been cloned, and another event listener has been setup in
2647 // the shadow tree. If that event listener has not been used yet, m_jsFunction is still 0,
2648 // and tryRemoveEventListener() above will fail. Work around that very seldom problem.
2649 EventTargetData* data = shadowTreeElement->eventTargetData();
2650 ASSERT(data);
2651
2652 EventListenerMap::iterator result = data->eventListenerMap.find(eventType);
2653 ASSERT(result != data->eventListenerMap.end());
2654
2655 EventListenerVector* entry = result->second;
2656 ASSERT(entry);
2657
2658 unsigned int index = 0;
2659 bool foundListener = false;
2660
2661 EventListenerVector::iterator end = entry->end();
2662 for (EventListenerVector::iterator it = entry->begin(); it != end; ++it) {
2663 if (!(*it).listener->wasCreatedFromMarkup()) {
2664 ++index;
2665 continue;
2666 }
2667
2668 foundListener = true;
2669 entry->remove(index);
2670 break;
2671 }
2672
2673 ASSERT(foundListener);
2674
2675 if (entry->isEmpty()) {
2676 delete entry;
2677 data->eventListenerMap.remove(result);
2678 }
2679 }
2680
2681 return true;
2682 #endif
2683 }
2684
eventTargetData()2685 EventTargetData* Node::eventTargetData()
2686 {
2687 return hasRareData() ? rareData()->eventTargetData() : 0;
2688 }
2689
ensureEventTargetData()2690 EventTargetData* Node::ensureEventTargetData()
2691 {
2692 return ensureRareData()->ensureEventTargetData();
2693 }
2694
handleLocalEvents(Event * event)2695 void Node::handleLocalEvents(Event* event)
2696 {
2697 if (!hasRareData() || !rareData()->eventTargetData())
2698 return;
2699
2700 if (disabled() && event->isMouseEvent())
2701 return;
2702
2703 fireEventListeners(event);
2704 }
2705
dispatchScopedEvent(PassRefPtr<Event> event)2706 void Node::dispatchScopedEvent(PassRefPtr<Event> event)
2707 {
2708 EventDispatcher::dispatchScopedEvent(this, event);
2709 }
2710
dispatchEvent(PassRefPtr<Event> event)2711 bool Node::dispatchEvent(PassRefPtr<Event> event)
2712 {
2713 return EventDispatcher::dispatchEvent(this, EventDispatchMediator(event));
2714 }
2715
dispatchSubtreeModifiedEvent()2716 void Node::dispatchSubtreeModifiedEvent()
2717 {
2718 ASSERT(!eventDispatchForbidden());
2719
2720 document()->incDOMTreeVersion();
2721
2722 notifyNodeListsAttributeChanged(); // FIXME: Can do better some day. Really only care about the name attribute changing.
2723
2724 if (!document()->hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER))
2725 return;
2726
2727 dispatchScopedEvent(MutationEvent::create(eventNames().DOMSubtreeModifiedEvent, true));
2728 }
2729
dispatchUIEvent(const AtomicString & eventType,int detail,PassRefPtr<Event> underlyingEvent)2730 void Node::dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr<Event> underlyingEvent)
2731 {
2732 ASSERT(!eventDispatchForbidden());
2733 ASSERT(eventType == eventNames().focusinEvent || eventType == eventNames().focusoutEvent ||
2734 eventType == eventNames().DOMFocusInEvent || eventType == eventNames().DOMFocusOutEvent || eventType == eventNames().DOMActivateEvent);
2735
2736 bool cancelable = eventType == eventNames().DOMActivateEvent;
2737
2738 RefPtr<UIEvent> event = UIEvent::create(eventType, true, cancelable, document()->defaultView(), detail);
2739 event->setUnderlyingEvent(underlyingEvent);
2740 dispatchScopedEvent(event.release());
2741 }
2742
dispatchKeyEvent(const PlatformKeyboardEvent & event)2743 bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& event)
2744 {
2745 return EventDispatcher::dispatchEvent(this, KeyboardEventDispatchMediator(KeyboardEvent::create(event, document()->defaultView())));
2746 }
2747
dispatchMouseEvent(const PlatformMouseEvent & event,const AtomicString & eventType,int detail,Node * relatedTarget)2748 bool Node::dispatchMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType,
2749 int detail, Node* relatedTarget)
2750 {
2751 return EventDispatcher::dispatchEvent(this, MouseEventDispatchMediator(MouseEvent::create(eventType, document()->defaultView(), event, detail, relatedTarget)));
2752 }
2753
dispatchSimulatedClick(PassRefPtr<Event> event,bool sendMouseEvents,bool showPressedLook)2754 void Node::dispatchSimulatedClick(PassRefPtr<Event> event, bool sendMouseEvents, bool showPressedLook)
2755 {
2756 EventDispatcher::dispatchSimulatedClick(this, event, sendMouseEvents, showPressedLook);
2757 }
2758
dispatchWheelEvent(const PlatformWheelEvent & event)2759 bool Node::dispatchWheelEvent(const PlatformWheelEvent& event)
2760 {
2761 return EventDispatcher::dispatchEvent(this, WheelEventDispatchMediator(event, document()->defaultView()));
2762 }
2763
dispatchFocusEvent()2764 void Node::dispatchFocusEvent()
2765 {
2766 dispatchEvent(Event::create(eventNames().focusEvent, false, false));
2767 }
2768
dispatchBlurEvent()2769 void Node::dispatchBlurEvent()
2770 {
2771 dispatchEvent(Event::create(eventNames().blurEvent, false, false));
2772 }
2773
dispatchChangeEvent()2774 void Node::dispatchChangeEvent()
2775 {
2776 dispatchEvent(Event::create(eventNames().changeEvent, true, false));
2777 }
2778
dispatchInputEvent()2779 void Node::dispatchInputEvent()
2780 {
2781 dispatchEvent(Event::create(eventNames().inputEvent, true, false));
2782 }
2783
disabled() const2784 bool Node::disabled() const
2785 {
2786 return false;
2787 }
2788
defaultEventHandler(Event * event)2789 void Node::defaultEventHandler(Event* event)
2790 {
2791 if (event->target() != this)
2792 return;
2793 const AtomicString& eventType = event->type();
2794 if (eventType == eventNames().keydownEvent || eventType == eventNames().keypressEvent) {
2795 if (event->isKeyboardEvent())
2796 if (Frame* frame = document()->frame())
2797 frame->eventHandler()->defaultKeyboardEventHandler(static_cast<KeyboardEvent*>(event));
2798 } else if (eventType == eventNames().clickEvent) {
2799 int detail = event->isUIEvent() ? static_cast<UIEvent*>(event)->detail() : 0;
2800 dispatchUIEvent(eventNames().DOMActivateEvent, detail, event);
2801 #if ENABLE(CONTEXT_MENUS)
2802 } else if (eventType == eventNames().contextmenuEvent) {
2803 if (Frame* frame = document()->frame())
2804 if (Page* page = frame->page())
2805 page->contextMenuController()->handleContextMenuEvent(event);
2806 #endif
2807 } else if (eventType == eventNames().textInputEvent) {
2808 if (event->isTextEvent())
2809 if (Frame* frame = document()->frame())
2810 frame->eventHandler()->defaultTextInputEventHandler(static_cast<TextEvent*>(event));
2811 #if ENABLE(PAN_SCROLLING)
2812 } else if (eventType == eventNames().mousedownEvent && event->isMouseEvent()) {
2813 MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
2814 if (mouseEvent->button() == MiddleButton) {
2815 if (enclosingLinkEventParentOrSelf())
2816 return;
2817
2818 RenderObject* renderer = this->renderer();
2819 while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()))
2820 renderer = renderer->parent();
2821
2822 if (renderer) {
2823 if (Frame* frame = document()->frame())
2824 frame->eventHandler()->startPanScrolling(renderer);
2825 }
2826 }
2827 #endif
2828 } else if (eventType == eventNames().mousewheelEvent && event->isWheelEvent()) {
2829 WheelEvent* wheelEvent = static_cast<WheelEvent*>(event);
2830
2831 // If we don't have a renderer, send the wheel event to the first node we find with a renderer.
2832 // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll.
2833 Node* startNode = this;
2834 while (startNode && !startNode->renderer())
2835 startNode = startNode->parentOrHostNode();
2836
2837 if (startNode && startNode->renderer())
2838 if (Frame* frame = document()->frame())
2839 frame->eventHandler()->defaultWheelEventHandler(startNode, wheelEvent);
2840 } else if (event->type() == eventNames().webkitEditableContentChangedEvent) {
2841 dispatchInputEvent();
2842 }
2843 }
2844
2845 } // namespace WebCore
2846
2847 #ifndef NDEBUG
2848
showTree(const WebCore::Node * node)2849 void showTree(const WebCore::Node* node)
2850 {
2851 if (node)
2852 node->showTreeForThis();
2853 }
2854
2855 #endif
2856