parser/html/nsHtml5TreeOperation.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:f1e8db7596d2
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 #ifndef nsHtml5TreeOperation_h
6 #define nsHtml5TreeOperation_h
7
8 #include "nsHtml5DocumentMode.h"
9 #include "nsHtml5HtmlAttributes.h"
10 #include "nsXPCOMStrings.h"
11 #include "mozilla/dom/FromParser.h"
12
13 class nsIContent;
14 class nsHtml5TreeOpExecutor;
15 class nsHtml5StateSnapshot;
16 class nsHtml5DocumentBuilder;
17
18 enum eHtml5TreeOperation {
19 #ifdef DEBUG
20 eTreeOpUninitialized,
21 #endif
22 // main HTML5 ops
23 eTreeOpAppend,
24 eTreeOpDetach,
25 eTreeOpAppendChildrenToNewParent,
26 eTreeOpFosterParent,
27 eTreeOpAppendToDocument,
28 eTreeOpAddAttributes,
29 eTreeOpDocumentMode,
30 eTreeOpCreateElementNetwork,
31 eTreeOpCreateElementNotNetwork,
32 eTreeOpSetFormElement,
33 eTreeOpAppendText,
34 eTreeOpAppendIsindexPrompt,
35 eTreeOpFosterParentText,
36 eTreeOpAppendComment,
37 eTreeOpAppendCommentToDocument,
38 eTreeOpAppendDoctypeToDocument,
39 eTreeOpGetDocumentFragmentForTemplate,
40 // Gecko-specific on-pop ops
41 eTreeOpMarkAsBroken,
42 eTreeOpRunScript,
43 eTreeOpRunScriptAsyncDefer,
44 eTreeOpPreventScriptExecution,
45 eTreeOpDoneAddingChildren,
46 eTreeOpDoneCreatingElement,
47 eTreeOpFlushPendingAppendNotifications,
48 eTreeOpSetDocumentCharset,
49 eTreeOpNeedsCharsetSwitchTo,
50 eTreeOpUpdateStyleSheet,
51 eTreeOpProcessMeta,
52 eTreeOpProcessOfflineManifest,
53 eTreeOpMarkMalformedIfScript,
54 eTreeOpStreamEnded,
55 eTreeOpSetStyleLineNumber,
56 eTreeOpSetScriptLineNumberAndFreeze,
57 eTreeOpSvgLoad,
58 eTreeOpMaybeComplainAboutCharset,
59 eTreeOpAddClass,
60 eTreeOpAddViewSourceHref,
61 eTreeOpAddError,
62 eTreeOpAddLineNumberId,
63 eTreeOpAddErrorAtom,
64 eTreeOpAddErrorTwoAtoms,
65 eTreeOpStartLayout
66 };
67
68 class nsHtml5TreeOperationStringPair {
69 private:
70 nsString mPublicId;
71 nsString mSystemId;
72 public:
73 nsHtml5TreeOperationStringPair(const nsAString& aPublicId,
74 const nsAString& aSystemId)
75 : mPublicId(aPublicId)
76 , mSystemId(aSystemId)
77 {
78 MOZ_COUNT_CTOR(nsHtml5TreeOperationStringPair);
79 }
80
81 ~nsHtml5TreeOperationStringPair()
82 {
83 MOZ_COUNT_DTOR(nsHtml5TreeOperationStringPair);
84 }
85
86 inline void Get(nsAString& aPublicId, nsAString& aSystemId)
87 {
88 aPublicId.Assign(mPublicId);
89 aSystemId.Assign(mSystemId);
90 }
91 };
92
93 class nsHtml5TreeOperation {
94
95 public:
96 /**
97 * Atom is used inside the parser core are either static atoms that are
98 * the same as Gecko-wide static atoms or they are dynamic atoms scoped by
99 * both thread and parser to a particular nsHtml5AtomTable. In order to
100 * such scoped atoms coming into contact with the rest of Gecko, atoms
101 * that are about to exit the parser must go through this method which
102 * reobtains dynamic atoms from the Gecko-global atom table.
103 *
104 * @param aAtom a potentially parser-scoped atom
105 * @return an nsIAtom that's pointer comparable on the main thread with
106 * other not-parser atoms.
107 */
108 static inline already_AddRefed<nsIAtom> Reget(nsIAtom* aAtom)
109 {
110 if (!aAtom || aAtom->IsStaticAtom()) {
111 return dont_AddRef(aAtom);
112 }
113 nsAutoString str;
114 aAtom->ToString(str);
115 return do_GetAtom(str);
116 }
117
118 static nsresult AppendTextToTextNode(const char16_t* aBuffer,
119 uint32_t aLength,
120 nsIContent* aTextNode,
121 nsHtml5DocumentBuilder* aBuilder);
122
123 static nsresult AppendText(const char16_t* aBuffer,
124 uint32_t aLength,
125 nsIContent* aParent,
126 nsHtml5DocumentBuilder* aBuilder);
127
128 static nsresult Append(nsIContent* aNode,
129 nsIContent* aParent,
130 nsHtml5DocumentBuilder* aBuilder);
131
132 static nsresult AppendToDocument(nsIContent* aNode,
133 nsHtml5DocumentBuilder* aBuilder);
134
135 static void Detach(nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder);
136
137 static nsresult AppendChildrenToNewParent(nsIContent* aNode,
138 nsIContent* aParent,
139 nsHtml5DocumentBuilder* aBuilder);
140
141 static nsresult FosterParent(nsIContent* aNode,
142 nsIContent* aParent,
143 nsIContent* aTable,
144 nsHtml5DocumentBuilder* aBuilder);
145
146 static nsresult AddAttributes(nsIContent* aNode,
147 nsHtml5HtmlAttributes* aAttributes,
148 nsHtml5DocumentBuilder* aBuilder);
149
150 static nsIContent* CreateElement(int32_t aNs,
151 nsIAtom* aName,
152 nsHtml5HtmlAttributes* aAttributes,
153 mozilla::dom::FromParser aFromParser,
154 nsHtml5DocumentBuilder* aBuilder);
155
156 static void SetFormElement(nsIContent* aNode, nsIContent* aParent);
157
158 static nsresult AppendIsindexPrompt(nsIContent* parent,
159 nsHtml5DocumentBuilder* aBuilder);
160
161 static nsresult FosterParentText(nsIContent* aStackParent,
162 char16_t* aBuffer,
163 uint32_t aLength,
164 nsIContent* aTable,
165 nsHtml5DocumentBuilder* aBuilder);
166
167 static nsresult AppendComment(nsIContent* aParent,
168 char16_t* aBuffer,
169 int32_t aLength,
170 nsHtml5DocumentBuilder* aBuilder);
171
172 static nsresult AppendCommentToDocument(char16_t* aBuffer,
173 int32_t aLength,
174 nsHtml5DocumentBuilder* aBuilder);
175
176 static nsresult AppendDoctypeToDocument(nsIAtom* aName,
177 const nsAString& aPublicId,
178 const nsAString& aSystemId,
179 nsHtml5DocumentBuilder* aBuilder);
180
181 static nsIContent* GetDocumentFragmentForTemplate(nsIContent* aNode);
182
183 static void PreventScriptExecution(nsIContent* aNode);
184
185 static void DoneAddingChildren(nsIContent* aNode,
186 nsHtml5DocumentBuilder* aBuilder);
187
188 static void DoneCreatingElement(nsIContent* aNode);
189
190 static void SvgLoad(nsIContent* aNode);
191
192 static void MarkMalformedIfScript(nsIContent* aNode);
193
194 nsHtml5TreeOperation();
195
196 ~nsHtml5TreeOperation();
197
198 inline void Init(eHtml5TreeOperation aOpCode)
199 {
200 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
201 "Op code must be uninitialized when initializing.");
202 mOpCode = aOpCode;
203 }
204
205 inline void Init(eHtml5TreeOperation aOpCode, nsIContentHandle* aNode)
206 {
207 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
208 "Op code must be uninitialized when initializing.");
209 NS_PRECONDITION(aNode, "Initialized tree op with null node.");
210 mOpCode = aOpCode;
211 mOne.node = static_cast<nsIContent**>(aNode);
212 }
213
214 inline void Init(eHtml5TreeOperation aOpCode,
215 nsIContentHandle* aNode,
216 nsIContentHandle* aParent)
217 {
218 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
219 "Op code must be uninitialized when initializing.");
220 NS_PRECONDITION(aNode, "Initialized tree op with null node.");
221 NS_PRECONDITION(aParent, "Initialized tree op with null parent.");
222 mOpCode = aOpCode;
223 mOne.node = static_cast<nsIContent**>(aNode);
224 mTwo.node = static_cast<nsIContent**>(aParent);
225 }
226
227 inline void Init(eHtml5TreeOperation aOpCode,
228 const nsACString& aString,
229 int32_t aInt32)
230 {
231 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
232 "Op code must be uninitialized when initializing.");
233
234 int32_t len = aString.Length();
235 char* str = new char[len + 1];
236 const char* start = aString.BeginReading();
237 for (int32_t i = 0; i < len; ++i) {
238 str[i] = start[i];
239 }
240 str[len] = '\0';
241
242 mOpCode = aOpCode;
243 mOne.charPtr = str;
244 mFour.integer = aInt32;
245 }
246
247 inline void Init(eHtml5TreeOperation aOpCode,
248 const nsACString& aString,
249 int32_t aInt32,
250 int32_t aLineNumber)
251 {
252 Init(aOpCode, aString, aInt32);
253 mTwo.integer = aLineNumber;
254 }
255
256 inline void Init(eHtml5TreeOperation aOpCode,
257 nsIContentHandle* aNode,
258 nsIContentHandle* aParent,
259 nsIContentHandle* aTable)
260 {
261 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
262 "Op code must be uninitialized when initializing.");
263 NS_PRECONDITION(aNode, "Initialized tree op with null node.");
264 NS_PRECONDITION(aParent, "Initialized tree op with null parent.");
265 NS_PRECONDITION(aTable, "Initialized tree op with null table.");
266 mOpCode = aOpCode;
267 mOne.node = static_cast<nsIContent**>(aNode);
268 mTwo.node = static_cast<nsIContent**>(aParent);
269 mThree.node = static_cast<nsIContent**>(aTable);
270 }
271
272 inline void Init(nsHtml5DocumentMode aMode)
273 {
274 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
275 "Op code must be uninitialized when initializing.");
276 mOpCode = eTreeOpDocumentMode;
277 mOne.mode = aMode;
278 }
279
280 inline void InitScript(nsIContentHandle* aNode)
281 {
282 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
283 "Op code must be uninitialized when initializing.");
284 NS_PRECONDITION(aNode, "Initialized tree op with null node.");
285 mOpCode = eTreeOpRunScript;
286 mOne.node = static_cast<nsIContent**>(aNode);
287 mTwo.state = nullptr;
288 }
289
290 inline void Init(int32_t aNamespace,
291 nsIAtom* aName,
292 nsHtml5HtmlAttributes* aAttributes,
293 nsIContentHandle* aTarget,
294 bool aFromNetwork)
295 {
296 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
297 "Op code must be uninitialized when initializing.");
298 NS_PRECONDITION(aName, "Initialized tree op with null name.");
299 NS_PRECONDITION(aTarget, "Initialized tree op with null target node.");
300 mOpCode = aFromNetwork ?
301 eTreeOpCreateElementNetwork :
302 eTreeOpCreateElementNotNetwork;
303 mFour.integer = aNamespace;
304 mOne.node = static_cast<nsIContent**>(aTarget);
305 mTwo.atom = aName;
306 if (aAttributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
307 mThree.attributes = nullptr;
308 } else {
309 mThree.attributes = aAttributes;
310 }
311 }
312
313 inline void Init(eHtml5TreeOperation aOpCode,
314 char16_t* aBuffer,
315 int32_t aLength,
316 nsIContentHandle* aStackParent,
317 nsIContentHandle* aTable)
318 {
319 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
320 "Op code must be uninitialized when initializing.");
321 NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer.");
322 mOpCode = aOpCode;
323 mOne.node = static_cast<nsIContent**>(aStackParent);
324 mTwo.unicharPtr = aBuffer;
325 mThree.node = static_cast<nsIContent**>(aTable);
326 mFour.integer = aLength;
327 }
328
329 inline void Init(eHtml5TreeOperation aOpCode,
330 char16_t* aBuffer,
331 int32_t aLength,
332 nsIContentHandle* aParent)
333 {
334 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
335 "Op code must be uninitialized when initializing.");
336 NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer.");
337 mOpCode = aOpCode;
338 mOne.node = static_cast<nsIContent**>(aParent);
339 mTwo.unicharPtr = aBuffer;
340 mFour.integer = aLength;
341 }
342
343 inline void Init(eHtml5TreeOperation aOpCode,
344 char16_t* aBuffer,
345 int32_t aLength)
346 {
347 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
348 "Op code must be uninitialized when initializing.");
349 NS_PRECONDITION(aBuffer, "Initialized tree op with null buffer.");
350 mOpCode = aOpCode;
351 mTwo.unicharPtr = aBuffer;
352 mFour.integer = aLength;
353 }
354
355 inline void Init(nsIContentHandle* aElement,
356 nsHtml5HtmlAttributes* aAttributes)
357 {
358 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
359 "Op code must be uninitialized when initializing.");
360 NS_PRECONDITION(aElement, "Initialized tree op with null element.");
361 mOpCode = eTreeOpAddAttributes;
362 mOne.node = static_cast<nsIContent**>(aElement);
363 mTwo.attributes = aAttributes;
364 }
365
366 inline void Init(nsIAtom* aName,
367 const nsAString& aPublicId,
368 const nsAString& aSystemId)
369 {
370 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
371 "Op code must be uninitialized when initializing.");
372 mOpCode = eTreeOpAppendDoctypeToDocument;
373 mOne.atom = aName;
374 mTwo.stringPair = new nsHtml5TreeOperationStringPair(aPublicId, aSystemId);
375 }
376
377 inline void Init(nsIContentHandle* aElement,
378 const char* aMsgId,
379 nsIAtom* aAtom,
380 nsIAtom* aOtherAtom)
381 {
382 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
383 "Op code must be uninitialized when initializing.");
384 mOpCode = eTreeOpAddError;
385 mOne.node = static_cast<nsIContent**>(aElement);
386 mTwo.charPtr = (char*)aMsgId;
387 mThree.atom = aAtom;
388 mFour.atom = aOtherAtom;
389 }
390
391 inline void Init(nsIContentHandle* aElement,
392 const char* aMsgId,
393 nsIAtom* aAtom)
394 {
395 Init(aElement, aMsgId, aAtom, nullptr);
396 }
397
398 inline void Init(nsIContentHandle* aElement,
399 const char* aMsgId)
400 {
401 Init(aElement, aMsgId, nullptr, nullptr);
402 }
403
404 inline void Init(const char* aMsgId,
405 bool aError,
406 int32_t aLineNumber)
407 {
408 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
409 "Op code must be uninitialized when initializing.");
410 mOpCode = eTreeOpMaybeComplainAboutCharset;
411 mOne.charPtr = const_cast<char*>(aMsgId);
412 mTwo.integer = aError;
413 mThree.integer = aLineNumber;
414 }
415
416 inline void Init(eHtml5TreeOperation aOpCode, const nsAString& aString)
417 {
418 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
419 "Op code must be uninitialized when initializing.");
420
421 char16_t* str = NS_StringCloneData(aString);
422 mOpCode = aOpCode;
423 mOne.unicharPtr = str;
424 }
425
426 inline void Init(eHtml5TreeOperation aOpCode,
427 nsIContentHandle* aNode,
428 int32_t aInt)
429 {
430 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
431 "Op code must be uninitialized when initializing.");
432 NS_PRECONDITION(aNode, "Initialized tree op with null node.");
433 mOpCode = aOpCode;
434 mOne.node = static_cast<nsIContent**>(aNode);
435 mFour.integer = aInt;
436 }
437
438 inline void Init(nsresult aRv)
439 {
440 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
441 "Op code must be uninitialized when initializing.");
442 NS_PRECONDITION(NS_FAILED(aRv), "Initialized tree op with non-failure.");
443 mOpCode = eTreeOpMarkAsBroken;
444 mOne.result = aRv;
445 }
446
447 inline void InitAddClass(nsIContentHandle* aNode, const char16_t* aClass)
448 {
449 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
450 "Op code must be uninitialized when initializing.");
451 NS_PRECONDITION(aNode, "Initialized tree op with null node.");
452 NS_PRECONDITION(aClass, "Initialized tree op with null string.");
453 // aClass must be a literal string that does not need freeing
454 mOpCode = eTreeOpAddClass;
455 mOne.node = static_cast<nsIContent**>(aNode);
456 mTwo.unicharPtr = (char16_t*)aClass;
457 }
458
459 inline void InitAddLineNumberId(nsIContentHandle* aNode,
460 const int32_t aLineNumber)
461 {
462 NS_PRECONDITION(mOpCode == eTreeOpUninitialized,
463 "Op code must be uninitialized when initializing.");
464 NS_PRECONDITION(aNode, "Initialized tree op with null node.");
465 NS_PRECONDITION(aLineNumber > 0, "Initialized tree op with line number.");
466 // aClass must be a literal string that does not need freeing
467 mOpCode = eTreeOpAddLineNumberId;
468 mOne.node = static_cast<nsIContent**>(aNode);
469 mFour.integer = aLineNumber;
470 }
471
472 inline bool IsRunScript()
473 {
474 return mOpCode == eTreeOpRunScript;
475 }
476
477 inline void SetSnapshot(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine)
478 {
479 NS_ASSERTION(IsRunScript(),
480 "Setting a snapshot for a tree operation other than eTreeOpRunScript!");
481 NS_PRECONDITION(aSnapshot, "Initialized tree op with null snapshot.");
482 mTwo.state = aSnapshot;
483 mFour.integer = aLine;
484 }
485
486 nsresult Perform(nsHtml5TreeOpExecutor* aBuilder,
487 nsIContent** aScriptElement);
488
489 private:
490 // possible optimization:
491 // Make the queue take items the size of pointer and make the op code
492 // decide how many operands it dequeues after it.
493 eHtml5TreeOperation mOpCode;
494 union {
495 nsIContent** node;
496 nsIAtom* atom;
497 nsHtml5HtmlAttributes* attributes;
498 nsHtml5DocumentMode mode;
499 char16_t* unicharPtr;
500 char* charPtr;
501 nsHtml5TreeOperationStringPair* stringPair;
502 nsAHtml5TreeBuilderState* state;
503 int32_t integer;
504 nsresult result;
505 } mOne, mTwo, mThree, mFour;
506 };
507
508 #endif // nsHtml5TreeOperation_h

mercurial