2 * Copyright (c) 2007 Henri Sivonen
3 * Copyright (c) 2007-2017 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 "nsHtml5AttributeName.h"
34 #include "nsHtml5ElementName.h"
35 #include "nsHtml5Tokenizer.h"
36 #include "nsHtml5StackNode.h"
37 #include "nsHtml5UTF16Buffer.h"
38 #include "nsHtml5StateSnapshot.h"
39 #include "nsHtml5Portability.h"
41 #include "nsHtml5TreeBuilder.h"
43 char16_t
nsHtml5TreeBuilder::REPLACEMENT_CHARACTER
[] = {0xfffd};
44 static const char* const QUIRKY_PUBLIC_IDS_DATA
[] = {
45 "+//silmaril//dtd html pro v0r11 19970101//",
46 "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
47 "-//as//dtd html 3.0 aswedit + extensions//",
48 "-//ietf//dtd html 2.0 level 1//",
49 "-//ietf//dtd html 2.0 level 2//",
50 "-//ietf//dtd html 2.0 strict level 1//",
51 "-//ietf//dtd html 2.0 strict level 2//",
52 "-//ietf//dtd html 2.0 strict//",
53 "-//ietf//dtd html 2.0//",
54 "-//ietf//dtd html 2.1e//",
55 "-//ietf//dtd html 3.0//",
56 "-//ietf//dtd html 3.2 final//",
57 "-//ietf//dtd html 3.2//",
58 "-//ietf//dtd html 3//",
59 "-//ietf//dtd html level 0//",
60 "-//ietf//dtd html level 1//",
61 "-//ietf//dtd html level 2//",
62 "-//ietf//dtd html level 3//",
63 "-//ietf//dtd html strict level 0//",
64 "-//ietf//dtd html strict level 1//",
65 "-//ietf//dtd html strict level 2//",
66 "-//ietf//dtd html strict level 3//",
67 "-//ietf//dtd html strict//",
68 "-//ietf//dtd html//",
69 "-//metrius//dtd metrius presentational//",
70 "-//microsoft//dtd internet explorer 2.0 html strict//",
71 "-//microsoft//dtd internet explorer 2.0 html//",
72 "-//microsoft//dtd internet explorer 2.0 tables//",
73 "-//microsoft//dtd internet explorer 3.0 html strict//",
74 "-//microsoft//dtd internet explorer 3.0 html//",
75 "-//microsoft//dtd internet explorer 3.0 tables//",
76 "-//netscape comm. corp.//dtd html//",
77 "-//netscape comm. corp.//dtd strict html//",
78 "-//o'reilly and associates//dtd html 2.0//",
79 "-//o'reilly and associates//dtd html extended 1.0//",
80 "-//o'reilly and associates//dtd html extended relaxed 1.0//",
81 "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html "
83 "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
84 "-//spyglass//dtd html 2.0 extended//",
85 "-//sq//dtd html 2.0 hotmetal + extensions//",
86 "-//sun microsystems corp.//dtd hotjava html//",
87 "-//sun microsystems corp.//dtd hotjava strict html//",
88 "-//w3c//dtd html 3 1995-03-24//",
89 "-//w3c//dtd html 3.2 draft//",
90 "-//w3c//dtd html 3.2 final//",
91 "-//w3c//dtd html 3.2//",
92 "-//w3c//dtd html 3.2s draft//",
93 "-//w3c//dtd html 4.0 frameset//",
94 "-//w3c//dtd html 4.0 transitional//",
95 "-//w3c//dtd html experimental 19960712//",
96 "-//w3c//dtd html experimental 970421//",
97 "-//w3c//dtd w3 html//",
98 "-//w3o//dtd w3 html 3.0//",
99 "-//webtechs//dtd mozilla html 2.0//",
100 "-//webtechs//dtd mozilla html//"};
101 staticJArray
<const char*, int32_t> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS
= {
102 QUIRKY_PUBLIC_IDS_DATA
, MOZ_ARRAY_LENGTH(QUIRKY_PUBLIC_IDS_DATA
)};
103 void nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer
* self
) {
105 stackNodes
= jArray
<nsHtml5StackNode
*, int32_t>::newJArray(64);
106 stack
= jArray
<nsHtml5StackNode
*, int32_t>::newJArray(64);
107 templateModeStack
= jArray
<int32_t, int32_t>::newJArray(64);
108 listOfActiveFormattingElements
=
109 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(64);
110 needToDropLF
= false;
111 originalMode
= INITIAL
;
112 templateModePtr
= -1;
117 formPointer
= nullptr;
118 headPointer
= nullptr;
121 charBuffer
= nullptr;
124 nsIContentHandle
* elt
;
128 elt
= createHtmlElementSetAsRoot(tokenizer
->emptyAttributes());
130 if (contextNamespace
== kNameSpaceID_SVG
) {
131 nsHtml5ElementName
* elementName
= nsHtml5ElementName::ELT_SVG
;
132 if (nsGkAtoms::title
== contextName
|| nsGkAtoms::desc
== contextName
||
133 nsGkAtoms::foreignObject
== contextName
) {
134 elementName
= nsHtml5ElementName::ELT_FOREIGNOBJECT
;
136 nsHtml5StackNode
* node
=
137 createStackNode(elementName
, elementName
->getCamelCaseName(), elt
);
139 stack
[currentPtr
] = node
;
140 tokenizer
->setState(nsHtml5Tokenizer::DATA
);
142 } else if (contextNamespace
== kNameSpaceID_MathML
) {
143 nsHtml5ElementName
* elementName
= nsHtml5ElementName::ELT_MATH
;
144 if (nsGkAtoms::mi_
== contextName
|| nsGkAtoms::mo_
== contextName
||
145 nsGkAtoms::mn_
== contextName
|| nsGkAtoms::ms_
== contextName
||
146 nsGkAtoms::mtext_
== contextName
) {
147 elementName
= nsHtml5ElementName::ELT_MTEXT
;
148 } else if (nsGkAtoms::annotation_xml_
== contextName
) {
149 elementName
= nsHtml5ElementName::ELT_ANNOTATION_XML
;
151 nsHtml5StackNode
* node
=
152 createStackNode(elementName
, elt
, elementName
->getName(), false);
154 stack
[currentPtr
] = node
;
155 tokenizer
->setState(nsHtml5Tokenizer::DATA
);
158 nsHtml5StackNode
* node
=
159 createStackNode(nsHtml5ElementName::ELT_HTML
, elt
);
161 stack
[currentPtr
] = node
;
162 if (nsGkAtoms::_template
== contextName
) {
163 pushTemplateMode(IN_TEMPLATE
);
165 resetTheInsertionMode();
166 formPointer
= getFormPointerForContext(contextNode
);
167 if (nsGkAtoms::title
== contextName
||
168 nsGkAtoms::textarea
== contextName
) {
169 tokenizer
->setState(nsHtml5Tokenizer::RCDATA
);
170 } else if (nsGkAtoms::style
== contextName
||
171 nsGkAtoms::xmp
== contextName
||
172 nsGkAtoms::iframe
== contextName
||
173 nsGkAtoms::noembed
== contextName
||
174 nsGkAtoms::noframes
== contextName
||
175 (scriptingEnabled
&& nsGkAtoms::noscript
== contextName
)) {
176 tokenizer
->setState(nsHtml5Tokenizer::RAWTEXT
);
177 } else if (nsGkAtoms::plaintext
== contextName
) {
178 tokenizer
->setState(nsHtml5Tokenizer::PLAINTEXT
);
179 } else if (nsGkAtoms::script
== contextName
) {
180 tokenizer
->setState(nsHtml5Tokenizer::SCRIPT_DATA
);
182 tokenizer
->setState(nsHtml5Tokenizer::DATA
);
187 if (tokenizer
->isViewingXmlSource()) {
188 nsIContentHandle
* elt
= createElement(
189 kNameSpaceID_SVG
, nsGkAtoms::svg
, tokenizer
->emptyAttributes(),
190 nullptr, svgCreator(NS_NewSVGSVGElement
));
191 nsHtml5StackNode
* node
=
192 createStackNode(nsHtml5ElementName::ELT_SVG
, nsGkAtoms::svg
, elt
);
194 stack
[currentPtr
] = node
;
199 void nsHtml5TreeBuilder::doctype(nsAtom
* name
, nsHtml5String publicIdentifier
,
200 nsHtml5String systemIdentifier
,
202 needToDropLF
= false;
203 if (!isInForeign() && mode
== INITIAL
) {
204 nsHtml5String emptyString
= nsHtml5Portability::newEmptyString();
205 appendDoctypeToDocument(!name
? nsGkAtoms::_empty
: name
,
206 !publicIdentifier
? emptyString
: publicIdentifier
,
207 !systemIdentifier
? emptyString
: systemIdentifier
);
208 emptyString
.Release();
209 if (isQuirky(name
, publicIdentifier
, systemIdentifier
, forceQuirks
)) {
211 documentModeInternal(QUIRKS_MODE
, publicIdentifier
, systemIdentifier
);
212 } else if (isAlmostStandards(publicIdentifier
, systemIdentifier
)) {
213 errAlmostStandardsDoctype();
214 documentModeInternal(ALMOST_STANDARDS_MODE
, publicIdentifier
,
217 documentModeInternal(STANDARDS_MODE
, publicIdentifier
, systemIdentifier
);
226 void nsHtml5TreeBuilder::comment(char16_t
* buf
, int32_t start
, int32_t length
) {
227 needToDropLF
= false;
228 if (!isInForeign()) {
232 case AFTER_AFTER_BODY
:
233 case AFTER_AFTER_FRAMESET
: {
234 appendCommentToDocument(buf
, start
, length
);
239 appendComment(stack
[0]->node
, buf
, start
, length
);
248 appendComment(stack
[currentPtr
]->node
, buf
, start
, length
);
252 void nsHtml5TreeBuilder::characters(const char16_t
* buf
, int32_t start
,
254 if (tokenizer
->isViewingXmlSource()) {
258 needToDropLF
= false;
259 if (buf
[start
] == '\n') {
271 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
272 reconstructTheActiveFormattingElements();
277 accumulateCharacters(buf
, start
, length
);
283 accumulateCharactersForced(buf
, start
, length
);
287 int32_t end
= start
+ length
;
288 for (int32_t i
= start
; i
< end
; i
++) {
303 case IN_HEAD_NOSCRIPT
:
305 case IN_COLUMN_GROUP
:
307 case AFTER_FRAMESET
: {
316 accumulateCharacters(buf
, start
, i
- start
);
319 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
321 reconstructTheActiveFormattingElements();
323 NS_HTML5_BREAK(charactersloop
);
326 case IN_SELECT_IN_TABLE
: {
327 NS_HTML5_BREAK(charactersloop
);
332 accumulateCharactersForced(buf
, i
, 1);
337 case AFTER_AFTER_BODY
:
338 case AFTER_AFTER_FRAMESET
: {
340 accumulateCharacters(buf
, start
, i
- start
);
344 reconstructTheActiveFormattingElements();
348 MOZ_FALLTHROUGH_ASSERT();
353 documentModeInternal(QUIRKS_MODE
, nullptr, nullptr);
359 appendHtmlElementToDocumentAndPush();
366 accumulateCharacters(buf
, start
, i
- start
);
370 appendToCurrentNodeAndPushHeadElement(
371 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
378 accumulateCharacters(buf
, start
, i
- start
);
387 case IN_HEAD_NOSCRIPT
: {
389 accumulateCharacters(buf
, start
, i
- start
);
392 errNonSpaceInNoscriptInHead();
401 accumulateCharacters(buf
, start
, i
- start
);
405 appendToCurrentNodeAndPushBodyElement();
421 accumulateCharacters(buf
, start
, i
- start
);
424 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
426 reconstructTheActiveFormattingElements();
428 NS_HTML5_BREAK(charactersloop
);
433 accumulateCharactersForced(buf
, i
, 1);
437 case IN_COLUMN_GROUP
: {
439 accumulateCharacters(buf
, start
, i
- start
);
442 if (!currentPtr
|| stack
[currentPtr
]->getGroup() ==
443 nsHtml5TreeBuilder::TEMPLATE
) {
444 errNonSpaceInColgroupInFragment();
455 case IN_SELECT_IN_TABLE
: {
456 NS_HTML5_BREAK(charactersloop
);
459 errNonSpaceAfterBody();
461 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
467 accumulateCharacters(buf
, start
, i
- start
);
469 errNonSpaceInFrameset();
473 case AFTER_FRAMESET
: {
475 accumulateCharacters(buf
, start
, i
- start
);
477 errNonSpaceAfterFrameset();
481 case AFTER_AFTER_BODY
: {
482 errNonSpaceInTrailer();
483 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
487 case AFTER_AFTER_FRAMESET
: {
489 accumulateCharacters(buf
, start
, i
- start
);
491 errNonSpaceInTrailer();
501 accumulateCharacters(buf
, start
, end
- start
);
507 void nsHtml5TreeBuilder::zeroOriginatingReplacementCharacter() {
509 accumulateCharacters(REPLACEMENT_CHARACTER
, 0, 1);
512 if (currentPtr
>= 0) {
513 if (isSpecialParentInForeign(stack
[currentPtr
])) {
516 accumulateCharacters(REPLACEMENT_CHARACTER
, 0, 1);
520 void nsHtml5TreeBuilder::zeroOrReplacementCharacter() {
521 zeroOriginatingReplacementCharacter();
524 void nsHtml5TreeBuilder::eof() {
529 documentModeInternal(QUIRKS_MODE
, nullptr, nullptr);
534 appendHtmlElementToDocumentAndPush();
539 appendToCurrentNodeAndPushHeadElement(
540 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
545 while (currentPtr
> 0) {
551 case IN_HEAD_NOSCRIPT
: {
552 while (currentPtr
> 1) {
559 appendToCurrentNodeAndPushBodyElement();
566 case IN_SELECT_IN_TABLE
:
568 case IN_COLUMN_GROUP
:
573 if (isTemplateModeStackEmpty()) {
574 NS_HTML5_BREAK(eofloop
);
579 int32_t eltPos
= findLast(nsGkAtoms::_template
);
580 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
581 MOZ_ASSERT(fragment
);
582 NS_HTML5_BREAK(eofloop
);
584 if (MOZ_UNLIKELY(mViewSource
)) {
585 errListUnclosedStartTags(0);
587 while (currentPtr
>= eltPos
) {
590 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
592 resetTheInsertionMode();
596 if (originalMode
== AFTER_HEAD
) {
604 NS_HTML5_BREAK(eofloop
);
608 case AFTER_AFTER_BODY
:
609 case AFTER_AFTER_FRAMESET
:
611 NS_HTML5_BREAK(eofloop
);
616 while (currentPtr
> 0) {
624 void nsHtml5TreeBuilder::endTokenization() {
625 formPointer
= nullptr;
626 headPointer
= nullptr;
627 contextName
= nullptr;
628 contextNode
= nullptr;
629 templateModeStack
= nullptr;
631 while (currentPtr
> -1) {
632 stack
[currentPtr
]->release(this);
637 if (listOfActiveFormattingElements
) {
638 while (listPtr
> -1) {
639 if (listOfActiveFormattingElements
[listPtr
]) {
640 listOfActiveFormattingElements
[listPtr
]->release(this);
644 listOfActiveFormattingElements
= nullptr;
647 for (int32_t i
= 0; i
< numStackNodes
; i
++) {
648 MOZ_ASSERT(stackNodes
[i
]->isUnused());
649 delete stackNodes
[i
];
653 stackNodes
= nullptr;
655 charBuffer
= nullptr;
659 void nsHtml5TreeBuilder::startTag(nsHtml5ElementName
* elementName
,
660 nsHtml5HtmlAttributes
* attributes
,
664 needToDropLF
= false;
667 int32_t group
= elementName
->getGroup();
668 nsAtom
* name
= elementName
->getName();
670 nsHtml5StackNode
* currentNode
= stack
[currentPtr
];
671 int32_t currNs
= currentNode
->ns
;
672 if (!(currentNode
->isHtmlIntegrationPoint() ||
673 (currNs
== kNameSpaceID_MathML
&&
674 ((currentNode
->getGroup() == MI_MO_MN_MS_MTEXT
&&
675 group
!= MGLYPH_OR_MALIGNMARK
) ||
676 (currentNode
->getGroup() == ANNOTATION_XML
&& group
== SVG
))))) {
678 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U
:
679 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU
:
682 case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR
:
687 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
:
697 if (!(group
== FONT
&&
698 !(attributes
->contains(nsHtml5AttributeName::ATTR_COLOR
) ||
699 attributes
->contains(nsHtml5AttributeName::ATTR_FACE
) ||
700 attributes
->contains(nsHtml5AttributeName::ATTR_SIZE
)))) {
701 errHtmlStartTagInForeignContext(name
);
703 while (!isSpecialParentInForeign(stack
[currentPtr
])) {
706 NS_HTML5_CONTINUE(starttagloop
);
712 if (kNameSpaceID_SVG
== currNs
) {
713 attributes
->adjustForSvg();
715 appendVoidElementToCurrentMayFosterSVG(elementName
, attributes
);
718 appendToCurrentNodeAndPushElementMayFosterSVG(elementName
,
721 attributes
= nullptr;
722 NS_HTML5_BREAK(starttagloop
);
724 attributes
->adjustForMath();
726 appendVoidElementToCurrentMayFosterMathML(elementName
,
730 appendToCurrentNodeAndPushElementMayFosterMathML(elementName
,
733 attributes
= nullptr;
734 NS_HTML5_BREAK(starttagloop
);
745 pushTemplateMode(IN_COLUMN_GROUP
);
746 mode
= IN_COLUMN_GROUP
;
751 case TBODY_OR_THEAD_OR_TFOOT
: {
753 pushTemplateMode(IN_TABLE
);
759 pushTemplateMode(IN_TABLE_BODY
);
760 mode
= IN_TABLE_BODY
;
765 pushTemplateMode(IN_ROW
);
770 checkMetaCharset(attributes
);
771 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
773 attributes
= nullptr;
774 NS_HTML5_BREAK(starttagloop
);
777 startTagTitleInHead(elementName
, attributes
);
778 attributes
= nullptr;
779 NS_HTML5_BREAK(starttagloop
);
782 case LINK_OR_BASEFONT_OR_BGSOUND
: {
783 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
785 attributes
= nullptr;
786 NS_HTML5_BREAK(starttagloop
);
789 startTagScriptInHead(elementName
, attributes
);
790 attributes
= nullptr;
791 NS_HTML5_BREAK(starttagloop
);
795 startTagGenericRawText(elementName
, attributes
);
796 attributes
= nullptr;
797 NS_HTML5_BREAK(starttagloop
);
800 startTagTemplateInHead(elementName
, attributes
);
801 attributes
= nullptr;
802 NS_HTML5_BREAK(starttagloop
);
806 pushTemplateMode(IN_BODY
);
815 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TR
));
816 appendToCurrentNodeAndPushElement(elementName
, attributes
);
819 attributes
= nullptr;
820 NS_HTML5_BREAK(starttagloop
);
825 case TBODY_OR_THEAD_OR_TFOOT
:
827 eltPos
= findLastOrRoot(nsHtml5TreeBuilder::TR
);
829 MOZ_ASSERT(fragment
|| isTemplateContents());
830 errNoTableRowToClose();
831 NS_HTML5_BREAK(starttagloop
);
833 clearStackBackTo(eltPos
);
835 mode
= IN_TABLE_BODY
;
838 default:; // fall through
842 case IN_TABLE_BODY
: {
846 findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
847 appendToCurrentNodeAndPushElement(elementName
, attributes
);
849 attributes
= nullptr;
850 NS_HTML5_BREAK(starttagloop
);
853 errStartTagInTableBody(name
);
855 findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
856 appendToCurrentNodeAndPushElement(
857 nsHtml5ElementName::ELT_TR
,
858 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
865 case TBODY_OR_THEAD_OR_TFOOT
: {
866 eltPos
= findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
867 if (!eltPos
|| stack
[eltPos
]->getGroup() == TEMPLATE
) {
868 MOZ_ASSERT(fragment
|| isTemplateContents());
869 errStrayStartTag(name
);
870 NS_HTML5_BREAK(starttagloop
);
872 clearStackBackTo(eltPos
);
878 default:; // fall through
886 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
888 appendToCurrentNodeAndPushElement(elementName
, attributes
);
890 attributes
= nullptr;
891 NS_HTML5_BREAK(starttagloop
);
894 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
895 appendToCurrentNodeAndPushElement(elementName
, attributes
);
896 mode
= IN_COLUMN_GROUP
;
897 attributes
= nullptr;
898 NS_HTML5_BREAK(starttagloop
);
901 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
902 appendToCurrentNodeAndPushElement(
903 nsHtml5ElementName::ELT_COLGROUP
,
904 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
905 mode
= IN_COLUMN_GROUP
;
906 NS_HTML5_CONTINUE(starttagloop
);
908 case TBODY_OR_THEAD_OR_TFOOT
: {
909 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
910 appendToCurrentNodeAndPushElement(elementName
, attributes
);
911 mode
= IN_TABLE_BODY
;
912 attributes
= nullptr;
913 NS_HTML5_BREAK(starttagloop
);
917 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
918 appendToCurrentNodeAndPushElement(
919 nsHtml5ElementName::ELT_TBODY
,
920 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
921 mode
= IN_TABLE_BODY
;
922 NS_HTML5_CONTINUE(starttagloop
);
925 NS_HTML5_BREAK(intableloop
);
928 errTableSeenWhileTableOpen();
929 eltPos
= findLastInTableScope(name
);
930 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
931 MOZ_ASSERT(fragment
|| isTemplateContents());
932 NS_HTML5_BREAK(starttagloop
);
934 generateImpliedEndTags();
935 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(nsGkAtoms::table
)) {
936 errNoCheckUnclosedElementsOnStack();
938 while (currentPtr
>= eltPos
) {
941 resetTheInsertionMode();
942 NS_HTML5_CONTINUE(starttagloop
);
945 appendToCurrentNodeAndPushElement(elementName
, attributes
);
948 tokenizer
->setStateAndEndTagExpectation(
949 nsHtml5Tokenizer::SCRIPT_DATA
, elementName
);
950 attributes
= nullptr;
951 NS_HTML5_BREAK(starttagloop
);
954 appendToCurrentNodeAndPushElement(elementName
, attributes
);
957 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
959 attributes
= nullptr;
960 NS_HTML5_BREAK(starttagloop
);
963 errStartTagInTable(name
);
964 if (!nsHtml5Portability::
965 lowerCaseLiteralEqualsIgnoreAsciiCaseString(
966 "hidden", attributes
->getValue(
967 nsHtml5AttributeName::ATTR_TYPE
))) {
968 NS_HTML5_BREAK(intableloop
);
970 appendVoidInputToCurrent(attributes
, formPointer
);
972 attributes
= nullptr;
973 NS_HTML5_BREAK(starttagloop
);
976 if (!!formPointer
|| isTemplateContents()) {
977 errFormWhenFormOpen();
978 NS_HTML5_BREAK(starttagloop
);
980 errStartTagInTable(name
);
981 appendVoidFormToCurrent(attributes
);
982 attributes
= nullptr;
983 NS_HTML5_BREAK(starttagloop
);
987 errStartTagInTable(name
);
988 NS_HTML5_BREAK(intableloop
);
1000 case TBODY_OR_THEAD_OR_TFOOT
:
1003 eltPos
= findLastInTableScope(nsGkAtoms::caption
);
1004 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1005 MOZ_ASSERT(fragment
|| isTemplateContents());
1006 errStrayStartTag(name
);
1007 NS_HTML5_BREAK(starttagloop
);
1009 generateImpliedEndTags();
1010 if (!!MOZ_UNLIKELY(mViewSource
) && currentPtr
!= eltPos
) {
1011 errNoCheckUnclosedElementsOnStack();
1013 while (currentPtr
>= eltPos
) {
1016 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
1020 default:; // fall through
1029 case TBODY_OR_THEAD_OR_TFOOT
:
1032 eltPos
= findLastInTableScopeTdTh();
1033 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1035 NS_HTML5_BREAK(starttagloop
);
1037 closeTheCell(eltPos
);
1041 default:; // fall through
1048 if (mode
== FRAMESET_OK
) {
1049 if (!currentPtr
|| stack
[1]->getGroup() != BODY
) {
1050 MOZ_ASSERT(fragment
|| isTemplateContents());
1051 errStrayStartTag(name
);
1052 NS_HTML5_BREAK(starttagloop
);
1055 detachFromParent(stack
[1]->node
);
1056 while (currentPtr
> 0) {
1059 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1061 attributes
= nullptr;
1062 NS_HTML5_BREAK(starttagloop
);
1065 errStrayStartTag(name
);
1066 NS_HTML5_BREAK(starttagloop
);
1069 case PRE_OR_LISTING
:
1073 case MARQUEE_OR_APPLET
:
1087 if (mode
== FRAMESET_OK
&&
1089 nsHtml5Portability::
1090 lowerCaseLiteralEqualsIgnoreAsciiCaseString(
1091 "hidden", attributes
->getValue(
1092 nsHtml5AttributeName::ATTR_TYPE
)))) {
1098 default:; // fall through
1106 errStrayStartTag(name
);
1107 if (!fragment
&& !isTemplateContents()) {
1108 addAttributesToHtml(attributes
);
1109 attributes
= nullptr;
1111 NS_HTML5_BREAK(starttagloop
);
1114 case LINK_OR_BASEFONT_OR_BGSOUND
:
1120 NS_HTML5_BREAK(inbodyloop
);
1123 if (!currentPtr
|| stack
[1]->getGroup() != BODY
||
1124 isTemplateContents()) {
1125 MOZ_ASSERT(fragment
|| isTemplateContents());
1126 errStrayStartTag(name
);
1127 NS_HTML5_BREAK(starttagloop
);
1129 errFooSeenWhenFooOpen(name
);
1131 if (mode
== FRAMESET_OK
) {
1134 if (addAttributesToBody(attributes
)) {
1135 attributes
= nullptr;
1137 NS_HTML5_BREAK(starttagloop
);
1140 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU
:
1141 case UL_OR_OL_OR_DL
:
1142 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_SEARCH_OR_SECTION_OR_SUMMARY
: {
1144 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1146 attributes
= nullptr;
1147 NS_HTML5_BREAK(starttagloop
);
1149 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
: {
1151 if (stack
[currentPtr
]->getGroup() ==
1152 H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
) {
1153 errHeadingWhenHeadingOpen();
1156 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1158 attributes
= nullptr;
1159 NS_HTML5_BREAK(starttagloop
);
1163 appendToCurrentNodeAndPushElementMayFoster(
1164 elementName
, attributes
, formPointer
);
1165 attributes
= nullptr;
1166 NS_HTML5_BREAK(starttagloop
);
1168 case PRE_OR_LISTING
: {
1170 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1172 needToDropLF
= true;
1173 attributes
= nullptr;
1174 NS_HTML5_BREAK(starttagloop
);
1177 if (!!formPointer
&& !isTemplateContents()) {
1178 errFormWhenFormOpen();
1179 NS_HTML5_BREAK(starttagloop
);
1182 appendToCurrentNodeAndPushFormElementMayFoster(attributes
);
1183 attributes
= nullptr;
1184 NS_HTML5_BREAK(starttagloop
);
1189 eltPos
= currentPtr
;
1191 nsHtml5StackNode
* node
= stack
[eltPos
];
1192 if (node
->getGroup() == group
) {
1193 generateImpliedEndTagsExceptFor(node
->name
);
1194 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
1195 errUnclosedElementsImplied(eltPos
, name
);
1197 while (currentPtr
>= eltPos
) {
1201 } else if (!eltPos
|| (node
->isSpecial() &&
1202 (node
->ns
!= kNameSpaceID_XHTML
||
1203 (node
->name
!= nsGkAtoms::p
&&
1204 node
->name
!= nsGkAtoms::address
&&
1205 node
->name
!= nsGkAtoms::div
)))) {
1211 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1213 attributes
= nullptr;
1214 NS_HTML5_BREAK(starttagloop
);
1218 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1220 tokenizer
->setStateAndEndTagExpectation(
1221 nsHtml5Tokenizer::PLAINTEXT
, elementName
);
1222 attributes
= nullptr;
1223 NS_HTML5_BREAK(starttagloop
);
1226 int32_t activeAPos
=
1227 findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
1229 if (activeAPos
!= -1) {
1230 errFooSeenWhenFooOpen(name
);
1231 nsHtml5StackNode
* activeA
=
1232 listOfActiveFormattingElements
[activeAPos
];
1234 adoptionAgencyEndTag(nsGkAtoms::a
);
1235 removeFromStack(activeA
);
1236 activeAPos
= findInListOfActiveFormattingElements(activeA
);
1237 if (activeAPos
!= -1) {
1238 removeFromListOfActiveFormattingElements(activeAPos
);
1240 activeA
->release(this);
1242 reconstructTheActiveFormattingElements();
1243 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName
,
1245 attributes
= nullptr;
1246 NS_HTML5_BREAK(starttagloop
);
1248 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U
:
1250 reconstructTheActiveFormattingElements();
1251 maybeForgetEarlierDuplicateFormattingElement(
1252 elementName
->getName(), attributes
);
1253 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName
,
1255 attributes
= nullptr;
1256 NS_HTML5_BREAK(starttagloop
);
1259 reconstructTheActiveFormattingElements();
1260 if (nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
!=
1261 findLastInScope(nsGkAtoms::nobr
)) {
1262 errFooSeenWhenFooOpen(name
);
1263 adoptionAgencyEndTag(nsGkAtoms::nobr
);
1264 reconstructTheActiveFormattingElements();
1266 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName
,
1268 attributes
= nullptr;
1269 NS_HTML5_BREAK(starttagloop
);
1272 eltPos
= findLastInScope(name
);
1273 if (eltPos
!= nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1274 errFooSeenWhenFooOpen(name
);
1275 generateImpliedEndTags();
1276 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
1277 errUnclosedElementsImplied(eltPos
, name
);
1279 while (currentPtr
>= eltPos
) {
1282 NS_HTML5_CONTINUE(starttagloop
);
1284 reconstructTheActiveFormattingElements();
1285 appendToCurrentNodeAndPushElementMayFoster(
1286 elementName
, attributes
, formPointer
);
1287 attributes
= nullptr;
1288 NS_HTML5_BREAK(starttagloop
);
1292 reconstructTheActiveFormattingElements();
1293 appendToCurrentNodeAndPushElementMayFoster(
1294 elementName
, attributes
, formPointer
);
1296 attributes
= nullptr;
1297 NS_HTML5_BREAK(starttagloop
);
1299 case MARQUEE_OR_APPLET
: {
1300 reconstructTheActiveFormattingElements();
1301 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1304 attributes
= nullptr;
1305 NS_HTML5_BREAK(starttagloop
);
1311 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1314 attributes
= nullptr;
1315 NS_HTML5_BREAK(starttagloop
);
1321 reconstructTheActiveFormattingElements();
1324 case PARAM_OR_SOURCE_OR_TRACK
: {
1325 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1326 selfClosing
= false;
1327 attributes
= nullptr;
1328 NS_HTML5_BREAK(starttagloop
);
1332 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1333 selfClosing
= false;
1334 attributes
= nullptr;
1335 NS_HTML5_BREAK(starttagloop
);
1339 elementName
= nsHtml5ElementName::ELT_IMG
;
1340 NS_HTML5_CONTINUE(starttagloop
);
1344 reconstructTheActiveFormattingElements();
1345 appendVoidElementToCurrentMayFoster(elementName
, attributes
,
1347 selfClosing
= false;
1348 attributes
= nullptr;
1349 NS_HTML5_BREAK(starttagloop
);
1352 appendToCurrentNodeAndPushElementMayFoster(
1353 elementName
, attributes
, formPointer
);
1354 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA
,
1356 originalMode
= mode
;
1358 needToDropLF
= true;
1359 attributes
= nullptr;
1360 NS_HTML5_BREAK(starttagloop
);
1364 reconstructTheActiveFormattingElements();
1365 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1367 originalMode
= mode
;
1369 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
1371 attributes
= nullptr;
1372 NS_HTML5_BREAK(starttagloop
);
1375 if (!scriptingEnabled
) {
1376 reconstructTheActiveFormattingElements();
1377 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1379 attributes
= nullptr;
1380 NS_HTML5_BREAK(starttagloop
);
1387 startTagGenericRawText(elementName
, attributes
);
1388 attributes
= nullptr;
1389 NS_HTML5_BREAK(starttagloop
);
1392 reconstructTheActiveFormattingElements();
1393 appendToCurrentNodeAndPushElementMayFoster(
1394 elementName
, attributes
, formPointer
);
1398 case IN_COLUMN_GROUP
:
1402 mode
= IN_SELECT_IN_TABLE
;
1410 attributes
= nullptr;
1411 NS_HTML5_BREAK(starttagloop
);
1415 if (isCurrent(nsGkAtoms::option
)) {
1418 reconstructTheActiveFormattingElements();
1419 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1421 attributes
= nullptr;
1422 NS_HTML5_BREAK(starttagloop
);
1425 eltPos
= findLastInScope(nsGkAtoms::ruby
);
1426 if (eltPos
!= NOT_FOUND_ON_STACK
) {
1427 generateImpliedEndTags();
1429 if (eltPos
!= currentPtr
) {
1430 if (eltPos
== NOT_FOUND_ON_STACK
) {
1431 errStartTagSeenWithoutRuby(name
);
1433 errUnclosedChildrenInRuby();
1436 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1438 attributes
= nullptr;
1439 NS_HTML5_BREAK(starttagloop
);
1442 eltPos
= findLastInScope(nsGkAtoms::ruby
);
1443 if (eltPos
!= NOT_FOUND_ON_STACK
) {
1444 generateImpliedEndTagsExceptFor(nsGkAtoms::rtc
);
1446 if (eltPos
!= currentPtr
) {
1447 if (!isCurrent(nsGkAtoms::rtc
)) {
1448 if (eltPos
== NOT_FOUND_ON_STACK
) {
1449 errStartTagSeenWithoutRuby(name
);
1451 errUnclosedChildrenInRuby();
1455 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1457 attributes
= nullptr;
1458 NS_HTML5_BREAK(starttagloop
);
1461 reconstructTheActiveFormattingElements();
1462 attributes
->adjustForMath();
1464 appendVoidElementToCurrentMayFosterMathML(elementName
,
1466 selfClosing
= false;
1468 appendToCurrentNodeAndPushElementMayFosterMathML(elementName
,
1471 attributes
= nullptr;
1472 NS_HTML5_BREAK(starttagloop
);
1475 reconstructTheActiveFormattingElements();
1476 attributes
->adjustForSvg();
1478 appendVoidElementToCurrentMayFosterSVG(elementName
, attributes
);
1479 selfClosing
= false;
1481 appendToCurrentNodeAndPushElementMayFosterSVG(elementName
,
1484 attributes
= nullptr;
1485 NS_HTML5_BREAK(starttagloop
);
1490 case TBODY_OR_THEAD_OR_TFOOT
:
1496 errStrayStartTag(name
);
1497 NS_HTML5_BREAK(starttagloop
);
1500 reconstructTheActiveFormattingElements();
1501 appendToCurrentNodeAndPushElementMayFoster(
1502 elementName
, attributes
, formPointer
);
1503 attributes
= nullptr;
1504 NS_HTML5_BREAK(starttagloop
);
1507 reconstructTheActiveFormattingElements();
1508 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1510 attributes
= nullptr;
1511 NS_HTML5_BREAK(starttagloop
);
1522 errStrayStartTag(name
);
1523 if (!fragment
&& !isTemplateContents()) {
1524 addAttributesToHtml(attributes
);
1525 attributes
= nullptr;
1527 NS_HTML5_BREAK(starttagloop
);
1530 case LINK_OR_BASEFONT_OR_BGSOUND
: {
1531 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1532 selfClosing
= false;
1533 attributes
= nullptr;
1534 NS_HTML5_BREAK(starttagloop
);
1537 NS_HTML5_BREAK(inheadloop
);
1540 startTagTitleInHead(elementName
, attributes
);
1541 attributes
= nullptr;
1542 NS_HTML5_BREAK(starttagloop
);
1545 if (scriptingEnabled
) {
1546 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1547 originalMode
= mode
;
1549 tokenizer
->setStateAndEndTagExpectation(
1550 nsHtml5Tokenizer::RAWTEXT
, elementName
);
1552 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1554 mode
= IN_HEAD_NOSCRIPT
;
1556 attributes
= nullptr;
1557 NS_HTML5_BREAK(starttagloop
);
1560 startTagScriptInHead(elementName
, attributes
);
1561 attributes
= nullptr;
1562 NS_HTML5_BREAK(starttagloop
);
1566 startTagGenericRawText(elementName
, attributes
);
1567 attributes
= nullptr;
1568 NS_HTML5_BREAK(starttagloop
);
1571 errFooSeenWhenFooOpen(name
);
1572 NS_HTML5_BREAK(starttagloop
);
1575 startTagTemplateInHead(elementName
, attributes
);
1576 attributes
= nullptr;
1577 NS_HTML5_BREAK(starttagloop
);
1582 NS_HTML5_CONTINUE(starttagloop
);
1589 case IN_HEAD_NOSCRIPT
: {
1592 errStrayStartTag(name
);
1593 if (!fragment
&& !isTemplateContents()) {
1594 addAttributesToHtml(attributes
);
1595 attributes
= nullptr;
1597 NS_HTML5_BREAK(starttagloop
);
1599 case LINK_OR_BASEFONT_OR_BGSOUND
: {
1600 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1601 selfClosing
= false;
1602 attributes
= nullptr;
1603 NS_HTML5_BREAK(starttagloop
);
1606 checkMetaCharset(attributes
);
1607 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1608 selfClosing
= false;
1609 attributes
= nullptr;
1610 NS_HTML5_BREAK(starttagloop
);
1614 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1615 originalMode
= mode
;
1617 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
1619 attributes
= nullptr;
1620 NS_HTML5_BREAK(starttagloop
);
1623 errFooSeenWhenFooOpen(name
);
1624 NS_HTML5_BREAK(starttagloop
);
1627 errFooSeenWhenFooOpen(name
);
1628 NS_HTML5_BREAK(starttagloop
);
1631 errBadStartTagInNoscriptInHead(name
);
1638 case IN_COLUMN_GROUP
: {
1641 errStrayStartTag(name
);
1642 if (!fragment
&& !isTemplateContents()) {
1643 addAttributesToHtml(attributes
);
1644 attributes
= nullptr;
1646 NS_HTML5_BREAK(starttagloop
);
1649 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1650 selfClosing
= false;
1651 attributes
= nullptr;
1652 NS_HTML5_BREAK(starttagloop
);
1655 startTagTemplateInHead(elementName
, attributes
);
1656 attributes
= nullptr;
1657 NS_HTML5_BREAK(starttagloop
);
1660 if (!currentPtr
|| stack
[currentPtr
]->getGroup() == TEMPLATE
) {
1661 MOZ_ASSERT(fragment
|| isTemplateContents());
1662 errGarbageInColgroup();
1663 NS_HTML5_BREAK(starttagloop
);
1671 case IN_SELECT_IN_TABLE
: {
1674 case TBODY_OR_THEAD_OR_TFOOT
:
1678 errStartTagWithSelectOpen(name
);
1679 eltPos
= findLastInTableScope(nsGkAtoms::select
);
1680 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1681 MOZ_ASSERT(fragment
);
1682 NS_HTML5_BREAK(starttagloop
);
1684 while (currentPtr
>= eltPos
) {
1687 resetTheInsertionMode();
1690 default:; // fall through
1697 errStrayStartTag(name
);
1699 addAttributesToHtml(attributes
);
1700 attributes
= nullptr;
1702 NS_HTML5_BREAK(starttagloop
);
1705 if (isCurrent(nsGkAtoms::option
)) {
1708 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1709 attributes
= nullptr;
1710 NS_HTML5_BREAK(starttagloop
);
1713 if (isCurrent(nsGkAtoms::option
)) {
1716 if (isCurrent(nsGkAtoms::optgroup
)) {
1719 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1720 attributes
= nullptr;
1721 NS_HTML5_BREAK(starttagloop
);
1724 errStartSelectWhereEndSelectExpected();
1725 eltPos
= findLastInTableScope(name
);
1726 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1727 MOZ_ASSERT(fragment
);
1728 errNoSelectInTableScope();
1729 NS_HTML5_BREAK(starttagloop
);
1731 while (currentPtr
>= eltPos
) {
1734 resetTheInsertionMode();
1735 NS_HTML5_BREAK(starttagloop
);
1740 errStartTagWithSelectOpen(name
);
1741 eltPos
= findLastInTableScope(nsGkAtoms::select
);
1742 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1743 MOZ_ASSERT(fragment
);
1744 NS_HTML5_BREAK(starttagloop
);
1746 while (currentPtr
>= eltPos
) {
1749 resetTheInsertionMode();
1753 startTagScriptInHead(elementName
, attributes
);
1754 attributes
= nullptr;
1755 NS_HTML5_BREAK(starttagloop
);
1758 startTagTemplateInHead(elementName
, attributes
);
1759 attributes
= nullptr;
1760 NS_HTML5_BREAK(starttagloop
);
1763 errStrayStartTag(name
);
1764 NS_HTML5_BREAK(starttagloop
);
1771 errStrayStartTag(name
);
1772 if (!fragment
&& !isTemplateContents()) {
1773 addAttributesToHtml(attributes
);
1774 attributes
= nullptr;
1776 NS_HTML5_BREAK(starttagloop
);
1779 errStrayStartTag(name
);
1780 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
1788 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1789 attributes
= nullptr;
1790 NS_HTML5_BREAK(starttagloop
);
1793 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1794 selfClosing
= false;
1795 attributes
= nullptr;
1796 NS_HTML5_BREAK(starttagloop
);
1798 default:; // fall through
1802 case AFTER_FRAMESET
: {
1805 errStrayStartTag(name
);
1806 if (!fragment
&& !isTemplateContents()) {
1807 addAttributesToHtml(attributes
);
1808 attributes
= nullptr;
1810 NS_HTML5_BREAK(starttagloop
);
1813 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1814 originalMode
= mode
;
1816 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
1818 attributes
= nullptr;
1819 NS_HTML5_BREAK(starttagloop
);
1822 errStrayStartTag(name
);
1823 NS_HTML5_BREAK(starttagloop
);
1828 errStartTagWithoutDoctype();
1829 documentModeInternal(QUIRKS_MODE
, nullptr, nullptr);
1836 if (attributes
== nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
) {
1837 appendHtmlElementToDocumentAndPush();
1839 appendHtmlElementToDocumentAndPush(attributes
);
1842 attributes
= nullptr;
1843 NS_HTML5_BREAK(starttagloop
);
1846 appendHtmlElementToDocumentAndPush();
1855 errStrayStartTag(name
);
1856 if (!fragment
&& !isTemplateContents()) {
1857 addAttributesToHtml(attributes
);
1858 attributes
= nullptr;
1860 NS_HTML5_BREAK(starttagloop
);
1863 appendToCurrentNodeAndPushHeadElement(attributes
);
1865 attributes
= nullptr;
1866 NS_HTML5_BREAK(starttagloop
);
1869 appendToCurrentNodeAndPushHeadElement(
1870 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
1879 errStrayStartTag(name
);
1880 if (!fragment
&& !isTemplateContents()) {
1881 addAttributesToHtml(attributes
);
1882 attributes
= nullptr;
1884 NS_HTML5_BREAK(starttagloop
);
1887 if (!attributes
->getLength()) {
1888 appendToCurrentNodeAndPushBodyElement();
1890 appendToCurrentNodeAndPushBodyElement(attributes
);
1894 attributes
= nullptr;
1895 NS_HTML5_BREAK(starttagloop
);
1898 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1900 attributes
= nullptr;
1901 NS_HTML5_BREAK(starttagloop
);
1904 errFooBetweenHeadAndBody(name
);
1905 pushHeadPointerOntoStack();
1906 nsHtml5StackNode
* headOnStack
= stack
[currentPtr
];
1907 startTagTemplateInHead(elementName
, attributes
);
1908 removeFromStack(headOnStack
);
1909 attributes
= nullptr;
1910 NS_HTML5_BREAK(starttagloop
);
1913 case LINK_OR_BASEFONT_OR_BGSOUND
: {
1914 errFooBetweenHeadAndBody(name
);
1915 pushHeadPointerOntoStack();
1916 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1917 selfClosing
= false;
1919 attributes
= nullptr;
1920 NS_HTML5_BREAK(starttagloop
);
1923 errFooBetweenHeadAndBody(name
);
1924 checkMetaCharset(attributes
);
1925 pushHeadPointerOntoStack();
1926 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1927 selfClosing
= false;
1929 attributes
= nullptr;
1930 NS_HTML5_BREAK(starttagloop
);
1933 errFooBetweenHeadAndBody(name
);
1934 pushHeadPointerOntoStack();
1935 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1936 originalMode
= mode
;
1938 tokenizer
->setStateAndEndTagExpectation(
1939 nsHtml5Tokenizer::SCRIPT_DATA
, elementName
);
1940 attributes
= nullptr;
1941 NS_HTML5_BREAK(starttagloop
);
1945 errFooBetweenHeadAndBody(name
);
1946 pushHeadPointerOntoStack();
1947 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1948 originalMode
= mode
;
1950 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
1952 attributes
= nullptr;
1953 NS_HTML5_BREAK(starttagloop
);
1956 errFooBetweenHeadAndBody(name
);
1957 pushHeadPointerOntoStack();
1958 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1959 originalMode
= mode
;
1961 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA
,
1963 attributes
= nullptr;
1964 NS_HTML5_BREAK(starttagloop
);
1967 errStrayStartTag(name
);
1968 NS_HTML5_BREAK(starttagloop
);
1971 appendToCurrentNodeAndPushBodyElement();
1977 case AFTER_AFTER_BODY
: {
1980 errStrayStartTag(name
);
1981 if (!fragment
&& !isTemplateContents()) {
1982 addAttributesToHtml(attributes
);
1983 attributes
= nullptr;
1985 NS_HTML5_BREAK(starttagloop
);
1988 errStrayStartTag(name
);
1990 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
1995 case AFTER_AFTER_FRAMESET
: {
1998 errStrayStartTag(name
);
1999 if (!fragment
&& !isTemplateContents()) {
2000 addAttributesToHtml(attributes
);
2001 attributes
= nullptr;
2003 NS_HTML5_BREAK(starttagloop
);
2006 startTagGenericRawText(elementName
, attributes
);
2007 attributes
= nullptr;
2008 NS_HTML5_BREAK(starttagloop
);
2011 errStrayStartTag(name
);
2012 NS_HTML5_BREAK(starttagloop
);
2018 NS_HTML5_BREAK(starttagloop
);
2026 if (!mBuilder
&& attributes
!= nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
) {
2031 void nsHtml5TreeBuilder::startTagTitleInHead(
2032 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
2033 appendToCurrentNodeAndPushElementMayFoster(elementName
, attributes
);
2034 originalMode
= mode
;
2036 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA
,
2040 void nsHtml5TreeBuilder::startTagGenericRawText(
2041 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
2042 appendToCurrentNodeAndPushElementMayFoster(elementName
, attributes
);
2043 originalMode
= mode
;
2045 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
2049 void nsHtml5TreeBuilder::startTagScriptInHead(
2050 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
2051 appendToCurrentNodeAndPushElementMayFoster(elementName
, attributes
);
2052 originalMode
= mode
;
2054 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::SCRIPT_DATA
,
2058 void nsHtml5TreeBuilder::startTagTemplateInHead(
2059 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
2060 appendToCurrentNodeAndPushElement(elementName
, attributes
);
2063 originalMode
= mode
;
2065 pushTemplateMode(IN_TEMPLATE
);
2068 bool nsHtml5TreeBuilder::isTemplateContents() {
2069 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
!=
2070 findLast(nsGkAtoms::_template
);
2073 bool nsHtml5TreeBuilder::isTemplateModeStackEmpty() {
2074 return templateModePtr
== -1;
2077 bool nsHtml5TreeBuilder::isSpecialParentInForeign(nsHtml5StackNode
* stackNode
) {
2078 int32_t ns
= stackNode
->ns
;
2079 return (kNameSpaceID_XHTML
== ns
) || (stackNode
->isHtmlIntegrationPoint()) ||
2080 ((kNameSpaceID_MathML
== ns
) &&
2081 (stackNode
->getGroup() == MI_MO_MN_MS_MTEXT
));
2084 nsHtml5String
nsHtml5TreeBuilder::extractCharsetFromContent(
2085 nsHtml5String attributeValue
, nsHtml5TreeBuilder
* tb
) {
2086 int32_t charsetState
= CHARSET_INITIAL
;
2089 autoJArray
<char16_t
, int32_t> buffer
=
2090 nsHtml5Portability::newCharArrayFromString(attributeValue
);
2091 for (int32_t i
= 0; i
< buffer
.length
; i
++) {
2092 char16_t c
= buffer
[i
];
2093 switch (charsetState
) {
2094 case CHARSET_INITIAL
: {
2098 charsetState
= CHARSET_C
;
2110 charsetState
= CHARSET_H
;
2114 charsetState
= CHARSET_INITIAL
;
2123 charsetState
= CHARSET_A
;
2127 charsetState
= CHARSET_INITIAL
;
2136 charsetState
= CHARSET_R
;
2140 charsetState
= CHARSET_INITIAL
;
2149 charsetState
= CHARSET_S
;
2153 charsetState
= CHARSET_INITIAL
;
2162 charsetState
= CHARSET_E
;
2166 charsetState
= CHARSET_INITIAL
;
2175 charsetState
= CHARSET_T
;
2179 charsetState
= CHARSET_INITIAL
;
2194 charsetState
= CHARSET_EQUALS
;
2202 case CHARSET_EQUALS
: {
2213 charsetState
= CHARSET_SINGLE_QUOTED
;
2218 charsetState
= CHARSET_DOUBLE_QUOTED
;
2223 charsetState
= CHARSET_UNQUOTED
;
2228 case CHARSET_SINGLE_QUOTED
: {
2232 NS_HTML5_BREAK(charsetloop
);
2239 case CHARSET_DOUBLE_QUOTED
: {
2243 NS_HTML5_BREAK(charsetloop
);
2250 case CHARSET_UNQUOTED
: {
2259 NS_HTML5_BREAK(charsetloop
);
2271 if (charsetState
== CHARSET_UNQUOTED
) {
2272 end
= buffer
.length
;
2277 return nsHtml5Portability::newStringFromBuffer(buffer
, start
, end
- start
,
2283 void nsHtml5TreeBuilder::checkMetaCharset(nsHtml5HtmlAttributes
* attributes
) {
2284 nsHtml5String charset
=
2285 attributes
->getValue(nsHtml5AttributeName::ATTR_CHARSET
);
2287 if (tokenizer
->internalEncodingDeclaration(charset
)) {
2288 requestSuspension();
2293 if (!nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
2295 attributes
->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV
))) {
2298 nsHtml5String content
=
2299 attributes
->getValue(nsHtml5AttributeName::ATTR_CONTENT
);
2301 nsHtml5String extract
=
2302 nsHtml5TreeBuilder::extractCharsetFromContent(content
, this);
2304 if (tokenizer
->internalEncodingDeclaration(extract
)) {
2305 requestSuspension();
2312 void nsHtml5TreeBuilder::endTag(nsHtml5ElementName
* elementName
) {
2314 needToDropLF
= false;
2316 int32_t group
= elementName
->getGroup();
2317 nsAtom
* name
= elementName
->getName();
2319 if (isInForeign()) {
2320 if (stack
[currentPtr
]->name
!= name
) {
2322 errStrayEndTag(name
);
2324 errEndTagDidNotMatchCurrentOpenElement(name
,
2325 stack
[currentPtr
]->popName
);
2328 eltPos
= currentPtr
;
2329 int32_t origPos
= currentPtr
;
2332 MOZ_ASSERT(fragment
,
2333 "We can get this close to the root of the stack in "
2334 "foreign content only in the fragment case.");
2335 NS_HTML5_BREAK(endtagloop
);
2337 if (stack
[eltPos
]->name
== name
) {
2338 while (currentPtr
>= eltPos
) {
2339 popForeign(origPos
, eltPos
);
2341 NS_HTML5_BREAK(endtagloop
);
2343 if (stack
[--eltPos
]->ns
== kNameSpaceID_XHTML
) {
2355 errStrayEndTag(name
);
2356 NS_HTML5_BREAK(endtagloop
);
2364 eltPos
= findLastOrRoot(nsHtml5TreeBuilder::TR
);
2366 MOZ_ASSERT(fragment
|| isTemplateContents());
2367 errNoTableRowToClose();
2368 NS_HTML5_BREAK(endtagloop
);
2370 clearStackBackTo(eltPos
);
2372 mode
= IN_TABLE_BODY
;
2373 NS_HTML5_BREAK(endtagloop
);
2376 eltPos
= findLastOrRoot(nsHtml5TreeBuilder::TR
);
2378 MOZ_ASSERT(fragment
|| isTemplateContents());
2379 errNoTableRowToClose();
2380 NS_HTML5_BREAK(endtagloop
);
2382 clearStackBackTo(eltPos
);
2384 mode
= IN_TABLE_BODY
;
2387 case TBODY_OR_THEAD_OR_TFOOT
: {
2388 if (findLastInTableScope(name
) ==
2389 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2390 errStrayEndTag(name
);
2391 NS_HTML5_BREAK(endtagloop
);
2393 eltPos
= findLastOrRoot(nsHtml5TreeBuilder::TR
);
2395 MOZ_ASSERT(fragment
|| isTemplateContents());
2396 errNoTableRowToClose();
2397 NS_HTML5_BREAK(endtagloop
);
2399 clearStackBackTo(eltPos
);
2401 mode
= IN_TABLE_BODY
;
2410 errStrayEndTag(name
);
2411 NS_HTML5_BREAK(endtagloop
);
2413 default:; // fall through
2417 case IN_TABLE_BODY
: {
2419 case TBODY_OR_THEAD_OR_TFOOT
: {
2420 eltPos
= findLastOrRoot(name
);
2422 errStrayEndTag(name
);
2423 NS_HTML5_BREAK(endtagloop
);
2425 clearStackBackTo(eltPos
);
2428 NS_HTML5_BREAK(endtagloop
);
2431 eltPos
= findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
2432 if (!eltPos
|| stack
[eltPos
]->getGroup() == TEMPLATE
) {
2433 MOZ_ASSERT(fragment
|| isTemplateContents());
2434 errStrayEndTag(name
);
2435 NS_HTML5_BREAK(endtagloop
);
2437 clearStackBackTo(eltPos
);
2449 errStrayEndTag(name
);
2450 NS_HTML5_BREAK(endtagloop
);
2452 default:; // fall through
2459 eltPos
= findLast(nsGkAtoms::table
);
2460 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2461 MOZ_ASSERT(fragment
|| isTemplateContents());
2462 errStrayEndTag(name
);
2463 NS_HTML5_BREAK(endtagloop
);
2465 while (currentPtr
>= eltPos
) {
2468 resetTheInsertionMode();
2469 NS_HTML5_BREAK(endtagloop
);
2476 case TBODY_OR_THEAD_OR_TFOOT
:
2479 errStrayEndTag(name
);
2480 NS_HTML5_BREAK(endtagloop
);
2486 errStrayEndTag(name
);
2494 eltPos
= findLastInTableScope(nsGkAtoms::caption
);
2495 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2496 NS_HTML5_BREAK(endtagloop
);
2498 generateImpliedEndTags();
2499 if (!!MOZ_UNLIKELY(mViewSource
) && currentPtr
!= eltPos
) {
2500 errUnclosedElements(eltPos
, name
);
2502 while (currentPtr
>= eltPos
) {
2505 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2507 NS_HTML5_BREAK(endtagloop
);
2510 eltPos
= findLastInTableScope(nsGkAtoms::caption
);
2511 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2512 MOZ_ASSERT(fragment
|| isTemplateContents());
2513 errStrayEndTag(name
);
2514 NS_HTML5_BREAK(endtagloop
);
2516 generateImpliedEndTags();
2517 if (!!MOZ_UNLIKELY(mViewSource
) && currentPtr
!= eltPos
) {
2518 errUnclosedElements(eltPos
, name
);
2520 while (currentPtr
>= eltPos
) {
2523 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2531 case TBODY_OR_THEAD_OR_TFOOT
:
2534 errStrayEndTag(name
);
2535 NS_HTML5_BREAK(endtagloop
);
2537 default:; // fall through
2544 eltPos
= findLastInTableScope(name
);
2545 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2546 errStrayEndTag(name
);
2547 NS_HTML5_BREAK(endtagloop
);
2549 generateImpliedEndTags();
2550 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2551 errUnclosedElements(eltPos
, name
);
2553 while (currentPtr
>= eltPos
) {
2556 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2558 NS_HTML5_BREAK(endtagloop
);
2561 case TBODY_OR_THEAD_OR_TFOOT
:
2563 if (findLastInTableScope(name
) ==
2564 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2565 MOZ_ASSERT(name
== nsGkAtoms::tbody
|| name
== nsGkAtoms::tfoot
||
2566 name
== nsGkAtoms::thead
|| fragment
||
2567 isTemplateContents());
2568 errStrayEndTag(name
);
2569 NS_HTML5_BREAK(endtagloop
);
2571 closeTheCell(findLastInTableScopeTdTh());
2579 errStrayEndTag(name
);
2580 NS_HTML5_BREAK(endtagloop
);
2582 default:; // fall through
2590 if (!isSecondOnStackBody()) {
2591 MOZ_ASSERT(fragment
|| isTemplateContents());
2592 errStrayEndTag(name
);
2593 NS_HTML5_BREAK(endtagloop
);
2595 MOZ_ASSERT(currentPtr
>= 1);
2596 if (MOZ_UNLIKELY(mViewSource
)) {
2597 for (int32_t i
= 2; i
<= currentPtr
; i
++) {
2598 switch (stack
[i
]->getGroup()) {
2607 case TBODY_OR_THEAD_OR_TFOOT
: {
2611 errEndWithUnclosedElements(name
);
2612 NS_HTML5_BREAK(uncloseloop1
);
2619 NS_HTML5_BREAK(endtagloop
);
2622 if (!isSecondOnStackBody()) {
2623 MOZ_ASSERT(fragment
|| isTemplateContents());
2624 errStrayEndTag(name
);
2625 NS_HTML5_BREAK(endtagloop
);
2627 if (MOZ_UNLIKELY(mViewSource
)) {
2628 for (int32_t i
= 0; i
<= currentPtr
; i
++) {
2629 switch (stack
[i
]->getGroup()) {
2635 case TBODY_OR_THEAD_OR_TFOOT
:
2642 errEndWithUnclosedElements(name
);
2643 NS_HTML5_BREAK(uncloseloop2
);
2652 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU
:
2653 case UL_OR_OL_OR_DL
:
2654 case PRE_OR_LISTING
:
2657 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_SEARCH_OR_SECTION_OR_SUMMARY
: {
2658 eltPos
= findLastInScope(name
);
2659 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2660 errStrayEndTag(name
);
2662 generateImpliedEndTags();
2663 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2664 errUnclosedElements(eltPos
, name
);
2666 while (currentPtr
>= eltPos
) {
2670 NS_HTML5_BREAK(endtagloop
);
2673 if (!isTemplateContents()) {
2675 errStrayEndTag(name
);
2676 NS_HTML5_BREAK(endtagloop
);
2678 formPointer
= nullptr;
2679 eltPos
= findLastInScope(name
);
2680 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2681 errStrayEndTag(name
);
2682 NS_HTML5_BREAK(endtagloop
);
2684 generateImpliedEndTags();
2685 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2686 errUnclosedElements(eltPos
, name
);
2688 removeFromStack(eltPos
);
2689 NS_HTML5_BREAK(endtagloop
);
2691 eltPos
= findLastInScope(name
);
2692 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2693 errStrayEndTag(name
);
2694 NS_HTML5_BREAK(endtagloop
);
2696 generateImpliedEndTags();
2697 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2698 errUnclosedElements(eltPos
, name
);
2700 while (currentPtr
>= eltPos
) {
2703 NS_HTML5_BREAK(endtagloop
);
2707 eltPos
= findLastInButtonScope(nsGkAtoms::p
);
2708 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2709 errNoElementToCloseButEndTagSeen(nsGkAtoms::p
);
2710 if (isInForeign()) {
2711 errHtmlStartTagInForeignContext(name
);
2712 while (currentPtr
>= 0 &&
2713 stack
[currentPtr
]->ns
!= kNameSpaceID_XHTML
) {
2717 appendVoidElementToCurrentMayFoster(
2718 elementName
, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
2719 NS_HTML5_BREAK(endtagloop
);
2721 generateImpliedEndTagsExceptFor(nsGkAtoms::p
);
2722 MOZ_ASSERT(eltPos
!= nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
);
2723 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
2724 errUnclosedElements(eltPos
, name
);
2726 while (currentPtr
>= eltPos
) {
2729 NS_HTML5_BREAK(endtagloop
);
2732 eltPos
= findLastInListScope(name
);
2733 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2734 errNoElementToCloseButEndTagSeen(name
);
2736 generateImpliedEndTagsExceptFor(name
);
2737 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
2738 errUnclosedElements(eltPos
, name
);
2740 while (currentPtr
>= eltPos
) {
2744 NS_HTML5_BREAK(endtagloop
);
2747 eltPos
= findLastInScope(name
);
2748 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2749 errNoElementToCloseButEndTagSeen(name
);
2751 generateImpliedEndTagsExceptFor(name
);
2752 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
2753 errUnclosedElements(eltPos
, name
);
2755 while (currentPtr
>= eltPos
) {
2759 NS_HTML5_BREAK(endtagloop
);
2761 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
: {
2762 eltPos
= findLastInScopeHn();
2763 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2764 errStrayEndTag(name
);
2766 generateImpliedEndTags();
2767 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2768 errUnclosedElements(eltPos
, name
);
2770 while (currentPtr
>= eltPos
) {
2774 NS_HTML5_BREAK(endtagloop
);
2777 case MARQUEE_OR_APPLET
: {
2778 eltPos
= findLastInScope(name
);
2779 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2780 errStrayEndTag(name
);
2782 generateImpliedEndTags();
2783 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2784 errUnclosedElements(eltPos
, name
);
2786 while (currentPtr
>= eltPos
) {
2789 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2791 NS_HTML5_BREAK(endtagloop
);
2795 if (isInForeign()) {
2796 errHtmlStartTagInForeignContext(name
);
2797 while (currentPtr
>= 0 &&
2798 stack
[currentPtr
]->ns
!= kNameSpaceID_XHTML
) {
2802 reconstructTheActiveFormattingElements();
2803 appendVoidElementToCurrentMayFoster(
2804 elementName
, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
2805 NS_HTML5_BREAK(endtagloop
);
2812 case PARAM_OR_SOURCE_OR_TRACK
:
2824 errStrayEndTag(name
);
2825 NS_HTML5_BREAK(endtagloop
);
2828 if (scriptingEnabled
) {
2829 errStrayEndTag(name
);
2830 NS_HTML5_BREAK(endtagloop
);
2835 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U
:
2838 if (adoptionAgencyEndTag(name
)) {
2839 NS_HTML5_BREAK(endtagloop
);
2844 if (isCurrent(name
)) {
2846 NS_HTML5_BREAK(endtagloop
);
2848 eltPos
= currentPtr
;
2850 nsHtml5StackNode
* node
= stack
[eltPos
];
2851 if (node
->ns
== kNameSpaceID_XHTML
&& node
->name
== name
) {
2852 generateImpliedEndTags();
2853 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2854 errUnclosedElements(eltPos
, name
);
2856 while (currentPtr
>= eltPos
) {
2859 NS_HTML5_BREAK(endtagloop
);
2860 } else if (!eltPos
|| node
->isSpecial()) {
2861 errStrayEndTag(name
);
2862 NS_HTML5_BREAK(endtagloop
);
2875 NS_HTML5_BREAK(endtagloop
);
2885 endTagTemplateInHead();
2886 NS_HTML5_BREAK(endtagloop
);
2889 errStrayEndTag(name
);
2890 NS_HTML5_BREAK(endtagloop
);
2894 case IN_HEAD_NOSCRIPT
: {
2899 NS_HTML5_BREAK(endtagloop
);
2902 errStrayEndTag(name
);
2908 errStrayEndTag(name
);
2909 NS_HTML5_BREAK(endtagloop
);
2913 case IN_COLUMN_GROUP
: {
2917 stack
[currentPtr
]->getGroup() == nsHtml5TreeBuilder::TEMPLATE
) {
2918 MOZ_ASSERT(fragment
|| isTemplateContents());
2919 errGarbageInColgroup();
2920 NS_HTML5_BREAK(endtagloop
);
2924 NS_HTML5_BREAK(endtagloop
);
2927 errStrayEndTag(name
);
2928 NS_HTML5_BREAK(endtagloop
);
2931 endTagTemplateInHead();
2932 NS_HTML5_BREAK(endtagloop
);
2936 stack
[currentPtr
]->getGroup() == nsHtml5TreeBuilder::TEMPLATE
) {
2937 MOZ_ASSERT(fragment
|| isTemplateContents());
2938 errGarbageInColgroup();
2939 NS_HTML5_BREAK(endtagloop
);
2947 case IN_SELECT_IN_TABLE
: {
2951 case TBODY_OR_THEAD_OR_TFOOT
:
2954 errEndTagSeenWithSelectOpen(name
);
2955 if (findLastInTableScope(name
) !=
2956 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2957 eltPos
= findLastInTableScope(nsGkAtoms::select
);
2958 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2959 MOZ_ASSERT(fragment
);
2960 NS_HTML5_BREAK(endtagloop
);
2962 while (currentPtr
>= eltPos
) {
2965 resetTheInsertionMode();
2968 NS_HTML5_BREAK(endtagloop
);
2971 default:; // fall through
2978 if (isCurrent(nsGkAtoms::option
)) {
2980 NS_HTML5_BREAK(endtagloop
);
2982 errStrayEndTag(name
);
2983 NS_HTML5_BREAK(endtagloop
);
2987 if (isCurrent(nsGkAtoms::option
) &&
2988 nsGkAtoms::optgroup
== stack
[currentPtr
- 1]->name
) {
2991 if (isCurrent(nsGkAtoms::optgroup
)) {
2994 errStrayEndTag(name
);
2996 NS_HTML5_BREAK(endtagloop
);
2999 eltPos
= findLastInTableScope(nsGkAtoms::select
);
3000 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
3001 MOZ_ASSERT(fragment
);
3002 errStrayEndTag(name
);
3003 NS_HTML5_BREAK(endtagloop
);
3005 while (currentPtr
>= eltPos
) {
3008 resetTheInsertionMode();
3009 NS_HTML5_BREAK(endtagloop
);
3012 endTagTemplateInHead();
3013 NS_HTML5_BREAK(endtagloop
);
3016 errStrayEndTag(name
);
3017 NS_HTML5_BREAK(endtagloop
);
3025 errStrayEndTag(name
);
3026 NS_HTML5_BREAK(endtagloop
);
3028 mode
= AFTER_AFTER_BODY
;
3029 NS_HTML5_BREAK(endtagloop
);
3033 errEndTagAfterBody();
3034 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3043 MOZ_ASSERT(fragment
);
3044 errStrayEndTag(name
);
3045 NS_HTML5_BREAK(endtagloop
);
3048 if ((!fragment
) && !isCurrent(nsGkAtoms::frameset
)) {
3049 mode
= AFTER_FRAMESET
;
3051 NS_HTML5_BREAK(endtagloop
);
3054 errStrayEndTag(name
);
3055 NS_HTML5_BREAK(endtagloop
);
3059 case AFTER_FRAMESET
: {
3062 mode
= AFTER_AFTER_FRAMESET
;
3063 NS_HTML5_BREAK(endtagloop
);
3066 errStrayEndTag(name
);
3067 NS_HTML5_BREAK(endtagloop
);
3072 errEndTagSeenWithoutDoctype();
3073 documentModeInternal(QUIRKS_MODE
, nullptr, nullptr);
3083 appendHtmlElementToDocumentAndPush();
3088 errStrayEndTag(name
);
3089 NS_HTML5_BREAK(endtagloop
);
3099 appendToCurrentNodeAndPushHeadElement(
3100 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
3105 errStrayEndTag(name
);
3106 NS_HTML5_BREAK(endtagloop
);
3113 endTagTemplateInHead();
3114 NS_HTML5_BREAK(endtagloop
);
3119 appendToCurrentNodeAndPushBodyElement();
3124 errStrayEndTag(name
);
3125 NS_HTML5_BREAK(endtagloop
);
3129 case AFTER_AFTER_BODY
: {
3130 errStrayEndTag(name
);
3131 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3134 case AFTER_AFTER_FRAMESET
: {
3135 errStrayEndTag(name
);
3136 NS_HTML5_BREAK(endtagloop
);
3140 if (originalMode
== AFTER_HEAD
) {
3143 mode
= originalMode
;
3144 NS_HTML5_BREAK(endtagloop
);
3151 void nsHtml5TreeBuilder::endTagTemplateInHead() {
3152 int32_t eltPos
= findLast(nsGkAtoms::_template
);
3153 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
3154 errStrayEndTag(nsGkAtoms::_template
);
3157 generateImpliedEndTagsThoroughly();
3158 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(nsGkAtoms::_template
)) {
3159 errUnclosedElements(eltPos
, nsGkAtoms::_template
);
3161 while (currentPtr
>= eltPos
) {
3164 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
3166 resetTheInsertionMode();
3170 nsHtml5TreeBuilder::findLastInTableScopeOrRootTemplateTbodyTheadTfoot() {
3171 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3172 if (stack
[i
]->ns
== kNameSpaceID_XHTML
&&
3173 (stack
[i
]->getGroup() == nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT
||
3174 stack
[i
]->getGroup() == nsHtml5TreeBuilder::TEMPLATE
)) {
3181 int32_t nsHtml5TreeBuilder::findLast(nsAtom
* name
) {
3182 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3183 if (stack
[i
]->ns
== kNameSpaceID_XHTML
&& stack
[i
]->name
== name
) {
3187 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3190 int32_t nsHtml5TreeBuilder::findLastInTableScope(nsAtom
* name
) {
3191 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3192 if (stack
[i
]->ns
== kNameSpaceID_XHTML
) {
3193 if (stack
[i
]->name
== name
) {
3195 } else if (stack
[i
]->name
== nsGkAtoms::table
||
3196 stack
[i
]->name
== nsGkAtoms::_template
) {
3197 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3201 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3204 int32_t nsHtml5TreeBuilder::findLastInButtonScope(nsAtom
* name
) {
3205 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3206 if (stack
[i
]->ns
== kNameSpaceID_XHTML
) {
3207 if (stack
[i
]->name
== name
) {
3209 } else if (stack
[i
]->name
== nsGkAtoms::button
) {
3210 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3213 if (stack
[i
]->isScoping()) {
3214 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3217 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3220 int32_t nsHtml5TreeBuilder::findLastInScope(nsAtom
* name
) {
3221 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3222 if (stack
[i
]->ns
== kNameSpaceID_XHTML
&& stack
[i
]->name
== name
) {
3224 } else if (stack
[i
]->isScoping()) {
3225 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3228 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3231 int32_t nsHtml5TreeBuilder::findLastInListScope(nsAtom
* name
) {
3232 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3233 if (stack
[i
]->ns
== kNameSpaceID_XHTML
) {
3234 if (stack
[i
]->name
== name
) {
3236 } else if (stack
[i
]->name
== nsGkAtoms::ul
||
3237 stack
[i
]->name
== nsGkAtoms::ol
) {
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::findLastInScopeHn() {
3249 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3250 if (stack
[i
]->getGroup() ==
3251 nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
) {
3253 } else if (stack
[i
]->isScoping()) {
3254 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3257 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3260 void nsHtml5TreeBuilder::generateImpliedEndTagsExceptFor(nsAtom
* name
) {
3262 nsHtml5StackNode
* node
= stack
[currentPtr
];
3263 switch (node
->getGroup()) {
3271 if (node
->ns
== kNameSpaceID_XHTML
&& node
->name
== name
) {
3284 void nsHtml5TreeBuilder::generateImpliedEndTags() {
3286 switch (stack
[currentPtr
]->getGroup()) {
3304 void nsHtml5TreeBuilder::generateImpliedEndTagsThoroughly() {
3306 switch (stack
[currentPtr
]->getGroup()) {
3316 case TBODY_OR_THEAD_OR_TFOOT
:
3329 bool nsHtml5TreeBuilder::isSecondOnStackBody() {
3330 return currentPtr
>= 1 && stack
[1]->getGroup() == nsHtml5TreeBuilder::BODY
;
3333 void nsHtml5TreeBuilder::documentModeInternal(nsHtml5DocumentMode m
,
3334 nsHtml5String publicIdentifier
,
3335 nsHtml5String systemIdentifier
) {
3336 if (forceNoQuirks
) {
3338 this->documentMode(STANDARDS_MODE
);
3341 quirks
= (m
== QUIRKS_MODE
);
3342 this->documentMode(m
);
3345 bool nsHtml5TreeBuilder::isAlmostStandards(nsHtml5String publicIdentifier
,
3346 nsHtml5String systemIdentifier
) {
3347 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3348 "-//w3c//dtd xhtml 1.0 transitional//", publicIdentifier
)) {
3351 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3352 "-//w3c//dtd xhtml 1.0 frameset//", publicIdentifier
)) {
3355 if (systemIdentifier
) {
3356 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3357 "-//w3c//dtd html 4.01 transitional//", publicIdentifier
)) {
3360 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3361 "-//w3c//dtd html 4.01 frameset//", publicIdentifier
)) {
3368 bool nsHtml5TreeBuilder::isQuirky(nsAtom
* name
, nsHtml5String publicIdentifier
,
3369 nsHtml5String systemIdentifier
,
3374 if (name
!= nsGkAtoms::html
) {
3377 if (publicIdentifier
) {
3378 for (int32_t i
= 0; i
< nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS
.length
; i
++) {
3379 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3380 nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS
[i
], publicIdentifier
)) {
3384 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3385 "-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier
) ||
3386 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3387 "-/w3c/dtd html 4.0 transitional/en", publicIdentifier
) ||
3388 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3389 "html", publicIdentifier
)) {
3393 if (!systemIdentifier
) {
3394 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3395 "-//w3c//dtd html 4.01 transitional//", publicIdentifier
)) {
3397 } else if (nsHtml5Portability::
3398 lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3399 "-//w3c//dtd html 4.01 frameset//", publicIdentifier
)) {
3402 } else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3403 "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd",
3404 systemIdentifier
)) {
3410 void nsHtml5TreeBuilder::closeTheCell(int32_t eltPos
) {
3411 generateImpliedEndTags();
3412 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
3413 errUnclosedElementsCell(eltPos
);
3415 while (currentPtr
>= eltPos
) {
3418 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
3423 int32_t nsHtml5TreeBuilder::findLastInTableScopeTdTh() {
3424 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3425 nsAtom
* name
= stack
[i
]->name
;
3426 if (stack
[i
]->ns
== kNameSpaceID_XHTML
) {
3427 if (nsGkAtoms::td
== name
|| nsGkAtoms::th
== name
) {
3429 } else if (name
== nsGkAtoms::table
|| name
== nsGkAtoms::_template
) {
3430 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3434 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3437 void nsHtml5TreeBuilder::clearStackBackTo(int32_t eltPos
) {
3438 int32_t eltGroup
= stack
[eltPos
]->getGroup();
3439 while (currentPtr
> eltPos
) {
3440 if (stack
[currentPtr
]->ns
== kNameSpaceID_XHTML
&&
3441 stack
[currentPtr
]->getGroup() == TEMPLATE
&&
3442 (eltGroup
== TABLE
|| eltGroup
== TBODY_OR_THEAD_OR_TFOOT
||
3443 eltGroup
== TR
|| !eltPos
)) {
3450 void nsHtml5TreeBuilder::resetTheInsertionMode() {
3451 nsHtml5StackNode
* node
;
3454 for (int32_t i
= currentPtr
; i
>= 0; i
--) {
3459 if (!(contextNamespace
== kNameSpaceID_XHTML
&&
3460 (contextName
== nsGkAtoms::td
|| contextName
== nsGkAtoms::th
))) {
3463 ns
= contextNamespace
;
3466 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3470 if (nsGkAtoms::select
== name
) {
3471 int32_t ancestorIndex
= i
;
3472 while (ancestorIndex
> 0) {
3473 nsHtml5StackNode
* ancestor
= stack
[ancestorIndex
--];
3474 if (kNameSpaceID_XHTML
== ancestor
->ns
) {
3475 if (nsGkAtoms::_template
== ancestor
->name
) {
3478 if (nsGkAtoms::table
== ancestor
->name
) {
3479 mode
= IN_SELECT_IN_TABLE
;
3486 } else if (nsGkAtoms::td
== name
|| nsGkAtoms::th
== name
) {
3489 } else if (nsGkAtoms::tr
== name
) {
3492 } else if (nsGkAtoms::tbody
== name
|| nsGkAtoms::thead
== name
||
3493 nsGkAtoms::tfoot
== name
) {
3494 mode
= IN_TABLE_BODY
;
3496 } else if (nsGkAtoms::caption
== name
) {
3499 } else if (nsGkAtoms::colgroup
== name
) {
3500 mode
= IN_COLUMN_GROUP
;
3502 } else if (nsGkAtoms::table
== name
) {
3505 } else if (kNameSpaceID_XHTML
!= ns
) {
3506 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3508 } else if (nsGkAtoms::_template
== name
) {
3509 MOZ_ASSERT(templateModePtr
>= 0);
3510 mode
= templateModeStack
[templateModePtr
];
3512 } else if (nsGkAtoms::head
== name
) {
3513 if (name
== contextName
) {
3514 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3519 } else if (nsGkAtoms::body
== name
) {
3520 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3522 } else if (nsGkAtoms::frameset
== name
) {
3525 } else if (nsGkAtoms::html
== name
) {
3533 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3539 void nsHtml5TreeBuilder::implicitlyCloseP() {
3540 int32_t eltPos
= findLastInButtonScope(nsGkAtoms::p
);
3541 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
3544 generateImpliedEndTagsExceptFor(nsGkAtoms::p
);
3545 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
3546 errUnclosedElementsImplied(eltPos
, nsGkAtoms::p
);
3548 while (currentPtr
>= eltPos
) {
3553 bool nsHtml5TreeBuilder::debugOnlyClearLastStackSlot() {
3554 stack
[currentPtr
] = nullptr;
3558 bool nsHtml5TreeBuilder::debugOnlyClearLastListSlot() {
3559 listOfActiveFormattingElements
[listPtr
] = nullptr;
3563 void nsHtml5TreeBuilder::pushTemplateMode(int32_t mode
) {
3565 if (templateModePtr
== templateModeStack
.length
) {
3566 jArray
<int32_t, int32_t> newStack
=
3567 jArray
<int32_t, int32_t>::newJArray(templateModeStack
.length
+ 64);
3568 nsHtml5ArrayCopy::arraycopy(templateModeStack
, newStack
,
3569 templateModeStack
.length
);
3570 templateModeStack
= newStack
;
3572 templateModeStack
[templateModePtr
] = mode
;
3575 void nsHtml5TreeBuilder::push(nsHtml5StackNode
* node
) {
3577 if (currentPtr
== stack
.length
) {
3578 jArray
<nsHtml5StackNode
*, int32_t> newStack
=
3579 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(stack
.length
+ 64);
3580 nsHtml5ArrayCopy::arraycopy(stack
, newStack
, stack
.length
);
3583 stack
[currentPtr
] = node
;
3584 elementPushed(node
->ns
, node
->popName
, node
->node
);
3587 void nsHtml5TreeBuilder::silentPush(nsHtml5StackNode
* node
) {
3589 if (currentPtr
== stack
.length
) {
3590 jArray
<nsHtml5StackNode
*, int32_t> newStack
=
3591 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(stack
.length
+ 64);
3592 nsHtml5ArrayCopy::arraycopy(stack
, newStack
, stack
.length
);
3595 stack
[currentPtr
] = node
;
3598 void nsHtml5TreeBuilder::append(nsHtml5StackNode
* node
) {
3600 if (listPtr
== listOfActiveFormattingElements
.length
) {
3601 jArray
<nsHtml5StackNode
*, int32_t> newList
=
3602 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(
3603 listOfActiveFormattingElements
.length
+ 64);
3604 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements
, newList
,
3605 listOfActiveFormattingElements
.length
);
3606 listOfActiveFormattingElements
= newList
;
3608 listOfActiveFormattingElements
[listPtr
] = node
;
3611 void nsHtml5TreeBuilder::
3612 clearTheListOfActiveFormattingElementsUpToTheLastMarker() {
3613 while (listPtr
> -1) {
3614 if (!listOfActiveFormattingElements
[listPtr
]) {
3618 listOfActiveFormattingElements
[listPtr
]->release(this);
3623 void nsHtml5TreeBuilder::removeFromStack(int32_t pos
) {
3624 if (currentPtr
== pos
) {
3627 stack
[pos
]->release(this);
3628 nsHtml5ArrayCopy::arraycopy(stack
, pos
+ 1, pos
, currentPtr
- pos
);
3629 MOZ_ASSERT(debugOnlyClearLastStackSlot());
3634 void nsHtml5TreeBuilder::removeFromStack(nsHtml5StackNode
* node
) {
3635 if (stack
[currentPtr
] == node
) {
3638 int32_t pos
= currentPtr
- 1;
3639 while (pos
>= 0 && stack
[pos
] != node
) {
3646 node
->release(this);
3647 nsHtml5ArrayCopy::arraycopy(stack
, pos
+ 1, pos
, currentPtr
- pos
);
3652 void nsHtml5TreeBuilder::removeFromListOfActiveFormattingElements(int32_t pos
) {
3653 MOZ_ASSERT(!!listOfActiveFormattingElements
[pos
]);
3654 listOfActiveFormattingElements
[pos
]->release(this);
3655 if (pos
== listPtr
) {
3656 MOZ_ASSERT(debugOnlyClearLastListSlot());
3660 MOZ_ASSERT(pos
< listPtr
);
3661 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements
, pos
+ 1, pos
,
3663 MOZ_ASSERT(debugOnlyClearLastListSlot());
3667 bool nsHtml5TreeBuilder::adoptionAgencyEndTag(nsAtom
* name
) {
3668 if (stack
[currentPtr
]->ns
== kNameSpaceID_XHTML
&&
3669 stack
[currentPtr
]->name
== name
&&
3670 findInListOfActiveFormattingElements(stack
[currentPtr
]) == -1) {
3674 for (int32_t i
= 0; i
< 8; ++i
) {
3675 int32_t formattingEltListPos
= listPtr
;
3676 while (formattingEltListPos
> -1) {
3677 nsHtml5StackNode
* listNode
=
3678 listOfActiveFormattingElements
[formattingEltListPos
];
3680 formattingEltListPos
= -1;
3682 } else if (listNode
->name
== name
) {
3685 formattingEltListPos
--;
3687 if (formattingEltListPos
== -1) {
3690 nsHtml5StackNode
* formattingElt
=
3691 listOfActiveFormattingElements
[formattingEltListPos
];
3692 int32_t formattingEltStackPos
= currentPtr
;
3693 bool inScope
= true;
3694 while (formattingEltStackPos
> -1) {
3695 nsHtml5StackNode
* node
= stack
[formattingEltStackPos
];
3696 if (node
== formattingElt
) {
3698 } else if (node
->isScoping()) {
3701 formattingEltStackPos
--;
3703 if (formattingEltStackPos
== -1) {
3704 errNoElementToCloseButEndTagSeen(name
);
3705 removeFromListOfActiveFormattingElements(formattingEltListPos
);
3709 errNoElementToCloseButEndTagSeen(name
);
3712 if (formattingEltStackPos
!= currentPtr
) {
3713 errEndTagViolatesNestingRules(name
);
3715 int32_t furthestBlockPos
= formattingEltStackPos
+ 1;
3716 while (furthestBlockPos
<= currentPtr
) {
3717 nsHtml5StackNode
* node
= stack
[furthestBlockPos
];
3718 MOZ_ASSERT(furthestBlockPos
> 0,
3719 "How is formattingEltStackPos + 1 not > 0?");
3720 if (node
->isSpecial()) {
3725 if (furthestBlockPos
> currentPtr
) {
3726 while (currentPtr
>= formattingEltStackPos
) {
3729 removeFromListOfActiveFormattingElements(formattingEltListPos
);
3732 nsHtml5StackNode
* commonAncestor
= stack
[formattingEltStackPos
- 1];
3733 nsIContentHandle
* insertionCommonAncestor
=
3734 nodeFromStackWithBlinkCompat(formattingEltStackPos
- 1);
3735 nsHtml5StackNode
* furthestBlock
= stack
[furthestBlockPos
];
3736 int32_t bookmark
= formattingEltListPos
;
3737 int32_t nodePos
= furthestBlockPos
;
3738 nsHtml5StackNode
* lastNode
= furthestBlock
;
3743 if (nodePos
== formattingEltStackPos
) {
3746 nsHtml5StackNode
* node
= stack
[nodePos
];
3747 int32_t nodeListPos
= findInListOfActiveFormattingElements(node
);
3748 if (j
> 3 && nodeListPos
!= -1) {
3749 removeFromListOfActiveFormattingElements(nodeListPos
);
3750 if (nodeListPos
<= formattingEltListPos
) {
3751 formattingEltListPos
--;
3753 if (nodeListPos
<= bookmark
) {
3758 if (nodeListPos
== -1) {
3759 MOZ_ASSERT(formattingEltStackPos
< nodePos
);
3760 MOZ_ASSERT(bookmark
< nodePos
);
3761 MOZ_ASSERT(furthestBlockPos
> nodePos
);
3762 removeFromStack(nodePos
);
3766 if (nodePos
== furthestBlockPos
) {
3767 bookmark
= nodeListPos
+ 1;
3769 MOZ_ASSERT(node
== listOfActiveFormattingElements
[nodeListPos
]);
3770 MOZ_ASSERT(node
== stack
[nodePos
]);
3771 nsIContentHandle
* clone
= createElement(
3772 kNameSpaceID_XHTML
, node
->name
, node
->attributes
->cloneAttributes(),
3773 insertionCommonAncestor
, htmlCreator(node
->getHtmlCreator()));
3774 nsHtml5StackNode
* newNode
= createStackNode(
3775 node
->getFlags(), node
->ns
, node
->name
, clone
, node
->popName
,
3776 node
->attributes
, node
->getHtmlCreator());
3777 node
->dropAttributes();
3778 stack
[nodePos
] = newNode
;
3780 listOfActiveFormattingElements
[nodeListPos
] = newNode
;
3781 node
->release(this);
3782 node
->release(this);
3784 detachFromParent(lastNode
->node
);
3785 appendElement(lastNode
->node
, nodeFromStackWithBlinkCompat(nodePos
));
3788 if (commonAncestor
->isFosterParenting()) {
3789 detachFromParent(lastNode
->node
);
3790 insertIntoFosterParent(lastNode
->node
);
3792 detachFromParent(lastNode
->node
);
3793 appendElement(lastNode
->node
, insertionCommonAncestor
);
3795 nsIContentHandle
* clone
= createElement(
3796 kNameSpaceID_XHTML
, formattingElt
->name
,
3797 formattingElt
->attributes
->cloneAttributes(), furthestBlock
->node
,
3798 htmlCreator(formattingElt
->getHtmlCreator()));
3799 nsHtml5StackNode
* formattingClone
= createStackNode(
3800 formattingElt
->getFlags(), formattingElt
->ns
, formattingElt
->name
,
3801 clone
, formattingElt
->popName
, formattingElt
->attributes
,
3802 formattingElt
->getHtmlCreator());
3803 formattingElt
->dropAttributes();
3804 appendChildrenToNewParent(furthestBlock
->node
, clone
);
3805 appendElement(clone
, furthestBlock
->node
);
3806 removeFromListOfActiveFormattingElements(formattingEltListPos
);
3807 insertIntoListOfActiveFormattingElements(formattingClone
, bookmark
);
3808 MOZ_ASSERT(formattingEltStackPos
< furthestBlockPos
);
3809 removeFromStack(formattingEltStackPos
);
3810 insertIntoStack(formattingClone
, furthestBlockPos
);
3815 void nsHtml5TreeBuilder::insertIntoStack(nsHtml5StackNode
* node
,
3817 MOZ_ASSERT(currentPtr
+ 1 < stack
.length
);
3818 MOZ_ASSERT(position
<= currentPtr
+ 1);
3819 if (position
== currentPtr
+ 1) {
3822 nsHtml5ArrayCopy::arraycopy(stack
, position
, position
+ 1,
3823 (currentPtr
- position
) + 1);
3825 stack
[position
] = node
;
3829 void nsHtml5TreeBuilder::insertIntoListOfActiveFormattingElements(
3830 nsHtml5StackNode
* formattingClone
, int32_t bookmark
) {
3831 formattingClone
->retain();
3832 MOZ_ASSERT(listPtr
+ 1 < listOfActiveFormattingElements
.length
);
3833 if (bookmark
<= listPtr
) {
3834 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements
, bookmark
,
3835 bookmark
+ 1, (listPtr
- bookmark
) + 1);
3838 listOfActiveFormattingElements
[bookmark
] = formattingClone
;
3841 int32_t nsHtml5TreeBuilder::findInListOfActiveFormattingElements(
3842 nsHtml5StackNode
* node
) {
3843 for (int32_t i
= listPtr
; i
>= 0; i
--) {
3844 if (node
== listOfActiveFormattingElements
[i
]) {
3851 int32_t nsHtml5TreeBuilder::
3852 findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
3854 for (int32_t i
= listPtr
; i
>= 0; i
--) {
3855 nsHtml5StackNode
* node
= listOfActiveFormattingElements
[i
];
3858 } else if (node
->name
== name
) {
3865 void nsHtml5TreeBuilder::maybeForgetEarlierDuplicateFormattingElement(
3866 nsAtom
* name
, nsHtml5HtmlAttributes
* attributes
) {
3867 int32_t candidate
= -1;
3869 for (int32_t i
= listPtr
; i
>= 0; i
--) {
3870 nsHtml5StackNode
* node
= listOfActiveFormattingElements
[i
];
3874 if (node
->name
== name
&& node
->attributes
->equalsAnother(attributes
)) {
3880 removeFromListOfActiveFormattingElements(candidate
);
3884 int32_t nsHtml5TreeBuilder::findLastOrRoot(nsAtom
* name
) {
3885 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3886 if (stack
[i
]->ns
== kNameSpaceID_XHTML
&& stack
[i
]->name
== name
) {
3893 int32_t nsHtml5TreeBuilder::findLastOrRoot(int32_t group
) {
3894 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3895 if (stack
[i
]->ns
== kNameSpaceID_XHTML
&& stack
[i
]->getGroup() == group
) {
3902 bool nsHtml5TreeBuilder::addAttributesToBody(
3903 nsHtml5HtmlAttributes
* attributes
) {
3904 if (currentPtr
>= 1) {
3905 nsHtml5StackNode
* body
= stack
[1];
3906 if (body
->getGroup() == nsHtml5TreeBuilder::BODY
) {
3907 addAttributesToElement(body
->node
, attributes
);
3914 void nsHtml5TreeBuilder::addAttributesToHtml(
3915 nsHtml5HtmlAttributes
* attributes
) {
3916 addAttributesToElement(stack
[0]->node
, attributes
);
3919 void nsHtml5TreeBuilder::pushHeadPointerOntoStack() {
3920 MOZ_ASSERT(!!headPointer
);
3921 MOZ_ASSERT(mode
== AFTER_HEAD
);
3923 silentPush(createStackNode(nsHtml5ElementName::ELT_HEAD
, headPointer
));
3926 void nsHtml5TreeBuilder::reconstructTheActiveFormattingElements() {
3927 if (listPtr
== -1) {
3930 nsHtml5StackNode
* mostRecent
= listOfActiveFormattingElements
[listPtr
];
3931 if (!mostRecent
|| isInStack(mostRecent
)) {
3934 int32_t entryPos
= listPtr
;
3937 if (entryPos
== -1) {
3940 if (!listOfActiveFormattingElements
[entryPos
]) {
3943 if (isInStack(listOfActiveFormattingElements
[entryPos
])) {
3947 while (entryPos
< listPtr
) {
3949 nsHtml5StackNode
* entry
= listOfActiveFormattingElements
[entryPos
];
3950 nsHtml5StackNode
* current
= stack
[currentPtr
];
3951 nsIContentHandle
* clone
;
3952 if (current
->isFosterParenting()) {
3953 clone
= createAndInsertFosterParentedElement(
3954 kNameSpaceID_XHTML
, entry
->name
, entry
->attributes
->cloneAttributes(),
3955 htmlCreator(entry
->getHtmlCreator()));
3957 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
3958 clone
= createElement(kNameSpaceID_XHTML
, entry
->name
,
3959 entry
->attributes
->cloneAttributes(), currentNode
,
3960 htmlCreator(entry
->getHtmlCreator()));
3961 appendElement(clone
, currentNode
);
3963 nsHtml5StackNode
* entryClone
= createStackNode(
3964 entry
->getFlags(), entry
->ns
, entry
->name
, clone
, entry
->popName
,
3965 entry
->attributes
, entry
->getHtmlCreator());
3966 entry
->dropAttributes();
3968 listOfActiveFormattingElements
[entryPos
] = entryClone
;
3969 entry
->release(this);
3970 entryClone
->retain();
3974 void nsHtml5TreeBuilder::notifyUnusedStackNode(int32_t idxInStackNodes
) {
3975 if (idxInStackNodes
< stackNodesIdx
) {
3976 stackNodesIdx
= idxInStackNodes
;
3980 nsHtml5StackNode
* nsHtml5TreeBuilder::getUnusedStackNode() {
3981 while (stackNodesIdx
< numStackNodes
) {
3982 if (stackNodes
[stackNodesIdx
]->isUnused()) {
3983 return stackNodes
[stackNodesIdx
++];
3987 if (stackNodesIdx
< stackNodes
.length
) {
3988 stackNodes
[stackNodesIdx
] = new nsHtml5StackNode(stackNodesIdx
);
3990 return stackNodes
[stackNodesIdx
++];
3992 jArray
<nsHtml5StackNode
*, int32_t> newStack
=
3993 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(stackNodes
.length
+ 64);
3994 nsHtml5ArrayCopy::arraycopy(stackNodes
, newStack
, stackNodes
.length
);
3995 stackNodes
= newStack
;
3996 stackNodes
[stackNodesIdx
] = new nsHtml5StackNode(stackNodesIdx
);
3998 return stackNodes
[stackNodesIdx
++];
4001 nsHtml5StackNode
* nsHtml5TreeBuilder::createStackNode(
4002 int32_t flags
, int32_t ns
, nsAtom
* name
, nsIContentHandle
* node
,
4003 nsAtom
* popName
, nsHtml5HtmlAttributes
* attributes
,
4004 mozilla::dom::HTMLContentCreatorFunction htmlCreator
) {
4005 nsHtml5StackNode
* instance
= getUnusedStackNode();
4006 instance
->setValues(flags
, ns
, name
, node
, popName
, attributes
, htmlCreator
);
4010 nsHtml5StackNode
* nsHtml5TreeBuilder::createStackNode(
4011 nsHtml5ElementName
* elementName
, nsIContentHandle
* node
) {
4012 nsHtml5StackNode
* instance
= getUnusedStackNode();
4013 instance
->setValues(elementName
, node
);
4017 nsHtml5StackNode
* nsHtml5TreeBuilder::createStackNode(
4018 nsHtml5ElementName
* elementName
, nsIContentHandle
* node
,
4019 nsHtml5HtmlAttributes
* attributes
) {
4020 nsHtml5StackNode
* instance
= getUnusedStackNode();
4021 instance
->setValues(elementName
, node
, attributes
);
4025 nsHtml5StackNode
* nsHtml5TreeBuilder::createStackNode(
4026 nsHtml5ElementName
* elementName
, nsIContentHandle
* node
, nsAtom
* popName
) {
4027 nsHtml5StackNode
* instance
= getUnusedStackNode();
4028 instance
->setValues(elementName
, node
, popName
);
4032 nsHtml5StackNode
* nsHtml5TreeBuilder::createStackNode(
4033 nsHtml5ElementName
* elementName
, nsAtom
* popName
, nsIContentHandle
* node
) {
4034 nsHtml5StackNode
* instance
= getUnusedStackNode();
4035 instance
->setValues(elementName
, popName
, node
);
4039 nsHtml5StackNode
* nsHtml5TreeBuilder::createStackNode(
4040 nsHtml5ElementName
* elementName
, nsIContentHandle
* node
, nsAtom
* popName
,
4041 bool markAsIntegrationPoint
) {
4042 nsHtml5StackNode
* instance
= getUnusedStackNode();
4043 instance
->setValues(elementName
, node
, popName
, markAsIntegrationPoint
);
4047 void nsHtml5TreeBuilder::insertIntoFosterParent(nsIContentHandle
* child
) {
4048 int32_t tablePos
= findLastOrRoot(nsHtml5TreeBuilder::TABLE
);
4049 int32_t templatePos
= findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE
);
4050 if (templatePos
>= tablePos
) {
4051 appendElement(child
, stack
[templatePos
]->node
);
4054 nsHtml5StackNode
* node
= stack
[tablePos
];
4055 insertFosterParentedChild(child
, node
->node
, stack
[tablePos
- 1]->node
);
4058 nsIContentHandle
* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
4059 int32_t ns
, nsAtom
* name
, nsHtml5HtmlAttributes
* attributes
,
4060 nsHtml5ContentCreatorFunction creator
) {
4061 return createAndInsertFosterParentedElement(ns
, name
, attributes
, nullptr,
4065 nsIContentHandle
* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
4066 int32_t ns
, nsAtom
* name
, nsHtml5HtmlAttributes
* attributes
,
4067 nsIContentHandle
* form
, nsHtml5ContentCreatorFunction creator
) {
4068 int32_t tablePos
= findLastOrRoot(nsHtml5TreeBuilder::TABLE
);
4069 int32_t templatePos
= findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE
);
4070 if (templatePos
>= tablePos
) {
4071 nsIContentHandle
* child
= createElement(ns
, name
, attributes
, form
,
4072 stack
[templatePos
]->node
, creator
);
4073 appendElement(child
, stack
[templatePos
]->node
);
4076 nsHtml5StackNode
* node
= stack
[tablePos
];
4077 return createAndInsertFosterParentedElement(
4078 ns
, name
, attributes
, form
, node
->node
, stack
[tablePos
- 1]->node
,
4082 bool nsHtml5TreeBuilder::isInStack(nsHtml5StackNode
* node
) {
4083 for (int32_t i
= currentPtr
; i
>= 0; i
--) {
4084 if (stack
[i
] == node
) {
4091 void nsHtml5TreeBuilder::popTemplateMode() { templateModePtr
--; }
4093 void nsHtml5TreeBuilder::pop() {
4094 nsHtml5StackNode
* node
= stack
[currentPtr
];
4095 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4097 elementPopped(node
->ns
, node
->popName
, node
->node
);
4098 node
->release(this);
4101 void nsHtml5TreeBuilder::popForeign(int32_t origPos
, int32_t eltPos
) {
4102 nsHtml5StackNode
* node
= stack
[currentPtr
];
4103 if (origPos
!= currentPtr
|| eltPos
!= currentPtr
) {
4104 markMalformedIfScript(node
->node
);
4106 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4108 elementPopped(node
->ns
, node
->popName
, node
->node
);
4109 node
->release(this);
4112 void nsHtml5TreeBuilder::silentPop() {
4113 nsHtml5StackNode
* node
= stack
[currentPtr
];
4114 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4116 node
->release(this);
4119 void nsHtml5TreeBuilder::popOnEof() {
4120 nsHtml5StackNode
* node
= stack
[currentPtr
];
4121 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4123 markMalformedIfScript(node
->node
);
4124 elementPopped(node
->ns
, node
->popName
, node
->node
);
4125 node
->release(this);
4128 void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush(
4129 nsHtml5HtmlAttributes
* attributes
) {
4130 nsIContentHandle
* elt
= createHtmlElementSetAsRoot(attributes
);
4131 nsHtml5StackNode
* node
= createStackNode(nsHtml5ElementName::ELT_HTML
, elt
);
4135 void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush() {
4136 appendHtmlElementToDocumentAndPush(tokenizer
->emptyAttributes());
4139 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(
4140 nsHtml5HtmlAttributes
* attributes
) {
4141 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4142 nsIContentHandle
* elt
=
4143 createElement(kNameSpaceID_XHTML
, nsGkAtoms::head
, attributes
,
4144 currentNode
, htmlCreator(NS_NewHTMLSharedElement
));
4145 appendElement(elt
, currentNode
);
4147 nsHtml5StackNode
* node
= createStackNode(nsHtml5ElementName::ELT_HEAD
, elt
);
4151 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement(
4152 nsHtml5HtmlAttributes
* attributes
) {
4153 appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_BODY
, attributes
);
4156 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement() {
4157 appendToCurrentNodeAndPushBodyElement(tokenizer
->emptyAttributes());
4160 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(
4161 nsHtml5HtmlAttributes
* attributes
) {
4162 nsIContentHandle
* elt
;
4163 nsHtml5StackNode
* current
= stack
[currentPtr
];
4164 if (current
->isFosterParenting()) {
4165 elt
= createAndInsertFosterParentedElement(
4166 kNameSpaceID_XHTML
, nsGkAtoms::form
, attributes
,
4167 htmlCreator(NS_NewHTMLFormElement
));
4169 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4170 elt
= createElement(kNameSpaceID_XHTML
, nsGkAtoms::form
, attributes
,
4171 currentNode
, htmlCreator(NS_NewHTMLFormElement
));
4172 appendElement(elt
, currentNode
);
4174 if (!isTemplateContents()) {
4177 nsHtml5StackNode
* node
= createStackNode(nsHtml5ElementName::ELT_FORM
, elt
);
4181 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(
4182 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4183 nsHtml5HtmlAttributes
* clone
= attributes
->cloneAttributes();
4184 nsIContentHandle
* elt
;
4185 nsHtml5StackNode
* current
= stack
[currentPtr
];
4186 if (current
->isFosterParenting()) {
4187 elt
= createAndInsertFosterParentedElement(
4188 kNameSpaceID_XHTML
, elementName
->getName(), attributes
,
4189 htmlCreator(elementName
->getHtmlCreator()));
4191 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4193 createElement(kNameSpaceID_XHTML
, elementName
->getName(), attributes
,
4194 currentNode
, htmlCreator(elementName
->getHtmlCreator()));
4195 appendElement(elt
, currentNode
);
4197 nsHtml5StackNode
* node
= createStackNode(elementName
, elt
, clone
);
4203 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(
4204 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4205 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4206 nsIContentHandle
* elt
=
4207 createElement(kNameSpaceID_XHTML
, elementName
->getName(), attributes
,
4208 currentNode
, htmlCreator(elementName
->getHtmlCreator()));
4209 appendElement(elt
, currentNode
);
4210 if (nsHtml5ElementName::ELT_TEMPLATE
== elementName
) {
4211 elt
= getDocumentFragmentForTemplate(elt
);
4213 nsHtml5StackNode
* node
= createStackNode(elementName
, elt
);
4217 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
4218 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4219 nsAtom
* popName
= elementName
->getName();
4220 nsIContentHandle
* elt
;
4221 nsHtml5StackNode
* current
= stack
[currentPtr
];
4222 if (current
->isFosterParenting()) {
4223 elt
= createAndInsertFosterParentedElement(
4224 kNameSpaceID_XHTML
, popName
, attributes
,
4225 htmlCreator(elementName
->getHtmlCreator()));
4227 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4228 elt
= createElement(kNameSpaceID_XHTML
, popName
, attributes
, currentNode
,
4229 htmlCreator(elementName
->getHtmlCreator()));
4230 appendElement(elt
, currentNode
);
4232 nsHtml5StackNode
* node
= createStackNode(elementName
, elt
, popName
);
4236 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(
4237 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4238 nsAtom
* popName
= elementName
->getName();
4239 bool markAsHtmlIntegrationPoint
= false;
4240 if (nsHtml5ElementName::ELT_ANNOTATION_XML
== elementName
&&
4241 annotationXmlEncodingPermitsHtml(attributes
)) {
4242 markAsHtmlIntegrationPoint
= true;
4244 nsIContentHandle
* elt
;
4245 nsHtml5StackNode
* current
= stack
[currentPtr
];
4246 if (current
->isFosterParenting()) {
4247 elt
= createAndInsertFosterParentedElement(
4248 kNameSpaceID_MathML
, popName
, attributes
, htmlCreator(nullptr));
4250 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4251 elt
= createElement(kNameSpaceID_MathML
, popName
, attributes
, currentNode
,
4252 htmlCreator(nullptr));
4253 appendElement(elt
, currentNode
);
4255 nsHtml5StackNode
* node
=
4256 createStackNode(elementName
, elt
, popName
, markAsHtmlIntegrationPoint
);
4260 bool nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(
4261 nsHtml5HtmlAttributes
* attributes
) {
4262 nsHtml5String encoding
=
4263 attributes
->getValue(nsHtml5AttributeName::ATTR_ENCODING
);
4267 return nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
4268 "application/xhtml+xml", encoding
) ||
4269 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
4270 "text/html", encoding
);
4273 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(
4274 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4275 nsAtom
* popName
= elementName
->getCamelCaseName();
4276 nsIContentHandle
* elt
;
4277 nsHtml5StackNode
* current
= stack
[currentPtr
];
4278 if (current
->isFosterParenting()) {
4279 elt
= createAndInsertFosterParentedElement(
4280 kNameSpaceID_SVG
, popName
, attributes
,
4281 svgCreator(elementName
->getSvgCreator()));
4283 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4284 elt
= createElement(kNameSpaceID_SVG
, popName
, attributes
, currentNode
,
4285 svgCreator(elementName
->getSvgCreator()));
4286 appendElement(elt
, currentNode
);
4288 nsHtml5StackNode
* node
= createStackNode(elementName
, popName
, elt
);
4292 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
4293 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
,
4294 nsIContentHandle
* form
) {
4295 nsIContentHandle
* elt
;
4296 nsIContentHandle
* formOwner
=
4297 !form
|| fragment
|| isTemplateContents() ? nullptr : form
;
4298 nsHtml5StackNode
* current
= stack
[currentPtr
];
4299 if (current
->isFosterParenting()) {
4300 elt
= createAndInsertFosterParentedElement(
4301 kNameSpaceID_XHTML
, elementName
->getName(), attributes
, formOwner
,
4302 htmlCreator(elementName
->getHtmlCreator()));
4304 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4305 elt
= createElement(kNameSpaceID_XHTML
, elementName
->getName(), attributes
,
4306 formOwner
, currentNode
,
4307 htmlCreator(elementName
->getHtmlCreator()));
4308 appendElement(elt
, currentNode
);
4310 nsHtml5StackNode
* node
= createStackNode(elementName
, elt
);
4314 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
4315 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
,
4316 nsIContentHandle
* form
) {
4317 nsAtom
* name
= elementName
->getName();
4318 nsIContentHandle
* elt
;
4319 nsIContentHandle
* formOwner
=
4320 !form
|| fragment
|| isTemplateContents() ? nullptr : form
;
4321 nsHtml5StackNode
* current
= stack
[currentPtr
];
4322 if (current
->isFosterParenting()) {
4323 elt
= createAndInsertFosterParentedElement(
4324 kNameSpaceID_XHTML
, name
, attributes
, formOwner
,
4325 htmlCreator(elementName
->getHtmlCreator()));
4327 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4329 createElement(kNameSpaceID_XHTML
, name
, attributes
, formOwner
,
4330 currentNode
, htmlCreator(elementName
->getHtmlCreator()));
4331 appendElement(elt
, currentNode
);
4333 elementPushed(kNameSpaceID_XHTML
, name
, elt
);
4334 elementPopped(kNameSpaceID_XHTML
, name
, elt
);
4337 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
4338 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4339 nsAtom
* popName
= elementName
->getName();
4340 nsIContentHandle
* elt
;
4341 nsHtml5StackNode
* current
= stack
[currentPtr
];
4342 if (current
->isFosterParenting()) {
4343 elt
= createAndInsertFosterParentedElement(
4344 kNameSpaceID_XHTML
, popName
, attributes
,
4345 htmlCreator(elementName
->getHtmlCreator()));
4347 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4348 elt
= createElement(kNameSpaceID_XHTML
, popName
, attributes
, currentNode
,
4349 htmlCreator(elementName
->getHtmlCreator()));
4350 appendElement(elt
, currentNode
);
4352 elementPushed(kNameSpaceID_XHTML
, popName
, elt
);
4353 elementPopped(kNameSpaceID_XHTML
, popName
, elt
);
4356 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(
4357 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4358 nsAtom
* popName
= elementName
->getCamelCaseName();
4359 nsIContentHandle
* elt
;
4360 nsHtml5StackNode
* current
= stack
[currentPtr
];
4361 if (current
->isFosterParenting()) {
4362 elt
= createAndInsertFosterParentedElement(
4363 kNameSpaceID_SVG
, popName
, attributes
,
4364 svgCreator(elementName
->getSvgCreator()));
4366 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4367 elt
= createElement(kNameSpaceID_SVG
, popName
, attributes
, currentNode
,
4368 svgCreator(elementName
->getSvgCreator()));
4369 appendElement(elt
, currentNode
);
4371 elementPushed(kNameSpaceID_SVG
, popName
, elt
);
4372 elementPopped(kNameSpaceID_SVG
, popName
, elt
);
4375 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(
4376 nsHtml5ElementName
* elementName
, nsHtml5HtmlAttributes
* attributes
) {
4377 nsAtom
* popName
= elementName
->getName();
4378 nsIContentHandle
* elt
;
4379 nsHtml5StackNode
* current
= stack
[currentPtr
];
4380 if (current
->isFosterParenting()) {
4381 elt
= createAndInsertFosterParentedElement(
4382 kNameSpaceID_MathML
, popName
, attributes
, htmlCreator(nullptr));
4384 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4385 elt
= createElement(kNameSpaceID_MathML
, popName
, attributes
, currentNode
,
4386 htmlCreator(nullptr));
4387 appendElement(elt
, currentNode
);
4389 elementPushed(kNameSpaceID_MathML
, popName
, elt
);
4390 elementPopped(kNameSpaceID_MathML
, popName
, elt
);
4393 void nsHtml5TreeBuilder::appendVoidInputToCurrent(
4394 nsHtml5HtmlAttributes
* attributes
, nsIContentHandle
* form
) {
4395 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4396 nsIContentHandle
* elt
=
4397 createElement(kNameSpaceID_XHTML
, nsGkAtoms::input
, attributes
,
4398 !form
|| fragment
|| isTemplateContents() ? nullptr : form
,
4399 currentNode
, htmlCreator(NS_NewHTMLInputElement
));
4400 appendElement(elt
, currentNode
);
4401 elementPushed(kNameSpaceID_XHTML
, nsGkAtoms::input
, elt
);
4402 elementPopped(kNameSpaceID_XHTML
, nsGkAtoms::input
, elt
);
4405 void nsHtml5TreeBuilder::appendVoidFormToCurrent(
4406 nsHtml5HtmlAttributes
* attributes
) {
4407 nsIContentHandle
* currentNode
= nodeFromStackWithBlinkCompat(currentPtr
);
4408 nsIContentHandle
* elt
=
4409 createElement(kNameSpaceID_XHTML
, nsGkAtoms::form
, attributes
,
4410 currentNode
, htmlCreator(NS_NewHTMLFormElement
));
4412 appendElement(elt
, currentNode
);
4413 elementPushed(kNameSpaceID_XHTML
, nsGkAtoms::form
, elt
);
4414 elementPopped(kNameSpaceID_XHTML
, nsGkAtoms::form
, elt
);
4417 void nsHtml5TreeBuilder::requestSuspension() {
4418 tokenizer
->requestSuspension();
4422 bool nsHtml5TreeBuilder::isInForeign() {
4423 return currentPtr
>= 0 && stack
[currentPtr
]->ns
!= kNameSpaceID_XHTML
;
4426 bool nsHtml5TreeBuilder::isInForeignButNotHtmlOrMathTextIntegrationPoint() {
4427 if (currentPtr
< 0) {
4430 return !isSpecialParentInForeign(stack
[currentPtr
]);
4433 void nsHtml5TreeBuilder::setFragmentContext(nsAtom
* context
, int32_t ns
,
4434 nsIContentHandle
* node
,
4436 this->contextName
= context
;
4437 this->contextNamespace
= ns
;
4438 this->contextNode
= node
;
4439 this->fragment
= (!!contextName
);
4440 this->quirks
= quirks
;
4443 nsIContentHandle
* nsHtml5TreeBuilder::currentNode() {
4444 return stack
[currentPtr
]->node
;
4447 bool nsHtml5TreeBuilder::isScriptingEnabled() { return scriptingEnabled
; }
4449 void nsHtml5TreeBuilder::setScriptingEnabled(bool scriptingEnabled
) {
4450 this->scriptingEnabled
= scriptingEnabled
;
4453 void nsHtml5TreeBuilder::setForceNoQuirks(bool forceNoQuirks
) {
4454 this->forceNoQuirks
= forceNoQuirks
;
4457 void nsHtml5TreeBuilder::setIsSrcdocDocument(bool isSrcdocDocument
) {
4458 this->setForceNoQuirks(isSrcdocDocument
);
4461 void nsHtml5TreeBuilder::flushCharacters() {
4462 if (charBufferLen
> 0) {
4463 if ((mode
== IN_TABLE
|| mode
== IN_TABLE_BODY
|| mode
== IN_ROW
) &&
4464 charBufferContainsNonWhitespace()) {
4465 errNonSpaceInTable();
4466 reconstructTheActiveFormattingElements();
4467 if (!stack
[currentPtr
]->isFosterParenting()) {
4468 appendCharacters(currentNode(), charBuffer
, 0, charBufferLen
);
4472 int32_t tablePos
= findLastOrRoot(nsHtml5TreeBuilder::TABLE
);
4473 int32_t templatePos
= findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE
);
4474 if (templatePos
>= tablePos
) {
4475 appendCharacters(stack
[templatePos
]->node
, charBuffer
, 0,
4480 nsHtml5StackNode
* tableElt
= stack
[tablePos
];
4481 insertFosterParentedCharacters(charBuffer
, 0, charBufferLen
,
4482 tableElt
->node
, stack
[tablePos
- 1]->node
);
4486 appendCharacters(currentNode(), charBuffer
, 0, charBufferLen
);
4491 bool nsHtml5TreeBuilder::charBufferContainsNonWhitespace() {
4492 for (int32_t i
= 0; i
< charBufferLen
; i
++) {
4493 switch (charBuffer
[i
]) {
4509 nsAHtml5TreeBuilderState
* nsHtml5TreeBuilder::newSnapshot() {
4510 jArray
<nsHtml5StackNode
*, int32_t> listCopy
=
4511 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(listPtr
+ 1);
4512 for (int32_t i
= 0; i
< listCopy
.length
; i
++) {
4513 nsHtml5StackNode
* node
= listOfActiveFormattingElements
[i
];
4515 nsHtml5StackNode
* newNode
= new nsHtml5StackNode(-1);
4516 newNode
->setValues(node
->getFlags(), node
->ns
, node
->name
, node
->node
,
4517 node
->popName
, node
->attributes
->cloneAttributes(),
4518 node
->getHtmlCreator());
4519 listCopy
[i
] = newNode
;
4521 listCopy
[i
] = nullptr;
4524 jArray
<nsHtml5StackNode
*, int32_t> stackCopy
=
4525 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(currentPtr
+ 1);
4526 for (int32_t i
= 0; i
< stackCopy
.length
; i
++) {
4527 nsHtml5StackNode
* node
= stack
[i
];
4528 int32_t listIndex
= findInListOfActiveFormattingElements(node
);
4529 if (listIndex
== -1) {
4530 nsHtml5StackNode
* newNode
= new nsHtml5StackNode(-1);
4531 newNode
->setValues(node
->getFlags(), node
->ns
, node
->name
, node
->node
,
4532 node
->popName
, nullptr, node
->getHtmlCreator());
4533 stackCopy
[i
] = newNode
;
4535 stackCopy
[i
] = listCopy
[listIndex
];
4536 stackCopy
[i
]->retain();
4539 jArray
<int32_t, int32_t> templateModeStackCopy
=
4540 jArray
<int32_t, int32_t>::newJArray(templateModePtr
+ 1);
4541 nsHtml5ArrayCopy::arraycopy(templateModeStack
, templateModeStackCopy
,
4542 templateModeStackCopy
.length
);
4543 return new nsHtml5StateSnapshot(stackCopy
, listCopy
, templateModeStackCopy
,
4544 formPointer
, headPointer
, mode
, originalMode
,
4545 framesetOk
, needToDropLF
, quirks
);
4548 bool nsHtml5TreeBuilder::snapshotMatches(nsAHtml5TreeBuilderState
* snapshot
) {
4549 jArray
<nsHtml5StackNode
*, int32_t> stackCopy
= snapshot
->getStack();
4550 int32_t stackLen
= snapshot
->getStackLength();
4551 jArray
<nsHtml5StackNode
*, int32_t> listCopy
=
4552 snapshot
->getListOfActiveFormattingElements();
4553 int32_t listLen
= snapshot
->getListOfActiveFormattingElementsLength();
4554 jArray
<int32_t, int32_t> templateModeStackCopy
=
4555 snapshot
->getTemplateModeStack();
4556 int32_t templateModeStackLen
= snapshot
->getTemplateModeStackLength();
4557 if (stackLen
!= currentPtr
+ 1 || listLen
!= listPtr
+ 1 ||
4558 templateModeStackLen
!= templateModePtr
+ 1 ||
4559 formPointer
!= snapshot
->getFormPointer() ||
4560 headPointer
!= snapshot
->getHeadPointer() ||
4561 mode
!= snapshot
->getMode() ||
4562 originalMode
!= snapshot
->getOriginalMode() ||
4563 framesetOk
!= snapshot
->isFramesetOk() ||
4564 needToDropLF
!= snapshot
->isNeedToDropLF() ||
4565 quirks
!= snapshot
->isQuirks()) {
4568 for (int32_t i
= listLen
- 1; i
>= 0; i
--) {
4569 if (!listCopy
[i
] && !listOfActiveFormattingElements
[i
]) {
4571 } else if (!listCopy
[i
] || !listOfActiveFormattingElements
[i
]) {
4574 if (listCopy
[i
]->node
!= listOfActiveFormattingElements
[i
]->node
) {
4578 for (int32_t i
= stackLen
- 1; i
>= 0; i
--) {
4579 if (stackCopy
[i
]->node
!= stack
[i
]->node
) {
4583 for (int32_t i
= templateModeStackLen
- 1; i
>= 0; i
--) {
4584 if (templateModeStackCopy
[i
] != templateModeStack
[i
]) {
4591 void nsHtml5TreeBuilder::loadState(nsAHtml5TreeBuilderState
* snapshot
) {
4592 mCurrentHtmlScriptCannotDocumentWriteOrBlock
= false;
4593 jArray
<nsHtml5StackNode
*, int32_t> stackCopy
= snapshot
->getStack();
4594 int32_t stackLen
= snapshot
->getStackLength();
4595 jArray
<nsHtml5StackNode
*, int32_t> listCopy
=
4596 snapshot
->getListOfActiveFormattingElements();
4597 int32_t listLen
= snapshot
->getListOfActiveFormattingElementsLength();
4598 jArray
<int32_t, int32_t> templateModeStackCopy
=
4599 snapshot
->getTemplateModeStack();
4600 int32_t templateModeStackLen
= snapshot
->getTemplateModeStackLength();
4601 for (int32_t i
= 0; i
<= listPtr
; i
++) {
4602 if (listOfActiveFormattingElements
[i
]) {
4603 listOfActiveFormattingElements
[i
]->release(this);
4606 if (listOfActiveFormattingElements
.length
< listLen
) {
4607 listOfActiveFormattingElements
=
4608 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(listLen
);
4610 listPtr
= listLen
- 1;
4611 for (int32_t i
= 0; i
<= currentPtr
; i
++) {
4612 stack
[i
]->release(this);
4614 if (stack
.length
< stackLen
) {
4615 stack
= jArray
<nsHtml5StackNode
*, int32_t>::newJArray(stackLen
);
4617 currentPtr
= stackLen
- 1;
4618 if (templateModeStack
.length
< templateModeStackLen
) {
4620 jArray
<int32_t, int32_t>::newJArray(templateModeStackLen
);
4622 templateModePtr
= templateModeStackLen
- 1;
4623 for (int32_t i
= 0; i
< listLen
; i
++) {
4624 nsHtml5StackNode
* node
= listCopy
[i
];
4626 nsHtml5StackNode
* newNode
= createStackNode(
4627 node
->getFlags(), node
->ns
, node
->name
, node
->node
, node
->popName
,
4628 node
->attributes
->cloneAttributes(), node
->getHtmlCreator());
4629 listOfActiveFormattingElements
[i
] = newNode
;
4631 listOfActiveFormattingElements
[i
] = nullptr;
4634 for (int32_t i
= 0; i
< stackLen
; i
++) {
4635 nsHtml5StackNode
* node
= stackCopy
[i
];
4636 int32_t listIndex
= findInArray(node
, listCopy
);
4637 if (listIndex
== -1) {
4638 nsHtml5StackNode
* newNode
=
4639 createStackNode(node
->getFlags(), node
->ns
, node
->name
, node
->node
,
4640 node
->popName
, nullptr, node
->getHtmlCreator());
4643 stack
[i
] = listOfActiveFormattingElements
[listIndex
];
4647 nsHtml5ArrayCopy::arraycopy(templateModeStackCopy
, templateModeStack
,
4648 templateModeStackLen
);
4649 formPointer
= snapshot
->getFormPointer();
4650 headPointer
= snapshot
->getHeadPointer();
4651 mode
= snapshot
->getMode();
4652 originalMode
= snapshot
->getOriginalMode();
4653 framesetOk
= snapshot
->isFramesetOk();
4654 needToDropLF
= snapshot
->isNeedToDropLF();
4655 quirks
= snapshot
->isQuirks();
4658 int32_t nsHtml5TreeBuilder::findInArray(
4659 nsHtml5StackNode
* node
, jArray
<nsHtml5StackNode
*, int32_t> arr
) {
4660 for (int32_t i
= listPtr
; i
>= 0; i
--) {
4661 if (node
== arr
[i
]) {
4668 nsIContentHandle
* nsHtml5TreeBuilder::nodeFromStackWithBlinkCompat(
4670 if (stackPos
> 511) {
4672 return stack
[511]->node
;
4674 return stack
[stackPos
]->node
;
4677 nsIContentHandle
* nsHtml5TreeBuilder::getFormPointer() { return formPointer
; }
4679 nsIContentHandle
* nsHtml5TreeBuilder::getHeadPointer() { return headPointer
; }
4681 jArray
<nsHtml5StackNode
*, int32_t>
4682 nsHtml5TreeBuilder::getListOfActiveFormattingElements() {
4683 return listOfActiveFormattingElements
;
4686 jArray
<nsHtml5StackNode
*, int32_t> nsHtml5TreeBuilder::getStack() {
4690 jArray
<int32_t, int32_t> nsHtml5TreeBuilder::getTemplateModeStack() {
4691 return templateModeStack
;
4694 int32_t nsHtml5TreeBuilder::getMode() { return mode
; }
4696 int32_t nsHtml5TreeBuilder::getOriginalMode() { return originalMode
; }
4698 bool nsHtml5TreeBuilder::isFramesetOk() { return framesetOk
; }
4700 bool nsHtml5TreeBuilder::isNeedToDropLF() { return needToDropLF
; }
4702 bool nsHtml5TreeBuilder::isQuirks() { return quirks
; }
4704 int32_t nsHtml5TreeBuilder::getListOfActiveFormattingElementsLength() {
4708 int32_t nsHtml5TreeBuilder::getStackLength() { return currentPtr
+ 1; }
4710 int32_t nsHtml5TreeBuilder::getTemplateModeStackLength() {
4711 return templateModePtr
+ 1;
4714 void nsHtml5TreeBuilder::initializeStatics() {}
4716 void nsHtml5TreeBuilder::releaseStatics() {}
4718 #include "nsHtml5TreeBuilderCppSupplement.h"