2 * Copyright (c) 2007 Henri Sivonen
3 * Copyright (c) 2007-2015 Mozilla Foundation
4 * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla
5 * Foundation, and Opera Software ASA.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
27 * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
28 * Please edit TreeBuilder.java instead and regenerate.
31 #define nsHtml5TreeBuilder_cpp__
33 #include "nsContentUtils.h"
35 #include "nsHtml5AtomTable.h"
36 #include "nsHtml5String.h"
37 #include "nsNameSpaceManager.h"
38 #include "nsIContent.h"
39 #include "nsTraceRefcnt.h"
41 #include "nsHtml5DocumentMode.h"
42 #include "nsHtml5ArrayCopy.h"
43 #include "nsHtml5Parser.h"
44 #include "nsGkAtoms.h"
45 #include "nsHtml5TreeOperation.h"
46 #include "nsHtml5StateSnapshot.h"
47 #include "nsHtml5StackNode.h"
48 #include "nsHtml5TreeOpExecutor.h"
49 #include "nsHtml5StreamParser.h"
50 #include "nsAHtml5TreeBuilderState.h"
51 #include "nsHtml5Highlighter.h"
52 #include "nsHtml5PlainTextUtils.h"
53 #include "nsHtml5ViewSourceUtils.h"
54 #include "mozilla/ImportScanner.h"
55 #include "mozilla/Likely.h"
56 #include "nsIContentHandle.h"
57 #include "nsHtml5OplessBuilder.h"
59 #include "nsHtml5AttributeName.h"
60 #include "nsHtml5ElementName.h"
61 #include "nsHtml5Tokenizer.h"
62 #include "nsHtml5MetaScanner.h"
63 #include "nsHtml5StackNode.h"
64 #include "nsHtml5UTF16Buffer.h"
65 #include "nsHtml5StateSnapshot.h"
66 #include "nsHtml5Portability.h"
68 #include "nsHtml5TreeBuilder.h"
70 char16_t
nsHtml5TreeBuilder::REPLACEMENT_CHARACTER
[] = {0xfffd};
71 static const char* const QUIRKY_PUBLIC_IDS_DATA
[] = {
72 "+//silmaril//dtd html pro v0r11 19970101//",
73 "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
74 "-//as//dtd html 3.0 aswedit + extensions//",
75 "-//ietf//dtd html 2.0 level 1//",
76 "-//ietf//dtd html 2.0 level 2//",
77 "-//ietf//dtd html 2.0 strict level 1//",
78 "-//ietf//dtd html 2.0 strict level 2//",
79 "-//ietf//dtd html 2.0 strict//",
80 "-//ietf//dtd html 2.0//",
81 "-//ietf//dtd html 2.1e//",
82 "-//ietf//dtd html 3.0//",
83 "-//ietf//dtd html 3.2 final//",
84 "-//ietf//dtd html 3.2//",
85 "-//ietf//dtd html 3//",
86 "-//ietf//dtd html level 0//",
87 "-//ietf//dtd html level 1//",
88 "-//ietf//dtd html level 2//",
89 "-//ietf//dtd html level 3//",
90 "-//ietf//dtd html strict level 0//",
91 "-//ietf//dtd html strict level 1//",
92 "-//ietf//dtd html strict level 2//",
93 "-//ietf//dtd html strict level 3//",
94 "-//ietf//dtd html strict//",
95 "-//ietf//dtd html//",
96 "-//metrius//dtd metrius presentational//",
97 "-//microsoft//dtd internet explorer 2.0 html strict//",
98 "-//microsoft//dtd internet explorer 2.0 html//",
99 "-//microsoft//dtd internet explorer 2.0 tables//",
100 "-//microsoft//dtd internet explorer 3.0 html strict//",
101 "-//microsoft//dtd internet explorer 3.0 html//",
102 "-//microsoft//dtd internet explorer 3.0 tables//",
103 "-//netscape comm. corp.//dtd html//",
104 "-//netscape comm. corp.//dtd strict html//",
105 "-//o'reilly and associates//dtd html 2.0//",
106 "-//o'reilly and associates//dtd html extended 1.0//",
107 "-//o'reilly and associates//dtd html extended relaxed 1.0//",
108 "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html "
110 "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
111 "-//spyglass//dtd html 2.0 extended//",
112 "-//sq//dtd html 2.0 hotmetal + extensions//",
113 "-//sun microsystems corp.//dtd hotjava html//",
114 "-//sun microsystems corp.//dtd hotjava strict html//",
115 "-//w3c//dtd html 3 1995-03-24//",
116 "-//w3c//dtd html 3.2 draft//",
117 "-//w3c//dtd html 3.2 final//",
118 "-//w3c//dtd html 3.2//",
119 "-//w3c//dtd html 3.2s draft//",
120 "-//w3c//dtd html 4.0 frameset//",
121 "-//w3c//dtd html 4.0 transitional//",
122 "-//w3c//dtd html experimental 19960712//",
123 "-//w3c//dtd html experimental 970421//",
124 "-//w3c//dtd w3 html//",
125 "-//w3o//dtd w3 html 3.0//",
126 "-//webtechs//dtd mozilla html 2.0//",
127 "-//webtechs//dtd mozilla html//"};
128 staticJArray
<const char*, int32_t> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS
= {
129 QUIRKY_PUBLIC_IDS_DATA
, MOZ_ARRAY_LENGTH(QUIRKY_PUBLIC_IDS_DATA
)};
130 void nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer
* self
) {
132 stackNodes
= jArray
<nsHtml5StackNode
*, int32_t>::newJArray(64);
133 stack
= jArray
<nsHtml5StackNode
*, int32_t>::newJArray(64);
134 templateModeStack
= jArray
<int32_t, int32_t>::newJArray(64);
135 listOfActiveFormattingElements
=
136 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(64);
137 needToDropLF
= false;
138 originalMode
= INITIAL
;
139 templateModePtr
= -1;
144 formPointer
= nullptr;
145 headPointer
= nullptr;
148 charBuffer
= nullptr;
151 nsIContentHandle
* elt
;
155 elt
= createHtmlElementSetAsRoot(tokenizer
->emptyAttributes());
157 if (contextNamespace
== kNameSpaceID_SVG
) {
158 nsHtml5ElementName
* elementName
= nsHtml5ElementName::ELT_SVG
;
159 if (nsGkAtoms::title
== contextName
|| nsGkAtoms::desc
== contextName
||
160 nsGkAtoms::foreignObject
== contextName
) {
161 elementName
= nsHtml5ElementName::ELT_FOREIGNOBJECT
;
163 nsHtml5StackNode
* node
=
164 createStackNode(elementName
, elementName
->getCamelCaseName(), elt
);
166 stack
[currentPtr
] = node
;
167 tokenizer
->setState(nsHtml5Tokenizer::DATA
);
169 } else if (contextNamespace
== kNameSpaceID_MathML
) {
170 nsHtml5ElementName
* elementName
= nsHtml5ElementName::ELT_MATH
;
171 if (nsGkAtoms::mi_
== contextName
|| nsGkAtoms::mo_
== contextName
||
172 nsGkAtoms::mn_
== contextName
|| nsGkAtoms::ms_
== contextName
||
173 nsGkAtoms::mtext_
== contextName
) {
174 elementName
= nsHtml5ElementName::ELT_MTEXT
;
175 } else if (nsGkAtoms::annotation_xml_
== contextName
) {
176 elementName
= nsHtml5ElementName::ELT_ANNOTATION_XML
;
178 nsHtml5StackNode
* node
=
179 createStackNode(elementName
, elt
, elementName
->getName(), false);
181 stack
[currentPtr
] = node
;
182 tokenizer
->setState(nsHtml5Tokenizer::DATA
);
185 nsHtml5StackNode
* node
=
186 createStackNode(nsHtml5ElementName::ELT_HTML
, elt
);
188 stack
[currentPtr
] = node
;
189 if (nsGkAtoms::_template
== contextName
) {
190 pushTemplateMode(IN_TEMPLATE
);
192 resetTheInsertionMode();
193 formPointer
= getFormPointerForContext(contextNode
);
194 if (nsGkAtoms::title
== contextName
||
195 nsGkAtoms::textarea
== contextName
) {
196 tokenizer
->setState(nsHtml5Tokenizer::RCDATA
);
197 } else if (nsGkAtoms::style
== contextName
||
198 nsGkAtoms::xmp
== contextName
||
199 nsGkAtoms::iframe
== contextName
||
200 nsGkAtoms::noembed
== contextName
||
201 nsGkAtoms::noframes
== contextName
||
202 (scriptingEnabled
&& nsGkAtoms::noscript
== contextName
)) {
203 tokenizer
->setState(nsHtml5Tokenizer::RAWTEXT
);
204 } else if (nsGkAtoms::plaintext
== contextName
) {
205 tokenizer
->setState(nsHtml5Tokenizer::PLAINTEXT
);
206 } else if (nsGkAtoms::script
== contextName
) {
207 tokenizer
->setState(nsHtml5Tokenizer::SCRIPT_DATA
);
209 tokenizer
->setState(nsHtml5Tokenizer::DATA
);
214 if (tokenizer
->isViewingXmlSource()) {
215 nsIContentHandle
* elt
= createElement(
216 kNameSpaceID_SVG
, nsGkAtoms::svg
, tokenizer
->emptyAttributes(),
217 nullptr, svgCreator(NS_NewSVGSVGElement
));
218 nsHtml5StackNode
* node
=
219 createStackNode(nsHtml5ElementName::ELT_SVG
, nsGkAtoms::svg
, elt
);
221 stack
[currentPtr
] = node
;
226 void nsHtml5TreeBuilder::doctype(nsAtom
* name
, nsHtml5String publicIdentifier
,
227 nsHtml5String systemIdentifier
,
229 needToDropLF
= false;
230 if (!isInForeign() && mode
== INITIAL
) {
231 nsHtml5String emptyString
= nsHtml5Portability::newEmptyString();
232 appendDoctypeToDocument(!name
? nsGkAtoms::_empty
: name
,
233 !publicIdentifier
? emptyString
: publicIdentifier
,
234 !systemIdentifier
? emptyString
: systemIdentifier
);
235 emptyString
.Release();
236 if (isQuirky(name
, publicIdentifier
, systemIdentifier
, forceQuirks
)) {
238 documentModeInternal(QUIRKS_MODE
, publicIdentifier
, systemIdentifier
,
240 } else if (isAlmostStandards(publicIdentifier
, systemIdentifier
)) {
241 errAlmostStandardsDoctype();
242 documentModeInternal(ALMOST_STANDARDS_MODE
, publicIdentifier
,
243 systemIdentifier
, false);
245 documentModeInternal(STANDARDS_MODE
, publicIdentifier
, systemIdentifier
,
255 void nsHtml5TreeBuilder::comment(char16_t
* buf
, int32_t start
, int32_t length
) {
256 needToDropLF
= false;
257 if (!isInForeign()) {
261 case AFTER_AFTER_BODY
:
262 case AFTER_AFTER_FRAMESET
: {
263 appendCommentToDocument(buf
, start
, length
);
268 appendComment(stack
[0]->node
, buf
, start
, length
);
277 appendComment(stack
[currentPtr
]->node
, buf
, start
, length
);
281 void nsHtml5TreeBuilder::characters(const char16_t
* buf
, int32_t start
,
283 if (tokenizer
->isViewingXmlSource()) {
287 needToDropLF
= false;
288 if (buf
[start
] == '\n') {
300 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
301 reconstructTheActiveFormattingElements();
306 accumulateCharacters(buf
, start
, length
);
312 accumulateCharactersForced(buf
, start
, length
);
316 int32_t end
= start
+ length
;
317 for (int32_t i
= start
; i
< end
; i
++) {
332 case IN_HEAD_NOSCRIPT
:
334 case IN_COLUMN_GROUP
:
336 case AFTER_FRAMESET
: {
345 accumulateCharacters(buf
, start
, i
- start
);
348 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
350 reconstructTheActiveFormattingElements();
352 NS_HTML5_BREAK(charactersloop
);
355 case IN_SELECT_IN_TABLE
: {
356 NS_HTML5_BREAK(charactersloop
);
361 accumulateCharactersForced(buf
, i
, 1);
366 case AFTER_AFTER_BODY
:
367 case AFTER_AFTER_FRAMESET
: {
369 accumulateCharacters(buf
, start
, i
- start
);
373 reconstructTheActiveFormattingElements();
377 MOZ_FALLTHROUGH_ASSERT();
382 documentModeInternal(QUIRKS_MODE
, nullptr, nullptr, false);
388 appendHtmlElementToDocumentAndPush();
395 accumulateCharacters(buf
, start
, i
- start
);
399 appendToCurrentNodeAndPushHeadElement(
400 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
407 accumulateCharacters(buf
, start
, i
- start
);
416 case IN_HEAD_NOSCRIPT
: {
418 accumulateCharacters(buf
, start
, i
- start
);
421 errNonSpaceInNoscriptInHead();
430 accumulateCharacters(buf
, start
, i
- start
);
434 appendToCurrentNodeAndPushBodyElement();
450 accumulateCharacters(buf
, start
, i
- start
);
453 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
455 reconstructTheActiveFormattingElements();
457 NS_HTML5_BREAK(charactersloop
);
462 accumulateCharactersForced(buf
, i
, 1);
466 case IN_COLUMN_GROUP
: {
468 accumulateCharacters(buf
, start
, i
- start
);
471 if (!currentPtr
|| stack
[currentPtr
]->getGroup() ==
472 nsHtml5TreeBuilder::TEMPLATE
) {
473 errNonSpaceInColgroupInFragment();
484 case IN_SELECT_IN_TABLE
: {
485 NS_HTML5_BREAK(charactersloop
);
488 errNonSpaceAfterBody();
490 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
496 accumulateCharacters(buf
, start
, i
- start
);
498 errNonSpaceInFrameset();
502 case AFTER_FRAMESET
: {
504 accumulateCharacters(buf
, start
, i
- start
);
506 errNonSpaceAfterFrameset();
510 case AFTER_AFTER_BODY
: {
511 errNonSpaceInTrailer();
512 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
516 case AFTER_AFTER_FRAMESET
: {
518 accumulateCharacters(buf
, start
, i
- start
);
520 errNonSpaceInTrailer();
530 accumulateCharacters(buf
, start
, end
- start
);
536 void nsHtml5TreeBuilder::zeroOriginatingReplacementCharacter() {
538 accumulateCharacters(REPLACEMENT_CHARACTER
, 0, 1);
541 if (currentPtr
>= 0) {
542 if (isSpecialParentInForeign(stack
[currentPtr
])) {
545 accumulateCharacters(REPLACEMENT_CHARACTER
, 0, 1);
549 void nsHtml5TreeBuilder::eof() {
554 documentModeInternal(QUIRKS_MODE
, nullptr, nullptr, false);
559 appendHtmlElementToDocumentAndPush();
564 appendToCurrentNodeAndPushHeadElement(
565 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
570 while (currentPtr
> 0) {
576 case IN_HEAD_NOSCRIPT
: {
577 while (currentPtr
> 1) {
584 appendToCurrentNodeAndPushBodyElement();
591 case IN_SELECT_IN_TABLE
:
593 case IN_COLUMN_GROUP
:
598 if (isTemplateModeStackEmpty()) {
599 NS_HTML5_BREAK(eofloop
);
604 int32_t eltPos
= findLast(nsGkAtoms::_template
);
605 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
606 MOZ_ASSERT(fragment
);
607 NS_HTML5_BREAK(eofloop
);
609 if (MOZ_UNLIKELY(mViewSource
)) {
610 errUnclosedElements(eltPos
, nsGkAtoms::_template
);
612 while (currentPtr
>= eltPos
) {
615 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
617 resetTheInsertionMode();
621 if (originalMode
== AFTER_HEAD
) {
629 NS_HTML5_BREAK(eofloop
);
633 case AFTER_AFTER_BODY
:
634 case AFTER_AFTER_FRAMESET
:
636 NS_HTML5_BREAK(eofloop
);
641 while (currentPtr
> 0) {
649 void nsHtml5TreeBuilder::endTokenization() {
650 formPointer
= nullptr;
651 headPointer
= nullptr;
652 contextName
= nullptr;
653 contextNode
= nullptr;
654 templateModeStack
= nullptr;
656 while (currentPtr
> -1) {
657 stack
[currentPtr
]->release(this);
662 if (listOfActiveFormattingElements
) {
663 while (listPtr
> -1) {
664 if (listOfActiveFormattingElements
[listPtr
]) {
665 listOfActiveFormattingElements
[listPtr
]->release(this);
669 listOfActiveFormattingElements
= nullptr;
672 for (int32_t i
= 0; i
< numStackNodes
; i
++) {
673 MOZ_ASSERT(stackNodes
[i
]->isUnused());
674 delete stackNodes
[i
];
678 stackNodes
= nullptr;
680 charBuffer
= nullptr;
684 void nsHtml5TreeBuilder::startTag(nsHtml5ElementName
* elementName
,
685 nsHtml5HtmlAttributes
* attributes
,
689 needToDropLF
= false;
692 int32_t group
= elementName
->getGroup();
693 nsAtom
* name
= elementName
->getName();
695 nsHtml5StackNode
* currentNode
= stack
[currentPtr
];
696 int32_t currNs
= currentNode
->ns
;
697 if (!(currentNode
->isHtmlIntegrationPoint() ||
698 (currNs
== kNameSpaceID_MathML
&&
699 ((currentNode
->getGroup() == MI_MO_MN_MS_MTEXT
&&
700 group
!= MGLYPH_OR_MALIGNMARK
) ||
701 (currentNode
->getGroup() == ANNOTATION_XML
&& group
== SVG
))))) {
703 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U
:
704 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU
:
707 case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR
:
712 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
:
722 if (!(group
== FONT
&&
723 !(attributes
->contains(nsHtml5AttributeName::ATTR_COLOR
) ||
724 attributes
->contains(nsHtml5AttributeName::ATTR_FACE
) ||
725 attributes
->contains(nsHtml5AttributeName::ATTR_SIZE
)))) {
726 errHtmlStartTagInForeignContext(name
);
728 while (!isSpecialParentInForeign(stack
[currentPtr
])) {
731 NS_HTML5_CONTINUE(starttagloop
);
737 if (kNameSpaceID_SVG
== currNs
) {
738 attributes
->adjustForSvg();
740 appendVoidElementToCurrentMayFosterSVG(elementName
, attributes
);
743 appendToCurrentNodeAndPushElementMayFosterSVG(elementName
,
746 attributes
= nullptr;
747 NS_HTML5_BREAK(starttagloop
);
749 attributes
->adjustForMath();
751 appendVoidElementToCurrentMayFosterMathML(elementName
,
755 appendToCurrentNodeAndPushElementMayFosterMathML(elementName
,
758 attributes
= nullptr;
759 NS_HTML5_BREAK(starttagloop
);
770 pushTemplateMode(IN_COLUMN_GROUP
);
771 mode
= IN_COLUMN_GROUP
;
776 case TBODY_OR_THEAD_OR_TFOOT
: {
778 pushTemplateMode(IN_TABLE
);
784 pushTemplateMode(IN_TABLE_BODY
);
785 mode
= IN_TABLE_BODY
;
790 pushTemplateMode(IN_ROW
);
795 checkMetaCharset(attributes
);
796 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
798 attributes
= nullptr;
799 NS_HTML5_BREAK(starttagloop
);
802 startTagTitleInHead(elementName
, attributes
);
803 attributes
= nullptr;
804 NS_HTML5_BREAK(starttagloop
);
807 case LINK_OR_BASEFONT_OR_BGSOUND
: {
808 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
810 attributes
= nullptr;
811 NS_HTML5_BREAK(starttagloop
);
814 startTagScriptInHead(elementName
, attributes
);
815 attributes
= nullptr;
816 NS_HTML5_BREAK(starttagloop
);
820 startTagGenericRawText(elementName
, attributes
);
821 attributes
= nullptr;
822 NS_HTML5_BREAK(starttagloop
);
825 startTagTemplateInHead(elementName
, attributes
);
826 attributes
= nullptr;
827 NS_HTML5_BREAK(starttagloop
);
831 pushTemplateMode(IN_BODY
);
840 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TR
));
841 appendToCurrentNodeAndPushElement(elementName
, attributes
);
844 attributes
= nullptr;
845 NS_HTML5_BREAK(starttagloop
);
850 case TBODY_OR_THEAD_OR_TFOOT
:
852 eltPos
= findLastOrRoot(nsHtml5TreeBuilder::TR
);
854 MOZ_ASSERT(fragment
|| isTemplateContents());
855 errNoTableRowToClose();
856 NS_HTML5_BREAK(starttagloop
);
858 clearStackBackTo(eltPos
);
860 mode
= IN_TABLE_BODY
;
863 default:; // fall through
867 case IN_TABLE_BODY
: {
871 findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
872 appendToCurrentNodeAndPushElement(elementName
, attributes
);
874 attributes
= nullptr;
875 NS_HTML5_BREAK(starttagloop
);
878 errStartTagInTableBody(name
);
880 findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
881 appendToCurrentNodeAndPushElement(
882 nsHtml5ElementName::ELT_TR
,
883 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
890 case TBODY_OR_THEAD_OR_TFOOT
: {
891 eltPos
= findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
892 if (!eltPos
|| stack
[eltPos
]->getGroup() == TEMPLATE
) {
893 MOZ_ASSERT(fragment
|| isTemplateContents());
894 errStrayStartTag(name
);
895 NS_HTML5_BREAK(starttagloop
);
897 clearStackBackTo(eltPos
);
903 default:; // fall through
911 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
913 appendToCurrentNodeAndPushElement(elementName
, attributes
);
915 attributes
= nullptr;
916 NS_HTML5_BREAK(starttagloop
);
919 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
920 appendToCurrentNodeAndPushElement(elementName
, attributes
);
921 mode
= IN_COLUMN_GROUP
;
922 attributes
= nullptr;
923 NS_HTML5_BREAK(starttagloop
);
926 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
927 appendToCurrentNodeAndPushElement(
928 nsHtml5ElementName::ELT_COLGROUP
,
929 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
930 mode
= IN_COLUMN_GROUP
;
931 NS_HTML5_CONTINUE(starttagloop
);
933 case TBODY_OR_THEAD_OR_TFOOT
: {
934 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
935 appendToCurrentNodeAndPushElement(elementName
, attributes
);
936 mode
= IN_TABLE_BODY
;
937 attributes
= nullptr;
938 NS_HTML5_BREAK(starttagloop
);
942 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
943 appendToCurrentNodeAndPushElement(
944 nsHtml5ElementName::ELT_TBODY
,
945 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
946 mode
= IN_TABLE_BODY
;
947 NS_HTML5_CONTINUE(starttagloop
);
950 NS_HTML5_BREAK(intableloop
);
953 errTableSeenWhileTableOpen();
954 eltPos
= findLastInTableScope(name
);
955 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
956 MOZ_ASSERT(fragment
|| isTemplateContents());
957 NS_HTML5_BREAK(starttagloop
);
959 generateImpliedEndTags();
960 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(nsGkAtoms::table
)) {
961 errNoCheckUnclosedElementsOnStack();
963 while (currentPtr
>= eltPos
) {
966 resetTheInsertionMode();
967 NS_HTML5_CONTINUE(starttagloop
);
970 appendToCurrentNodeAndPushElement(elementName
, attributes
);
973 tokenizer
->setStateAndEndTagExpectation(
974 nsHtml5Tokenizer::SCRIPT_DATA
, elementName
);
975 attributes
= nullptr;
976 NS_HTML5_BREAK(starttagloop
);
979 appendToCurrentNodeAndPushElement(elementName
, attributes
);
982 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
984 attributes
= nullptr;
985 NS_HTML5_BREAK(starttagloop
);
988 errStartTagInTable(name
);
989 if (!nsHtml5Portability::
990 lowerCaseLiteralEqualsIgnoreAsciiCaseString(
991 "hidden", attributes
->getValue(
992 nsHtml5AttributeName::ATTR_TYPE
))) {
993 NS_HTML5_BREAK(intableloop
);
995 appendVoidInputToCurrent(attributes
, formPointer
);
997 attributes
= nullptr;
998 NS_HTML5_BREAK(starttagloop
);
1001 if (!!formPointer
|| isTemplateContents()) {
1002 errFormWhenFormOpen();
1003 NS_HTML5_BREAK(starttagloop
);
1005 errStartTagInTable(name
);
1006 appendVoidFormToCurrent(attributes
);
1007 attributes
= nullptr;
1008 NS_HTML5_BREAK(starttagloop
);
1012 errStartTagInTable(name
);
1013 NS_HTML5_BREAK(intableloop
);
1025 case TBODY_OR_THEAD_OR_TFOOT
:
1028 errStrayStartTag(name
);
1029 eltPos
= findLastInTableScope(nsGkAtoms::caption
);
1030 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1031 NS_HTML5_BREAK(starttagloop
);
1033 generateImpliedEndTags();
1034 if (!!MOZ_UNLIKELY(mViewSource
) && currentPtr
!= eltPos
) {
1035 errNoCheckUnclosedElementsOnStack();
1037 while (currentPtr
>= eltPos
) {
1040 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
1044 default:; // fall through
1053 case TBODY_OR_THEAD_OR_TFOOT
:
1056 eltPos
= findLastInTableScopeTdTh();
1057 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1059 NS_HTML5_BREAK(starttagloop
);
1061 closeTheCell(eltPos
);
1065 default:; // fall through
1072 if (mode
== FRAMESET_OK
) {
1073 if (!currentPtr
|| stack
[1]->getGroup() != BODY
) {
1074 MOZ_ASSERT(fragment
|| isTemplateContents());
1075 errStrayStartTag(name
);
1076 NS_HTML5_BREAK(starttagloop
);
1079 detachFromParent(stack
[1]->node
);
1080 while (currentPtr
> 0) {
1083 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1085 attributes
= nullptr;
1086 NS_HTML5_BREAK(starttagloop
);
1089 errStrayStartTag(name
);
1090 NS_HTML5_BREAK(starttagloop
);
1093 case PRE_OR_LISTING
:
1097 case MARQUEE_OR_APPLET
:
1111 if (mode
== FRAMESET_OK
&&
1113 nsHtml5Portability::
1114 lowerCaseLiteralEqualsIgnoreAsciiCaseString(
1115 "hidden", attributes
->getValue(
1116 nsHtml5AttributeName::ATTR_TYPE
)))) {
1122 default:; // fall through
1130 errStrayStartTag(name
);
1131 if (!fragment
&& !isTemplateContents()) {
1132 addAttributesToHtml(attributes
);
1133 attributes
= nullptr;
1135 NS_HTML5_BREAK(starttagloop
);
1138 case LINK_OR_BASEFONT_OR_BGSOUND
:
1144 NS_HTML5_BREAK(inbodyloop
);
1147 if (!currentPtr
|| stack
[1]->getGroup() != BODY
||
1148 isTemplateContents()) {
1149 MOZ_ASSERT(fragment
|| isTemplateContents());
1150 errStrayStartTag(name
);
1151 NS_HTML5_BREAK(starttagloop
);
1153 errFooSeenWhenFooOpen(name
);
1155 if (mode
== FRAMESET_OK
) {
1158 if (addAttributesToBody(attributes
)) {
1159 attributes
= nullptr;
1161 NS_HTML5_BREAK(starttagloop
);
1164 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU
:
1165 case UL_OR_OL_OR_DL
:
1166 case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY
: {
1168 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1170 attributes
= nullptr;
1171 NS_HTML5_BREAK(starttagloop
);
1173 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
: {
1175 if (stack
[currentPtr
]->getGroup() ==
1176 H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
) {
1177 errHeadingWhenHeadingOpen();
1180 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1182 attributes
= nullptr;
1183 NS_HTML5_BREAK(starttagloop
);
1187 appendToCurrentNodeAndPushElementMayFoster(
1188 elementName
, attributes
, formPointer
);
1189 attributes
= nullptr;
1190 NS_HTML5_BREAK(starttagloop
);
1192 case PRE_OR_LISTING
: {
1194 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1196 needToDropLF
= true;
1197 attributes
= nullptr;
1198 NS_HTML5_BREAK(starttagloop
);
1201 if (!!formPointer
&& !isTemplateContents()) {
1202 errFormWhenFormOpen();
1203 NS_HTML5_BREAK(starttagloop
);
1206 appendToCurrentNodeAndPushFormElementMayFoster(attributes
);
1207 attributes
= nullptr;
1208 NS_HTML5_BREAK(starttagloop
);
1213 eltPos
= currentPtr
;
1215 nsHtml5StackNode
* node
= stack
[eltPos
];
1216 if (node
->getGroup() == group
) {
1217 generateImpliedEndTagsExceptFor(node
->name
);
1218 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
1219 errUnclosedElementsImplied(eltPos
, name
);
1221 while (currentPtr
>= eltPos
) {
1225 } else if (!eltPos
|| (node
->isSpecial() &&
1226 (node
->ns
!= kNameSpaceID_XHTML
||
1227 (node
->name
!= nsGkAtoms::p
&&
1228 node
->name
!= nsGkAtoms::address
&&
1229 node
->name
!= nsGkAtoms::div
)))) {
1235 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1237 attributes
= nullptr;
1238 NS_HTML5_BREAK(starttagloop
);
1242 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1244 tokenizer
->setStateAndEndTagExpectation(
1245 nsHtml5Tokenizer::PLAINTEXT
, elementName
);
1246 attributes
= nullptr;
1247 NS_HTML5_BREAK(starttagloop
);
1250 int32_t activeAPos
=
1251 findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
1253 if (activeAPos
!= -1) {
1254 errFooSeenWhenFooOpen(name
);
1255 nsHtml5StackNode
* activeA
=
1256 listOfActiveFormattingElements
[activeAPos
];
1258 adoptionAgencyEndTag(nsGkAtoms::a
);
1259 removeFromStack(activeA
);
1260 activeAPos
= findInListOfActiveFormattingElements(activeA
);
1261 if (activeAPos
!= -1) {
1262 removeFromListOfActiveFormattingElements(activeAPos
);
1264 activeA
->release(this);
1266 reconstructTheActiveFormattingElements();
1267 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName
,
1269 attributes
= nullptr;
1270 NS_HTML5_BREAK(starttagloop
);
1272 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U
:
1274 reconstructTheActiveFormattingElements();
1275 maybeForgetEarlierDuplicateFormattingElement(
1276 elementName
->getName(), attributes
);
1277 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName
,
1279 attributes
= nullptr;
1280 NS_HTML5_BREAK(starttagloop
);
1283 reconstructTheActiveFormattingElements();
1284 if (nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
!=
1285 findLastInScope(nsGkAtoms::nobr
)) {
1286 errFooSeenWhenFooOpen(name
);
1287 adoptionAgencyEndTag(nsGkAtoms::nobr
);
1288 reconstructTheActiveFormattingElements();
1290 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName
,
1292 attributes
= nullptr;
1293 NS_HTML5_BREAK(starttagloop
);
1296 eltPos
= findLastInScope(name
);
1297 if (eltPos
!= nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1298 errFooSeenWhenFooOpen(name
);
1299 generateImpliedEndTags();
1300 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
1301 errUnclosedElementsImplied(eltPos
, name
);
1303 while (currentPtr
>= eltPos
) {
1306 NS_HTML5_CONTINUE(starttagloop
);
1308 reconstructTheActiveFormattingElements();
1309 appendToCurrentNodeAndPushElementMayFoster(
1310 elementName
, attributes
, formPointer
);
1311 attributes
= nullptr;
1312 NS_HTML5_BREAK(starttagloop
);
1316 reconstructTheActiveFormattingElements();
1317 appendToCurrentNodeAndPushElementMayFoster(
1318 elementName
, attributes
, formPointer
);
1320 attributes
= nullptr;
1321 NS_HTML5_BREAK(starttagloop
);
1323 case MARQUEE_OR_APPLET
: {
1324 reconstructTheActiveFormattingElements();
1325 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1328 attributes
= nullptr;
1329 NS_HTML5_BREAK(starttagloop
);
1335 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1338 attributes
= nullptr;
1339 NS_HTML5_BREAK(starttagloop
);
1345 reconstructTheActiveFormattingElements();
1348 #ifdef ENABLE_VOID_MENUITEM
1351 case PARAM_OR_SOURCE_OR_TRACK
: {
1352 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1353 selfClosing
= false;
1354 attributes
= nullptr;
1355 NS_HTML5_BREAK(starttagloop
);
1359 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1360 selfClosing
= false;
1361 attributes
= nullptr;
1362 NS_HTML5_BREAK(starttagloop
);
1366 elementName
= nsHtml5ElementName::ELT_IMG
;
1367 NS_HTML5_CONTINUE(starttagloop
);
1371 reconstructTheActiveFormattingElements();
1372 appendVoidElementToCurrentMayFoster(elementName
, attributes
,
1374 selfClosing
= false;
1375 attributes
= nullptr;
1376 NS_HTML5_BREAK(starttagloop
);
1379 appendToCurrentNodeAndPushElementMayFoster(
1380 elementName
, attributes
, formPointer
);
1381 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA
,
1383 originalMode
= mode
;
1385 needToDropLF
= true;
1386 attributes
= nullptr;
1387 NS_HTML5_BREAK(starttagloop
);
1391 reconstructTheActiveFormattingElements();
1392 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1394 originalMode
= mode
;
1396 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
1398 attributes
= nullptr;
1399 NS_HTML5_BREAK(starttagloop
);
1402 if (!scriptingEnabled
) {
1403 reconstructTheActiveFormattingElements();
1404 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1406 attributes
= nullptr;
1407 NS_HTML5_BREAK(starttagloop
);
1414 startTagGenericRawText(elementName
, attributes
);
1415 attributes
= nullptr;
1416 NS_HTML5_BREAK(starttagloop
);
1419 reconstructTheActiveFormattingElements();
1420 appendToCurrentNodeAndPushElementMayFoster(
1421 elementName
, attributes
, formPointer
);
1425 case IN_COLUMN_GROUP
:
1429 mode
= IN_SELECT_IN_TABLE
;
1437 attributes
= nullptr;
1438 NS_HTML5_BREAK(starttagloop
);
1442 if (isCurrent(nsGkAtoms::option
)) {
1445 reconstructTheActiveFormattingElements();
1446 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1448 attributes
= nullptr;
1449 NS_HTML5_BREAK(starttagloop
);
1452 eltPos
= findLastInScope(nsGkAtoms::ruby
);
1453 if (eltPos
!= NOT_FOUND_ON_STACK
) {
1454 generateImpliedEndTags();
1456 if (eltPos
!= currentPtr
) {
1457 if (eltPos
== NOT_FOUND_ON_STACK
) {
1458 errStartTagSeenWithoutRuby(name
);
1460 errUnclosedChildrenInRuby();
1463 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1465 attributes
= nullptr;
1466 NS_HTML5_BREAK(starttagloop
);
1469 eltPos
= findLastInScope(nsGkAtoms::ruby
);
1470 if (eltPos
!= NOT_FOUND_ON_STACK
) {
1471 generateImpliedEndTagsExceptFor(nsGkAtoms::rtc
);
1473 if (eltPos
!= currentPtr
) {
1474 if (!isCurrent(nsGkAtoms::rtc
)) {
1475 if (eltPos
== NOT_FOUND_ON_STACK
) {
1476 errStartTagSeenWithoutRuby(name
);
1478 errUnclosedChildrenInRuby();
1482 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1484 attributes
= nullptr;
1485 NS_HTML5_BREAK(starttagloop
);
1488 reconstructTheActiveFormattingElements();
1489 attributes
->adjustForMath();
1491 appendVoidElementToCurrentMayFosterMathML(elementName
,
1493 selfClosing
= false;
1495 appendToCurrentNodeAndPushElementMayFosterMathML(elementName
,
1498 attributes
= nullptr;
1499 NS_HTML5_BREAK(starttagloop
);
1502 reconstructTheActiveFormattingElements();
1503 attributes
->adjustForSvg();
1505 appendVoidElementToCurrentMayFosterSVG(elementName
, attributes
);
1506 selfClosing
= false;
1508 appendToCurrentNodeAndPushElementMayFosterSVG(elementName
,
1511 attributes
= nullptr;
1512 NS_HTML5_BREAK(starttagloop
);
1517 case TBODY_OR_THEAD_OR_TFOOT
:
1523 errStrayStartTag(name
);
1524 NS_HTML5_BREAK(starttagloop
);
1527 reconstructTheActiveFormattingElements();
1528 appendToCurrentNodeAndPushElementMayFoster(
1529 elementName
, attributes
, formPointer
);
1530 attributes
= nullptr;
1531 NS_HTML5_BREAK(starttagloop
);
1534 reconstructTheActiveFormattingElements();
1535 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1537 attributes
= nullptr;
1538 NS_HTML5_BREAK(starttagloop
);
1549 errStrayStartTag(name
);
1550 if (!fragment
&& !isTemplateContents()) {
1551 addAttributesToHtml(attributes
);
1552 attributes
= nullptr;
1554 NS_HTML5_BREAK(starttagloop
);
1557 case LINK_OR_BASEFONT_OR_BGSOUND
: {
1558 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1559 selfClosing
= false;
1560 attributes
= nullptr;
1561 NS_HTML5_BREAK(starttagloop
);
1564 NS_HTML5_BREAK(inheadloop
);
1567 startTagTitleInHead(elementName
, attributes
);
1568 attributes
= nullptr;
1569 NS_HTML5_BREAK(starttagloop
);
1572 if (scriptingEnabled
) {
1573 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1574 originalMode
= mode
;
1576 tokenizer
->setStateAndEndTagExpectation(
1577 nsHtml5Tokenizer::RAWTEXT
, elementName
);
1579 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1581 mode
= IN_HEAD_NOSCRIPT
;
1583 attributes
= nullptr;
1584 NS_HTML5_BREAK(starttagloop
);
1587 startTagScriptInHead(elementName
, attributes
);
1588 attributes
= nullptr;
1589 NS_HTML5_BREAK(starttagloop
);
1593 startTagGenericRawText(elementName
, attributes
);
1594 attributes
= nullptr;
1595 NS_HTML5_BREAK(starttagloop
);
1598 errFooSeenWhenFooOpen(name
);
1599 NS_HTML5_BREAK(starttagloop
);
1602 startTagTemplateInHead(elementName
, attributes
);
1603 attributes
= nullptr;
1604 NS_HTML5_BREAK(starttagloop
);
1609 NS_HTML5_CONTINUE(starttagloop
);
1616 case IN_HEAD_NOSCRIPT
: {
1619 errStrayStartTag(name
);
1620 if (!fragment
&& !isTemplateContents()) {
1621 addAttributesToHtml(attributes
);
1622 attributes
= nullptr;
1624 NS_HTML5_BREAK(starttagloop
);
1626 case LINK_OR_BASEFONT_OR_BGSOUND
: {
1627 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1628 selfClosing
= false;
1629 attributes
= nullptr;
1630 NS_HTML5_BREAK(starttagloop
);
1633 checkMetaCharset(attributes
);
1634 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1635 selfClosing
= false;
1636 attributes
= nullptr;
1637 NS_HTML5_BREAK(starttagloop
);
1641 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1642 originalMode
= mode
;
1644 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
1646 attributes
= nullptr;
1647 NS_HTML5_BREAK(starttagloop
);
1650 errFooSeenWhenFooOpen(name
);
1651 NS_HTML5_BREAK(starttagloop
);
1654 errFooSeenWhenFooOpen(name
);
1655 NS_HTML5_BREAK(starttagloop
);
1658 errBadStartTagInHead(name
);
1665 case IN_COLUMN_GROUP
: {
1668 errStrayStartTag(name
);
1669 if (!fragment
&& !isTemplateContents()) {
1670 addAttributesToHtml(attributes
);
1671 attributes
= nullptr;
1673 NS_HTML5_BREAK(starttagloop
);
1676 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1677 selfClosing
= false;
1678 attributes
= nullptr;
1679 NS_HTML5_BREAK(starttagloop
);
1682 startTagTemplateInHead(elementName
, attributes
);
1683 attributes
= nullptr;
1684 NS_HTML5_BREAK(starttagloop
);
1687 if (!currentPtr
|| stack
[currentPtr
]->getGroup() == TEMPLATE
) {
1688 MOZ_ASSERT(fragment
|| isTemplateContents());
1689 errGarbageInColgroup();
1690 NS_HTML5_BREAK(starttagloop
);
1698 case IN_SELECT_IN_TABLE
: {
1701 case TBODY_OR_THEAD_OR_TFOOT
:
1705 errStartTagWithSelectOpen(name
);
1706 eltPos
= findLastInTableScope(nsGkAtoms::select
);
1707 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1708 MOZ_ASSERT(fragment
);
1709 NS_HTML5_BREAK(starttagloop
);
1711 while (currentPtr
>= eltPos
) {
1714 resetTheInsertionMode();
1717 default:; // fall through
1724 errStrayStartTag(name
);
1726 addAttributesToHtml(attributes
);
1727 attributes
= nullptr;
1729 NS_HTML5_BREAK(starttagloop
);
1732 if (isCurrent(nsGkAtoms::option
)) {
1735 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1736 attributes
= nullptr;
1737 NS_HTML5_BREAK(starttagloop
);
1740 if (isCurrent(nsGkAtoms::option
)) {
1743 if (isCurrent(nsGkAtoms::optgroup
)) {
1746 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1747 attributes
= nullptr;
1748 NS_HTML5_BREAK(starttagloop
);
1751 errStartSelectWhereEndSelectExpected();
1752 eltPos
= findLastInTableScope(name
);
1753 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1754 MOZ_ASSERT(fragment
);
1755 errNoSelectInTableScope();
1756 NS_HTML5_BREAK(starttagloop
);
1758 while (currentPtr
>= eltPos
) {
1761 resetTheInsertionMode();
1762 NS_HTML5_BREAK(starttagloop
);
1767 errStartTagWithSelectOpen(name
);
1768 eltPos
= findLastInTableScope(nsGkAtoms::select
);
1769 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1770 MOZ_ASSERT(fragment
);
1771 NS_HTML5_BREAK(starttagloop
);
1773 while (currentPtr
>= eltPos
) {
1776 resetTheInsertionMode();
1780 startTagScriptInHead(elementName
, attributes
);
1781 attributes
= nullptr;
1782 NS_HTML5_BREAK(starttagloop
);
1785 startTagTemplateInHead(elementName
, attributes
);
1786 attributes
= nullptr;
1787 NS_HTML5_BREAK(starttagloop
);
1790 errStrayStartTag(name
);
1791 NS_HTML5_BREAK(starttagloop
);
1798 errStrayStartTag(name
);
1799 if (!fragment
&& !isTemplateContents()) {
1800 addAttributesToHtml(attributes
);
1801 attributes
= nullptr;
1803 NS_HTML5_BREAK(starttagloop
);
1806 errStrayStartTag(name
);
1807 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
1815 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1816 attributes
= nullptr;
1817 NS_HTML5_BREAK(starttagloop
);
1820 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1821 selfClosing
= false;
1822 attributes
= nullptr;
1823 NS_HTML5_BREAK(starttagloop
);
1825 default:; // fall through
1829 case AFTER_FRAMESET
: {
1832 errStrayStartTag(name
);
1833 if (!fragment
&& !isTemplateContents()) {
1834 addAttributesToHtml(attributes
);
1835 attributes
= nullptr;
1837 NS_HTML5_BREAK(starttagloop
);
1840 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1841 originalMode
= mode
;
1843 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
1845 attributes
= nullptr;
1846 NS_HTML5_BREAK(starttagloop
);
1849 errStrayStartTag(name
);
1850 NS_HTML5_BREAK(starttagloop
);
1855 errStartTagWithoutDoctype();
1856 documentModeInternal(QUIRKS_MODE
, nullptr, nullptr, false);
1863 if (attributes
== nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
) {
1864 appendHtmlElementToDocumentAndPush();
1866 appendHtmlElementToDocumentAndPush(attributes
);
1869 attributes
= nullptr;
1870 NS_HTML5_BREAK(starttagloop
);
1873 appendHtmlElementToDocumentAndPush();
1882 errStrayStartTag(name
);
1883 if (!fragment
&& !isTemplateContents()) {
1884 addAttributesToHtml(attributes
);
1885 attributes
= nullptr;
1887 NS_HTML5_BREAK(starttagloop
);
1890 appendToCurrentNodeAndPushHeadElement(attributes
);
1892 attributes
= nullptr;
1893 NS_HTML5_BREAK(starttagloop
);
1896 appendToCurrentNodeAndPushHeadElement(
1897 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
1906 errStrayStartTag(name
);
1907 if (!fragment
&& !isTemplateContents()) {
1908 addAttributesToHtml(attributes
);
1909 attributes
= nullptr;
1911 NS_HTML5_BREAK(starttagloop
);
1914 if (!attributes
->getLength()) {
1915 appendToCurrentNodeAndPushBodyElement();
1917 appendToCurrentNodeAndPushBodyElement(attributes
);
1921 attributes
= nullptr;
1922 NS_HTML5_BREAK(starttagloop
);
1925 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1927 attributes
= nullptr;
1928 NS_HTML5_BREAK(starttagloop
);
1931 errFooBetweenHeadAndBody(name
);
1932 pushHeadPointerOntoStack();
1933 nsHtml5StackNode
* headOnStack
= stack
[currentPtr
];
1934 startTagTemplateInHead(elementName
, attributes
);
1935 removeFromStack(headOnStack
);
1936 attributes
= nullptr;
1937 NS_HTML5_BREAK(starttagloop
);
1940 case LINK_OR_BASEFONT_OR_BGSOUND
: {
1941 errFooBetweenHeadAndBody(name
);
1942 pushHeadPointerOntoStack();
1943 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1944 selfClosing
= false;
1946 attributes
= nullptr;
1947 NS_HTML5_BREAK(starttagloop
);
1950 errFooBetweenHeadAndBody(name
);
1951 checkMetaCharset(attributes
);
1952 pushHeadPointerOntoStack();
1953 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1954 selfClosing
= false;
1956 attributes
= nullptr;
1957 NS_HTML5_BREAK(starttagloop
);
1960 errFooBetweenHeadAndBody(name
);
1961 pushHeadPointerOntoStack();
1962 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1963 originalMode
= mode
;
1965 tokenizer
->setStateAndEndTagExpectation(
1966 nsHtml5Tokenizer::SCRIPT_DATA
, elementName
);
1967 attributes
= nullptr;
1968 NS_HTML5_BREAK(starttagloop
);
1972 errFooBetweenHeadAndBody(name
);
1973 pushHeadPointerOntoStack();
1974 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1975 originalMode
= mode
;
1977 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
1979 attributes
= nullptr;
1980 NS_HTML5_BREAK(starttagloop
);
1983 errFooBetweenHeadAndBody(name
);
1984 pushHeadPointerOntoStack();
1985 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1986 originalMode
= mode
;
1988 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA
,
1990 attributes
= nullptr;
1991 NS_HTML5_BREAK(starttagloop
);
1994 errStrayStartTag(name
);
1995 NS_HTML5_BREAK(starttagloop
);
1998 appendToCurrentNodeAndPushBodyElement();
2004 case AFTER_AFTER_BODY
: {
2007 errStrayStartTag(name
);
2008 if (!fragment
&& !isTemplateContents()) {
2009 addAttributesToHtml(attributes
);
2010 attributes
= nullptr;
2012 NS_HTML5_BREAK(starttagloop
);
2015 errStrayStartTag(name
);
2017 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
2022 case AFTER_AFTER_FRAMESET
: {
2025 errStrayStartTag(name
);
2026 if (!fragment
&& !isTemplateContents()) {
2027 addAttributesToHtml(attributes
);
2028 attributes
= nullptr;
2030 NS_HTML5_BREAK(starttagloop
);
2033 startTagGenericRawText(elementName
, attributes
);
2034 attributes
= nullptr;
2035 NS_HTML5_BREAK(starttagloop
);
2038 errStrayStartTag(name
);
2039 NS_HTML5_BREAK(starttagloop
);
2045 NS_HTML5_BREAK(starttagloop
);
2053 if (!mBuilder
&& attributes
!= nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
) {
2058 void nsHtml5TreeBuilder::startTagTitleInHead(
2059 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
2060 appendToCurrentNodeAndPushElementMayFoster(elementName
, attributes
);
2061 originalMode
= mode
;
2063 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA
,
2067 void nsHtml5TreeBuilder::startTagGenericRawText(
2068 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
2069 appendToCurrentNodeAndPushElementMayFoster(elementName
, attributes
);
2070 originalMode
= mode
;
2072 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
2076 void nsHtml5TreeBuilder::startTagScriptInHead(
2077 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
2078 appendToCurrentNodeAndPushElementMayFoster(elementName
, attributes
);
2079 originalMode
= mode
;
2081 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::SCRIPT_DATA
,
2085 void nsHtml5TreeBuilder::startTagTemplateInHead(
2086 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
2087 appendToCurrentNodeAndPushElement(elementName
, attributes
);
2090 originalMode
= mode
;
2092 pushTemplateMode(IN_TEMPLATE
);
2095 bool nsHtml5TreeBuilder::isTemplateContents() {
2096 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
!=
2097 findLast(nsGkAtoms::_template
);
2100 bool nsHtml5TreeBuilder::isTemplateModeStackEmpty() {
2101 return templateModePtr
== -1;
2104 bool nsHtml5TreeBuilder::isSpecialParentInForeign(nsHtml5StackNode
* stackNode
) {
2105 int32_t ns
= stackNode
->ns
;
2106 return (kNameSpaceID_XHTML
== ns
) || (stackNode
->isHtmlIntegrationPoint()) ||
2107 ((kNameSpaceID_MathML
== ns
) &&
2108 (stackNode
->getGroup() == MI_MO_MN_MS_MTEXT
));
2111 nsHtml5String
nsHtml5TreeBuilder::extractCharsetFromContent(
2112 nsHtml5String attributeValue
, nsHtml5TreeBuilder
* tb
) {
2113 int32_t charsetState
= CHARSET_INITIAL
;
2116 autoJArray
<char16_t
, int32_t> buffer
=
2117 nsHtml5Portability::newCharArrayFromString(attributeValue
);
2118 for (int32_t i
= 0; i
< buffer
.length
; i
++) {
2119 char16_t c
= buffer
[i
];
2120 switch (charsetState
) {
2121 case CHARSET_INITIAL
: {
2125 charsetState
= CHARSET_C
;
2137 charsetState
= CHARSET_H
;
2141 charsetState
= CHARSET_INITIAL
;
2150 charsetState
= CHARSET_A
;
2154 charsetState
= CHARSET_INITIAL
;
2163 charsetState
= CHARSET_R
;
2167 charsetState
= CHARSET_INITIAL
;
2176 charsetState
= CHARSET_S
;
2180 charsetState
= CHARSET_INITIAL
;
2189 charsetState
= CHARSET_E
;
2193 charsetState
= CHARSET_INITIAL
;
2202 charsetState
= CHARSET_T
;
2206 charsetState
= CHARSET_INITIAL
;
2221 charsetState
= CHARSET_EQUALS
;
2229 case CHARSET_EQUALS
: {
2240 charsetState
= CHARSET_SINGLE_QUOTED
;
2245 charsetState
= CHARSET_DOUBLE_QUOTED
;
2250 charsetState
= CHARSET_UNQUOTED
;
2255 case CHARSET_SINGLE_QUOTED
: {
2259 NS_HTML5_BREAK(charsetloop
);
2266 case CHARSET_DOUBLE_QUOTED
: {
2270 NS_HTML5_BREAK(charsetloop
);
2277 case CHARSET_UNQUOTED
: {
2286 NS_HTML5_BREAK(charsetloop
);
2298 if (charsetState
== CHARSET_UNQUOTED
) {
2299 end
= buffer
.length
;
2304 return nsHtml5Portability::newStringFromBuffer(buffer
, start
, end
- start
,
2310 void nsHtml5TreeBuilder::checkMetaCharset(nsHtml5HtmlAttributes
* attributes
) {
2311 nsHtml5String charset
=
2312 attributes
->getValue(nsHtml5AttributeName::ATTR_CHARSET
);
2314 if (tokenizer
->internalEncodingDeclaration(charset
)) {
2315 requestSuspension();
2320 if (!nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
2322 attributes
->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV
))) {
2325 nsHtml5String content
=
2326 attributes
->getValue(nsHtml5AttributeName::ATTR_CONTENT
);
2328 nsHtml5String extract
=
2329 nsHtml5TreeBuilder::extractCharsetFromContent(content
, this);
2331 if (tokenizer
->internalEncodingDeclaration(extract
)) {
2332 requestSuspension();
2339 void nsHtml5TreeBuilder::endTag(nsHtml5ElementName
* elementName
) {
2341 needToDropLF
= false;
2343 int32_t group
= elementName
->getGroup();
2344 nsAtom
* name
= elementName
->getName();
2346 if (isInForeign()) {
2347 if (stack
[currentPtr
]->name
!= name
) {
2349 errStrayEndTag(name
);
2351 errEndTagDidNotMatchCurrentOpenElement(name
,
2352 stack
[currentPtr
]->popName
);
2355 eltPos
= currentPtr
;
2356 int32_t origPos
= currentPtr
;
2359 MOZ_ASSERT(fragment
,
2360 "We can get this close to the root of the stack in "
2361 "foreign content only in the fragment case.");
2362 NS_HTML5_BREAK(endtagloop
);
2364 if (stack
[eltPos
]->name
== name
) {
2365 while (currentPtr
>= eltPos
) {
2366 popForeign(origPos
, eltPos
);
2368 NS_HTML5_BREAK(endtagloop
);
2370 if (stack
[--eltPos
]->ns
== kNameSpaceID_XHTML
) {
2382 errStrayEndTag(name
);
2383 NS_HTML5_BREAK(endtagloop
);
2391 eltPos
= findLastOrRoot(nsHtml5TreeBuilder::TR
);
2393 MOZ_ASSERT(fragment
|| isTemplateContents());
2394 errNoTableRowToClose();
2395 NS_HTML5_BREAK(endtagloop
);
2397 clearStackBackTo(eltPos
);
2399 mode
= IN_TABLE_BODY
;
2400 NS_HTML5_BREAK(endtagloop
);
2403 eltPos
= findLastOrRoot(nsHtml5TreeBuilder::TR
);
2405 MOZ_ASSERT(fragment
|| isTemplateContents());
2406 errNoTableRowToClose();
2407 NS_HTML5_BREAK(endtagloop
);
2409 clearStackBackTo(eltPos
);
2411 mode
= IN_TABLE_BODY
;
2414 case TBODY_OR_THEAD_OR_TFOOT
: {
2415 if (findLastInTableScope(name
) ==
2416 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2417 errStrayEndTag(name
);
2418 NS_HTML5_BREAK(endtagloop
);
2420 eltPos
= findLastOrRoot(nsHtml5TreeBuilder::TR
);
2422 MOZ_ASSERT(fragment
|| isTemplateContents());
2423 errNoTableRowToClose();
2424 NS_HTML5_BREAK(endtagloop
);
2426 clearStackBackTo(eltPos
);
2428 mode
= IN_TABLE_BODY
;
2437 errStrayEndTag(name
);
2438 NS_HTML5_BREAK(endtagloop
);
2440 default:; // fall through
2444 case IN_TABLE_BODY
: {
2446 case TBODY_OR_THEAD_OR_TFOOT
: {
2447 eltPos
= findLastOrRoot(name
);
2449 errStrayEndTag(name
);
2450 NS_HTML5_BREAK(endtagloop
);
2452 clearStackBackTo(eltPos
);
2455 NS_HTML5_BREAK(endtagloop
);
2458 eltPos
= findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
2459 if (!eltPos
|| stack
[eltPos
]->getGroup() == TEMPLATE
) {
2460 MOZ_ASSERT(fragment
|| isTemplateContents());
2461 errStrayEndTag(name
);
2462 NS_HTML5_BREAK(endtagloop
);
2464 clearStackBackTo(eltPos
);
2476 errStrayEndTag(name
);
2477 NS_HTML5_BREAK(endtagloop
);
2479 default:; // fall through
2486 eltPos
= findLast(nsGkAtoms::table
);
2487 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2488 MOZ_ASSERT(fragment
|| isTemplateContents());
2489 errStrayEndTag(name
);
2490 NS_HTML5_BREAK(endtagloop
);
2492 while (currentPtr
>= eltPos
) {
2495 resetTheInsertionMode();
2496 NS_HTML5_BREAK(endtagloop
);
2503 case TBODY_OR_THEAD_OR_TFOOT
:
2506 errStrayEndTag(name
);
2507 NS_HTML5_BREAK(endtagloop
);
2513 errStrayEndTag(name
);
2521 eltPos
= findLastInTableScope(nsGkAtoms::caption
);
2522 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2523 NS_HTML5_BREAK(endtagloop
);
2525 generateImpliedEndTags();
2526 if (!!MOZ_UNLIKELY(mViewSource
) && currentPtr
!= eltPos
) {
2527 errUnclosedElements(eltPos
, name
);
2529 while (currentPtr
>= eltPos
) {
2532 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2534 NS_HTML5_BREAK(endtagloop
);
2537 errTableClosedWhileCaptionOpen();
2538 eltPos
= findLastInTableScope(nsGkAtoms::caption
);
2539 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2540 NS_HTML5_BREAK(endtagloop
);
2542 generateImpliedEndTags();
2543 if (!!MOZ_UNLIKELY(mViewSource
) && currentPtr
!= eltPos
) {
2544 errUnclosedElements(eltPos
, name
);
2546 while (currentPtr
>= eltPos
) {
2549 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2557 case TBODY_OR_THEAD_OR_TFOOT
:
2560 errStrayEndTag(name
);
2561 NS_HTML5_BREAK(endtagloop
);
2563 default:; // fall through
2570 eltPos
= findLastInTableScope(name
);
2571 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2572 errStrayEndTag(name
);
2573 NS_HTML5_BREAK(endtagloop
);
2575 generateImpliedEndTags();
2576 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2577 errUnclosedElements(eltPos
, name
);
2579 while (currentPtr
>= eltPos
) {
2582 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2584 NS_HTML5_BREAK(endtagloop
);
2587 case TBODY_OR_THEAD_OR_TFOOT
:
2589 if (findLastInTableScope(name
) ==
2590 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2591 MOZ_ASSERT(name
== nsGkAtoms::tbody
|| name
== nsGkAtoms::tfoot
||
2592 name
== nsGkAtoms::thead
|| fragment
||
2593 isTemplateContents());
2594 errStrayEndTag(name
);
2595 NS_HTML5_BREAK(endtagloop
);
2597 closeTheCell(findLastInTableScopeTdTh());
2605 errStrayEndTag(name
);
2606 NS_HTML5_BREAK(endtagloop
);
2608 default:; // fall through
2616 if (!isSecondOnStackBody()) {
2617 MOZ_ASSERT(fragment
|| isTemplateContents());
2618 errStrayEndTag(name
);
2619 NS_HTML5_BREAK(endtagloop
);
2621 MOZ_ASSERT(currentPtr
>= 1);
2622 if (MOZ_UNLIKELY(mViewSource
)) {
2623 for (int32_t i
= 2; i
<= currentPtr
; i
++) {
2624 switch (stack
[i
]->getGroup()) {
2633 case TBODY_OR_THEAD_OR_TFOOT
: {
2637 errEndWithUnclosedElements(name
);
2638 NS_HTML5_BREAK(uncloseloop1
);
2645 NS_HTML5_BREAK(endtagloop
);
2648 if (!isSecondOnStackBody()) {
2649 MOZ_ASSERT(fragment
|| isTemplateContents());
2650 errStrayEndTag(name
);
2651 NS_HTML5_BREAK(endtagloop
);
2653 if (MOZ_UNLIKELY(mViewSource
)) {
2654 for (int32_t i
= 0; i
<= currentPtr
; i
++) {
2655 switch (stack
[i
]->getGroup()) {
2661 case TBODY_OR_THEAD_OR_TFOOT
:
2668 errEndWithUnclosedElements(name
);
2669 NS_HTML5_BREAK(uncloseloop2
);
2678 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU
:
2679 case UL_OR_OL_OR_DL
:
2680 case PRE_OR_LISTING
:
2683 case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY
: {
2684 eltPos
= findLastInScope(name
);
2685 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2686 errStrayEndTag(name
);
2688 generateImpliedEndTags();
2689 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2690 errUnclosedElements(eltPos
, name
);
2692 while (currentPtr
>= eltPos
) {
2696 NS_HTML5_BREAK(endtagloop
);
2699 if (!isTemplateContents()) {
2701 errStrayEndTag(name
);
2702 NS_HTML5_BREAK(endtagloop
);
2704 formPointer
= nullptr;
2705 eltPos
= findLastInScope(name
);
2706 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2707 errStrayEndTag(name
);
2708 NS_HTML5_BREAK(endtagloop
);
2710 generateImpliedEndTags();
2711 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2712 errUnclosedElements(eltPos
, name
);
2714 removeFromStack(eltPos
);
2715 NS_HTML5_BREAK(endtagloop
);
2717 eltPos
= findLastInScope(name
);
2718 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2719 errStrayEndTag(name
);
2720 NS_HTML5_BREAK(endtagloop
);
2722 generateImpliedEndTags();
2723 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2724 errUnclosedElements(eltPos
, name
);
2726 while (currentPtr
>= eltPos
) {
2729 NS_HTML5_BREAK(endtagloop
);
2733 eltPos
= findLastInButtonScope(nsGkAtoms::p
);
2734 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2735 errNoElementToCloseButEndTagSeen(nsGkAtoms::p
);
2736 if (isInForeign()) {
2737 errHtmlStartTagInForeignContext(name
);
2738 while (currentPtr
>= 0 &&
2739 stack
[currentPtr
]->ns
!= kNameSpaceID_XHTML
) {
2743 appendVoidElementToCurrentMayFoster(
2744 elementName
, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
2745 NS_HTML5_BREAK(endtagloop
);
2747 generateImpliedEndTagsExceptFor(nsGkAtoms::p
);
2748 MOZ_ASSERT(eltPos
!= nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
);
2749 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
2750 errUnclosedElements(eltPos
, name
);
2752 while (currentPtr
>= eltPos
) {
2755 NS_HTML5_BREAK(endtagloop
);
2758 eltPos
= findLastInListScope(name
);
2759 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2760 errNoElementToCloseButEndTagSeen(name
);
2762 generateImpliedEndTagsExceptFor(name
);
2763 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
2764 errUnclosedElements(eltPos
, name
);
2766 while (currentPtr
>= eltPos
) {
2770 NS_HTML5_BREAK(endtagloop
);
2773 eltPos
= findLastInScope(name
);
2774 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2775 errNoElementToCloseButEndTagSeen(name
);
2777 generateImpliedEndTagsExceptFor(name
);
2778 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
2779 errUnclosedElements(eltPos
, name
);
2781 while (currentPtr
>= eltPos
) {
2785 NS_HTML5_BREAK(endtagloop
);
2787 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
: {
2788 eltPos
= findLastInScopeHn();
2789 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2790 errStrayEndTag(name
);
2792 generateImpliedEndTags();
2793 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2794 errUnclosedElements(eltPos
, name
);
2796 while (currentPtr
>= eltPos
) {
2800 NS_HTML5_BREAK(endtagloop
);
2803 case MARQUEE_OR_APPLET
: {
2804 eltPos
= findLastInScope(name
);
2805 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2806 errStrayEndTag(name
);
2808 generateImpliedEndTags();
2809 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2810 errUnclosedElements(eltPos
, name
);
2812 while (currentPtr
>= eltPos
) {
2815 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2817 NS_HTML5_BREAK(endtagloop
);
2821 if (isInForeign()) {
2822 errHtmlStartTagInForeignContext(name
);
2823 while (currentPtr
>= 0 &&
2824 stack
[currentPtr
]->ns
!= kNameSpaceID_XHTML
) {
2828 reconstructTheActiveFormattingElements();
2829 appendVoidElementToCurrentMayFoster(
2830 elementName
, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
2831 NS_HTML5_BREAK(endtagloop
);
2838 #ifdef ENABLE_VOID_MENUITEM
2841 case PARAM_OR_SOURCE_OR_TRACK
:
2853 errStrayEndTag(name
);
2854 NS_HTML5_BREAK(endtagloop
);
2857 if (scriptingEnabled
) {
2858 errStrayEndTag(name
);
2859 NS_HTML5_BREAK(endtagloop
);
2864 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U
:
2867 if (adoptionAgencyEndTag(name
)) {
2868 NS_HTML5_BREAK(endtagloop
);
2873 if (isCurrent(name
)) {
2875 NS_HTML5_BREAK(endtagloop
);
2877 eltPos
= currentPtr
;
2879 nsHtml5StackNode
* node
= stack
[eltPos
];
2880 if (node
->ns
== kNameSpaceID_XHTML
&& node
->name
== name
) {
2881 generateImpliedEndTags();
2882 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2883 errUnclosedElements(eltPos
, name
);
2885 while (currentPtr
>= eltPos
) {
2888 NS_HTML5_BREAK(endtagloop
);
2889 } else if (!eltPos
|| node
->isSpecial()) {
2890 errStrayEndTag(name
);
2891 NS_HTML5_BREAK(endtagloop
);
2904 NS_HTML5_BREAK(endtagloop
);
2914 endTagTemplateInHead();
2915 NS_HTML5_BREAK(endtagloop
);
2918 errStrayEndTag(name
);
2919 NS_HTML5_BREAK(endtagloop
);
2923 case IN_HEAD_NOSCRIPT
: {
2928 NS_HTML5_BREAK(endtagloop
);
2931 errStrayEndTag(name
);
2937 errStrayEndTag(name
);
2938 NS_HTML5_BREAK(endtagloop
);
2942 case IN_COLUMN_GROUP
: {
2946 stack
[currentPtr
]->getGroup() == nsHtml5TreeBuilder::TEMPLATE
) {
2947 MOZ_ASSERT(fragment
|| isTemplateContents());
2948 errGarbageInColgroup();
2949 NS_HTML5_BREAK(endtagloop
);
2953 NS_HTML5_BREAK(endtagloop
);
2956 errStrayEndTag(name
);
2957 NS_HTML5_BREAK(endtagloop
);
2960 endTagTemplateInHead();
2961 NS_HTML5_BREAK(endtagloop
);
2965 stack
[currentPtr
]->getGroup() == nsHtml5TreeBuilder::TEMPLATE
) {
2966 MOZ_ASSERT(fragment
|| isTemplateContents());
2967 errGarbageInColgroup();
2968 NS_HTML5_BREAK(endtagloop
);
2976 case IN_SELECT_IN_TABLE
: {
2980 case TBODY_OR_THEAD_OR_TFOOT
:
2983 errEndTagSeenWithSelectOpen(name
);
2984 if (findLastInTableScope(name
) !=
2985 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2986 eltPos
= findLastInTableScope(nsGkAtoms::select
);
2987 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2988 MOZ_ASSERT(fragment
);
2989 NS_HTML5_BREAK(endtagloop
);
2991 while (currentPtr
>= eltPos
) {
2994 resetTheInsertionMode();
2997 NS_HTML5_BREAK(endtagloop
);
3000 default:; // fall through
3007 if (isCurrent(nsGkAtoms::option
)) {
3009 NS_HTML5_BREAK(endtagloop
);
3011 errStrayEndTag(name
);
3012 NS_HTML5_BREAK(endtagloop
);
3016 if (isCurrent(nsGkAtoms::option
) &&
3017 nsGkAtoms::optgroup
== stack
[currentPtr
- 1]->name
) {
3020 if (isCurrent(nsGkAtoms::optgroup
)) {
3023 errStrayEndTag(name
);
3025 NS_HTML5_BREAK(endtagloop
);
3028 eltPos
= findLastInTableScope(nsGkAtoms::select
);
3029 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
3030 MOZ_ASSERT(fragment
);
3031 errStrayEndTag(name
);
3032 NS_HTML5_BREAK(endtagloop
);
3034 while (currentPtr
>= eltPos
) {
3037 resetTheInsertionMode();
3038 NS_HTML5_BREAK(endtagloop
);
3041 endTagTemplateInHead();
3042 NS_HTML5_BREAK(endtagloop
);
3045 errStrayEndTag(name
);
3046 NS_HTML5_BREAK(endtagloop
);
3054 errStrayEndTag(name
);
3055 NS_HTML5_BREAK(endtagloop
);
3057 mode
= AFTER_AFTER_BODY
;
3058 NS_HTML5_BREAK(endtagloop
);
3062 errEndTagAfterBody();
3063 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3072 MOZ_ASSERT(fragment
);
3073 errStrayEndTag(name
);
3074 NS_HTML5_BREAK(endtagloop
);
3077 if ((!fragment
) && !isCurrent(nsGkAtoms::frameset
)) {
3078 mode
= AFTER_FRAMESET
;
3080 NS_HTML5_BREAK(endtagloop
);
3083 errStrayEndTag(name
);
3084 NS_HTML5_BREAK(endtagloop
);
3088 case AFTER_FRAMESET
: {
3091 mode
= AFTER_AFTER_FRAMESET
;
3092 NS_HTML5_BREAK(endtagloop
);
3095 errStrayEndTag(name
);
3096 NS_HTML5_BREAK(endtagloop
);
3101 errEndTagSeenWithoutDoctype();
3102 documentModeInternal(QUIRKS_MODE
, nullptr, nullptr, false);
3112 appendHtmlElementToDocumentAndPush();
3117 errStrayEndTag(name
);
3118 NS_HTML5_BREAK(endtagloop
);
3128 appendToCurrentNodeAndPushHeadElement(
3129 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
3134 errStrayEndTag(name
);
3135 NS_HTML5_BREAK(endtagloop
);
3142 endTagTemplateInHead();
3143 NS_HTML5_BREAK(endtagloop
);
3148 appendToCurrentNodeAndPushBodyElement();
3153 errStrayEndTag(name
);
3154 NS_HTML5_BREAK(endtagloop
);
3158 case AFTER_AFTER_BODY
: {
3159 errStrayEndTag(name
);
3160 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3163 case AFTER_AFTER_FRAMESET
: {
3164 errStrayEndTag(name
);
3165 NS_HTML5_BREAK(endtagloop
);
3169 if (originalMode
== AFTER_HEAD
) {
3172 mode
= originalMode
;
3173 NS_HTML5_BREAK(endtagloop
);
3180 void nsHtml5TreeBuilder::endTagTemplateInHead() {
3181 int32_t eltPos
= findLast(nsGkAtoms::_template
);
3182 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
3183 errStrayEndTag(nsGkAtoms::_template
);
3186 generateImpliedEndTags();
3187 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(nsGkAtoms::_template
)) {
3188 errUnclosedElements(eltPos
, nsGkAtoms::_template
);
3190 while (currentPtr
>= eltPos
) {
3193 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
3195 resetTheInsertionMode();
3199 nsHtml5TreeBuilder::findLastInTableScopeOrRootTemplateTbodyTheadTfoot() {
3200 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3201 if (stack
[i
]->getGroup() == nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT
||
3202 stack
[i
]->getGroup() == nsHtml5TreeBuilder::TEMPLATE
) {
3209 int32_t nsHtml5TreeBuilder::findLast(nsAtom
* name
) {
3210 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3211 if (stack
[i
]->ns
== kNameSpaceID_XHTML
&& stack
[i
]->name
== name
) {
3215 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3218 int32_t nsHtml5TreeBuilder::findLastInTableScope(nsAtom
* name
) {
3219 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3220 if (stack
[i
]->ns
== kNameSpaceID_XHTML
) {
3221 if (stack
[i
]->name
== name
) {
3223 } else if (stack
[i
]->name
== nsGkAtoms::table
||
3224 stack
[i
]->name
== nsGkAtoms::_template
) {
3225 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3229 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3232 int32_t nsHtml5TreeBuilder::findLastInButtonScope(nsAtom
* name
) {
3233 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3234 if (stack
[i
]->ns
== kNameSpaceID_XHTML
) {
3235 if (stack
[i
]->name
== name
) {
3237 } else if (stack
[i
]->name
== nsGkAtoms::button
) {
3238 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3241 if (stack
[i
]->isScoping()) {
3242 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3245 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3248 int32_t nsHtml5TreeBuilder::findLastInScope(nsAtom
* name
) {
3249 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3250 if (stack
[i
]->ns
== kNameSpaceID_XHTML
&& stack
[i
]->name
== name
) {
3252 } else if (stack
[i
]->isScoping()) {
3253 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3256 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3259 int32_t nsHtml5TreeBuilder::findLastInListScope(nsAtom
* name
) {
3260 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3261 if (stack
[i
]->ns
== kNameSpaceID_XHTML
) {
3262 if (stack
[i
]->name
== name
) {
3264 } else if (stack
[i
]->name
== nsGkAtoms::ul
||
3265 stack
[i
]->name
== nsGkAtoms::ol
) {
3266 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3269 if (stack
[i
]->isScoping()) {
3270 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3273 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3276 int32_t nsHtml5TreeBuilder::findLastInScopeHn() {
3277 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3278 if (stack
[i
]->getGroup() ==
3279 nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
) {
3281 } else if (stack
[i
]->isScoping()) {
3282 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3285 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3288 void nsHtml5TreeBuilder::generateImpliedEndTagsExceptFor(nsAtom
* name
) {
3290 nsHtml5StackNode
* node
= stack
[currentPtr
];
3291 switch (node
->getGroup()) {
3299 if (node
->ns
== kNameSpaceID_XHTML
&& node
->name
== name
) {
3312 void nsHtml5TreeBuilder::generateImpliedEndTags() {
3314 switch (stack
[currentPtr
]->getGroup()) {
3332 bool nsHtml5TreeBuilder::isSecondOnStackBody() {
3333 return currentPtr
>= 1 && stack
[1]->getGroup() == nsHtml5TreeBuilder::BODY
;
3336 void nsHtml5TreeBuilder::documentModeInternal(
3337 nsHtml5DocumentMode m
, nsHtml5String publicIdentifier
,
3338 nsHtml5String systemIdentifier
, bool html4SpecificAdditionalErrorChecks
) {
3339 if (isSrcdocDocument
) {
3341 this->documentMode(STANDARDS_MODE
);
3344 quirks
= (m
== QUIRKS_MODE
);
3345 this->documentMode(m
);
3348 bool nsHtml5TreeBuilder::isAlmostStandards(nsHtml5String publicIdentifier
,
3349 nsHtml5String systemIdentifier
) {
3350 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3351 "-//w3c//dtd xhtml 1.0 transitional//", publicIdentifier
)) {
3354 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3355 "-//w3c//dtd xhtml 1.0 frameset//", publicIdentifier
)) {
3358 if (systemIdentifier
) {
3359 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3360 "-//w3c//dtd html 4.01 transitional//", publicIdentifier
)) {
3363 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3364 "-//w3c//dtd html 4.01 frameset//", publicIdentifier
)) {
3371 bool nsHtml5TreeBuilder::isQuirky(nsAtom
* name
, nsHtml5String publicIdentifier
,
3372 nsHtml5String systemIdentifier
,
3377 if (name
!= nsGkAtoms::html
) {
3380 if (publicIdentifier
) {
3381 for (int32_t i
= 0; i
< nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS
.length
; i
++) {
3382 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3383 nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS
[i
], publicIdentifier
)) {
3387 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3388 "-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier
) ||
3389 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3390 "-/w3c/dtd html 4.0 transitional/en", publicIdentifier
) ||
3391 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3392 "html", publicIdentifier
)) {
3396 if (!systemIdentifier
) {
3397 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3398 "-//w3c//dtd html 4.01 transitional//", publicIdentifier
)) {
3400 } else if (nsHtml5Portability::
3401 lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3402 "-//w3c//dtd html 4.01 frameset//", publicIdentifier
)) {
3405 } else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3406 "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd",
3407 systemIdentifier
)) {
3413 void nsHtml5TreeBuilder::closeTheCell(int32_t eltPos
) {
3414 generateImpliedEndTags();
3415 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
3416 errUnclosedElementsCell(eltPos
);
3418 while (currentPtr
>= eltPos
) {
3421 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
3426 int32_t nsHtml5TreeBuilder::findLastInTableScopeTdTh() {
3427 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3428 nsAtom
* name
= stack
[i
]->name
;
3429 if (stack
[i
]->ns
== kNameSpaceID_XHTML
) {
3430 if (nsGkAtoms::td
== name
|| nsGkAtoms::th
== name
) {
3432 } else if (name
== nsGkAtoms::table
|| name
== nsGkAtoms::_template
) {
3433 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3437 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3440 void nsHtml5TreeBuilder::clearStackBackTo(int32_t eltPos
) {
3441 int32_t eltGroup
= stack
[eltPos
]->getGroup();
3442 while (currentPtr
> eltPos
) {
3443 if (stack
[currentPtr
]->ns
== kNameSpaceID_XHTML
&&
3444 stack
[currentPtr
]->getGroup() == TEMPLATE
&&
3445 (eltGroup
== TABLE
|| eltGroup
== TBODY_OR_THEAD_OR_TFOOT
||
3446 eltGroup
== TR
|| !eltPos
)) {
3453 void nsHtml5TreeBuilder::resetTheInsertionMode() {
3454 nsHtml5StackNode
* node
;
3457 for (int32_t i
= currentPtr
; i
>= 0; i
--) {
3462 if (!(contextNamespace
== kNameSpaceID_XHTML
&&
3463 (contextName
== nsGkAtoms::td
|| contextName
== nsGkAtoms::th
))) {
3466 ns
= contextNamespace
;
3469 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3473 if (nsGkAtoms::select
== name
) {
3474 int32_t ancestorIndex
= i
;
3475 while (ancestorIndex
> 0) {
3476 nsHtml5StackNode
* ancestor
= stack
[ancestorIndex
--];
3477 if (kNameSpaceID_XHTML
== ancestor
->ns
) {
3478 if (nsGkAtoms::_template
== ancestor
->name
) {
3481 if (nsGkAtoms::table
== ancestor
->name
) {
3482 mode
= IN_SELECT_IN_TABLE
;
3489 } else if (nsGkAtoms::td
== name
|| nsGkAtoms::th
== name
) {
3492 } else if (nsGkAtoms::tr
== name
) {
3495 } else if (nsGkAtoms::tbody
== name
|| nsGkAtoms::thead
== name
||
3496 nsGkAtoms::tfoot
== name
) {
3497 mode
= IN_TABLE_BODY
;
3499 } else if (nsGkAtoms::caption
== name
) {
3502 } else if (nsGkAtoms::colgroup
== name
) {
3503 mode
= IN_COLUMN_GROUP
;
3505 } else if (nsGkAtoms::table
== name
) {
3508 } else if (kNameSpaceID_XHTML
!= ns
) {
3509 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3511 } else if (nsGkAtoms::_template
== name
) {
3512 MOZ_ASSERT(templateModePtr
>= 0);
3513 mode
= templateModeStack
[templateModePtr
];
3515 } else if (nsGkAtoms::head
== name
) {
3516 if (name
== contextName
) {
3517 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3522 } else if (nsGkAtoms::body
== name
) {
3523 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3525 } else if (nsGkAtoms::frameset
== name
) {
3528 } else if (nsGkAtoms::html
== name
) {
3536 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3542 void nsHtml5TreeBuilder::implicitlyCloseP() {
3543 int32_t eltPos
= findLastInButtonScope(nsGkAtoms::p
);
3544 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
3547 generateImpliedEndTagsExceptFor(nsGkAtoms::p
);
3548 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
3549 errUnclosedElementsImplied(eltPos
, nsGkAtoms::p
);
3551 while (currentPtr
>= eltPos
) {
3556 bool nsHtml5TreeBuilder::debugOnlyClearLastStackSlot() {
3557 stack
[currentPtr
] = nullptr;
3561 bool nsHtml5TreeBuilder::debugOnlyClearLastListSlot() {
3562 listOfActiveFormattingElements
[listPtr
] = nullptr;
3566 void nsHtml5TreeBuilder::pushTemplateMode(int32_t mode
) {
3568 if (templateModePtr
== templateModeStack
.length
) {
3569 jArray
<int32_t, int32_t> newStack
=
3570 jArray
<int32_t, int32_t>::newJArray(templateModeStack
.length
+ 64);
3571 nsHtml5ArrayCopy::arraycopy(templateModeStack
, newStack
,
3572 templateModeStack
.length
);
3573 templateModeStack
= newStack
;
3575 templateModeStack
[templateModePtr
] = mode
;
3578 void nsHtml5TreeBuilder::push(nsHtml5StackNode
* node
) {
3580 if (currentPtr
== stack
.length
) {
3581 jArray
<nsHtml5StackNode
*, int32_t> newStack
=
3582 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(stack
.length
+ 64);
3583 nsHtml5ArrayCopy::arraycopy(stack
, newStack
, stack
.length
);
3586 stack
[currentPtr
] = node
;
3587 elementPushed(node
->ns
, node
->popName
, node
->node
);
3590 void nsHtml5TreeBuilder::silentPush(nsHtml5StackNode
* node
) {
3592 if (currentPtr
== stack
.length
) {
3593 jArray
<nsHtml5StackNode
*, int32_t> newStack
=
3594 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(stack
.length
+ 64);
3595 nsHtml5ArrayCopy::arraycopy(stack
, newStack
, stack
.length
);
3598 stack
[currentPtr
] = node
;
3601 void nsHtml5TreeBuilder::append(nsHtml5StackNode
* node
) {
3603 if (listPtr
== listOfActiveFormattingElements
.length
) {
3604 jArray
<nsHtml5StackNode
*, int32_t> newList
=
3605 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(
3606 listOfActiveFormattingElements
.length
+ 64);
3607 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements
, newList
,
3608 listOfActiveFormattingElements
.length
);
3609 listOfActiveFormattingElements
= newList
;
3611 listOfActiveFormattingElements
[listPtr
] = node
;
3614 void nsHtml5TreeBuilder::
3615 clearTheListOfActiveFormattingElementsUpToTheLastMarker() {
3616 while (listPtr
> -1) {
3617 if (!listOfActiveFormattingElements
[listPtr
]) {
3621 listOfActiveFormattingElements
[listPtr
]->release(this);
3626 void nsHtml5TreeBuilder::removeFromStack(int32_t pos
) {
3627 if (currentPtr
== pos
) {
3630 stack
[pos
]->release(this);
3631 nsHtml5ArrayCopy::arraycopy(stack
, pos
+ 1, pos
, currentPtr
- pos
);
3632 MOZ_ASSERT(debugOnlyClearLastStackSlot());
3637 void nsHtml5TreeBuilder::removeFromStack(nsHtml5StackNode
* node
) {
3638 if (stack
[currentPtr
] == node
) {
3641 int32_t pos
= currentPtr
- 1;
3642 while (pos
>= 0 && stack
[pos
] != node
) {
3649 node
->release(this);
3650 nsHtml5ArrayCopy::arraycopy(stack
, pos
+ 1, pos
, currentPtr
- pos
);
3655 void nsHtml5TreeBuilder::removeFromListOfActiveFormattingElements(int32_t pos
) {
3656 MOZ_ASSERT(!!listOfActiveFormattingElements
[pos
]);
3657 listOfActiveFormattingElements
[pos
]->release(this);
3658 if (pos
== listPtr
) {
3659 MOZ_ASSERT(debugOnlyClearLastListSlot());
3663 MOZ_ASSERT(pos
< listPtr
);
3664 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements
, pos
+ 1, pos
,
3666 MOZ_ASSERT(debugOnlyClearLastListSlot());
3670 bool nsHtml5TreeBuilder::adoptionAgencyEndTag(nsAtom
* name
) {
3671 if (stack
[currentPtr
]->ns
== kNameSpaceID_XHTML
&&
3672 stack
[currentPtr
]->name
== name
&&
3673 findInListOfActiveFormattingElements(stack
[currentPtr
]) == -1) {
3677 for (int32_t i
= 0; i
< 8; ++i
) {
3678 int32_t formattingEltListPos
= listPtr
;
3679 while (formattingEltListPos
> -1) {
3680 nsHtml5StackNode
* listNode
=
3681 listOfActiveFormattingElements
[formattingEltListPos
];
3683 formattingEltListPos
= -1;
3685 } else if (listNode
->name
== name
) {
3688 formattingEltListPos
--;
3690 if (formattingEltListPos
== -1) {
3693 nsHtml5StackNode
* formattingElt
=
3694 listOfActiveFormattingElements
[formattingEltListPos
];
3695 int32_t formattingEltStackPos
= currentPtr
;
3696 bool inScope
= true;
3697 while (formattingEltStackPos
> -1) {
3698 nsHtml5StackNode
* node
= stack
[formattingEltStackPos
];
3699 if (node
== formattingElt
) {
3701 } else if (node
->isScoping()) {
3704 formattingEltStackPos
--;
3706 if (formattingEltStackPos
== -1) {
3707 errNoElementToCloseButEndTagSeen(name
);
3708 removeFromListOfActiveFormattingElements(formattingEltListPos
);
3712 errNoElementToCloseButEndTagSeen(name
);
3715 if (formattingEltStackPos
!= currentPtr
) {
3716 errEndTagViolatesNestingRules(name
);
3718 int32_t furthestBlockPos
= formattingEltStackPos
+ 1;
3719 while (furthestBlockPos
<= currentPtr
) {
3720 nsHtml5StackNode
* node
= stack
[furthestBlockPos
];
3721 MOZ_ASSERT(furthestBlockPos
> 0,
3722 "How is formattingEltStackPos + 1 not > 0?");
3723 if (node
->isSpecial()) {
3728 if (furthestBlockPos
> currentPtr
) {
3729 while (currentPtr
>= formattingEltStackPos
) {
3732 removeFromListOfActiveFormattingElements(formattingEltListPos
);
3735 nsHtml5StackNode
* commonAncestor
= stack
[formattingEltStackPos
- 1];
3736 nsIContentHandle
* insertionCommonAncestor
=
3737 nodeFromStackWithBlinkCompat(formattingEltStackPos
- 1);
3738 nsHtml5StackNode
* furthestBlock
= stack
[furthestBlockPos
];
3739 int32_t bookmark
= formattingEltListPos
;
3740 int32_t nodePos
= furthestBlockPos
;
3741 nsHtml5StackNode
* lastNode
= furthestBlock
;
3746 if (nodePos
== formattingEltStackPos
) {
3749 nsHtml5StackNode
* node
= stack
[nodePos
];
3750 int32_t nodeListPos
= findInListOfActiveFormattingElements(node
);
3751 if (j
> 3 && nodeListPos
!= -1) {
3752 removeFromListOfActiveFormattingElements(nodeListPos
);
3753 if (nodeListPos
<= formattingEltListPos
) {
3754 formattingEltListPos
--;
3756 if (nodeListPos
<= bookmark
) {
3761 if (nodeListPos
== -1) {
3762 MOZ_ASSERT(formattingEltStackPos
< nodePos
);
3763 MOZ_ASSERT(bookmark
< nodePos
);
3764 MOZ_ASSERT(furthestBlockPos
> nodePos
);
3765 removeFromStack(nodePos
);
3769 if (nodePos
== furthestBlockPos
) {
3770 bookmark
= nodeListPos
+ 1;
3772 MOZ_ASSERT(node
== listOfActiveFormattingElements
[nodeListPos
]);
3773 MOZ_ASSERT(node
== stack
[nodePos
]);
3774 nsIContentHandle
* clone
= createElement(
3775 kNameSpaceID_XHTML
, node
->name
, node
->attributes
->cloneAttributes(),
3776 insertionCommonAncestor
, htmlCreator(node
->getHtmlCreator()));
3777 nsHtml5StackNode
* newNode
= createStackNode(
3778 node
->getFlags(), node
->ns
, node
->name
, clone
, node
->popName
,
3779 node
->attributes
, node
->getHtmlCreator());
3780 node
->dropAttributes();
3781 stack
[nodePos
] = newNode
;
3783 listOfActiveFormattingElements
[nodeListPos
] = newNode
;
3784 node
->release(this);
3785 node
->release(this);
3787 detachFromParent(lastNode
->node
);
3788 appendElement(lastNode
->node
, nodeFromStackWithBlinkCompat(nodePos
));
3791 if (commonAncestor
->isFosterParenting()) {
3792 detachFromParent(lastNode
->node
);
3793 insertIntoFosterParent(lastNode
->node
);
3795 detachFromParent(lastNode
->node
);
3796 appendElement(lastNode
->node
, insertionCommonAncestor
);
3798 nsIContentHandle
* clone
= createElement(
3799 kNameSpaceID_XHTML
, formattingElt
->name
,
3800 formattingElt
->attributes
->cloneAttributes(), furthestBlock
->node
,
3801 htmlCreator(formattingElt
->getHtmlCreator()));
3802 nsHtml5StackNode
* formattingClone
= createStackNode(
3803 formattingElt
->getFlags(), formattingElt
->ns
, formattingElt
->name
,
3804 clone
, formattingElt
->popName
, formattingElt
->attributes
,
3805 formattingElt
->getHtmlCreator());
3806 formattingElt
->dropAttributes();
3807 appendChildrenToNewParent(furthestBlock
->node
, clone
);
3808 appendElement(clone
, furthestBlock
->node
);
3809 removeFromListOfActiveFormattingElements(formattingEltListPos
);
3810 insertIntoListOfActiveFormattingElements(formattingClone
, bookmark
);
3811 MOZ_ASSERT(formattingEltStackPos
< furthestBlockPos
);
3812 removeFromStack(formattingEltStackPos
);
3813 insertIntoStack(formattingClone
, furthestBlockPos
);
3818 void nsHtml5TreeBuilder::insertIntoStack(nsHtml5StackNode
* node
,
3820 MOZ_ASSERT(currentPtr
+ 1 < stack
.length
);
3821 MOZ_ASSERT(position
<= currentPtr
+ 1);
3822 if (position
== currentPtr
+ 1) {
3825 nsHtml5ArrayCopy::arraycopy(stack
, position
, position
+ 1,
3826 (currentPtr
- position
) + 1);
3828 stack
[position
] = node
;
3832 void nsHtml5TreeBuilder::insertIntoListOfActiveFormattingElements(
3833 nsHtml5StackNode
* formattingClone
, int32_t bookmark
) {
3834 formattingClone
->retain();
3835 MOZ_ASSERT(listPtr
+ 1 < listOfActiveFormattingElements
.length
);
3836 if (bookmark
<= listPtr
) {
3837 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements
, bookmark
,
3838 bookmark
+ 1, (listPtr
- bookmark
) + 1);
3841 listOfActiveFormattingElements
[bookmark
] = formattingClone
;
3844 int32_t nsHtml5TreeBuilder::findInListOfActiveFormattingElements(
3845 nsHtml5StackNode
* node
) {
3846 for (int32_t i
= listPtr
; i
>= 0; i
--) {
3847 if (node
== listOfActiveFormattingElements
[i
]) {
3854 int32_t nsHtml5TreeBuilder::
3855 findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
3857 for (int32_t i
= listPtr
; i
>= 0; i
--) {
3858 nsHtml5StackNode
* node
= listOfActiveFormattingElements
[i
];
3861 } else if (node
->name
== name
) {
3868 void nsHtml5TreeBuilder::maybeForgetEarlierDuplicateFormattingElement(
3869 nsAtom
* name
, nsHtml5HtmlAttributes
* attributes
) {
3870 int32_t candidate
= -1;
3872 for (int32_t i
= listPtr
; i
>= 0; i
--) {
3873 nsHtml5StackNode
* node
= listOfActiveFormattingElements
[i
];
3877 if (node
->name
== name
&& node
->attributes
->equalsAnother(attributes
)) {
3883 removeFromListOfActiveFormattingElements(candidate
);
3887 int32_t nsHtml5TreeBuilder::findLastOrRoot(nsAtom
* name
) {
3888 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3889 if (stack
[i
]->ns
== kNameSpaceID_XHTML
&& stack
[i
]->name
== name
) {
3896 int32_t nsHtml5TreeBuilder::findLastOrRoot(int32_t group
) {
3897 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3898 if (stack
[i
]->getGroup() == group
) {
3905 bool nsHtml5TreeBuilder::addAttributesToBody(
3906 nsHtml5HtmlAttributes
* attributes
) {
3907 if (currentPtr
>= 1) {
3908 nsHtml5StackNode
* body
= stack
[1];
3909 if (body
->getGroup() == nsHtml5TreeBuilder::BODY
) {
3910 addAttributesToElement(body
->node
, attributes
);
3917 void nsHtml5TreeBuilder::addAttributesToHtml(
3918 nsHtml5HtmlAttributes
* attributes
) {
3919 addAttributesToElement(stack
[0]->node
, attributes
);
3922 void nsHtml5TreeBuilder::pushHeadPointerOntoStack() {
3923 MOZ_ASSERT(!!headPointer
);
3924 MOZ_ASSERT(mode
== AFTER_HEAD
);
3926 silentPush(createStackNode(nsHtml5ElementName::ELT_HEAD
, headPointer
));
3929 void nsHtml5TreeBuilder::reconstructTheActiveFormattingElements() {
3930 if (listPtr
== -1) {
3933 nsHtml5StackNode
* mostRecent
= listOfActiveFormattingElements
[listPtr
];
3934 if (!mostRecent
|| isInStack(mostRecent
)) {
3937 int32_t entryPos
= listPtr
;
3940 if (entryPos
== -1) {
3943 if (!listOfActiveFormattingElements
[entryPos
]) {
3946 if (isInStack(listOfActiveFormattingElements
[entryPos
])) {
3950 while (entryPos
< listPtr
) {
3952 nsHtml5StackNode
* entry
= listOfActiveFormattingElements
[entryPos
];
3953 nsHtml5StackNode
* current
= stack
[currentPtr
];
3954 nsIContentHandle
* clone
;
3955 if (current
->isFosterParenting()) {
3956 clone
= createAndInsertFosterParentedElement(
3957 kNameSpaceID_XHTML
, entry
->name
, entry
->attributes
->cloneAttributes(),
3958 htmlCreator(entry
->getHtmlCreator()));
3960 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
3961 clone
= createElement(kNameSpaceID_XHTML
, entry
->name
,
3962 entry
->attributes
->cloneAttributes(), currentNode
,
3963 htmlCreator(entry
->getHtmlCreator()));
3964 appendElement(clone
, currentNode
);
3966 nsHtml5StackNode
* entryClone
= createStackNode(
3967 entry
->getFlags(), entry
->ns
, entry
->name
, clone
, entry
->popName
,
3968 entry
->attributes
, entry
->getHtmlCreator());
3969 entry
->dropAttributes();
3971 listOfActiveFormattingElements
[entryPos
] = entryClone
;
3972 entry
->release(this);
3973 entryClone
->retain();
3977 void nsHtml5TreeBuilder::notifyUnusedStackNode(int32_t idxInStackNodes
) {
3978 if (idxInStackNodes
< stackNodesIdx
) {
3979 stackNodesIdx
= idxInStackNodes
;
3983 nsHtml5StackNode
* nsHtml5TreeBuilder::getUnusedStackNode() {
3984 while (stackNodesIdx
< numStackNodes
) {
3985 if (stackNodes
[stackNodesIdx
]->isUnused()) {
3986 return stackNodes
[stackNodesIdx
++];
3990 if (stackNodesIdx
< stackNodes
.length
) {
3991 stackNodes
[stackNodesIdx
] = new nsHtml5StackNode(stackNodesIdx
);
3993 return stackNodes
[stackNodesIdx
++];
3995 jArray
<nsHtml5StackNode
*, int32_t> newStack
=
3996 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(stackNodes
.length
+ 64);
3997 nsHtml5ArrayCopy::arraycopy(stackNodes
, newStack
, stackNodes
.length
);
3998 stackNodes
= newStack
;
3999 stackNodes
[stackNodesIdx
] = new nsHtml5StackNode(stackNodesIdx
);
4001 return stackNodes
[stackNodesIdx
++];
4004 nsHtml5StackNode
* nsHtml5TreeBuilder::createStackNode(
4005 int32_t flags
, int32_t ns
, nsAtom
* name
, nsIContentHandle
* node
,
4006 nsAtom
* popName
, nsHtml5HtmlAttributes
* attributes
,
4007 mozilla::dom::HTMLContentCreatorFunction htmlCreator
) {
4008 nsHtml5StackNode
* instance
= getUnusedStackNode();
4009 instance
->setValues(flags
, ns
, name
, node
, popName
, attributes
, htmlCreator
);
4013 nsHtml5StackNode
* nsHtml5TreeBuilder::createStackNode(
4014 nsHtml5ElementName
* elementName
, nsIContentHandle
* node
) {
4015 nsHtml5StackNode
* instance
= getUnusedStackNode();
4016 instance
->setValues(elementName
, node
);
4020 nsHtml5StackNode
* nsHtml5TreeBuilder::createStackNode(
4021 nsHtml5ElementName
* elementName
, nsIContentHandle
* node
,
4022 nsHtml5HtmlAttributes
* attributes
) {
4023 nsHtml5StackNode
* instance
= getUnusedStackNode();
4024 instance
->setValues(elementName
, node
, attributes
);
4028 nsHtml5StackNode
* nsHtml5TreeBuilder::createStackNode(
4029 nsHtml5ElementName
* elementName
, nsIContentHandle
* node
, nsAtom
* popName
) {
4030 nsHtml5StackNode
* instance
= getUnusedStackNode();
4031 instance
->setValues(elementName
, node
, popName
);
4035 nsHtml5StackNode
* nsHtml5TreeBuilder::createStackNode(
4036 nsHtml5ElementName
* elementName
, nsAtom
* popName
, nsIContentHandle
* node
) {
4037 nsHtml5StackNode
* instance
= getUnusedStackNode();
4038 instance
->setValues(elementName
, popName
, node
);
4042 nsHtml5StackNode
* nsHtml5TreeBuilder::createStackNode(
4043 nsHtml5ElementName
* elementName
, nsIContentHandle
* node
, nsAtom
* popName
,
4044 bool markAsIntegrationPoint
) {
4045 nsHtml5StackNode
* instance
= getUnusedStackNode();
4046 instance
->setValues(elementName
, node
, popName
, markAsIntegrationPoint
);
4050 void nsHtml5TreeBuilder::insertIntoFosterParent(nsIContentHandle
* child
) {
4051 int32_t tablePos
= findLastOrRoot(nsHtml5TreeBuilder::TABLE
);
4052 int32_t templatePos
= findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE
);
4053 if (templatePos
>= tablePos
) {
4054 appendElement(child
, stack
[templatePos
]->node
);
4057 nsHtml5StackNode
* node
= stack
[tablePos
];
4058 insertFosterParentedChild(child
, node
->node
, stack
[tablePos
- 1]->node
);
4061 nsIContentHandle
* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
4062 int32_t ns
, nsAtom
* name
, nsHtml5HtmlAttributes
* attributes
,
4063 nsHtml5ContentCreatorFunction creator
) {
4064 return createAndInsertFosterParentedElement(ns
, name
, attributes
, nullptr,
4068 nsIContentHandle
* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
4069 int32_t ns
, nsAtom
* name
, nsHtml5HtmlAttributes
* attributes
,
4070 nsIContentHandle
* form
, nsHtml5ContentCreatorFunction creator
) {
4071 int32_t tablePos
= findLastOrRoot(nsHtml5TreeBuilder::TABLE
);
4072 int32_t templatePos
= findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE
);
4073 if (templatePos
>= tablePos
) {
4074 nsIContentHandle
* child
= createElement(ns
, name
, attributes
, form
,
4075 stack
[templatePos
]->node
, creator
);
4076 appendElement(child
, stack
[templatePos
]->node
);
4079 nsHtml5StackNode
* node
= stack
[tablePos
];
4080 return createAndInsertFosterParentedElement(
4081 ns
, name
, attributes
, form
, node
->node
, stack
[tablePos
- 1]->node
,
4085 bool nsHtml5TreeBuilder::isInStack(nsHtml5StackNode
* node
) {
4086 for (int32_t i
= currentPtr
; i
>= 0; i
--) {
4087 if (stack
[i
] == node
) {
4094 void nsHtml5TreeBuilder::popTemplateMode() { templateModePtr
--; }
4096 void nsHtml5TreeBuilder::pop() {
4097 nsHtml5StackNode
* node
= stack
[currentPtr
];
4098 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4100 elementPopped(node
->ns
, node
->popName
, node
->node
);
4101 node
->release(this);
4104 void nsHtml5TreeBuilder::popForeign(int32_t origPos
, int32_t eltPos
) {
4105 nsHtml5StackNode
* node
= stack
[currentPtr
];
4106 if (origPos
!= currentPtr
|| eltPos
!= currentPtr
) {
4107 markMalformedIfScript(node
->node
);
4109 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4111 elementPopped(node
->ns
, node
->popName
, node
->node
);
4112 node
->release(this);
4115 void nsHtml5TreeBuilder::silentPop() {
4116 nsHtml5StackNode
* node
= stack
[currentPtr
];
4117 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4119 node
->release(this);
4122 void nsHtml5TreeBuilder::popOnEof() {
4123 nsHtml5StackNode
* node
= stack
[currentPtr
];
4124 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4126 markMalformedIfScript(node
->node
);
4127 elementPopped(node
->ns
, node
->popName
, node
->node
);
4128 node
->release(this);
4131 void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush(
4132 nsHtml5HtmlAttributes
* attributes
) {
4133 nsIContentHandle
* elt
= createHtmlElementSetAsRoot(attributes
);
4134 nsHtml5StackNode
* node
= createStackNode(nsHtml5ElementName::ELT_HTML
, elt
);
4138 void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush() {
4139 appendHtmlElementToDocumentAndPush(tokenizer
->emptyAttributes());
4142 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(
4143 nsHtml5HtmlAttributes
* attributes
) {
4144 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4145 nsIContentHandle
* elt
=
4146 createElement(kNameSpaceID_XHTML
, nsGkAtoms::head
, attributes
,
4147 currentNode
, htmlCreator(NS_NewHTMLSharedElement
));
4148 appendElement(elt
, currentNode
);
4150 nsHtml5StackNode
* node
= createStackNode(nsHtml5ElementName::ELT_HEAD
, elt
);
4154 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement(
4155 nsHtml5HtmlAttributes
* attributes
) {
4156 appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_BODY
, attributes
);
4159 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement() {
4160 appendToCurrentNodeAndPushBodyElement(tokenizer
->emptyAttributes());
4163 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(
4164 nsHtml5HtmlAttributes
* attributes
) {
4165 nsIContentHandle
* elt
;
4166 nsHtml5StackNode
* current
= stack
[currentPtr
];
4167 if (current
->isFosterParenting()) {
4168 elt
= createAndInsertFosterParentedElement(
4169 kNameSpaceID_XHTML
, nsGkAtoms::form
, attributes
,
4170 htmlCreator(NS_NewHTMLFormElement
));
4172 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4173 elt
= createElement(kNameSpaceID_XHTML
, nsGkAtoms::form
, attributes
,
4174 currentNode
, htmlCreator(NS_NewHTMLFormElement
));
4175 appendElement(elt
, currentNode
);
4177 if (!isTemplateContents()) {
4180 nsHtml5StackNode
* node
= createStackNode(nsHtml5ElementName::ELT_FORM
, elt
);
4184 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(
4185 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4186 nsHtml5HtmlAttributes
* clone
= attributes
->cloneAttributes();
4187 nsIContentHandle
* elt
;
4188 nsHtml5StackNode
* current
= stack
[currentPtr
];
4189 if (current
->isFosterParenting()) {
4190 elt
= createAndInsertFosterParentedElement(
4191 kNameSpaceID_XHTML
, elementName
->getName(), attributes
,
4192 htmlCreator(elementName
->getHtmlCreator()));
4194 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4196 createElement(kNameSpaceID_XHTML
, elementName
->getName(), attributes
,
4197 currentNode
, htmlCreator(elementName
->getHtmlCreator()));
4198 appendElement(elt
, currentNode
);
4200 nsHtml5StackNode
* node
= createStackNode(elementName
, elt
, clone
);
4206 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(
4207 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4208 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4209 nsIContentHandle
* elt
=
4210 createElement(kNameSpaceID_XHTML
, elementName
->getName(), attributes
,
4211 currentNode
, htmlCreator(elementName
->getHtmlCreator()));
4212 appendElement(elt
, currentNode
);
4213 if (nsHtml5ElementName::ELT_TEMPLATE
== elementName
) {
4214 elt
= getDocumentFragmentForTemplate(elt
);
4216 nsHtml5StackNode
* node
= createStackNode(elementName
, elt
);
4220 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
4221 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4222 nsAtom
* popName
= elementName
->getName();
4223 nsIContentHandle
* elt
;
4224 nsHtml5StackNode
* current
= stack
[currentPtr
];
4225 if (current
->isFosterParenting()) {
4226 elt
= createAndInsertFosterParentedElement(
4227 kNameSpaceID_XHTML
, popName
, attributes
,
4228 htmlCreator(elementName
->getHtmlCreator()));
4230 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4231 elt
= createElement(kNameSpaceID_XHTML
, popName
, attributes
, currentNode
,
4232 htmlCreator(elementName
->getHtmlCreator()));
4233 appendElement(elt
, currentNode
);
4235 nsHtml5StackNode
* node
= createStackNode(elementName
, elt
, popName
);
4239 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(
4240 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4241 nsAtom
* popName
= elementName
->getName();
4242 bool markAsHtmlIntegrationPoint
= false;
4243 if (nsHtml5ElementName::ELT_ANNOTATION_XML
== elementName
&&
4244 annotationXmlEncodingPermitsHtml(attributes
)) {
4245 markAsHtmlIntegrationPoint
= true;
4247 nsIContentHandle
* elt
;
4248 nsHtml5StackNode
* current
= stack
[currentPtr
];
4249 if (current
->isFosterParenting()) {
4250 elt
= createAndInsertFosterParentedElement(
4251 kNameSpaceID_MathML
, popName
, attributes
, htmlCreator(nullptr));
4253 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4254 elt
= createElement(kNameSpaceID_MathML
, popName
, attributes
, currentNode
,
4255 htmlCreator(nullptr));
4256 appendElement(elt
, currentNode
);
4258 nsHtml5StackNode
* node
=
4259 createStackNode(elementName
, elt
, popName
, markAsHtmlIntegrationPoint
);
4263 bool nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(
4264 nsHtml5HtmlAttributes
* attributes
) {
4265 nsHtml5String encoding
=
4266 attributes
->getValue(nsHtml5AttributeName::ATTR_ENCODING
);
4270 return nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
4271 "application/xhtml+xml", encoding
) ||
4272 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
4273 "text/html", encoding
);
4276 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(
4277 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4278 nsAtom
* popName
= elementName
->getCamelCaseName();
4279 nsIContentHandle
* elt
;
4280 nsHtml5StackNode
* current
= stack
[currentPtr
];
4281 if (current
->isFosterParenting()) {
4282 elt
= createAndInsertFosterParentedElement(
4283 kNameSpaceID_SVG
, popName
, attributes
,
4284 svgCreator(elementName
->getSvgCreator()));
4286 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4287 elt
= createElement(kNameSpaceID_SVG
, popName
, attributes
, currentNode
,
4288 svgCreator(elementName
->getSvgCreator()));
4289 appendElement(elt
, currentNode
);
4291 nsHtml5StackNode
* node
= createStackNode(elementName
, popName
, elt
);
4295 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
4296 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
,
4297 nsIContentHandle
* form
) {
4298 nsIContentHandle
* elt
;
4299 nsIContentHandle
* formOwner
=
4300 !form
|| fragment
|| isTemplateContents() ? nullptr : form
;
4301 nsHtml5StackNode
* current
= stack
[currentPtr
];
4302 if (current
->isFosterParenting()) {
4303 elt
= createAndInsertFosterParentedElement(
4304 kNameSpaceID_XHTML
, elementName
->getName(), attributes
, formOwner
,
4305 htmlCreator(elementName
->getHtmlCreator()));
4307 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4308 elt
= createElement(kNameSpaceID_XHTML
, elementName
->getName(), attributes
,
4309 formOwner
, currentNode
,
4310 htmlCreator(elementName
->getHtmlCreator()));
4311 appendElement(elt
, currentNode
);
4313 nsHtml5StackNode
* node
= createStackNode(elementName
, elt
);
4317 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
4318 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
,
4319 nsIContentHandle
* form
) {
4320 nsAtom
* name
= elementName
->getName();
4321 nsIContentHandle
* elt
;
4322 nsIContentHandle
* formOwner
=
4323 !form
|| fragment
|| isTemplateContents() ? nullptr : form
;
4324 nsHtml5StackNode
* current
= stack
[currentPtr
];
4325 if (current
->isFosterParenting()) {
4326 elt
= createAndInsertFosterParentedElement(
4327 kNameSpaceID_XHTML
, name
, attributes
, formOwner
,
4328 htmlCreator(elementName
->getHtmlCreator()));
4330 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4332 createElement(kNameSpaceID_XHTML
, name
, attributes
, formOwner
,
4333 currentNode
, htmlCreator(elementName
->getHtmlCreator()));
4334 appendElement(elt
, currentNode
);
4336 elementPushed(kNameSpaceID_XHTML
, name
, elt
);
4337 elementPopped(kNameSpaceID_XHTML
, name
, elt
);
4340 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
4341 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4342 nsAtom
* popName
= elementName
->getName();
4343 nsIContentHandle
* elt
;
4344 nsHtml5StackNode
* current
= stack
[currentPtr
];
4345 if (current
->isFosterParenting()) {
4346 elt
= createAndInsertFosterParentedElement(
4347 kNameSpaceID_XHTML
, popName
, attributes
,
4348 htmlCreator(elementName
->getHtmlCreator()));
4350 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4351 elt
= createElement(kNameSpaceID_XHTML
, popName
, attributes
, currentNode
,
4352 htmlCreator(elementName
->getHtmlCreator()));
4353 appendElement(elt
, currentNode
);
4355 elementPushed(kNameSpaceID_XHTML
, popName
, elt
);
4356 elementPopped(kNameSpaceID_XHTML
, popName
, elt
);
4359 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(
4360 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4361 nsAtom
* popName
= elementName
->getCamelCaseName();
4362 nsIContentHandle
* elt
;
4363 nsHtml5StackNode
* current
= stack
[currentPtr
];
4364 if (current
->isFosterParenting()) {
4365 elt
= createAndInsertFosterParentedElement(
4366 kNameSpaceID_SVG
, popName
, attributes
,
4367 svgCreator(elementName
->getSvgCreator()));
4369 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4370 elt
= createElement(kNameSpaceID_SVG
, popName
, attributes
, currentNode
,
4371 svgCreator(elementName
->getSvgCreator()));
4372 appendElement(elt
, currentNode
);
4374 elementPushed(kNameSpaceID_SVG
, popName
, elt
);
4375 elementPopped(kNameSpaceID_SVG
, popName
, elt
);
4378 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(
4379 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4380 nsAtom
* popName
= elementName
->getName();
4381 nsIContentHandle
* elt
;
4382 nsHtml5StackNode
* current
= stack
[currentPtr
];
4383 if (current
->isFosterParenting()) {
4384 elt
= createAndInsertFosterParentedElement(
4385 kNameSpaceID_MathML
, popName
, attributes
, htmlCreator(nullptr));
4387 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4388 elt
= createElement(kNameSpaceID_MathML
, popName
, attributes
, currentNode
,
4389 htmlCreator(nullptr));
4390 appendElement(elt
, currentNode
);
4392 elementPushed(kNameSpaceID_MathML
, popName
, elt
);
4393 elementPopped(kNameSpaceID_MathML
, popName
, elt
);
4396 void nsHtml5TreeBuilder::appendVoidInputToCurrent(
4397 nsHtml5HtmlAttributes
* attributes
, nsIContentHandle
* form
) {
4398 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4399 nsIContentHandle
* elt
=
4400 createElement(kNameSpaceID_XHTML
, nsGkAtoms::input
, attributes
,
4401 !form
|| fragment
|| isTemplateContents() ? nullptr : form
,
4402 currentNode
, htmlCreator(NS_NewHTMLInputElement
));
4403 appendElement(elt
, currentNode
);
4404 elementPushed(kNameSpaceID_XHTML
, nsGkAtoms::input
, elt
);
4405 elementPopped(kNameSpaceID_XHTML
, nsGkAtoms::input
, elt
);
4408 void nsHtml5TreeBuilder::appendVoidFormToCurrent(
4409 nsHtml5HtmlAttributes
* attributes
) {
4410 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4411 nsIContentHandle
* elt
=
4412 createElement(kNameSpaceID_XHTML
, nsGkAtoms::form
, attributes
,
4413 currentNode
, htmlCreator(NS_NewHTMLFormElement
));
4415 appendElement(elt
, currentNode
);
4416 elementPushed(kNameSpaceID_XHTML
, nsGkAtoms::form
, elt
);
4417 elementPopped(kNameSpaceID_XHTML
, nsGkAtoms::form
, elt
);
4420 void nsHtml5TreeBuilder::requestSuspension() {
4421 tokenizer
->requestSuspension();
4425 bool nsHtml5TreeBuilder::isInForeign() {
4426 return currentPtr
>= 0 && stack
[currentPtr
]->ns
!= kNameSpaceID_XHTML
;
4429 bool nsHtml5TreeBuilder::isInForeignButNotHtmlOrMathTextIntegrationPoint() {
4430 if (currentPtr
< 0) {
4433 return !isSpecialParentInForeign(stack
[currentPtr
]);
4436 void nsHtml5TreeBuilder::setFragmentContext(nsAtom
* context
, int32_t ns
,
4437 nsIContentHandle
* node
,
4439 this->contextName
= context
;
4440 this->contextNamespace
= ns
;
4441 this->contextNode
= node
;
4442 this->fragment
= (!!contextName
);
4443 this->quirks
= quirks
;
4446 nsIContentHandle
* nsHtml5TreeBuilder::currentNode() {
4447 return stack
[currentPtr
]->node
;
4450 bool nsHtml5TreeBuilder::isScriptingEnabled() { return scriptingEnabled
; }
4452 void nsHtml5TreeBuilder::setScriptingEnabled(bool scriptingEnabled
) {
4453 this->scriptingEnabled
= scriptingEnabled
;
4456 void nsHtml5TreeBuilder::setIsSrcdocDocument(bool isSrcdocDocument
) {
4457 this->isSrcdocDocument
= isSrcdocDocument
;
4460 void nsHtml5TreeBuilder::flushCharacters() {
4461 if (charBufferLen
> 0) {
4462 if ((mode
== IN_TABLE
|| mode
== IN_TABLE_BODY
|| mode
== IN_ROW
) &&
4463 charBufferContainsNonWhitespace()) {
4464 errNonSpaceInTable();
4465 reconstructTheActiveFormattingElements();
4466 if (!stack
[currentPtr
]->isFosterParenting()) {
4467 appendCharacters(currentNode(), charBuffer
, 0, charBufferLen
);
4471 int32_t tablePos
= findLastOrRoot(nsHtml5TreeBuilder::TABLE
);
4472 int32_t templatePos
= findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE
);
4473 if (templatePos
>= tablePos
) {
4474 appendCharacters(stack
[templatePos
]->node
, charBuffer
, 0,
4479 nsHtml5StackNode
* tableElt
= stack
[tablePos
];
4480 insertFosterParentedCharacters(charBuffer
, 0, charBufferLen
,
4481 tableElt
->node
, stack
[tablePos
- 1]->node
);
4485 appendCharacters(currentNode(), charBuffer
, 0, charBufferLen
);
4490 bool nsHtml5TreeBuilder::charBufferContainsNonWhitespace() {
4491 for (int32_t i
= 0; i
< charBufferLen
; i
++) {
4492 switch (charBuffer
[i
]) {
4508 nsAHtml5TreeBuilderState
* nsHtml5TreeBuilder::newSnapshot() {
4509 jArray
<nsHtml5StackNode
*, int32_t> listCopy
=
4510 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(listPtr
+ 1);
4511 for (int32_t i
= 0; i
< listCopy
.length
; i
++) {
4512 nsHtml5StackNode
* node
= listOfActiveFormattingElements
[i
];
4514 nsHtml5StackNode
* newNode
= new nsHtml5StackNode(-1);
4515 newNode
->setValues(node
->getFlags(), node
->ns
, node
->name
, node
->node
,
4516 node
->popName
, node
->attributes
->cloneAttributes(),
4517 node
->getHtmlCreator());
4518 listCopy
[i
] = newNode
;
4520 listCopy
[i
] = nullptr;
4523 jArray
<nsHtml5StackNode
*, int32_t> stackCopy
=
4524 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(currentPtr
+ 1);
4525 for (int32_t i
= 0; i
< stackCopy
.length
; i
++) {
4526 nsHtml5StackNode
* node
= stack
[i
];
4527 int32_t listIndex
= findInListOfActiveFormattingElements(node
);
4528 if (listIndex
== -1) {
4529 nsHtml5StackNode
* newNode
= new nsHtml5StackNode(-1);
4530 newNode
->setValues(node
->getFlags(), node
->ns
, node
->name
, node
->node
,
4531 node
->popName
, nullptr, node
->getHtmlCreator());
4532 stackCopy
[i
] = newNode
;
4534 stackCopy
[i
] = listCopy
[listIndex
];
4535 stackCopy
[i
]->retain();
4538 jArray
<int32_t, int32_t> templateModeStackCopy
=
4539 jArray
<int32_t, int32_t>::newJArray(templateModePtr
+ 1);
4540 nsHtml5ArrayCopy::arraycopy(templateModeStack
, templateModeStackCopy
,
4541 templateModeStackCopy
.length
);
4542 return new nsHtml5StateSnapshot(stackCopy
, listCopy
, templateModeStackCopy
,
4543 formPointer
, headPointer
, mode
, originalMode
,
4544 framesetOk
, needToDropLF
, quirks
);
4547 bool nsHtml5TreeBuilder::snapshotMatches(nsAHtml5TreeBuilderState
* snapshot
) {
4548 jArray
<nsHtml5StackNode
*, int32_t> stackCopy
= snapshot
->getStack();
4549 int32_t stackLen
= snapshot
->getStackLength();
4550 jArray
<nsHtml5StackNode
*, int32_t> listCopy
=
4551 snapshot
->getListOfActiveFormattingElements();
4552 int32_t listLen
= snapshot
->getListOfActiveFormattingElementsLength();
4553 jArray
<int32_t, int32_t> templateModeStackCopy
=
4554 snapshot
->getTemplateModeStack();
4555 int32_t templateModeStackLen
= snapshot
->getTemplateModeStackLength();
4556 if (stackLen
!= currentPtr
+ 1 || listLen
!= listPtr
+ 1 ||
4557 templateModeStackLen
!= templateModePtr
+ 1 ||
4558 formPointer
!= snapshot
->getFormPointer() ||
4559 headPointer
!= snapshot
->getHeadPointer() ||
4560 mode
!= snapshot
->getMode() ||
4561 originalMode
!= snapshot
->getOriginalMode() ||
4562 framesetOk
!= snapshot
->isFramesetOk() ||
4563 needToDropLF
!= snapshot
->isNeedToDropLF() ||
4564 quirks
!= snapshot
->isQuirks()) {
4567 for (int32_t i
= listLen
- 1; i
>= 0; i
--) {
4568 if (!listCopy
[i
] && !listOfActiveFormattingElements
[i
]) {
4570 } else if (!listCopy
[i
] || !listOfActiveFormattingElements
[i
]) {
4573 if (listCopy
[i
]->node
!= listOfActiveFormattingElements
[i
]->node
) {
4577 for (int32_t i
= stackLen
- 1; i
>= 0; i
--) {
4578 if (stackCopy
[i
]->node
!= stack
[i
]->node
) {
4582 for (int32_t i
= templateModeStackLen
- 1; i
>= 0; i
--) {
4583 if (templateModeStackCopy
[i
] != templateModeStack
[i
]) {
4590 void nsHtml5TreeBuilder::loadState(nsAHtml5TreeBuilderState
* snapshot
) {
4591 mCurrentHtmlScriptIsAsyncOrDefer
= false;
4592 jArray
<nsHtml5StackNode
*, int32_t> stackCopy
= snapshot
->getStack();
4593 int32_t stackLen
= snapshot
->getStackLength();
4594 jArray
<nsHtml5StackNode
*, int32_t> listCopy
=
4595 snapshot
->getListOfActiveFormattingElements();
4596 int32_t listLen
= snapshot
->getListOfActiveFormattingElementsLength();
4597 jArray
<int32_t, int32_t> templateModeStackCopy
=
4598 snapshot
->getTemplateModeStack();
4599 int32_t templateModeStackLen
= snapshot
->getTemplateModeStackLength();
4600 for (int32_t i
= 0; i
<= listPtr
; i
++) {
4601 if (listOfActiveFormattingElements
[i
]) {
4602 listOfActiveFormattingElements
[i
]->release(this);
4605 if (listOfActiveFormattingElements
.length
< listLen
) {
4606 listOfActiveFormattingElements
=
4607 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(listLen
);
4609 listPtr
= listLen
- 1;
4610 for (int32_t i
= 0; i
<= currentPtr
; i
++) {
4611 stack
[i
]->release(this);
4613 if (stack
.length
< stackLen
) {
4614 stack
= jArray
<nsHtml5StackNode
*, int32_t>::newJArray(stackLen
);
4616 currentPtr
= stackLen
- 1;
4617 if (templateModeStack
.length
< templateModeStackLen
) {
4619 jArray
<int32_t, int32_t>::newJArray(templateModeStackLen
);
4621 templateModePtr
= templateModeStackLen
- 1;
4622 for (int32_t i
= 0; i
< listLen
; i
++) {
4623 nsHtml5StackNode
* node
= listCopy
[i
];
4625 nsHtml5StackNode
* newNode
= createStackNode(
4626 node
->getFlags(), node
->ns
, node
->name
, node
->node
, node
->popName
,
4627 node
->attributes
->cloneAttributes(), node
->getHtmlCreator());
4628 listOfActiveFormattingElements
[i
] = newNode
;
4630 listOfActiveFormattingElements
[i
] = nullptr;
4633 for (int32_t i
= 0; i
< stackLen
; i
++) {
4634 nsHtml5StackNode
* node
= stackCopy
[i
];
4635 int32_t listIndex
= findInArray(node
, listCopy
);
4636 if (listIndex
== -1) {
4637 nsHtml5StackNode
* newNode
=
4638 createStackNode(node
->getFlags(), node
->ns
, node
->name
, node
->node
,
4639 node
->popName
, nullptr, node
->getHtmlCreator());
4642 stack
[i
] = listOfActiveFormattingElements
[listIndex
];
4646 nsHtml5ArrayCopy::arraycopy(templateModeStackCopy
, templateModeStack
,
4647 templateModeStackLen
);
4648 formPointer
= snapshot
->getFormPointer();
4649 headPointer
= snapshot
->getHeadPointer();
4650 mode
= snapshot
->getMode();
4651 originalMode
= snapshot
->getOriginalMode();
4652 framesetOk
= snapshot
->isFramesetOk();
4653 needToDropLF
= snapshot
->isNeedToDropLF();
4654 quirks
= snapshot
->isQuirks();
4657 int32_t nsHtml5TreeBuilder::findInArray(
4658 nsHtml5StackNode
* node
, jArray
<nsHtml5StackNode
*, int32_t> arr
) {
4659 for (int32_t i
= listPtr
; i
>= 0; i
--) {
4660 if (node
== arr
[i
]) {
4667 nsIContentHandle
* nsHtml5TreeBuilder::nodeFromStackWithBlinkCompat(
4669 if (stackPos
> 511) {
4671 return stack
[511]->node
;
4673 return stack
[stackPos
]->node
;
4676 nsIContentHandle
* nsHtml5TreeBuilder::getFormPointer() { return formPointer
; }
4678 nsIContentHandle
* nsHtml5TreeBuilder::getHeadPointer() { return headPointer
; }
4680 jArray
<nsHtml5StackNode
*, int32_t>
4681 nsHtml5TreeBuilder::getListOfActiveFormattingElements() {
4682 return listOfActiveFormattingElements
;
4685 jArray
<nsHtml5StackNode
*, int32_t> nsHtml5TreeBuilder::getStack() {
4689 jArray
<int32_t, int32_t> nsHtml5TreeBuilder::getTemplateModeStack() {
4690 return templateModeStack
;
4693 int32_t nsHtml5TreeBuilder::getMode() { return mode
; }
4695 int32_t nsHtml5TreeBuilder::getOriginalMode() { return originalMode
; }
4697 bool nsHtml5TreeBuilder::isFramesetOk() { return framesetOk
; }
4699 bool nsHtml5TreeBuilder::isNeedToDropLF() { return needToDropLF
; }
4701 bool nsHtml5TreeBuilder::isQuirks() { return quirks
; }
4703 int32_t nsHtml5TreeBuilder::getListOfActiveFormattingElementsLength() {
4707 int32_t nsHtml5TreeBuilder::getStackLength() { return currentPtr
+ 1; }
4709 int32_t nsHtml5TreeBuilder::getTemplateModeStackLength() {
4710 return templateModePtr
+ 1;
4713 void nsHtml5TreeBuilder::initializeStatics() {}
4715 void nsHtml5TreeBuilder::releaseStatics() {}
4717 #include "nsHtml5TreeBuilderCppSupplement.h"