Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / parser / HTMLConstructionSite.h
index cac778c..48be3b0 100644 (file)
@@ -27,6 +27,7 @@
 #ifndef HTMLConstructionSite_h
 #define HTMLConstructionSite_h
 
+#include "core/dom/Document.h"
 #include "core/dom/ParserContentPolicy.h"
 #include "core/html/parser/HTMLElementStack.h"
 #include "core/html/parser/HTMLFormattingElementList.h"
 #include "wtf/Vector.h"
 #include "wtf/text/StringBuilder.h"
 
-namespace WebCore {
+namespace blink {
 
 struct HTMLConstructionSiteTask {
+    ALLOW_ONLY_INLINE_ALLOCATION();
+public:
     enum Operation {
         Insert,
+        InsertText, // Handles possible merging of text nodes.
         InsertAlreadyParsedChild, // Insert w/o calling begin/end parsing.
         Reparent,
         TakeAllChildren,
@@ -52,6 +56,13 @@ struct HTMLConstructionSiteTask {
     {
     }
 
+    void trace(Visitor* visitor)
+    {
+        visitor->trace(parent);
+        visitor->trace(nextChild);
+        visitor->trace(child);
+    }
+
     ContainerNode* oldParent()
     {
         // It's sort of ugly, but we store the |oldParent| in the |child| field
@@ -61,19 +72,17 @@ struct HTMLConstructionSiteTask {
     }
 
     Operation operation;
-    RefPtr<ContainerNode> parent;
-    RefPtr<Node> nextChild;
-    RefPtr<Node> child;
+    RefPtrWillBeMember<ContainerNode> parent;
+    RefPtrWillBeMember<Node> nextChild;
+    RefPtrWillBeMember<Node> child;
     bool selfClosing;
 };
 
-} // namespace WebCore
+} // namespace blink
 
-namespace WTF {
-template<> struct VectorTraits<WebCore::HTMLConstructionSiteTask> : SimpleClassVectorTraits { };
-} // namespace WTF
+WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::HTMLConstructionSiteTask);
 
-namespace WebCore {
+namespace blink {
 
 // Note: These are intentionally ordered so that when we concatonate
 // strings and whitespaces the resulting whitespace is ws = min(ws1, ws2).
@@ -88,16 +97,39 @@ class Document;
 class Element;
 class HTMLFormElement;
 
-class HTMLConstructionSite {
+class HTMLConstructionSite FINAL {
     WTF_MAKE_NONCOPYABLE(HTMLConstructionSite);
+    DISALLOW_ALLOCATION();
 public:
     HTMLConstructionSite(Document*, ParserContentPolicy);
     HTMLConstructionSite(DocumentFragment*, ParserContentPolicy);
     ~HTMLConstructionSite();
+    void trace(Visitor*);
 
     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();
@@ -128,10 +160,10 @@ public:
     void insertAlreadyParsedChild(HTMLStackItem* newParent, HTMLElementStack::ElementRecord* child);
     void takeAllChildren(HTMLStackItem* newParent, HTMLElementStack::ElementRecord* oldParent);
 
-    PassRefPtr<HTMLStackItem> createElementFromSavedToken(HTMLStackItem*);
+    PassRefPtrWillBeRawPtr<HTMLStackItem> createElementFromSavedToken(HTMLStackItem*);
 
     bool shouldFosterParent() const;
-    void fosterParent(PassRefPtr<Node>);
+    void fosterParent(PassRefPtrWillBeRawPtr<Node>);
 
     bool indexOfFirstUnopenFormattingElement(unsigned& firstUnopenElementIndex) const;
     void reconstructTheActiveFormattingElements();
@@ -157,7 +189,7 @@ public:
 
     void setForm(HTMLFormElement*);
     HTMLFormElement* form() const { return m_form.get(); }
-    PassRefPtr<HTMLFormElement> takeForm();
+    PassRefPtrWillBeRawPtr<HTMLFormElement> takeForm();
 
     ParserContentPolicy parserContentPolicy() { return m_parserContentPolicy; }
 
@@ -184,17 +216,17 @@ public:
 private:
     // In the common case, this queue will have only one task because most
     // tokens produce only one DOM mutation.
-    typedef Vector<HTMLConstructionSiteTask, 1> TaskQueue;
+    typedef WillBeHeapVector<HTMLConstructionSiteTask, 1> TaskQueue;
 
     void setCompatibilityMode(Document::CompatibilityMode);
     void setCompatibilityModeFromDoctype(const String& name, const String& publicId, const String& systemId);
 
-    void attachLater(ContainerNode* parent, PassRefPtr<Node> child, bool selfClosing = false);
+    void attachLater(ContainerNode* parent, PassRefPtrWillBeRawPtr<Node> child, bool selfClosing = false);
 
     void findFosterSite(HTMLConstructionSiteTask&);
 
-    PassRefPtr<Element> createHTMLElement(AtomicHTMLToken*);
-    PassRefPtr<Element> createElement(AtomicHTMLToken*, const AtomicString& namespaceURI);
+    PassRefPtrWillBeRawPtr<HTMLElement> createHTMLElement(AtomicHTMLToken*);
+    PassRefPtrWillBeRawPtr<Element> createElement(AtomicHTMLToken*, const AtomicString& namespaceURI);
 
     void mergeAttributesFromTokenIntoElement(AtomicHTMLToken*, Element*);
     void dispatchDocumentElementAvailableIfNeeded();
@@ -202,20 +234,71 @@ private:
     void executeTask(HTMLConstructionSiteTask&);
     void queueTask(const HTMLConstructionSiteTask&);
 
-    Document* m_document;
+    RawPtrWillBeMember<Document> m_document;
 
     // This is the root ContainerNode to which the parser attaches all newly
     // constructed nodes. It points to a DocumentFragment when parsing fragments
     // and a Document in all other cases.
-    ContainerNode* m_attachmentRoot;
+    RawPtrWillBeMember<ContainerNode> m_attachmentRoot;
 
-    RefPtr<HTMLStackItem> m_head;
-    RefPtr<HTMLFormElement> m_form;
+    RefPtrWillBeMember<HTMLStackItem> m_head;
+    RefPtrWillBeMember<HTMLFormElement> m_form;
     mutable HTMLElementStack m_openElements;
     mutable HTMLFormattingElementList m_activeFormattingElements;
 
     TaskQueue m_taskQueue;
 
+    class PendingText FINAL {
+        DISALLOW_ALLOCATION();
+    public:
+        PendingText()
+            : whitespaceMode(WhitespaceUnknown)
+        {
+        }
+
+        void append(PassRefPtrWillBeRawPtr<ContainerNode> newParent, PassRefPtrWillBeRawPtr<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();
+        }
+
+        void trace(Visitor*);
+
+        RefPtrWillBeMember<ContainerNode> parent;
+        RefPtrWillBeMember<Node> nextChild;
+        StringBuilder stringBuilder;
+        WhitespaceMode whitespaceMode;
+    };
+
+    PendingText m_pendingText;
+
     ParserContentPolicy m_parserContentPolicy;
     bool m_isParsingFragment;
 
@@ -228,6 +311,6 @@ private:
     bool m_inQuirksMode;
 };
 
-} // namespace WebCore
+} // namespace blink
 
 #endif