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 |