1 : /* ***** BEGIN LICENSE BLOCK *****
2 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 : *
4 : * The contents of this file are subject to the Mozilla Public License Version
5 : * 1.1 (the "License"); you may not use this file except in compliance with
6 : * the License. You may obtain a copy of the License at
7 : * http://www.mozilla.org/MPL/
8 : *
9 : * Software distributed under the License is distributed on an "AS IS" basis,
10 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 : * for the specific language governing rights and limitations under the
12 : * License.
13 : *
14 : * The Original Code is HTML Parser C++ Translator code.
15 : *
16 : * The Initial Developer of the Original Code is
17 : * Mozilla Foundation.
18 : * Portions created by the Initial Developer are Copyright (C) 2009
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Henri Sivonen <hsivonen@iki.fi>
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #ifndef nsHtml5TreeOperation_h__
39 : #define nsHtml5TreeOperation_h__
40 :
41 : #include "nsHtml5DocumentMode.h"
42 : #include "nsHtml5HtmlAttributes.h"
43 : #include "nsXPCOMStrings.h"
44 :
45 : class nsIContent;
46 : class nsHtml5TreeOpExecutor;
47 : class nsHtml5StateSnapshot;
48 :
49 : enum eHtml5TreeOperation {
50 : #ifdef DEBUG
51 : eTreeOpUninitialized,
52 : #endif
53 : // main HTML5 ops
54 : eTreeOpAppend,
55 : eTreeOpDetach,
56 : eTreeOpAppendChildrenToNewParent,
57 : eTreeOpFosterParent,
58 : eTreeOpAppendToDocument,
59 : eTreeOpAddAttributes,
60 : eTreeOpDocumentMode,
61 : eTreeOpCreateElementNetwork,
62 : eTreeOpCreateElementNotNetwork,
63 : eTreeOpSetFormElement,
64 : eTreeOpAppendText,
65 : eTreeOpAppendIsindexPrompt,
66 : eTreeOpFosterParentText,
67 : eTreeOpAppendComment,
68 : eTreeOpAppendCommentToDocument,
69 : eTreeOpAppendDoctypeToDocument,
70 : // Gecko-specific on-pop ops
71 : eTreeOpMarkAsBroken,
72 : eTreeOpRunScript,
73 : eTreeOpRunScriptAsyncDefer,
74 : eTreeOpDoneAddingChildren,
75 : eTreeOpDoneCreatingElement,
76 : eTreeOpFlushPendingAppendNotifications,
77 : eTreeOpSetDocumentCharset,
78 : eTreeOpNeedsCharsetSwitchTo,
79 : eTreeOpUpdateStyleSheet,
80 : eTreeOpProcessMeta,
81 : eTreeOpProcessOfflineManifest,
82 : eTreeOpMarkMalformedIfScript,
83 : eTreeOpStreamEnded,
84 : eTreeOpSetStyleLineNumber,
85 : eTreeOpSetScriptLineNumberAndFreeze,
86 : eTreeOpSvgLoad,
87 : eTreeOpAddClass,
88 : eTreeOpAddViewSourceHref,
89 : eTreeOpAddError,
90 : eTreeOpAddLineNumberId,
91 : eTreeOpAddErrorAtom,
92 : eTreeOpAddErrorTwoAtoms,
93 : eTreeOpStartLayout
94 : };
95 :
96 : class nsHtml5TreeOperationStringPair {
97 : private:
98 : nsString mPublicId;
99 : nsString mSystemId;
100 : public:
101 0 : nsHtml5TreeOperationStringPair(const nsAString& aPublicId,
102 : const nsAString& aSystemId)
103 : : mPublicId(aPublicId)
104 0 : , mSystemId(aSystemId) {
105 0 : MOZ_COUNT_CTOR(nsHtml5TreeOperationStringPair);
106 0 : }
107 :
108 0 : ~nsHtml5TreeOperationStringPair() {
109 0 : MOZ_COUNT_DTOR(nsHtml5TreeOperationStringPair);
110 0 : }
111 :
112 0 : inline void Get(nsAString& aPublicId, nsAString& aSystemId) {
113 0 : aPublicId.Assign(mPublicId);
114 0 : aSystemId.Assign(mSystemId);
115 0 : }
116 : };
117 :
118 : class nsHtml5TreeOperation {
119 :
120 : public:
121 : nsHtml5TreeOperation();
122 :
123 : ~nsHtml5TreeOperation();
124 :
125 468 : inline void Init(eHtml5TreeOperation aOpCode) {
126 468 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
127 : "Op code must be uninitialized when initializing.");
128 468 : mOpCode = aOpCode;
129 468 : }
130 :
131 702 : inline void Init(eHtml5TreeOperation aOpCode, nsIContent** aNode) {
132 702 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
133 : "Op code must be uninitialized when initializing.");
134 702 : NS_PRECONDITION(aNode, "Initialized tree op with null node.");
135 702 : mOpCode = aOpCode;
136 702 : mOne.node = aNode;
137 702 : }
138 :
139 546 : inline void Init(eHtml5TreeOperation aOpCode,
140 : nsIContent** aNode,
141 : nsIContent** aParent) {
142 546 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
143 : "Op code must be uninitialized when initializing.");
144 546 : NS_PRECONDITION(aNode, "Initialized tree op with null node.");
145 546 : NS_PRECONDITION(aParent, "Initialized tree op with null parent.");
146 546 : mOpCode = aOpCode;
147 546 : mOne.node = aNode;
148 546 : mTwo.node = aParent;
149 546 : }
150 :
151 0 : inline void Init(eHtml5TreeOperation aOpCode,
152 : const nsACString& aString,
153 : PRInt32 aInt32) {
154 0 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
155 : "Op code must be uninitialized when initializing.");
156 :
157 0 : PRInt32 len = aString.Length();
158 0 : char* str = new char[len + 1];
159 0 : const char* start = aString.BeginReading();
160 0 : for (PRInt32 i = 0; i < len; ++i) {
161 0 : str[i] = start[i];
162 : }
163 0 : str[len] = '\0';
164 :
165 0 : mOpCode = aOpCode;
166 0 : mOne.charPtr = str;
167 0 : mFour.integer = aInt32;
168 0 : }
169 :
170 0 : inline void Init(eHtml5TreeOperation aOpCode,
171 : nsIContent** aNode,
172 : nsIContent** aParent,
173 : nsIContent** aTable) {
174 0 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
175 : "Op code must be uninitialized when initializing.");
176 0 : NS_PRECONDITION(aNode, "Initialized tree op with null node.");
177 0 : NS_PRECONDITION(aParent, "Initialized tree op with null parent.");
178 0 : NS_PRECONDITION(aTable, "Initialized tree op with null table.");
179 0 : mOpCode = aOpCode;
180 0 : mOne.node = aNode;
181 0 : mTwo.node = aParent;
182 0 : mThree.node = aTable;
183 0 : }
184 :
185 234 : inline void Init(nsHtml5DocumentMode aMode) {
186 234 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
187 : "Op code must be uninitialized when initializing.");
188 234 : mOpCode = eTreeOpDocumentMode;
189 234 : mOne.mode = aMode;
190 234 : }
191 :
192 0 : inline void InitScript(nsIContent** aNode) {
193 0 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
194 : "Op code must be uninitialized when initializing.");
195 0 : NS_PRECONDITION(aNode, "Initialized tree op with null node.");
196 0 : mOpCode = eTreeOpRunScript;
197 0 : mOne.node = aNode;
198 0 : mTwo.state = nsnull;
199 0 : }
200 :
201 780 : inline void Init(PRInt32 aNamespace,
202 : nsIAtom* aName,
203 : nsHtml5HtmlAttributes* aAttributes,
204 : nsIContent** aTarget,
205 : bool aFromNetwork) {
206 780 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
207 : "Op code must be uninitialized when initializing.");
208 780 : NS_PRECONDITION(aName, "Initialized tree op with null name.");
209 780 : NS_PRECONDITION(aTarget, "Initialized tree op with null target node.");
210 : mOpCode = aFromNetwork ?
211 : eTreeOpCreateElementNetwork :
212 780 : eTreeOpCreateElementNotNetwork;
213 780 : mFour.integer = aNamespace;
214 780 : mOne.node = aTarget;
215 780 : mTwo.atom = aName;
216 780 : if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
217 780 : mThree.attributes = nsnull;
218 : } else {
219 0 : mThree.attributes = aAttributes;
220 : }
221 780 : }
222 :
223 0 : inline void Init(eHtml5TreeOperation aOpCode,
224 : PRUnichar* aBuffer,
225 : PRInt32 aLength,
226 : nsIContent** aStackParent,
227 : nsIContent** aTable) {
228 0 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
229 : "Op code must be uninitialized when initializing.");
230 0 : NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer.");
231 0 : mOpCode = aOpCode;
232 0 : mOne.node = aStackParent;
233 0 : mTwo.unicharPtr = aBuffer;
234 0 : mThree.node = aTable;
235 0 : mFour.integer = aLength;
236 0 : }
237 :
238 287 : inline void Init(eHtml5TreeOperation aOpCode,
239 : PRUnichar* aBuffer,
240 : PRInt32 aLength,
241 : nsIContent** aParent) {
242 287 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
243 : "Op code must be uninitialized when initializing.");
244 287 : NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer.");
245 287 : mOpCode = aOpCode;
246 287 : mOne.node = aParent;
247 287 : mTwo.unicharPtr = aBuffer;
248 287 : mFour.integer = aLength;
249 287 : }
250 :
251 0 : inline void Init(eHtml5TreeOperation aOpCode,
252 : PRUnichar* aBuffer,
253 : PRInt32 aLength) {
254 0 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
255 : "Op code must be uninitialized when initializing.");
256 0 : NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer.");
257 0 : mOpCode = aOpCode;
258 0 : mTwo.unicharPtr = aBuffer;
259 0 : mFour.integer = aLength;
260 0 : }
261 :
262 0 : inline void Init(nsIContent** aElement,
263 : nsHtml5HtmlAttributes* aAttributes) {
264 0 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
265 : "Op code must be uninitialized when initializing.");
266 0 : NS_PRECONDITION(aElement, "Initialized tree op with null element.");
267 0 : mOpCode = eTreeOpAddAttributes;
268 0 : mOne.node = aElement;
269 0 : mTwo.attributes = aAttributes;
270 0 : }
271 :
272 0 : inline void Init(nsIAtom* aName,
273 : const nsAString& aPublicId,
274 : const nsAString& aSystemId) {
275 0 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
276 : "Op code must be uninitialized when initializing.");
277 0 : mOpCode = eTreeOpAppendDoctypeToDocument;
278 0 : mOne.atom = aName;
279 0 : mTwo.stringPair = new nsHtml5TreeOperationStringPair(aPublicId, aSystemId);
280 0 : }
281 :
282 0 : inline void Init(nsIContent** aElement,
283 : const char* aMsgId,
284 : nsIAtom* aAtom,
285 : nsIAtom* aOtherAtom) {
286 0 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
287 : "Op code must be uninitialized when initializing.");
288 0 : mOpCode = eTreeOpAddError;
289 0 : mOne.node = aElement;
290 0 : mTwo.charPtr = (char*)aMsgId;
291 0 : mThree.atom = aAtom;
292 0 : mFour.atom = aOtherAtom;
293 0 : }
294 :
295 0 : inline void Init(nsIContent** aElement,
296 : const char* aMsgId,
297 : nsIAtom* aAtom) {
298 0 : Init(aElement, aMsgId, aAtom, nsnull);
299 0 : }
300 :
301 0 : inline void Init(nsIContent** aElement,
302 : const char* aMsgId) {
303 0 : Init(aElement, aMsgId, nsnull, nsnull);
304 0 : }
305 :
306 234 : inline void Init(eHtml5TreeOperation aOpCode, const nsAString& aString) {
307 234 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
308 : "Op code must be uninitialized when initializing.");
309 :
310 234 : PRUnichar* str = NS_StringCloneData(aString);
311 234 : mOpCode = aOpCode;
312 234 : mOne.unicharPtr = str;
313 234 : }
314 :
315 0 : inline void Init(eHtml5TreeOperation aOpCode,
316 : nsIContent** aNode,
317 : PRInt32 aInt) {
318 0 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
319 : "Op code must be uninitialized when initializing.");
320 0 : NS_PRECONDITION(aNode, "Initialized tree op with null node.");
321 0 : mOpCode = aOpCode;
322 0 : mOne.node = aNode;
323 0 : mFour.integer = aInt;
324 0 : }
325 :
326 0 : inline void InitAddClass(nsIContent** aNode, const PRUnichar* aClass) {
327 0 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
328 : "Op code must be uninitialized when initializing.");
329 0 : NS_PRECONDITION(aNode, "Initialized tree op with null node.");
330 0 : NS_PRECONDITION(aClass, "Initialized tree op with null string.");
331 : // aClass must be a literal string that does not need freeing
332 0 : mOpCode = eTreeOpAddClass;
333 0 : mOne.node = aNode;
334 0 : mTwo.unicharPtr = (PRUnichar*)aClass;
335 0 : }
336 :
337 0 : inline void InitAddLineNumberId(nsIContent** aNode,
338 : const PRInt32 aLineNumber) {
339 0 : NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
340 : "Op code must be uninitialized when initializing.");
341 0 : NS_PRECONDITION(aNode, "Initialized tree op with null node.");
342 0 : NS_PRECONDITION(aLineNumber > 0, "Initialized tree op with line number.");
343 : // aClass must be a literal string that does not need freeing
344 0 : mOpCode = eTreeOpAddLineNumberId;
345 0 : mOne.node = aNode;
346 0 : mFour.integer = aLineNumber;
347 0 : }
348 :
349 234 : inline bool IsRunScript() {
350 234 : return mOpCode == eTreeOpRunScript;
351 : }
352 :
353 0 : inline void SetSnapshot(nsAHtml5TreeBuilderState* aSnapshot, PRInt32 aLine) {
354 0 : NS_ASSERTION(IsRunScript(),
355 : "Setting a snapshot for a tree operation other than eTreeOpRunScript!");
356 0 : NS_PRECONDITION(aSnapshot, "Initialized tree op with null snapshot.");
357 0 : mTwo.state = aSnapshot;
358 0 : mFour.integer = aLine;
359 0 : }
360 :
361 : nsresult Perform(nsHtml5TreeOpExecutor* aBuilder, nsIContent** aScriptElement);
362 :
363 780 : inline already_AddRefed<nsIAtom> Reget(nsIAtom* aAtom) {
364 780 : if (!aAtom || aAtom->IsStaticAtom()) {
365 780 : return aAtom;
366 : }
367 0 : nsAutoString str;
368 0 : aAtom->ToString(str);
369 0 : return do_GetAtom(str);
370 : }
371 :
372 : private:
373 :
374 : nsresult AppendTextToTextNode(const PRUnichar* aBuffer,
375 : PRUint32 aLength,
376 : nsIContent* aTextNode,
377 : nsHtml5TreeOpExecutor* aBuilder);
378 :
379 : nsresult AppendText(const PRUnichar* aBuffer,
380 : PRUint32 aLength,
381 : nsIContent* aParent,
382 : nsHtml5TreeOpExecutor* aBuilder);
383 :
384 : nsresult Append(nsIContent* aNode,
385 : nsIContent* aParent,
386 : nsHtml5TreeOpExecutor* aBuilder);
387 :
388 : nsresult AppendToDocument(nsIContent* aNode,
389 : nsHtml5TreeOpExecutor* aBuilder);
390 :
391 : // possible optimization:
392 : // Make the queue take items the size of pointer and make the op code
393 : // decide how many operands it dequeues after it.
394 : eHtml5TreeOperation mOpCode;
395 : union {
396 : nsIContent** node;
397 : nsIAtom* atom;
398 : nsHtml5HtmlAttributes* attributes;
399 : nsHtml5DocumentMode mode;
400 : PRUnichar* unicharPtr;
401 : char* charPtr;
402 : nsHtml5TreeOperationStringPair* stringPair;
403 : nsAHtml5TreeBuilderState* state;
404 : PRInt32 integer;
405 : } mOne, mTwo, mThree, mFour;
406 : };
407 :
408 : #endif // nsHtml5TreeOperation_h__
|