| Index: Source/core/html/parser/HTMLConstructionSite.h
|
| diff --git a/Source/core/html/parser/HTMLConstructionSite.h b/Source/core/html/parser/HTMLConstructionSite.h
|
| index cac778c02c85fffa9c32b77cda5a94dea932bc09..d4d812eb109b92268815bcf5ad77b5ffb2b2e43b 100644
|
| --- a/Source/core/html/parser/HTMLConstructionSite.h
|
| +++ b/Source/core/html/parser/HTMLConstructionSite.h
|
| @@ -41,6 +41,7 @@ namespace WebCore {
|
| struct HTMLConstructionSiteTask {
|
| enum Operation {
|
| Insert,
|
| + InsertText, // Handles possible merging of text nodes.
|
| InsertAlreadyParsedChild, // Insert w/o calling begin/end parsing.
|
| Reparent,
|
| TakeAllChildren,
|
| @@ -96,8 +97,29 @@ public:
|
| ~HTMLConstructionSite();
|
|
|
| void detach();
|
| +
|
| + // executeQueuedTasks empties the queue but does not flush pending text.
|
| + // NOTE: Possible reentrancy via JavaScript execution.
|
| void executeQueuedTasks();
|
|
|
| + // flushPendingText turns pending text into queued Text insertions, but does not execute them.
|
| + void flushPendingText();
|
| +
|
| + // Called before every token in HTMLTreeBuilder::processToken, thus inlined:
|
| + void flush()
|
| + {
|
| + if (!hasPendingTasks())
|
| + return;
|
| + flushPendingText();
|
| + executeQueuedTasks(); // NOTE: Possible reentrancy via JavaScript execution.
|
| + ASSERT(!hasPendingTasks());
|
| + }
|
| +
|
| + bool hasPendingTasks()
|
| + {
|
| + return !m_pendingText.isEmpty() || !m_taskQueue.isEmpty();
|
| + }
|
| +
|
| void setDefaultCompatibilityMode();
|
| void processEndOfFile();
|
| void finishedParsing();
|
| @@ -216,6 +238,53 @@ private:
|
|
|
| TaskQueue m_taskQueue;
|
|
|
| + struct PendingText {
|
| + PendingText()
|
| + : whitespaceMode(WhitespaceUnknown)
|
| + {
|
| + }
|
| +
|
| + void append(PassRefPtr<ContainerNode> newParent, PassRefPtr<Node> newNextChild, const String& newString, WhitespaceMode newWhitespaceMode)
|
| + {
|
| + ASSERT(!parent || parent == newParent);
|
| + parent = newParent;
|
| + ASSERT(!nextChild || nextChild == newNextChild);
|
| + nextChild = newNextChild;
|
| + stringBuilder.append(newString);
|
| + whitespaceMode = std::min(whitespaceMode, newWhitespaceMode);
|
| + }
|
| +
|
| + void swap(PendingText& other)
|
| + {
|
| + std::swap(whitespaceMode, other.whitespaceMode);
|
| + parent.swap(other.parent);
|
| + nextChild.swap(other.nextChild);
|
| + stringBuilder.swap(other.stringBuilder);
|
| + }
|
| +
|
| + void discard()
|
| + {
|
| + PendingText discardedText;
|
| + swap(discardedText);
|
| + }
|
| +
|
| + bool isEmpty()
|
| + {
|
| + // When the stringbuilder is empty, the parent and whitespace should also be "empty".
|
| + ASSERT(stringBuilder.isEmpty() == !parent);
|
| + ASSERT(!stringBuilder.isEmpty() || !nextChild);
|
| + ASSERT(!stringBuilder.isEmpty() || (whitespaceMode == WhitespaceUnknown));
|
| + return stringBuilder.isEmpty();
|
| + }
|
| +
|
| + RefPtr<ContainerNode> parent;
|
| + RefPtr<Node> nextChild;
|
| + StringBuilder stringBuilder;
|
| + WhitespaceMode whitespaceMode;
|
| + };
|
| +
|
| + PendingText m_pendingText;
|
| +
|
| ParserContentPolicy m_parserContentPolicy;
|
| bool m_isParsingFragment;
|
|
|
|
|