/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * Copyright (C) 2012 The Linux Foundation All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef Node_h #define Node_h #include "EventTarget.h" #include "KURLHash.h" #include "RenderStyleConstants.h" #include "ScriptWrappable.h" #include "TreeShared.h" #include #include #if USE(JSC) namespace JSC { class JSGlobalData; class MarkStack; } #endif namespace WebCore { class Attribute; class ClassNodeList; class ContainerNode; class Document; class DynamicNodeList; class Element; class Event; class EventContext; class EventListener; class FloatPoint; class Frame; class InputElement; class IntRect; class KeyboardEvent; class NSResolver; class NamedNodeMap; class NameNodeList; class NodeList; class NodeRareData; class PlatformKeyboardEvent; class PlatformMouseEvent; class PlatformWheelEvent; class QualifiedName; class RegisteredEventListener; class RenderArena; class RenderBox; class RenderBoxModelObject; class RenderObject; class RenderStyle; #if ENABLE(SVG) class SVGUseElement; #endif class TagNodeList; class TagNodeListNS; class TreeScope; typedef int ExceptionCode; const int nodeStyleChangeShift = 25; // SyntheticStyleChange means that we need to go through the entire style change logic even though // no style property has actually changed. It is used to restructure the tree when, for instance, // RenderLayers are created or destroyed due to animation changes. enum StyleChangeType { NoStyleChange = 0, InlineStyleChange = 1 << nodeStyleChangeShift, FullStyleChange = 2 << nodeStyleChangeShift, SyntheticStyleChange = 3 << nodeStyleChangeShift }; class Node : public EventTarget, public TreeShared, public ScriptWrappable { friend class Document; friend class TreeScope; public: enum NodeType { ELEMENT_NODE = 1, ATTRIBUTE_NODE = 2, TEXT_NODE = 3, CDATA_SECTION_NODE = 4, ENTITY_REFERENCE_NODE = 5, ENTITY_NODE = 6, PROCESSING_INSTRUCTION_NODE = 7, COMMENT_NODE = 8, DOCUMENT_NODE = 9, DOCUMENT_TYPE_NODE = 10, DOCUMENT_FRAGMENT_NODE = 11, NOTATION_NODE = 12, XPATH_NAMESPACE_NODE = 13 }; enum DocumentPosition { DOCUMENT_POSITION_EQUIVALENT = 0x00, DOCUMENT_POSITION_DISCONNECTED = 0x01, DOCUMENT_POSITION_PRECEDING = 0x02, DOCUMENT_POSITION_FOLLOWING = 0x04, DOCUMENT_POSITION_CONTAINS = 0x08, DOCUMENT_POSITION_CONTAINED_BY = 0x10, DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20, }; static const int cPrefetchTargetDepth; static bool isSupported(const String& feature, const String& version); static void startIgnoringLeaks(); static void stopIgnoringLeaks(); static void dumpStatistics(); enum StyleChange { NoChange, NoInherit, Inherit, Detach, Force }; static StyleChange diff(const RenderStyle*, const RenderStyle*); virtual ~Node(); // DOM methods & attributes for Node bool hasTagName(const QualifiedName&) const; bool hasLocalName(const AtomicString&) const; virtual String nodeName() const = 0; virtual String nodeValue() const; virtual void setNodeValue(const String&, ExceptionCode&); virtual NodeType nodeType() const = 0; ContainerNode* parentNode() const; Element* parentElement() const; ALWAYS_INLINE Node* previousSibling() const { return m_previous; } ALWAYS_INLINE Node* nextSibling() const { return m_next; } PassRefPtr childNodes(); Node* firstChild() const; Node* lastChild() const; bool hasAttributes() const; NamedNodeMap* attributes() const; virtual KURL baseURI() const; void getSubresourceURLs(ListHashSet&) const; // These should all actually return a node, but this is only important for language bindings, // which will already know and hold a ref on the right node to return. Returning bool allows // these methods to be more efficient since they don't need to return a ref bool insertBefore(PassRefPtr newChild, Node* refChild, ExceptionCode&, bool shouldLazyAttach = false); bool replaceChild(PassRefPtr newChild, Node* oldChild, ExceptionCode&, bool shouldLazyAttach = false); bool removeChild(Node* child, ExceptionCode&); bool appendChild(PassRefPtr newChild, ExceptionCode&, bool shouldLazyAttach = false); void remove(ExceptionCode&); bool hasChildNodes() const { return firstChild(); } virtual PassRefPtr cloneNode(bool deep) = 0; const AtomicString& localName() const { return virtualLocalName(); } const AtomicString& namespaceURI() const { return virtualNamespaceURI(); } const AtomicString& prefix() const { return virtualPrefix(); } virtual void setPrefix(const AtomicString&, ExceptionCode&); void normalize(); bool isSameNode(Node* other) const { return this == other; } bool isEqualNode(Node*) const; bool isDefaultNamespace(const AtomicString& namespaceURI) const; String lookupPrefix(const AtomicString& namespaceURI) const; String lookupNamespaceURI(const String& prefix) const; String lookupNamespacePrefix(const AtomicString& namespaceURI, const Element* originalElement) const; String textContent(bool convertBRsToNewlines = false) const; void setTextContent(const String&, ExceptionCode&); Node* lastDescendant() const; Node* firstDescendant() const; // Other methods (not part of DOM) ALWAYS_INLINE bool isElementNode() const { return getFlag(IsElementFlag); } ALWAYS_INLINE bool isContainerNode() const { return getFlag(IsContainerFlag); } bool isTextNode() const { return getFlag(IsTextFlag); } bool isHTMLElement() const { return getFlag(IsHTMLFlag); } ALWAYS_INLINE bool isSVGElement() const { return getFlag(IsSVGFlag); } ALWAYS_INLINE bool isSVGShadowRoot() const { return getFlag(IsShadowRootOrSVGShadowRootFlag) && isSVGElement(); } #if ENABLE(SVG) SVGUseElement* svgShadowHost() const; #endif #if ENABLE(WML) virtual bool isWMLElement() const { return false; } #else static bool isWMLElement() { return false; } #endif virtual bool isMediaControlElement() const { return false; } virtual bool isMediaControls() const { return false; } bool isStyledElement() const { return getFlag(IsStyledElementFlag); } virtual bool isFrameOwnerElement() const { return false; } virtual bool isAttributeNode() const { return false; } bool isCommentNode() const { return getFlag(IsCommentFlag); } virtual bool isCharacterDataNode() const { return false; } bool isDocumentNode() const; bool isShadowRoot() const { return getFlag(IsShadowRootOrSVGShadowRootFlag) && !isSVGElement(); } // FIXME: Remove this when all shadow roots are ShadowRoots. virtual bool isShadowBoundary() const { return false; } virtual bool canHaveLightChildRendererWithShadow() const { return false; } Node* shadowAncestorNode() const; Node* shadowTreeRootNode() const; bool isInShadowTree(); // Node's parent, shadow tree host, or SVG use. ContainerNode* parentOrHostNode() const; // Use when it's guaranteed to that shadowHost is 0 and svgShadowHost is 0. ContainerNode* parentNodeGuaranteedHostFree() const; Element* shadowHost() const; void setShadowHost(Element*); bool selfOrAncestorHasDirAutoAttribute() const { return getFlag(SelfOrAncestorHasDirAutoFlag); } void setSelfOrAncestorHasDirAutoAttribute(bool flag) { setFlag(flag, SelfOrAncestorHasDirAutoFlag); } // Returns the enclosing event parent node (or self) that, when clicked, would trigger a navigation. Node* enclosingLinkEventParentOrSelf(); bool isBlockFlow() const; bool isBlockFlowOrBlockTable() const; // These low-level calls give the caller responsibility for maintaining the integrity of the tree. void setPreviousSibling(Node* previous) { m_previous = previous; } ALWAYS_INLINE void updatePrefetchTarget() { if (m_next) { int skew; Node* from = this; Node* n = from->traversePreviousNodePostOrder(); for (skew = cPrefetchTargetDepth - 1; skew && n; skew--) { from = n; n = n->traversePreviousNodePostOrder(); } from->setPrefetchTarget(m_next); } } void setPrefetchTarget(Node *prefetch) { m_prefetch = prefetch; } void setNextSibling(Node* next) { m_next = next; updatePrefetchTarget(); } void updatePreviousNode() { m_previousNode = traversePreviousNode(); if (m_previousNode) m_previousNode->setNextNode(this); } void updateNextNode() { m_nextNode = traverseNextNode(); if (m_nextNode) m_nextNode->setPreviousNode(this); } void updatePrevNextNodesInSubtree(); void setPreviousNode(Node* previous) { m_previousNode = previous; } void setNextNode(Node* next) { m_nextNode = next; } // FIXME: These two functions belong in editing -- "atomic node" is an editing concept. Node* previousNodeConsideringAtomicNodes() const; Node* nextNodeConsideringAtomicNodes() const; // Returns the next leaf node or 0 if there are no more. // Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes. // Uses an editing-specific concept of what a leaf node is, and should probably be moved // out of the Node class into an editing-specific source file. Node* nextLeafNode() const; // Returns the previous leaf node or 0 if there are no more. // Delivers leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes. // Uses an editing-specific concept of what a leaf node is, and should probably be moved // out of the Node class into an editing-specific source file. Node* previousLeafNode() const; // enclosingBlockFlowElement() is deprecated. Use enclosingBlock instead. Element* enclosingBlockFlowElement() const; Element* rootEditableElement() const; bool inSameContainingBlockFlowElement(Node*); // FIXME: All callers of this function are almost certainly wrong! virtual void deprecatedParserAddChild(PassRefPtr); // Called by the parser when this element's close tag is reached, // signaling that all child tags have been parsed and added. // This is needed for and elements, which can't lay themselves out // until they know all of their nested s. [Radar 3603191, 4040848]. // Also used for script elements and some SVG elements for similar purposes, // but making parsing a special case in this respect should be avoided if possible. virtual void finishParsingChildren() { } virtual void beginParsingChildren() { } // Called on the focused node right before dispatching an unload event. virtual void aboutToUnload() { } // For and