• 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 Apple Inc. All rights reserved.
6  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #ifdef ANDROID_DOM_LOGGING
25 #define LOG_TAG "webcore"
26 #include "AndroidLog.h"
27 #endif
28 
29 #include "config.h"
30 #include "Node.h"
31 
32 #include "CSSParser.h"
33 #include "CSSRule.h"
34 #include "CSSRuleList.h"
35 #include "CSSSelector.h"
36 #include "CSSSelectorList.h"
37 #include "CSSStyleRule.h"
38 #include "CSSStyleSelector.h"
39 #include "CSSStyleSheet.h"
40 #include "CString.h"
41 #include "ChildNodeList.h"
42 #include "ClassNodeList.h"
43 #include "DOMImplementation.h"
44 #include "Document.h"
45 #include "DynamicNodeList.h"
46 #include "Element.h"
47 #include "ExceptionCode.h"
48 #include "Frame.h"
49 #include "HTMLNames.h"
50 #include "JSDOMBinding.h"
51 #include "Logging.h"
52 #include "NameNodeList.h"
53 #include "NamedAttrMap.h"
54 #include "NodeRareData.h"
55 #include "ProcessingInstruction.h"
56 #include "RenderObject.h"
57 #include "ScriptController.h"
58 #include "SelectorNodeList.h"
59 #include "StringBuilder.h"
60 #include "TagNodeList.h"
61 #include "Text.h"
62 #include "XMLNames.h"
63 #include "htmlediting.h"
64 #include <wtf/RefCountedLeakCounter.h>
65 
66 #define DUMP_NODE_STATISTICS 0
67 
68 using namespace std;
69 
70 namespace WebCore {
71 
72 using namespace HTMLNames;
73 
isSupported(const String & feature,const String & version)74 bool Node::isSupported(const String& feature, const String& version)
75 {
76     return DOMImplementation::hasFeature(feature, version);
77 }
78 
79 #if DUMP_NODE_STATISTICS
80 static HashSet<Node*> liveNodeSet;
81 #endif
82 
dumpStatistics()83 void Node::dumpStatistics()
84 {
85 #if DUMP_NODE_STATISTICS
86     size_t nodesWithRareData = 0;
87 
88     size_t elementNodes = 0;
89     size_t attrNodes = 0;
90     size_t textNodes = 0;
91     size_t cdataNodes = 0;
92     size_t commentNodes = 0;
93     size_t entityReferenceNodes = 0;
94     size_t entityNodes = 0;
95     size_t piNodes = 0;
96     size_t documentNodes = 0;
97     size_t docTypeNodes = 0;
98     size_t fragmentNodes = 0;
99     size_t notationNodes = 0;
100     size_t xpathNSNodes = 0;
101 
102     HashMap<String, size_t> perTagCount;
103 
104     size_t attributes = 0;
105     size_t mappedAttributes = 0;
106     size_t mappedAttributesWithStyleDecl = 0;
107     size_t attributesWithAttr = 0;
108     size_t attrMaps = 0;
109     size_t mappedAttrMaps = 0;
110 
111     for (HashSet<Node*>::const_iterator it = liveNodeSet.begin(); it != liveNodeSet.end(); ++it) {
112         Node* node = *it;
113 
114         if (node->hasRareData())
115             ++nodesWithRareData;
116 
117         switch (node->nodeType()) {
118             case ELEMENT_NODE: {
119                 ++elementNodes;
120 
121                 // Tag stats
122                 Element* element = static_cast<Element*>(node);
123                 pair<HashMap<String, size_t>::iterator, bool> result = perTagCount.add(element->tagName(), 1);
124                 if (!result.second)
125                     result.first->second++;
126 
127                 // AttributeMap stats
128                 if (NamedAttrMap* attrMap = element->attributes(true)) {
129                     attributes += attrMap->length();
130                     ++attrMaps;
131                     if (attrMap->isMappedAttributeMap())
132                         ++mappedAttrMaps;
133                     for (unsigned i = 0; i < attrMap->length(); ++i) {
134                         Attribute* attr = attrMap->attributeItem(i);
135                         if (attr->attr())
136                             ++attributesWithAttr;
137                         if (attr->isMappedAttribute()) {
138                             ++mappedAttributes;
139                             if (attr->style())
140                                 ++mappedAttributesWithStyleDecl;
141                         }
142                     }
143                 }
144                 break;
145             }
146             case ATTRIBUTE_NODE: {
147                 ++attrNodes;
148                 break;
149             }
150             case TEXT_NODE: {
151                 ++textNodes;
152                 break;
153             }
154             case CDATA_SECTION_NODE: {
155                 ++cdataNodes;
156                 break;
157             }
158             case COMMENT_NODE: {
159                 ++commentNodes;
160                 break;
161             }
162             case ENTITY_REFERENCE_NODE: {
163                 ++entityReferenceNodes;
164                 break;
165             }
166             case ENTITY_NODE: {
167                 ++entityNodes;
168                 break;
169             }
170             case PROCESSING_INSTRUCTION_NODE: {
171                 ++piNodes;
172                 break;
173             }
174             case DOCUMENT_NODE: {
175                 ++documentNodes;
176                 break;
177             }
178             case DOCUMENT_TYPE_NODE: {
179                 ++docTypeNodes;
180                 break;
181             }
182             case DOCUMENT_FRAGMENT_NODE: {
183                 ++fragmentNodes;
184                 break;
185             }
186             case NOTATION_NODE: {
187                 ++notationNodes;
188                 break;
189             }
190             case XPATH_NAMESPACE_NODE: {
191                 ++xpathNSNodes;
192                 break;
193             }
194         }
195 
196     }
197 
198     printf("Number of Nodes: %d\n\n", liveNodeSet.size());
199     printf("Number of Nodes with RareData: %zu\n\n", nodesWithRareData);
200 
201     printf("NodeType distrubution:\n");
202     printf("  Number of Element nodes: %zu\n", elementNodes);
203     printf("  Number of Attribute nodes: %zu\n", attrNodes);
204     printf("  Number of Text nodes: %zu\n", textNodes);
205     printf("  Number of CDATASection nodes: %zu\n", cdataNodes);
206     printf("  Number of Comment nodes: %zu\n", commentNodes);
207     printf("  Number of EntityReference nodes: %zu\n", entityReferenceNodes);
208     printf("  Number of Entity nodes: %zu\n", entityNodes);
209     printf("  Number of ProcessingInstruction nodes: %zu\n", piNodes);
210     printf("  Number of Document nodes: %zu\n", documentNodes);
211     printf("  Number of DocumentType nodes: %zu\n", docTypeNodes);
212     printf("  Number of DocumentFragment nodes: %zu\n", fragmentNodes);
213     printf("  Number of Notation nodes: %zu\n", notationNodes);
214     printf("  Number of XPathNS nodes: %zu\n", xpathNSNodes);
215 
216     printf("Element tag name distibution:\n");
217     for (HashMap<String, size_t>::const_iterator it = perTagCount.begin(); it != perTagCount.end(); ++it)
218         printf("  Number of <%s> tags: %zu\n", it->first.utf8().data(), it->second);
219 
220     printf("Attribute Maps:\n");
221     printf("  Number of Attributes (non-Node and Node): %zu [%zu]\n", attributes, sizeof(Attribute));
222     printf("  Number of MappedAttributes: %zu [%zu]\n", mappedAttributes, sizeof(MappedAttribute));
223     printf("  Number of MappedAttributes with a StyleDeclaration: %zu\n", mappedAttributesWithStyleDecl);
224     printf("  Number of Attributes with an Attr: %zu\n", attributesWithAttr);
225     printf("  Number of NamedAttrMaps: %zu\n", attrMaps);
226     printf("  Number of NamedMappedAttrMap: %zu\n", mappedAttrMaps);
227 #endif
228 }
229 
230 #ifndef NDEBUG
231 static WTF::RefCountedLeakCounter nodeCounter("WebCoreNode");
232 
233 static bool shouldIgnoreLeaks = false;
234 static HashSet<Node*> ignoreSet;
235 #endif
236 
startIgnoringLeaks()237 void Node::startIgnoringLeaks()
238 {
239 #ifndef NDEBUG
240     shouldIgnoreLeaks = true;
241 #endif
242 }
243 
stopIgnoringLeaks()244 void Node::stopIgnoringLeaks()
245 {
246 #ifndef NDEBUG
247     shouldIgnoreLeaks = false;
248 #endif
249 }
250 
diff(RenderStyle * s1,RenderStyle * s2)251 Node::StyleChange Node::diff( RenderStyle *s1, RenderStyle *s2 )
252 {
253     // FIXME: The behavior of this function is just totally wrong.  It doesn't handle
254     // explicit inheritance of non-inherited properties and so you end up not re-resolving
255     // style in cases where you need to.
256     StyleChange ch = NoInherit;
257     EDisplay display1 = s1 ? s1->display() : NONE;
258     bool fl1 = s1 && s1->hasPseudoStyle(RenderStyle::FIRST_LETTER);
259     EDisplay display2 = s2 ? s2->display() : NONE;
260     bool fl2 = s2 && s2->hasPseudoStyle(RenderStyle::FIRST_LETTER);
261 
262     if (display1 != display2 || fl1 != fl2 || (s1 && s2 && !s1->contentDataEquivalent(s2)))
263         ch = Detach;
264     else if (!s1 || !s2)
265         ch = Inherit;
266     else if (*s1 == *s2)
267         ch = NoChange;
268     else if (s1->inheritedNotEqual(s2))
269         ch = Inherit;
270 
271     // If the pseudoStyles have changed, we want any StyleChange that is not NoChange
272     // because setStyle will do the right thing with anything else.
273     if (ch == NoChange && s1->hasPseudoStyle(RenderStyle::BEFORE)) {
274         RenderStyle* ps2 = s2->getCachedPseudoStyle(RenderStyle::BEFORE);
275         if (!ps2)
276             ch = NoInherit;
277         else {
278             RenderStyle* ps1 = s1->getCachedPseudoStyle(RenderStyle::BEFORE);
279             ch = ps1 && *ps1 == *ps2 ? NoChange : NoInherit;
280         }
281     }
282     if (ch == NoChange && s1->hasPseudoStyle(RenderStyle::AFTER)) {
283         RenderStyle* ps2 = s2->getCachedPseudoStyle(RenderStyle::AFTER);
284         if (!ps2)
285             ch = NoInherit;
286         else {
287             RenderStyle* ps1 = s1->getCachedPseudoStyle(RenderStyle::AFTER);
288             ch = ps2 && *ps1 == *ps2 ? NoChange : NoInherit;
289         }
290     }
291 
292     return ch;
293 }
294 
Node(Document * doc,bool isElement,bool isContainer,bool isText)295 Node::Node(Document* doc, bool isElement, bool isContainer, bool isText)
296     : m_document(doc)
297     , m_previous(0)
298     , m_next(0)
299     , m_renderer(0)
300     , m_styleChange(NoStyleChange)
301     , m_hasId(false)
302     , m_hasClass(false)
303     , m_attached(false)
304     , m_hasChangedChild(false)
305     , m_inDocument(false)
306     , m_isLink(false)
307     , m_active(false)
308     , m_hovered(false)
309     , m_inActiveChain(false)
310     , m_inDetach(false)
311     , m_inSubtreeMark(false)
312     , m_hasRareData(false)
313     , m_isElement(isElement)
314     , m_isContainer(isContainer)
315     , m_isText(isText)
316     , m_parsingChildrenFinished(true)
317 #if ENABLE(SVG)
318     , m_areSVGAttributesValid(true)
319 #endif
320     , m_isStyleAttributeValid(true)
321     , m_synchronizingStyleAttribute(false)
322 #if ENABLE(SVG)
323     , m_synchronizingSVGAttributes(false)
324 #endif
325 {
326 #ifndef NDEBUG
327     if (shouldIgnoreLeaks)
328         ignoreSet.add(this);
329     else
330         nodeCounter.increment();
331 #endif
332 #if DUMP_NODE_STATISTICS
333     liveNodeSet.add(this);
334 #endif
335 }
336 
~Node()337 Node::~Node()
338 {
339 #ifndef NDEBUG
340     HashSet<Node*>::iterator it = ignoreSet.find(this);
341     if (it != ignoreSet.end())
342         ignoreSet.remove(it);
343     else
344         nodeCounter.decrement();
345 #endif
346 
347 #if DUMP_NODE_STATISTICS
348     liveNodeSet.remove(this);
349 #endif
350 
351     if (!hasRareData())
352         ASSERT(!NodeRareData::rareDataMap().contains(this));
353     else {
354         if (m_document && rareData()->nodeLists())
355             m_document->removeNodeListCache();
356 
357         NodeRareData::NodeRareDataMap& dataMap = NodeRareData::rareDataMap();
358         NodeRareData::NodeRareDataMap::iterator it = dataMap.find(this);
359         ASSERT(it != dataMap.end());
360         delete it->second;
361         dataMap.remove(it);
362     }
363 
364     if (renderer())
365         detach();
366 
367     if (m_previous)
368         m_previous->setNextSibling(0);
369     if (m_next)
370         m_next->setPreviousSibling(0);
371 }
372 
setDocument(Document * doc)373 void Node::setDocument(Document* doc)
374 {
375     if (inDocument() || m_document == doc)
376         return;
377 
378     willMoveToNewOwnerDocument();
379 
380     updateDOMNodeDocument(this, m_document.get(), doc);
381 
382     m_document = doc;
383 
384     didMoveToNewOwnerDocument();
385 }
386 
rareData() const387 NodeRareData* Node::rareData() const
388 {
389     ASSERT(hasRareData());
390     return NodeRareData::rareDataFromMap(this);
391 }
392 
ensureRareData()393 NodeRareData* Node::ensureRareData()
394 {
395     if (hasRareData())
396         return rareData();
397 
398     ASSERT(!NodeRareData::rareDataMap().contains(this));
399     NodeRareData* data = createRareData();
400     NodeRareData::rareDataMap().set(this, data);
401     m_hasRareData = true;
402     return data;
403 }
404 
createRareData()405 NodeRareData* Node::createRareData()
406 {
407     return new NodeRareData;
408 }
409 
tabIndex() const410 short Node::tabIndex() const
411 {
412     return hasRareData() ? rareData()->tabIndex() : 0;
413 }
414 
setTabIndexExplicitly(short i)415 void Node::setTabIndexExplicitly(short i)
416 {
417     ensureRareData()->setTabIndexExplicitly(i);
418 }
419 
nodeValue() const420 String Node::nodeValue() const
421 {
422   return String();
423 }
424 
setNodeValue(const String &,ExceptionCode & ec)425 void Node::setNodeValue(const String& /*nodeValue*/, ExceptionCode& ec)
426 {
427     // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
428     if (isReadOnlyNode()) {
429         ec = NO_MODIFICATION_ALLOWED_ERR;
430         return;
431     }
432 
433     // By default, setting nodeValue has no effect.
434 }
435 
childNodes()436 PassRefPtr<NodeList> Node::childNodes()
437 {
438     NodeRareData* data = ensureRareData();
439     if (!data->nodeLists()) {
440         data->setNodeLists(auto_ptr<NodeListsNodeData>(new NodeListsNodeData));
441         document()->addNodeListCache();
442     }
443 
444     return ChildNodeList::create(this, &data->nodeLists()->m_childNodeListCaches);
445 }
446 
lastDescendant() const447 Node *Node::lastDescendant() const
448 {
449     Node *n = const_cast<Node *>(this);
450     while (n && n->lastChild())
451         n = n->lastChild();
452     return n;
453 }
454 
firstDescendant() const455 Node* Node::firstDescendant() const
456 {
457     Node *n = const_cast<Node *>(this);
458     while (n && n->firstChild())
459         n = n->firstChild();
460     return n;
461 }
462 
insertBefore(PassRefPtr<Node>,Node *,ExceptionCode & ec,bool)463 bool Node::insertBefore(PassRefPtr<Node>, Node*, ExceptionCode& ec, bool)
464 {
465     ec = HIERARCHY_REQUEST_ERR;
466     return false;
467 }
468 
replaceChild(PassRefPtr<Node>,Node *,ExceptionCode & ec,bool)469 bool Node::replaceChild(PassRefPtr<Node>, Node*, ExceptionCode& ec, bool)
470 {
471     ec = HIERARCHY_REQUEST_ERR;
472     return false;
473 }
474 
removeChild(Node *,ExceptionCode & ec)475 bool Node::removeChild(Node*, ExceptionCode& ec)
476 {
477     ec = NOT_FOUND_ERR;
478     return false;
479 }
480 
appendChild(PassRefPtr<Node>,ExceptionCode & ec,bool)481 bool Node::appendChild(PassRefPtr<Node>, ExceptionCode& ec, bool)
482 {
483     ec = HIERARCHY_REQUEST_ERR;
484     return false;
485 }
486 
remove(ExceptionCode & ec)487 void Node::remove(ExceptionCode& ec)
488 {
489     ref();
490     if (Node *p = parentNode())
491         p->removeChild(this, ec);
492     else
493         ec = HIERARCHY_REQUEST_ERR;
494     deref();
495 }
496 
normalize()497 void Node::normalize()
498 {
499     // Go through the subtree beneath us, normalizing all nodes. This means that
500     // any two adjacent text nodes are merged together.
501 
502     RefPtr<Node> node = this;
503     while (Node* firstChild = node->firstChild())
504         node = firstChild;
505     for (; node; node = node->traverseNextNodePostOrder()) {
506         NodeType type = node->nodeType();
507         if (type == ELEMENT_NODE)
508             static_cast<Element*>(node.get())->normalizeAttributes();
509 
510         Node* firstChild = node->firstChild();
511         if (firstChild && !firstChild->nextSibling() && firstChild->isTextNode()) {
512             Text* text = static_cast<Text*>(firstChild);
513             if (!text->length()) {
514                 ExceptionCode ec;
515                 text->remove(ec);
516             }
517         }
518 
519         if (node == this)
520             break;
521 
522         if (type == TEXT_NODE) {
523             while (1) {
524                 Node* nextSibling = node->nextSibling();
525                 if (!nextSibling || !nextSibling->isTextNode())
526                     break;
527                 // Current child and the next one are both text nodes. Merge them.
528                 Text* text = static_cast<Text*>(node.get());
529                 RefPtr<Text> nextText = static_cast<Text*>(nextSibling);
530                 unsigned offset = text->length();
531                 ExceptionCode ec;
532                 text->appendData(nextText->data(), ec);
533                 document()->textNodesMerged(nextText.get(), offset);
534                 nextText->remove(ec);
535             }
536         }
537     }
538 }
539 
virtualPrefix() const540 const AtomicString& Node::virtualPrefix() const
541 {
542     // For nodes other than elements and attributes, the prefix is always null
543     return nullAtom;
544 }
545 
setPrefix(const AtomicString &,ExceptionCode & ec)546 void Node::setPrefix(const AtomicString& /*prefix*/, ExceptionCode& ec)
547 {
548     // The spec says that for nodes other than elements and attributes, prefix is always null.
549     // It does not say what to do when the user tries to set the prefix on another type of
550     // node, however Mozilla throws a NAMESPACE_ERR exception.
551     ec = NAMESPACE_ERR;
552 }
553 
virtualLocalName() const554 const AtomicString& Node::virtualLocalName() const
555 {
556     return nullAtom;
557 }
558 
virtualNamespaceURI() const559 const AtomicString& Node::virtualNamespaceURI() const
560 {
561     return nullAtom;
562 }
563 
addChild(PassRefPtr<Node>)564 ContainerNode* Node::addChild(PassRefPtr<Node>)
565 {
566     return 0;
567 }
568 
isContentEditable() const569 bool Node::isContentEditable() const
570 {
571     return parent() && parent()->isContentEditable();
572 }
573 
isContentRichlyEditable() const574 bool Node::isContentRichlyEditable() const
575 {
576     return parent() && parent()->isContentRichlyEditable();
577 }
578 
shouldUseInputMethod() const579 bool Node::shouldUseInputMethod() const
580 {
581     return isContentEditable();
582 }
583 
renderBox() const584 RenderBox* Node::renderBox() const
585 {
586     return m_renderer && m_renderer->isBox() ? static_cast<RenderBox*>(m_renderer) : 0;
587 }
588 
getRect() const589 IntRect Node::getRect() const
590 {
591     // FIXME: broken with transforms
592     if (renderer())
593         return renderer()->absoluteBoundingBoxRect();
594     return IntRect();
595 }
596 
setChanged(StyleChangeType changeType)597 void Node::setChanged(StyleChangeType changeType)
598 {
599     if ((changeType != NoStyleChange) && !attached()) // changed compared to what?
600         return;
601 
602     if (!(changeType == InlineStyleChange && (m_styleChange == FullStyleChange || m_styleChange == AnimationStyleChange)))
603         m_styleChange = changeType;
604 
605     if (m_styleChange != NoStyleChange) {
606         for (Node* p = parentNode(); p && !p->hasChangedChild(); p = p->parentNode())
607             p->setHasChangedChild(true);
608         document()->setDocumentChanged(true);
609     }
610 }
611 
outermostLazyAttachedAncestor(Node * start)612 static Node* outermostLazyAttachedAncestor(Node* start)
613 {
614     Node* p = start;
615     for (Node* next = p->parentNode(); !next->renderer(); p = next, next = next->parentNode()) {}
616     return p;
617 }
618 
lazyAttach()619 void Node::lazyAttach()
620 {
621     bool mustDoFullAttach = false;
622 
623     for (Node* n = this; n; n = n->traverseNextNode(this)) {
624         if (!n->canLazyAttach()) {
625             mustDoFullAttach = true;
626             break;
627         }
628 
629         if (n->firstChild())
630             n->setHasChangedChild(true);
631         n->m_styleChange = FullStyleChange;
632         n->m_attached = true;
633     }
634 
635     if (mustDoFullAttach) {
636         Node* lazyAttachedAncestor = outermostLazyAttachedAncestor(this);
637         if (lazyAttachedAncestor->attached())
638             lazyAttachedAncestor->detach();
639         lazyAttachedAncestor->attach();
640     } else {
641         for (Node* p = parentNode(); p && !p->hasChangedChild(); p = p->parentNode())
642             p->setHasChangedChild(true);
643         document()->setDocumentChanged(true);
644     }
645 }
646 
canLazyAttach()647 bool Node::canLazyAttach()
648 {
649     return shadowAncestorNode() == this;
650 }
651 
setFocus(bool b)652 void Node::setFocus(bool b)
653 {
654     if (b || hasRareData())
655         ensureRareData()->setFocused(b);
656 }
657 
rareDataFocused() const658 bool Node::rareDataFocused() const
659 {
660     ASSERT(hasRareData());
661     return rareData()->isFocused();
662 }
663 
isFocusable() const664 bool Node::isFocusable() const
665 {
666     return hasRareData() && rareData()->tabIndexSetExplicitly();
667 }
668 
isKeyboardFocusable(KeyboardEvent *) const669 bool Node::isKeyboardFocusable(KeyboardEvent*) const
670 {
671     return isFocusable() && tabIndex() >= 0;
672 }
673 
isMouseFocusable() const674 bool Node::isMouseFocusable() const
675 {
676     return isFocusable();
677 }
678 
nodeIndex() const679 unsigned Node::nodeIndex() const
680 {
681     Node *_tempNode = previousSibling();
682     unsigned count=0;
683     for( count=0; _tempNode; count++ )
684         _tempNode = _tempNode->previousSibling();
685     return count;
686 }
687 
registerDynamicNodeList(DynamicNodeList * list)688 void Node::registerDynamicNodeList(DynamicNodeList* list)
689 {
690     NodeRareData* data = ensureRareData();
691     if (!data->nodeLists()) {
692         data->setNodeLists(auto_ptr<NodeListsNodeData>(new NodeListsNodeData));
693         document()->addNodeListCache();
694     } else if (!m_document->hasNodeListCaches()) {
695         // We haven't been receiving notifications while there were no registered lists, so the cache is invalid now.
696         data->nodeLists()->invalidateCaches();
697     }
698 
699     if (list->hasOwnCaches())
700         data->nodeLists()->m_listsWithCaches.add(list);
701 }
702 
unregisterDynamicNodeList(DynamicNodeList * list)703 void Node::unregisterDynamicNodeList(DynamicNodeList* list)
704 {
705     ASSERT(rareData());
706     ASSERT(rareData()->nodeLists());
707     if (list->hasOwnCaches()) {
708         NodeRareData* data = rareData();
709         data->nodeLists()->m_listsWithCaches.remove(list);
710         if (data->nodeLists()->isEmpty()) {
711             data->clearNodeLists();
712             document()->removeNodeListCache();
713         }
714     }
715 }
716 
notifyLocalNodeListsAttributeChanged()717 void Node::notifyLocalNodeListsAttributeChanged()
718 {
719     if (!hasRareData())
720         return;
721     NodeRareData* data = rareData();
722     if (!data->nodeLists())
723         return;
724 
725     data->nodeLists()->invalidateCachesThatDependOnAttributes();
726 
727     if (data->nodeLists()->isEmpty()) {
728         data->clearNodeLists();
729         document()->removeNodeListCache();
730     }
731 }
732 
notifyNodeListsAttributeChanged()733 void Node::notifyNodeListsAttributeChanged()
734 {
735     for (Node *n = this; n; n = n->parentNode())
736         n->notifyLocalNodeListsAttributeChanged();
737 }
738 
notifyLocalNodeListsChildrenChanged()739 void Node::notifyLocalNodeListsChildrenChanged()
740 {
741     if (!hasRareData())
742         return;
743     NodeRareData* data = rareData();
744     if (!data->nodeLists())
745         return;
746 
747     data->nodeLists()->invalidateCaches();
748 
749     NodeListsNodeData::NodeListSet::iterator end = data->nodeLists()->m_listsWithCaches.end();
750     for (NodeListsNodeData::NodeListSet::iterator i = data->nodeLists()->m_listsWithCaches.begin(); i != end; ++i)
751         (*i)->invalidateCache();
752 
753     if (data->nodeLists()->isEmpty()) {
754         data->clearNodeLists();
755         document()->removeNodeListCache();
756     }
757 }
758 
notifyNodeListsChildrenChanged()759 void Node::notifyNodeListsChildrenChanged()
760 {
761     for (Node* n = this; n; n = n->parentNode())
762         n->notifyLocalNodeListsChildrenChanged();
763 }
764 
traverseNextNode(const Node * stayWithin) const765 Node *Node::traverseNextNode(const Node *stayWithin) const
766 {
767     if (firstChild())
768         return firstChild();
769     if (this == stayWithin)
770         return 0;
771     if (nextSibling())
772         return nextSibling();
773     const Node *n = this;
774     while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
775         n = n->parentNode();
776     if (n)
777         return n->nextSibling();
778     return 0;
779 }
780 
traverseNextSibling(const Node * stayWithin) const781 Node *Node::traverseNextSibling(const Node *stayWithin) const
782 {
783     if (this == stayWithin)
784         return 0;
785     if (nextSibling())
786         return nextSibling();
787     const Node *n = this;
788     while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
789         n = n->parentNode();
790     if (n)
791         return n->nextSibling();
792     return 0;
793 }
794 
traverseNextNodePostOrder() const795 Node* Node::traverseNextNodePostOrder() const
796 {
797     Node* next = nextSibling();
798     if (!next)
799         return parentNode();
800     while (Node* firstChild = next->firstChild())
801         next = firstChild;
802     return next;
803 }
804 
traversePreviousNode(const Node * stayWithin) const805 Node *Node::traversePreviousNode(const Node *stayWithin) const
806 {
807     if (this == stayWithin)
808         return 0;
809     if (previousSibling()) {
810         Node *n = previousSibling();
811         while (n->lastChild())
812             n = n->lastChild();
813         return n;
814     }
815     return parentNode();
816 }
817 
traversePreviousNodePostOrder(const Node * stayWithin) const818 Node *Node::traversePreviousNodePostOrder(const Node *stayWithin) const
819 {
820     if (lastChild())
821         return lastChild();
822     if (this == stayWithin)
823         return 0;
824     if (previousSibling())
825         return previousSibling();
826     const Node *n = this;
827     while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
828         n = n->parentNode();
829     if (n)
830         return n->previousSibling();
831     return 0;
832 }
833 
traversePreviousSiblingPostOrder(const Node * stayWithin) const834 Node* Node::traversePreviousSiblingPostOrder(const Node* stayWithin) const
835 {
836     if (this == stayWithin)
837         return 0;
838     if (previousSibling())
839         return previousSibling();
840     const Node *n = this;
841     while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
842         n = n->parentNode();
843     if (n)
844         return n->previousSibling();
845     return 0;
846 }
847 
checkSetPrefix(const AtomicString &,ExceptionCode & ec)848 void Node::checkSetPrefix(const AtomicString&, ExceptionCode& ec)
849 {
850     // Perform error checking as required by spec for setting Node.prefix. Used by
851     // Element::setPrefix() and Attr::setPrefix()
852 
853     // FIXME: Implement support for INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
854 
855     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
856     if (isReadOnlyNode()) {
857         ec = NO_MODIFICATION_ALLOWED_ERR;
858         return;
859     }
860 
861     // FIXME: Implement NAMESPACE_ERR: - Raised if the specified prefix is malformed
862     // We have to comment this out, since it's used for attributes and tag names, and we've only
863     // switched one over.
864     /*
865     // - if the namespaceURI of this node is null,
866     // - if the specified prefix is "xml" and the namespaceURI of this node is different from
867     //   "http://www.w3.org/XML/1998/namespace",
868     // - if this node is an attribute and the specified prefix is "xmlns" and
869     //   the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
870     // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
871     if ((namespacePart(id()) == noNamespace && id() > ID_LAST_TAG) ||
872         (_prefix == "xml" && String(document()->namespaceURI(id())) != "http://www.w3.org/XML/1998/namespace")) {
873         ec = NAMESPACE_ERR;
874         return;
875     }*/
876 }
877 
canReplaceChild(Node * newChild,Node *)878 bool Node::canReplaceChild(Node* newChild, Node*)
879 {
880     if (newChild->nodeType() != DOCUMENT_FRAGMENT_NODE) {
881         if (!childTypeAllowed(newChild->nodeType()))
882             return false;
883     } else {
884         for (Node *n = newChild->firstChild(); n; n = n->nextSibling()) {
885             if (!childTypeAllowed(n->nodeType()))
886                 return false;
887         }
888     }
889     return true;
890 }
891 
checkReplaceChild(Node * newChild,Node * oldChild,ExceptionCode & ec)892 void Node::checkReplaceChild(Node* newChild, Node* oldChild, ExceptionCode& ec)
893 {
894     // Perform error checking as required by spec for adding a new child. Used by
895     // appendChild(), replaceChild() and insertBefore()
896 
897     // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
898     if (!newChild) {
899         ec = NOT_FOUND_ERR;
900         return;
901     }
902 
903     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
904     if (isReadOnlyNode()) {
905         ec = NO_MODIFICATION_ALLOWED_ERR;
906         return;
907     }
908 
909     bool shouldAdoptChild = false;
910 
911     // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
912     // created this node.
913     // We assume that if newChild is a DocumentFragment, all children are created from the same document
914     // as the fragment itself (otherwise they could not have been added as children)
915     if (newChild->document() != document()) {
916         // but if the child is not in a document yet then loosen the
917         // restriction, so that e.g. creating an element with the Option()
918         // constructor and then adding it to a different document works,
919         // as it does in Mozilla and Mac IE.
920         if (!newChild->inDocument()) {
921             shouldAdoptChild = true;
922         } else {
923             ec = WRONG_DOCUMENT_ERR;
924             return;
925         }
926     }
927 
928     // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
929     // newChild node, or if the node to append is one of this node's ancestors.
930 
931     // check for ancestor/same node
932     if (newChild == this || isDescendantOf(newChild)) {
933         ec = HIERARCHY_REQUEST_ERR;
934         return;
935     }
936 
937     if (!canReplaceChild(newChild, oldChild)) {
938         ec = HIERARCHY_REQUEST_ERR;
939         return;
940     }
941 
942     // change the document pointer of newChild and all of its children to be the new document
943     if (shouldAdoptChild)
944         for (Node* node = newChild; node; node = node->traverseNextNode(newChild))
945             node->setDocument(document());
946 }
947 
checkAddChild(Node * newChild,ExceptionCode & ec)948 void Node::checkAddChild(Node *newChild, ExceptionCode& ec)
949 {
950     // Perform error checking as required by spec for adding a new child. Used by
951     // appendChild(), replaceChild() and insertBefore()
952 
953     // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
954     if (!newChild) {
955         ec = NOT_FOUND_ERR;
956         return;
957     }
958 
959     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
960     if (isReadOnlyNode()) {
961         ec = NO_MODIFICATION_ALLOWED_ERR;
962         return;
963     }
964 
965     bool shouldAdoptChild = false;
966 
967     // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
968     // created this node.
969     // We assume that if newChild is a DocumentFragment, all children are created from the same document
970     // as the fragment itself (otherwise they could not have been added as children)
971     if (newChild->document() != document()) {
972         // but if the child is not in a document yet then loosen the
973         // restriction, so that e.g. creating an element with the Option()
974         // constructor and then adding it to a different document works,
975         // as it does in Mozilla and Mac IE.
976         if (!newChild->inDocument()) {
977             shouldAdoptChild = true;
978         } else {
979             ec = WRONG_DOCUMENT_ERR;
980             return;
981         }
982     }
983 
984     // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
985     // newChild node, or if the node to append is one of this node's ancestors.
986 
987     // check for ancestor/same node
988     if (newChild == this || isDescendantOf(newChild)) {
989         ec = HIERARCHY_REQUEST_ERR;
990         return;
991     }
992 
993     if (newChild->nodeType() != DOCUMENT_FRAGMENT_NODE) {
994         if (!childTypeAllowed(newChild->nodeType())) {
995             ec = HIERARCHY_REQUEST_ERR;
996             return;
997         }
998     }
999     else {
1000         for (Node *n = newChild->firstChild(); n; n = n->nextSibling()) {
1001             if (!childTypeAllowed(n->nodeType())) {
1002                 ec = HIERARCHY_REQUEST_ERR;
1003                 return;
1004             }
1005         }
1006     }
1007 
1008     // change the document pointer of newChild and all of its children to be the new document
1009     if (shouldAdoptChild)
1010         for (Node* node = newChild; node; node = node->traverseNextNode(newChild))
1011             node->setDocument(document());
1012 }
1013 
isDescendantOf(const Node * other) const1014 bool Node::isDescendantOf(const Node *other) const
1015 {
1016     // Return true if other is an ancestor of this, otherwise false
1017     if (!other)
1018         return false;
1019     for (const Node *n = parentNode(); n; n = n->parentNode()) {
1020         if (n == other)
1021             return true;
1022     }
1023     return false;
1024 }
1025 
contains(const Node * node) const1026 bool Node::contains(const Node* node) const
1027 {
1028     if (!node)
1029         return false;
1030     return this == node || node->isDescendantOf(this);
1031 }
1032 
childAllowed(Node * newChild)1033 bool Node::childAllowed(Node* newChild)
1034 {
1035     return childTypeAllowed(newChild->nodeType());
1036 }
1037 
attach()1038 void Node::attach()
1039 {
1040     ASSERT(!attached());
1041     ASSERT(!renderer() || (renderer()->style() && renderer()->parent()));
1042 
1043     // If this node got a renderer it may be the previousRenderer() of sibling text nodes and thus affect the
1044     // result of Text::rendererIsNeeded() for those nodes.
1045     if (renderer()) {
1046         for (Node* next = nextSibling(); next; next = next->nextSibling()) {
1047             if (next->renderer())
1048                 break;
1049             if (!next->attached())
1050                 break;  // Assume this means none of the following siblings are attached.
1051             if (next->isTextNode())
1052                 next->createRendererIfNeeded();
1053         }
1054     }
1055 
1056     m_attached = true;
1057 }
1058 
willRemove()1059 void Node::willRemove()
1060 {
1061 }
1062 
detach()1063 void Node::detach()
1064 {
1065     m_inDetach = true;
1066 
1067     if (renderer())
1068         renderer()->destroy();
1069     setRenderer(0);
1070 
1071     Document* doc = document();
1072     if (m_hovered)
1073         doc->hoveredNodeDetached(this);
1074     if (m_inActiveChain)
1075         doc->activeChainNodeDetached(this);
1076 
1077     m_active = false;
1078     m_hovered = false;
1079     m_inActiveChain = false;
1080     m_attached = false;
1081     m_inDetach = false;
1082 }
1083 
insertedIntoDocument()1084 void Node::insertedIntoDocument()
1085 {
1086     setInDocument(true);
1087     insertedIntoTree(false);
1088 }
1089 
removedFromDocument()1090 void Node::removedFromDocument()
1091 {
1092     if (m_document && m_document->getCSSTarget() == this)
1093         m_document->setCSSTarget(0);
1094 
1095     setInDocument(false);
1096     removedFromTree(false);
1097 }
1098 
previousEditable() const1099 Node *Node::previousEditable() const
1100 {
1101     Node *node = previousLeafNode();
1102     while (node) {
1103         if (node->isContentEditable())
1104             return node;
1105         node = node->previousLeafNode();
1106     }
1107     return 0;
1108 }
1109 
nextEditable() const1110 Node *Node::nextEditable() const
1111 {
1112     Node *node = nextLeafNode();
1113     while (node) {
1114         if (node->isContentEditable())
1115             return node;
1116         node = node->nextLeafNode();
1117     }
1118     return 0;
1119 }
1120 
previousRenderer()1121 RenderObject * Node::previousRenderer()
1122 {
1123     for (Node *n = previousSibling(); n; n = n->previousSibling()) {
1124         if (n->renderer())
1125             return n->renderer();
1126     }
1127     return 0;
1128 }
1129 
nextRenderer()1130 RenderObject * Node::nextRenderer()
1131 {
1132     // Avoid an O(n^2) problem with this function by not checking for nextRenderer() when the parent element hasn't even
1133     // been attached yet.
1134     if (parent() && !parent()->attached())
1135         return 0;
1136 
1137     for (Node *n = nextSibling(); n; n = n->nextSibling()) {
1138         if (n->renderer())
1139             return n->renderer();
1140     }
1141     return 0;
1142 }
1143 
1144 // FIXME: This code is used by editing.  Seems like it could move over there and not pollute Node.
previousNodeConsideringAtomicNodes() const1145 Node *Node::previousNodeConsideringAtomicNodes() const
1146 {
1147     if (previousSibling()) {
1148         Node *n = previousSibling();
1149         while (!isAtomicNode(n) && n->lastChild())
1150             n = n->lastChild();
1151         return n;
1152     }
1153     else if (parentNode()) {
1154         return parentNode();
1155     }
1156     else {
1157         return 0;
1158     }
1159 }
1160 
nextNodeConsideringAtomicNodes() const1161 Node *Node::nextNodeConsideringAtomicNodes() const
1162 {
1163     if (!isAtomicNode(this) && firstChild())
1164         return firstChild();
1165     if (nextSibling())
1166         return nextSibling();
1167     const Node *n = this;
1168     while (n && !n->nextSibling())
1169         n = n->parentNode();
1170     if (n)
1171         return n->nextSibling();
1172     return 0;
1173 }
1174 
previousLeafNode() const1175 Node *Node::previousLeafNode() const
1176 {
1177     Node *node = previousNodeConsideringAtomicNodes();
1178     while (node) {
1179         if (isAtomicNode(node))
1180             return node;
1181         node = node->previousNodeConsideringAtomicNodes();
1182     }
1183     return 0;
1184 }
1185 
nextLeafNode() const1186 Node *Node::nextLeafNode() const
1187 {
1188     Node *node = nextNodeConsideringAtomicNodes();
1189     while (node) {
1190         if (isAtomicNode(node))
1191             return node;
1192         node = node->nextNodeConsideringAtomicNodes();
1193     }
1194     return 0;
1195 }
1196 
createRendererIfNeeded()1197 void Node::createRendererIfNeeded()
1198 {
1199     if (!document()->shouldCreateRenderers())
1200         return;
1201 
1202     ASSERT(!renderer());
1203 
1204     Node* parent = parentNode();
1205     ASSERT(parent);
1206 
1207     RenderObject* parentRenderer = parent->renderer();
1208     if (parentRenderer && parentRenderer->canHaveChildren()
1209 #if ENABLE(SVG)
1210         && parent->childShouldCreateRenderer(this)
1211 #endif
1212         ) {
1213         RefPtr<RenderStyle> style = styleForRenderer();
1214         if (rendererIsNeeded(style.get())) {
1215             if (RenderObject* r = createRenderer(document()->renderArena(), style.get())) {
1216                 if (!parentRenderer->isChildAllowed(r, style.get()))
1217                     r->destroy();
1218                 else {
1219                     setRenderer(r);
1220                     renderer()->setAnimatableStyle(style.release());
1221                     parentRenderer->addChild(renderer(), nextRenderer());
1222                 }
1223             }
1224         }
1225     }
1226 }
1227 
styleForRenderer()1228 PassRefPtr<RenderStyle> Node::styleForRenderer()
1229 {
1230     if (isElementNode())
1231         return document()->styleSelector()->styleForElement(static_cast<Element*>(this));
1232     return parentNode() && parentNode()->renderer() ? parentNode()->renderer()->style() : 0;
1233 }
1234 
rendererIsNeeded(RenderStyle * style)1235 bool Node::rendererIsNeeded(RenderStyle *style)
1236 {
1237     return (document()->documentElement() == this) || (style->display() != NONE);
1238 }
1239 
createRenderer(RenderArena *,RenderStyle *)1240 RenderObject* Node::createRenderer(RenderArena*, RenderStyle*)
1241 {
1242     ASSERT(false);
1243     return 0;
1244 }
1245 
nonRendererRenderStyle() const1246 RenderStyle* Node::nonRendererRenderStyle() const
1247 {
1248     return 0;
1249 }
1250 
setRenderStyle(PassRefPtr<RenderStyle> s)1251 void Node::setRenderStyle(PassRefPtr<RenderStyle> s)
1252 {
1253     if (m_renderer)
1254         m_renderer->setAnimatableStyle(s);
1255 }
1256 
computedStyle()1257 RenderStyle* Node::computedStyle()
1258 {
1259     return parent() ? parent()->computedStyle() : 0;
1260 }
1261 
maxCharacterOffset() const1262 int Node::maxCharacterOffset() const
1263 {
1264     ASSERT_NOT_REACHED();
1265     return 0;
1266 }
1267 
1268 // FIXME: Shouldn't these functions be in the editing code?  Code that asks questions about HTML in the core DOM class
1269 // is obviously misplaced.
canStartSelection() const1270 bool Node::canStartSelection() const
1271 {
1272     if (isContentEditable())
1273         return true;
1274     return parent() ? parent()->canStartSelection() : true;
1275 }
1276 
shadowAncestorNode()1277 Node* Node::shadowAncestorNode()
1278 {
1279 #if ENABLE(SVG)
1280     // SVG elements living in a shadow tree only occour when <use> created them.
1281     // For these cases we do NOT want to return the shadowParentNode() here
1282     // but the actual shadow tree element - as main difference to the HTML forms
1283     // shadow tree concept. (This function _could_ be made virtual - opinions?)
1284     if (isSVGElement())
1285         return this;
1286 #endif
1287 
1288     Node* root = shadowTreeRootNode();
1289     if (root)
1290         return root->shadowParentNode();
1291     return this;
1292 }
1293 
shadowTreeRootNode()1294 Node* Node::shadowTreeRootNode()
1295 {
1296     Node* root = this;
1297     while (root) {
1298         if (root->isShadowNode())
1299             return root;
1300         root = root->parentNode();
1301     }
1302     return 0;
1303 }
1304 
isInShadowTree()1305 bool Node::isInShadowTree()
1306 {
1307     for (Node* n = this; n; n = n->parentNode())
1308         if (n->isShadowNode())
1309             return true;
1310     return false;
1311 }
1312 
isBlockFlow() const1313 bool Node::isBlockFlow() const
1314 {
1315     return renderer() && renderer()->isBlockFlow();
1316 }
1317 
isBlockFlowOrBlockTable() const1318 bool Node::isBlockFlowOrBlockTable() const
1319 {
1320     return renderer() && (renderer()->isBlockFlow() || renderer()->isTable() && !renderer()->isInline());
1321 }
1322 
isEditableBlock() const1323 bool Node::isEditableBlock() const
1324 {
1325     return isContentEditable() && isBlockFlow();
1326 }
1327 
enclosingBlockFlowElement() const1328 Element *Node::enclosingBlockFlowElement() const
1329 {
1330     Node *n = const_cast<Node *>(this);
1331     if (isBlockFlow())
1332         return static_cast<Element *>(n);
1333 
1334     while (1) {
1335         n = n->parentNode();
1336         if (!n)
1337             break;
1338         if (n->isBlockFlow() || n->hasTagName(bodyTag))
1339             return static_cast<Element *>(n);
1340     }
1341     return 0;
1342 }
1343 
enclosingInlineElement() const1344 Element *Node::enclosingInlineElement() const
1345 {
1346     Node *n = const_cast<Node *>(this);
1347     Node *p;
1348 
1349     while (1) {
1350         p = n->parentNode();
1351         if (!p || p->isBlockFlow() || p->hasTagName(bodyTag))
1352             return static_cast<Element *>(n);
1353         // Also stop if any previous sibling is a block
1354         for (Node *sibling = n->previousSibling(); sibling; sibling = sibling->previousSibling()) {
1355             if (sibling->isBlockFlow())
1356                 return static_cast<Element *>(n);
1357         }
1358         n = p;
1359     }
1360     ASSERT_NOT_REACHED();
1361     return 0;
1362 }
1363 
rootEditableElement() const1364 Element* Node::rootEditableElement() const
1365 {
1366     Element* result = 0;
1367     for (Node* n = const_cast<Node*>(this); n && n->isContentEditable(); n = n->parentNode()) {
1368         if (n->isElementNode())
1369             result = static_cast<Element*>(n);
1370         if (n->hasTagName(bodyTag))
1371             break;
1372     }
1373     return result;
1374 }
1375 
inSameContainingBlockFlowElement(Node * n)1376 bool Node::inSameContainingBlockFlowElement(Node *n)
1377 {
1378     return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
1379 }
1380 
1381 // FIXME: End of obviously misplaced HTML editing functions.  Try to move these out of Node.
1382 
getElementsByTagName(const String & name)1383 PassRefPtr<NodeList> Node::getElementsByTagName(const String& name)
1384 {
1385     return getElementsByTagNameNS(starAtom, name);
1386 }
1387 
getElementsByTagNameNS(const AtomicString & namespaceURI,const String & localName)1388 PassRefPtr<NodeList> Node::getElementsByTagNameNS(const AtomicString& namespaceURI, const String& localName)
1389 {
1390     if (localName.isNull())
1391         return 0;
1392 
1393     NodeRareData* data = ensureRareData();
1394     if (!data->nodeLists()) {
1395         data->setNodeLists(auto_ptr<NodeListsNodeData>(new NodeListsNodeData));
1396         document()->addNodeListCache();
1397     }
1398 
1399     String name = localName;
1400     if (document()->isHTMLDocument())
1401         name = localName.lower();
1402 
1403     AtomicString localNameAtom = name;
1404 
1405     pair<NodeListsNodeData::TagCacheMap::iterator, bool> result = data->nodeLists()->m_tagNodeListCaches.add(QualifiedName(nullAtom, localNameAtom, namespaceURI), 0);
1406     if (result.second)
1407         result.first->second = new DynamicNodeList::Caches;
1408 
1409     return TagNodeList::create(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localNameAtom, result.first->second);
1410 }
1411 
getElementsByName(const String & elementName)1412 PassRefPtr<NodeList> Node::getElementsByName(const String& elementName)
1413 {
1414     NodeRareData* data = ensureRareData();
1415     if (!data->nodeLists()) {
1416         data->setNodeLists(auto_ptr<NodeListsNodeData>(new NodeListsNodeData));
1417         document()->addNodeListCache();
1418     }
1419 
1420     pair<NodeListsNodeData::CacheMap::iterator, bool> result = data->nodeLists()->m_nameNodeListCaches.add(elementName, 0);
1421     if (result.second)
1422         result.first->second = new DynamicNodeList::Caches;
1423 
1424     return NameNodeList::create(this, elementName, result.first->second);
1425 }
1426 
getElementsByClassName(const String & classNames)1427 PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames)
1428 {
1429     NodeRareData* data = ensureRareData();
1430     if (!data->nodeLists()) {
1431         data->setNodeLists(auto_ptr<NodeListsNodeData>(new NodeListsNodeData));
1432         document()->addNodeListCache();
1433     }
1434 
1435     pair<NodeListsNodeData::CacheMap::iterator, bool> result = data->nodeLists()->m_classNodeListCaches.add(classNames, 0);
1436     if (result.second)
1437         result.first->second = new DynamicNodeList::Caches;
1438 
1439     return ClassNodeList::create(this, classNames, result.first->second);
1440 }
1441 
1442 template <typename Functor>
forEachTagSelector(Functor & functor,CSSSelector * selector)1443 static bool forEachTagSelector(Functor& functor, CSSSelector* selector)
1444 {
1445     ASSERT(selector);
1446 
1447     do {
1448         if (functor(selector))
1449             return true;
1450         if (CSSSelector* simpleSelector = selector->simpleSelector()) {
1451             if (forEachTagSelector(functor, simpleSelector))
1452                 return true;
1453         }
1454     } while ((selector = selector->tagHistory()));
1455 
1456     return false;
1457 }
1458 
1459 template <typename Functor>
forEachSelector(Functor & functor,const CSSSelectorList & selectorList)1460 static bool forEachSelector(Functor& functor, const CSSSelectorList& selectorList)
1461 {
1462     for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
1463         if (forEachTagSelector(functor, selector))
1464             return true;
1465     }
1466 
1467     return false;
1468 }
1469 
1470 class SelectorNeedsNamespaceResolutionFunctor {
1471 public:
operator ()(CSSSelector * selector)1472     bool operator()(CSSSelector* selector)
1473     {
1474         if (selector->hasTag() && selector->m_tag.prefix() != nullAtom && selector->m_tag.prefix() != starAtom)
1475             return true;
1476         if (selector->hasAttribute() && selector->attribute().prefix() != nullAtom && selector->attribute().prefix() != starAtom)
1477             return true;
1478         return false;
1479     }
1480 };
1481 
selectorNeedsNamespaceResolution(const CSSSelectorList & selectorList)1482 static bool selectorNeedsNamespaceResolution(const CSSSelectorList& selectorList)
1483 {
1484     SelectorNeedsNamespaceResolutionFunctor functor;
1485     return forEachSelector(functor, selectorList);
1486 }
1487 
querySelector(const String & selectors,ExceptionCode & ec)1488 PassRefPtr<Element> Node::querySelector(const String& selectors, ExceptionCode& ec)
1489 {
1490     if (selectors.isEmpty()) {
1491         ec = SYNTAX_ERR;
1492         return 0;
1493     }
1494     bool strictParsing = !document()->inCompatMode();
1495     CSSParser p(strictParsing);
1496 
1497     CSSSelectorList querySelectorList;
1498     p.parseSelector(selectors, document(), querySelectorList);
1499 
1500     if (!querySelectorList.first()) {
1501         ec = SYNTAX_ERR;
1502         return 0;
1503     }
1504 
1505     // throw a NAMESPACE_ERR if the selector includes any namespace prefixes.
1506     if (selectorNeedsNamespaceResolution(querySelectorList)) {
1507         ec = NAMESPACE_ERR;
1508         return 0;
1509     }
1510 
1511     CSSStyleSelector::SelectorChecker selectorChecker(document(), strictParsing);
1512 
1513     // FIXME: we could also optimize for the the [id="foo"] case
1514     if (strictParsing && inDocument() && querySelectorList.hasOneSelector() && querySelectorList.first()->m_match == CSSSelector::Id) {
1515         ASSERT(querySelectorList.first()->attribute() == idAttr);
1516         Element* element = document()->getElementById(querySelectorList.first()->m_value);
1517         if (element && (isDocumentNode() || element->isDescendantOf(this)) && selectorChecker.checkSelector(querySelectorList.first(), element))
1518             return element;
1519         return 0;
1520     }
1521 
1522     // FIXME: We can speed this up by implementing caching similar to the one use by getElementById
1523     for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
1524         if (n->isElementNode()) {
1525             Element* element = static_cast<Element*>(n);
1526             for (CSSSelector* selector = querySelectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
1527                 if (selectorChecker.checkSelector(selector, element))
1528                     return element;
1529             }
1530         }
1531     }
1532 
1533     return 0;
1534 }
1535 
querySelectorAll(const String & selectors,ExceptionCode & ec)1536 PassRefPtr<NodeList> Node::querySelectorAll(const String& selectors, ExceptionCode& ec)
1537 {
1538     if (selectors.isEmpty()) {
1539         ec = SYNTAX_ERR;
1540         return 0;
1541     }
1542     bool strictParsing = !document()->inCompatMode();
1543     CSSParser p(strictParsing);
1544 
1545     CSSSelectorList querySelectorList;
1546     p.parseSelector(selectors, document(), querySelectorList);
1547 
1548     if (!querySelectorList.first()) {
1549         ec = SYNTAX_ERR;
1550         return 0;
1551     }
1552 
1553     // Throw a NAMESPACE_ERR if the selector includes any namespace prefixes.
1554     if (selectorNeedsNamespaceResolution(querySelectorList)) {
1555         ec = NAMESPACE_ERR;
1556         return 0;
1557     }
1558 
1559     return createSelectorNodeList(this, querySelectorList);
1560 }
1561 
ownerDocument() const1562 Document *Node::ownerDocument() const
1563 {
1564     Document *doc = document();
1565     return doc == this ? 0 : doc;
1566 }
1567 
baseURI() const1568 KURL Node::baseURI() const
1569 {
1570     return parentNode() ? parentNode()->baseURI() : KURL();
1571 }
1572 
isEqualNode(Node * other) const1573 bool Node::isEqualNode(Node *other) const
1574 {
1575     if (!other)
1576         return false;
1577 
1578     if (nodeType() != other->nodeType())
1579         return false;
1580 
1581     if (nodeName() != other->nodeName())
1582         return false;
1583 
1584     if (localName() != other->localName())
1585         return false;
1586 
1587     if (namespaceURI() != other->namespaceURI())
1588         return false;
1589 
1590     if (prefix() != other->prefix())
1591         return false;
1592 
1593     if (nodeValue() != other->nodeValue())
1594         return false;
1595 
1596     NamedAttrMap *attrs = attributes();
1597     NamedAttrMap *otherAttrs = other->attributes();
1598 
1599     if (!attrs && otherAttrs)
1600         return false;
1601 
1602     if (attrs && !attrs->mapsEquivalent(otherAttrs))
1603         return false;
1604 
1605     Node *child = firstChild();
1606     Node *otherChild = other->firstChild();
1607 
1608     while (child) {
1609         if (!child->isEqualNode(otherChild))
1610             return false;
1611 
1612         child = child->nextSibling();
1613         otherChild = otherChild->nextSibling();
1614     }
1615 
1616     if (otherChild)
1617         return false;
1618 
1619     // FIXME: For DocumentType nodes we should check equality on
1620     // the entities and notations NamedNodeMaps as well.
1621 
1622     return true;
1623 }
1624 
isDefaultNamespace(const AtomicString & namespaceURI) const1625 bool Node::isDefaultNamespace(const AtomicString &namespaceURI) const
1626 {
1627     // Implemented according to
1628     // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#isDefaultNamespaceAlgo
1629 
1630     switch (nodeType()) {
1631         case ELEMENT_NODE: {
1632             const Element *elem = static_cast<const Element *>(this);
1633 
1634             if (elem->prefix().isNull())
1635                 return elem->namespaceURI() == namespaceURI;
1636 
1637             if (elem->hasAttributes()) {
1638                 NamedAttrMap *attrs = elem->attributes();
1639 
1640                 for (unsigned i = 0; i < attrs->length(); i++) {
1641                     Attribute *attr = attrs->attributeItem(i);
1642 
1643                     if (attr->localName() == "xmlns")
1644                         return attr->value() == namespaceURI;
1645                 }
1646             }
1647 
1648             if (Element* ancestor = ancestorElement())
1649                 return ancestor->isDefaultNamespace(namespaceURI);
1650 
1651             return false;
1652         }
1653         case DOCUMENT_NODE:
1654             if (Element* de = static_cast<const Document*>(this)->documentElement())
1655                 return de->isDefaultNamespace(namespaceURI);
1656             return false;
1657         case ENTITY_NODE:
1658         case NOTATION_NODE:
1659         case DOCUMENT_TYPE_NODE:
1660         case DOCUMENT_FRAGMENT_NODE:
1661             return false;
1662         case ATTRIBUTE_NODE: {
1663             const Attr *attr = static_cast<const Attr *>(this);
1664             if (attr->ownerElement())
1665                 return attr->ownerElement()->isDefaultNamespace(namespaceURI);
1666             return false;
1667         }
1668         default:
1669             if (Element* ancestor = ancestorElement())
1670                 return ancestor->isDefaultNamespace(namespaceURI);
1671             return false;
1672     }
1673 }
1674 
lookupPrefix(const AtomicString & namespaceURI) const1675 String Node::lookupPrefix(const AtomicString &namespaceURI) const
1676 {
1677     // Implemented according to
1678     // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespacePrefixAlgo
1679 
1680     if (namespaceURI.isEmpty())
1681         return String();
1682 
1683     switch (nodeType()) {
1684         case ELEMENT_NODE:
1685             return lookupNamespacePrefix(namespaceURI, static_cast<const Element *>(this));
1686         case DOCUMENT_NODE:
1687             if (Element* de = static_cast<const Document*>(this)->documentElement())
1688                 return de->lookupPrefix(namespaceURI);
1689             return String();
1690         case ENTITY_NODE:
1691         case NOTATION_NODE:
1692         case DOCUMENT_FRAGMENT_NODE:
1693         case DOCUMENT_TYPE_NODE:
1694             return String();
1695         case ATTRIBUTE_NODE: {
1696             const Attr *attr = static_cast<const Attr *>(this);
1697             if (attr->ownerElement())
1698                 return attr->ownerElement()->lookupPrefix(namespaceURI);
1699             return String();
1700         }
1701         default:
1702             if (Element* ancestor = ancestorElement())
1703                 return ancestor->lookupPrefix(namespaceURI);
1704             return String();
1705     }
1706 }
1707 
lookupNamespaceURI(const String & prefix) const1708 String Node::lookupNamespaceURI(const String &prefix) const
1709 {
1710     // Implemented according to
1711     // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespaceURIAlgo
1712 
1713     if (!prefix.isNull() && prefix.isEmpty())
1714         return String();
1715 
1716     switch (nodeType()) {
1717         case ELEMENT_NODE: {
1718             const Element *elem = static_cast<const Element *>(this);
1719 
1720             if (!elem->namespaceURI().isNull() && elem->prefix() == prefix)
1721                 return elem->namespaceURI();
1722 
1723             if (elem->hasAttributes()) {
1724                 NamedAttrMap *attrs = elem->attributes();
1725 
1726                 for (unsigned i = 0; i < attrs->length(); i++) {
1727                     Attribute *attr = attrs->attributeItem(i);
1728 
1729                     if (attr->prefix() == "xmlns" && attr->localName() == prefix) {
1730                         if (!attr->value().isEmpty())
1731                             return attr->value();
1732 
1733                         return String();
1734                     } else if (attr->localName() == "xmlns" && prefix.isNull()) {
1735                         if (!attr->value().isEmpty())
1736                             return attr->value();
1737 
1738                         return String();
1739                     }
1740                 }
1741             }
1742             if (Element* ancestor = ancestorElement())
1743                 return ancestor->lookupNamespaceURI(prefix);
1744             return String();
1745         }
1746         case DOCUMENT_NODE:
1747             if (Element* de = static_cast<const Document*>(this)->documentElement())
1748                 return de->lookupNamespaceURI(prefix);
1749             return String();
1750         case ENTITY_NODE:
1751         case NOTATION_NODE:
1752         case DOCUMENT_TYPE_NODE:
1753         case DOCUMENT_FRAGMENT_NODE:
1754             return String();
1755         case ATTRIBUTE_NODE: {
1756             const Attr *attr = static_cast<const Attr *>(this);
1757 
1758             if (attr->ownerElement())
1759                 return attr->ownerElement()->lookupNamespaceURI(prefix);
1760             else
1761                 return String();
1762         }
1763         default:
1764             if (Element* ancestor = ancestorElement())
1765                 return ancestor->lookupNamespaceURI(prefix);
1766             return String();
1767     }
1768 }
1769 
lookupNamespacePrefix(const AtomicString & _namespaceURI,const Element * originalElement) const1770 String Node::lookupNamespacePrefix(const AtomicString &_namespaceURI, const Element *originalElement) const
1771 {
1772     if (_namespaceURI.isNull())
1773         return String();
1774 
1775     if (originalElement->lookupNamespaceURI(prefix()) == _namespaceURI)
1776         return prefix();
1777 
1778     if (hasAttributes()) {
1779         NamedAttrMap *attrs = attributes();
1780 
1781         for (unsigned i = 0; i < attrs->length(); i++) {
1782             Attribute *attr = attrs->attributeItem(i);
1783 
1784             if (attr->prefix() == "xmlns" &&
1785                 attr->value() == _namespaceURI &&
1786                 originalElement->lookupNamespaceURI(attr->localName()) == _namespaceURI)
1787                 return attr->localName();
1788         }
1789     }
1790 
1791     if (Element* ancestor = ancestorElement())
1792         return ancestor->lookupNamespacePrefix(_namespaceURI, originalElement);
1793     return String();
1794 }
1795 
appendTextContent(bool convertBRsToNewlines,StringBuilder & content) const1796 void Node::appendTextContent(bool convertBRsToNewlines, StringBuilder& content) const
1797 {
1798     switch (nodeType()) {
1799         case TEXT_NODE:
1800         case CDATA_SECTION_NODE:
1801         case COMMENT_NODE:
1802             content.append(static_cast<const CharacterData*>(this)->CharacterData::nodeValue());
1803             break;
1804 
1805         case PROCESSING_INSTRUCTION_NODE:
1806             content.append(static_cast<const ProcessingInstruction*>(this)->ProcessingInstruction::nodeValue());
1807             break;
1808 
1809         case ELEMENT_NODE:
1810             if (hasTagName(brTag) && convertBRsToNewlines) {
1811                 content.append('\n');
1812                 break;
1813         }
1814         // Fall through.
1815         case ATTRIBUTE_NODE:
1816         case ENTITY_NODE:
1817         case ENTITY_REFERENCE_NODE:
1818         case DOCUMENT_FRAGMENT_NODE:
1819             content.setNonNull();
1820 
1821             for (Node *child = firstChild(); child; child = child->nextSibling()) {
1822                 if (child->nodeType() == COMMENT_NODE || child->nodeType() == PROCESSING_INSTRUCTION_NODE)
1823                     continue;
1824 
1825                 child->appendTextContent(convertBRsToNewlines, content);
1826             }
1827             break;
1828 
1829         case DOCUMENT_NODE:
1830         case DOCUMENT_TYPE_NODE:
1831         case NOTATION_NODE:
1832         case XPATH_NAMESPACE_NODE:
1833             break;
1834     }
1835 }
1836 
textContent(bool convertBRsToNewlines) const1837 String Node::textContent(bool convertBRsToNewlines) const
1838 {
1839     StringBuilder content;
1840     appendTextContent(convertBRsToNewlines, content);
1841     return content.toString();
1842 }
1843 
setTextContent(const String & text,ExceptionCode & ec)1844 void Node::setTextContent(const String &text, ExceptionCode& ec)
1845 {
1846     switch (nodeType()) {
1847         case TEXT_NODE:
1848         case CDATA_SECTION_NODE:
1849         case COMMENT_NODE:
1850         case PROCESSING_INSTRUCTION_NODE:
1851             setNodeValue(text, ec);
1852             break;
1853         case ELEMENT_NODE:
1854         case ATTRIBUTE_NODE:
1855         case ENTITY_NODE:
1856         case ENTITY_REFERENCE_NODE:
1857         case DOCUMENT_FRAGMENT_NODE: {
1858             ContainerNode *container = static_cast<ContainerNode *>(this);
1859 
1860             container->removeChildren();
1861 
1862             if (!text.isEmpty())
1863                 appendChild(document()->createTextNode(text), ec);
1864             break;
1865         }
1866         case DOCUMENT_NODE:
1867         case DOCUMENT_TYPE_NODE:
1868         case NOTATION_NODE:
1869         default:
1870             // Do nothing
1871             break;
1872     }
1873 }
1874 
ancestorElement() const1875 Element* Node::ancestorElement() const
1876 {
1877     // In theory, there can be EntityReference nodes between elements, but this is currently not supported.
1878     for (Node* n = parentNode(); n; n = n->parentNode()) {
1879         if (n->isElementNode())
1880             return static_cast<Element*>(n);
1881     }
1882     return 0;
1883 }
1884 
offsetInCharacters() const1885 bool Node::offsetInCharacters() const
1886 {
1887     return false;
1888 }
1889 
compareDocumentPosition(Node * otherNode)1890 unsigned short Node::compareDocumentPosition(Node* otherNode)
1891 {
1892     // It is not clear what should be done if |otherNode| is 0.
1893     if (!otherNode)
1894         return DOCUMENT_POSITION_DISCONNECTED;
1895 
1896     if (otherNode == this)
1897         return DOCUMENT_POSITION_EQUIVALENT;
1898 
1899     Attr* attr1 = nodeType() == ATTRIBUTE_NODE ? static_cast<Attr*>(this) : 0;
1900     Attr* attr2 = otherNode->nodeType() == ATTRIBUTE_NODE ? static_cast<Attr*>(otherNode) : 0;
1901 
1902     Node* start1 = attr1 ? attr1->ownerElement() : this;
1903     Node* start2 = attr2 ? attr2->ownerElement() : otherNode;
1904 
1905     // If either of start1 or start2 is null, then we are disconnected, since one of the nodes is
1906     // an orphaned attribute node.
1907     if (!start1 || !start2)
1908         return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1909 
1910     Vector<Node*, 16> chain1;
1911     Vector<Node*, 16> chain2;
1912     if (attr1)
1913         chain1.append(attr1);
1914     if (attr2)
1915         chain2.append(attr2);
1916 
1917     if (attr1 && attr2 && start1 == start2 && start1) {
1918         // We are comparing two attributes on the same node.  Crawl our attribute map
1919         // and see which one we hit first.
1920         NamedAttrMap* map = attr1->ownerElement()->attributes(true);
1921         unsigned length = map->length();
1922         for (unsigned i = 0; i < length; ++i) {
1923             // If neither of the two determining nodes is a child node and nodeType is the same for both determining nodes, then an
1924             // implementation-dependent order between the determining nodes is returned. This order is stable as long as no nodes of
1925             // the same nodeType are inserted into or removed from the direct container. This would be the case, for example,
1926             // when comparing two attributes of the same element, and inserting or removing additional attributes might change
1927             // the order between existing attributes.
1928             Attribute* attr = map->attributeItem(i);
1929             if (attr1->attr() == attr)
1930                 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING;
1931             if (attr2->attr() == attr)
1932                 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_PRECEDING;
1933         }
1934 
1935         ASSERT_NOT_REACHED();
1936         return DOCUMENT_POSITION_DISCONNECTED;
1937     }
1938 
1939     // If one node is in the document and the other is not, we must be disconnected.
1940     // If the nodes have different owning documents, they must be disconnected.  Note that we avoid
1941     // comparing Attr nodes here, since they return false from inDocument() all the time (which seems like a bug).
1942     if (start1->inDocument() != start2->inDocument() ||
1943         start1->document() != start2->document())
1944         return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1945 
1946     // We need to find a common ancestor container, and then compare the indices of the two immediate children.
1947     Node* current;
1948     for (current = start1; current; current = current->parentNode())
1949         chain1.append(current);
1950     for (current = start2; current; current = current->parentNode())
1951         chain2.append(current);
1952 
1953     // Walk the two chains backwards and look for the first difference.
1954     unsigned index1 = chain1.size();
1955     unsigned index2 = chain2.size();
1956     for (unsigned i = min(index1, index2); i; --i) {
1957         Node* child1 = chain1[--index1];
1958         Node* child2 = chain2[--index2];
1959         if (child1 != child2) {
1960             // If one of the children is an attribute, it wins.
1961             if (child1->nodeType() == ATTRIBUTE_NODE)
1962                 return DOCUMENT_POSITION_FOLLOWING;
1963             if (child2->nodeType() == ATTRIBUTE_NODE)
1964                 return DOCUMENT_POSITION_PRECEDING;
1965 
1966             if (!child2->nextSibling())
1967                 return DOCUMENT_POSITION_FOLLOWING;
1968             if (!child1->nextSibling())
1969                 return DOCUMENT_POSITION_PRECEDING;
1970 
1971             // Otherwise we need to see which node occurs first.  Crawl backwards from child2 looking for child1.
1972             for (Node* child = child2->previousSibling(); child; child = child->previousSibling()) {
1973                 if (child == child1)
1974                     return DOCUMENT_POSITION_FOLLOWING;
1975             }
1976             return DOCUMENT_POSITION_PRECEDING;
1977         }
1978     }
1979 
1980     // There was no difference between the two parent chains, i.e., one was a subset of the other.  The shorter
1981     // chain is the ancestor.
1982     return index1 < index2 ?
1983                DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_CONTAINED_BY :
1984                DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_CONTAINS;
1985 }
1986 
1987 #if !defined(NDEBUG) || defined(ANDROID_DOM_LOGGING)
1988 
appendAttributeDesc(const Node * node,String & string,const QualifiedName & name,const char * attrDesc)1989 static void appendAttributeDesc(const Node* node, String& string, const QualifiedName& name, const char* attrDesc)
1990 {
1991     if (node->isElementNode()) {
1992         String attr = static_cast<const Element*>(node)->getAttribute(name);
1993         if (!attr.isEmpty()) {
1994             string += attrDesc;
1995             string += attr;
1996         }
1997     }
1998 }
1999 
showNode(const char * prefix) const2000 void Node::showNode(const char* prefix) const
2001 {
2002     if (!prefix)
2003         prefix = "";
2004     if (isTextNode()) {
2005         String value = nodeValue();
2006 #ifdef ANDROID_DOM_LOGGING
2007         bool hasNoneWhitespace = false;
2008         for (int i = value.length()-1; i >= 0; i--)
2009             if (!isSpaceOrNewline(value[i])) {
2010                 hasNoneWhitespace = true;
2011                 break;
2012             }
2013 #endif
2014         value.replace('\\', "\\\\");
2015         value.replace('\n', "\\n");
2016 #ifdef ANDROID_DOM_LOGGING
2017         if (hasNoneWhitespace)
2018             DUMP_DOM_LOGD("%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this, value.utf8().data());
2019 #else
2020         fprintf(stderr, "%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this, value.utf8().data());
2021 #endif
2022     } else {
2023         String attrs = "";
2024         appendAttributeDesc(this, attrs, classAttr, " CLASS=");
2025         appendAttributeDesc(this, attrs, styleAttr, " STYLE=");
2026 #ifdef ANDROID_DOM_LOGGING
2027         appendAttributeDesc(this, attrs, idAttr, " ID=");
2028         appendAttributeDesc(this, attrs, nameAttr, " NAME=");
2029         DUMP_DOM_LOGD("%s%s\t%p%s\n", prefix, nodeName().utf8().data(), this, attrs.utf8().data());
2030 #else
2031         fprintf(stderr, "%s%s\t%p%s\n", prefix, nodeName().utf8().data(), this, attrs.utf8().data());
2032 #endif
2033     }
2034 }
2035 
showTreeForThis() const2036 void Node::showTreeForThis() const
2037 {
2038     showTreeAndMark(this, "*");
2039 }
2040 
showTreeAndMark(const Node * markedNode1,const char * markedLabel1,const Node * markedNode2,const char * markedLabel2) const2041 void Node::showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char * markedLabel2) const
2042 {
2043     const Node* rootNode;
2044     const Node* node = this;
2045     while (node->parentNode() && !node->hasTagName(bodyTag))
2046         node = node->parentNode();
2047     rootNode = node;
2048 
2049     for (node = rootNode; node; node = node->traverseNextNode()) {
2050 #ifdef ANDROID_DOM_LOGGING
2051         String prefix = "";
2052 #endif
2053         if (node == markedNode1)
2054 #ifdef ANDROID_DOM_LOGGING
2055             prefix.append(markedLabel1);
2056 #else
2057             fprintf(stderr, "%s", markedLabel1);
2058 #endif
2059         if (node == markedNode2)
2060 #ifdef ANDROID_DOM_LOGGING
2061             prefix.append(markedLabel2);
2062 #else
2063             fprintf(stderr, "%s", markedLabel2);
2064 #endif
2065 
2066 #ifdef ANDROID_DOM_LOGGING
2067         for (const Node* tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentNode())
2068             prefix.append("\t");
2069         node->showNode(prefix.utf8().data());
2070 #else
2071         for (const Node* tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentNode())
2072             fprintf(stderr, "\t");
2073         node->showNode();
2074 #endif
2075     }
2076 }
2077 
formatForDebugger(char * buffer,unsigned length) const2078 void Node::formatForDebugger(char* buffer, unsigned length) const
2079 {
2080     String result;
2081     String s;
2082 
2083     s = nodeName();
2084     if (s.length() == 0)
2085         result += "<none>";
2086     else
2087         result += s;
2088 
2089     strncpy(buffer, result.utf8().data(), length - 1);
2090 }
2091 
2092 #endif
2093 
2094 // --------
2095 
invalidateCaches()2096 void NodeListsNodeData::invalidateCaches()
2097 {
2098     m_childNodeListCaches.reset();
2099     TagCacheMap::const_iterator tagCachesEnd = m_tagNodeListCaches.end();
2100     for (TagCacheMap::const_iterator it = m_tagNodeListCaches.begin(); it != tagCachesEnd; ++it)
2101         it->second->reset();
2102     invalidateCachesThatDependOnAttributes();
2103 }
2104 
invalidateCachesThatDependOnAttributes()2105 void NodeListsNodeData::invalidateCachesThatDependOnAttributes()
2106 {
2107     CacheMap::iterator classCachesEnd = m_classNodeListCaches.end();
2108     for (CacheMap::iterator it = m_classNodeListCaches.begin(); it != classCachesEnd; ++it)
2109         it->second->reset();
2110 
2111     CacheMap::iterator nameCachesEnd = m_nameNodeListCaches.end();
2112     for (CacheMap::iterator it = m_nameNodeListCaches.begin(); it != nameCachesEnd; ++it)
2113         it->second->reset();
2114 }
2115 
isEmpty() const2116 bool NodeListsNodeData::isEmpty() const
2117 {
2118     if (!m_listsWithCaches.isEmpty())
2119         return false;
2120 
2121     if (m_childNodeListCaches.refCount)
2122         return false;
2123 
2124     TagCacheMap::const_iterator tagCachesEnd = m_tagNodeListCaches.end();
2125     for (TagCacheMap::const_iterator it = m_tagNodeListCaches.begin(); it != tagCachesEnd; ++it) {
2126         if (it->second->refCount)
2127             return false;
2128     }
2129 
2130     CacheMap::const_iterator classCachesEnd = m_classNodeListCaches.end();
2131     for (CacheMap::const_iterator it = m_classNodeListCaches.begin(); it != classCachesEnd; ++it) {
2132         if (it->second->refCount)
2133             return false;
2134     }
2135 
2136     CacheMap::const_iterator nameCachesEnd = m_nameNodeListCaches.end();
2137     for (CacheMap::const_iterator it = m_nameNodeListCaches.begin(); it != nameCachesEnd; ++it) {
2138         if (it->second->refCount)
2139             return false;
2140     }
2141 
2142     return true;
2143 }
2144 
getSubresourceURLs(ListHashSet<KURL> & urls) const2145 void Node::getSubresourceURLs(ListHashSet<KURL>& urls) const
2146 {
2147     addSubresourceAttributeURLs(urls);
2148 }
2149 
eventParentNode()2150 ContainerNode* Node::eventParentNode()
2151 {
2152     Node* parent = parentNode();
2153     ASSERT(!parent || parent->isContainerNode());
2154     return static_cast<ContainerNode*>(parent);
2155 }
2156 
2157 #ifdef ANDROID_INSTRUMENT
2158 static size_t nodeSize = 0;
2159 
operator new(size_t s)2160 void* Node::operator new(size_t s) throw()
2161 {
2162     nodeSize += s;
2163     return ::operator new(s);
2164 }
2165 
operator delete(void * ptr,size_t s)2166 void Node::operator delete(void* ptr, size_t s)
2167 {
2168     nodeSize -= s;
2169     ::operator delete(ptr);
2170 }
2171 
reportDOMNodesSize()2172 size_t Node::reportDOMNodesSize()
2173 {
2174     return nodeSize;
2175 }
2176 #endif
2177 
2178 // --------
2179 
2180 } // namespace WebCore
2181 
2182 #ifndef NDEBUG
2183 
showTree(const WebCore::Node * node)2184 void showTree(const WebCore::Node* node)
2185 {
2186     if (node)
2187         node->showTreeForThis();
2188 }
2189 
2190 #endif
2191