Use the original token to create an element in "reconstruct the active formatting...
[WebKit-https.git] / Source / WebCore / html / parser / HTMLConstructionSite.h
1 /*
2  * Copyright (C) 2010 Google, Inc. All Rights Reserved.
3  * Copyright (C) 2011 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GOOGLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #ifndef HTMLConstructionSite_h
28 #define HTMLConstructionSite_h
29
30 #include "FragmentScriptingPermission.h"
31 #include "HTMLElementStack.h"
32 #include "HTMLFormattingElementList.h"
33 #include "NotImplemented.h"
34 #include <wtf/Noncopyable.h>
35 #include <wtf/PassRefPtr.h>
36 #include <wtf/RefPtr.h>
37 #include <wtf/Vector.h>
38
39 namespace WebCore {
40
41 struct HTMLConstructionSiteTask {
42     HTMLConstructionSiteTask()
43         : selfClosing(false)
44     {
45     }
46
47     void take(HTMLConstructionSiteTask& other)
48     {
49         parent = other.parent.release();
50         nextChild = other.nextChild.release();
51         child = other.child.release();
52         selfClosing = other.selfClosing;
53     }
54
55     RefPtr<ContainerNode> parent;
56     RefPtr<Node> nextChild;
57     RefPtr<Node> child;
58     bool selfClosing;
59 };
60
61 } // namespace WebCore
62
63 namespace WTF {
64 template<> struct VectorTraits<WebCore::HTMLConstructionSiteTask> : SimpleClassVectorTraits { };
65 } // namespace WTF
66
67 namespace WebCore {
68
69 enum WhitespaceMode {
70     AllWhitespace,
71     NotAllWhitespace,
72     WhitespaceUnknown
73 };
74
75 class AtomicHTMLToken;
76 class Document;
77 class Element;
78 class HTMLFormElement;
79
80 class HTMLConstructionSite {
81     WTF_MAKE_NONCOPYABLE(HTMLConstructionSite);
82 public:
83     HTMLConstructionSite(Document*, unsigned maximumDOMTreeDepth);
84     HTMLConstructionSite(DocumentFragment*, FragmentScriptingPermission, unsigned maximumDOMTreeDepth);
85     ~HTMLConstructionSite();
86
87     void detach();
88     void executeQueuedTasks();
89
90     void insertDoctype(AtomicHTMLToken*);
91     void insertComment(AtomicHTMLToken*);
92     void insertCommentOnDocument(AtomicHTMLToken*);
93     void insertCommentOnHTMLHtmlElement(AtomicHTMLToken*);
94     void insertHTMLElement(AtomicHTMLToken*);
95     void insertSelfClosingHTMLElement(AtomicHTMLToken*);
96     void insertFormattingElement(AtomicHTMLToken*);
97     void insertHTMLHeadElement(AtomicHTMLToken*);
98     void insertHTMLBodyElement(AtomicHTMLToken*);
99     void insertHTMLFormElement(AtomicHTMLToken*, bool isDemoted = false);
100     void insertScriptElement(AtomicHTMLToken*);
101     void insertTextNode(const String&, WhitespaceMode = WhitespaceUnknown);
102     void insertForeignElement(AtomicHTMLToken*, const AtomicString& namespaceURI);
103
104     void insertHTMLHtmlStartTagBeforeHTML(AtomicHTMLToken*);
105     void insertHTMLHtmlStartTagInBody(AtomicHTMLToken*);
106     void insertHTMLBodyStartTagInBody(AtomicHTMLToken*);
107
108     PassRefPtr<Element> createHTMLElement(AtomicHTMLToken*);
109     PassRefPtr<HTMLStackItem> createElementFromSavedToken(HTMLStackItem*);
110
111     bool shouldFosterParent() const;
112     void fosterParent(PassRefPtr<Node>);
113
114     bool indexOfFirstUnopenFormattingElement(unsigned& firstUnopenElementIndex) const;
115     void reconstructTheActiveFormattingElements();
116
117     void generateImpliedEndTags();
118     void generateImpliedEndTagsWithExclusion(const AtomicString& tagName);
119
120     bool isEmpty() const { return !m_openElements.stackDepth(); }
121     HTMLElementStack::ElementRecord* currentElementRecord() const { return m_openElements.topRecord(); }
122     Element* currentElement() const { return m_openElements.top(); }
123     ContainerNode* currentNode() const { return m_openElements.topNode(); }
124     Element* oneBelowTop() const { return m_openElements.oneBelowTop(); }
125
126     HTMLElementStack* openElements() const { return &m_openElements; }
127     HTMLFormattingElementList* activeFormattingElements() const { return &m_activeFormattingElements; }
128
129     Element* head() const { return m_head.get(); }
130
131     void setForm(HTMLFormElement*);
132     HTMLFormElement* form() const { return m_form.get(); }
133     PassRefPtr<HTMLFormElement> takeForm();
134
135     class RedirectToFosterParentGuard {
136         WTF_MAKE_NONCOPYABLE(RedirectToFosterParentGuard);
137     public:
138         RedirectToFosterParentGuard(HTMLConstructionSite& tree)
139             : m_tree(tree)
140             , m_wasRedirectingBefore(tree.m_redirectAttachToFosterParent)
141         {
142             m_tree.m_redirectAttachToFosterParent = true;
143         }
144
145         ~RedirectToFosterParentGuard()
146         {
147             m_tree.m_redirectAttachToFosterParent = m_wasRedirectingBefore;
148         }
149
150     private:
151         HTMLConstructionSite& m_tree;
152         bool m_wasRedirectingBefore;
153     };
154
155 private:
156     // In the common case, this queue will have only one task because most
157     // tokens produce only one DOM mutation.
158     typedef Vector<HTMLConstructionSiteTask, 1> AttachmentQueue;
159
160     void attachLater(ContainerNode* parent, PassRefPtr<Node> child, bool selfClosing = false);
161
162     void findFosterSite(HTMLConstructionSiteTask&);
163
164     PassRefPtr<Element> createElement(AtomicHTMLToken*, const AtomicString& namespaceURI);
165
166     void mergeAttributesFromTokenIntoElement(AtomicHTMLToken*, Element*);
167     void dispatchDocumentElementAvailableIfNeeded();
168
169     Document* m_document;
170     
171     // This is the root ContainerNode to which the parser attaches all newly
172     // constructed nodes. It points to a DocumentFragment when parsing fragments
173     // and a Document in all other cases.
174     ContainerNode* m_attachmentRoot;
175     
176     RefPtr<Element> m_head;
177     RefPtr<HTMLFormElement> m_form;
178     mutable HTMLElementStack m_openElements;
179     mutable HTMLFormattingElementList m_activeFormattingElements;
180
181     AttachmentQueue m_attachmentQueue;
182
183     FragmentScriptingPermission m_fragmentScriptingPermission;
184     bool m_isParsingFragment;
185
186     // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-intable
187     // In the "in table" insertion mode, we sometimes get into a state where
188     // "whenever a node would be inserted into the current node, it must instead
189     // be foster parented."  This flag tracks whether we're in that state.
190     bool m_redirectAttachToFosterParent;
191
192     unsigned m_maximumDOMTreeDepth;
193 };
194
195 } // namespace WebCore
196
197 #endif