• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()->inDesignMode() || (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()1617 Node* Node::shadowAncestorNode()
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 this;
1626 #endif
1627 
1628     Node* root = shadowTreeRootNode();
1629     if (root)
1630         return root->shadowHost();
1631     return this;
1632 }
1633 
shadowTreeRootNode()1634 Node* Node::shadowTreeRootNode()
1635 {
1636     Node* root = 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 #ifdef ANDROID_INSTRUMENT
2502 static size_t nodeSize = 0;
2503 
operator new(size_t size)2504 void* Node::operator new(size_t size)
2505 {
2506     nodeSize += size;
2507     return ::operator new(size);
2508 }
2509 
operator new[](size_t size)2510 void* Node::operator new[](size_t size)
2511 {
2512     nodeSize += size;
2513     return ::operator new[](size);
2514 }
2515 
operator delete(void * p,size_t size)2516 void Node::operator delete(void* p, size_t size)
2517 {
2518     nodeSize -= size;
2519     ::operator delete(p);
2520 }
2521 
operator delete[](void * p,size_t size)2522 void Node::operator delete[](void* p, size_t size)
2523 {
2524     nodeSize -= size;
2525     ::operator delete[](p);
2526 }
2527 
reportDOMNodesSize()2528 size_t Node::reportDOMNodesSize()
2529 {
2530     return nodeSize;
2531 }
2532 #endif
2533 
2534 // --------
2535 
scriptExecutionContext() const2536 ScriptExecutionContext* Node::scriptExecutionContext() const
2537 {
2538     return document();
2539 }
2540 
insertedIntoDocument()2541 void Node::insertedIntoDocument()
2542 {
2543     setInDocument();
2544 }
2545 
removedFromDocument()2546 void Node::removedFromDocument()
2547 {
2548     clearInDocument();
2549 }
2550 
willMoveToNewOwnerDocument()2551 void Node::willMoveToNewOwnerDocument()
2552 {
2553     ASSERT(!willMoveToNewOwnerDocumentWasCalled);
2554     setWillMoveToNewOwnerDocumentWasCalled(true);
2555 }
2556 
didMoveToNewOwnerDocument()2557 void Node::didMoveToNewOwnerDocument()
2558 {
2559     ASSERT(!didMoveToNewOwnerDocumentWasCalled);
2560     setDidMoveToNewOwnerDocumentWasCalled(true);
2561 }
2562 
2563 #if ENABLE(SVG)
instancesForSVGElement(Node * node)2564 static inline HashSet<SVGElementInstance*> instancesForSVGElement(Node* node)
2565 {
2566     HashSet<SVGElementInstance*> instances;
2567 
2568     ASSERT(node);
2569     if (!node->isSVGElement() || node->shadowTreeRootNode())
2570         return HashSet<SVGElementInstance*>();
2571 
2572     SVGElement* element = static_cast<SVGElement*>(node);
2573     if (!element->isStyled())
2574         return HashSet<SVGElementInstance*>();
2575 
2576     SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(element);
2577     ASSERT(!styledElement->instanceUpdatesBlocked());
2578 
2579     return styledElement->instancesForElement();
2580 }
2581 #endif
2582 
tryAddEventListener(Node * targetNode,const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)2583 static inline bool tryAddEventListener(Node* targetNode, const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
2584 {
2585     if (!targetNode->EventTarget::addEventListener(eventType, listener, useCapture))
2586         return false;
2587 
2588     if (Document* document = targetNode->document())
2589         document->addListenerTypeIfNeeded(eventType);
2590 
2591     return true;
2592 }
2593 
addEventListener(const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)2594 bool Node::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
2595 {
2596 #if !ENABLE(SVG)
2597     return tryAddEventListener(this, eventType, listener, useCapture);
2598 #else
2599     if (!isSVGElement())
2600         return tryAddEventListener(this, eventType, listener, useCapture);
2601 
2602     HashSet<SVGElementInstance*> instances = instancesForSVGElement(this);
2603     if (instances.isEmpty())
2604         return tryAddEventListener(this, eventType, listener, useCapture);
2605 
2606     RefPtr<EventListener> listenerForRegularTree = listener;
2607     RefPtr<EventListener> listenerForShadowTree = listenerForRegularTree;
2608 
2609     // Add event listener to regular DOM element
2610     if (!tryAddEventListener(this, eventType, listenerForRegularTree.release(), useCapture))
2611         return false;
2612 
2613     // Add event listener to all shadow tree DOM element instances
2614     const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
2615     for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
2616         ASSERT((*it)->shadowTreeElement());
2617         ASSERT((*it)->correspondingElement() == this);
2618 
2619         RefPtr<EventListener> listenerForCurrentShadowTreeElement = listenerForShadowTree;
2620         bool result = tryAddEventListener((*it)->shadowTreeElement(), eventType, listenerForCurrentShadowTreeElement.release(), useCapture);
2621         ASSERT_UNUSED(result, result);
2622     }
2623 
2624     return true;
2625 #endif
2626 }
2627 
tryRemoveEventListener(Node * targetNode,const AtomicString & eventType,EventListener * listener,bool useCapture)2628 static inline bool tryRemoveEventListener(Node* targetNode, const AtomicString& eventType, EventListener* listener, bool useCapture)
2629 {
2630     if (!targetNode->EventTarget::removeEventListener(eventType, listener, useCapture))
2631         return false;
2632 
2633     // FIXME: Notify Document that the listener has vanished. We need to keep track of a number of
2634     // listeners for each type, not just a bool - see https://bugs.webkit.org/show_bug.cgi?id=33861
2635 
2636     return true;
2637 }
2638 
removeEventListener(const AtomicString & eventType,EventListener * listener,bool useCapture)2639 bool Node::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
2640 {
2641 #if !ENABLE(SVG)
2642     return tryRemoveEventListener(this, eventType, listener, useCapture);
2643 #else
2644     if (!isSVGElement())
2645         return tryRemoveEventListener(this, eventType, listener, useCapture);
2646 
2647     HashSet<SVGElementInstance*> instances = instancesForSVGElement(this);
2648     if (instances.isEmpty())
2649         return tryRemoveEventListener(this, eventType, listener, useCapture);
2650 
2651     // EventTarget::removeEventListener creates a PassRefPtr around the given EventListener
2652     // object when creating a temporary RegisteredEventListener object used to look up the
2653     // event listener in a cache. If we want to be able to call removeEventListener() multiple
2654     // times on different nodes, we have to delay its immediate destruction, which would happen
2655     // after the first call below.
2656     RefPtr<EventListener> protector(listener);
2657 
2658     // Remove event listener from regular DOM element
2659     if (!tryRemoveEventListener(this, eventType, listener, useCapture))
2660         return false;
2661 
2662     // Remove event listener from all shadow tree DOM element instances
2663     const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
2664     for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
2665         ASSERT((*it)->correspondingElement() == this);
2666 
2667         SVGElement* shadowTreeElement = (*it)->shadowTreeElement();
2668         ASSERT(shadowTreeElement);
2669 
2670         if (tryRemoveEventListener(shadowTreeElement, eventType, listener, useCapture))
2671             continue;
2672 
2673         // This case can only be hit for event listeners created from markup
2674         ASSERT(listener->wasCreatedFromMarkup());
2675 
2676         // If the event listener 'listener' has been created from markup and has been fired before
2677         // then JSLazyEventListener::parseCode() has been called and m_jsFunction of that listener
2678         // has been created (read: it's not 0 anymore). During shadow tree creation, the event
2679         // listener DOM attribute has been cloned, and another event listener has been setup in
2680         // the shadow tree. If that event listener has not been used yet, m_jsFunction is still 0,
2681         // and tryRemoveEventListener() above will fail. Work around that very seldom problem.
2682         EventTargetData* data = shadowTreeElement->eventTargetData();
2683         ASSERT(data);
2684 
2685         EventListenerMap::iterator result = data->eventListenerMap.find(eventType);
2686         ASSERT(result != data->eventListenerMap.end());
2687 
2688         EventListenerVector* entry = result->second;
2689         ASSERT(entry);
2690 
2691         unsigned int index = 0;
2692         bool foundListener = false;
2693 
2694         EventListenerVector::iterator end = entry->end();
2695         for (EventListenerVector::iterator it = entry->begin(); it != end; ++it) {
2696             if (!(*it).listener->wasCreatedFromMarkup()) {
2697                 ++index;
2698                 continue;
2699             }
2700 
2701             foundListener = true;
2702             entry->remove(index);
2703             break;
2704         }
2705 
2706         ASSERT(foundListener);
2707 
2708         if (entry->isEmpty()) {
2709             delete entry;
2710             data->eventListenerMap.remove(result);
2711         }
2712     }
2713 
2714     return true;
2715 #endif
2716 }
2717 
eventTargetData()2718 EventTargetData* Node::eventTargetData()
2719 {
2720     return hasRareData() ? rareData()->eventTargetData() : 0;
2721 }
2722 
ensureEventTargetData()2723 EventTargetData* Node::ensureEventTargetData()
2724 {
2725     return ensureRareData()->ensureEventTargetData();
2726 }
2727 
handleLocalEvents(Event * event)2728 void Node::handleLocalEvents(Event* event)
2729 {
2730     if (!hasRareData() || !rareData()->eventTargetData())
2731         return;
2732 
2733     if (disabled() && event->isMouseEvent())
2734         return;
2735 
2736     fireEventListeners(event);
2737 }
2738 
dispatchScopedEvent(PassRefPtr<Event> event)2739 void Node::dispatchScopedEvent(PassRefPtr<Event> event)
2740 {
2741     EventDispatcher::dispatchScopedEvent(this, event);
2742 }
2743 
dispatchEvent(PassRefPtr<Event> event)2744 bool Node::dispatchEvent(PassRefPtr<Event> event)
2745 {
2746     return EventDispatcher::dispatchEvent(this, EventDispatchMediator(event));
2747 }
2748 
dispatchSubtreeModifiedEvent()2749 void Node::dispatchSubtreeModifiedEvent()
2750 {
2751     ASSERT(!eventDispatchForbidden());
2752 
2753     document()->incDOMTreeVersion();
2754 
2755     notifyNodeListsAttributeChanged(); // FIXME: Can do better some day. Really only care about the name attribute changing.
2756 
2757     if (!document()->hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER))
2758         return;
2759 
2760     dispatchScopedEvent(MutationEvent::create(eventNames().DOMSubtreeModifiedEvent, true));
2761 }
2762 
dispatchUIEvent(const AtomicString & eventType,int detail,PassRefPtr<Event> underlyingEvent)2763 void Node::dispatchUIEvent(const AtomicString& eventType, int detail, PassRefPtr<Event> underlyingEvent)
2764 {
2765     ASSERT(!eventDispatchForbidden());
2766     ASSERT(eventType == eventNames().focusinEvent || eventType == eventNames().focusoutEvent ||
2767            eventType == eventNames().DOMFocusInEvent || eventType == eventNames().DOMFocusOutEvent || eventType == eventNames().DOMActivateEvent);
2768 
2769     bool cancelable = eventType == eventNames().DOMActivateEvent;
2770 
2771     RefPtr<UIEvent> event = UIEvent::create(eventType, true, cancelable, document()->defaultView(), detail);
2772     event->setUnderlyingEvent(underlyingEvent);
2773     dispatchScopedEvent(event.release());
2774 }
2775 
dispatchKeyEvent(const PlatformKeyboardEvent & event)2776 bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& event)
2777 {
2778     return EventDispatcher::dispatchEvent(this, KeyboardEventDispatchMediator(KeyboardEvent::create(event, document()->defaultView())));
2779 }
2780 
dispatchMouseEvent(const PlatformMouseEvent & event,const AtomicString & eventType,int detail,Node * relatedTarget)2781 bool Node::dispatchMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType,
2782     int detail, Node* relatedTarget)
2783 {
2784     return EventDispatcher::dispatchEvent(this, MouseEventDispatchMediator(MouseEvent::create(eventType, document()->defaultView(), event, detail, relatedTarget)));
2785 }
2786 
dispatchSimulatedClick(PassRefPtr<Event> event,bool sendMouseEvents,bool showPressedLook)2787 void Node::dispatchSimulatedClick(PassRefPtr<Event> event, bool sendMouseEvents, bool showPressedLook)
2788 {
2789     EventDispatcher::dispatchSimulatedClick(this, event, sendMouseEvents, showPressedLook);
2790 }
2791 
dispatchWheelEvent(const PlatformWheelEvent & event)2792 bool Node::dispatchWheelEvent(const PlatformWheelEvent& event)
2793 {
2794     return EventDispatcher::dispatchEvent(this, WheelEventDispatchMediator(event, document()->defaultView()));
2795 }
2796 
dispatchFocusEvent()2797 void Node::dispatchFocusEvent()
2798 {
2799     dispatchEvent(Event::create(eventNames().focusEvent, false, false));
2800 }
2801 
dispatchBlurEvent()2802 void Node::dispatchBlurEvent()
2803 {
2804     dispatchEvent(Event::create(eventNames().blurEvent, false, false));
2805 }
2806 
dispatchChangeEvent()2807 void Node::dispatchChangeEvent()
2808 {
2809     dispatchEvent(Event::create(eventNames().changeEvent, true, false));
2810 }
2811 
dispatchInputEvent()2812 void Node::dispatchInputEvent()
2813 {
2814     dispatchEvent(Event::create(eventNames().inputEvent, true, false));
2815 }
2816 
disabled() const2817 bool Node::disabled() const
2818 {
2819     return false;
2820 }
2821 
defaultEventHandler(Event * event)2822 void Node::defaultEventHandler(Event* event)
2823 {
2824     if (event->target() != this)
2825         return;
2826     const AtomicString& eventType = event->type();
2827     if (eventType == eventNames().keydownEvent || eventType == eventNames().keypressEvent) {
2828         if (event->isKeyboardEvent())
2829             if (Frame* frame = document()->frame())
2830                 frame->eventHandler()->defaultKeyboardEventHandler(static_cast<KeyboardEvent*>(event));
2831     } else if (eventType == eventNames().clickEvent) {
2832         int detail = event->isUIEvent() ? static_cast<UIEvent*>(event)->detail() : 0;
2833         dispatchUIEvent(eventNames().DOMActivateEvent, detail, event);
2834 #if ENABLE(CONTEXT_MENUS)
2835     } else if (eventType == eventNames().contextmenuEvent) {
2836         if (Frame* frame = document()->frame())
2837             if (Page* page = frame->page())
2838                 page->contextMenuController()->handleContextMenuEvent(event);
2839 #endif
2840     } else if (eventType == eventNames().textInputEvent) {
2841         if (event->isTextEvent())
2842             if (Frame* frame = document()->frame())
2843                 frame->eventHandler()->defaultTextInputEventHandler(static_cast<TextEvent*>(event));
2844 #if ENABLE(PAN_SCROLLING)
2845     } else if (eventType == eventNames().mousedownEvent && event->isMouseEvent()) {
2846         MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
2847         if (mouseEvent->button() == MiddleButton) {
2848             if (enclosingLinkEventParentOrSelf())
2849                 return;
2850 
2851             RenderObject* renderer = this->renderer();
2852             while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()))
2853                 renderer = renderer->parent();
2854 
2855             if (renderer) {
2856                 if (Frame* frame = document()->frame())
2857                     frame->eventHandler()->startPanScrolling(renderer);
2858             }
2859         }
2860 #endif
2861     } else if (eventType == eventNames().mousewheelEvent && event->isWheelEvent()) {
2862         WheelEvent* wheelEvent = static_cast<WheelEvent*>(event);
2863 
2864         // If we don't have a renderer, send the wheel event to the first node we find with a renderer.
2865         // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll.
2866         Node* startNode = this;
2867         while (startNode && !startNode->renderer())
2868             startNode = startNode->parentOrHostNode();
2869 
2870         if (startNode && startNode->renderer())
2871             if (Frame* frame = document()->frame())
2872                 frame->eventHandler()->defaultWheelEventHandler(startNode, wheelEvent);
2873     } else if (event->type() == eventNames().webkitEditableContentChangedEvent) {
2874         dispatchInputEvent();
2875     }
2876 }
2877 
2878 } // namespace WebCore
2879 
2880 #ifndef NDEBUG
2881 
showTree(const WebCore::Node * node)2882 void showTree(const WebCore::Node* node)
2883 {
2884     if (node)
2885         node->showTreeForThis();
2886 }
2887 
2888 #endif
2889