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/ScriptWrappable.h" 29 #include "core/dom/EventTarget.h" 30 #include "core/dom/MutationObserver.h" 31 #include "core/dom/SimulatedClickOptions.h" 32 #include "core/dom/TreeScope.h" 33 #include "core/editing/EditingBoundary.h" 34 #include "core/inspector/InspectorCounters.h" 35 #include "core/platform/TreeShared.h" 36 #include "core/platform/graphics/LayoutRect.h" 37 #include "core/rendering/style/RenderStyleConstants.h" 38 #include "weborigin/KURLHash.h" 39 #include "wtf/Forward.h" 40 #include "wtf/ListHashSet.h" 41 #include "wtf/text/AtomicString.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 ClassNodeList; 50 class ContainerNode; 51 class DOMSettableTokenList; 52 class Document; 53 class Element; 54 class Event; 55 class EventContext; 56 class EventDispatchMediator; 57 class EventListener; 58 class ExceptionState; 59 class FloatPoint; 60 class Frame; 61 class HTMLInputElement; 62 class IntRect; 63 class KeyboardEvent; 64 class NSResolver; 65 class NamedNodeMap; 66 class NameNodeList; 67 class NodeList; 68 class NodeListsNodeData; 69 class NodeRareData; 70 class NodeRenderingContext; 71 class PlatformGestureEvent; 72 class PlatformKeyboardEvent; 73 class PlatformMouseEvent; 74 class PlatformWheelEvent; 75 class QualifiedName; 76 class RadioNodeList; 77 class RegisteredEventListener; 78 class RenderBox; 79 class RenderBoxModelObject; 80 class RenderObject; 81 class RenderStyle; 82 class ShadowRoot; 83 class TagNodeList; 84 class TouchEvent; 85 86 const int nodeStyleChangeShift = 14; 87 88 enum StyleChangeType { 89 NoStyleChange = 0, 90 LocalStyleChange = 1 << nodeStyleChangeShift, 91 SubtreeStyleChange = 2 << nodeStyleChangeShift, 92 LazyAttachStyleChange = 3 << nodeStyleChangeShift, 93 }; 94 95 // If the style change is from the renderer then we'll call setStyle on the 96 // renderer even if the style computed from CSS is identical. 97 enum StyleChangeSource { 98 StyleChangeFromCSS, 99 StyleChangeFromRenderer 100 }; 101 102 class NodeRareDataBase { 103 public: 104 RenderObject* renderer() const { return m_renderer; } 105 void setRenderer(RenderObject* renderer) { m_renderer = renderer; } 106 107 protected: 108 NodeRareDataBase(RenderObject* renderer) 109 : m_renderer(renderer) 110 { } 111 112 private: 113 RenderObject* m_renderer; 114 }; 115 116 enum AttachBehavior { 117 AttachNow, 118 AttachLazily, 119 }; 120 121 class Node : public EventTarget, public ScriptWrappable, public TreeShared<Node> { 122 friend class Document; 123 friend class TreeScope; 124 friend class TreeScopeAdopter; 125 126 public: 127 enum NodeType { 128 ELEMENT_NODE = 1, 129 ATTRIBUTE_NODE = 2, 130 TEXT_NODE = 3, 131 CDATA_SECTION_NODE = 4, 132 ENTITY_NODE = 6, 133 PROCESSING_INSTRUCTION_NODE = 7, 134 COMMENT_NODE = 8, 135 DOCUMENT_NODE = 9, 136 DOCUMENT_TYPE_NODE = 10, 137 DOCUMENT_FRAGMENT_NODE = 11, 138 NOTATION_NODE = 12, 139 XPATH_NAMESPACE_NODE = 13, 140 }; 141 142 // EntityReference nodes are deprecated and impossible to create in WebKit. 143 // We want Node.ENTITY_REFERNCE_NODE to exist in JS and this enum, makes the bindings 144 // generation not complain about ENTITY_REFERENCE_NODE being missing from the implementation 145 // while not requiring all switch(NodeType) blocks to include this deprecated constant. 146 enum DeprecatedNodeType { 147 ENTITY_REFERENCE_NODE = 5 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 // All Nodes are placed in their own heap partition for security. 161 // See http://crbug.com/246860 for detail. 162 void* operator new(size_t); 163 void operator delete(void*); 164 165 static bool isSupported(const String& feature, const String& version); 166 static void dumpStatistics(); 167 168 enum StyleChange { NoChange, NoInherit, Inherit, Detach, Force }; 169 static StyleChange diff(const RenderStyle*, const RenderStyle*, Document*); 170 171 virtual ~Node(); 172 void willBeDeletedFrom(Document*); 173 174 // DOM methods & attributes for Node 175 176 bool hasTagName(const QualifiedName&) const; 177 bool hasLocalName(const AtomicString&) const; 178 virtual String nodeName() const = 0; 179 virtual String nodeValue() const; 180 virtual void setNodeValue(const String&); 181 virtual NodeType nodeType() const = 0; 182 ContainerNode* parentNode() const; 183 Element* parentElement() const; 184 Node* previousSibling() const { return m_previous; } 185 Node* nextSibling() const { return m_next; } 186 PassRefPtr<NodeList> childNodes(); 187 Node* firstChild() const; 188 Node* lastChild() const; 189 bool hasAttributes() const; 190 NamedNodeMap* attributes() const; 191 192 // ChildNode interface API 193 Element* previousElementSibling() const; 194 Element* nextElementSibling() const; 195 void remove(ExceptionState&); 196 197 Node* pseudoAwareNextSibling() const; 198 Node* pseudoAwarePreviousSibling() const; 199 Node* pseudoAwareFirstChild() const; 200 Node* pseudoAwareLastChild() const; 201 202 virtual KURL baseURI() const; 203 204 // These should all actually return a node, but this is only important for language bindings, 205 // which will already know and hold a ref on the right node to return. Returning bool allows 206 // these methods to be more efficient since they don't need to return a ref 207 void insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionState&, AttachBehavior = AttachNow); 208 void replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionState&, AttachBehavior = AttachNow); 209 void removeChild(Node* child, ExceptionState&); 210 void appendChild(PassRefPtr<Node> newChild, ExceptionState&, AttachBehavior = AttachNow); 211 212 bool hasChildNodes() const { return firstChild(); } 213 virtual PassRefPtr<Node> cloneNode(bool deep = true) = 0; 214 virtual const AtomicString& localName() const; 215 virtual const AtomicString& namespaceURI() const; 216 virtual const AtomicString& prefix() const; 217 virtual void setPrefix(const AtomicString&, ExceptionState&); 218 void normalize(); 219 220 bool isSameNode(Node* other) const { return this == other; } 221 bool isEqualNode(Node*) const; 222 bool isDefaultNamespace(const AtomicString& namespaceURI) const; 223 String lookupPrefix(const AtomicString& namespaceURI) const; 224 String lookupNamespaceURI(const String& prefix) const; 225 String lookupNamespacePrefix(const AtomicString& namespaceURI, const Element* originalElement) const; 226 227 String textContent(bool convertBRsToNewlines = false) const; 228 void setTextContent(const String&, ExceptionState&); 229 230 Node* lastDescendant() const; 231 Node* firstDescendant() const; 232 233 // Other methods (not part of DOM) 234 235 bool isElementNode() const { return getFlag(IsElementFlag); } 236 bool isContainerNode() const { return getFlag(IsContainerFlag); } 237 bool isTextNode() const { return getFlag(IsTextFlag); } 238 bool isHTMLElement() const { return getFlag(IsHTMLFlag); } 239 bool isSVGElement() const { return getFlag(IsSVGFlag); } 240 241 bool isPseudoElement() const { return pseudoId() != NOPSEUDO; } 242 bool isBeforePseudoElement() const { return pseudoId() == BEFORE; } 243 bool isAfterPseudoElement() const { return pseudoId() == AFTER; } 244 PseudoId pseudoId() const { return (isElementNode() && hasCustomStyleCallbacks()) ? customPseudoId() : NOPSEUDO; } 245 246 enum CustomElementState { 247 NotCustomElement, 248 UpgradeCandidate, 249 Defined, 250 Upgraded 251 }; 252 bool isCustomElement() const { return customElementState() != NotCustomElement; } 253 CustomElementState customElementState() const { return CustomElementState((getFlag(CustomElementHasDefinitionOrIsUpgraded) ? 2 : 0) | (getFlag(CustomElementIsUpgradeCandidateOrUpgraded) ? 1 : 0)); } 254 void setCustomElementState(CustomElementState newState); 255 256 virtual bool isMediaControlElement() const { return false; } 257 virtual bool isMediaControls() const { return false; } 258 virtual bool isWebVTTElement() const { return false; } 259 virtual bool isAttributeNode() const { return false; } 260 virtual bool isCharacterDataNode() const { return false; } 261 virtual bool isFrameOwnerElement() const { return false; } 262 virtual bool isPluginElement() const { return false; } 263 264 // StyledElements allow inline style (style="border: 1px"), presentational attributes (ex. color), 265 // class names (ex. class="foo bar") and other non-basic styling features. They and also control 266 // if this element can participate in style sharing. 267 // 268 // FIXME: The only things that ever go through StyleResolver that aren't StyledElements are 269 // PseudoElements and WebVTTElements. It's possible we can just eliminate all the checks 270 // since those elements will never have class names, inline style, or other things that 271 // this apparently guards against. 272 bool isStyledElement() const { return isHTMLElement() || isSVGElement(); } 273 274 bool isDocumentNode() const; 275 bool isTreeScope() const { return treeScope()->rootNode() == this; } 276 bool isDocumentFragment() const { return getFlag(IsDocumentFragmentFlag); } 277 bool isShadowRoot() const { return isDocumentFragment() && isTreeScope(); } 278 bool isInsertionPoint() const { return getFlag(IsInsertionPointFlag); } 279 280 bool inNamedFlow() const { return getFlag(InNamedFlowFlag); } 281 bool hasCustomStyleCallbacks() const { return getFlag(HasCustomStyleCallbacksFlag); } 282 283 bool isRegisteredWithNamedFlow() const; 284 285 bool hasSyntheticAttrChildNodes() const { return getFlag(HasSyntheticAttrChildNodesFlag); } 286 void setHasSyntheticAttrChildNodes(bool flag) { setFlag(flag, HasSyntheticAttrChildNodesFlag); } 287 288 // If this node is in a shadow tree, returns its shadow host. Otherwise, returns 0. 289 Element* shadowHost() const; 290 // If this node is in a shadow tree, returns its shadow host. Otherwise, returns this. 291 // Deprecated. Should use shadowHost() and check the return value. 292 Node* deprecatedShadowAncestorNode() const; 293 ShadowRoot* containingShadowRoot() const; 294 ShadowRoot* youngestShadowRoot() const; 295 296 // Returns 0, a child of ShadowRoot, or a legacy shadow root. 297 Node* nonBoundaryShadowTreeRootNode(); 298 299 // Node's parent, shadow tree host. 300 ContainerNode* parentOrShadowHostNode() const; 301 Element* parentOrShadowHostElement() const; 302 void setParentOrShadowHostNode(ContainerNode*); 303 Node* highestAncestor() const; 304 305 // Use when it's guaranteed to that shadowHost is 0. 306 ContainerNode* parentNodeGuaranteedHostFree() const; 307 // Returns the parent node, but 0 if the parent node is a ShadowRoot. 308 ContainerNode* nonShadowBoundaryParentNode() const; 309 310 bool selfOrAncestorHasDirAutoAttribute() const { return getFlag(SelfOrAncestorHasDirAutoFlag); } 311 void setSelfOrAncestorHasDirAutoAttribute(bool flag) { setFlag(flag, SelfOrAncestorHasDirAutoFlag); } 312 313 // Returns the enclosing event parent node (or self) that, when clicked, would trigger a navigation. 314 Node* enclosingLinkEventParentOrSelf(); 315 316 bool isBlockFlowElement() const; 317 318 // These low-level calls give the caller responsibility for maintaining the integrity of the tree. 319 void setPreviousSibling(Node* previous) { m_previous = previous; } 320 void setNextSibling(Node* next) { m_next = next; } 321 322 virtual bool canContainRangeEndPoint() const { return false; } 323 324 // FIXME: These two functions belong in editing -- "atomic node" is an editing concept. 325 Node* previousNodeConsideringAtomicNodes() const; 326 Node* nextNodeConsideringAtomicNodes() const; 327 328 // Returns the next leaf node or 0 if there are no more. 329 // Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes. 330 // Uses an editing-specific concept of what a leaf node is, and should probably be moved 331 // out of the Node class into an editing-specific source file. 332 Node* nextLeafNode() const; 333 334 // Returns the previous leaf node or 0 if there are no more. 335 // Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes. 336 // Uses an editing-specific concept of what a leaf node is, and should probably be moved 337 // out of the Node class into an editing-specific source file. 338 Node* previousLeafNode() const; 339 340 // enclosingBlockFlowElement() is deprecated. Use enclosingBlock instead. 341 Element* enclosingBlockFlowElement() const; 342 343 bool isRootEditableElement() const; 344 Element* rootEditableElement() const; 345 Element* rootEditableElement(EditableType) const; 346 347 bool inSameContainingBlockFlowElement(Node*); 348 349 // Called by the parser when this element's close tag is reached, 350 // signaling that all child tags have been parsed and added. 351 // This is needed for <applet> and <object> elements, which can't lay themselves out 352 // until they know all of their nested <param>s. [Radar 3603191, 4040848]. 353 // Also used for script elements and some SVG elements for similar purposes, 354 // but making parsing a special case in this respect should be avoided if possible. 355 virtual void finishParsingChildren() { } 356 virtual void beginParsingChildren() { } 357 358 // For <link> and <style> elements. 359 virtual bool sheetLoaded() { return true; } 360 virtual void notifyLoadedSheetAndAllCriticalSubresources(bool /* error loading subresource */) { } 361 virtual void startLoadingDynamicSheet() { ASSERT_NOT_REACHED(); } 362 363 bool hasName() const { return !isTextNode() && getFlag(HasNameOrIsEditingTextFlag); } 364 bool hasID() const; 365 bool hasClass() const; 366 367 bool isUserActionElement() const { return getFlag(IsUserActionElement); } 368 void setUserActionElement(bool flag) { setFlag(flag, IsUserActionElement); } 369 370 bool active() const { return isUserActionElement() && isUserActionElementActive(); } 371 bool inActiveChain() const { return isUserActionElement() && isUserActionElementInActiveChain(); } 372 bool hovered() const { return isUserActionElement() && isUserActionElementHovered(); } 373 bool focused() const { return isUserActionElement() && isUserActionElementFocused(); } 374 375 bool attached() const { return getFlag(IsAttachedFlag); } 376 void setAttached() { setFlag(IsAttachedFlag); } 377 bool needsStyleRecalc() const { return styleChangeType() != NoStyleChange; } 378 StyleChangeType styleChangeType() const { return static_cast<StyleChangeType>(m_nodeFlags & StyleChangeMask); } 379 bool childNeedsStyleRecalc() const { return getFlag(ChildNeedsStyleRecalcFlag); } 380 bool isLink() const { return getFlag(IsLinkFlag); } 381 bool isEditingText() const { return isTextNode() && getFlag(HasNameOrIsEditingTextFlag); } 382 383 void setHasName(bool f) { ASSERT(!isTextNode()); setFlag(f, HasNameOrIsEditingTextFlag); } 384 void setChildNeedsStyleRecalc() { setFlag(ChildNeedsStyleRecalcFlag); } 385 void clearChildNeedsStyleRecalc() { clearFlag(ChildNeedsStyleRecalcFlag); } 386 387 void setNeedsStyleRecalc(StyleChangeType = SubtreeStyleChange, StyleChangeSource = StyleChangeFromCSS); 388 void clearNeedsStyleRecalc() 389 { 390 m_nodeFlags &= ~StyleChangeMask; 391 clearFlag(NotifyRendererWithIdenticalStyles); 392 } 393 394 bool childNeedsDistributionRecalc() const { return getFlag(ChildNeedsDistributionRecalc); } 395 void setChildNeedsDistributionRecalc() { setFlag(ChildNeedsDistributionRecalc); } 396 void clearChildNeedsDistributionRecalc() { clearFlag(ChildNeedsDistributionRecalc); } 397 void markAncestorsWithChildNeedsDistributionRecalc(); 398 399 void recalcDistribution(); 400 401 bool shouldNotifyRendererWithIdenticalStyles() const { return getFlag(NotifyRendererWithIdenticalStyles); } 402 403 void setIsLink(bool f) { setFlag(f, IsLinkFlag); } 404 void setIsLink() { setFlag(IsLinkFlag); } 405 void clearIsLink() { clearFlag(IsLinkFlag); } 406 407 void setInNamedFlow() { setFlag(InNamedFlowFlag); } 408 void clearInNamedFlow() { clearFlag(InNamedFlowFlag); } 409 410 bool hasScopedHTMLStyleChild() const { return getFlag(HasScopedHTMLStyleChildFlag); } 411 void setHasScopedHTMLStyleChild(bool flag) { setFlag(flag, HasScopedHTMLStyleChildFlag); } 412 413 bool hasEventTargetData() const { return getFlag(HasEventTargetDataFlag); } 414 void setHasEventTargetData(bool flag) { setFlag(flag, HasEventTargetDataFlag); } 415 416 bool isV8CollectableDuringMinorGC() const { return getFlag(V8CollectableDuringMinorGCFlag); } 417 void setV8CollectableDuringMinorGC(bool flag) { setFlag(flag, V8CollectableDuringMinorGCFlag); } 418 419 enum ShouldSetAttached { 420 SetAttached, 421 DoNotSetAttached 422 }; 423 void lazyAttach(ShouldSetAttached = SetAttached); 424 void lazyReattach(ShouldSetAttached = SetAttached); 425 426 virtual void setFocus(bool flag); 427 virtual void setActive(bool flag = true, bool pause = false); 428 virtual void setHovered(bool flag = true); 429 430 virtual short tabIndex() const; 431 432 virtual Node* focusDelegate(); 433 // This is called only when the node is focused. 434 virtual bool shouldHaveFocusAppearance() const; 435 436 enum UserSelectAllTreatment { 437 UserSelectAllDoesNotAffectEditability, 438 UserSelectAllIsAlwaysNonEditable 439 }; 440 bool isContentEditable(UserSelectAllTreatment = UserSelectAllDoesNotAffectEditability); 441 bool isContentRichlyEditable(); 442 443 bool rendererIsEditable(EditableType editableType = ContentIsEditable, UserSelectAllTreatment treatment = UserSelectAllIsAlwaysNonEditable) const 444 { 445 switch (editableType) { 446 case ContentIsEditable: 447 return rendererIsEditable(Editable, treatment); 448 case HasEditableAXRole: 449 return isEditableToAccessibility(Editable); 450 } 451 ASSERT_NOT_REACHED(); 452 return false; 453 } 454 455 bool rendererIsRichlyEditable(EditableType editableType = ContentIsEditable) const 456 { 457 switch (editableType) { 458 case ContentIsEditable: 459 return rendererIsEditable(RichlyEditable, UserSelectAllIsAlwaysNonEditable); 460 case HasEditableAXRole: 461 return isEditableToAccessibility(RichlyEditable); 462 } 463 ASSERT_NOT_REACHED(); 464 return false; 465 } 466 467 virtual bool shouldUseInputMethod(); 468 virtual LayoutRect boundingBox() const; 469 IntRect pixelSnappedBoundingBox() const { return pixelSnappedIntRect(boundingBox()); } 470 LayoutRect renderRect(bool* isReplaced); 471 IntRect pixelSnappedRenderRect(bool* isReplaced) { return pixelSnappedIntRect(renderRect(isReplaced)); } 472 473 // Returns true if the node has a non-empty bounding box in layout. 474 // This does not 100% guarantee the user can see it, but is pretty close. 475 // Note: This method only works properly after layout has occurred. 476 bool hasNonEmptyBoundingBox() const; 477 478 unsigned nodeIndex() const; 479 480 // Returns the DOM ownerDocument attribute. This method never returns NULL, except in the case 481 // of (1) a Document node or (2) a DocumentType node that is not used with any Document yet. 482 Document* ownerDocument() const; 483 484 // Returns the document associated with this node. This method never returns NULL, except in the case 485 // of a DocumentType node that is not used with any Document yet. A Document node returns itself. 486 Document* document() const 487 { 488 ASSERT(this); 489 // FIXME: below ASSERT is useful, but prevents the use of document() in the constructor or destructor 490 // due to the virtual function call to nodeType(). 491 ASSERT(documentInternal() || (nodeType() == DOCUMENT_TYPE_NODE && !inDocument())); 492 return documentInternal(); 493 } 494 495 TreeScope* treeScope() const { return m_treeScope; } 496 497 // Returns true if this node is associated with a document and is in its associated document's 498 // node tree, false otherwise. 499 bool inDocument() const 500 { 501 ASSERT(documentInternal() || !getFlag(InDocumentFlag)); 502 return getFlag(InDocumentFlag); 503 } 504 bool isInShadowTree() const { return getFlag(IsInShadowTreeFlag); } 505 bool isInTreeScope() const { return getFlag(static_cast<NodeFlags>(InDocumentFlag | IsInShadowTreeFlag)); } 506 507 bool isDocumentTypeNode() const { return nodeType() == DOCUMENT_TYPE_NODE; } 508 virtual bool childTypeAllowed(NodeType) const { return false; } 509 unsigned childNodeCount() const; 510 Node* childNode(unsigned index) const; 511 512 void checkSetPrefix(const AtomicString& prefix, ExceptionState&); 513 bool isDescendantOf(const Node*) const; 514 bool contains(const Node*) const; 515 bool containsIncludingShadowDOM(const Node*) const; 516 bool containsIncludingHostElements(const Node*) const; 517 518 // FIXME: Remove this when crbug.com/265716 cleans up contains semantics. 519 bool bindingsContains(const Node* node) const { return containsIncludingShadowDOM(node); } 520 521 // Used to determine whether range offsets use characters or node indices. 522 virtual bool offsetInCharacters() const; 523 // Number of DOM 16-bit units contained in node. Note that rendered text length can be different - e.g. because of 524 // css-transform:capitalize breaking up precomposed characters and ligatures. 525 virtual int maxCharacterOffset() const; 526 527 // Whether or not a selection can be started in this object 528 virtual bool canStartSelection() const; 529 530 // Getting points into and out of screen space 531 FloatPoint convertToPage(const FloatPoint&) const; 532 FloatPoint convertFromPage(const FloatPoint&) const; 533 534 // ----------------------------------------------------------------------------- 535 // Integration with rendering tree 536 537 // As renderer() includes a branch you should avoid calling it repeatedly in hot code paths. 538 RenderObject* renderer() const { return hasRareData() ? m_data.m_rareData->renderer() : m_data.m_renderer; }; 539 void setRenderer(RenderObject* renderer) 540 { 541 if (hasRareData()) 542 m_data.m_rareData->setRenderer(renderer); 543 else 544 m_data.m_renderer = renderer; 545 } 546 547 // Use these two methods with caution. 548 RenderBox* renderBox() const; 549 RenderBoxModelObject* renderBoxModelObject() const; 550 551 struct AttachContext { 552 RenderStyle* resolvedStyle; 553 bool performingReattach; 554 555 AttachContext() : resolvedStyle(0), performingReattach(false) { } 556 }; 557 558 // Attaches this node to the rendering tree. This calculates the style to be applied to the node and creates an 559 // appropriate RenderObject which will be inserted into the tree (except when the style has display: none). This 560 // makes the node visible in the FrameView. 561 virtual void attach(const AttachContext& = AttachContext()); 562 563 // Detaches the node from the rendering tree, making it invisible in the rendered view. This method will remove 564 // the node's rendering object from the rendering tree and delete it. 565 virtual void detach(const AttachContext& = AttachContext()); 566 567 #ifndef NDEBUG 568 bool inDetach() const; 569 #endif 570 571 void reattach(const AttachContext& = AttachContext()); 572 void lazyReattachIfAttached(); 573 574 // Wrapper for nodes that don't have a renderer, but still cache the style (like HTMLOptionElement). 575 RenderStyle* renderStyle() const; 576 RenderStyle* parentRenderStyle() const; 577 578 RenderStyle* computedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return virtualComputedStyle(pseudoElementSpecifier); } 579 580 // ----------------------------------------------------------------------------- 581 // Notification of document structure changes (see ContainerNode.h for more notification methods) 582 // 583 // At first, WebKit notifies the node that it has been inserted into the document. This is called during document parsing, and also 584 // 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. 585 // This is similar to the DOMNodeInsertedIntoDocument DOM event, but does not require the overhead of event 586 // dispatching. 587 // 588 // WebKit notifies this callback regardless if the subtree of the node is a document tree or a floating subtree. 589 // Implementation can determine the type of subtree by seeing insertionPoint->inDocument(). 590 // For a performance reason, notifications are delivered only to ContainerNode subclasses if the insertionPoint is out of document. 591 // 592 // There are another callback named didNotifyDescendantInsertions(), which is called after all the descendant is notified. 593 // Only a few subclasses actually need this. To utilize this, the node should return InsertionShouldCallDidNotifyDescendantInsertions 594 // from insrtedInto(). 595 // 596 enum InsertionNotificationRequest { 597 InsertionDone, 598 InsertionShouldCallDidNotifySubtreeInsertions 599 }; 600 601 virtual InsertionNotificationRequest insertedInto(ContainerNode* insertionPoint); 602 virtual void didNotifySubtreeInsertions(ContainerNode*) { } 603 604 // Notifies the node that it is no longer part of the tree. 605 // 606 // This is a dual of insertedInto(), and is similar to the DOMNodeRemovedFromDocument DOM event, but does not require the overhead of event 607 // dispatching, and is called _after_ the node is removed from the tree. 608 // 609 virtual void removedFrom(ContainerNode* insertionPoint); 610 611 #ifndef NDEBUG 612 String debugName() const; 613 614 virtual void formatForDebugger(char* buffer, unsigned length) const; 615 616 void showNode(const char* prefix = "") const; 617 void showTreeForThis() const; 618 void showNodePathForThis() const; 619 void showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2 = 0, const char* markedLabel2 = 0) const; 620 void showTreeForThisAcrossFrame() const; 621 #endif 622 623 void invalidateNodeListCachesInAncestors(const QualifiedName* attrName = 0, Element* attributeOwnerElement = 0); 624 NodeListsNodeData* nodeLists(); 625 void clearNodeLists(); 626 627 PassRefPtr<NodeList> getElementsByTagName(const AtomicString&); 628 PassRefPtr<NodeList> getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName); 629 PassRefPtr<NodeList> getElementsByName(const String& elementName); 630 PassRefPtr<NodeList> getElementsByClassName(const String& classNames); 631 PassRefPtr<RadioNodeList> radioNodeList(const AtomicString&); 632 633 virtual bool willRespondToMouseMoveEvents(); 634 virtual bool willRespondToMouseClickEvents(); 635 virtual bool willRespondToTouchEvents(); 636 637 PassRefPtr<Element> querySelector(const AtomicString& selectors, ExceptionState&); 638 PassRefPtr<NodeList> querySelectorAll(const AtomicString& selectors, ExceptionState&); 639 640 unsigned short compareDocumentPosition(const Node*) const; 641 642 enum ShadowTreesTreatment { 643 TreatShadowTreesAsDisconnected, 644 TreatShadowTreesAsComposed 645 }; 646 647 unsigned short compareDocumentPositionInternal(const Node*, ShadowTreesTreatment) const; 648 649 virtual Node* toNode(); 650 651 virtual const AtomicString& interfaceName() const; 652 virtual ScriptExecutionContext* scriptExecutionContext() const; 653 654 virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); 655 virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); 656 657 // Handlers to do/undo actions on the target node before an event is dispatched to it and after the event 658 // has been dispatched. The data pointer is handed back by the preDispatch and passed to postDispatch. 659 virtual void* preDispatchEventHandler(Event*) { return 0; } 660 virtual void postDispatchEventHandler(Event*, void* /*dataFromPreDispatch*/) { } 661 662 using EventTarget::dispatchEvent; 663 virtual bool dispatchEvent(PassRefPtr<Event>) OVERRIDE; 664 665 void dispatchScopedEvent(PassRefPtr<Event>); 666 void dispatchScopedEventDispatchMediator(PassRefPtr<EventDispatchMediator>); 667 668 virtual void handleLocalEvents(Event*); 669 670 void dispatchSubtreeModifiedEvent(); 671 bool dispatchDOMActivateEvent(int detail, PassRefPtr<Event> underlyingEvent); 672 673 bool dispatchKeyEvent(const PlatformKeyboardEvent&); 674 bool dispatchWheelEvent(const PlatformWheelEvent&); 675 bool dispatchMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType, int clickCount = 0, Node* relatedTarget = 0); 676 bool dispatchGestureEvent(const PlatformGestureEvent&); 677 bool dispatchTouchEvent(PassRefPtr<TouchEvent>); 678 679 void dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions = SendNoEvents, SimulatedClickVisualOptions = ShowPressedLook); 680 681 virtual bool dispatchBeforeLoadEvent(const String& sourceURL); 682 virtual void dispatchChangeEvent(); 683 virtual void dispatchInputEvent(); 684 685 // Perform the default action for an event. 686 virtual void defaultEventHandler(Event*); 687 virtual void willCallDefaultEventHandler(const Event&); 688 689 using TreeShared<Node>::ref; 690 using TreeShared<Node>::deref; 691 692 virtual EventTargetData* eventTargetData(); 693 virtual EventTargetData* ensureEventTargetData(); 694 695 void getRegisteredMutationObserversOfType(HashMap<MutationObserver*, MutationRecordDeliveryOptions>&, MutationObserver::MutationType, const QualifiedName* attributeName); 696 void registerMutationObserver(MutationObserver*, MutationObserverOptions, const HashSet<AtomicString>& attributeFilter); 697 void unregisterMutationObserver(MutationObserverRegistration*); 698 void registerTransientMutationObserver(MutationObserverRegistration*); 699 void unregisterTransientMutationObserver(MutationObserverRegistration*); 700 void notifyMutationObserversNodeWillDetach(); 701 702 virtual void registerScopedHTMLStyleChild(); 703 virtual void unregisterScopedHTMLStyleChild(); 704 size_t numberOfScopedHTMLStyleChildren() const; 705 706 void textRects(Vector<IntRect>&) const; 707 708 unsigned connectedSubframeCount() const; 709 void incrementConnectedSubframeCount(unsigned amount = 1); 710 void decrementConnectedSubframeCount(unsigned amount = 1); 711 void updateAncestorConnectedSubframeCountForRemoval() const; 712 void updateAncestorConnectedSubframeCountForInsertion() const; 713 714 PassRefPtr<NodeList> getDestinationInsertionPoints(); 715 716 private: 717 enum NodeFlags { 718 IsTextFlag = 1, 719 IsContainerFlag = 1 << 1, 720 IsElementFlag = 1 << 2, 721 IsHTMLFlag = 1 << 3, 722 IsSVGFlag = 1 << 4, 723 IsAttachedFlag = 1 << 5, 724 ChildNeedsStyleRecalcFlag = 1 << 6, 725 InDocumentFlag = 1 << 7, 726 IsLinkFlag = 1 << 8, 727 IsUserActionElement = 1 << 9, 728 HasRareDataFlag = 1 << 10, 729 IsDocumentFragmentFlag = 1 << 11, 730 731 // These bits are used by derived classes, pulled up here so they can 732 // be stored in the same memory word as the Node bits above. 733 IsParsingChildrenFinishedFlag = 1 << 12, // Element 734 HasSVGRareDataFlag = 1 << 13, // SVGElement 735 736 StyleChangeMask = 1 << nodeStyleChangeShift | 1 << (nodeStyleChangeShift + 1), 737 738 SelfOrAncestorHasDirAutoFlag = 1 << 16, 739 740 HasNameOrIsEditingTextFlag = 1 << 17, 741 742 InNamedFlowFlag = 1 << 18, 743 HasSyntheticAttrChildNodesFlag = 1 << 19, 744 HasCustomStyleCallbacksFlag = 1 << 20, 745 HasScopedHTMLStyleChildFlag = 1 << 21, 746 HasEventTargetDataFlag = 1 << 22, 747 V8CollectableDuringMinorGCFlag = 1 << 23, 748 IsInsertionPointFlag = 1 << 24, 749 IsInShadowTreeFlag = 1 << 25, 750 751 NotifyRendererWithIdenticalStyles = 1 << 26, 752 753 CustomElementIsUpgradeCandidateOrUpgraded = 1 << 27, 754 CustomElementHasDefinitionOrIsUpgraded = 1 << 28, 755 756 ChildNeedsDistributionRecalc = 1 << 29, 757 758 DefaultNodeFlags = IsParsingChildrenFinishedFlag 759 }; 760 761 // 2 bits remaining 762 763 bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; } 764 void setFlag(bool f, NodeFlags mask) const { m_nodeFlags = (m_nodeFlags & ~mask) | (-(int32_t)f & mask); } 765 void setFlag(NodeFlags mask) const { m_nodeFlags |= mask; } 766 void clearFlag(NodeFlags mask) const { m_nodeFlags &= ~mask; } 767 768 protected: 769 enum ConstructionType { 770 CreateOther = DefaultNodeFlags, 771 CreateText = DefaultNodeFlags | IsTextFlag, 772 CreateContainer = DefaultNodeFlags | IsContainerFlag, 773 CreateElement = CreateContainer | IsElementFlag, 774 CreatePseudoElement = CreateElement | InDocumentFlag, 775 CreateShadowRoot = CreateContainer | IsDocumentFragmentFlag | IsInShadowTreeFlag, 776 CreateDocumentFragment = CreateContainer | IsDocumentFragmentFlag, 777 CreateHTMLElement = CreateElement | IsHTMLFlag, 778 CreateSVGElement = CreateElement | IsSVGFlag, 779 CreateDocument = CreateContainer | InDocumentFlag, 780 CreateInsertionPoint = CreateHTMLElement | IsInsertionPointFlag, 781 CreateEditingText = CreateText | HasNameOrIsEditingTextFlag, 782 }; 783 784 Node(TreeScope* treeScope, ConstructionType type) 785 : m_nodeFlags(type) 786 , m_parentOrShadowHostNode(0) 787 , m_treeScope(treeScope) 788 , m_previous(0) 789 , m_next(0) 790 { 791 ScriptWrappable::init(this); 792 if (!m_treeScope) 793 m_treeScope = TreeScope::noDocumentInstance(); 794 m_treeScope->guardRef(); 795 796 #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS) 797 trackForDebugging(); 798 #endif 799 InspectorCounters::incrementCounter(InspectorCounters::NodeCounter); 800 } 801 802 virtual void didMoveToNewDocument(Document* oldDocument); 803 804 virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const { } 805 806 bool hasRareData() const { return getFlag(HasRareDataFlag); } 807 808 NodeRareData* rareData() const; 809 NodeRareData* ensureRareData(); 810 void clearRareData(); 811 812 void clearEventTargetData(); 813 814 void setHasCustomStyleCallbacks() { setFlag(true, HasCustomStyleCallbacksFlag); } 815 816 Document* documentInternal() const { return treeScope()->documentScope(); } 817 void setTreeScope(TreeScope* scope) { m_treeScope = scope; } 818 819 private: 820 friend class TreeShared<Node>; 821 822 virtual PseudoId customPseudoId() const 823 { 824 ASSERT(hasCustomStyleCallbacks()); 825 return NOPSEUDO; 826 } 827 828 void removedLastRef(); 829 bool hasTreeSharedParent() const { return !!parentOrShadowHostNode(); } 830 831 enum EditableLevel { Editable, RichlyEditable }; 832 bool rendererIsEditable(EditableLevel, UserSelectAllTreatment = UserSelectAllIsAlwaysNonEditable) const; 833 bool isEditableToAccessibility(EditableLevel) const; 834 835 bool isUserActionElementActive() const; 836 bool isUserActionElementInActiveChain() const; 837 bool isUserActionElementHovered() const; 838 bool isUserActionElementFocused() const; 839 840 void setStyleChange(StyleChangeType); 841 842 // Used to share code between lazyAttach and setNeedsStyleRecalc. 843 void markAncestorsWithChildNeedsStyleRecalc(); 844 845 virtual void refEventTarget(); 846 virtual void derefEventTarget(); 847 848 virtual RenderStyle* nonRendererStyle() const { return 0; } 849 850 virtual RenderStyle* virtualComputedStyle(PseudoId = NOPSEUDO); 851 852 Element* ancestorElement() const; 853 854 void trackForDebugging(); 855 856 Vector<OwnPtr<MutationObserverRegistration> >* mutationObserverRegistry(); 857 HashSet<MutationObserverRegistration*>* transientMutationObserverRegistry(); 858 859 mutable uint32_t m_nodeFlags; 860 ContainerNode* m_parentOrShadowHostNode; 861 TreeScope* m_treeScope; 862 Node* m_previous; 863 Node* m_next; 864 // When a node has rare data we move the renderer into the rare data. 865 union DataUnion { 866 DataUnion() : m_renderer(0) { } 867 RenderObject* m_renderer; 868 NodeRareDataBase* m_rareData; 869 } m_data; 870 871 protected: 872 bool isParsingChildrenFinished() const { return getFlag(IsParsingChildrenFinishedFlag); } 873 void setIsParsingChildrenFinished() { setFlag(IsParsingChildrenFinishedFlag); } 874 void clearIsParsingChildrenFinished() { clearFlag(IsParsingChildrenFinishedFlag); } 875 876 bool hasSVGRareData() const { return getFlag(HasSVGRareDataFlag); } 877 void setHasSVGRareData() { setFlag(HasSVGRareDataFlag); } 878 void clearHasSVGRareData() { clearFlag(HasSVGRareDataFlag); } 879 }; 880 881 // Used in Node::addSubresourceAttributeURLs() and in addSubresourceStyleURLs() 882 inline void addSubresourceURL(ListHashSet<KURL>& urls, const KURL& url) 883 { 884 if (!url.isNull()) 885 urls.add(url); 886 } 887 888 inline void Node::setParentOrShadowHostNode(ContainerNode* parent) 889 { 890 ASSERT(isMainThread()); 891 m_parentOrShadowHostNode = parent; 892 } 893 894 inline ContainerNode* Node::parentOrShadowHostNode() const 895 { 896 ASSERT(isMainThread()); 897 return m_parentOrShadowHostNode; 898 } 899 900 inline ContainerNode* Node::parentNode() const 901 { 902 return isShadowRoot() ? 0 : parentOrShadowHostNode(); 903 } 904 905 inline ContainerNode* Node::parentNodeGuaranteedHostFree() const 906 { 907 ASSERT(!isShadowRoot()); 908 return parentOrShadowHostNode(); 909 } 910 911 inline void Node::lazyReattachIfAttached() 912 { 913 if (attached()) 914 lazyReattach(); 915 } 916 917 inline void Node::lazyReattach(ShouldSetAttached shouldSetAttached) 918 { 919 if (styleChangeType() == LazyAttachStyleChange) 920 return; 921 922 AttachContext context; 923 context.performingReattach = true; 924 925 if (attached()) 926 detach(context); 927 lazyAttach(shouldSetAttached); 928 } 929 930 inline bool shouldRecalcStyle(Node::StyleChange change, const Node* node) 931 { 932 return change >= Node::Inherit || node->childNeedsStyleRecalc() || node->needsStyleRecalc(); 933 } 934 935 } //namespace 936 937 #ifndef NDEBUG 938 // Outside the WebCore namespace for ease of invocation from gdb. 939 void showTree(const WebCore::Node*); 940 void showNodePath(const WebCore::Node*); 941 #endif 942 943 #endif 944