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