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, 2011 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 "core/dom/Node.h" 27 28#include "bindings/core/v8/DOMDataStore.h" 29#include "bindings/core/v8/ExceptionState.h" 30#include "bindings/core/v8/ScriptCallStackFactory.h" 31#include "bindings/core/v8/V8DOMWrapper.h" 32#include "core/HTMLNames.h" 33#include "core/XMLNames.h" 34#include "core/accessibility/AXObjectCache.h" 35#include "core/css/resolver/StyleResolver.h" 36#include "core/dom/Attr.h" 37#include "core/dom/Attribute.h" 38#include "core/dom/ChildListMutationScope.h" 39#include "core/dom/ChildNodeList.h" 40#include "core/dom/DOMImplementation.h" 41#include "core/dom/Document.h" 42#include "core/dom/DocumentFragment.h" 43#include "core/dom/DocumentMarkerController.h" 44#include "core/dom/DocumentType.h" 45#include "core/dom/Element.h" 46#include "core/dom/ElementRareData.h" 47#include "core/dom/ElementTraversal.h" 48#include "core/dom/ExceptionCode.h" 49#include "core/dom/LiveNodeList.h" 50#include "core/dom/NodeRareData.h" 51#include "core/dom/NodeRenderingTraversal.h" 52#include "core/dom/NodeTraversal.h" 53#include "core/dom/ProcessingInstruction.h" 54#include "core/dom/Range.h" 55#include "core/dom/StaticNodeList.h" 56#include "core/dom/TemplateContentDocumentFragment.h" 57#include "core/dom/Text.h" 58#include "core/dom/TreeScopeAdopter.h" 59#include "core/dom/UserActionElementSet.h" 60#include "core/dom/WeakNodeMap.h" 61#include "core/dom/shadow/ElementShadow.h" 62#include "core/dom/shadow/InsertionPoint.h" 63#include "core/dom/shadow/ShadowRoot.h" 64#include "core/editing/htmlediting.h" 65#include "core/editing/markup.h" 66#include "core/events/Event.h" 67#include "core/events/EventDispatchMediator.h" 68#include "core/events/EventDispatcher.h" 69#include "core/events/EventListener.h" 70#include "core/events/GestureEvent.h" 71#include "core/events/KeyboardEvent.h" 72#include "core/events/MouseEvent.h" 73#include "core/events/MutationEvent.h" 74#include "core/events/TextEvent.h" 75#include "core/events/TouchEvent.h" 76#include "core/events/UIEvent.h" 77#include "core/events/WheelEvent.h" 78#include "core/frame/EventHandlerRegistry.h" 79#include "core/frame/LocalFrame.h" 80#include "core/frame/Settings.h" 81#include "core/html/HTMLAnchorElement.h" 82#include "core/html/HTMLDialogElement.h" 83#include "core/html/HTMLFrameOwnerElement.h" 84#include "core/html/HTMLStyleElement.h" 85#include "core/page/ContextMenuController.h" 86#include "core/page/EventHandler.h" 87#include "core/page/Page.h" 88#include "core/rendering/FlowThreadController.h" 89#include "core/rendering/RenderBox.h" 90#include "core/svg/graphics/SVGImage.h" 91#include "platform/EventDispatchForbiddenScope.h" 92#include "platform/Partitions.h" 93#include "platform/TraceEvent.h" 94#include "platform/TracedValue.h" 95#include "wtf/HashSet.h" 96#include "wtf/PassOwnPtr.h" 97#include "wtf/RefCountedLeakCounter.h" 98#include "wtf/Vector.h" 99#include "wtf/text/CString.h" 100#include "wtf/text/StringBuilder.h" 101 102namespace blink { 103 104using namespace HTMLNames; 105 106struct SameSizeAsNode : NODE_BASE_CLASSES { 107 uint32_t m_nodeFlags; 108 void* m_pointer[5]; 109}; 110 111COMPILE_ASSERT(sizeof(Node) <= sizeof(SameSizeAsNode), Node_should_stay_small); 112 113#if !ENABLE(OILPAN) 114void* Node::operator new(size_t size) 115{ 116 ASSERT(isMainThread()); 117 return partitionAlloc(Partitions::getObjectModelPartition(), size); 118} 119 120void Node::operator delete(void* ptr) 121{ 122 ASSERT(isMainThread()); 123 partitionFree(ptr); 124} 125#endif 126 127#if DUMP_NODE_STATISTICS 128typedef WillBeHeapHashSet<RawPtrWillBeWeakMember<Node> > WeakNodeSet; 129static WeakNodeSet& liveNodeSet() 130{ 131 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<WeakNodeSet>, set, (adoptPtrWillBeNoop(new WeakNodeSet()))); 132 return *set; 133} 134#endif 135 136void Node::dumpStatistics() 137{ 138#if DUMP_NODE_STATISTICS 139 size_t nodesWithRareData = 0; 140 141 size_t elementNodes = 0; 142 size_t attrNodes = 0; 143 size_t textNodes = 0; 144 size_t cdataNodes = 0; 145 size_t commentNodes = 0; 146 size_t piNodes = 0; 147 size_t documentNodes = 0; 148 size_t docTypeNodes = 0; 149 size_t fragmentNodes = 0; 150 size_t shadowRootNodes = 0; 151 152 HashMap<String, size_t> perTagCount; 153 154 size_t attributes = 0; 155 size_t elementsWithAttributeStorage = 0; 156 size_t elementsWithRareData = 0; 157 size_t elementsWithNamedNodeMap = 0; 158 159 for (WeakNodeSet::iterator it = liveNodeSet().begin(); it != liveNodeSet().end(); ++it) { 160 Node* node = *it; 161 162 if (node->hasRareData()) { 163 ++nodesWithRareData; 164 if (node->isElementNode()) { 165 ++elementsWithRareData; 166 if (toElement(node)->hasNamedNodeMap()) 167 ++elementsWithNamedNodeMap; 168 } 169 } 170 171 switch (node->nodeType()) { 172 case ELEMENT_NODE: { 173 ++elementNodes; 174 175 // Tag stats 176 Element* element = toElement(node); 177 HashMap<String, size_t>::AddResult result = perTagCount.add(element->tagName(), 1); 178 if (!result.isNewEntry) 179 result.storedValue->value++; 180 181 if (const ElementData* elementData = element->elementData()) { 182 attributes += elementData->attributes().size(); 183 ++elementsWithAttributeStorage; 184 } 185 break; 186 } 187 case ATTRIBUTE_NODE: { 188 ++attrNodes; 189 break; 190 } 191 case TEXT_NODE: { 192 ++textNodes; 193 break; 194 } 195 case CDATA_SECTION_NODE: { 196 ++cdataNodes; 197 break; 198 } 199 case COMMENT_NODE: { 200 ++commentNodes; 201 break; 202 } 203 case PROCESSING_INSTRUCTION_NODE: { 204 ++piNodes; 205 break; 206 } 207 case DOCUMENT_NODE: { 208 ++documentNodes; 209 break; 210 } 211 case DOCUMENT_TYPE_NODE: { 212 ++docTypeNodes; 213 break; 214 } 215 case DOCUMENT_FRAGMENT_NODE: { 216 if (node->isShadowRoot()) 217 ++shadowRootNodes; 218 else 219 ++fragmentNodes; 220 break; 221 } 222 } 223 } 224 225 printf("Number of Nodes: %d\n\n", liveNodeSet().size()); 226 printf("Number of Nodes with RareData: %zu\n\n", nodesWithRareData); 227 228 printf("NodeType distribution:\n"); 229 printf(" Number of Element nodes: %zu\n", elementNodes); 230 printf(" Number of Attribute nodes: %zu\n", attrNodes); 231 printf(" Number of Text nodes: %zu\n", textNodes); 232 printf(" Number of CDATASection nodes: %zu\n", cdataNodes); 233 printf(" Number of Comment nodes: %zu\n", commentNodes); 234 printf(" Number of ProcessingInstruction nodes: %zu\n", piNodes); 235 printf(" Number of Document nodes: %zu\n", documentNodes); 236 printf(" Number of DocumentType nodes: %zu\n", docTypeNodes); 237 printf(" Number of DocumentFragment nodes: %zu\n", fragmentNodes); 238 printf(" Number of ShadowRoot nodes: %zu\n", shadowRootNodes); 239 240 printf("Element tag name distibution:\n"); 241 for (HashMap<String, size_t>::iterator it = perTagCount.begin(); it != perTagCount.end(); ++it) 242 printf(" Number of <%s> tags: %zu\n", it->key.utf8().data(), it->value); 243 244 printf("Attributes:\n"); 245 printf(" Number of Attributes (non-Node and Node): %zu [%zu]\n", attributes, sizeof(Attribute)); 246 printf(" Number of Elements with attribute storage: %zu [%zu]\n", elementsWithAttributeStorage, sizeof(ElementData)); 247 printf(" Number of Elements with RareData: %zu\n", elementsWithRareData); 248 printf(" Number of Elements with NamedNodeMap: %zu [%zu]\n", elementsWithNamedNodeMap, sizeof(NamedNodeMap)); 249#endif 250} 251 252DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, nodeCounter, ("WebCoreNode")); 253 254void Node::trackForDebugging() 255{ 256#ifndef NDEBUG 257 nodeCounter.increment(); 258#endif 259 260#if DUMP_NODE_STATISTICS 261 liveNodeSet().add(this); 262#endif 263} 264 265Node::Node(TreeScope* treeScope, ConstructionType type) 266 : m_nodeFlags(type) 267 , m_parentOrShadowHostNode(nullptr) 268 , m_treeScope(treeScope) 269 , m_previous(nullptr) 270 , m_next(nullptr) 271{ 272 ASSERT(m_treeScope || type == CreateDocument || type == CreateShadowRoot); 273#if !ENABLE(OILPAN) 274 if (m_treeScope) 275 m_treeScope->guardRef(); 276#endif 277 278#if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS) 279 trackForDebugging(); 280#endif 281 InspectorCounters::incrementCounter(InspectorCounters::NodeCounter); 282} 283 284Node::~Node() 285{ 286#ifndef NDEBUG 287 nodeCounter.decrement(); 288#endif 289 290#if !ENABLE(OILPAN) 291#if DUMP_NODE_STATISTICS 292 liveNodeSet().remove(this); 293#endif 294 295 if (hasRareData()) 296 clearRareData(); 297 298 RELEASE_ASSERT(!renderer()); 299 300 if (!isContainerNode()) 301 willBeDeletedFromDocument(); 302 303 if (m_previous) 304 m_previous->setNextSibling(0); 305 if (m_next) 306 m_next->setPreviousSibling(0); 307 308 if (m_treeScope) 309 m_treeScope->guardDeref(); 310 311 if (getFlag(HasWeakReferencesFlag)) 312 WeakNodeMap::notifyNodeDestroyed(this); 313#else 314 // With Oilpan, the rare data finalizer also asserts for 315 // this condition (we cannot directly access it here.) 316 RELEASE_ASSERT(hasRareData() || !renderer()); 317#endif 318 319 InspectorCounters::decrementCounter(InspectorCounters::NodeCounter); 320} 321 322#if !ENABLE(OILPAN) 323// With Oilpan all of this is handled with weak processing of the document. 324void Node::willBeDeletedFromDocument() 325{ 326 if (!isTreeScopeInitialized()) 327 return; 328 329 Document& document = this->document(); 330 331 if (hasEventTargetData()) 332 clearEventTargetData(); 333 334 if (document.frameHost()) 335 document.frameHost()->eventHandlerRegistry().didRemoveAllEventHandlers(*this); 336 337 if (AXObjectCache* cache = document.existingAXObjectCache()) 338 cache->remove(this); 339 340 document.markers().removeMarkers(this); 341} 342#endif 343 344NodeRareData* Node::rareData() const 345{ 346 ASSERT_WITH_SECURITY_IMPLICATION(hasRareData()); 347 return static_cast<NodeRareData*>(m_data.m_rareData); 348} 349 350NodeRareData& Node::ensureRareData() 351{ 352 if (hasRareData()) 353 return *rareData(); 354 355 if (isElementNode()) 356 m_data.m_rareData = ElementRareData::create(m_data.m_renderer); 357 else 358 m_data.m_rareData = NodeRareData::create(m_data.m_renderer); 359 360 ASSERT(m_data.m_rareData); 361 362 setFlag(HasRareDataFlag); 363 return *rareData(); 364} 365 366#if !ENABLE(OILPAN) 367void Node::clearRareData() 368{ 369 ASSERT(hasRareData()); 370 ASSERT(!transientMutationObserverRegistry() || transientMutationObserverRegistry()->isEmpty()); 371 372 RenderObject* renderer = m_data.m_rareData->renderer(); 373 if (isElementNode()) 374 delete static_cast<ElementRareData*>(m_data.m_rareData); 375 else 376 delete static_cast<NodeRareData*>(m_data.m_rareData); 377 m_data.m_renderer = renderer; 378 clearFlag(HasRareDataFlag); 379} 380#endif 381 382Node* Node::toNode() 383{ 384 return this; 385} 386 387short Node::tabIndex() const 388{ 389 return 0; 390} 391 392String Node::nodeValue() const 393{ 394 return String(); 395} 396 397void Node::setNodeValue(const String&) 398{ 399 // By default, setting nodeValue has no effect. 400} 401 402PassRefPtrWillBeRawPtr<NodeList> Node::childNodes() 403{ 404 if (isContainerNode()) 405 return ensureRareData().ensureNodeLists().ensureChildNodeList(toContainerNode(*this)); 406 return ensureRareData().ensureNodeLists().ensureEmptyChildNodeList(*this); 407} 408 409Node* Node::pseudoAwarePreviousSibling() const 410{ 411 if (parentElement() && !previousSibling()) { 412 Element* parent = parentElement(); 413 if (isAfterPseudoElement() && parent->lastChild()) 414 return parent->lastChild(); 415 if (!isBeforePseudoElement()) 416 return parent->pseudoElement(BEFORE); 417 } 418 return previousSibling(); 419} 420 421Node* Node::pseudoAwareNextSibling() const 422{ 423 if (parentElement() && !nextSibling()) { 424 Element* parent = parentElement(); 425 if (isBeforePseudoElement() && parent->hasChildren()) 426 return parent->firstChild(); 427 if (!isAfterPseudoElement()) 428 return parent->pseudoElement(AFTER); 429 } 430 return nextSibling(); 431} 432 433Node* Node::pseudoAwareFirstChild() const 434{ 435 if (isElementNode()) { 436 const Element* currentElement = toElement(this); 437 Node* first = currentElement->pseudoElement(BEFORE); 438 if (first) 439 return first; 440 first = currentElement->firstChild(); 441 if (!first) 442 first = currentElement->pseudoElement(AFTER); 443 return first; 444 } 445 446 return firstChild(); 447} 448 449Node* Node::pseudoAwareLastChild() const 450{ 451 if (isElementNode()) { 452 const Element* currentElement = toElement(this); 453 Node* last = currentElement->pseudoElement(AFTER); 454 if (last) 455 return last; 456 last = currentElement->lastChild(); 457 if (!last) 458 last = currentElement->pseudoElement(BEFORE); 459 return last; 460 } 461 462 return lastChild(); 463} 464 465PassRefPtrWillBeRawPtr<Node> Node::insertBefore(PassRefPtrWillBeRawPtr<Node> newChild, Node* refChild, ExceptionState& exceptionState) 466{ 467 if (isContainerNode()) 468 return toContainerNode(this)->insertBefore(newChild, refChild, exceptionState); 469 470 exceptionState.throwDOMException(HierarchyRequestError, "This node type does not support this method."); 471 return nullptr; 472} 473 474PassRefPtrWillBeRawPtr<Node> Node::replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, PassRefPtrWillBeRawPtr<Node> oldChild, ExceptionState& exceptionState) 475{ 476 if (isContainerNode()) 477 return toContainerNode(this)->replaceChild(newChild, oldChild, exceptionState); 478 479 exceptionState.throwDOMException(HierarchyRequestError, "This node type does not support this method."); 480 return nullptr; 481} 482 483PassRefPtrWillBeRawPtr<Node> Node::removeChild(PassRefPtrWillBeRawPtr<Node> oldChild, ExceptionState& exceptionState) 484{ 485 if (isContainerNode()) 486 return toContainerNode(this)->removeChild(oldChild, exceptionState); 487 488 exceptionState.throwDOMException(NotFoundError, "This node type does not support this method."); 489 return nullptr; 490} 491 492PassRefPtrWillBeRawPtr<Node> Node::appendChild(PassRefPtrWillBeRawPtr<Node> newChild, ExceptionState& exceptionState) 493{ 494 if (isContainerNode()) 495 return toContainerNode(this)->appendChild(newChild, exceptionState); 496 497 exceptionState.throwDOMException(HierarchyRequestError, "This node type does not support this method."); 498 return nullptr; 499} 500 501void Node::remove(ExceptionState& exceptionState) 502{ 503 if (ContainerNode* parent = parentNode()) 504 parent->removeChild(this, exceptionState); 505} 506 507void Node::normalize() 508{ 509 document().updateDistributionForNodeIfNeeded(this); 510 511 // Go through the subtree beneath us, normalizing all nodes. This means that 512 // any two adjacent text nodes are merged and any empty text nodes are removed. 513 514 RefPtrWillBeRawPtr<Node> node = this; 515 while (Node* firstChild = node->firstChild()) 516 node = firstChild; 517 while (node) { 518 if (node->isElementNode()) 519 toElement(node)->normalizeAttributes(); 520 521 if (node == this) 522 break; 523 524 if (node->nodeType() == TEXT_NODE) 525 node = toText(node)->mergeNextSiblingNodesIfPossible(); 526 else 527 node = NodeTraversal::nextPostOrder(*node); 528 } 529} 530 531const AtomicString& Node::localName() const 532{ 533 return nullAtom; 534} 535 536const AtomicString& Node::namespaceURI() const 537{ 538 return nullAtom; 539} 540 541bool Node::isContentEditable(UserSelectAllTreatment treatment) 542{ 543 document().updateRenderTreeIfNeeded(); 544 return hasEditableStyle(Editable, treatment); 545} 546 547bool Node::isContentRichlyEditable() 548{ 549 document().updateRenderTreeIfNeeded(); 550 return hasEditableStyle(RichlyEditable, UserSelectAllIsAlwaysNonEditable); 551} 552 553bool Node::hasEditableStyle(EditableLevel editableLevel, UserSelectAllTreatment treatment) const 554{ 555 if (isPseudoElement()) 556 return false; 557 558 // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but 559 // ContainerNode::setFocus() calls setNeedsStyleRecalc(), so the assertion 560 // would fire in the middle of Document::setFocusedNode(). 561 562 for (const Node* node = this; node; node = node->parentNode()) { 563 if ((node->isHTMLElement() || node->isDocumentNode()) && node->renderer()) { 564 // Elements with user-select: all style are considered atomic 565 // therefore non editable. 566 if (Position::nodeIsUserSelectAll(node) && treatment == UserSelectAllIsAlwaysNonEditable) 567 return false; 568 switch (node->renderer()->style()->userModify()) { 569 case READ_ONLY: 570 return false; 571 case READ_WRITE: 572 return true; 573 case READ_WRITE_PLAINTEXT_ONLY: 574 return editableLevel != RichlyEditable; 575 } 576 ASSERT_NOT_REACHED(); 577 return false; 578 } 579 } 580 581 return false; 582} 583 584bool Node::isEditableToAccessibility(EditableLevel editableLevel) const 585{ 586 if (hasEditableStyle(editableLevel)) 587 return true; 588 589 // FIXME: Respect editableLevel for ARIA editable elements. 590 if (editableLevel == RichlyEditable) 591 return false; 592 593 ASSERT(document().settings() && document().settings()->accessibilityEnabled()); 594 ASSERT(document().existingAXObjectCache()); 595 596 if (AXObjectCache* cache = document().existingAXObjectCache()) 597 return cache->rootAXEditableElement(this); 598 599 return false; 600} 601 602RenderBox* Node::renderBox() const 603{ 604 RenderObject* renderer = this->renderer(); 605 return renderer && renderer->isBox() ? toRenderBox(renderer) : 0; 606} 607 608RenderBoxModelObject* Node::renderBoxModelObject() const 609{ 610 RenderObject* renderer = this->renderer(); 611 return renderer && renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0; 612} 613 614LayoutRect Node::boundingBox() const 615{ 616 if (renderer()) 617 return renderer()->absoluteBoundingBoxRect(); 618 return LayoutRect(); 619} 620 621bool Node::hasNonEmptyBoundingBox() const 622{ 623 // Before calling absoluteRects, check for the common case where the renderer 624 // is non-empty, since this is a faster check and almost always returns true. 625 RenderBoxModelObject* box = renderBoxModelObject(); 626 if (!box) 627 return false; 628 if (!box->borderBoundingBox().isEmpty()) 629 return true; 630 631 Vector<IntRect> rects; 632 FloatPoint absPos = renderer()->localToAbsolute(); 633 renderer()->absoluteRects(rects, flooredLayoutPoint(absPos)); 634 size_t n = rects.size(); 635 for (size_t i = 0; i < n; ++i) 636 if (!rects[i].isEmpty()) 637 return true; 638 639 return false; 640} 641 642#ifndef NDEBUG 643inline static ShadowRoot* oldestShadowRootFor(const Node* node) 644{ 645 if (!node->isElementNode()) 646 return 0; 647 if (ElementShadow* shadow = toElement(node)->shadow()) 648 return shadow->oldestShadowRoot(); 649 return 0; 650} 651#endif 652 653void Node::recalcDistribution() 654{ 655 if (isElementNode()) { 656 if (ElementShadow* shadow = toElement(this)->shadow()) 657 shadow->distributeIfNeeded(); 658 } 659 660 for (Node* child = firstChild(); child; child = child->nextSibling()) { 661 if (child->childNeedsDistributionRecalc()) 662 child->recalcDistribution(); 663 } 664 665 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { 666 if (root->childNeedsDistributionRecalc()) 667 root->recalcDistribution(); 668 } 669 670 clearChildNeedsDistributionRecalc(); 671} 672 673void Node::setIsLink(bool isLink) 674{ 675 setFlag(isLink && !SVGImage::isInSVGImage(toElement(this)), IsLinkFlag); 676} 677 678void Node::setNeedsStyleInvalidation() 679{ 680 setFlag(NeedsStyleInvalidationFlag); 681 markAncestorsWithChildNeedsStyleInvalidation(); 682} 683 684void Node::markAncestorsWithChildNeedsStyleInvalidation() 685{ 686 for (Node* node = parentOrShadowHostNode(); node && !node->childNeedsStyleInvalidation(); node = node->parentOrShadowHostNode()) 687 node->setChildNeedsStyleInvalidation(); 688 document().scheduleRenderTreeUpdateIfNeeded(); 689} 690 691void Node::markAncestorsWithChildNeedsDistributionRecalc() 692{ 693 for (Node* node = this; node && !node->childNeedsDistributionRecalc(); node = node->parentOrShadowHostNode()) 694 node->setChildNeedsDistributionRecalc(); 695 document().scheduleRenderTreeUpdateIfNeeded(); 696} 697 698namespace { 699 700void addJsStack(TracedValue* stackFrames) 701{ 702 RefPtrWillBeRawPtr<ScriptCallStack> stack = createScriptCallStack(10); 703 if (!stack) 704 return; 705 for (size_t i = 0; i < stack->size(); i++) 706 stackFrames->pushString(stack->at(i).functionName()); 707} 708 709PassRefPtr<TraceEvent::ConvertableToTraceFormat> jsonObjectForStyleInvalidation(unsigned nodeCount, const Node* rootNode) 710{ 711 RefPtr<TracedValue> value = TracedValue::create(); 712 value->setInteger("node_count", nodeCount); 713 value->setString("root_node", rootNode->debugName()); 714 value->beginArray("js_stack"); 715 addJsStack(value.get()); 716 value->endArray(); 717 return value; 718} 719 720} // anonymous namespace'd functions supporting traceStyleChange 721 722unsigned Node::styledSubtreeSize() const 723{ 724 unsigned nodeCount = 0; 725 726 for (const Node* node = this; node; node = NodeTraversal::next(*node, this)) { 727 if (node->isTextNode() || node->isElementNode()) 728 nodeCount++; 729 for (ShadowRoot* root = node->youngestShadowRoot(); root; root = root->olderShadowRoot()) 730 nodeCount += root->styledSubtreeSize(); 731 } 732 733 return nodeCount; 734} 735 736void Node::traceStyleChange(StyleChangeType changeType) 737{ 738 static const unsigned kMinLoggedSize = 100; 739 unsigned nodeCount = styledSubtreeSize(); 740 if (nodeCount < kMinLoggedSize) 741 return; 742 743 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("style.debug"), 744 "Node::setNeedsStyleRecalc", 745 "data", jsonObjectForStyleInvalidation(nodeCount, this) 746 ); 747} 748 749void Node::traceStyleChangeIfNeeded(StyleChangeType changeType) 750{ 751 // TRACE_EVENT_CATEGORY_GROUP_ENABLED macro loads a global static bool into our local bool. 752 bool styleTracingEnabled; 753 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("style.debug"), &styleTracingEnabled); 754 if (UNLIKELY(styleTracingEnabled)) 755 traceStyleChange(changeType); 756} 757 758inline void Node::setStyleChange(StyleChangeType changeType) 759{ 760 m_nodeFlags = (m_nodeFlags & ~StyleChangeMask) | changeType; 761} 762 763void Node::markAncestorsWithChildNeedsStyleRecalc() 764{ 765 for (ContainerNode* p = parentOrShadowHostNode(); p && !p->childNeedsStyleRecalc(); p = p->parentOrShadowHostNode()) 766 p->setChildNeedsStyleRecalc(); 767 document().scheduleRenderTreeUpdateIfNeeded(); 768} 769 770void Node::setNeedsStyleRecalc(StyleChangeType changeType) 771{ 772 ASSERT(changeType != NoStyleChange); 773 if (!inActiveDocument()) 774 return; 775 776 StyleChangeType existingChangeType = styleChangeType(); 777 if (changeType > existingChangeType) { 778 setStyleChange(changeType); 779 if (changeType >= SubtreeStyleChange) 780 traceStyleChangeIfNeeded(changeType); 781 } 782 783 if (existingChangeType == NoStyleChange) 784 markAncestorsWithChildNeedsStyleRecalc(); 785 786 if (isElementNode() && hasRareData()) 787 toElement(*this).setAnimationStyleChange(false); 788} 789 790void Node::clearNeedsStyleRecalc() 791{ 792 m_nodeFlags &= ~StyleChangeMask; 793 794 clearSVGFilterNeedsLayerUpdate(); 795 796 if (isElementNode() && hasRareData()) 797 toElement(*this).setAnimationStyleChange(false); 798} 799 800bool Node::inActiveDocument() const 801{ 802 return inDocument() && document().isActive(); 803} 804 805Node* Node::focusDelegate() 806{ 807 return this; 808} 809 810bool Node::shouldHaveFocusAppearance() const 811{ 812 ASSERT(focused()); 813 return true; 814} 815 816bool Node::isInert() const 817{ 818 const HTMLDialogElement* dialog = document().activeModalDialog(); 819 if (dialog && this != document() && !NodeRenderingTraversal::contains(dialog, this)) 820 return true; 821 return document().ownerElement() && document().ownerElement()->isInert(); 822} 823 824unsigned Node::nodeIndex() const 825{ 826 Node *_tempNode = previousSibling(); 827 unsigned count=0; 828 for ( count=0; _tempNode; count++ ) 829 _tempNode = _tempNode->previousSibling(); 830 return count; 831} 832 833NodeListsNodeData* Node::nodeLists() 834{ 835 return hasRareData() ? rareData()->nodeLists() : 0; 836} 837 838void Node::clearNodeLists() 839{ 840 rareData()->clearNodeLists(); 841} 842 843bool Node::isDescendantOf(const Node *other) const 844{ 845 // Return true if other is an ancestor of this, otherwise false 846 if (!other || !other->hasChildren() || inDocument() != other->inDocument()) 847 return false; 848 if (other->treeScope() != treeScope()) 849 return false; 850 if (other->isTreeScope()) 851 return !isTreeScope(); 852 for (const ContainerNode* n = parentNode(); n; n = n->parentNode()) { 853 if (n == other) 854 return true; 855 } 856 return false; 857} 858 859bool Node::contains(const Node* node) const 860{ 861 if (!node) 862 return false; 863 return this == node || node->isDescendantOf(this); 864} 865 866bool Node::containsIncludingShadowDOM(const Node* node) const 867{ 868 if (!node) 869 return false; 870 871 if (this == node) 872 return true; 873 874 if (document() != node->document()) 875 return false; 876 877 if (inDocument() != node->inDocument()) 878 return false; 879 880 bool hasChildren = isContainerNode() && toContainerNode(this)->hasChildren(); 881 bool hasShadow = isElementNode() && toElement(this)->shadow(); 882 if (!hasChildren && !hasShadow) 883 return false; 884 885 for (; node; node = node->shadowHost()) { 886 if (treeScope() == node->treeScope()) 887 return contains(node); 888 } 889 890 return false; 891} 892 893bool Node::containsIncludingHostElements(const Node& node) const 894{ 895 const Node* current = &node; 896 do { 897 if (current == this) 898 return true; 899 if (current->isDocumentFragment() && toDocumentFragment(current)->isTemplateContent()) 900 current = static_cast<const TemplateContentDocumentFragment*>(current)->host(); 901 else 902 current = current->parentOrShadowHostNode(); 903 } while (current); 904 return false; 905} 906 907Node* Node::commonAncestor(const Node& other, Node* (*parent)(const Node&)) 908{ 909 if (this == other) 910 return this; 911 if (document() != other.document()) 912 return 0; 913 int thisDepth = 0; 914 for (Node* node = this; node; node = parent(*node)) { 915 if (node == &other) 916 return node; 917 thisDepth++; 918 } 919 int otherDepth = 0; 920 for (const Node* node = &other; node; node = parent(*node)) { 921 if (node == this) 922 return this; 923 otherDepth++; 924 } 925 Node* thisIterator = this; 926 const Node* otherIterator = &other; 927 if (thisDepth > otherDepth) { 928 for (int i = thisDepth; i > otherDepth; --i) 929 thisIterator = parent(*thisIterator); 930 } else if (otherDepth > thisDepth) { 931 for (int i = otherDepth; i > thisDepth; --i) 932 otherIterator = parent(*otherIterator); 933 } 934 while (thisIterator) { 935 if (thisIterator == otherIterator) 936 return thisIterator; 937 thisIterator = parent(*thisIterator); 938 otherIterator = parent(*otherIterator); 939 } 940 ASSERT(!otherIterator); 941 return 0; 942} 943 944void Node::reattach(const AttachContext& context) 945{ 946 AttachContext reattachContext(context); 947 reattachContext.performingReattach = true; 948 949 // We only need to detach if the node has already been through attach(). 950 if (styleChangeType() < NeedsReattachStyleChange) 951 detach(reattachContext); 952 attach(reattachContext); 953} 954 955void Node::attach(const AttachContext&) 956{ 957 ASSERT(document().inStyleRecalc() || isDocumentNode()); 958 ASSERT(needsAttach()); 959 ASSERT(!renderer() || (renderer()->style() && (renderer()->parent() || renderer()->isRenderView()))); 960 961 clearNeedsStyleRecalc(); 962 963 if (AXObjectCache* cache = document().axObjectCache()) 964 cache->updateCacheAfterNodeIsAttached(this); 965} 966 967#if ENABLE(ASSERT) 968static Node* detachingNode; 969 970bool Node::inDetach() const 971{ 972 return detachingNode == this; 973} 974#endif 975 976void Node::detach(const AttachContext& context) 977{ 978 ASSERT(document().lifecycle().stateAllowsDetach()); 979 DocumentLifecycle::DetachScope willDetach(document().lifecycle()); 980 981#if ENABLE(ASSERT) 982 ASSERT(!detachingNode); 983 detachingNode = this; 984#endif 985 986 if (renderer()) 987 renderer()->destroyAndCleanupAnonymousWrappers(); 988 setRenderer(0); 989 990 // Do not remove the element's hovered and active status 991 // if performing a reattach. 992 if (!context.performingReattach) { 993 Document& doc = document(); 994 if (isUserActionElement()) { 995 if (hovered()) 996 doc.hoveredNodeDetached(this); 997 if (inActiveChain()) 998 doc.activeChainNodeDetached(this); 999 doc.userActionElements().didDetach(this); 1000 } 1001 } 1002 1003 setStyleChange(NeedsReattachStyleChange); 1004 setChildNeedsStyleRecalc(); 1005 1006 if (StyleResolver* resolver = document().styleResolver()) 1007 resolver->ruleFeatureSet().styleInvalidator().clearInvalidation(*this); 1008 clearChildNeedsStyleInvalidation(); 1009 clearNeedsStyleInvalidation(); 1010 1011#if ENABLE(ASSERT) 1012 detachingNode = 0; 1013#endif 1014} 1015 1016void Node::reattachWhitespaceSiblings(Text* start) 1017{ 1018 for (Node* sibling = start; sibling; sibling = sibling->nextSibling()) { 1019 if (sibling->isTextNode() && toText(sibling)->containsOnlyWhitespace()) { 1020 bool hadRenderer = !!sibling->renderer(); 1021 sibling->reattach(); 1022 // If the reattach didn't toggle the visibility of the whitespace we don't 1023 // need to continue reattaching siblings since they won't toggle visibility 1024 // either. 1025 if (hadRenderer == !!sibling->renderer()) 1026 return; 1027 } else if (sibling->renderer()) { 1028 return; 1029 } 1030 } 1031} 1032 1033// FIXME: This code is used by editing. Seems like it could move over there and not pollute Node. 1034Node *Node::previousNodeConsideringAtomicNodes() const 1035{ 1036 if (previousSibling()) { 1037 Node *n = previousSibling(); 1038 while (!isAtomicNode(n) && n->lastChild()) 1039 n = n->lastChild(); 1040 return n; 1041 } 1042 else if (parentNode()) { 1043 return parentNode(); 1044 } 1045 else { 1046 return 0; 1047 } 1048} 1049 1050Node *Node::nextNodeConsideringAtomicNodes() const 1051{ 1052 if (!isAtomicNode(this) && hasChildren()) 1053 return firstChild(); 1054 if (nextSibling()) 1055 return nextSibling(); 1056 const Node *n = this; 1057 while (n && !n->nextSibling()) 1058 n = n->parentNode(); 1059 if (n) 1060 return n->nextSibling(); 1061 return 0; 1062} 1063 1064Node *Node::previousLeafNode() const 1065{ 1066 Node *node = previousNodeConsideringAtomicNodes(); 1067 while (node) { 1068 if (isAtomicNode(node)) 1069 return node; 1070 node = node->previousNodeConsideringAtomicNodes(); 1071 } 1072 return 0; 1073} 1074 1075Node *Node::nextLeafNode() const 1076{ 1077 Node *node = nextNodeConsideringAtomicNodes(); 1078 while (node) { 1079 if (isAtomicNode(node)) 1080 return node; 1081 node = node->nextNodeConsideringAtomicNodes(); 1082 } 1083 return 0; 1084} 1085 1086RenderStyle* Node::virtualComputedStyle(PseudoId pseudoElementSpecifier) 1087{ 1088 return parentOrShadowHostNode() ? parentOrShadowHostNode()->computedStyle(pseudoElementSpecifier) : 0; 1089} 1090 1091int Node::maxCharacterOffset() const 1092{ 1093 ASSERT_NOT_REACHED(); 1094 return 0; 1095} 1096 1097// FIXME: Shouldn't these functions be in the editing code? Code that asks questions about HTML in the core DOM class 1098// is obviously misplaced. 1099bool Node::canStartSelection() const 1100{ 1101 if (hasEditableStyle()) 1102 return true; 1103 1104 if (renderer()) { 1105 RenderStyle* style = renderer()->style(); 1106 // We allow selections to begin within an element that has -webkit-user-select: none set, 1107 // but if the element is draggable then dragging should take priority over selection. 1108 if (style->userDrag() == DRAG_ELEMENT && style->userSelect() == SELECT_NONE) 1109 return false; 1110 } 1111 return parentOrShadowHostNode() ? parentOrShadowHostNode()->canStartSelection() : true; 1112} 1113 1114Element* Node::shadowHost() const 1115{ 1116 if (ShadowRoot* root = containingShadowRoot()) 1117 return root->host(); 1118 return 0; 1119} 1120 1121ShadowRoot* Node::containingShadowRoot() const 1122{ 1123 Node& root = treeScope().rootNode(); 1124 return root.isShadowRoot() ? toShadowRoot(&root) : 0; 1125} 1126 1127Node* Node::nonBoundaryShadowTreeRootNode() 1128{ 1129 ASSERT(!isShadowRoot()); 1130 Node* root = this; 1131 while (root) { 1132 if (root->isShadowRoot()) 1133 return root; 1134 Node* parent = root->parentOrShadowHostNode(); 1135 if (parent && parent->isShadowRoot()) 1136 return root; 1137 root = parent; 1138 } 1139 return 0; 1140} 1141 1142ContainerNode* Node::nonShadowBoundaryParentNode() const 1143{ 1144 ContainerNode* parent = parentNode(); 1145 return parent && !parent->isShadowRoot() ? parent : 0; 1146} 1147 1148Element* Node::parentOrShadowHostElement() const 1149{ 1150 ContainerNode* parent = parentOrShadowHostNode(); 1151 if (!parent) 1152 return 0; 1153 1154 if (parent->isShadowRoot()) 1155 return toShadowRoot(parent)->host(); 1156 1157 if (!parent->isElementNode()) 1158 return 0; 1159 1160 return toElement(parent); 1161} 1162 1163ContainerNode* Node::parentOrShadowHostOrTemplateHostNode() const 1164{ 1165 if (isDocumentFragment() && toDocumentFragment(this)->isTemplateContent()) 1166 return static_cast<const TemplateContentDocumentFragment*>(this)->host(); 1167 return parentOrShadowHostNode(); 1168} 1169 1170bool Node::isRootEditableElement() const 1171{ 1172 return hasEditableStyle() && isElementNode() && (!parentNode() || !parentNode()->hasEditableStyle() 1173 || !parentNode()->isElementNode() || isHTMLBodyElement((*this))); 1174} 1175 1176Element* Node::rootEditableElement(EditableType editableType) const 1177{ 1178 if (editableType == HasEditableAXRole) { 1179 if (AXObjectCache* cache = document().existingAXObjectCache()) 1180 return const_cast<Element*>(cache->rootAXEditableElement(this)); 1181 } 1182 1183 return rootEditableElement(); 1184} 1185 1186Element* Node::rootEditableElement() const 1187{ 1188 Element* result = 0; 1189 for (Node* n = const_cast<Node*>(this); n && n->hasEditableStyle(); n = n->parentNode()) { 1190 if (n->isElementNode()) 1191 result = toElement(n); 1192 if (isHTMLBodyElement(*n)) 1193 break; 1194 } 1195 return result; 1196} 1197 1198// FIXME: End of obviously misplaced HTML editing functions. Try to move these out of Node. 1199 1200Document* Node::ownerDocument() const 1201{ 1202 Document* doc = &document(); 1203 return doc == this ? 0 : doc; 1204} 1205 1206KURL Node::baseURI() const 1207{ 1208 return parentNode() ? parentNode()->baseURI() : KURL(); 1209} 1210 1211bool Node::isEqualNode(Node* other) const 1212{ 1213 if (!other) 1214 return false; 1215 1216 NodeType nodeType = this->nodeType(); 1217 if (nodeType != other->nodeType()) 1218 return false; 1219 1220 if (nodeName() != other->nodeName()) 1221 return false; 1222 1223 if (localName() != other->localName()) 1224 return false; 1225 1226 if (namespaceURI() != other->namespaceURI()) 1227 return false; 1228 1229 if (nodeValue() != other->nodeValue()) 1230 return false; 1231 1232 if (isElementNode() && !toElement(this)->hasEquivalentAttributes(toElement(other))) 1233 return false; 1234 1235 Node* child = firstChild(); 1236 Node* otherChild = other->firstChild(); 1237 1238 while (child) { 1239 if (!child->isEqualNode(otherChild)) 1240 return false; 1241 1242 child = child->nextSibling(); 1243 otherChild = otherChild->nextSibling(); 1244 } 1245 1246 if (otherChild) 1247 return false; 1248 1249 if (isDocumentTypeNode()) { 1250 const DocumentType* documentTypeThis = toDocumentType(this); 1251 const DocumentType* documentTypeOther = toDocumentType(other); 1252 1253 if (documentTypeThis->publicId() != documentTypeOther->publicId()) 1254 return false; 1255 1256 if (documentTypeThis->systemId() != documentTypeOther->systemId()) 1257 return false; 1258 } 1259 1260 return true; 1261} 1262 1263bool Node::isDefaultNamespace(const AtomicString& namespaceURIMaybeEmpty) const 1264{ 1265 const AtomicString& namespaceURI = namespaceURIMaybeEmpty.isEmpty() ? nullAtom : namespaceURIMaybeEmpty; 1266 1267 switch (nodeType()) { 1268 case ELEMENT_NODE: { 1269 const Element& element = toElement(*this); 1270 1271 if (element.prefix().isNull()) 1272 return element.namespaceURI() == namespaceURI; 1273 1274 AttributeCollection attributes = element.attributes(); 1275 AttributeCollection::iterator end = attributes.end(); 1276 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) { 1277 if (it->localName() == xmlnsAtom) 1278 return it->value() == namespaceURI; 1279 } 1280 1281 if (Element* parent = parentElement()) 1282 return parent->isDefaultNamespace(namespaceURI); 1283 1284 return false; 1285 } 1286 case DOCUMENT_NODE: 1287 if (Element* de = toDocument(this)->documentElement()) 1288 return de->isDefaultNamespace(namespaceURI); 1289 return false; 1290 case DOCUMENT_TYPE_NODE: 1291 case DOCUMENT_FRAGMENT_NODE: 1292 return false; 1293 case ATTRIBUTE_NODE: { 1294 const Attr* attr = toAttr(this); 1295 if (attr->ownerElement()) 1296 return attr->ownerElement()->isDefaultNamespace(namespaceURI); 1297 return false; 1298 } 1299 default: 1300 if (Element* parent = parentElement()) 1301 return parent->isDefaultNamespace(namespaceURI); 1302 return false; 1303 } 1304} 1305 1306const AtomicString& Node::lookupPrefix(const AtomicString& namespaceURI) const 1307{ 1308 // Implemented according to 1309 // http://dom.spec.whatwg.org/#dom-node-lookupprefix 1310 1311 if (namespaceURI.isEmpty() || namespaceURI.isNull()) 1312 return nullAtom; 1313 1314 const Element* context; 1315 1316 switch (nodeType()) { 1317 case ELEMENT_NODE: 1318 context = toElement(this); 1319 break; 1320 case DOCUMENT_NODE: 1321 context = toDocument(this)->documentElement(); 1322 break; 1323 case DOCUMENT_FRAGMENT_NODE: 1324 case DOCUMENT_TYPE_NODE: 1325 context = 0; 1326 break; 1327 // FIXME: Remove this when Attr no longer extends Node (CR305105) 1328 case ATTRIBUTE_NODE: 1329 context = toAttr(this)->ownerElement(); 1330 break; 1331 default: 1332 context = parentElement(); 1333 break; 1334 } 1335 1336 if (!context) 1337 return nullAtom; 1338 1339 return context->locateNamespacePrefix(namespaceURI); 1340} 1341 1342const AtomicString& Node::lookupNamespaceURI(const String& prefix) const 1343{ 1344 // Implemented according to 1345 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespaceURIAlgo 1346 1347 if (!prefix.isNull() && prefix.isEmpty()) 1348 return nullAtom; 1349 1350 switch (nodeType()) { 1351 case ELEMENT_NODE: { 1352 const Element& element = toElement(*this); 1353 1354 if (!element.namespaceURI().isNull() && element.prefix() == prefix) 1355 return element.namespaceURI(); 1356 1357 AttributeCollection attributes = element.attributes(); 1358 AttributeCollection::iterator end = attributes.end(); 1359 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) { 1360 if (it->prefix() == xmlnsAtom && it->localName() == prefix) { 1361 if (!it->value().isEmpty()) 1362 return it->value(); 1363 return nullAtom; 1364 } 1365 if (it->localName() == xmlnsAtom && prefix.isNull()) { 1366 if (!it->value().isEmpty()) 1367 return it->value(); 1368 return nullAtom; 1369 } 1370 } 1371 1372 if (Element* parent = parentElement()) 1373 return parent->lookupNamespaceURI(prefix); 1374 return nullAtom; 1375 } 1376 case DOCUMENT_NODE: 1377 if (Element* de = toDocument(this)->documentElement()) 1378 return de->lookupNamespaceURI(prefix); 1379 return nullAtom; 1380 case DOCUMENT_TYPE_NODE: 1381 case DOCUMENT_FRAGMENT_NODE: 1382 return nullAtom; 1383 case ATTRIBUTE_NODE: { 1384 const Attr *attr = toAttr(this); 1385 if (attr->ownerElement()) 1386 return attr->ownerElement()->lookupNamespaceURI(prefix); 1387 else 1388 return nullAtom; 1389 } 1390 default: 1391 if (Element* parent = parentElement()) 1392 return parent->lookupNamespaceURI(prefix); 1393 return nullAtom; 1394 } 1395} 1396 1397static void appendTextContent(const Node* node, bool convertBRsToNewlines, bool& isNullString, StringBuilder& content) 1398{ 1399 switch (node->nodeType()) { 1400 case Node::TEXT_NODE: 1401 case Node::CDATA_SECTION_NODE: 1402 case Node::COMMENT_NODE: 1403 isNullString = false; 1404 content.append(toCharacterData(node)->data()); 1405 break; 1406 1407 case Node::PROCESSING_INSTRUCTION_NODE: 1408 isNullString = false; 1409 content.append(toProcessingInstruction(node)->data()); 1410 break; 1411 1412 case Node::ELEMENT_NODE: 1413 if (isHTMLBRElement(*node) && convertBRsToNewlines) { 1414 isNullString = false; 1415 content.append('\n'); 1416 break; 1417 } 1418 // Fall through. 1419 case Node::ATTRIBUTE_NODE: 1420 case Node::DOCUMENT_FRAGMENT_NODE: 1421 isNullString = false; 1422 for (Node* child = toContainerNode(node)->firstChild(); child; child = child->nextSibling()) { 1423 Node::NodeType childNodeType = child->nodeType(); 1424 if (childNodeType == Node::COMMENT_NODE || childNodeType == Node::PROCESSING_INSTRUCTION_NODE) 1425 continue; 1426 appendTextContent(child, convertBRsToNewlines, isNullString, content); 1427 } 1428 break; 1429 1430 case Node::DOCUMENT_NODE: 1431 case Node::DOCUMENT_TYPE_NODE: 1432 break; 1433 } 1434} 1435 1436String Node::textContent(bool convertBRsToNewlines) const 1437{ 1438 StringBuilder content; 1439 bool isNullString = true; 1440 appendTextContent(this, convertBRsToNewlines, isNullString, content); 1441 return isNullString ? String() : content.toString(); 1442} 1443 1444void Node::setTextContent(const String& text) 1445{ 1446 switch (nodeType()) { 1447 case TEXT_NODE: 1448 case CDATA_SECTION_NODE: 1449 case COMMENT_NODE: 1450 case PROCESSING_INSTRUCTION_NODE: 1451 setNodeValue(text); 1452 return; 1453 case ELEMENT_NODE: 1454 case ATTRIBUTE_NODE: 1455 case DOCUMENT_FRAGMENT_NODE: { 1456 // FIXME: Merge this logic into replaceChildrenWithText. 1457 RefPtrWillBeRawPtr<ContainerNode> container = toContainerNode(this); 1458 1459 // Note: This is an intentional optimization. 1460 // See crbug.com/352836 also. 1461 // No need to do anything if the text is identical. 1462 if (container->hasOneTextChild() && toText(container->firstChild())->data() == text) 1463 return; 1464 1465 ChildListMutationScope mutation(*this); 1466 container->removeChildren(); 1467 // Note: This API will not insert empty text nodes: 1468 // http://dom.spec.whatwg.org/#dom-node-textcontent 1469 if (!text.isEmpty()) 1470 container->appendChild(document().createTextNode(text), ASSERT_NO_EXCEPTION); 1471 return; 1472 } 1473 case DOCUMENT_NODE: 1474 case DOCUMENT_TYPE_NODE: 1475 // Do nothing. 1476 return; 1477 } 1478 ASSERT_NOT_REACHED(); 1479} 1480 1481bool Node::offsetInCharacters() const 1482{ 1483 return false; 1484} 1485 1486unsigned short Node::compareDocumentPosition(const Node* otherNode, ShadowTreesTreatment treatment) const 1487{ 1488 // It is not clear what should be done if |otherNode| is 0. 1489 if (!otherNode) 1490 return DOCUMENT_POSITION_DISCONNECTED; 1491 1492 if (otherNode == this) 1493 return DOCUMENT_POSITION_EQUIVALENT; 1494 1495 const Attr* attr1 = nodeType() == ATTRIBUTE_NODE ? toAttr(this) : 0; 1496 const Attr* attr2 = otherNode->nodeType() == ATTRIBUTE_NODE ? toAttr(otherNode) : 0; 1497 1498 const Node* start1 = attr1 ? attr1->ownerElement() : this; 1499 const Node* start2 = attr2 ? attr2->ownerElement() : otherNode; 1500 1501 // If either of start1 or start2 is null, then we are disconnected, since one of the nodes is 1502 // an orphaned attribute node. 1503 if (!start1 || !start2) { 1504 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING; 1505 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction; 1506 } 1507 1508 Vector<const Node*, 16> chain1; 1509 Vector<const Node*, 16> chain2; 1510 if (attr1) 1511 chain1.append(attr1); 1512 if (attr2) 1513 chain2.append(attr2); 1514 1515 if (attr1 && attr2 && start1 == start2 && start1) { 1516 // We are comparing two attributes on the same node. Crawl our attribute map and see which one we hit first. 1517 const Element* owner1 = attr1->ownerElement(); 1518 AttributeCollection attributes = owner1->attributes(); 1519 AttributeCollection::iterator end = attributes.end(); 1520 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) { 1521 // If neither of the two determining nodes is a child node and nodeType is the same for both determining nodes, then an 1522 // implementation-dependent order between the determining nodes is returned. This order is stable as long as no nodes of 1523 // the same nodeType are inserted into or removed from the direct container. This would be the case, for example, 1524 // when comparing two attributes of the same element, and inserting or removing additional attributes might change 1525 // the order between existing attributes. 1526 if (attr1->qualifiedName() == it->name()) 1527 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING; 1528 if (attr2->qualifiedName() == it->name()) 1529 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_PRECEDING; 1530 } 1531 1532 ASSERT_NOT_REACHED(); 1533 return DOCUMENT_POSITION_DISCONNECTED; 1534 } 1535 1536 // If one node is in the document and the other is not, we must be disconnected. 1537 // If the nodes have different owning documents, they must be disconnected. Note that we avoid 1538 // comparing Attr nodes here, since they return false from inDocument() all the time (which seems like a bug). 1539 if (start1->inDocument() != start2->inDocument() || (treatment == TreatShadowTreesAsDisconnected && start1->treeScope() != start2->treeScope())) { 1540 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING; 1541 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction; 1542 } 1543 1544 // We need to find a common ancestor container, and then compare the indices of the two immediate children. 1545 const Node* current; 1546 for (current = start1; current; current = current->parentOrShadowHostNode()) 1547 chain1.append(current); 1548 for (current = start2; current; current = current->parentOrShadowHostNode()) 1549 chain2.append(current); 1550 1551 unsigned index1 = chain1.size(); 1552 unsigned index2 = chain2.size(); 1553 1554 // If the two elements don't have a common root, they're not in the same tree. 1555 if (chain1[index1 - 1] != chain2[index2 - 1]) { 1556 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECEDING : DOCUMENT_POSITION_FOLLOWING; 1557 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | direction; 1558 } 1559 1560 unsigned connection = start1->treeScope() != start2->treeScope() ? DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 0; 1561 1562 // Walk the two chains backwards and look for the first difference. 1563 for (unsigned i = std::min(index1, index2); i; --i) { 1564 const Node* child1 = chain1[--index1]; 1565 const Node* child2 = chain2[--index2]; 1566 if (child1 != child2) { 1567 // If one of the children is an attribute, it wins. 1568 if (child1->nodeType() == ATTRIBUTE_NODE) 1569 return DOCUMENT_POSITION_FOLLOWING | connection; 1570 if (child2->nodeType() == ATTRIBUTE_NODE) 1571 return DOCUMENT_POSITION_PRECEDING | connection; 1572 1573 // If one of the children is a shadow root, 1574 if (child1->isShadowRoot() || child2->isShadowRoot()) { 1575 if (!child2->isShadowRoot()) 1576 return Node::DOCUMENT_POSITION_FOLLOWING | connection; 1577 if (!child1->isShadowRoot()) 1578 return Node::DOCUMENT_POSITION_PRECEDING | connection; 1579 1580 for (ShadowRoot* child = toShadowRoot(child2)->olderShadowRoot(); child; child = child->olderShadowRoot()) 1581 if (child == child1) 1582 return Node::DOCUMENT_POSITION_FOLLOWING | connection; 1583 1584 return Node::DOCUMENT_POSITION_PRECEDING | connection; 1585 } 1586 1587 if (!child2->nextSibling()) 1588 return DOCUMENT_POSITION_FOLLOWING | connection; 1589 if (!child1->nextSibling()) 1590 return DOCUMENT_POSITION_PRECEDING | connection; 1591 1592 // Otherwise we need to see which node occurs first. Crawl backwards from child2 looking for child1. 1593 for (Node* child = child2->previousSibling(); child; child = child->previousSibling()) { 1594 if (child == child1) 1595 return DOCUMENT_POSITION_FOLLOWING | connection; 1596 } 1597 return DOCUMENT_POSITION_PRECEDING | connection; 1598 } 1599 } 1600 1601 // There was no difference between the two parent chains, i.e., one was a subset of the other. The shorter 1602 // chain is the ancestor. 1603 return index1 < index2 ? 1604 DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_CONTAINED_BY | connection : 1605 DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_CONTAINS | connection; 1606} 1607 1608String Node::debugName() const 1609{ 1610 StringBuilder name; 1611 name.append(nodeName()); 1612 1613 if (isElementNode()) { 1614 const Element& thisElement = toElement(*this); 1615 if (thisElement.hasID()) { 1616 name.appendLiteral(" id=\'"); 1617 name.append(thisElement.getIdAttribute()); 1618 name.append('\''); 1619 } 1620 1621 if (thisElement.hasClass()) { 1622 name.appendLiteral(" class=\'"); 1623 for (size_t i = 0; i < thisElement.classNames().size(); ++i) { 1624 if (i > 0) 1625 name.append(' '); 1626 name.append(thisElement.classNames()[i]); 1627 } 1628 name.append('\''); 1629 } 1630 } 1631 1632 return name.toString(); 1633} 1634 1635#ifndef NDEBUG 1636 1637static void appendAttributeDesc(const Node* node, StringBuilder& stringBuilder, const QualifiedName& name, const char* attrDesc) 1638{ 1639 if (!node->isElementNode()) 1640 return; 1641 1642 String attr = toElement(node)->getAttribute(name); 1643 if (attr.isEmpty()) 1644 return; 1645 1646 stringBuilder.append(attrDesc); 1647 stringBuilder.appendLiteral("=\""); 1648 stringBuilder.append(attr); 1649 stringBuilder.appendLiteral("\""); 1650} 1651 1652void Node::showNode(const char* prefix) const 1653{ 1654 if (!prefix) 1655 prefix = ""; 1656 if (isTextNode()) { 1657 String value = nodeValue(); 1658 value.replaceWithLiteral('\\', "\\\\"); 1659 value.replaceWithLiteral('\n', "\\n"); 1660 fprintf(stderr, "%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this, value.utf8().data()); 1661 } else { 1662 StringBuilder attrs; 1663 appendAttributeDesc(this, attrs, idAttr, " ID"); 1664 appendAttributeDesc(this, attrs, classAttr, " CLASS"); 1665 appendAttributeDesc(this, attrs, styleAttr, " STYLE"); 1666 fprintf(stderr, "%s%s\t%p%s\n", prefix, nodeName().utf8().data(), this, attrs.toString().utf8().data()); 1667 } 1668} 1669 1670void Node::showTreeForThis() const 1671{ 1672 showTreeAndMark(this, "*"); 1673} 1674 1675void Node::showNodePathForThis() const 1676{ 1677 Vector<const Node*, 16> chain; 1678 const Node* node = this; 1679 while (node->parentOrShadowHostNode()) { 1680 chain.append(node); 1681 node = node->parentOrShadowHostNode(); 1682 } 1683 for (unsigned index = chain.size(); index > 0; --index) { 1684 const Node* node = chain[index - 1]; 1685 if (node->isShadowRoot()) { 1686 int count = 0; 1687 for (ShadowRoot* shadowRoot = toShadowRoot(node)->olderShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) 1688 ++count; 1689 fprintf(stderr, "/#shadow-root[%d]", count); 1690 continue; 1691 } 1692 1693 switch (node->nodeType()) { 1694 case ELEMENT_NODE: { 1695 fprintf(stderr, "/%s", node->nodeName().utf8().data()); 1696 1697 const Element* element = toElement(node); 1698 const AtomicString& idattr = element->getIdAttribute(); 1699 bool hasIdAttr = !idattr.isNull() && !idattr.isEmpty(); 1700 if (node->previousSibling() || node->nextSibling()) { 1701 int count = 0; 1702 for (Node* previous = node->previousSibling(); previous; previous = previous->previousSibling()) 1703 if (previous->nodeName() == node->nodeName()) 1704 ++count; 1705 if (hasIdAttr) 1706 fprintf(stderr, "[@id=\"%s\" and position()=%d]", idattr.utf8().data(), count); 1707 else 1708 fprintf(stderr, "[%d]", count); 1709 } else if (hasIdAttr) { 1710 fprintf(stderr, "[@id=\"%s\"]", idattr.utf8().data()); 1711 } 1712 break; 1713 } 1714 case TEXT_NODE: 1715 fprintf(stderr, "/text()"); 1716 break; 1717 case ATTRIBUTE_NODE: 1718 fprintf(stderr, "/@%s", node->nodeName().utf8().data()); 1719 break; 1720 default: 1721 break; 1722 } 1723 } 1724 fprintf(stderr, "\n"); 1725} 1726 1727static void traverseTreeAndMark(const String& baseIndent, const Node* rootNode, const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2) 1728{ 1729 for (const Node* node = rootNode; node; node = NodeTraversal::next(*node)) { 1730 if (node == markedNode1) 1731 fprintf(stderr, "%s", markedLabel1); 1732 if (node == markedNode2) 1733 fprintf(stderr, "%s", markedLabel2); 1734 1735 StringBuilder indent; 1736 indent.append(baseIndent); 1737 for (const Node* tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentOrShadowHostNode()) 1738 indent.append('\t'); 1739 fprintf(stderr, "%s", indent.toString().utf8().data()); 1740 node->showNode(); 1741 indent.append('\t'); 1742 if (node->isShadowRoot()) { 1743 if (ShadowRoot* youngerShadowRoot = toShadowRoot(node)->youngerShadowRoot()) 1744 traverseTreeAndMark(indent.toString(), youngerShadowRoot, markedNode1, markedLabel1, markedNode2, markedLabel2); 1745 } else if (ShadowRoot* oldestShadowRoot = oldestShadowRootFor(node)) 1746 traverseTreeAndMark(indent.toString(), oldestShadowRoot, markedNode1, markedLabel1, markedNode2, markedLabel2); 1747 } 1748} 1749 1750void Node::showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char* markedLabel2) const 1751{ 1752 const Node* rootNode; 1753 const Node* node = this; 1754 while (node->parentOrShadowHostNode() && !isHTMLBodyElement(*node)) 1755 node = node->parentOrShadowHostNode(); 1756 rootNode = node; 1757 1758 String startingIndent; 1759 traverseTreeAndMark(startingIndent, rootNode, markedNode1, markedLabel1, markedNode2, markedLabel2); 1760} 1761 1762void Node::formatForDebugger(char* buffer, unsigned length) const 1763{ 1764 String result; 1765 String s; 1766 1767 s = nodeName(); 1768 if (s.isEmpty()) 1769 result = "<none>"; 1770 else 1771 result = s; 1772 1773 strncpy(buffer, result.utf8().data(), length - 1); 1774} 1775 1776static ContainerNode* parentOrShadowHostOrFrameOwner(const Node* node) 1777{ 1778 ContainerNode* parent = node->parentOrShadowHostNode(); 1779 if (!parent && node->document().frame()) 1780 parent = node->document().frame()->deprecatedLocalOwner(); 1781 return parent; 1782} 1783 1784static void showSubTreeAcrossFrame(const Node* node, const Node* markedNode, const String& indent) 1785{ 1786 if (node == markedNode) 1787 fputs("*", stderr); 1788 fputs(indent.utf8().data(), stderr); 1789 node->showNode(); 1790 if (node->isShadowRoot()) { 1791 if (ShadowRoot* youngerShadowRoot = toShadowRoot(node)->youngerShadowRoot()) 1792 showSubTreeAcrossFrame(youngerShadowRoot, markedNode, indent + "\t"); 1793 } else { 1794 if (node->isFrameOwnerElement()) 1795 showSubTreeAcrossFrame(toHTMLFrameOwnerElement(node)->contentDocument(), markedNode, indent + "\t"); 1796 if (ShadowRoot* oldestShadowRoot = oldestShadowRootFor(node)) 1797 showSubTreeAcrossFrame(oldestShadowRoot, markedNode, indent + "\t"); 1798 } 1799 for (Node* child = node->firstChild(); child; child = child->nextSibling()) 1800 showSubTreeAcrossFrame(child, markedNode, indent + "\t"); 1801} 1802 1803void Node::showTreeForThisAcrossFrame() const 1804{ 1805 Node* rootNode = const_cast<Node*>(this); 1806 while (parentOrShadowHostOrFrameOwner(rootNode)) 1807 rootNode = parentOrShadowHostOrFrameOwner(rootNode); 1808 showSubTreeAcrossFrame(rootNode, this, ""); 1809} 1810 1811#endif 1812 1813// -------- 1814 1815Element* Node::enclosingLinkEventParentOrSelf() 1816{ 1817 for (Node* node = this; node; node = NodeRenderingTraversal::parent(node)) { 1818 // For imagemaps, the enclosing link node is the associated area element not the image itself. 1819 // So we don't let images be the enclosingLinkNode, even though isLink sometimes returns true 1820 // for them. 1821 if (node->isLink() && !isHTMLImageElement(*node)) { 1822 // Casting to Element is safe because only HTMLAnchorElement, HTMLImageElement and 1823 // SVGAElement can return true for isLink(). 1824 return toElement(node); 1825 } 1826 } 1827 1828 return 0; 1829} 1830 1831const AtomicString& Node::interfaceName() const 1832{ 1833 return EventTargetNames::Node; 1834} 1835 1836ExecutionContext* Node::executionContext() const 1837{ 1838 return document().contextDocument().get(); 1839} 1840 1841void Node::didMoveToNewDocument(Document& oldDocument) 1842{ 1843 TreeScopeAdopter::ensureDidMoveToNewDocumentWasCalled(oldDocument); 1844 1845 if (const EventTargetData* eventTargetData = this->eventTargetData()) { 1846 const EventListenerMap& listenerMap = eventTargetData->eventListenerMap; 1847 if (!listenerMap.isEmpty()) { 1848 Vector<AtomicString> types = listenerMap.eventTypes(); 1849 for (unsigned i = 0; i < types.size(); ++i) 1850 document().addListenerTypeIfNeeded(types[i]); 1851 } 1852 } 1853 1854 Settings* settings = document().settings(); 1855 if (settings && settings->accessibilityEnabled()) { 1856 if (AXObjectCache* cache = oldDocument.existingAXObjectCache()) 1857 cache->remove(this); 1858 } 1859 1860 oldDocument.markers().removeMarkers(this); 1861 oldDocument.updateRangesAfterNodeMovedToAnotherDocument(*this); 1862 if (oldDocument.frameHost() && !document().frameHost()) 1863 oldDocument.frameHost()->eventHandlerRegistry().didMoveOutOfFrameHost(*this); 1864 else if (document().frameHost() && !oldDocument.frameHost()) 1865 document().frameHost()->eventHandlerRegistry().didMoveIntoFrameHost(*this); 1866 else if (oldDocument.frameHost() != document().frameHost()) 1867 EventHandlerRegistry::didMoveBetweenFrameHosts(*this, oldDocument.frameHost(), document().frameHost()); 1868 1869 if (WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* registry = mutationObserverRegistry()) { 1870 for (size_t i = 0; i < registry->size(); ++i) { 1871 document().addMutationObserverTypes(registry->at(i)->mutationTypes()); 1872 } 1873 } 1874 1875 if (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* transientRegistry = transientMutationObserverRegistry()) { 1876 for (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >::iterator iter = transientRegistry->begin(); iter != transientRegistry->end(); ++iter) { 1877 document().addMutationObserverTypes((*iter)->mutationTypes()); 1878 } 1879 } 1880} 1881 1882static inline bool tryAddEventListener(Node* targetNode, const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 1883{ 1884 if (!targetNode->EventTarget::addEventListener(eventType, listener, useCapture)) 1885 return false; 1886 1887 Document& document = targetNode->document(); 1888 document.addListenerTypeIfNeeded(eventType); 1889 if (document.frameHost()) 1890 document.frameHost()->eventHandlerRegistry().didAddEventHandler(*targetNode, eventType); 1891 1892 return true; 1893} 1894 1895bool Node::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 1896{ 1897 return tryAddEventListener(this, eventType, listener, useCapture); 1898} 1899 1900static inline bool tryRemoveEventListener(Node* targetNode, const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 1901{ 1902 if (!targetNode->EventTarget::removeEventListener(eventType, listener, useCapture)) 1903 return false; 1904 1905 // FIXME: Notify Document that the listener has vanished. We need to keep track of a number of 1906 // listeners for each type, not just a bool - see https://bugs.webkit.org/show_bug.cgi?id=33861 1907 Document& document = targetNode->document(); 1908 if (document.frameHost()) 1909 document.frameHost()->eventHandlerRegistry().didRemoveEventHandler(*targetNode, eventType); 1910 1911 return true; 1912} 1913 1914bool Node::removeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 1915{ 1916 return tryRemoveEventListener(this, eventType, listener, useCapture); 1917} 1918 1919void Node::removeAllEventListeners() 1920{ 1921 if (hasEventListeners() && document().frameHost()) 1922 document().frameHost()->eventHandlerRegistry().didRemoveAllEventHandlers(*this); 1923 EventTarget::removeAllEventListeners(); 1924} 1925 1926void Node::removeAllEventListenersRecursively() 1927{ 1928 for (Node* node = this; node; node = NodeTraversal::next(*node)) { 1929 node->removeAllEventListeners(); 1930 for (ShadowRoot* root = node->youngestShadowRoot(); root; root = root->olderShadowRoot()) 1931 root->removeAllEventListenersRecursively(); 1932 } 1933} 1934 1935typedef WillBeHeapHashMap<RawPtrWillBeWeakMember<Node>, OwnPtr<EventTargetData> > EventTargetDataMap; 1936 1937static EventTargetDataMap& eventTargetDataMap() 1938{ 1939 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<EventTargetDataMap>, map, (adoptPtrWillBeNoop(new EventTargetDataMap()))); 1940 return *map; 1941} 1942 1943EventTargetData* Node::eventTargetData() 1944{ 1945 return hasEventTargetData() ? eventTargetDataMap().get(this) : 0; 1946} 1947 1948EventTargetData& Node::ensureEventTargetData() 1949{ 1950 if (hasEventTargetData()) 1951 return *eventTargetDataMap().get(this); 1952 setHasEventTargetData(true); 1953 EventTargetData* data = new EventTargetData; 1954 eventTargetDataMap().set(this, adoptPtr(data)); 1955 return *data; 1956} 1957 1958#if !ENABLE(OILPAN) 1959void Node::clearEventTargetData() 1960{ 1961 eventTargetDataMap().remove(this); 1962} 1963#endif 1964 1965WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* Node::mutationObserverRegistry() 1966{ 1967 if (!hasRareData()) 1968 return 0; 1969 NodeMutationObserverData* data = rareData()->mutationObserverData(); 1970 if (!data) 1971 return 0; 1972 return &data->registry; 1973} 1974 1975WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* Node::transientMutationObserverRegistry() 1976{ 1977 if (!hasRareData()) 1978 return 0; 1979 NodeMutationObserverData* data = rareData()->mutationObserverData(); 1980 if (!data) 1981 return 0; 1982 return &data->transientRegistry; 1983} 1984 1985template<typename Registry> 1986static inline void collectMatchingObserversForMutation(WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>& observers, Registry* registry, Node& target, MutationObserver::MutationType type, const QualifiedName* attributeName) 1987{ 1988 if (!registry) 1989 return; 1990 for (typename Registry::iterator iter = registry->begin(); iter != registry->end(); ++iter) { 1991 const MutationObserverRegistration& registration = **iter; 1992 if (registration.shouldReceiveMutationFrom(target, type, attributeName)) { 1993 MutationRecordDeliveryOptions deliveryOptions = registration.deliveryOptions(); 1994 WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>::AddResult result = observers.add(®istration.observer(), deliveryOptions); 1995 if (!result.isNewEntry) 1996 result.storedValue->value |= deliveryOptions; 1997 } 1998 } 1999} 2000 2001void Node::getRegisteredMutationObserversOfType(WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>& observers, MutationObserver::MutationType type, const QualifiedName* attributeName) 2002{ 2003 ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName); 2004 collectMatchingObserversForMutation(observers, mutationObserverRegistry(), *this, type, attributeName); 2005 collectMatchingObserversForMutation(observers, transientMutationObserverRegistry(), *this, type, attributeName); 2006 for (Node* node = parentNode(); node; node = node->parentNode()) { 2007 collectMatchingObserversForMutation(observers, node->mutationObserverRegistry(), *this, type, attributeName); 2008 collectMatchingObserversForMutation(observers, node->transientMutationObserverRegistry(), *this, type, attributeName); 2009 } 2010} 2011 2012void Node::registerMutationObserver(MutationObserver& observer, MutationObserverOptions options, const HashSet<AtomicString>& attributeFilter) 2013{ 2014 MutationObserverRegistration* registration = 0; 2015 WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >& registry = ensureRareData().ensureMutationObserverData().registry; 2016 for (size_t i = 0; i < registry.size(); ++i) { 2017 if (®istry[i]->observer() == &observer) { 2018 registration = registry[i].get(); 2019 registration->resetObservation(options, attributeFilter); 2020 } 2021 } 2022 2023 if (!registration) { 2024 registry.append(MutationObserverRegistration::create(observer, this, options, attributeFilter)); 2025 registration = registry.last().get(); 2026 } 2027 2028 document().addMutationObserverTypes(registration->mutationTypes()); 2029} 2030 2031void Node::unregisterMutationObserver(MutationObserverRegistration* registration) 2032{ 2033 WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* registry = mutationObserverRegistry(); 2034 ASSERT(registry); 2035 if (!registry) 2036 return; 2037 2038 size_t index = registry->find(registration); 2039 ASSERT(index != kNotFound); 2040 if (index == kNotFound) 2041 return; 2042 2043 // Deleting the registration may cause this node to be derefed, so we must make sure the Vector operation completes 2044 // before that, in case |this| is destroyed (see MutationObserverRegistration::m_registrationNodeKeepAlive). 2045 // FIXME: Simplify the registration/transient registration logic to make this understandable by humans. 2046 RefPtrWillBeRawPtr<Node> protect(this); 2047#if ENABLE(OILPAN) 2048 // The explicit dispose() is needed to have the registration 2049 // object unregister itself promptly. 2050 registration->dispose(); 2051#endif 2052 registry->remove(index); 2053} 2054 2055void Node::registerTransientMutationObserver(MutationObserverRegistration* registration) 2056{ 2057 ensureRareData().ensureMutationObserverData().transientRegistry.add(registration); 2058} 2059 2060void Node::unregisterTransientMutationObserver(MutationObserverRegistration* registration) 2061{ 2062 WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* transientRegistry = transientMutationObserverRegistry(); 2063 ASSERT(transientRegistry); 2064 if (!transientRegistry) 2065 return; 2066 2067 ASSERT(transientRegistry->contains(registration)); 2068 transientRegistry->remove(registration); 2069} 2070 2071void Node::notifyMutationObserversNodeWillDetach() 2072{ 2073 if (!document().hasMutationObservers()) 2074 return; 2075 2076 for (Node* node = parentNode(); node; node = node->parentNode()) { 2077 if (WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* registry = node->mutationObserverRegistry()) { 2078 const size_t size = registry->size(); 2079 for (size_t i = 0; i < size; ++i) 2080 registry->at(i)->observedSubtreeNodeWillDetach(*this); 2081 } 2082 2083 if (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* transientRegistry = node->transientMutationObserverRegistry()) { 2084 for (WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >::iterator iter = transientRegistry->begin(); iter != transientRegistry->end(); ++iter) 2085 (*iter)->observedSubtreeNodeWillDetach(*this); 2086 } 2087 } 2088} 2089 2090void Node::handleLocalEvents(Event* event) 2091{ 2092 if (!hasEventTargetData()) 2093 return; 2094 2095 if (isDisabledFormControl(this) && event->isMouseEvent()) 2096 return; 2097 2098 fireEventListeners(event); 2099} 2100 2101void Node::dispatchScopedEvent(PassRefPtrWillBeRawPtr<Event> event) 2102{ 2103 dispatchScopedEventDispatchMediator(EventDispatchMediator::create(event)); 2104} 2105 2106void Node::dispatchScopedEventDispatchMediator(PassRefPtrWillBeRawPtr<EventDispatchMediator> eventDispatchMediator) 2107{ 2108 EventDispatcher::dispatchScopedEvent(this, eventDispatchMediator); 2109} 2110 2111bool Node::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event) 2112{ 2113 if (event->isMouseEvent()) 2114 return EventDispatcher::dispatchEvent(this, MouseEventDispatchMediator::create(static_pointer_cast<MouseEvent>(event), MouseEventDispatchMediator::SyntheticMouseEvent)); 2115 if (event->isTouchEvent()) 2116 return dispatchTouchEvent(static_pointer_cast<TouchEvent>(event)); 2117 return EventDispatcher::dispatchEvent(this, EventDispatchMediator::create(event)); 2118} 2119 2120void Node::dispatchSubtreeModifiedEvent() 2121{ 2122 if (isInShadowTree()) 2123 return; 2124 2125 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden()); 2126 2127 if (!document().hasListenerType(Document::DOMSUBTREEMODIFIED_LISTENER)) 2128 return; 2129 2130 dispatchScopedEvent(MutationEvent::create(EventTypeNames::DOMSubtreeModified, true)); 2131} 2132 2133bool Node::dispatchDOMActivateEvent(int detail, PassRefPtrWillBeRawPtr<Event> underlyingEvent) 2134{ 2135 ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden()); 2136 RefPtrWillBeRawPtr<UIEvent> event = UIEvent::create(EventTypeNames::DOMActivate, true, true, document().domWindow(), detail); 2137 event->setUnderlyingEvent(underlyingEvent); 2138 dispatchScopedEvent(event); 2139 return event->defaultHandled(); 2140} 2141 2142bool Node::dispatchKeyEvent(const PlatformKeyboardEvent& event) 2143{ 2144 return EventDispatcher::dispatchEvent(this, KeyboardEventDispatchMediator::create(KeyboardEvent::create(event, document().domWindow()))); 2145} 2146 2147bool Node::dispatchMouseEvent(const PlatformMouseEvent& event, const AtomicString& eventType, 2148 int detail, Node* relatedTarget) 2149{ 2150 return EventDispatcher::dispatchEvent(this, MouseEventDispatchMediator::create(MouseEvent::create(eventType, document().domWindow(), event, detail, relatedTarget))); 2151} 2152 2153bool Node::dispatchGestureEvent(const PlatformGestureEvent& event) 2154{ 2155 RefPtrWillBeRawPtr<GestureEvent> gestureEvent = GestureEvent::create(document().domWindow(), event); 2156 if (!gestureEvent.get()) 2157 return false; 2158 return EventDispatcher::dispatchEvent(this, GestureEventDispatchMediator::create(gestureEvent)); 2159} 2160 2161bool Node::dispatchTouchEvent(PassRefPtrWillBeRawPtr<TouchEvent> event) 2162{ 2163 return EventDispatcher::dispatchEvent(this, TouchEventDispatchMediator::create(event)); 2164} 2165 2166void Node::dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions eventOptions) 2167{ 2168 EventDispatcher::dispatchSimulatedClick(this, underlyingEvent, eventOptions); 2169} 2170 2171bool Node::dispatchWheelEvent(const PlatformWheelEvent& event) 2172{ 2173 return EventDispatcher::dispatchEvent(this, WheelEventDispatchMediator::create(event, document().domWindow())); 2174} 2175 2176void Node::dispatchInputEvent() 2177{ 2178 dispatchScopedEvent(Event::createBubble(EventTypeNames::input)); 2179} 2180 2181void Node::defaultEventHandler(Event* event) 2182{ 2183 if (event->target() != this) 2184 return; 2185 const AtomicString& eventType = event->type(); 2186 if (eventType == EventTypeNames::keydown || eventType == EventTypeNames::keypress) { 2187 if (event->isKeyboardEvent()) { 2188 if (LocalFrame* frame = document().frame()) 2189 frame->eventHandler().defaultKeyboardEventHandler(toKeyboardEvent(event)); 2190 } 2191 } else if (eventType == EventTypeNames::click) { 2192 int detail = event->isUIEvent() ? static_cast<UIEvent*>(event)->detail() : 0; 2193 if (dispatchDOMActivateEvent(detail, event)) 2194 event->setDefaultHandled(); 2195 } else if (eventType == EventTypeNames::contextmenu) { 2196 if (Page* page = document().page()) 2197 page->contextMenuController().handleContextMenuEvent(event); 2198 } else if (eventType == EventTypeNames::textInput) { 2199 if (event->hasInterface(EventNames::TextEvent)) { 2200 if (LocalFrame* frame = document().frame()) 2201 frame->eventHandler().defaultTextInputEventHandler(toTextEvent(event)); 2202 } 2203#if OS(WIN) 2204 } else if (eventType == EventTypeNames::mousedown && event->isMouseEvent()) { 2205 MouseEvent* mouseEvent = toMouseEvent(event); 2206 if (mouseEvent->button() == MiddleButton) { 2207 if (enclosingLinkEventParentOrSelf()) 2208 return; 2209 2210 // Avoid that canBeScrolledAndHasScrollableArea changes render tree 2211 // structure. 2212 // FIXME: We should avoid synchronous layout if possible. We can 2213 // remove this synchronous layout if we avoid synchronous layout in 2214 // RenderTextControlSingleLine::scrollHeight 2215 document().updateLayoutIgnorePendingStylesheets(); 2216 RenderObject* renderer = this->renderer(); 2217 while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea())) 2218 renderer = renderer->parent(); 2219 2220 if (renderer) { 2221 if (LocalFrame* frame = document().frame()) 2222 frame->eventHandler().startPanScrolling(renderer); 2223 } 2224 } 2225#endif 2226 } else if ((eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel) && event->hasInterface(EventNames::WheelEvent)) { 2227 WheelEvent* wheelEvent = toWheelEvent(event); 2228 2229 // If we don't have a renderer, send the wheel event to the first node we find with a renderer. 2230 // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll. 2231 Node* startNode = this; 2232 while (startNode && !startNode->renderer()) 2233 startNode = startNode->parentOrShadowHostNode(); 2234 2235 if (startNode && startNode->renderer()) { 2236 if (LocalFrame* frame = document().frame()) 2237 frame->eventHandler().defaultWheelEventHandler(startNode, wheelEvent); 2238 } 2239 } else if (event->type() == EventTypeNames::webkitEditableContentChanged) { 2240 dispatchInputEvent(); 2241 } 2242} 2243 2244void Node::willCallDefaultEventHandler(const Event&) 2245{ 2246} 2247 2248bool Node::willRespondToMouseMoveEvents() 2249{ 2250 if (isDisabledFormControl(this)) 2251 return false; 2252 return hasEventListeners(EventTypeNames::mousemove) || hasEventListeners(EventTypeNames::mouseover) || hasEventListeners(EventTypeNames::mouseout); 2253} 2254 2255bool Node::willRespondToMouseClickEvents() 2256{ 2257 if (isDisabledFormControl(this)) 2258 return false; 2259 return isContentEditable(UserSelectAllIsAlwaysNonEditable) || hasEventListeners(EventTypeNames::mouseup) || hasEventListeners(EventTypeNames::mousedown) || hasEventListeners(EventTypeNames::click) || hasEventListeners(EventTypeNames::DOMActivate); 2260} 2261 2262bool Node::willRespondToTouchEvents() 2263{ 2264 if (isDisabledFormControl(this)) 2265 return false; 2266 return hasEventListeners(EventTypeNames::touchstart) || hasEventListeners(EventTypeNames::touchmove) || hasEventListeners(EventTypeNames::touchcancel) || hasEventListeners(EventTypeNames::touchend); 2267} 2268 2269#if !ENABLE(OILPAN) 2270// This is here for inlining 2271inline void TreeScope::removedLastRefToScope() 2272{ 2273 ASSERT_WITH_SECURITY_IMPLICATION(!deletionHasBegun()); 2274 if (m_guardRefCount) { 2275 // If removing a child removes the last self-only ref, we don't 2276 // want the scope to be destructed until after 2277 // removeDetachedChildren returns, so we guard ourselves with an 2278 // extra self-only ref. 2279 guardRef(); 2280 dispose(); 2281#if ENABLE(ASSERT) 2282 // We need to do this right now since guardDeref() can delete this. 2283 rootNode().m_inRemovedLastRefFunction = false; 2284#endif 2285 guardDeref(); 2286 } else { 2287#if ENABLE(ASSERT) 2288 rootNode().m_inRemovedLastRefFunction = false; 2289#endif 2290#if ENABLE(SECURITY_ASSERT) 2291 beginDeletion(); 2292#endif 2293 delete this; 2294 } 2295} 2296 2297// It's important not to inline removedLastRef, because we don't want to inline the code to 2298// delete a Node at each deref call site. 2299void Node::removedLastRef() 2300{ 2301 // An explicit check for Document here is better than a virtual function since it is 2302 // faster for non-Document nodes, and because the call to removedLastRef that is inlined 2303 // at all deref call sites is smaller if it's a non-virtual function. 2304 if (isTreeScope()) { 2305 treeScope().removedLastRefToScope(); 2306 return; 2307 } 2308 2309#if ENABLE(SECURITY_ASSERT) 2310 m_deletionHasBegun = true; 2311#endif 2312 delete this; 2313} 2314#endif 2315 2316unsigned Node::connectedSubframeCount() const 2317{ 2318 return hasRareData() ? rareData()->connectedSubframeCount() : 0; 2319} 2320 2321void Node::incrementConnectedSubframeCount(unsigned amount) 2322{ 2323 ASSERT(isContainerNode()); 2324 ensureRareData().incrementConnectedSubframeCount(amount); 2325} 2326 2327void Node::decrementConnectedSubframeCount(unsigned amount) 2328{ 2329 rareData()->decrementConnectedSubframeCount(amount); 2330} 2331 2332void Node::updateAncestorConnectedSubframeCountForRemoval() const 2333{ 2334 unsigned count = connectedSubframeCount(); 2335 2336 if (!count) 2337 return; 2338 2339 for (Node* node = parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode()) 2340 node->decrementConnectedSubframeCount(count); 2341} 2342 2343void Node::updateAncestorConnectedSubframeCountForInsertion() const 2344{ 2345 unsigned count = connectedSubframeCount(); 2346 2347 if (!count) 2348 return; 2349 2350 for (Node* node = parentOrShadowHostNode(); node; node = node->parentOrShadowHostNode()) 2351 node->incrementConnectedSubframeCount(count); 2352} 2353 2354PassRefPtrWillBeRawPtr<StaticNodeList> Node::getDestinationInsertionPoints() 2355{ 2356 document().updateDistributionForNodeIfNeeded(this); 2357 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints; 2358 collectDestinationInsertionPoints(*this, insertionPoints); 2359 WillBeHeapVector<RefPtrWillBeMember<Node> > filteredInsertionPoints; 2360 for (size_t i = 0; i < insertionPoints.size(); ++i) { 2361 InsertionPoint* insertionPoint = insertionPoints[i]; 2362 ASSERT(insertionPoint->containingShadowRoot()); 2363 if (insertionPoint->containingShadowRoot()->type() != ShadowRoot::UserAgentShadowRoot) 2364 filteredInsertionPoints.append(insertionPoint); 2365 } 2366 return StaticNodeList::adopt(filteredInsertionPoints); 2367} 2368 2369void Node::setFocus(bool flag) 2370{ 2371 document().userActionElements().setFocused(this, flag); 2372} 2373 2374void Node::setActive(bool flag) 2375{ 2376 document().userActionElements().setActive(this, flag); 2377} 2378 2379void Node::setHovered(bool flag) 2380{ 2381 document().userActionElements().setHovered(this, flag); 2382} 2383 2384bool Node::isUserActionElementActive() const 2385{ 2386 ASSERT(isUserActionElement()); 2387 return document().userActionElements().isActive(this); 2388} 2389 2390bool Node::isUserActionElementInActiveChain() const 2391{ 2392 ASSERT(isUserActionElement()); 2393 return document().userActionElements().isInActiveChain(this); 2394} 2395 2396bool Node::isUserActionElementHovered() const 2397{ 2398 ASSERT(isUserActionElement()); 2399 return document().userActionElements().isHovered(this); 2400} 2401 2402bool Node::isUserActionElementFocused() const 2403{ 2404 ASSERT(isUserActionElement()); 2405 return document().userActionElements().isFocused(this); 2406} 2407 2408void Node::setCustomElementState(CustomElementState newState) 2409{ 2410 CustomElementState oldState = customElementState(); 2411 2412 switch (newState) { 2413 case NotCustomElement: 2414 ASSERT_NOT_REACHED(); // Everything starts in this state 2415 return; 2416 2417 case WaitingForUpgrade: 2418 ASSERT(NotCustomElement == oldState); 2419 break; 2420 2421 case Upgraded: 2422 ASSERT(WaitingForUpgrade == oldState); 2423 break; 2424 } 2425 2426 ASSERT(isHTMLElement() || isSVGElement()); 2427 setFlag(CustomElementFlag); 2428 setFlag(newState == Upgraded, CustomElementUpgradedFlag); 2429 2430 if (oldState == NotCustomElement || newState == Upgraded) 2431 setNeedsStyleRecalc(SubtreeStyleChange); // :unresolved has changed 2432} 2433 2434void Node::trace(Visitor* visitor) 2435{ 2436#if ENABLE(OILPAN) 2437 visitor->trace(m_parentOrShadowHostNode); 2438 visitor->trace(m_previous); 2439 visitor->trace(m_next); 2440 // rareData() and m_data.m_renderer share their storage. We have to trace 2441 // only one of them. 2442 if (hasRareData()) 2443 visitor->trace(rareData()); 2444 else 2445 visitor->trace(m_data.m_renderer); 2446 visitor->trace(m_treeScope); 2447#endif 2448 EventTarget::trace(visitor); 2449} 2450 2451unsigned Node::lengthOfContents() const 2452{ 2453 // This switch statement must be consistent with that of Range::processContentsBetweenOffsets. 2454 switch (nodeType()) { 2455 case Node::TEXT_NODE: 2456 case Node::CDATA_SECTION_NODE: 2457 case Node::COMMENT_NODE: 2458 return toCharacterData(this)->length(); 2459 case Node::PROCESSING_INSTRUCTION_NODE: 2460 return toProcessingInstruction(this)->data().length(); 2461 case Node::ELEMENT_NODE: 2462 case Node::ATTRIBUTE_NODE: 2463 case Node::DOCUMENT_NODE: 2464 case Node::DOCUMENT_FRAGMENT_NODE: 2465 return toContainerNode(this)->countChildren(); 2466 case Node::DOCUMENT_TYPE_NODE: 2467 return 0; 2468 } 2469 ASSERT_NOT_REACHED(); 2470 return 0; 2471} 2472 2473v8::Handle<v8::Object> Node::wrap(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 2474{ 2475 // It's possible that no one except for the new wrapper owns this object at 2476 // this moment, so we have to prevent GC to collect this object until the 2477 // object gets associated with the wrapper. 2478 RefPtrWillBeRawPtr<Node> protect(this); 2479 2480 ASSERT(!DOMDataStore::containsWrapperNonTemplate(this, isolate)); 2481 2482 const WrapperTypeInfo* wrapperType = wrapperTypeInfo(); 2483 2484 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, wrapperType, toScriptWrappableBase(), isolate); 2485 if (UNLIKELY(wrapper.IsEmpty())) 2486 return wrapper; 2487 2488 wrapperType->installConditionallyEnabledProperties(wrapper, isolate); 2489 return associateWithWrapper(wrapperType, wrapper, isolate); 2490} 2491 2492v8::Handle<v8::Object> Node::associateWithWrapper(const WrapperTypeInfo* wrapperType, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate) 2493{ 2494 return V8DOMWrapper::associateObjectWithWrapperNonTemplate(this, wrapperType, wrapper, isolate); 2495} 2496 2497} // namespace blink 2498 2499#ifndef NDEBUG 2500 2501void showNode(const blink::Node* node) 2502{ 2503 if (node) 2504 node->showNode(""); 2505} 2506 2507void showTree(const blink::Node* node) 2508{ 2509 if (node) 2510 node->showTreeForThis(); 2511} 2512 2513void showNodePath(const blink::Node* node) 2514{ 2515 if (node) 2516 node->showNodePathForThis(); 2517} 2518 2519#endif 2520