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