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/. */
5 #ifndef nsHtml5TreeOperation_h
6 #define nsHtml5TreeOperation_h
8 #include "nsHtml5DocumentMode.h"
9 #include "nsHtml5HtmlAttributes.h"
10 #include "nsXPCOMStrings.h"
11 #include "mozilla/dom/FromParser.h"
14 class nsHtml5TreeOpExecutor
;
15 class nsHtml5StateSnapshot
;
16 class nsHtml5DocumentBuilder
;
18 enum eHtml5TreeOperation
{
25 eTreeOpAppendChildrenToNewParent
,
27 eTreeOpAppendToDocument
,
30 eTreeOpCreateElementNetwork
,
31 eTreeOpCreateElementNotNetwork
,
32 eTreeOpSetFormElement
,
34 eTreeOpAppendIsindexPrompt
,
35 eTreeOpFosterParentText
,
37 eTreeOpAppendCommentToDocument
,
38 eTreeOpAppendDoctypeToDocument
,
39 eTreeOpGetDocumentFragmentForTemplate
,
40 // Gecko-specific on-pop ops
43 eTreeOpRunScriptAsyncDefer
,
44 eTreeOpPreventScriptExecution
,
45 eTreeOpDoneAddingChildren
,
46 eTreeOpDoneCreatingElement
,
47 eTreeOpSetDocumentCharset
,
48 eTreeOpNeedsCharsetSwitchTo
,
49 eTreeOpUpdateStyleSheet
,
51 eTreeOpProcessOfflineManifest
,
52 eTreeOpMarkMalformedIfScript
,
54 eTreeOpSetStyleLineNumber
,
55 eTreeOpSetScriptLineNumberAndFreeze
,
57 eTreeOpMaybeComplainAboutCharset
,
59 eTreeOpAddViewSourceHref
,
61 eTreeOpAddLineNumberId
,
63 eTreeOpAddErrorTwoAtoms
,
67 class nsHtml5TreeOperationStringPair
{
72 nsHtml5TreeOperationStringPair(const nsAString
& aPublicId
,
73 const nsAString
& aSystemId
)
74 : mPublicId(aPublicId
)
75 , mSystemId(aSystemId
)
77 MOZ_COUNT_CTOR(nsHtml5TreeOperationStringPair
);
80 ~nsHtml5TreeOperationStringPair()
82 MOZ_COUNT_DTOR(nsHtml5TreeOperationStringPair
);
85 inline void Get(nsAString
& aPublicId
, nsAString
& aSystemId
)
87 aPublicId
.Assign(mPublicId
);
88 aSystemId
.Assign(mSystemId
);
92 class nsHtml5TreeOperation
{
96 * Atom is used inside the parser core are either static atoms that are
97 * the same as Gecko-wide static atoms or they are dynamic atoms scoped by
98 * both thread and parser to a particular nsHtml5AtomTable. In order to
99 * such scoped atoms coming into contact with the rest of Gecko, atoms
100 * that are about to exit the parser must go through this method which
101 * reobtains dynamic atoms from the Gecko-global atom table.
103 * @param aAtom a potentially parser-scoped atom
104 * @return an nsIAtom that's pointer comparable on the main thread with
105 * other not-parser atoms.
107 static inline already_AddRefed
<nsIAtom
> Reget(nsIAtom
* aAtom
)
109 if (!aAtom
|| aAtom
->IsStaticAtom()) {
110 return dont_AddRef(aAtom
);
113 aAtom
->ToString(str
);
114 return do_GetAtom(str
);
117 static nsresult
AppendTextToTextNode(const char16_t
* aBuffer
,
119 nsIContent
* aTextNode
,
120 nsHtml5DocumentBuilder
* aBuilder
);
122 static nsresult
AppendText(const char16_t
* aBuffer
,
125 nsHtml5DocumentBuilder
* aBuilder
);
127 static nsresult
Append(nsIContent
* aNode
,
129 nsHtml5DocumentBuilder
* aBuilder
);
131 static nsresult
AppendToDocument(nsIContent
* aNode
,
132 nsHtml5DocumentBuilder
* aBuilder
);
134 static void Detach(nsIContent
* aNode
, nsHtml5DocumentBuilder
* aBuilder
);
136 static nsresult
AppendChildrenToNewParent(nsIContent
* aNode
,
138 nsHtml5DocumentBuilder
* aBuilder
);
140 static nsresult
FosterParent(nsIContent
* aNode
,
143 nsHtml5DocumentBuilder
* aBuilder
);
145 static nsresult
AddAttributes(nsIContent
* aNode
,
146 nsHtml5HtmlAttributes
* aAttributes
,
147 nsHtml5DocumentBuilder
* aBuilder
);
149 static nsIContent
* CreateElement(int32_t aNs
,
151 nsHtml5HtmlAttributes
* aAttributes
,
152 mozilla::dom::FromParser aFromParser
,
153 nsHtml5DocumentBuilder
* aBuilder
);
155 static void SetFormElement(nsIContent
* aNode
, nsIContent
* aParent
);
157 static nsresult
AppendIsindexPrompt(nsIContent
* parent
,
158 nsHtml5DocumentBuilder
* aBuilder
);
160 static nsresult
FosterParentText(nsIContent
* aStackParent
,
164 nsHtml5DocumentBuilder
* aBuilder
);
166 static nsresult
AppendComment(nsIContent
* aParent
,
169 nsHtml5DocumentBuilder
* aBuilder
);
171 static nsresult
AppendCommentToDocument(char16_t
* aBuffer
,
173 nsHtml5DocumentBuilder
* aBuilder
);
175 static nsresult
AppendDoctypeToDocument(nsIAtom
* aName
,
176 const nsAString
& aPublicId
,
177 const nsAString
& aSystemId
,
178 nsHtml5DocumentBuilder
* aBuilder
);
180 static nsIContent
* GetDocumentFragmentForTemplate(nsIContent
* aNode
);
182 static void PreventScriptExecution(nsIContent
* aNode
);
184 static void DoneAddingChildren(nsIContent
* aNode
);
186 static void DoneCreatingElement(nsIContent
* aNode
);
188 static void SvgLoad(nsIContent
* aNode
);
190 static void MarkMalformedIfScript(nsIContent
* aNode
);
192 nsHtml5TreeOperation();
194 ~nsHtml5TreeOperation();
196 inline void Init(eHtml5TreeOperation aOpCode
)
198 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
199 "Op code must be uninitialized when initializing.");
203 inline void Init(eHtml5TreeOperation aOpCode
, nsIContentHandle
* aNode
)
205 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
206 "Op code must be uninitialized when initializing.");
207 NS_PRECONDITION(aNode
, "Initialized tree op with null node.");
209 mOne
.node
= static_cast<nsIContent
**>(aNode
);
212 inline void Init(eHtml5TreeOperation aOpCode
,
213 nsIContentHandle
* aNode
,
214 nsIContentHandle
* aParent
)
216 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
217 "Op code must be uninitialized when initializing.");
218 NS_PRECONDITION(aNode
, "Initialized tree op with null node.");
219 NS_PRECONDITION(aParent
, "Initialized tree op with null parent.");
221 mOne
.node
= static_cast<nsIContent
**>(aNode
);
222 mTwo
.node
= static_cast<nsIContent
**>(aParent
);
225 inline void Init(eHtml5TreeOperation aOpCode
,
226 const nsACString
& aString
,
229 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
230 "Op code must be uninitialized when initializing.");
232 int32_t len
= aString
.Length();
233 char* str
= new char[len
+ 1];
234 const char* start
= aString
.BeginReading();
235 for (int32_t i
= 0; i
< len
; ++i
) {
242 mFour
.integer
= aInt32
;
245 inline void Init(eHtml5TreeOperation aOpCode
,
246 const nsACString
& aString
,
250 Init(aOpCode
, aString
, aInt32
);
251 mTwo
.integer
= aLineNumber
;
254 inline void Init(eHtml5TreeOperation aOpCode
,
255 nsIContentHandle
* aNode
,
256 nsIContentHandle
* aParent
,
257 nsIContentHandle
* aTable
)
259 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
260 "Op code must be uninitialized when initializing.");
261 NS_PRECONDITION(aNode
, "Initialized tree op with null node.");
262 NS_PRECONDITION(aParent
, "Initialized tree op with null parent.");
263 NS_PRECONDITION(aTable
, "Initialized tree op with null table.");
265 mOne
.node
= static_cast<nsIContent
**>(aNode
);
266 mTwo
.node
= static_cast<nsIContent
**>(aParent
);
267 mThree
.node
= static_cast<nsIContent
**>(aTable
);
270 inline void Init(nsHtml5DocumentMode aMode
)
272 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
273 "Op code must be uninitialized when initializing.");
274 mOpCode
= eTreeOpDocumentMode
;
278 inline void InitScript(nsIContentHandle
* aNode
)
280 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
281 "Op code must be uninitialized when initializing.");
282 NS_PRECONDITION(aNode
, "Initialized tree op with null node.");
283 mOpCode
= eTreeOpRunScript
;
284 mOne
.node
= static_cast<nsIContent
**>(aNode
);
285 mTwo
.state
= nullptr;
288 inline void Init(int32_t aNamespace
,
290 nsHtml5HtmlAttributes
* aAttributes
,
291 nsIContentHandle
* aTarget
,
294 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
295 "Op code must be uninitialized when initializing.");
296 NS_PRECONDITION(aName
, "Initialized tree op with null name.");
297 NS_PRECONDITION(aTarget
, "Initialized tree op with null target node.");
298 mOpCode
= aFromNetwork
?
299 eTreeOpCreateElementNetwork
:
300 eTreeOpCreateElementNotNetwork
;
301 mFour
.integer
= aNamespace
;
302 mOne
.node
= static_cast<nsIContent
**>(aTarget
);
304 if (aAttributes
== nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
) {
305 mThree
.attributes
= nullptr;
307 mThree
.attributes
= aAttributes
;
311 inline void Init(eHtml5TreeOperation aOpCode
,
314 nsIContentHandle
* aStackParent
,
315 nsIContentHandle
* aTable
)
317 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
318 "Op code must be uninitialized when initializing.");
319 NS_PRECONDITION(aBuffer
, "Initialized tree op with null buffer.");
321 mOne
.node
= static_cast<nsIContent
**>(aStackParent
);
322 mTwo
.unicharPtr
= aBuffer
;
323 mThree
.node
= static_cast<nsIContent
**>(aTable
);
324 mFour
.integer
= aLength
;
327 inline void Init(eHtml5TreeOperation aOpCode
,
330 nsIContentHandle
* aParent
)
332 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
333 "Op code must be uninitialized when initializing.");
334 NS_PRECONDITION(aBuffer
, "Initialized tree op with null buffer.");
336 mOne
.node
= static_cast<nsIContent
**>(aParent
);
337 mTwo
.unicharPtr
= aBuffer
;
338 mFour
.integer
= aLength
;
341 inline void Init(eHtml5TreeOperation aOpCode
,
345 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
346 "Op code must be uninitialized when initializing.");
347 NS_PRECONDITION(aBuffer
, "Initialized tree op with null buffer.");
349 mTwo
.unicharPtr
= aBuffer
;
350 mFour
.integer
= aLength
;
353 inline void Init(nsIContentHandle
* aElement
,
354 nsHtml5HtmlAttributes
* aAttributes
)
356 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
357 "Op code must be uninitialized when initializing.");
358 NS_PRECONDITION(aElement
, "Initialized tree op with null element.");
359 mOpCode
= eTreeOpAddAttributes
;
360 mOne
.node
= static_cast<nsIContent
**>(aElement
);
361 mTwo
.attributes
= aAttributes
;
364 inline void Init(nsIAtom
* aName
,
365 const nsAString
& aPublicId
,
366 const nsAString
& aSystemId
)
368 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
369 "Op code must be uninitialized when initializing.");
370 mOpCode
= eTreeOpAppendDoctypeToDocument
;
372 mTwo
.stringPair
= new nsHtml5TreeOperationStringPair(aPublicId
, aSystemId
);
375 inline void Init(nsIContentHandle
* aElement
,
380 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
381 "Op code must be uninitialized when initializing.");
382 mOpCode
= eTreeOpAddError
;
383 mOne
.node
= static_cast<nsIContent
**>(aElement
);
384 mTwo
.charPtr
= (char*)aMsgId
;
386 mFour
.atom
= aOtherAtom
;
389 inline void Init(nsIContentHandle
* aElement
,
393 Init(aElement
, aMsgId
, aAtom
, nullptr);
396 inline void Init(nsIContentHandle
* aElement
,
399 Init(aElement
, aMsgId
, nullptr, nullptr);
402 inline void Init(const char* aMsgId
,
406 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
407 "Op code must be uninitialized when initializing.");
408 mOpCode
= eTreeOpMaybeComplainAboutCharset
;
409 mOne
.charPtr
= const_cast<char*>(aMsgId
);
410 mTwo
.integer
= aError
;
411 mThree
.integer
= aLineNumber
;
414 inline void Init(eHtml5TreeOperation aOpCode
, const nsAString
& aString
)
416 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
417 "Op code must be uninitialized when initializing.");
419 char16_t
* str
= NS_StringCloneData(aString
);
421 mOne
.unicharPtr
= str
;
424 inline void Init(eHtml5TreeOperation aOpCode
,
425 nsIContentHandle
* aNode
,
428 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
429 "Op code must be uninitialized when initializing.");
430 NS_PRECONDITION(aNode
, "Initialized tree op with null node.");
432 mOne
.node
= static_cast<nsIContent
**>(aNode
);
433 mFour
.integer
= aInt
;
436 inline void Init(nsresult aRv
)
438 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
439 "Op code must be uninitialized when initializing.");
440 NS_PRECONDITION(NS_FAILED(aRv
), "Initialized tree op with non-failure.");
441 mOpCode
= eTreeOpMarkAsBroken
;
445 inline void InitAddClass(nsIContentHandle
* aNode
, const char16_t
* aClass
)
447 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
448 "Op code must be uninitialized when initializing.");
449 NS_PRECONDITION(aNode
, "Initialized tree op with null node.");
450 NS_PRECONDITION(aClass
, "Initialized tree op with null string.");
451 // aClass must be a literal string that does not need freeing
452 mOpCode
= eTreeOpAddClass
;
453 mOne
.node
= static_cast<nsIContent
**>(aNode
);
454 mTwo
.unicharPtr
= (char16_t
*)aClass
;
457 inline void InitAddLineNumberId(nsIContentHandle
* aNode
,
458 const int32_t aLineNumber
)
460 NS_PRECONDITION(mOpCode
== eTreeOpUninitialized
,
461 "Op code must be uninitialized when initializing.");
462 NS_PRECONDITION(aNode
, "Initialized tree op with null node.");
463 NS_PRECONDITION(aLineNumber
> 0, "Initialized tree op with line number.");
464 // aClass must be a literal string that does not need freeing
465 mOpCode
= eTreeOpAddLineNumberId
;
466 mOne
.node
= static_cast<nsIContent
**>(aNode
);
467 mFour
.integer
= aLineNumber
;
470 inline bool IsRunScript()
472 return mOpCode
== eTreeOpRunScript
;
475 inline void SetSnapshot(nsAHtml5TreeBuilderState
* aSnapshot
, int32_t aLine
)
477 NS_ASSERTION(IsRunScript(),
478 "Setting a snapshot for a tree operation other than eTreeOpRunScript!");
479 NS_PRECONDITION(aSnapshot
, "Initialized tree op with null snapshot.");
480 mTwo
.state
= aSnapshot
;
481 mFour
.integer
= aLine
;
484 nsresult
Perform(nsHtml5TreeOpExecutor
* aBuilder
,
485 nsIContent
** aScriptElement
);
488 // possible optimization:
489 // Make the queue take items the size of pointer and make the op code
490 // decide how many operands it dequeues after it.
491 eHtml5TreeOperation mOpCode
;
495 nsHtml5HtmlAttributes
* attributes
;
496 nsHtml5DocumentMode mode
;
497 char16_t
* unicharPtr
;
499 nsHtml5TreeOperationStringPair
* stringPair
;
500 nsAHtml5TreeBuilderState
* state
;
503 } mOne
, mTwo
, mThree
, mFour
;
506 #endif // nsHtml5TreeOperation_h