1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 6 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 * 23 */ 24 25 #ifndef Node_h 26 #define Node_h 27 28 #include "bindings/v8/ExceptionStatePlaceholder.h" 29 #include "bindings/v8/ScriptWrappable.h" 30 #include "core/dom/MutationObserver.h" 31 #include "core/dom/SimulatedClickOptions.h" 32 #include "core/dom/TreeScope.h" 33 #include "core/dom/TreeShared.h" 34 #include "core/editing/EditingBoundary.h" 35 #include "core/events/EventTarget.h" 36 #include "core/inspector/InspectorCounters.h" 37 #include "core/rendering/style/RenderStyleConstants.h" 38 #include "platform/geometry/LayoutRect.h" 39 #include "platform/heap/Handle.h" 40 #include "platform/weborigin/KURLHash.h" 41 #include "wtf/Forward.h" 42 43 // This needs to be here because Document.h also depends on it. 44 #define DUMP_NODE_STATISTICS 0 45 46 namespace WebCore { 47 48 class Attribute; 49 class ClassCollection; 50 class ContainerNode; 51 class DOMSettableTokenList; 52 class Document; 53 class Element; 54 class Event; 55 class EventDispatchMediator; 56 class EventListener; 57 class ExceptionState; 58 class FloatPoint; 59 class LocalFrame; 60 class HTMLInputElement; 61 class IntRect; 62 class KeyboardEvent; 63 class NSResolver; 64 class NameNodeList; 65 class NamedNodeMap; 66 class NodeEventContext; 67 class NodeList; 68 class NodeListsNodeData; 69 class NodeRareData; 70 class PlatformGestureEvent; 71 class PlatformKeyboardEvent; 72 class PlatformMouseEvent; 73 class PlatformWheelEvent; 74 class QualifiedName; 75 class RadioNodeList; 76 class RegisteredEventListener; 77 class RenderBox; 78 class RenderBoxModelObject; 79 class RenderObject; 80 class RenderStyle; 81 class ShadowRoot; 82 class StaticNodeList; 83 class TagCollection; 84 class Text; 85 class TouchEvent; 86 class WeakNodeMap; 87 88 const int nodeStyleChangeShift = 19; 89 90 enum StyleChangeType { 91 NoStyleChange = 0, 92 LocalStyleChange = 1 << nodeStyleChangeShift, 93 SubtreeStyleChange = 2 << nodeStyleChangeShift, 94 NeedsReattachStyleChange = 3 << nodeStyleChangeShift, 95 }; 96 97 class NodeRareDataBase { 98 public: 99 RenderObject* renderer() const { return m_renderer; } 100 void setRenderer(RenderObject* renderer) { m_renderer = renderer; } 101 102 protected: 103 NodeRareDataBase(RenderObject* renderer) 104 : m_renderer(renderer) 105 { } 106 107 private: 108 RenderObject* m_renderer; 109 }; 110 111 #if ENABLE(OILPAN) 112 #define NODE_BASE_CLASSES public GarbageCollectedFinalized<Node>, public EventTarget, public ScriptWrappable 113 #else 114 // TreeShared should be the last to pack TreeShared::m_refCount and 115 // Node::m_nodeFlags on 64bit platforms. 116 #define NODE_BASE_CLASSES public EventTarget, public ScriptWrappable, public TreeShared<Node> 117 #endif 118 119 class Node : NODE_BASE_CLASSES { 120 friend class Document; 121 friend class TreeScope; 122 friend class TreeScopeAdopter; 123 124 DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(TreeShared<Node>); 125 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(Node); 126 public: 127 enum NodeType { 128 ELEMENT_NODE = 1, 129 ATTRIBUTE_NODE = 2, 130 TEXT_NODE = 3, 131 CDATA_SECTION_NODE = 4, 132 PROCESSING_INSTRUCTION_NODE = 7, 133 COMMENT_NODE = 8, 134 DOCUMENT_NODE = 9, 135 DOCUMENT_TYPE_NODE = 10, 136 DOCUMENT_FRAGMENT_NODE = 11, 137 }; 138 139 // Entity, EntityReference, Notation, and XPathNamespace nodes are impossible to create in Blink. 140 // But for compatibility reasons we want these enum values exist in JS, and this enum makes the bindings 141 // generation not complain about ENTITY_REFERENCE_NODE being missing from the implementation 142 // while not requiring all switch(NodeType) blocks to include this deprecated constant. 143 enum DeprecatedNodeType { 144 ENTITY_REFERENCE_NODE = 5, 145 ENTITY_NODE = 6, 146 NOTATION_NODE = 12, 147 XPATH_NAMESPACE_NODE = 13, 148 }; 149 150 enum DocumentPosition { 151 DOCUMENT_POSITION_EQUIVALENT = 0x00, 152 DOCUMENT_POSITION_DISCONNECTED = 0x01, 153 DOCUMENT_POSITION_PRECEDING = 0x02, 154 DOCUMENT_POSITION_FOLLOWING = 0x04, 155 DOCUMENT_POSITION_CONTAINS = 0x08, 156 DOCUMENT_POSITION_CONTAINED_BY = 0x10, 157 DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20, 158 }; 159 160 #if !ENABLE(OILPAN) 161 // All Nodes are placed in their own heap partition for security. 162 // See http://crbug.com/246860 for detail. 163 void* operator new(size_t); 164 void operator delete(void*); 165 #endif 166 167 static void dumpStatistics(); 168 169 virtual ~Node(); 170 171 // DOM methods & attributes for Node 172 173 bool hasTagName(const QualifiedName&) const; 174 virtual String nodeName() const = 0; 175 virtual String nodeValue() const; 176 virtual void setNodeValue(const String&); 177 virtual NodeType nodeType() const = 0; 178 ContainerNode* parentNode() const; 179 Element* parentElement() const; 180 ContainerNode* parentElementOrShadowRoot() const; 181 ContainerNode* parentElementOrDocumentFragment() const; 182 Node* previousSibling() const { return m_previous; } 183 Node* nextSibling() const { return m_next; } 184 PassRefPtrWillBeRawPtr<NodeList> childNodes(); 185 Node* firstChild() const; 186 Node* lastChild() const; 187 188 void remove(ExceptionState&); 189 190 Node* pseudoAwareNextSibling() const; 191 Node* pseudoAwarePreviousSibling() const; 192 Node* pseudoAwareFirstChild() const; 193 Node* pseudoAwareLastChild() const; 194 195 virtual KURL baseURI() const; 196 197 // These should all actually return a node, but this is only important for language bindings, 198 // which will already know and hold a ref on the right node to return. 199 void insertBefore(PassRefPtrWillBeRawPtr<Node> newChild, Node* refChild, ExceptionState& = ASSERT_NO_EXCEPTION); 200 void replaceChild(PassRefPtrWillBeRawPtr<Node> newChild, Node* oldChild, ExceptionState& = ASSERT_NO_EXCEPTION); 201 void removeChild(Node* child, ExceptionState&); 202 void appendChild(PassRefPtrWillBeRawPtr<Node> newChild, ExceptionState& = ASSERT_NO_EXCEPTION); 203 204 bool hasChildren() const { return firstChild(); } 205 virtual PassRefPtrWillBeRawPtr<Node> cloneNode(bool deep = false) = 0; 206 virtual const AtomicString& localName() const; 207 virtual const AtomicString& namespaceURI() const; 208 void normalize(); 209 210 bool isSameNode(Node* other) const { return this == other; } 211 bool isEqualNode(Node*) const; 212 bool isDefaultNamespace(const AtomicString& namespaceURI) const; 213 const AtomicString& lookupPrefix(const AtomicString& namespaceURI) const; 214 const AtomicString& lookupNamespaceURI(const String& prefix) const; 215 216 String textContent(bool convertBRsToNewlines = false) const; 217 void setTextContent(const String&); 218 219 Node& lastDescendantOrSelf() const; 220 221 // Other methods (not part of DOM) 222 223 bool isElementNode() const { return getFlag(IsElementFlag); } 224 bool isContainerNode() const { return getFlag(IsContainerFlag); } 225 bool isTextNode() const { return getFlag(IsTextFlag); } 226 bool isHTMLElement() const { return getFlag(IsHTMLFlag); } 227 bool isSVGElement() const { return getFlag(IsSVGFlag); } 228 229 bool isPseudoElement() const { return pseudoId() != NOPSEUDO; } 230 bool isBeforePseudoElement() const { return pseudoId() == BEFORE; } 231 bool isAfterPseudoElement() const { return pseudoId() == AFTER; } 232 PseudoId pseudoId() const { return (isElementNode() && hasCustomStyleCallbacks()) ? customPseudoId() : NOPSEUDO; } 233 234 bool isCustomElement() const { return getFlag(CustomElementFlag); } 235 enum CustomElementState { 236 NotCustomElement = 0, 237 WaitingForUpgrade = 1 << 0, 238 Upgraded = 1 << 1 239 }; 240 CustomElementState customElementState() const 241 { 242 return isCustomElement() 243 ? (getFlag(CustomElementUpgradedFlag) ? Upgraded : WaitingForUpgrade) 244 : NotCustomElement; 245 } 246 void setCustomElementState(CustomElementState newState); 247 248 virtual bool isMediaControlElement() const { return false; } 249 virtual bool isMediaControls() const { return false; } 250 virtual bool isVTTElement() const { return false; } 251 virtual bool isAttributeNode() const { return false; } 252 virtual bool isCharacterDataNode() const { return false; } 253 virtual bool isFrameOwnerElement() const { return false; } 254 255 // StyledElements allow inline style (style="border: 1px"), presentational attributes (ex. color), 256 // class names (ex. class="foo bar") and other non-basic styling features. They and also control 257 // if this element can participate in style sharing. 258 // 259 // FIXME: The only things that ever go through StyleResolver that aren't StyledElements are 260 // PseudoElements and VTTElements. It's possible we can just eliminate all the checks 261 // since those elements will never have class names, inline style, or other things that 262 // this apparently guards against. 263 bool isStyledElement() const { return isHTMLElement() || isSVGElement(); } 264 265 bool isDocumentNode() const; 266 bool isTreeScope() const { return &treeScope().rootNode() == this; } 267 bool isDocumentFragment() const { return getFlag(IsDocumentFragmentFlag); } 268 bool isShadowRoot() const { return isDocumentFragment() && isTreeScope(); } 269 bool isInsertionPoint() const { return getFlag(IsInsertionPointFlag); } 270 271 bool hasCustomStyleCallbacks() const { return getFlag(HasCustomStyleCallbacksFlag); } 272 273 bool hasSyntheticAttrChildNodes() const { return getFlag(HasSyntheticAttrChildNodesFlag); } 274 void setHasSyntheticAttrChildNodes(bool flag) { setFlag(flag, HasSyntheticAttrChildNodesFlag); } 275 276 // If this node is in a shadow tree, returns its shadow host. Otherwise, returns 0. 277 Element* shadowHost() const; 278 // If this node is in a shadow tree, returns its shadow host. Otherwise, returns this. 279 // Deprecated. Should use shadowHost() and check the return value. 280 Node* deprecatedShadowAncestorNode() const; 281 ShadowRoot* containingShadowRoot() const; 282 ShadowRoot* youngestShadowRoot() const; 283 284 // Returns 0, a child of ShadowRoot, or a legacy shadow root. 285 Node* nonBoundaryShadowTreeRootNode(); 286 287 // Node's parent, shadow tree host. 288 ContainerNode* parentOrShadowHostNode() const; 289 Element* parentOrShadowHostElement() const; 290 void setParentOrShadowHostNode(ContainerNode*); 291 Node& highestAncestorOrSelf() const; 292 293 // Knows about all kinds of hosts. 294 ContainerNode* parentOrShadowHostOrTemplateHostNode() const; 295 296 // Returns the parent node, but 0 if the parent node is a ShadowRoot. 297 ContainerNode* nonShadowBoundaryParentNode() const; 298 299 bool selfOrAncestorHasDirAutoAttribute() const { return getFlag(SelfOrAncestorHasDirAutoFlag); } 300 void setSelfOrAncestorHasDirAutoAttribute(bool flag) { setFlag(flag, SelfOrAncestorHasDirAutoFlag); } 301 302 // Returns the enclosing event parent node (or self) that, when clicked, would trigger a navigation. 303 Node* enclosingLinkEventParentOrSelf(); 304 305 bool isBlockFlowElement() const; 306 307 // These low-level calls give the caller responsibility for maintaining the integrity of the tree. 308 void setPreviousSibling(Node* previous) { m_previous = previous; } 309 void setNextSibling(Node* next) { m_next = next; } 310 311 virtual bool canContainRangeEndPoint() const { return false; } 312 313 // FIXME: These two functions belong in editing -- "atomic node" is an editing concept. 314 Node* previousNodeConsideringAtomicNodes() const; 315 Node* nextNodeConsideringAtomicNodes() const; 316 317 // Returns the next leaf node or 0 if there are no more. 318 // Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes. 319 // Uses an editing-specific concept of what a leaf node is, and should probably be moved 320 // out of the Node class into an editing-specific source file. 321 Node* nextLeafNode() const; 322 323 // Returns the previous leaf node or 0 if there are no more. 324 // Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes. 325 // Uses an editing-specific concept of what a leaf node is, and should probably be moved 326 // out of the Node class into an editing-specific source file. 327 Node* previousLeafNode() const; 328 329 // enclosingBlockFlowElement() is deprecated. Use enclosingBlock instead. 330 Element* enclosingBlockFlowElement() const; 331 332 bool isRootEditableElement() const; 333 Element* rootEditableElement() const; 334 Element* rootEditableElement(EditableType) const; 335 336 bool inSameContainingBlockFlowElement(Node*); 337 338 // For <link> and <style> elements. 339 virtual bool sheetLoaded() { return true; } 340 virtual void notifyLoadedSheetAndAllCriticalSubresources(bool /* error loading subresource */) { } 341 virtual void startLoadingDynamicSheet() { ASSERT_NOT_REACHED(); } 342 343 bool hasName() const { return !isTextNode() && getFlag(HasNameOrIsEditingTextFlag); } 344 bool hasID() const; 345 bool hasClass() const; 346 347 bool isUserActionElement() const { return getFlag(IsUserActionElementFlag); } 348 void setUserActionElement(bool flag) { setFlag(flag, IsUserActionElementFlag); } 349 350 bool active() const { return isUserActionElement() && isUserActionElementActive(); } 351 bool inActiveChain() const { return isUserActionElement() && isUserActionElementInActiveChain(); } 352 bool hovered() const { return isUserActionElement() && isUserActionElementHovered(); } 353 bool focused() const { return isUserActionElement() && isUserActionElementFocused(); } 354 355 bool needsAttach() const { return styleChangeType() == NeedsReattachStyleChange; } 356 bool needsStyleRecalc() const { return styleChangeType() != NoStyleChange; } 357 StyleChangeType styleChangeType() const { return static_cast<StyleChangeType>(m_nodeFlags & StyleChangeMask); } 358 bool childNeedsStyleRecalc() const { return getFlag(ChildNeedsStyleRecalcFlag); } 359 bool isLink() const { return getFlag(IsLinkFlag); } 360 bool isEditingText() const { return isTextNode() && getFlag(HasNameOrIsEditingTextFlag); } 361 362 void setHasName(bool f) { ASSERT(!isTextNode()); setFlag(f, HasNameOrIsEditingTextFlag); } 363 void setChildNeedsStyleRecalc() { setFlag(ChildNeedsStyleRecalcFlag); } 364 void clearChildNeedsStyleRecalc() { clearFlag(ChildNeedsStyleRecalcFlag); } 365 366 void setNeedsStyleRecalc(StyleChangeType); 367 void clearNeedsStyleRecalc(); 368 369 bool childNeedsDistributionRecalc() const { return getFlag(ChildNeedsDistributionRecalcFlag); } 370 void setChildNeedsDistributionRecalc() { setFlag(ChildNeedsDistributionRecalcFlag); } 371 void clearChildNeedsDistributionRecalc() { clearFlag(ChildNeedsDistributionRecalcFlag); } 372 void markAncestorsWithChildNeedsDistributionRecalc(); 373 374 bool childNeedsStyleInvalidation() const { return getFlag(ChildNeedsStyleInvalidationFlag); } 375 void setChildNeedsStyleInvalidation() { setFlag(ChildNeedsStyleInvalidationFlag); } 376 void clearChildNeedsStyleInvalidation() { clearFlag(ChildNeedsStyleInvalidationFlag); } 377 void markAncestorsWithChildNeedsStyleInvalidation(); 378 bool needsStyleInvalidation() const { return getFlag(NeedsStyleInvalidationFlag); } 379 void clearNeedsStyleInvalidation() { clearFlag(NeedsStyleInvalidationFlag); } 380 void setNeedsStyleInvalidation(); 381 382 void recalcDistribution(); 383 384 bool svgFilterNeedsLayerUpdate() const { return getFlag(SVGFilterNeedsLayerUpdateFlag); } 385 void setSVGFilterNeedsLayerUpdate() { setFlag(SVGFilterNeedsLayerUpdateFlag); } 386 void clearSVGFilterNeedsLayerUpdate() { clearFlag(SVGFilterNeedsLayerUpdateFlag); } 387 388 void setIsLink(bool f); 389 390 bool hasEventTargetData() const { return getFlag(HasEventTargetDataFlag); } 391 void setHasEventTargetData(bool flag) { setFlag(flag, HasEventTargetDataFlag); } 392 393 bool isV8CollectableDuringMinorGC() const { return getFlag(V8CollectableDuringMinorGCFlag); } 394 void markV8CollectableDuringMinorGC() { setFlag(true, V8CollectableDuringMinorGCFlag); } 395 void clearV8CollectableDuringMinorGC() { setFlag(false, V8CollectableDuringMinorGCFlag); } 396 397 virtual void setFocus(bool flag); 398 virtual void setActive(bool flag = true); 399 virtual void setHovered(bool flag = true); 400 401 virtual short tabIndex() const; 402 403 virtual Node* focusDelegate(); 404 // This is called only when the node is focused. 405 virtual bool shouldHaveFocusAppearance() const; 406 407 // Whether the node is inert. This can't be in Element because text nodes 408 // must be recognized as inert to prevent text selection. 409 bool isInert() const; 410 411 enum UserSelectAllTreatment { 412 UserSelectAllDoesNotAffectEditability, 413 UserSelectAllIsAlwaysNonEditable 414 }; 415 bool isContentEditable(UserSelectAllTreatment = UserSelectAllDoesNotAffectEditability); 416 bool isContentRichlyEditable(); 417 418 bool rendererIsEditable(EditableType editableType = ContentIsEditable, UserSelectAllTreatment treatment = UserSelectAllIsAlwaysNonEditable) const 419 { 420 switch (editableType) { 421 case ContentIsEditable: 422 return rendererIsEditable(Editable, treatment); 423 case HasEditableAXRole: 424 return isEditableToAccessibility(Editable); 425 } 426 ASSERT_NOT_REACHED(); 427 return false; 428 } 429 430 bool rendererIsRichlyEditable(EditableType editableType = ContentIsEditable) const 431 { 432 switch (editableType) { 433 case ContentIsEditable: 434 return rendererIsEditable(RichlyEditable, UserSelectAllIsAlwaysNonEditable); 435 case HasEditableAXRole: 436 return isEditableToAccessibility(RichlyEditable); 437 } 438 ASSERT_NOT_REACHED(); 439 return false; 440 } 441 442 virtual bool shouldUseInputMethod(); 443 virtual LayoutRect boundingBox() const; 444 IntRect pixelSnappedBoundingBox() const { return pixelSnappedIntRect(boundingBox()); } 445 446 // Returns true if the node has a non-empty bounding box in layout. 447 // This does not 100% guarantee the user can see it, but is pretty close. 448 // Note: This method only works properly after layout has occurred. 449 bool hasNonEmptyBoundingBox() const; 450 451 unsigned nodeIndex() const; 452 453 // Returns the DOM ownerDocument attribute. This method never returns NULL, except in the case 454 // of a Document node. 455 Document* ownerDocument() const; 456 457 // Returns the document associated with this node. A Document node returns itself. 458 Document& document() const 459 { 460 return treeScope().document(); 461 } 462 463 TreeScope& treeScope() const 464 { 465 ASSERT(m_treeScope); 466 return *m_treeScope; 467 } 468 469 bool inActiveDocument() const; 470 471 // Returns true if this node is associated with a document and is in its associated document's 472 // node tree, false otherwise. 473 bool inDocument() const 474 { 475 return getFlag(InDocumentFlag); 476 } 477 bool isInShadowTree() const { return getFlag(IsInShadowTreeFlag); } 478 bool isInTreeScope() const { return getFlag(static_cast<NodeFlags>(InDocumentFlag | IsInShadowTreeFlag)); } 479 480 bool isDocumentTypeNode() const { return nodeType() == DOCUMENT_TYPE_NODE; } 481 virtual bool childTypeAllowed(NodeType) const { return false; } 482 unsigned countChildren() const; 483 Node* traverseToChildAt(unsigned index) const; 484 485 bool isDescendantOf(const Node*) const; 486 bool contains(const Node*) const; 487 bool containsIncludingShadowDOM(const Node*) const; 488 bool containsIncludingHostElements(const Node&) const; 489 Node* commonAncestor(const Node&, Node* (*parent)(const Node&)); 490 491 // Used to determine whether range offsets use characters or node indices. 492 virtual bool offsetInCharacters() const; 493 // Number of DOM 16-bit units contained in node. Note that rendered text length can be different - e.g. because of 494 // css-transform:capitalize breaking up precomposed characters and ligatures. 495 virtual int maxCharacterOffset() const; 496 497 // Whether or not a selection can be started in this object 498 virtual bool canStartSelection() const; 499 500 // Getting points into and out of screen space 501 FloatPoint convertToPage(const FloatPoint&) const; 502 FloatPoint convertFromPage(const FloatPoint&) const; 503 504 // ----------------------------------------------------------------------------- 505 // Integration with rendering tree 506 507 // As renderer() includes a branch you should avoid calling it repeatedly in hot code paths. 508 // Note that if a Node has a renderer, it's parentNode is guaranteed to have one as well. 509 RenderObject* renderer() const { return hasRareData() ? m_data.m_rareData->renderer() : m_data.m_renderer; }; 510 void setRenderer(RenderObject* renderer) 511 { 512 if (hasRareData()) 513 m_data.m_rareData->setRenderer(renderer); 514 else 515 m_data.m_renderer = renderer; 516 } 517 518 // Use these two methods with caution. 519 RenderBox* renderBox() const; 520 RenderBoxModelObject* renderBoxModelObject() const; 521 522 struct AttachContext { 523 RenderStyle* resolvedStyle; 524 bool performingReattach; 525 526 AttachContext() : resolvedStyle(0), performingReattach(false) { } 527 }; 528 529 // Attaches this node to the rendering tree. This calculates the style to be applied to the node and creates an 530 // appropriate RenderObject which will be inserted into the tree (except when the style has display: none). This 531 // makes the node visible in the FrameView. 532 virtual void attach(const AttachContext& = AttachContext()); 533 534 // Detaches the node from the rendering tree, making it invisible in the rendered view. This method will remove 535 // the node's rendering object from the rendering tree and delete it. 536 virtual void detach(const AttachContext& = AttachContext()); 537 538 #ifndef NDEBUG 539 bool inDetach() const; 540 #endif 541 542 void reattach(const AttachContext& = AttachContext()); 543 void lazyReattachIfAttached(); 544 545 // Returns true if recalcStyle should be called on the object, if there is such a method (on Document and Element). 546 bool shouldCallRecalcStyle(StyleRecalcChange); 547 548 // Wrapper for nodes that don't have a renderer, but still cache the style (like HTMLOptionElement). 549 RenderStyle* renderStyle() const; 550 RenderStyle* parentRenderStyle() const; 551 552 RenderStyle* computedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return virtualComputedStyle(pseudoElementSpecifier); } 553 554 // ----------------------------------------------------------------------------- 555 // Notification of document structure changes (see ContainerNode.h for more notification methods) 556 // 557 // At first, WebKit notifies the node that it has been inserted into the document. This is called during document parsing, and also 558 // when a node is added through the DOM methods insertBefore(), appendChild() or replaceChild(). The call happens _after_ the node has been added to the tree. 559 // This is similar to the DOMNodeInsertedIntoDocument DOM event, but does not require the overhead of event 560 // dispatching. 561 // 562 // WebKit notifies this callback regardless if the subtree of the node is a document tree or a floating subtree. 563 // Implementation can determine the type of subtree by seeing insertionPoint->inDocument(). 564 // For a performance reason, notifications are delivered only to ContainerNode subclasses if the insertionPoint is out of document. 565 // 566 // There are another callback named didNotifySubtreeInsertionsToDocument(), which is called after all the descendant is notified, 567 // if this node was inserted into the document tree. Only a few subclasses actually need this. To utilize this, the node should 568 // return InsertionShouldCallDidNotifySubtreeInsertions from insertedInto(). 569 // 570 enum InsertionNotificationRequest { 571 InsertionDone, 572 InsertionShouldCallDidNotifySubtreeInsertions 573 }; 574 575 virtual InsertionNotificationRequest insertedInto(ContainerNode* insertionPoint); 576 virtual void didNotifySubtreeInsertionsToDocument() { } 577 578 // Notifies the node that it is no longer part of the tree. 579 // 580 // This is a dual of insertedInto(), and is similar to the DOMNodeRemovedFromDocument DOM event, but does not require the overhead of event 581 // dispatching, and is called _after_ the node is removed from the tree. 582 // 583 virtual void removedFrom(ContainerNode* insertionPoint); 584 585 String debugName() const; 586 587 #ifndef NDEBUG 588 virtual void formatForDebugger(char* buffer, unsigned length) const; 589 590 void showNode(const char* prefix = "") const; 591 void showTreeForThis() const; 592 void showNodePathForThis() const; 593 void showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2 = 0, const char* markedLabel2 = 0) const; 594 void showTreeForThisAcrossFrame() const; 595 #endif 596 597 void invalidateNodeListCachesInAncestors(const QualifiedName* attrName = 0, Element* attributeOwnerElement = 0); 598 NodeListsNodeData* nodeLists(); 599 void clearNodeLists(); 600 601 virtual bool willRespondToMouseMoveEvents(); 602 virtual bool willRespondToMouseClickEvents(); 603 virtual bool willRespondToTouchEvents(); 604 605 unsigned short compareDocumentPosition(const Node*) const; 606 607 enum ShadowTreesTreatment { 608 TreatShadowTreesAsDisconnected, 609 TreatShadowTreesAsComposed 610 }; 611 612 unsigned short compareDocumentPositionInternal(const Node*, ShadowTreesTreatment) const; 613 614 virtual Node* toNode() OVERRIDE FINAL; 615 616 virtual const AtomicString& interfaceName() const OVERRIDE; 617 virtual ExecutionContext* executionContext() const OVERRIDE FINAL; 618 619 virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture = false) OVERRIDE; 620 virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture = false) OVERRIDE; 621 virtual void removeAllEventListeners() OVERRIDE; 622 void removeAllEventListenersRecursively(); 623 624 // Handlers to do/undo actions on the target node before an event is dispatched to it and after the event 625 // has been dispatched. The data pointer is handed back by the preDispatch and passed to postDispatch. 626 virtual void* preDispatchEventHandler(Event*) { return 0; } 627 virtual void postDispatchEventHandler(Event*, void* /*dataFromPreDispatch*/) { } 628 629 using EventTarget::dispatchEvent; 630 virtual bool dispatchEvent(PassRefPtrWillBeRawPtr<Event>) OVERRIDE; 631 632 void dispatchScopedEvent(PassRefPtrWillBeRawPtr<Event>); 633 void dispatchScopedEventDispatchMediator(PassRefPtrWillBeRawPtr<EventDispatchMediator>); 634 635 virtual void handleLocalEvents(Event*); 636 637 void dispatchSubtreeModifiedEvent(); 638 bool dispatchDOMActivateEvent(int detail, PassRefPtrWillBeRawPtr<Event> underlyingEvent); 639 640 bool dispatchKeyEvent(const PlatformKeyboardEvent&); 641 bool dispatchWheelEvent(const PlatformWheelEvent&); 642 bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, int clickCount = 0, Node* relatedTarget = 0); 643 bool dispatchGestureEvent(const PlatformGestureEvent&); 644 bool dispatchTouchEvent(PassRefPtrWillBeRawPtr<TouchEvent>); 645 646 void dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions = SendNoEvents); 647 648 void dispatchInputEvent(); 649 650 // Perform the default action for an event. 651 virtual void defaultEventHandler(Event*); 652 virtual void willCallDefaultEventHandler(const Event&); 653 654 virtual EventTargetData* eventTargetData() OVERRIDE; 655 virtual EventTargetData& ensureEventTargetData() OVERRIDE; 656 657 void getRegisteredMutationObserversOfType(WillBeHeapHashMap<RawPtrWillBeMember<MutationObserver>, MutationRecordDeliveryOptions>&, MutationObserver::MutationType, const QualifiedName* attributeName); 658 void registerMutationObserver(MutationObserver&, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter); 659 void unregisterMutationObserver(MutationObserverRegistration*); 660 void registerTransientMutationObserver(MutationObserverRegistration*); 661 void unregisterTransientMutationObserver(MutationObserverRegistration*); 662 void notifyMutationObserversNodeWillDetach(); 663 664 unsigned connectedSubframeCount() const; 665 void incrementConnectedSubframeCount(unsigned amount = 1); 666 void decrementConnectedSubframeCount(unsigned amount = 1); 667 void updateAncestorConnectedSubframeCountForRemoval() const; 668 void updateAncestorConnectedSubframeCountForInsertion() const; 669 670 PassRefPtrWillBeRawPtr<StaticNodeList> getDestinationInsertionPoints(); 671 672 void setAlreadySpellChecked(bool flag) { setFlag(flag, AlreadySpellCheckedFlag); } 673 bool isAlreadySpellChecked() { return getFlag(AlreadySpellCheckedFlag); } 674 675 bool isFinishedParsingChildren() const { return getFlag(IsFinishedParsingChildrenFlag); } 676 677 virtual void trace(Visitor*) OVERRIDE; 678 679 unsigned lengthOfContents() const; 680 681 private: 682 enum NodeFlags { 683 HasRareDataFlag = 1, 684 685 // Node type flags. These never change once created. 686 IsTextFlag = 1 << 1, 687 IsContainerFlag = 1 << 2, 688 IsElementFlag = 1 << 3, 689 IsHTMLFlag = 1 << 4, 690 IsSVGFlag = 1 << 5, 691 IsDocumentFragmentFlag = 1 << 6, 692 IsInsertionPointFlag = 1 << 7, 693 694 // Changes based on if the element should be treated like a link, 695 // ex. When setting the href attribute on an <a>. 696 IsLinkFlag = 1 << 8, 697 698 // Changes based on :hover, :active and :focus state. 699 IsUserActionElementFlag = 1 << 9, 700 701 // Tree state flags. These change when the element is added/removed 702 // from a DOM tree. 703 InDocumentFlag = 1 << 10, 704 IsInShadowTreeFlag = 1 << 11, 705 706 // Set by the parser when the children are done parsing. 707 IsFinishedParsingChildrenFlag = 1 << 12, 708 709 // Flags related to recalcStyle. 710 SVGFilterNeedsLayerUpdateFlag = 1 << 13, 711 HasCustomStyleCallbacksFlag = 1 << 14, 712 ChildNeedsStyleInvalidationFlag = 1 << 15, 713 NeedsStyleInvalidationFlag = 1 << 16, 714 ChildNeedsDistributionRecalcFlag = 1 << 17, 715 ChildNeedsStyleRecalcFlag = 1 << 18, 716 StyleChangeMask = 1 << nodeStyleChangeShift | 1 << (nodeStyleChangeShift + 1), 717 718 CustomElementFlag = 1 << 21, 719 CustomElementUpgradedFlag = 1 << 22, 720 721 HasNameOrIsEditingTextFlag = 1 << 23, 722 HasWeakReferencesFlag = 1 << 24, 723 V8CollectableDuringMinorGCFlag = 1 << 25, 724 HasSyntheticAttrChildNodesFlag = 1 << 26, 725 HasEventTargetDataFlag = 1 << 27, 726 AlreadySpellCheckedFlag = 1 << 28, 727 728 // HTML dir=auto. 729 SelfOrAncestorHasDirAutoFlag = 1 << 29, 730 731 DefaultNodeFlags = IsFinishedParsingChildrenFlag | ChildNeedsStyleRecalcFlag | NeedsReattachStyleChange 732 }; 733 734 // 2 bits remaining. 735 736 bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; } 737 void setFlag(bool f, NodeFlags mask) { m_nodeFlags = (m_nodeFlags & ~mask) | (-(int32_t)f & mask); } 738 void setFlag(NodeFlags mask) { m_nodeFlags |= mask; } 739 void clearFlag(NodeFlags mask) { m_nodeFlags &= ~mask; } 740 741 protected: 742 enum ConstructionType { 743 CreateOther = DefaultNodeFlags, 744 CreateText = DefaultNodeFlags | IsTextFlag, 745 CreateContainer = DefaultNodeFlags | IsContainerFlag, 746 CreateElement = CreateContainer | IsElementFlag, 747 CreateShadowRoot = CreateContainer | IsDocumentFragmentFlag | IsInShadowTreeFlag, 748 CreateDocumentFragment = CreateContainer | IsDocumentFragmentFlag, 749 CreateHTMLElement = CreateElement | IsHTMLFlag, 750 CreateSVGElement = CreateElement | IsSVGFlag, 751 CreateDocument = CreateContainer | InDocumentFlag, 752 CreateInsertionPoint = CreateHTMLElement | IsInsertionPointFlag, 753 CreateEditingText = CreateText | HasNameOrIsEditingTextFlag, 754 }; 755 756 Node(TreeScope*, ConstructionType); 757 758 virtual void didMoveToNewDocument(Document& oldDocument); 759 760 static void reattachWhitespaceSiblings(Text* start); 761 762 #if !ENABLE(OILPAN) 763 void willBeDeletedFromDocument(); 764 #endif 765 766 bool hasRareData() const { return getFlag(HasRareDataFlag); } 767 768 NodeRareData* rareData() const; 769 NodeRareData& ensureRareData(); 770 #if !ENABLE(OILPAN) 771 void clearRareData(); 772 773 void clearEventTargetData(); 774 #endif 775 776 void setHasCustomStyleCallbacks() { setFlag(true, HasCustomStyleCallbacksFlag); } 777 778 void setTreeScope(TreeScope* scope) { m_treeScope = scope; } 779 780 // isTreeScopeInitialized() can be false 781 // - in the destruction of Document or ShadowRoot where m_treeScope is set to null or 782 // - in the Node constructor called by these two classes where m_treeScope is set by TreeScope ctor. 783 bool isTreeScopeInitialized() const { return m_treeScope; } 784 785 void markAncestorsWithChildNeedsStyleRecalc(); 786 787 void setIsFinishedParsingChildren(bool value) { setFlag(value, IsFinishedParsingChildrenFlag); } 788 789 private: 790 friend class TreeShared<Node>; 791 friend class WeakNodeMap; 792 793 virtual PseudoId customPseudoId() const 794 { 795 ASSERT(hasCustomStyleCallbacks()); 796 return NOPSEUDO; 797 } 798 799 unsigned styledSubtreeSize() const; 800 801 #if !ENABLE(OILPAN) 802 void removedLastRef(); 803 #endif 804 bool hasTreeSharedParent() const { return !!parentOrShadowHostNode(); } 805 806 enum EditableLevel { Editable, RichlyEditable }; 807 bool rendererIsEditable(EditableLevel, UserSelectAllTreatment = UserSelectAllIsAlwaysNonEditable) const; 808 bool isEditableToAccessibility(EditableLevel) const; 809 810 bool isUserActionElementActive() const; 811 bool isUserActionElementInActiveChain() const; 812 bool isUserActionElementHovered() const; 813 bool isUserActionElementFocused() const; 814 815 void traceStyleChange(StyleChangeType); 816 void traceStyleChangeIfNeeded(StyleChangeType); 817 void setStyleChange(StyleChangeType); 818 819 virtual RenderStyle* nonRendererStyle() const { return 0; } 820 821 virtual RenderStyle* virtualComputedStyle(PseudoId = NOPSEUDO); 822 823 void trackForDebugging(); 824 825 WillBeHeapVector<OwnPtrWillBeMember<MutationObserverRegistration> >* mutationObserverRegistry(); 826 WillBeHeapHashSet<RawPtrWillBeMember<MutationObserverRegistration> >* transientMutationObserverRegistry(); 827 828 uint32_t m_nodeFlags; 829 RawPtrWillBeMember<ContainerNode> m_parentOrShadowHostNode; 830 RawPtrWillBeMember<TreeScope> m_treeScope; 831 RawPtrWillBeMember<Node> m_previous; 832 RawPtrWillBeMember<Node> m_next; 833 // When a node has rare data we move the renderer into the rare data. 834 union DataUnion { 835 DataUnion() : m_renderer(0) { } 836 RenderObject* m_renderer; 837 NodeRareDataBase* m_rareData; 838 } m_data; 839 }; 840 841 inline void Node::setParentOrShadowHostNode(ContainerNode* parent) 842 { 843 ASSERT(isMainThread()); 844 m_parentOrShadowHostNode = parent; 845 } 846 847 inline ContainerNode* Node::parentOrShadowHostNode() const 848 { 849 ASSERT(isMainThread()); 850 return m_parentOrShadowHostNode; 851 } 852 853 inline ContainerNode* Node::parentNode() const 854 { 855 return isShadowRoot() ? 0 : parentOrShadowHostNode(); 856 } 857 858 inline void Node::lazyReattachIfAttached() 859 { 860 if (styleChangeType() == NeedsReattachStyleChange) 861 return; 862 if (!inActiveDocument()) 863 return; 864 865 AttachContext context; 866 context.performingReattach = true; 867 868 detach(context); 869 markAncestorsWithChildNeedsStyleRecalc(); 870 } 871 872 inline bool Node::shouldCallRecalcStyle(StyleRecalcChange change) 873 { 874 return change >= Inherit || needsStyleRecalc() || childNeedsStyleRecalc(); 875 } 876 877 inline bool isTreeScopeRoot(const Node* node) 878 { 879 return !node || node->isDocumentNode() || node->isShadowRoot(); 880 } 881 882 inline bool isTreeScopeRoot(const Node& node) 883 { 884 return node.isDocumentNode() || node.isShadowRoot(); 885 } 886 887 // Allow equality comparisons of Nodes by reference or pointer, interchangeably. 888 DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES_REFCOUNTED(Node) 889 890 891 #define DEFINE_NODE_TYPE_CASTS(thisType, predicate) \ 892 template<typename T> inline thisType* to##thisType(const RefPtr<T>& node) { return to##thisType(node.get()); } \ 893 DEFINE_TYPE_CASTS(thisType, Node, node, node->predicate, node.predicate) 894 895 // This requires isClassName(const Node&). 896 #define DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(thisType) \ 897 template<typename T> inline thisType* to##thisType(const RefPtr<T>& node) { return to##thisType(node.get()); } \ 898 DEFINE_TYPE_CASTS(thisType, Node, node, is##thisType(*node), is##thisType(node)) 899 900 #define DECLARE_NODE_FACTORY(T) \ 901 static PassRefPtrWillBeRawPtr<T> create(Document&) 902 #define DEFINE_NODE_FACTORY(T) \ 903 PassRefPtrWillBeRawPtr<T> T::create(Document& document) \ 904 { \ 905 return adoptRefWillBeNoop(new T(document)); \ 906 } 907 908 } // namespace WebCore 909 910 #ifndef NDEBUG 911 // Outside the WebCore namespace for ease of invocation from gdb. 912 void showNode(const WebCore::Node*); 913 void showTree(const WebCore::Node*); 914 void showNodePath(const WebCore::Node*); 915 #endif 916 917 #endif 918