Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #define NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH 512
6 : private:
7 : using Encoding = mozilla::Encoding;
8 : template <typename T> using NotNull = mozilla::NotNull<T>;
9 :
10 : nsHtml5OplessBuilder* mBuilder;
11 : // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12 : // If mBuilder is not null, the tree op machinery is not in use and
13 : // the fields below aren't in use, either.
14 : // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
15 : nsHtml5Highlighter* mViewSource;
16 : nsTArray<nsHtml5TreeOperation> mOpQueue;
17 : nsTArray<nsHtml5SpeculativeLoad> mSpeculativeLoadQueue;
18 : nsAHtml5TreeOpSink* mOpSink;
19 : mozilla::UniquePtr<nsIContent*[]> mHandles;
20 : int32_t mHandlesUsed;
21 : nsTArray<mozilla::UniquePtr<nsIContent*[]>> mOldHandles;
22 : nsHtml5TreeOpStage* mSpeculativeLoadStage;
23 : nsresult mBroken;
24 : bool mCurrentHtmlScriptIsAsyncOrDefer;
25 : bool mPreventScriptExecution;
26 : #ifdef DEBUG
27 : bool mActive;
28 : #endif
29 :
30 : // DocumentModeHandler
31 : /**
32 : * Tree builder uses this to report quirkiness of the document
33 : */
34 : void documentMode(nsHtml5DocumentMode m);
35 :
36 : nsIContentHandle* getDocumentFragmentForTemplate(nsIContentHandle* aTemplate);
37 :
38 : nsIContentHandle* getFormPointerForContext(nsIContentHandle* aContext);
39 :
40 : /**
41 : * Using nsIContent** instead of nsIContent* is the parser deals with DOM
42 : * nodes in a way that works off the main thread. Non-main-thread code
43 : * can't refcount or otherwise touch nsIContent objects in any way.
44 : * Yet, the off-the-main-thread code needs to have a way to hold onto a
45 : * particular node and repeatedly operate on the same node.
46 : *
47 : * The way this works is that the off-the-main-thread code has an
48 : * nsIContent** for each DOM node and a given nsIContent** is only ever
49 : * actually dereferenced into an actual nsIContent* on the main thread.
50 : * When the off-the-main-thread code requests a new node, it gets an
51 : * nsIContent** immediately and a tree op is enqueued for later allocating
52 : * an actual nsIContent object and writing a pointer to it into the memory
53 : * location pointed to by the nsIContent**.
54 : *
55 : * Since tree ops are in a queue, the node creating tree op will always
56 : * run before tree ops that try to further operate on the node that the
57 : * nsIContent** is a handle to.
58 : *
59 : * On-the-main-thread parts of the parser use nsIContent* instead of
60 : * nsIContent**. Since both cases share the same parser core, the parser
61 : * core casts both to nsIContentHandle*.
62 : */
63 : nsIContentHandle* AllocateContentHandle();
64 :
65 0 : void accumulateCharactersForced(const char16_t* aBuf, int32_t aStart, int32_t aLength)
66 : {
67 0 : accumulateCharacters(aBuf, aStart, aLength);
68 0 : }
69 :
70 0 : void MarkAsBrokenAndRequestSuspension(nsresult aRv)
71 : {
72 0 : mBuilder->MarkAsBroken(aRv);
73 0 : requestSuspension();
74 0 : }
75 :
76 : void MarkAsBrokenFromPortability(nsresult aRv);
77 :
78 : public:
79 :
80 : explicit nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder);
81 :
82 : nsHtml5TreeBuilder(nsAHtml5TreeOpSink* aOpSink,
83 : nsHtml5TreeOpStage* aStage);
84 :
85 : ~nsHtml5TreeBuilder();
86 :
87 : void StartPlainTextViewSource(const nsAutoString& aTitle);
88 :
89 : void StartPlainText();
90 :
91 : void StartPlainTextBody();
92 :
93 : bool HasScript();
94 :
95 7 : void SetOpSink(nsAHtml5TreeOpSink* aOpSink)
96 : {
97 7 : mOpSink = aOpSink;
98 7 : }
99 :
100 0 : void ClearOps()
101 : {
102 0 : mOpQueue.Clear();
103 0 : }
104 :
105 : bool Flush(bool aDiscretionary = false);
106 :
107 : void FlushLoads();
108 :
109 : void SetDocumentCharset(NotNull<const Encoding*> aEncoding,
110 : int32_t aCharsetSource);
111 :
112 : void StreamEnded();
113 :
114 : void NeedsCharsetSwitchTo(NotNull<const Encoding*> aEncoding,
115 : int32_t aSource,
116 : int32_t aLineNumber);
117 :
118 : void MaybeComplainAboutCharset(const char* aMsgId,
119 : bool aError,
120 : int32_t aLineNumber);
121 :
122 : void AddSnapshotToScript(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine);
123 :
124 : void DropHandles();
125 :
126 4 : void SetPreventScriptExecution(bool aPrevent)
127 : {
128 4 : mPreventScriptExecution = aPrevent;
129 4 : }
130 :
131 8 : bool HasBuilder()
132 : {
133 8 : return mBuilder;
134 : }
135 :
136 : /**
137 : * Makes sure the buffers are large enough to be able to tokenize aLength
138 : * UTF-16 code units before having to make the buffers larger.
139 : *
140 : * @param aLength the number of UTF-16 code units to be tokenized before the
141 : * next call to this method.
142 : * @return true if successful; false if out of memory
143 : */
144 : bool EnsureBufferSpace(int32_t aLength);
145 :
146 : void EnableViewSource(nsHtml5Highlighter* aHighlighter);
147 :
148 : void errStrayStartTag(nsIAtom* aName);
149 :
150 : void errStrayEndTag(nsIAtom* aName);
151 :
152 : void errUnclosedElements(int32_t aIndex, nsIAtom* aName);
153 :
154 : void errUnclosedElementsImplied(int32_t aIndex, nsIAtom* aName);
155 :
156 : void errUnclosedElementsCell(int32_t aIndex);
157 :
158 : void errStrayDoctype();
159 :
160 : void errAlmostStandardsDoctype();
161 :
162 : void errQuirkyDoctype();
163 :
164 : void errNonSpaceInTrailer();
165 :
166 : void errNonSpaceAfterFrameset();
167 :
168 : void errNonSpaceInFrameset();
169 :
170 : void errNonSpaceAfterBody();
171 :
172 : void errNonSpaceInColgroupInFragment();
173 :
174 : void errNonSpaceInNoscriptInHead();
175 :
176 : void errFooBetweenHeadAndBody(nsIAtom* aName);
177 :
178 : void errStartTagWithoutDoctype();
179 :
180 : void errNoSelectInTableScope();
181 :
182 : void errStartSelectWhereEndSelectExpected();
183 :
184 : void errStartTagWithSelectOpen(nsIAtom* aName);
185 :
186 : void errBadStartTagInHead(nsIAtom* aName);
187 :
188 : void errImage();
189 :
190 : void errIsindex();
191 :
192 : void errFooSeenWhenFooOpen(nsIAtom* aName);
193 :
194 : void errHeadingWhenHeadingOpen();
195 :
196 : void errFramesetStart();
197 :
198 : void errNoCellToClose();
199 :
200 : void errStartTagInTable(nsIAtom* aName);
201 :
202 : void errFormWhenFormOpen();
203 :
204 : void errTableSeenWhileTableOpen();
205 :
206 : void errStartTagInTableBody(nsIAtom* aName);
207 :
208 : void errEndTagSeenWithoutDoctype();
209 :
210 : void errEndTagAfterBody();
211 :
212 : void errEndTagSeenWithSelectOpen(nsIAtom* aName);
213 :
214 : void errGarbageInColgroup();
215 :
216 : void errEndTagBr();
217 :
218 : void errNoElementToCloseButEndTagSeen(nsIAtom* aName);
219 :
220 : void errHtmlStartTagInForeignContext(nsIAtom* aName);
221 :
222 : void errTableClosedWhileCaptionOpen();
223 :
224 : void errNoTableRowToClose();
225 :
226 : void errNonSpaceInTable();
227 :
228 : void errUnclosedChildrenInRuby();
229 :
230 : void errStartTagSeenWithoutRuby(nsIAtom* aName);
231 :
232 : void errSelfClosing();
233 :
234 : void errNoCheckUnclosedElementsOnStack();
235 :
236 : void errEndTagDidNotMatchCurrentOpenElement(nsIAtom* aName, nsIAtom* aOther);
237 :
238 : void errEndTagViolatesNestingRules(nsIAtom* aName);
239 :
240 : void errEndWithUnclosedElements(nsIAtom* aName);
241 :
242 : void MarkAsBroken(nsresult aRv);
243 :
244 : /**
245 : * Checks if this parser is broken. Returns a non-NS_OK (i.e. non-0)
246 : * value if broken.
247 : */
248 15 : nsresult IsBroken()
249 : {
250 15 : return mBroken;
251 : }
|