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 "mozilla/dom/FromParser.h"
11 #include "mozilla/NotNull.h"
12 #include "mozilla/Variant.h"
15 class nsHtml5TreeOpExecutor
;
16 class nsHtml5DocumentBuilder
;
23 } // namespace mozilla
25 struct uninitialized
{};
29 nsIContent
** mElement
;
31 explicit opDetach(nsIContentHandle
* aElement
) {
32 mElement
= static_cast<nsIContent
**>(aElement
);
39 mozilla::dom::FromParser mFromNetwork
;
41 explicit opAppend(nsIContentHandle
* aChild
, nsIContentHandle
* aParent
,
42 mozilla::dom::FromParser aFromNetwork
)
43 : mFromNetwork(aFromNetwork
) {
44 mChild
= static_cast<nsIContent
**>(aChild
);
45 mParent
= static_cast<nsIContent
**>(aParent
);
49 struct opAppendChildrenToNewParent
{
50 nsIContent
** mOldParent
;
51 nsIContent
** mNewParent
;
53 explicit opAppendChildrenToNewParent(nsIContentHandle
* aOldParent
,
54 nsIContentHandle
* aNewParent
) {
55 mOldParent
= static_cast<nsIContent
**>(aOldParent
);
56 mNewParent
= static_cast<nsIContent
**>(aNewParent
);
60 struct opFosterParent
{
62 nsIContent
** mStackParent
;
65 explicit opFosterParent(nsIContentHandle
* aChild
,
66 nsIContentHandle
* aStackParent
,
67 nsIContentHandle
* aTable
) {
68 mChild
= static_cast<nsIContent
**>(aChild
);
69 mStackParent
= static_cast<nsIContent
**>(aStackParent
);
70 mTable
= static_cast<nsIContent
**>(aTable
);
74 struct opAppendToDocument
{
75 nsIContent
** mContent
;
77 explicit opAppendToDocument(nsIContentHandle
* aContent
) {
78 mContent
= static_cast<nsIContent
**>(aContent
);
82 struct opAddAttributes
{
83 nsIContent
** mElement
;
84 nsHtml5HtmlAttributes
* mAttributes
;
86 explicit opAddAttributes(nsIContentHandle
* aElement
,
87 nsHtml5HtmlAttributes
* aAttributes
)
88 : mAttributes(aAttributes
) {
89 mElement
= static_cast<nsIContent
**>(aElement
);
93 struct opCreateHTMLElement
{
94 nsIContent
** mContent
;
96 nsHtml5HtmlAttributes
* mAttributes
;
97 mozilla::dom::HTMLContentCreatorFunction mCreator
;
98 nsIContent
** mIntendedParent
;
99 mozilla::dom::FromParser mFromNetwork
;
101 explicit opCreateHTMLElement(
102 nsIContentHandle
* aContent
, nsAtom
* aName
,
103 nsHtml5HtmlAttributes
* aAttributes
,
104 mozilla::dom::HTMLContentCreatorFunction aCreator
,
105 nsIContentHandle
* aIntendedParent
, mozilla::dom::FromParser mFromNetwork
)
107 mAttributes(aAttributes
),
109 mFromNetwork(mFromNetwork
) {
110 mContent
= static_cast<nsIContent
**>(aContent
);
111 mIntendedParent
= static_cast<nsIContent
**>(aIntendedParent
);
113 if (mAttributes
== nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
) {
114 mAttributes
= nullptr;
119 struct opCreateSVGElement
{
120 nsIContent
** mContent
;
122 nsHtml5HtmlAttributes
* mAttributes
;
123 mozilla::dom::SVGContentCreatorFunction mCreator
;
124 nsIContent
** mIntendedParent
;
125 mozilla::dom::FromParser mFromNetwork
;
127 explicit opCreateSVGElement(nsIContentHandle
* aContent
, nsAtom
* aName
,
128 nsHtml5HtmlAttributes
* aAttributes
,
129 mozilla::dom::SVGContentCreatorFunction aCreator
,
130 nsIContentHandle
* aIntendedParent
,
131 mozilla::dom::FromParser mFromNetwork
)
133 mAttributes(aAttributes
),
135 mFromNetwork(mFromNetwork
) {
136 mContent
= static_cast<nsIContent
**>(aContent
);
137 mIntendedParent
= static_cast<nsIContent
**>(aIntendedParent
);
139 if (mAttributes
== nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
) {
140 mAttributes
= nullptr;
145 struct opCreateMathMLElement
{
146 nsIContent
** mContent
;
148 nsHtml5HtmlAttributes
* mAttributes
;
149 nsIContent
** mIntendedParent
;
151 explicit opCreateMathMLElement(nsIContentHandle
* aContent
, nsAtom
* aName
,
152 nsHtml5HtmlAttributes
* aAttributes
,
153 nsIContentHandle
* aIntendedParent
)
154 : mName(aName
), mAttributes(aAttributes
) {
155 mContent
= static_cast<nsIContent
**>(aContent
);
156 mIntendedParent
= static_cast<nsIContent
**>(aIntendedParent
);
158 if (mAttributes
== nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
) {
159 mAttributes
= nullptr;
164 struct opSetFormElement
{
165 nsIContent
** mContent
;
166 nsIContent
** mFormElement
;
168 explicit opSetFormElement(nsIContentHandle
* aContent
,
169 nsIContentHandle
* aFormElement
) {
170 mContent
= static_cast<nsIContent
**>(aContent
);
171 mFormElement
= static_cast<nsIContent
**>(aFormElement
);
175 struct opAppendText
{
176 nsIContent
** mParent
;
180 explicit opAppendText(nsIContentHandle
* aParent
, char16_t
* aBuffer
,
182 : mBuffer(aBuffer
), mLength(aLength
) {
183 mParent
= static_cast<nsIContent
**>(aParent
);
187 struct opFosterParentText
{
188 nsIContent
** mStackParent
;
193 explicit opFosterParentText(nsIContentHandle
* aStackParent
, char16_t
* aBuffer
,
194 nsIContentHandle
* aTable
, int32_t aLength
)
195 : mBuffer(aBuffer
), mLength(aLength
) {
196 mStackParent
= static_cast<nsIContent
**>(aStackParent
);
197 mTable
= static_cast<nsIContent
**>(aTable
);
201 struct opAppendComment
{
202 nsIContent
** mParent
;
206 explicit opAppendComment(nsIContentHandle
* aParent
, char16_t
* aBuffer
,
208 : mBuffer(aBuffer
), mLength(aLength
) {
209 mParent
= static_cast<nsIContent
**>(aParent
);
213 struct opAppendCommentToDocument
{
217 explicit opAppendCommentToDocument(char16_t
* aBuffer
, int32_t aLength
)
218 : mBuffer(aBuffer
), mLength(aLength
){};
221 class nsHtml5TreeOperationStringPair
{
227 nsHtml5TreeOperationStringPair(const nsAString
& aPublicId
,
228 const nsAString
& aSystemId
)
229 : mPublicId(aPublicId
), mSystemId(aSystemId
) {
230 MOZ_COUNT_CTOR(nsHtml5TreeOperationStringPair
);
233 ~nsHtml5TreeOperationStringPair() {
234 MOZ_COUNT_DTOR(nsHtml5TreeOperationStringPair
);
237 inline void Get(nsAString
& aPublicId
, nsAString
& aSystemId
) {
238 aPublicId
.Assign(mPublicId
);
239 aSystemId
.Assign(mSystemId
);
243 struct opAppendDoctypeToDocument
{
245 nsHtml5TreeOperationStringPair
* mStringPair
;
247 explicit opAppendDoctypeToDocument(nsAtom
* aName
, const nsAString
& aPublicId
,
248 const nsAString
& aSystemId
) {
251 mStringPair
= new nsHtml5TreeOperationStringPair(aPublicId
, aSystemId
);
255 struct opGetDocumentFragmentForTemplate
{
256 nsIContent
** mTemplate
;
257 nsIContent
** mFragHandle
;
259 explicit opGetDocumentFragmentForTemplate(nsIContentHandle
* aTemplate
,
260 nsIContentHandle
* aFragHandle
) {
261 mTemplate
= static_cast<nsIContent
**>(aTemplate
);
262 mFragHandle
= static_cast<nsIContent
**>(aFragHandle
);
266 struct opGetFosterParent
{
268 nsIContent
** mStackParent
;
269 nsIContent
** mParentHandle
;
271 explicit opGetFosterParent(nsIContentHandle
* aTable
,
272 nsIContentHandle
* aStackParent
,
273 nsIContentHandle
* aParentHandle
) {
274 mTable
= static_cast<nsIContent
**>(aTable
);
275 mStackParent
= static_cast<nsIContent
**>(aStackParent
);
276 mParentHandle
= static_cast<nsIContent
**>(aParentHandle
);
280 // Gecko-specific on-pop ops
281 struct opMarkAsBroken
{
284 explicit opMarkAsBroken(nsresult aResult
) : mResult(aResult
){};
288 nsIContent
** mElement
;
289 nsAHtml5TreeBuilderState
* mBuilderState
;
292 explicit opRunScript(nsIContentHandle
* aElement
,
293 nsAHtml5TreeBuilderState
* aBuilderState
)
294 : mBuilderState(aBuilderState
), mLineNumber(0) {
295 mElement
= static_cast<nsIContent
**>(aElement
);
299 struct opRunScriptAsyncDefer
{
300 nsIContent
** mElement
;
302 explicit opRunScriptAsyncDefer(nsIContentHandle
* aElement
) {
303 mElement
= static_cast<nsIContent
**>(aElement
);
307 struct opPreventScriptExecution
{
308 nsIContent
** mElement
;
310 explicit opPreventScriptExecution(nsIContentHandle
* aElement
) {
311 mElement
= static_cast<nsIContent
**>(aElement
);
315 struct opDoneAddingChildren
{
316 nsIContent
** mElement
;
318 explicit opDoneAddingChildren(nsIContentHandle
* aElement
) {
319 mElement
= static_cast<nsIContent
**>(aElement
);
323 struct opDoneCreatingElement
{
324 nsIContent
** mElement
;
326 explicit opDoneCreatingElement(nsIContentHandle
* aElement
) {
327 mElement
= static_cast<nsIContent
**>(aElement
);
331 struct opSetDocumentCharset
{
332 const mozilla::Encoding
* mEncoding
;
333 int32_t mCharsetSource
;
335 explicit opSetDocumentCharset(const mozilla::Encoding
* aEncoding
,
336 int32_t aCharsetSource
)
337 : mEncoding(aEncoding
), mCharsetSource(aCharsetSource
){};
340 struct opCharsetSwitchTo
{
341 const mozilla::Encoding
* mEncoding
;
342 int32_t mCharsetSource
;
345 explicit opCharsetSwitchTo(const mozilla::Encoding
* aEncoding
,
346 int32_t aCharsetSource
, int32_t aLineNumber
)
347 : mEncoding(aEncoding
),
348 mCharsetSource(aCharsetSource
),
349 mLineNumber(aLineNumber
){};
352 struct opUpdateStyleSheet
{
353 nsIContent
** mElement
;
355 explicit opUpdateStyleSheet(nsIContentHandle
* aElement
) {
356 mElement
= static_cast<nsIContent
**>(aElement
);
360 struct opProcessOfflineManifest
{
363 explicit opProcessOfflineManifest(char16_t
* aUrl
) : mUrl(aUrl
){};
366 struct opMarkMalformedIfScript
{
367 nsIContent
** mElement
;
369 explicit opMarkMalformedIfScript(nsIContentHandle
* aElement
) {
370 mElement
= static_cast<nsIContent
**>(aElement
);
374 struct opStreamEnded
{};
376 struct opSetStyleLineNumber
{
377 nsIContent
** mContent
;
380 explicit opSetStyleLineNumber(nsIContentHandle
* aContent
, int32_t aLineNumber
)
381 : mLineNumber(aLineNumber
) {
382 mContent
= static_cast<nsIContent
**>(aContent
);
386 struct opSetScriptLineNumberAndFreeze
{
387 nsIContent
** mContent
;
390 explicit opSetScriptLineNumberAndFreeze(nsIContentHandle
* aContent
,
392 : mLineNumber(aLineNumber
) {
393 mContent
= static_cast<nsIContent
**>(aContent
);
398 nsIContent
** mElement
;
400 explicit opSvgLoad(nsIContentHandle
* aElement
) {
401 mElement
= static_cast<nsIContent
**>(aElement
);
405 struct opMaybeComplainAboutCharset
{
410 explicit opMaybeComplainAboutCharset(char* aMsgId
, bool aError
,
412 : mMsgId(aMsgId
), mError(aError
), mLineNumber(aLineNumber
){};
415 struct opMaybeComplainAboutDeepTree
{
418 explicit opMaybeComplainAboutDeepTree(int32_t aLineNumber
)
419 : mLineNumber(aLineNumber
){};
423 nsIContent
** mElement
;
426 explicit opAddClass(nsIContentHandle
* aElement
, char16_t
* aClass
)
428 mElement
= static_cast<nsIContent
**>(aElement
);
432 struct opAddViewSourceHref
{
433 nsIContent
** mElement
;
437 explicit opAddViewSourceHref(nsIContentHandle
* aElement
, char16_t
* aBuffer
,
439 : mBuffer(aBuffer
), mLength(aLength
) {
440 mElement
= static_cast<nsIContent
**>(aElement
);
444 struct opAddViewSourceBase
{
448 explicit opAddViewSourceBase(char16_t
* aBuffer
, int32_t aLength
)
449 : mBuffer(aBuffer
), mLength(aLength
){};
452 struct opAddErrorType
{
453 nsIContent
** mElement
;
458 explicit opAddErrorType(nsIContentHandle
* aElement
, char* aMsgId
,
459 nsAtom
* aName
= nullptr, nsAtom
* aOther
= nullptr)
460 : mMsgId(aMsgId
), mName(aName
), mOther(aOther
) {
461 mElement
= static_cast<nsIContent
**>(aElement
);
471 struct opAddLineNumberId
{
472 nsIContent
** mElement
;
475 explicit opAddLineNumberId(nsIContentHandle
* aElement
, int32_t aLineNumber
)
476 : mLineNumber(aLineNumber
) {
477 mElement
= static_cast<nsIContent
**>(aElement
);
481 struct opStartLayout
{};
483 struct opEnableEncodingMenu
{};
485 typedef mozilla::Variant
<
488 opAppend
, opDetach
, opAppendChildrenToNewParent
, opFosterParent
,
489 opAppendToDocument
, opAddAttributes
, nsHtml5DocumentMode
,
490 opCreateHTMLElement
, opCreateSVGElement
, opCreateMathMLElement
,
491 opSetFormElement
, opAppendText
, opFosterParentText
, opAppendComment
,
492 opAppendCommentToDocument
, opAppendDoctypeToDocument
,
493 opGetDocumentFragmentForTemplate
, opGetFosterParent
,
494 // Gecko-specific on-pop ops
495 opMarkAsBroken
, opRunScript
, opRunScriptAsyncDefer
,
496 opPreventScriptExecution
, opDoneAddingChildren
, opDoneCreatingElement
,
497 opSetDocumentCharset
, opCharsetSwitchTo
, opUpdateStyleSheet
,
498 opProcessOfflineManifest
, opMarkMalformedIfScript
, opStreamEnded
,
499 opSetStyleLineNumber
, opSetScriptLineNumberAndFreeze
, opSvgLoad
,
500 opMaybeComplainAboutCharset
, opMaybeComplainAboutDeepTree
, opAddClass
,
501 opAddViewSourceHref
, opAddViewSourceBase
, opAddErrorType
, opAddLineNumberId
,
502 opStartLayout
, opEnableEncodingMenu
>
505 class nsHtml5TreeOperation final
{
506 template <typename T
>
507 using NotNull
= mozilla::NotNull
<T
>;
508 using Encoding
= mozilla::Encoding
;
511 static nsresult
AppendTextToTextNode(const char16_t
* aBuffer
,
513 mozilla::dom::Text
* aTextNode
,
514 nsHtml5DocumentBuilder
* aBuilder
);
516 static nsresult
AppendText(const char16_t
* aBuffer
, uint32_t aLength
,
518 nsHtml5DocumentBuilder
* aBuilder
);
520 static nsresult
Append(nsIContent
* aNode
, nsIContent
* aParent
,
521 nsHtml5DocumentBuilder
* aBuilder
);
523 static nsresult
Append(nsIContent
* aNode
, nsIContent
* aParent
,
524 mozilla::dom::FromParser aFromParser
,
525 nsHtml5DocumentBuilder
* aBuilder
);
527 static nsresult
AppendToDocument(nsIContent
* aNode
,
528 nsHtml5DocumentBuilder
* aBuilder
);
530 static void Detach(nsIContent
* aNode
, nsHtml5DocumentBuilder
* aBuilder
);
532 static nsresult
AppendChildrenToNewParent(nsIContent
* aNode
,
534 nsHtml5DocumentBuilder
* aBuilder
);
536 static nsresult
FosterParent(nsIContent
* aNode
, nsIContent
* aParent
,
538 nsHtml5DocumentBuilder
* aBuilder
);
540 static nsresult
AddAttributes(nsIContent
* aNode
,
541 nsHtml5HtmlAttributes
* aAttributes
,
542 nsHtml5DocumentBuilder
* aBuilder
);
544 static void SetHTMLElementAttributes(mozilla::dom::Element
* aElement
,
546 nsHtml5HtmlAttributes
* aAttributes
);
548 static nsIContent
* CreateHTMLElement(
549 nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
,
550 mozilla::dom::FromParser aFromParser
, nsNodeInfoManager
* aNodeInfoManager
,
551 nsHtml5DocumentBuilder
* aBuilder
,
552 mozilla::dom::HTMLContentCreatorFunction aCreator
);
554 static nsIContent
* CreateSVGElement(
555 nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
,
556 mozilla::dom::FromParser aFromParser
, nsNodeInfoManager
* aNodeInfoManager
,
557 nsHtml5DocumentBuilder
* aBuilder
,
558 mozilla::dom::SVGContentCreatorFunction aCreator
);
560 static nsIContent
* CreateMathMLElement(nsAtom
* aName
,
561 nsHtml5HtmlAttributes
* aAttributes
,
562 nsNodeInfoManager
* aNodeInfoManager
,
563 nsHtml5DocumentBuilder
* aBuilder
);
565 static void SetFormElement(nsIContent
* aNode
, nsIContent
* aParent
);
567 static nsresult
AppendIsindexPrompt(nsIContent
* parent
,
568 nsHtml5DocumentBuilder
* aBuilder
);
570 static nsresult
FosterParentText(nsIContent
* aStackParent
, char16_t
* aBuffer
,
571 uint32_t aLength
, nsIContent
* aTable
,
572 nsHtml5DocumentBuilder
* aBuilder
);
574 static nsresult
AppendComment(nsIContent
* aParent
, char16_t
* aBuffer
,
576 nsHtml5DocumentBuilder
* aBuilder
);
578 static nsresult
AppendCommentToDocument(char16_t
* aBuffer
, int32_t aLength
,
579 nsHtml5DocumentBuilder
* aBuilder
);
581 static nsresult
AppendDoctypeToDocument(nsAtom
* aName
,
582 const nsAString
& aPublicId
,
583 const nsAString
& aSystemId
,
584 nsHtml5DocumentBuilder
* aBuilder
);
586 static nsIContent
* GetDocumentFragmentForTemplate(nsIContent
* aNode
);
588 static nsIContent
* GetFosterParent(nsIContent
* aTable
,
589 nsIContent
* aStackParent
);
591 static void PreventScriptExecution(nsIContent
* aNode
);
593 static void DoneAddingChildren(nsIContent
* aNode
);
595 static void DoneCreatingElement(nsIContent
* aNode
);
597 static void SvgLoad(nsIContent
* aNode
);
599 static void MarkMalformedIfScript(nsIContent
* aNode
);
601 nsHtml5TreeOperation();
603 ~nsHtml5TreeOperation();
605 inline void Init(const treeOperation
& aOperation
) {
606 NS_ASSERTION(mOperation
.is
<uninitialized
>(),
607 "Op code must be uninitialized when initializing.");
608 mOperation
= aOperation
;
611 inline bool IsRunScript() { return mOperation
.is
<opRunScript
>(); }
613 inline bool IsMarkAsBroken() { return mOperation
.is
<opMarkAsBroken
>(); }
615 inline void SetSnapshot(nsAHtml5TreeBuilderState
* aSnapshot
, int32_t aLine
) {
618 "Setting a snapshot for a tree operation other than eTreeOpRunScript!");
619 MOZ_ASSERT(aSnapshot
, "Initialized tree op with null snapshot.");
620 opRunScript data
= mOperation
.as
<opRunScript
>();
621 data
.mBuilderState
= aSnapshot
;
622 data
.mLineNumber
= aLine
;
623 mOperation
= mozilla::AsVariant(data
);
626 nsresult
Perform(nsHtml5TreeOpExecutor
* aBuilder
, nsIContent
** aScriptElement
,
627 bool* aInterrupted
, bool* aStreamEnded
);
630 nsHtml5TreeOperation(const nsHtml5TreeOperation
&) = delete;
631 nsHtml5TreeOperation
& operator=(const nsHtml5TreeOperation
&) = delete;
633 treeOperation mOperation
;
636 #endif // nsHtml5TreeOperation_h