Home | History | Annotate | Download | only in dom
      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, 2009, 2010, 2011 Apple Inc. All rights reserved.
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Library General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Library General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Library General Public License
     18  * along with this library; see the file COPYING.LIB.  If not, write to
     19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     20  * Boston, MA 02110-1301, USA.
     21  *
     22  */
     23 
     24 #ifndef ContainerNode_h
     25 #define ContainerNode_h
     26 
     27 #include "bindings/v8/ExceptionStatePlaceholder.h"
     28 #include "core/dom/Node.h"
     29 #include "wtf/OwnPtr.h"
     30 #include "wtf/Vector.h"
     31 
     32 namespace WebCore {
     33 
     34 class ExceptionState;
     35 class FloatPoint;
     36 class HTMLCollection;
     37 
     38 namespace Private {
     39     template<class GenericNode, class GenericNodeContainer>
     40     void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer&);
     41 }
     42 
     43 class NoEventDispatchAssertion {
     44 public:
     45     NoEventDispatchAssertion()
     46     {
     47 #ifndef NDEBUG
     48         if (!isMainThread())
     49             return;
     50         s_count++;
     51 #endif
     52     }
     53 
     54     ~NoEventDispatchAssertion()
     55     {
     56 #ifndef NDEBUG
     57         if (!isMainThread())
     58             return;
     59         ASSERT(s_count);
     60         s_count--;
     61 #endif
     62     }
     63 
     64 #ifndef NDEBUG
     65     static bool isEventDispatchForbidden()
     66     {
     67         if (!isMainThread())
     68             return false;
     69         return s_count;
     70     }
     71 #endif
     72 
     73 private:
     74 #ifndef NDEBUG
     75     static unsigned s_count;
     76 #endif
     77 };
     78 
     79 class ContainerNode : public Node {
     80 public:
     81     virtual ~ContainerNode();
     82 
     83     Node* firstChild() const { return m_firstChild; }
     84     Node* lastChild() const { return m_lastChild; }
     85     bool hasChildNodes() const { return m_firstChild; }
     86 
     87     bool hasOneChild() const { return m_firstChild && !m_firstChild->nextSibling(); }
     88     bool hasOneTextChild() const { return hasOneChild() && m_firstChild->isTextNode(); }
     89 
     90     // ParentNode interface API
     91     PassRefPtr<HTMLCollection> children();
     92     Element* firstElementChild() const;
     93     Element* lastElementChild() const;
     94     unsigned childElementCount() const;
     95 
     96     unsigned childNodeCount() const;
     97     Node* childNode(unsigned index) const;
     98 
     99     void insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionState& = ASSERT_NO_EXCEPTION);
    100     void replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionState& = ASSERT_NO_EXCEPTION);
    101     void removeChild(Node* child, ExceptionState& = ASSERT_NO_EXCEPTION);
    102     void appendChild(PassRefPtr<Node> newChild, ExceptionState& = ASSERT_NO_EXCEPTION);
    103 
    104     // These methods are only used during parsing.
    105     // They don't send DOM mutation events or handle reparenting.
    106     // However, arbitrary code may be run by beforeload handlers.
    107     void parserAppendChild(PassRefPtr<Node>);
    108     void parserRemoveChild(Node&);
    109     void parserInsertBefore(PassRefPtr<Node> newChild, Node& refChild);
    110     void parserTakeAllChildrenFrom(ContainerNode&);
    111 
    112     void removeChildren();
    113 
    114     void cloneChildNodes(ContainerNode* clone);
    115 
    116     virtual void attach(const AttachContext& = AttachContext()) OVERRIDE;
    117     virtual void detach(const AttachContext& = AttachContext()) OVERRIDE;
    118     virtual LayoutRect boundingBox() const OVERRIDE;
    119     virtual void setFocus(bool) OVERRIDE;
    120     void focusStateChanged();
    121     virtual void setActive(bool = true) OVERRIDE;
    122     virtual void setHovered(bool = true) OVERRIDE;
    123 
    124     // -----------------------------------------------------------------------------
    125     // Notification of document structure changes (see core/dom/Node.h for more notification methods)
    126 
    127     // Notifies the node that it's list of children have changed (either by adding or removing child nodes), or a child
    128     // node that is of the type CDATA_SECTION_NODE, TEXT_NODE or COMMENT_NODE has changed its value.
    129     virtual void childrenChanged(bool createdByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
    130 
    131     void disconnectDescendantFrames();
    132 
    133     virtual bool childShouldCreateRenderer(const Node& child) const { return true; }
    134 
    135 protected:
    136     ContainerNode(TreeScope*, ConstructionType = CreateContainer);
    137 
    138     template<class GenericNode, class GenericNodeContainer>
    139     friend void appendChildToContainer(GenericNode& child, GenericNodeContainer&);
    140 
    141     template<class GenericNode, class GenericNodeContainer>
    142     friend void Private::addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer&);
    143 
    144     void removeDetachedChildren();
    145     void setFirstChild(Node* child) { m_firstChild = child; }
    146     void setLastChild(Node* child) { m_lastChild = child; }
    147 
    148 private:
    149     void removeBetween(Node* previousChild, Node* nextChild, Node& oldChild);
    150     void insertBeforeCommon(Node& nextChild, Node& oldChild);
    151     void updateTreeAfterInsertion(Node& child);
    152     void willRemoveChildren();
    153     void willRemoveChild(Node& child);
    154 
    155     inline bool checkAcceptChildGuaranteedNodeTypes(const Node& newChild, ExceptionState&) const;
    156     inline bool checkAcceptChild(const Node* newChild, const Node* oldChild, ExceptionState&) const;
    157     inline bool containsConsideringHostElements(const Node&) const;
    158     inline bool isChildTypeAllowed(const Node& child) const;
    159 
    160     void attachChildren(const AttachContext& = AttachContext());
    161     void detachChildren(const AttachContext& = AttachContext());
    162 
    163     bool getUpperLeftCorner(FloatPoint&) const;
    164     bool getLowerRightCorner(FloatPoint&) const;
    165 
    166     Node* m_firstChild;
    167     Node* m_lastChild;
    168 };
    169 
    170 #ifndef NDEBUG
    171 bool childAttachedAllowedWhenAttachingChildren(ContainerNode*);
    172 #endif
    173 
    174 DEFINE_NODE_TYPE_CASTS(ContainerNode, isContainerNode());
    175 
    176 inline ContainerNode::ContainerNode(TreeScope* treeScope, ConstructionType type)
    177     : Node(treeScope, type)
    178     , m_firstChild(0)
    179     , m_lastChild(0)
    180 {
    181 }
    182 
    183 inline void ContainerNode::attachChildren(const AttachContext& context)
    184 {
    185     AttachContext childrenContext(context);
    186     childrenContext.resolvedStyle = 0;
    187 
    188     for (Node* child = firstChild(); child; child = child->nextSibling()) {
    189         ASSERT(child->needsAttach() || childAttachedAllowedWhenAttachingChildren(this));
    190         if (child->needsAttach())
    191             child->attach(childrenContext);
    192     }
    193 }
    194 
    195 inline void ContainerNode::detachChildren(const AttachContext& context)
    196 {
    197     AttachContext childrenContext(context);
    198     childrenContext.resolvedStyle = 0;
    199 
    200     for (Node* child = firstChild(); child; child = child->nextSibling())
    201         child->detach(childrenContext);
    202 }
    203 
    204 inline unsigned Node::childNodeCount() const
    205 {
    206     if (!isContainerNode())
    207         return 0;
    208     return toContainerNode(this)->childNodeCount();
    209 }
    210 
    211 inline Node* Node::childNode(unsigned index) const
    212 {
    213     if (!isContainerNode())
    214         return 0;
    215     return toContainerNode(this)->childNode(index);
    216 }
    217 
    218 inline Node* Node::firstChild() const
    219 {
    220     if (!isContainerNode())
    221         return 0;
    222     return toContainerNode(this)->firstChild();
    223 }
    224 
    225 inline Node* Node::lastChild() const
    226 {
    227     if (!isContainerNode())
    228         return 0;
    229     return toContainerNode(this)->lastChild();
    230 }
    231 
    232 inline Node* Node::highestAncestor() const
    233 {
    234     Node* node = const_cast<Node*>(this);
    235     Node* highest = node;
    236     for (; node; node = node->parentNode())
    237         highest = node;
    238     return highest;
    239 }
    240 
    241 // This constant controls how much buffer is initially allocated
    242 // for a Node Vector that is used to store child Nodes of a given Node.
    243 // FIXME: Optimize the value.
    244 const int initialNodeVectorSize = 11;
    245 typedef Vector<RefPtr<Node>, initialNodeVectorSize> NodeVector;
    246 
    247 inline void getChildNodes(Node& node, NodeVector& nodes)
    248 {
    249     ASSERT(!nodes.size());
    250     for (Node* child = node.firstChild(); child; child = child->nextSibling())
    251         nodes.append(child);
    252 }
    253 
    254 class ChildNodesLazySnapshot {
    255     WTF_MAKE_NONCOPYABLE(ChildNodesLazySnapshot);
    256     WTF_MAKE_FAST_ALLOCATED;
    257 public:
    258     explicit ChildNodesLazySnapshot(Node& parentNode)
    259         : m_currentNode(parentNode.firstChild())
    260         , m_currentIndex(0)
    261     {
    262         m_nextSnapshot = latestSnapshot;
    263         latestSnapshot = this;
    264     }
    265 
    266     ~ChildNodesLazySnapshot()
    267     {
    268         latestSnapshot = m_nextSnapshot;
    269     }
    270 
    271     // Returns 0 if there is no next Node.
    272     PassRefPtr<Node> nextNode()
    273     {
    274         if (LIKELY(!hasSnapshot())) {
    275             RefPtr<Node> node = m_currentNode;
    276             if (node)
    277                 m_currentNode = node->nextSibling();
    278             return node.release();
    279         }
    280         Vector<RefPtr<Node> >& nodeVector = *m_childNodes;
    281         if (m_currentIndex >= nodeVector.size())
    282             return 0;
    283         return nodeVector[m_currentIndex++];
    284     }
    285 
    286     void takeSnapshot()
    287     {
    288         if (hasSnapshot())
    289             return;
    290         m_childNodes = adoptPtr(new Vector<RefPtr<Node> >());
    291         Node* node = m_currentNode.get();
    292         while (node) {
    293             m_childNodes->append(node);
    294             node = node->nextSibling();
    295         }
    296     }
    297 
    298     ChildNodesLazySnapshot* nextSnapshot() { return m_nextSnapshot; }
    299     bool hasSnapshot() { return !!m_childNodes.get(); }
    300 
    301     static void takeChildNodesLazySnapshot()
    302     {
    303         ChildNodesLazySnapshot* snapshot = latestSnapshot;
    304         while (snapshot && !snapshot->hasSnapshot()) {
    305             snapshot->takeSnapshot();
    306             snapshot = snapshot->nextSnapshot();
    307         }
    308     }
    309 
    310 private:
    311     static ChildNodesLazySnapshot* latestSnapshot;
    312 
    313     RefPtr<Node> m_currentNode;
    314     unsigned m_currentIndex;
    315     OwnPtr<Vector<RefPtr<Node> > > m_childNodes; // Lazily instantiated.
    316     ChildNodesLazySnapshot* m_nextSnapshot;
    317 };
    318 
    319 } // namespace WebCore
    320 
    321 #endif // ContainerNode_h
    322