| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights
reserved. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights
reserved. |
| 6 * | 6 * |
| 7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 | 29 |
| 30 #include <wtf/OwnPtr.h> | 30 #include <wtf/OwnPtr.h> |
| 31 #include <wtf/Vector.h> | 31 #include <wtf/Vector.h> |
| 32 | 32 |
| 33 namespace WebCore { | 33 namespace WebCore { |
| 34 | 34 |
| 35 class FloatPoint; | 35 class FloatPoint; |
| 36 class HTMLCollection; | 36 class HTMLCollection; |
| 37 | 37 |
| 38 typedef void (*NodeCallback)(Node*); | 38 typedef void (*NodeCallback)(Node*); |
| 39 typedef void (*ElementCallback)(Element*); |
| 39 | 40 |
| 40 namespace Private { | 41 namespace Private { |
| 41 template<class GenericNode, class GenericNodeContainer> | 42 template<class GenericNode, class GenericNodeContainer> |
| 42 void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, Ge
nericNodeContainer*); | 43 void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, Ge
nericNodeContainer*); |
| 43 }; | 44 }; |
| 44 | 45 |
| 45 class NoEventDispatchAssertion { | 46 class NoEventDispatchAssertion { |
| 46 public: | 47 public: |
| 47 NoEventDispatchAssertion() | 48 NoEventDispatchAssertion() |
| 48 { | 49 { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 73 #endif | 74 #endif |
| 74 | 75 |
| 75 private: | 76 private: |
| 76 #ifndef NDEBUG | 77 #ifndef NDEBUG |
| 77 static unsigned s_count; | 78 static unsigned s_count; |
| 78 #endif | 79 #endif |
| 79 }; | 80 }; |
| 80 | 81 |
| 81 class ContainerNode : public Node { | 82 class ContainerNode : public Node { |
| 82 friend class PostAttachCallbackDisabler; | 83 friend class PostAttachCallbackDisabler; |
| 84 friend class InsertionCallbackDeferer; |
| 83 public: | 85 public: |
| 84 virtual ~ContainerNode(); | 86 virtual ~ContainerNode(); |
| 85 | 87 |
| 86 Node* firstChild() const { return m_firstChild; } | 88 Node* firstChild() const { return m_firstChild; } |
| 87 Node* lastChild() const { return m_lastChild; } | 89 Node* lastChild() const { return m_lastChild; } |
| 88 bool hasChildNodes() const { return m_firstChild; } | 90 bool hasChildNodes() const { return m_firstChild; } |
| 89 | 91 |
| 90 // ParentNode interface API | 92 // ParentNode interface API |
| 91 PassRefPtr<HTMLCollection> children(); | 93 PassRefPtr<HTMLCollection> children(); |
| 92 Element* firstElementChild() const; | 94 Element* firstElementChild() const; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 // Notifies the node that it's list of children have changed (either by addi
ng or removing child nodes), or a child | 128 // Notifies the node that it's list of children have changed (either by addi
ng or removing child nodes), or a child |
| 127 // node that is of the type CDATA_SECTION_NODE, TEXT_NODE or COMMENT_NODE ha
s changed its value. | 129 // node that is of the type CDATA_SECTION_NODE, TEXT_NODE or COMMENT_NODE ha
s changed its value. |
| 128 virtual void childrenChanged(bool createdByParser = false, Node* beforeChang
e = 0, Node* afterChange = 0, int childCountDelta = 0); | 130 virtual void childrenChanged(bool createdByParser = false, Node* beforeChang
e = 0, Node* afterChange = 0, int childCountDelta = 0); |
| 129 | 131 |
| 130 void disconnectDescendantFrames(); | 132 void disconnectDescendantFrames(); |
| 131 | 133 |
| 132 virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const {
return true; } | 134 virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const {
return true; } |
| 133 | 135 |
| 134 virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE; | 136 virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE; |
| 135 | 137 |
| 138 static void queueInsertionCallback(ElementCallback, Element*); |
| 136 protected: | 139 protected: |
| 137 ContainerNode(TreeScope*, ConstructionType = CreateContainer); | 140 ContainerNode(TreeScope*, ConstructionType = CreateContainer); |
| 138 | 141 |
| 142 static bool insertionCallbacksAreSuspended(); |
| 139 static void queuePostAttachCallback(NodeCallback, Node*); | 143 static void queuePostAttachCallback(NodeCallback, Node*); |
| 140 static bool postAttachCallbacksAreSuspended(); | 144 static bool postAttachCallbacksAreSuspended(); |
| 141 | 145 |
| 142 template<class GenericNode, class GenericNodeContainer> | 146 template<class GenericNode, class GenericNodeContainer> |
| 143 friend void appendChildToContainer(GenericNode* child, GenericNodeContainer*
); | 147 friend void appendChildToContainer(GenericNode* child, GenericNodeContainer*
); |
| 144 | 148 |
| 145 template<class GenericNode, class GenericNodeContainer> | 149 template<class GenericNode, class GenericNodeContainer> |
| 146 friend void Private::addChildNodesToDeletionQueue(GenericNode*& head, Generi
cNode*& tail, GenericNodeContainer*); | 150 friend void Private::addChildNodesToDeletionQueue(GenericNode*& head, Generi
cNode*& tail, GenericNodeContainer*); |
| 147 | 151 |
| 148 void removeDetachedChildren(); | 152 void removeDetachedChildren(); |
| 149 void setFirstChild(Node* child) { m_firstChild = child; } | 153 void setFirstChild(Node* child) { m_firstChild = child; } |
| 150 void setLastChild(Node* child) { m_lastChild = child; } | 154 void setLastChild(Node* child) { m_lastChild = child; } |
| 151 | 155 |
| 152 private: | 156 private: |
| 153 void removeBetween(Node* previousChild, Node* nextChild, Node* oldChild); | 157 void removeBetween(Node* previousChild, Node* nextChild, Node* oldChild); |
| 154 void insertBeforeCommon(Node* nextChild, Node* oldChild); | 158 void insertBeforeCommon(Node* nextChild, Node* oldChild); |
| 155 | 159 |
| 156 void attachChildren(const AttachContext& = AttachContext()); | 160 void attachChildren(const AttachContext& = AttachContext()); |
| 157 void detachChildren(const AttachContext& = AttachContext()); | 161 void detachChildren(const AttachContext& = AttachContext()); |
| 158 | 162 |
| 159 static void dispatchPostAttachCallbacks(); | 163 static void dispatchPostAttachCallbacks(); |
| 160 | 164 |
| 161 void suspendPostAttachCallbacks(); | 165 void suspendPostAttachCallbacks(); |
| 162 void resumePostAttachCallbacks(); | 166 void resumePostAttachCallbacks(); |
| 163 | 167 |
| 168 static void dispatchInsertionCallbacks(); |
| 169 |
| 170 static void suspendInsertionCallbacks(); |
| 171 static void resumeInsertionCallbacks(); |
| 172 |
| 164 bool getUpperLeftCorner(FloatPoint&) const; | 173 bool getUpperLeftCorner(FloatPoint&) const; |
| 165 bool getLowerRightCorner(FloatPoint&) const; | 174 bool getLowerRightCorner(FloatPoint&) const; |
| 166 | 175 |
| 167 Node* m_firstChild; | 176 Node* m_firstChild; |
| 168 Node* m_lastChild; | 177 Node* m_lastChild; |
| 169 }; | 178 }; |
| 170 | 179 |
| 171 #ifndef NDEBUG | 180 #ifndef NDEBUG |
| 172 bool childAttachedAllowedWhenAttachingChildren(ContainerNode*); | 181 bool childAttachedAllowedWhenAttachingChildren(ContainerNode*); |
| 173 #endif | 182 #endif |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 ASSERT(!nodes.size()); | 272 ASSERT(!nodes.size()); |
| 264 for (Node* child = node->firstChild(); child; child = child->nextSibling()) | 273 for (Node* child = node->firstChild(); child; child = child->nextSibling()) |
| 265 nodes.append(child); | 274 nodes.append(child); |
| 266 } | 275 } |
| 267 | 276 |
| 268 class ChildNodesLazySnapshot { | 277 class ChildNodesLazySnapshot { |
| 269 WTF_MAKE_NONCOPYABLE(ChildNodesLazySnapshot); | 278 WTF_MAKE_NONCOPYABLE(ChildNodesLazySnapshot); |
| 270 WTF_MAKE_FAST_ALLOCATED; | 279 WTF_MAKE_FAST_ALLOCATED; |
| 271 public: | 280 public: |
| 272 explicit ChildNodesLazySnapshot(Node* parentNode) | 281 explicit ChildNodesLazySnapshot(Node* parentNode) |
| 273 : m_currentNode(parentNode->firstChild()) | 282 : m_currentNode(parentNode->lastChild()) |
| 274 , m_currentIndex(0) | 283 , m_currentIndex(0) |
| 275 { | 284 { |
| 276 m_nextSnapshot = latestSnapshot; | 285 m_nextSnapshot = latestSnapshot; |
| 277 latestSnapshot = this; | 286 latestSnapshot = this; |
| 278 } | 287 } |
| 279 | 288 |
| 280 ~ChildNodesLazySnapshot() | 289 ~ChildNodesLazySnapshot() |
| 281 { | 290 { |
| 282 latestSnapshot = m_nextSnapshot; | 291 latestSnapshot = m_nextSnapshot; |
| 283 } | 292 } |
| 284 | 293 |
| 285 // Returns 0 if there is no next Node. | 294 // Returns 0 if there is no previous Node. |
| 286 PassRefPtr<Node> nextNode() | 295 PassRefPtr<Node> previousNode() |
| 287 { | 296 { |
| 288 if (LIKELY(!hasSnapshot())) { | 297 if (LIKELY(!hasSnapshot())) { |
| 289 RefPtr<Node> node = m_currentNode; | 298 RefPtr<Node> node = m_currentNode; |
| 290 if (node) | 299 if (node) |
| 291 m_currentNode = node->nextSibling(); | 300 m_currentNode = node->previousSibling(); |
| 292 return node.release(); | 301 return node.release(); |
| 293 } | 302 } |
| 294 Vector<RefPtr<Node> >& nodeVector = *m_childNodes; | 303 Vector<RefPtr<Node> >& nodeVector = *m_childNodes; |
| 295 if (m_currentIndex >= nodeVector.size()) | 304 if (m_currentIndex >= nodeVector.size()) |
| 296 return 0; | 305 return 0; |
| 297 return nodeVector[m_currentIndex++]; | 306 return nodeVector[m_currentIndex++]; |
| 298 } | 307 } |
| 299 | 308 |
| 300 void takeSnapshot() | 309 void takeSnapshot() |
| 301 { | 310 { |
| 302 if (hasSnapshot()) | 311 if (hasSnapshot()) |
| 303 return; | 312 return; |
| 304 m_childNodes = adoptPtr(new Vector<RefPtr<Node> >()); | 313 m_childNodes = adoptPtr(new Vector<RefPtr<Node> >()); |
| 305 Node* node = m_currentNode.get(); | 314 Node* node = m_currentNode.get(); |
| 306 while (node) { | 315 while (node) { |
| 307 m_childNodes->append(node); | 316 m_childNodes->append(node); |
| 308 node = node->nextSibling(); | 317 node = node->previousSibling(); |
| 309 } | 318 } |
| 310 } | 319 } |
| 311 | 320 |
| 312 ChildNodesLazySnapshot* nextSnapshot() { return m_nextSnapshot; } | 321 ChildNodesLazySnapshot* nextSnapshot() { return m_nextSnapshot; } |
| 313 bool hasSnapshot() { return !!m_childNodes.get(); } | 322 bool hasSnapshot() { return !!m_childNodes.get(); } |
| 314 | 323 |
| 315 static void takeChildNodesLazySnapshot() | 324 static void takeChildNodesLazySnapshot() |
| 316 { | 325 { |
| 317 ChildNodesLazySnapshot* snapshot = latestSnapshot; | 326 ChildNodesLazySnapshot* snapshot = latestSnapshot; |
| 318 while (snapshot && !snapshot->hasSnapshot()) { | 327 while (snapshot && !snapshot->hasSnapshot()) { |
| 319 snapshot->takeSnapshot(); | 328 snapshot->takeSnapshot(); |
| 320 snapshot = snapshot->nextSnapshot(); | 329 snapshot = snapshot->nextSnapshot(); |
| 321 } | 330 } |
| 322 } | 331 } |
| 323 | 332 |
| 324 private: | 333 private: |
| 325 static ChildNodesLazySnapshot* latestSnapshot; | 334 static ChildNodesLazySnapshot* latestSnapshot; |
| 326 | 335 |
| 327 RefPtr<Node> m_currentNode; | 336 RefPtr<Node> m_currentNode; |
| 328 unsigned m_currentIndex; | 337 unsigned m_currentIndex; |
| 329 OwnPtr<Vector<RefPtr<Node> > > m_childNodes; // Lazily instantiated. | 338 OwnPtr<Vector<RefPtr<Node> > > m_childNodes; // Lazily instantiated. |
| 330 ChildNodesLazySnapshot* m_nextSnapshot; | 339 ChildNodesLazySnapshot* m_nextSnapshot; |
| 331 }; | 340 }; |
| 332 | 341 |
| 342 // Used to ensure Radio Buttons resolve their checked state in document |
| 343 // order when a subtree of them is inserted. This is necessary because |
| 344 // we resolve style in reverse document order. |
| 345 class InsertionCallbackDeferer { |
| 346 public: |
| 347 InsertionCallbackDeferer() |
| 348 { |
| 349 ContainerNode::suspendInsertionCallbacks(); |
| 350 } |
| 351 |
| 352 ~InsertionCallbackDeferer() |
| 353 { |
| 354 ContainerNode::resumeInsertionCallbacks(); |
| 355 } |
| 356 }; |
| 357 |
| 333 class PostAttachCallbackDisabler { | 358 class PostAttachCallbackDisabler { |
| 334 public: | 359 public: |
| 335 PostAttachCallbackDisabler(ContainerNode* node) | 360 PostAttachCallbackDisabler(ContainerNode* node) |
| 336 : m_node(node) | 361 : m_node(node) |
| 337 { | 362 { |
| 338 ASSERT(m_node); | 363 ASSERT(m_node); |
| 339 m_node->suspendPostAttachCallbacks(); | 364 m_node->suspendPostAttachCallbacks(); |
| 340 } | 365 } |
| 341 | 366 |
| 342 ~PostAttachCallbackDisabler() | 367 ~PostAttachCallbackDisabler() |
| 343 { | 368 { |
| 344 m_node->resumePostAttachCallbacks(); | 369 m_node->resumePostAttachCallbacks(); |
| 345 } | 370 } |
| 346 | 371 |
| 347 private: | 372 private: |
| 348 ContainerNode* m_node; | 373 ContainerNode* m_node; |
| 349 }; | 374 }; |
| 350 | 375 |
| 351 } // namespace WebCore | 376 } // namespace WebCore |
| 352 | 377 |
| 353 #endif // ContainerNode_h | 378 #endif // ContainerNode_h |
| OLD | NEW |