OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. | 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. |
3 * Copyright (C) 2011 Apple Inc. All rights reserved. | 3 * Copyright (C) 2011 Apple Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 23 matching lines...) Expand all Loading... |
34 #include "wtf/PassRefPtr.h" | 34 #include "wtf/PassRefPtr.h" |
35 #include "wtf/RefPtr.h" | 35 #include "wtf/RefPtr.h" |
36 #include "wtf/Vector.h" | 36 #include "wtf/Vector.h" |
37 #include "wtf/text/StringBuilder.h" | 37 #include "wtf/text/StringBuilder.h" |
38 | 38 |
39 namespace WebCore { | 39 namespace WebCore { |
40 | 40 |
41 struct HTMLConstructionSiteTask { | 41 struct HTMLConstructionSiteTask { |
42 enum Operation { | 42 enum Operation { |
43 Insert, | 43 Insert, |
| 44 InsertText, // Handles possible merging of text nodes. |
44 InsertAlreadyParsedChild, // Insert w/o calling begin/end parsing. | 45 InsertAlreadyParsedChild, // Insert w/o calling begin/end parsing. |
45 Reparent, | 46 Reparent, |
46 TakeAllChildren, | 47 TakeAllChildren, |
47 }; | 48 }; |
48 | 49 |
49 explicit HTMLConstructionSiteTask(Operation op) | 50 explicit HTMLConstructionSiteTask(Operation op) |
50 : operation(op) | 51 : operation(op) |
51 , selfClosing(false) | 52 , selfClosing(false) |
52 { | 53 { |
53 } | 54 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 class HTMLFormElement; | 90 class HTMLFormElement; |
90 | 91 |
91 class HTMLConstructionSite { | 92 class HTMLConstructionSite { |
92 WTF_MAKE_NONCOPYABLE(HTMLConstructionSite); | 93 WTF_MAKE_NONCOPYABLE(HTMLConstructionSite); |
93 public: | 94 public: |
94 HTMLConstructionSite(Document*, ParserContentPolicy); | 95 HTMLConstructionSite(Document*, ParserContentPolicy); |
95 HTMLConstructionSite(DocumentFragment*, ParserContentPolicy); | 96 HTMLConstructionSite(DocumentFragment*, ParserContentPolicy); |
96 ~HTMLConstructionSite(); | 97 ~HTMLConstructionSite(); |
97 | 98 |
98 void detach(); | 99 void detach(); |
| 100 |
| 101 // executeQueuedTasks empties the queue but does not flush pending text. |
| 102 // NOTE: Possible reentrancy via JavaScript execution. |
99 void executeQueuedTasks(); | 103 void executeQueuedTasks(); |
100 | 104 |
| 105 // flushPendingText turns pending text into queued Text insertions, but does
not execute them. |
| 106 void flushPendingText(); |
| 107 |
| 108 // Called before every token in HTMLTreeBuilder::processToken, thus inlined: |
| 109 void flush() |
| 110 { |
| 111 if (!hasPendingTasks()) |
| 112 return; |
| 113 flushPendingText(); |
| 114 executeQueuedTasks(); // NOTE: Possible reentrancy via JavaScript execut
ion. |
| 115 ASSERT(!hasPendingTasks()); |
| 116 } |
| 117 |
| 118 bool hasPendingTasks() |
| 119 { |
| 120 return !m_pendingText.isEmpty() || !m_taskQueue.isEmpty(); |
| 121 } |
| 122 |
101 void setDefaultCompatibilityMode(); | 123 void setDefaultCompatibilityMode(); |
102 void processEndOfFile(); | 124 void processEndOfFile(); |
103 void finishedParsing(); | 125 void finishedParsing(); |
104 | 126 |
105 void insertDoctype(AtomicHTMLToken*); | 127 void insertDoctype(AtomicHTMLToken*); |
106 void insertComment(AtomicHTMLToken*); | 128 void insertComment(AtomicHTMLToken*); |
107 void insertCommentOnDocument(AtomicHTMLToken*); | 129 void insertCommentOnDocument(AtomicHTMLToken*); |
108 void insertCommentOnHTMLHtmlElement(AtomicHTMLToken*); | 130 void insertCommentOnHTMLHtmlElement(AtomicHTMLToken*); |
109 void insertHTMLElement(AtomicHTMLToken*); | 131 void insertHTMLElement(AtomicHTMLToken*); |
110 void insertSelfClosingHTMLElement(AtomicHTMLToken*); | 132 void insertSelfClosingHTMLElement(AtomicHTMLToken*); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 // and a Document in all other cases. | 231 // and a Document in all other cases. |
210 ContainerNode* m_attachmentRoot; | 232 ContainerNode* m_attachmentRoot; |
211 | 233 |
212 RefPtr<HTMLStackItem> m_head; | 234 RefPtr<HTMLStackItem> m_head; |
213 RefPtr<HTMLFormElement> m_form; | 235 RefPtr<HTMLFormElement> m_form; |
214 mutable HTMLElementStack m_openElements; | 236 mutable HTMLElementStack m_openElements; |
215 mutable HTMLFormattingElementList m_activeFormattingElements; | 237 mutable HTMLFormattingElementList m_activeFormattingElements; |
216 | 238 |
217 TaskQueue m_taskQueue; | 239 TaskQueue m_taskQueue; |
218 | 240 |
| 241 struct PendingText { |
| 242 PendingText() |
| 243 : whitespaceMode(WhitespaceUnknown) |
| 244 { |
| 245 } |
| 246 |
| 247 void append(PassRefPtr<ContainerNode> newParent, PassRefPtr<Node> newNex
tChild, const String& newString, WhitespaceMode newWhitespaceMode) |
| 248 { |
| 249 ASSERT(!parent || parent == newParent); |
| 250 parent = newParent; |
| 251 ASSERT(!nextChild || nextChild == newNextChild); |
| 252 nextChild = newNextChild; |
| 253 stringBuilder.append(newString); |
| 254 whitespaceMode = std::min(whitespaceMode, newWhitespaceMode); |
| 255 } |
| 256 |
| 257 void swap(PendingText& other) |
| 258 { |
| 259 std::swap(whitespaceMode, other.whitespaceMode); |
| 260 parent.swap(other.parent); |
| 261 nextChild.swap(other.nextChild); |
| 262 stringBuilder.swap(other.stringBuilder); |
| 263 } |
| 264 |
| 265 void discard() |
| 266 { |
| 267 PendingText discardedText; |
| 268 swap(discardedText); |
| 269 } |
| 270 |
| 271 bool isEmpty() |
| 272 { |
| 273 // When the stringbuilder is empty, the parent and whitespace should
also be "empty". |
| 274 ASSERT(stringBuilder.isEmpty() == !parent); |
| 275 ASSERT(!stringBuilder.isEmpty() || !nextChild); |
| 276 ASSERT(!stringBuilder.isEmpty() || (whitespaceMode == WhitespaceUnkn
own)); |
| 277 return stringBuilder.isEmpty(); |
| 278 } |
| 279 |
| 280 RefPtr<ContainerNode> parent; |
| 281 RefPtr<Node> nextChild; |
| 282 StringBuilder stringBuilder; |
| 283 WhitespaceMode whitespaceMode; |
| 284 }; |
| 285 |
| 286 PendingText m_pendingText; |
| 287 |
219 ParserContentPolicy m_parserContentPolicy; | 288 ParserContentPolicy m_parserContentPolicy; |
220 bool m_isParsingFragment; | 289 bool m_isParsingFragment; |
221 | 290 |
222 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.
html#parsing-main-intable | 291 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.
html#parsing-main-intable |
223 // In the "in table" insertion mode, we sometimes get into a state where | 292 // In the "in table" insertion mode, we sometimes get into a state where |
224 // "whenever a node would be inserted into the current node, it must instead | 293 // "whenever a node would be inserted into the current node, it must instead |
225 // be foster parented." This flag tracks whether we're in that state. | 294 // be foster parented." This flag tracks whether we're in that state. |
226 bool m_redirectAttachToFosterParent; | 295 bool m_redirectAttachToFosterParent; |
227 | 296 |
228 bool m_inQuirksMode; | 297 bool m_inQuirksMode; |
229 }; | 298 }; |
230 | 299 |
231 } // namespace WebCore | 300 } // namespace WebCore |
232 | 301 |
233 #endif | 302 #endif |
OLD | NEW |