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