2 * Copyright (c) 2007 Henri Sivonen
3 * Copyright (c) 2007-2015 Mozilla Foundation
4 * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla
5 * Foundation, and Opera Software ASA.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
27 * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
28 * Please edit TreeBuilder.java instead and regenerate.
31 #define nsHtml5TreeBuilder_cpp__
33 #include "nsContentUtils.h"
35 #include "nsHtml5AtomTable.h"
37 #include "nsHtml5String.h"
38 #include "nsNameSpaceManager.h"
39 #include "nsIContent.h"
40 #include "nsTraceRefcnt.h"
42 #include "nsHtml5DocumentMode.h"
43 #include "nsHtml5ArrayCopy.h"
44 #include "nsHtml5Parser.h"
45 #include "nsGkAtoms.h"
46 #include "nsHtml5TreeOperation.h"
47 #include "nsHtml5StateSnapshot.h"
48 #include "nsHtml5StackNode.h"
49 #include "nsHtml5TreeOpExecutor.h"
50 #include "nsHtml5StreamParser.h"
51 #include "nsAHtml5TreeBuilderState.h"
52 #include "nsHtml5Highlighter.h"
53 #include "nsHtml5PlainTextUtils.h"
54 #include "nsHtml5ViewSourceUtils.h"
55 #include "mozilla/Likely.h"
56 #include "nsIContentHandle.h"
57 #include "nsHtml5OplessBuilder.h"
59 #include "nsHtml5AttributeName.h"
60 #include "nsHtml5ElementName.h"
61 #include "nsHtml5Tokenizer.h"
62 #include "nsHtml5MetaScanner.h"
63 #include "nsHtml5StackNode.h"
64 #include "nsHtml5UTF16Buffer.h"
65 #include "nsHtml5StateSnapshot.h"
66 #include "nsHtml5Portability.h"
68 #include "nsHtml5TreeBuilder.h"
70 char16_t
nsHtml5TreeBuilder::REPLACEMENT_CHARACTER
[] = { 0xfffd };
71 static const char* const QUIRKY_PUBLIC_IDS_DATA
[] = {
72 "+//silmaril//dtd html pro v0r11 19970101//",
73 "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
74 "-//as//dtd html 3.0 aswedit + extensions//",
75 "-//ietf//dtd html 2.0 level 1//",
76 "-//ietf//dtd html 2.0 level 2//",
77 "-//ietf//dtd html 2.0 strict level 1//",
78 "-//ietf//dtd html 2.0 strict level 2//",
79 "-//ietf//dtd html 2.0 strict//",
80 "-//ietf//dtd html 2.0//",
81 "-//ietf//dtd html 2.1e//",
82 "-//ietf//dtd html 3.0//",
83 "-//ietf//dtd html 3.2 final//",
84 "-//ietf//dtd html 3.2//",
85 "-//ietf//dtd html 3//",
86 "-//ietf//dtd html level 0//",
87 "-//ietf//dtd html level 1//",
88 "-//ietf//dtd html level 2//",
89 "-//ietf//dtd html level 3//",
90 "-//ietf//dtd html strict level 0//",
91 "-//ietf//dtd html strict level 1//",
92 "-//ietf//dtd html strict level 2//",
93 "-//ietf//dtd html strict level 3//",
94 "-//ietf//dtd html strict//",
95 "-//ietf//dtd html//",
96 "-//metrius//dtd metrius presentational//",
97 "-//microsoft//dtd internet explorer 2.0 html strict//",
98 "-//microsoft//dtd internet explorer 2.0 html//",
99 "-//microsoft//dtd internet explorer 2.0 tables//",
100 "-//microsoft//dtd internet explorer 3.0 html strict//",
101 "-//microsoft//dtd internet explorer 3.0 html//",
102 "-//microsoft//dtd internet explorer 3.0 tables//",
103 "-//netscape comm. corp.//dtd html//",
104 "-//netscape comm. corp.//dtd strict html//",
105 "-//o'reilly and associates//dtd html 2.0//",
106 "-//o'reilly and associates//dtd html extended 1.0//",
107 "-//o'reilly and associates//dtd html extended relaxed 1.0//",
108 "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html "
110 "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
111 "-//spyglass//dtd html 2.0 extended//",
112 "-//sq//dtd html 2.0 hotmetal + extensions//",
113 "-//sun microsystems corp.//dtd hotjava html//",
114 "-//sun microsystems corp.//dtd hotjava strict html//",
115 "-//w3c//dtd html 3 1995-03-24//",
116 "-//w3c//dtd html 3.2 draft//",
117 "-//w3c//dtd html 3.2 final//",
118 "-//w3c//dtd html 3.2//",
119 "-//w3c//dtd html 3.2s draft//",
120 "-//w3c//dtd html 4.0 frameset//",
121 "-//w3c//dtd html 4.0 transitional//",
122 "-//w3c//dtd html experimental 19960712//",
123 "-//w3c//dtd html experimental 970421//",
124 "-//w3c//dtd w3 html//",
125 "-//w3o//dtd w3 html 3.0//",
126 "-//webtechs//dtd mozilla html 2.0//",
127 "-//webtechs//dtd mozilla html//"
129 staticJArray
<const char*, int32_t> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS
= {
130 QUIRKY_PUBLIC_IDS_DATA
,
131 MOZ_ARRAY_LENGTH(QUIRKY_PUBLIC_IDS_DATA
)
134 nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer
* self
)
137 stackNodes
= jArray
<nsHtml5StackNode
*, int32_t>::newJArray(64);
138 stack
= jArray
<nsHtml5StackNode
*, int32_t>::newJArray(64);
139 templateModeStack
= jArray
<int32_t, int32_t>::newJArray(64);
140 listOfActiveFormattingElements
=
141 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(64);
142 needToDropLF
= false;
143 originalMode
= INITIAL
;
144 templateModePtr
= -1;
149 formPointer
= nullptr;
150 headPointer
= nullptr;
151 deepTreeSurrogateParent
= nullptr;
154 charBuffer
= nullptr;
157 nsIContentHandle
* elt
;
161 elt
= createHtmlElementSetAsRoot(tokenizer
->emptyAttributes());
163 if (contextNamespace
== kNameSpaceID_SVG
) {
164 nsHtml5ElementName
* elementName
= nsHtml5ElementName::ELT_SVG
;
165 if (nsGkAtoms::title
== contextName
|| nsGkAtoms::desc
== contextName
||
166 nsGkAtoms::foreignObject
== contextName
) {
167 elementName
= nsHtml5ElementName::ELT_FOREIGNOBJECT
;
169 nsHtml5StackNode
* node
=
170 createStackNode(elementName
, elementName
->getCamelCaseName(), elt
);
172 stack
[currentPtr
] = node
;
173 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::DATA
,
176 } else if (contextNamespace
== kNameSpaceID_MathML
) {
177 nsHtml5ElementName
* elementName
= nsHtml5ElementName::ELT_MATH
;
178 if (nsGkAtoms::mi_
== contextName
|| nsGkAtoms::mo_
== contextName
||
179 nsGkAtoms::mn_
== contextName
|| nsGkAtoms::ms_
== contextName
||
180 nsGkAtoms::mtext_
== contextName
) {
181 elementName
= nsHtml5ElementName::ELT_MTEXT
;
182 } else if (nsGkAtoms::annotation_xml_
== contextName
) {
183 elementName
= nsHtml5ElementName::ELT_ANNOTATION_XML
;
185 nsHtml5StackNode
* node
=
186 createStackNode(elementName
, elt
, elementName
->getName(), false);
188 stack
[currentPtr
] = node
;
189 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::DATA
,
193 nsHtml5StackNode
* node
=
194 createStackNode(nsHtml5ElementName::ELT_HTML
, elt
);
196 stack
[currentPtr
] = node
;
197 if (nsGkAtoms::_template
== contextName
) {
198 pushTemplateMode(IN_TEMPLATE
);
200 resetTheInsertionMode();
201 formPointer
= getFormPointerForContext(contextNode
);
202 if (nsGkAtoms::title
== contextName
||
203 nsGkAtoms::textarea
== contextName
) {
204 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA
,
206 } else if (nsGkAtoms::style
== contextName
||
207 nsGkAtoms::xmp
== contextName
||
208 nsGkAtoms::iframe
== contextName
||
209 nsGkAtoms::noembed
== contextName
||
210 nsGkAtoms::noframes
== contextName
||
211 (scriptingEnabled
&& nsGkAtoms::noscript
== contextName
)) {
212 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
214 } else if (nsGkAtoms::plaintext
== contextName
) {
215 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::PLAINTEXT
,
217 } else if (nsGkAtoms::script
== contextName
) {
218 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::SCRIPT_DATA
,
221 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::DATA
,
225 contextName
= nullptr;
226 contextNode
= nullptr;
229 if (tokenizer
->isViewingXmlSource()) {
230 nsIContentHandle
* elt
= createElement(kNameSpaceID_SVG
,
232 tokenizer
->emptyAttributes(),
234 svgCreator(NS_NewSVGSVGElement
));
235 nsHtml5StackNode
* node
=
236 createStackNode(nsHtml5ElementName::ELT_SVG
, nsGkAtoms::svg
, elt
);
238 stack
[currentPtr
] = node
;
244 nsHtml5TreeBuilder::doctype(nsAtom
* name
,
245 nsHtml5String publicIdentifier
,
246 nsHtml5String systemIdentifier
,
249 needToDropLF
= false;
250 if (!isInForeign() && mode
== INITIAL
) {
251 nsHtml5String emptyString
= nsHtml5Portability::newEmptyString();
252 appendDoctypeToDocument(!name
? nsGkAtoms::_empty
: name
,
253 !publicIdentifier
? emptyString
: publicIdentifier
,
254 !systemIdentifier
? emptyString
: systemIdentifier
);
255 emptyString
.Release();
256 if (isQuirky(name
, publicIdentifier
, systemIdentifier
, forceQuirks
)) {
258 documentModeInternal(
259 QUIRKS_MODE
, publicIdentifier
, systemIdentifier
, false);
260 } else if (isAlmostStandards(publicIdentifier
, systemIdentifier
)) {
261 errAlmostStandardsDoctype();
262 documentModeInternal(
263 ALMOST_STANDARDS_MODE
, publicIdentifier
, systemIdentifier
, false);
265 documentModeInternal(
266 STANDARDS_MODE
, publicIdentifier
, systemIdentifier
, false);
276 nsHtml5TreeBuilder::comment(char16_t
* buf
, int32_t start
, int32_t length
)
278 needToDropLF
= false;
279 if (!isInForeign()) {
283 case AFTER_AFTER_BODY
:
284 case AFTER_AFTER_FRAMESET
: {
285 appendCommentToDocument(buf
, start
, length
);
290 appendComment(stack
[0]->node
, buf
, start
, length
);
299 appendComment(stack
[currentPtr
]->node
, buf
, start
, length
);
304 nsHtml5TreeBuilder::characters(const char16_t
* buf
,
308 if (tokenizer
->isViewingXmlSource()) {
312 needToDropLF
= false;
313 if (buf
[start
] == '\n') {
325 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
326 reconstructTheActiveFormattingElements();
331 accumulateCharacters(buf
, start
, length
);
337 accumulateCharactersForced(buf
, start
, length
);
341 int32_t end
= start
+ length
;
342 for (int32_t i
= start
; i
< end
; i
++) {
357 case IN_HEAD_NOSCRIPT
:
359 case IN_COLUMN_GROUP
:
361 case AFTER_FRAMESET
: {
370 accumulateCharacters(buf
, start
, i
- start
);
373 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
375 reconstructTheActiveFormattingElements();
377 NS_HTML5_BREAK(charactersloop
);
380 case IN_SELECT_IN_TABLE
: {
381 NS_HTML5_BREAK(charactersloop
);
386 accumulateCharactersForced(buf
, i
, 1);
391 case AFTER_AFTER_BODY
:
392 case AFTER_AFTER_FRAMESET
: {
394 accumulateCharacters(buf
, start
, i
- start
);
398 reconstructTheActiveFormattingElements();
402 MOZ_FALLTHROUGH_ASSERT();
407 documentModeInternal(QUIRKS_MODE
, nullptr, nullptr, false);
413 appendHtmlElementToDocumentAndPush();
420 accumulateCharacters(buf
, start
, i
- start
);
424 appendToCurrentNodeAndPushHeadElement(
425 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
432 accumulateCharacters(buf
, start
, i
- start
);
441 case IN_HEAD_NOSCRIPT
: {
443 accumulateCharacters(buf
, start
, i
- start
);
446 errNonSpaceInNoscriptInHead();
455 accumulateCharacters(buf
, start
, i
- start
);
459 appendToCurrentNodeAndPushBodyElement();
475 accumulateCharacters(buf
, start
, i
- start
);
478 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
480 reconstructTheActiveFormattingElements();
482 NS_HTML5_BREAK(charactersloop
);
487 accumulateCharactersForced(buf
, i
, 1);
491 case IN_COLUMN_GROUP
: {
493 accumulateCharacters(buf
, start
, i
- start
);
496 if (!currentPtr
|| stack
[currentPtr
]->getGroup() ==
497 nsHtml5TreeBuilder::TEMPLATE
) {
498 errNonSpaceInColgroupInFragment();
509 case IN_SELECT_IN_TABLE
: {
510 NS_HTML5_BREAK(charactersloop
);
513 errNonSpaceAfterBody();
515 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
521 accumulateCharacters(buf
, start
, i
- start
);
523 errNonSpaceInFrameset();
527 case AFTER_FRAMESET
: {
529 accumulateCharacters(buf
, start
, i
- start
);
531 errNonSpaceAfterFrameset();
535 case AFTER_AFTER_BODY
: {
536 errNonSpaceInTrailer();
537 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
541 case AFTER_AFTER_FRAMESET
: {
543 accumulateCharacters(buf
, start
, i
- start
);
545 errNonSpaceInTrailer();
555 accumulateCharacters(buf
, start
, end
- start
);
562 nsHtml5TreeBuilder::zeroOriginatingReplacementCharacter()
565 accumulateCharacters(REPLACEMENT_CHARACTER
, 0, 1);
568 if (currentPtr
>= 0) {
569 if (isSpecialParentInForeign(stack
[currentPtr
])) {
572 accumulateCharacters(REPLACEMENT_CHARACTER
, 0, 1);
577 nsHtml5TreeBuilder::eof()
583 documentModeInternal(QUIRKS_MODE
, nullptr, nullptr, false);
588 appendHtmlElementToDocumentAndPush();
593 appendToCurrentNodeAndPushHeadElement(
594 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
599 while (currentPtr
> 0) {
605 case IN_HEAD_NOSCRIPT
: {
606 while (currentPtr
> 1) {
613 appendToCurrentNodeAndPushBodyElement();
620 case IN_SELECT_IN_TABLE
:
622 case IN_COLUMN_GROUP
:
627 if (isTemplateModeStackEmpty()) {
628 NS_HTML5_BREAK(eofloop
);
633 int32_t eltPos
= findLast(nsGkAtoms::_template
);
634 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
635 MOZ_ASSERT(fragment
);
636 NS_HTML5_BREAK(eofloop
);
638 if (MOZ_UNLIKELY(mViewSource
)) {
639 errUnclosedElements(eltPos
, nsGkAtoms::_template
);
641 while (currentPtr
>= eltPos
) {
644 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
646 resetTheInsertionMode();
650 if (originalMode
== AFTER_HEAD
) {
658 NS_HTML5_BREAK(eofloop
);
662 case AFTER_AFTER_BODY
:
663 case AFTER_AFTER_FRAMESET
:
665 NS_HTML5_BREAK(eofloop
);
670 while (currentPtr
> 0) {
679 nsHtml5TreeBuilder::endTokenization()
681 formPointer
= nullptr;
682 headPointer
= nullptr;
683 deepTreeSurrogateParent
= nullptr;
684 templateModeStack
= nullptr;
686 while (currentPtr
> -1) {
687 stack
[currentPtr
]->release(this);
692 if (listOfActiveFormattingElements
) {
693 while (listPtr
> -1) {
694 if (listOfActiveFormattingElements
[listPtr
]) {
695 listOfActiveFormattingElements
[listPtr
]->release(this);
699 listOfActiveFormattingElements
= nullptr;
702 for (int32_t i
= 0; i
< numStackNodes
; i
++) {
703 MOZ_ASSERT(stackNodes
[i
]->isUnused());
704 delete stackNodes
[i
];
708 stackNodes
= nullptr;
710 charBuffer
= nullptr;
715 nsHtml5TreeBuilder::startTag(nsHtml5ElementName
* elementName
,
716 nsHtml5HtmlAttributes
* attributes
,
721 needToDropLF
= false;
724 int32_t group
= elementName
->getGroup();
725 nsAtom
* name
= elementName
->getName();
727 nsHtml5StackNode
* currentNode
= stack
[currentPtr
];
728 int32_t currNs
= currentNode
->ns
;
729 if (!(currentNode
->isHtmlIntegrationPoint() ||
730 (currNs
== kNameSpaceID_MathML
&&
731 ((currentNode
->getGroup() == MI_MO_MN_MS_MTEXT
&&
732 group
!= MGLYPH_OR_MALIGNMARK
) ||
733 (currentNode
->getGroup() == ANNOTATION_XML
&& group
== SVG
))))) {
735 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U
:
736 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU
:
739 case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR
:
744 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
:
754 if (!(group
== FONT
&&
755 !(attributes
->contains(nsHtml5AttributeName::ATTR_COLOR
) ||
756 attributes
->contains(nsHtml5AttributeName::ATTR_FACE
) ||
757 attributes
->contains(nsHtml5AttributeName::ATTR_SIZE
)))) {
758 errHtmlStartTagInForeignContext(name
);
760 while (!isSpecialParentInForeign(stack
[currentPtr
])) {
763 NS_HTML5_CONTINUE(starttagloop
);
769 if (kNameSpaceID_SVG
== currNs
) {
770 attributes
->adjustForSvg();
772 appendVoidElementToCurrentMayFosterSVG(elementName
, attributes
);
775 appendToCurrentNodeAndPushElementMayFosterSVG(elementName
,
778 attributes
= nullptr;
779 NS_HTML5_BREAK(starttagloop
);
781 attributes
->adjustForMath();
783 appendVoidElementToCurrentMayFosterMathML(elementName
,
787 appendToCurrentNodeAndPushElementMayFosterMathML(elementName
,
790 attributes
= nullptr;
791 NS_HTML5_BREAK(starttagloop
);
802 pushTemplateMode(IN_COLUMN_GROUP
);
803 mode
= IN_COLUMN_GROUP
;
808 case TBODY_OR_THEAD_OR_TFOOT
: {
810 pushTemplateMode(IN_TABLE
);
816 pushTemplateMode(IN_TABLE_BODY
);
817 mode
= IN_TABLE_BODY
;
822 pushTemplateMode(IN_ROW
);
827 checkMetaCharset(attributes
);
828 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
830 attributes
= nullptr;
831 NS_HTML5_BREAK(starttagloop
);
834 startTagTitleInHead(elementName
, attributes
);
835 attributes
= nullptr;
836 NS_HTML5_BREAK(starttagloop
);
839 case LINK_OR_BASEFONT_OR_BGSOUND
: {
840 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
842 attributes
= nullptr;
843 NS_HTML5_BREAK(starttagloop
);
846 startTagScriptInHead(elementName
, attributes
);
847 attributes
= nullptr;
848 NS_HTML5_BREAK(starttagloop
);
852 startTagGenericRawText(elementName
, attributes
);
853 attributes
= nullptr;
854 NS_HTML5_BREAK(starttagloop
);
857 startTagTemplateInHead(elementName
, attributes
);
858 attributes
= nullptr;
859 NS_HTML5_BREAK(starttagloop
);
863 pushTemplateMode(IN_BODY
);
872 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TR
));
873 appendToCurrentNodeAndPushElement(elementName
, attributes
);
876 attributes
= nullptr;
877 NS_HTML5_BREAK(starttagloop
);
882 case TBODY_OR_THEAD_OR_TFOOT
:
884 eltPos
= findLastOrRoot(nsHtml5TreeBuilder::TR
);
886 MOZ_ASSERT(fragment
|| isTemplateContents());
887 errNoTableRowToClose();
888 NS_HTML5_BREAK(starttagloop
);
890 clearStackBackTo(eltPos
);
892 mode
= IN_TABLE_BODY
;
895 default:; // fall through
899 case IN_TABLE_BODY
: {
903 findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
904 appendToCurrentNodeAndPushElement(elementName
, attributes
);
906 attributes
= nullptr;
907 NS_HTML5_BREAK(starttagloop
);
910 errStartTagInTableBody(name
);
912 findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
913 appendToCurrentNodeAndPushElement(
914 nsHtml5ElementName::ELT_TR
,
915 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
922 case TBODY_OR_THEAD_OR_TFOOT
: {
923 eltPos
= findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
924 if (!eltPos
|| stack
[eltPos
]->getGroup() == TEMPLATE
) {
925 MOZ_ASSERT(fragment
|| isTemplateContents());
926 errStrayStartTag(name
);
927 NS_HTML5_BREAK(starttagloop
);
929 clearStackBackTo(eltPos
);
935 default:; // fall through
943 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
945 appendToCurrentNodeAndPushElement(elementName
, attributes
);
947 attributes
= nullptr;
948 NS_HTML5_BREAK(starttagloop
);
951 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
952 appendToCurrentNodeAndPushElement(elementName
, attributes
);
953 mode
= IN_COLUMN_GROUP
;
954 attributes
= nullptr;
955 NS_HTML5_BREAK(starttagloop
);
958 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
959 appendToCurrentNodeAndPushElement(
960 nsHtml5ElementName::ELT_COLGROUP
,
961 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
962 mode
= IN_COLUMN_GROUP
;
963 NS_HTML5_CONTINUE(starttagloop
);
965 case TBODY_OR_THEAD_OR_TFOOT
: {
966 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
967 appendToCurrentNodeAndPushElement(elementName
, attributes
);
968 mode
= IN_TABLE_BODY
;
969 attributes
= nullptr;
970 NS_HTML5_BREAK(starttagloop
);
974 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE
));
975 appendToCurrentNodeAndPushElement(
976 nsHtml5ElementName::ELT_TBODY
,
977 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
978 mode
= IN_TABLE_BODY
;
979 NS_HTML5_CONTINUE(starttagloop
);
982 NS_HTML5_BREAK(intableloop
);
985 errTableSeenWhileTableOpen();
986 eltPos
= findLastInTableScope(name
);
987 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
988 MOZ_ASSERT(fragment
|| isTemplateContents());
989 NS_HTML5_BREAK(starttagloop
);
991 generateImpliedEndTags();
992 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(nsGkAtoms::table
)) {
993 errNoCheckUnclosedElementsOnStack();
995 while (currentPtr
>= eltPos
) {
998 resetTheInsertionMode();
999 NS_HTML5_CONTINUE(starttagloop
);
1002 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1003 originalMode
= mode
;
1005 tokenizer
->setStateAndEndTagExpectation(
1006 nsHtml5Tokenizer::SCRIPT_DATA
, elementName
);
1007 attributes
= nullptr;
1008 NS_HTML5_BREAK(starttagloop
);
1011 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1012 originalMode
= mode
;
1014 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
1016 attributes
= nullptr;
1017 NS_HTML5_BREAK(starttagloop
);
1020 errStartTagInTable(name
);
1021 if (!nsHtml5Portability::
1022 lowerCaseLiteralEqualsIgnoreAsciiCaseString(
1024 attributes
->getValue(nsHtml5AttributeName::ATTR_TYPE
))) {
1025 NS_HTML5_BREAK(intableloop
);
1027 appendVoidInputToCurrent(attributes
, formPointer
);
1028 selfClosing
= false;
1029 attributes
= nullptr;
1030 NS_HTML5_BREAK(starttagloop
);
1033 if (!!formPointer
|| isTemplateContents()) {
1034 errFormWhenFormOpen();
1035 NS_HTML5_BREAK(starttagloop
);
1037 errStartTagInTable(name
);
1038 appendVoidFormToCurrent(attributes
);
1039 attributes
= nullptr;
1040 NS_HTML5_BREAK(starttagloop
);
1044 errStartTagInTable(name
);
1045 NS_HTML5_BREAK(intableloop
);
1057 case TBODY_OR_THEAD_OR_TFOOT
:
1060 errStrayStartTag(name
);
1061 eltPos
= findLastInTableScope(nsGkAtoms::caption
);
1062 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1063 NS_HTML5_BREAK(starttagloop
);
1065 generateImpliedEndTags();
1066 if (!!MOZ_UNLIKELY(mViewSource
) && currentPtr
!= eltPos
) {
1067 errNoCheckUnclosedElementsOnStack();
1069 while (currentPtr
>= eltPos
) {
1072 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
1076 default:; // fall through
1085 case TBODY_OR_THEAD_OR_TFOOT
:
1088 eltPos
= findLastInTableScopeTdTh();
1089 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1091 NS_HTML5_BREAK(starttagloop
);
1093 closeTheCell(eltPos
);
1097 default:; // fall through
1104 if (mode
== FRAMESET_OK
) {
1105 if (!currentPtr
|| stack
[1]->getGroup() != BODY
) {
1106 MOZ_ASSERT(fragment
|| isTemplateContents());
1107 errStrayStartTag(name
);
1108 NS_HTML5_BREAK(starttagloop
);
1111 detachFromParent(stack
[1]->node
);
1112 while (currentPtr
> 0) {
1115 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1117 attributes
= nullptr;
1118 NS_HTML5_BREAK(starttagloop
);
1121 errStrayStartTag(name
);
1122 NS_HTML5_BREAK(starttagloop
);
1125 case PRE_OR_LISTING
:
1129 case MARQUEE_OR_APPLET
:
1143 if (mode
== FRAMESET_OK
&&
1145 nsHtml5Portability::
1146 lowerCaseLiteralEqualsIgnoreAsciiCaseString(
1148 attributes
->getValue(nsHtml5AttributeName::ATTR_TYPE
)))) {
1154 default:; // fall through
1162 errStrayStartTag(name
);
1163 if (!fragment
&& !isTemplateContents()) {
1164 addAttributesToHtml(attributes
);
1165 attributes
= nullptr;
1167 NS_HTML5_BREAK(starttagloop
);
1170 case LINK_OR_BASEFONT_OR_BGSOUND
:
1176 NS_HTML5_BREAK(inbodyloop
);
1179 if (!currentPtr
|| stack
[1]->getGroup() != BODY
||
1180 isTemplateContents()) {
1181 MOZ_ASSERT(fragment
|| isTemplateContents());
1182 errStrayStartTag(name
);
1183 NS_HTML5_BREAK(starttagloop
);
1185 errFooSeenWhenFooOpen(name
);
1187 if (mode
== FRAMESET_OK
) {
1190 if (addAttributesToBody(attributes
)) {
1191 attributes
= nullptr;
1193 NS_HTML5_BREAK(starttagloop
);
1196 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU
:
1197 case UL_OR_OL_OR_DL
:
1198 case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY
: {
1200 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1202 attributes
= nullptr;
1203 NS_HTML5_BREAK(starttagloop
);
1205 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
: {
1207 if (stack
[currentPtr
]->getGroup() ==
1208 H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
) {
1209 errHeadingWhenHeadingOpen();
1212 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1214 attributes
= nullptr;
1215 NS_HTML5_BREAK(starttagloop
);
1219 appendToCurrentNodeAndPushElementMayFoster(
1220 elementName
, attributes
, formPointer
);
1221 attributes
= nullptr;
1222 NS_HTML5_BREAK(starttagloop
);
1224 case PRE_OR_LISTING
: {
1226 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1228 needToDropLF
= true;
1229 attributes
= nullptr;
1230 NS_HTML5_BREAK(starttagloop
);
1233 if (!!formPointer
&& !isTemplateContents()) {
1234 errFormWhenFormOpen();
1235 NS_HTML5_BREAK(starttagloop
);
1238 appendToCurrentNodeAndPushFormElementMayFoster(attributes
);
1239 attributes
= nullptr;
1240 NS_HTML5_BREAK(starttagloop
);
1245 eltPos
= currentPtr
;
1247 nsHtml5StackNode
* node
= stack
[eltPos
];
1248 if (node
->getGroup() == group
) {
1249 generateImpliedEndTagsExceptFor(node
->name
);
1250 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
1251 errUnclosedElementsImplied(eltPos
, name
);
1253 while (currentPtr
>= eltPos
) {
1257 } else if (!eltPos
|| (node
->isSpecial() &&
1258 (node
->ns
!= kNameSpaceID_XHTML
||
1259 (node
->name
!= nsGkAtoms::p
&&
1260 node
->name
!= nsGkAtoms::address
&&
1261 node
->name
!= nsGkAtoms::div
)))) {
1267 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1269 attributes
= nullptr;
1270 NS_HTML5_BREAK(starttagloop
);
1274 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1276 tokenizer
->setStateAndEndTagExpectation(
1277 nsHtml5Tokenizer::PLAINTEXT
, elementName
);
1278 attributes
= nullptr;
1279 NS_HTML5_BREAK(starttagloop
);
1282 int32_t activeAPos
=
1283 findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
1285 if (activeAPos
!= -1) {
1286 errFooSeenWhenFooOpen(name
);
1287 nsHtml5StackNode
* activeA
=
1288 listOfActiveFormattingElements
[activeAPos
];
1290 adoptionAgencyEndTag(nsGkAtoms::a
);
1291 removeFromStack(activeA
);
1292 activeAPos
= findInListOfActiveFormattingElements(activeA
);
1293 if (activeAPos
!= -1) {
1294 removeFromListOfActiveFormattingElements(activeAPos
);
1296 activeA
->release(this);
1298 reconstructTheActiveFormattingElements();
1299 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName
,
1301 attributes
= nullptr;
1302 NS_HTML5_BREAK(starttagloop
);
1304 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U
:
1306 reconstructTheActiveFormattingElements();
1307 maybeForgetEarlierDuplicateFormattingElement(
1308 elementName
->getName(), attributes
);
1309 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName
,
1311 attributes
= nullptr;
1312 NS_HTML5_BREAK(starttagloop
);
1315 reconstructTheActiveFormattingElements();
1316 if (nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
!=
1317 findLastInScope(nsGkAtoms::nobr
)) {
1318 errFooSeenWhenFooOpen(name
);
1319 adoptionAgencyEndTag(nsGkAtoms::nobr
);
1320 reconstructTheActiveFormattingElements();
1322 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName
,
1324 attributes
= nullptr;
1325 NS_HTML5_BREAK(starttagloop
);
1328 eltPos
= findLastInScope(name
);
1329 if (eltPos
!= nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1330 errFooSeenWhenFooOpen(name
);
1331 generateImpliedEndTags();
1332 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
1333 errUnclosedElementsImplied(eltPos
, name
);
1335 while (currentPtr
>= eltPos
) {
1338 NS_HTML5_CONTINUE(starttagloop
);
1340 reconstructTheActiveFormattingElements();
1341 appendToCurrentNodeAndPushElementMayFoster(
1342 elementName
, attributes
, formPointer
);
1343 attributes
= nullptr;
1344 NS_HTML5_BREAK(starttagloop
);
1348 reconstructTheActiveFormattingElements();
1349 appendToCurrentNodeAndPushElementMayFoster(
1350 elementName
, attributes
, formPointer
);
1352 attributes
= nullptr;
1353 NS_HTML5_BREAK(starttagloop
);
1355 case MARQUEE_OR_APPLET
: {
1356 reconstructTheActiveFormattingElements();
1357 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1360 attributes
= nullptr;
1361 NS_HTML5_BREAK(starttagloop
);
1367 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1370 attributes
= nullptr;
1371 NS_HTML5_BREAK(starttagloop
);
1376 reconstructTheActiveFormattingElements();
1379 #ifdef ENABLE_VOID_MENUITEM
1382 case PARAM_OR_SOURCE_OR_TRACK
: {
1383 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1384 selfClosing
= false;
1385 attributes
= nullptr;
1386 NS_HTML5_BREAK(starttagloop
);
1390 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1391 selfClosing
= false;
1392 attributes
= nullptr;
1393 NS_HTML5_BREAK(starttagloop
);
1397 elementName
= nsHtml5ElementName::ELT_IMG
;
1398 NS_HTML5_CONTINUE(starttagloop
);
1403 reconstructTheActiveFormattingElements();
1404 appendVoidElementToCurrentMayFoster(
1405 elementName
, attributes
, formPointer
);
1406 selfClosing
= false;
1407 attributes
= nullptr;
1408 NS_HTML5_BREAK(starttagloop
);
1411 appendToCurrentNodeAndPushElementMayFoster(
1412 elementName
, attributes
, formPointer
);
1413 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA
,
1415 originalMode
= mode
;
1417 needToDropLF
= true;
1418 attributes
= nullptr;
1419 NS_HTML5_BREAK(starttagloop
);
1423 reconstructTheActiveFormattingElements();
1424 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1426 originalMode
= mode
;
1428 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
1430 attributes
= nullptr;
1431 NS_HTML5_BREAK(starttagloop
);
1434 if (!scriptingEnabled
) {
1435 reconstructTheActiveFormattingElements();
1436 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1438 attributes
= nullptr;
1439 NS_HTML5_BREAK(starttagloop
);
1446 startTagGenericRawText(elementName
, attributes
);
1447 attributes
= nullptr;
1448 NS_HTML5_BREAK(starttagloop
);
1451 reconstructTheActiveFormattingElements();
1452 appendToCurrentNodeAndPushElementMayFoster(
1453 elementName
, attributes
, formPointer
);
1457 case IN_COLUMN_GROUP
:
1461 mode
= IN_SELECT_IN_TABLE
;
1469 attributes
= nullptr;
1470 NS_HTML5_BREAK(starttagloop
);
1474 if (isCurrent(nsGkAtoms::option
)) {
1477 reconstructTheActiveFormattingElements();
1478 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1480 attributes
= nullptr;
1481 NS_HTML5_BREAK(starttagloop
);
1484 eltPos
= findLastInScope(nsGkAtoms::ruby
);
1485 if (eltPos
!= NOT_FOUND_ON_STACK
) {
1486 generateImpliedEndTags();
1488 if (eltPos
!= currentPtr
) {
1489 if (eltPos
== NOT_FOUND_ON_STACK
) {
1490 errStartTagSeenWithoutRuby(name
);
1492 errUnclosedChildrenInRuby();
1495 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1497 attributes
= nullptr;
1498 NS_HTML5_BREAK(starttagloop
);
1501 eltPos
= findLastInScope(nsGkAtoms::ruby
);
1502 if (eltPos
!= NOT_FOUND_ON_STACK
) {
1503 generateImpliedEndTagsExceptFor(nsGkAtoms::rtc
);
1505 if (eltPos
!= currentPtr
) {
1506 if (!isCurrent(nsGkAtoms::rtc
)) {
1507 if (eltPos
== NOT_FOUND_ON_STACK
) {
1508 errStartTagSeenWithoutRuby(name
);
1510 errUnclosedChildrenInRuby();
1514 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1516 attributes
= nullptr;
1517 NS_HTML5_BREAK(starttagloop
);
1520 reconstructTheActiveFormattingElements();
1521 attributes
->adjustForMath();
1523 appendVoidElementToCurrentMayFosterMathML(elementName
,
1525 selfClosing
= false;
1527 appendToCurrentNodeAndPushElementMayFosterMathML(elementName
,
1530 attributes
= nullptr;
1531 NS_HTML5_BREAK(starttagloop
);
1534 reconstructTheActiveFormattingElements();
1535 attributes
->adjustForSvg();
1537 appendVoidElementToCurrentMayFosterSVG(elementName
, attributes
);
1538 selfClosing
= false;
1540 appendToCurrentNodeAndPushElementMayFosterSVG(elementName
,
1543 attributes
= nullptr;
1544 NS_HTML5_BREAK(starttagloop
);
1549 case TBODY_OR_THEAD_OR_TFOOT
:
1555 errStrayStartTag(name
);
1556 NS_HTML5_BREAK(starttagloop
);
1559 reconstructTheActiveFormattingElements();
1560 appendToCurrentNodeAndPushElementMayFoster(
1561 elementName
, attributes
, formPointer
);
1562 attributes
= nullptr;
1563 NS_HTML5_BREAK(starttagloop
);
1566 reconstructTheActiveFormattingElements();
1567 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1569 attributes
= nullptr;
1570 NS_HTML5_BREAK(starttagloop
);
1581 errStrayStartTag(name
);
1582 if (!fragment
&& !isTemplateContents()) {
1583 addAttributesToHtml(attributes
);
1584 attributes
= nullptr;
1586 NS_HTML5_BREAK(starttagloop
);
1589 case LINK_OR_BASEFONT_OR_BGSOUND
: {
1590 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1591 selfClosing
= false;
1592 attributes
= nullptr;
1593 NS_HTML5_BREAK(starttagloop
);
1596 NS_HTML5_BREAK(inheadloop
);
1599 startTagTitleInHead(elementName
, attributes
);
1600 attributes
= nullptr;
1601 NS_HTML5_BREAK(starttagloop
);
1604 if (scriptingEnabled
) {
1605 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1606 originalMode
= mode
;
1608 tokenizer
->setStateAndEndTagExpectation(
1609 nsHtml5Tokenizer::RAWTEXT
, elementName
);
1611 appendToCurrentNodeAndPushElementMayFoster(elementName
,
1613 mode
= IN_HEAD_NOSCRIPT
;
1615 attributes
= nullptr;
1616 NS_HTML5_BREAK(starttagloop
);
1619 startTagScriptInHead(elementName
, attributes
);
1620 attributes
= nullptr;
1621 NS_HTML5_BREAK(starttagloop
);
1625 startTagGenericRawText(elementName
, attributes
);
1626 attributes
= nullptr;
1627 NS_HTML5_BREAK(starttagloop
);
1630 errFooSeenWhenFooOpen(name
);
1631 NS_HTML5_BREAK(starttagloop
);
1634 startTagTemplateInHead(elementName
, attributes
);
1635 attributes
= nullptr;
1636 NS_HTML5_BREAK(starttagloop
);
1641 NS_HTML5_CONTINUE(starttagloop
);
1648 case IN_HEAD_NOSCRIPT
: {
1651 errStrayStartTag(name
);
1652 if (!fragment
&& !isTemplateContents()) {
1653 addAttributesToHtml(attributes
);
1654 attributes
= nullptr;
1656 NS_HTML5_BREAK(starttagloop
);
1658 case LINK_OR_BASEFONT_OR_BGSOUND
: {
1659 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1660 selfClosing
= false;
1661 attributes
= nullptr;
1662 NS_HTML5_BREAK(starttagloop
);
1665 checkMetaCharset(attributes
);
1666 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1667 selfClosing
= false;
1668 attributes
= nullptr;
1669 NS_HTML5_BREAK(starttagloop
);
1673 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1674 originalMode
= mode
;
1676 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
1678 attributes
= nullptr;
1679 NS_HTML5_BREAK(starttagloop
);
1682 errFooSeenWhenFooOpen(name
);
1683 NS_HTML5_BREAK(starttagloop
);
1686 errFooSeenWhenFooOpen(name
);
1687 NS_HTML5_BREAK(starttagloop
);
1690 errBadStartTagInHead(name
);
1697 case IN_COLUMN_GROUP
: {
1700 errStrayStartTag(name
);
1701 if (!fragment
&& !isTemplateContents()) {
1702 addAttributesToHtml(attributes
);
1703 attributes
= nullptr;
1705 NS_HTML5_BREAK(starttagloop
);
1708 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1709 selfClosing
= false;
1710 attributes
= nullptr;
1711 NS_HTML5_BREAK(starttagloop
);
1714 startTagTemplateInHead(elementName
, attributes
);
1715 attributes
= nullptr;
1716 NS_HTML5_BREAK(starttagloop
);
1719 if (!currentPtr
|| stack
[currentPtr
]->getGroup() == TEMPLATE
) {
1720 MOZ_ASSERT(fragment
|| isTemplateContents());
1721 errGarbageInColgroup();
1722 NS_HTML5_BREAK(starttagloop
);
1730 case IN_SELECT_IN_TABLE
: {
1733 case TBODY_OR_THEAD_OR_TFOOT
:
1737 errStartTagWithSelectOpen(name
);
1738 eltPos
= findLastInTableScope(nsGkAtoms::select
);
1739 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1740 MOZ_ASSERT(fragment
);
1741 NS_HTML5_BREAK(starttagloop
);
1743 while (currentPtr
>= eltPos
) {
1746 resetTheInsertionMode();
1749 default:; // fall through
1756 errStrayStartTag(name
);
1758 addAttributesToHtml(attributes
);
1759 attributes
= nullptr;
1761 NS_HTML5_BREAK(starttagloop
);
1764 if (isCurrent(nsGkAtoms::option
)) {
1767 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1768 attributes
= nullptr;
1769 NS_HTML5_BREAK(starttagloop
);
1772 if (isCurrent(nsGkAtoms::option
)) {
1775 if (isCurrent(nsGkAtoms::optgroup
)) {
1778 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1779 attributes
= nullptr;
1780 NS_HTML5_BREAK(starttagloop
);
1783 errStartSelectWhereEndSelectExpected();
1784 eltPos
= findLastInTableScope(name
);
1785 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1786 MOZ_ASSERT(fragment
);
1787 errNoSelectInTableScope();
1788 NS_HTML5_BREAK(starttagloop
);
1790 while (currentPtr
>= eltPos
) {
1793 resetTheInsertionMode();
1794 NS_HTML5_BREAK(starttagloop
);
1800 errStartTagWithSelectOpen(name
);
1801 eltPos
= findLastInTableScope(nsGkAtoms::select
);
1802 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
1803 MOZ_ASSERT(fragment
);
1804 NS_HTML5_BREAK(starttagloop
);
1806 while (currentPtr
>= eltPos
) {
1809 resetTheInsertionMode();
1813 startTagScriptInHead(elementName
, attributes
);
1814 attributes
= nullptr;
1815 NS_HTML5_BREAK(starttagloop
);
1818 startTagTemplateInHead(elementName
, attributes
);
1819 attributes
= nullptr;
1820 NS_HTML5_BREAK(starttagloop
);
1823 errStrayStartTag(name
);
1824 NS_HTML5_BREAK(starttagloop
);
1831 errStrayStartTag(name
);
1832 if (!fragment
&& !isTemplateContents()) {
1833 addAttributesToHtml(attributes
);
1834 attributes
= nullptr;
1836 NS_HTML5_BREAK(starttagloop
);
1839 errStrayStartTag(name
);
1840 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
1848 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1849 attributes
= nullptr;
1850 NS_HTML5_BREAK(starttagloop
);
1853 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1854 selfClosing
= false;
1855 attributes
= nullptr;
1856 NS_HTML5_BREAK(starttagloop
);
1858 default:; // fall through
1862 case AFTER_FRAMESET
: {
1865 errStrayStartTag(name
);
1866 if (!fragment
&& !isTemplateContents()) {
1867 addAttributesToHtml(attributes
);
1868 attributes
= nullptr;
1870 NS_HTML5_BREAK(starttagloop
);
1873 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1874 originalMode
= mode
;
1876 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
1878 attributes
= nullptr;
1879 NS_HTML5_BREAK(starttagloop
);
1882 errStrayStartTag(name
);
1883 NS_HTML5_BREAK(starttagloop
);
1888 errStartTagWithoutDoctype();
1889 documentModeInternal(QUIRKS_MODE
, nullptr, nullptr, false);
1896 if (attributes
== nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
) {
1897 appendHtmlElementToDocumentAndPush();
1899 appendHtmlElementToDocumentAndPush(attributes
);
1902 attributes
= nullptr;
1903 NS_HTML5_BREAK(starttagloop
);
1906 appendHtmlElementToDocumentAndPush();
1915 errStrayStartTag(name
);
1916 if (!fragment
&& !isTemplateContents()) {
1917 addAttributesToHtml(attributes
);
1918 attributes
= nullptr;
1920 NS_HTML5_BREAK(starttagloop
);
1923 appendToCurrentNodeAndPushHeadElement(attributes
);
1925 attributes
= nullptr;
1926 NS_HTML5_BREAK(starttagloop
);
1929 appendToCurrentNodeAndPushHeadElement(
1930 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
1939 errStrayStartTag(name
);
1940 if (!fragment
&& !isTemplateContents()) {
1941 addAttributesToHtml(attributes
);
1942 attributes
= nullptr;
1944 NS_HTML5_BREAK(starttagloop
);
1947 if (!attributes
->getLength()) {
1948 appendToCurrentNodeAndPushBodyElement();
1950 appendToCurrentNodeAndPushBodyElement(attributes
);
1954 attributes
= nullptr;
1955 NS_HTML5_BREAK(starttagloop
);
1958 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1960 attributes
= nullptr;
1961 NS_HTML5_BREAK(starttagloop
);
1964 errFooBetweenHeadAndBody(name
);
1965 pushHeadPointerOntoStack();
1966 nsHtml5StackNode
* headOnStack
= stack
[currentPtr
];
1967 startTagTemplateInHead(elementName
, attributes
);
1968 removeFromStack(headOnStack
);
1969 attributes
= nullptr;
1970 NS_HTML5_BREAK(starttagloop
);
1973 case LINK_OR_BASEFONT_OR_BGSOUND
: {
1974 errFooBetweenHeadAndBody(name
);
1975 pushHeadPointerOntoStack();
1976 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1977 selfClosing
= false;
1979 attributes
= nullptr;
1980 NS_HTML5_BREAK(starttagloop
);
1983 errFooBetweenHeadAndBody(name
);
1984 checkMetaCharset(attributes
);
1985 pushHeadPointerOntoStack();
1986 appendVoidElementToCurrentMayFoster(elementName
, attributes
);
1987 selfClosing
= false;
1989 attributes
= nullptr;
1990 NS_HTML5_BREAK(starttagloop
);
1993 errFooBetweenHeadAndBody(name
);
1994 pushHeadPointerOntoStack();
1995 appendToCurrentNodeAndPushElement(elementName
, attributes
);
1996 originalMode
= mode
;
1998 tokenizer
->setStateAndEndTagExpectation(
1999 nsHtml5Tokenizer::SCRIPT_DATA
, elementName
);
2000 attributes
= nullptr;
2001 NS_HTML5_BREAK(starttagloop
);
2005 errFooBetweenHeadAndBody(name
);
2006 pushHeadPointerOntoStack();
2007 appendToCurrentNodeAndPushElement(elementName
, attributes
);
2008 originalMode
= mode
;
2010 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
2012 attributes
= nullptr;
2013 NS_HTML5_BREAK(starttagloop
);
2016 errFooBetweenHeadAndBody(name
);
2017 pushHeadPointerOntoStack();
2018 appendToCurrentNodeAndPushElement(elementName
, attributes
);
2019 originalMode
= mode
;
2021 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA
,
2023 attributes
= nullptr;
2024 NS_HTML5_BREAK(starttagloop
);
2027 errStrayStartTag(name
);
2028 NS_HTML5_BREAK(starttagloop
);
2031 appendToCurrentNodeAndPushBodyElement();
2037 case AFTER_AFTER_BODY
: {
2040 errStrayStartTag(name
);
2041 if (!fragment
&& !isTemplateContents()) {
2042 addAttributesToHtml(attributes
);
2043 attributes
= nullptr;
2045 NS_HTML5_BREAK(starttagloop
);
2048 errStrayStartTag(name
);
2050 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
2055 case AFTER_AFTER_FRAMESET
: {
2058 errStrayStartTag(name
);
2059 if (!fragment
&& !isTemplateContents()) {
2060 addAttributesToHtml(attributes
);
2061 attributes
= nullptr;
2063 NS_HTML5_BREAK(starttagloop
);
2066 startTagGenericRawText(elementName
, attributes
);
2067 attributes
= nullptr;
2068 NS_HTML5_BREAK(starttagloop
);
2071 errStrayStartTag(name
);
2072 NS_HTML5_BREAK(starttagloop
);
2078 NS_HTML5_BREAK(starttagloop
);
2086 if (!mBuilder
&& attributes
!= nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
) {
2092 nsHtml5TreeBuilder::startTagTitleInHead(nsHtml5ElementName
* elementName
,
2093 nsHtml5HtmlAttributes
* attributes
)
2095 appendToCurrentNodeAndPushElementMayFoster(elementName
, attributes
);
2096 originalMode
= mode
;
2098 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA
,
2103 nsHtml5TreeBuilder::startTagGenericRawText(nsHtml5ElementName
* elementName
,
2104 nsHtml5HtmlAttributes
* attributes
)
2106 appendToCurrentNodeAndPushElementMayFoster(elementName
, attributes
);
2107 originalMode
= mode
;
2109 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT
,
2114 nsHtml5TreeBuilder::startTagScriptInHead(nsHtml5ElementName
* elementName
,
2115 nsHtml5HtmlAttributes
* attributes
)
2117 appendToCurrentNodeAndPushElementMayFoster(elementName
, attributes
);
2118 originalMode
= mode
;
2120 tokenizer
->setStateAndEndTagExpectation(nsHtml5Tokenizer::SCRIPT_DATA
,
2125 nsHtml5TreeBuilder::startTagTemplateInHead(nsHtml5ElementName
* elementName
,
2126 nsHtml5HtmlAttributes
* attributes
)
2128 appendToCurrentNodeAndPushElement(elementName
, attributes
);
2131 originalMode
= mode
;
2133 pushTemplateMode(IN_TEMPLATE
);
2137 nsHtml5TreeBuilder::isTemplateContents()
2139 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
!=
2140 findLast(nsGkAtoms::_template
);
2144 nsHtml5TreeBuilder::isTemplateModeStackEmpty()
2146 return templateModePtr
== -1;
2150 nsHtml5TreeBuilder::isSpecialParentInForeign(nsHtml5StackNode
* stackNode
)
2152 int32_t ns
= stackNode
->ns
;
2153 return (kNameSpaceID_XHTML
== ns
) || (stackNode
->isHtmlIntegrationPoint()) ||
2154 ((kNameSpaceID_MathML
== ns
) &&
2155 (stackNode
->getGroup() == MI_MO_MN_MS_MTEXT
));
2159 nsHtml5TreeBuilder::extractCharsetFromContent(nsHtml5String attributeValue
,
2160 nsHtml5TreeBuilder
* tb
)
2162 int32_t charsetState
= CHARSET_INITIAL
;
2165 autoJArray
<char16_t
, int32_t> buffer
=
2166 nsHtml5Portability::newCharArrayFromString(attributeValue
);
2167 for (int32_t i
= 0; i
< buffer
.length
; i
++) {
2168 char16_t c
= buffer
[i
];
2169 switch (charsetState
) {
2170 case CHARSET_INITIAL
: {
2174 charsetState
= CHARSET_C
;
2186 charsetState
= CHARSET_H
;
2190 charsetState
= CHARSET_INITIAL
;
2199 charsetState
= CHARSET_A
;
2203 charsetState
= CHARSET_INITIAL
;
2212 charsetState
= CHARSET_R
;
2216 charsetState
= CHARSET_INITIAL
;
2225 charsetState
= CHARSET_S
;
2229 charsetState
= CHARSET_INITIAL
;
2238 charsetState
= CHARSET_E
;
2242 charsetState
= CHARSET_INITIAL
;
2251 charsetState
= CHARSET_T
;
2255 charsetState
= CHARSET_INITIAL
;
2270 charsetState
= CHARSET_EQUALS
;
2278 case CHARSET_EQUALS
: {
2289 charsetState
= CHARSET_SINGLE_QUOTED
;
2294 charsetState
= CHARSET_DOUBLE_QUOTED
;
2299 charsetState
= CHARSET_UNQUOTED
;
2304 case CHARSET_SINGLE_QUOTED
: {
2308 NS_HTML5_BREAK(charsetloop
);
2315 case CHARSET_DOUBLE_QUOTED
: {
2319 NS_HTML5_BREAK(charsetloop
);
2326 case CHARSET_UNQUOTED
: {
2335 NS_HTML5_BREAK(charsetloop
);
2345 nsHtml5String charset
= nullptr;
2348 end
= buffer
.length
;
2350 charset
= nsHtml5Portability::newStringFromBuffer(
2351 buffer
, start
, end
- start
, tb
, false);
2357 nsHtml5TreeBuilder::checkMetaCharset(nsHtml5HtmlAttributes
* attributes
)
2359 nsHtml5String charset
=
2360 attributes
->getValue(nsHtml5AttributeName::ATTR_CHARSET
);
2362 if (tokenizer
->internalEncodingDeclaration(charset
)) {
2363 requestSuspension();
2368 if (!nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
2370 attributes
->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV
))) {
2373 nsHtml5String content
=
2374 attributes
->getValue(nsHtml5AttributeName::ATTR_CONTENT
);
2376 nsHtml5String extract
=
2377 nsHtml5TreeBuilder::extractCharsetFromContent(content
, this);
2379 if (tokenizer
->internalEncodingDeclaration(extract
)) {
2380 requestSuspension();
2388 nsHtml5TreeBuilder::endTag(nsHtml5ElementName
* elementName
)
2391 needToDropLF
= false;
2393 int32_t group
= elementName
->getGroup();
2394 nsAtom
* name
= elementName
->getName();
2396 if (isInForeign()) {
2397 if (stack
[currentPtr
]->name
!= name
) {
2399 errStrayEndTag(name
);
2401 errEndTagDidNotMatchCurrentOpenElement(name
,
2402 stack
[currentPtr
]->popName
);
2405 eltPos
= currentPtr
;
2408 MOZ_ASSERT(fragment
,
2409 "We can get this close to the root of the stack in "
2410 "foreign content only in the fragment case.");
2411 NS_HTML5_BREAK(endtagloop
);
2413 if (stack
[eltPos
]->name
== name
) {
2414 while (currentPtr
>= eltPos
) {
2417 NS_HTML5_BREAK(endtagloop
);
2419 if (stack
[--eltPos
]->ns
== kNameSpaceID_XHTML
) {
2431 errStrayEndTag(name
);
2432 NS_HTML5_BREAK(endtagloop
);
2440 eltPos
= findLastOrRoot(nsHtml5TreeBuilder::TR
);
2442 MOZ_ASSERT(fragment
|| isTemplateContents());
2443 errNoTableRowToClose();
2444 NS_HTML5_BREAK(endtagloop
);
2446 clearStackBackTo(eltPos
);
2448 mode
= IN_TABLE_BODY
;
2449 NS_HTML5_BREAK(endtagloop
);
2452 eltPos
= findLastOrRoot(nsHtml5TreeBuilder::TR
);
2454 MOZ_ASSERT(fragment
|| isTemplateContents());
2455 errNoTableRowToClose();
2456 NS_HTML5_BREAK(endtagloop
);
2458 clearStackBackTo(eltPos
);
2460 mode
= IN_TABLE_BODY
;
2463 case TBODY_OR_THEAD_OR_TFOOT
: {
2464 if (findLastInTableScope(name
) ==
2465 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2466 errStrayEndTag(name
);
2467 NS_HTML5_BREAK(endtagloop
);
2469 eltPos
= findLastOrRoot(nsHtml5TreeBuilder::TR
);
2471 MOZ_ASSERT(fragment
|| isTemplateContents());
2472 errNoTableRowToClose();
2473 NS_HTML5_BREAK(endtagloop
);
2475 clearStackBackTo(eltPos
);
2477 mode
= IN_TABLE_BODY
;
2486 errStrayEndTag(name
);
2487 NS_HTML5_BREAK(endtagloop
);
2489 default:; // fall through
2493 case IN_TABLE_BODY
: {
2495 case TBODY_OR_THEAD_OR_TFOOT
: {
2496 eltPos
= findLastOrRoot(name
);
2498 errStrayEndTag(name
);
2499 NS_HTML5_BREAK(endtagloop
);
2501 clearStackBackTo(eltPos
);
2504 NS_HTML5_BREAK(endtagloop
);
2507 eltPos
= findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
2508 if (!eltPos
|| stack
[eltPos
]->getGroup() == TEMPLATE
) {
2509 MOZ_ASSERT(fragment
|| isTemplateContents());
2510 errStrayEndTag(name
);
2511 NS_HTML5_BREAK(endtagloop
);
2513 clearStackBackTo(eltPos
);
2525 errStrayEndTag(name
);
2526 NS_HTML5_BREAK(endtagloop
);
2528 default:; // fall through
2535 eltPos
= findLast(nsGkAtoms::table
);
2536 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2537 MOZ_ASSERT(fragment
|| isTemplateContents());
2538 errStrayEndTag(name
);
2539 NS_HTML5_BREAK(endtagloop
);
2541 while (currentPtr
>= eltPos
) {
2544 resetTheInsertionMode();
2545 NS_HTML5_BREAK(endtagloop
);
2552 case TBODY_OR_THEAD_OR_TFOOT
:
2555 errStrayEndTag(name
);
2556 NS_HTML5_BREAK(endtagloop
);
2562 errStrayEndTag(name
);
2570 eltPos
= findLastInTableScope(nsGkAtoms::caption
);
2571 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2572 NS_HTML5_BREAK(endtagloop
);
2574 generateImpliedEndTags();
2575 if (!!MOZ_UNLIKELY(mViewSource
) && currentPtr
!= eltPos
) {
2576 errUnclosedElements(eltPos
, name
);
2578 while (currentPtr
>= eltPos
) {
2581 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2583 NS_HTML5_BREAK(endtagloop
);
2586 errTableClosedWhileCaptionOpen();
2587 eltPos
= findLastInTableScope(nsGkAtoms::caption
);
2588 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2589 NS_HTML5_BREAK(endtagloop
);
2591 generateImpliedEndTags();
2592 if (!!MOZ_UNLIKELY(mViewSource
) && currentPtr
!= eltPos
) {
2593 errUnclosedElements(eltPos
, name
);
2595 while (currentPtr
>= eltPos
) {
2598 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2606 case TBODY_OR_THEAD_OR_TFOOT
:
2609 errStrayEndTag(name
);
2610 NS_HTML5_BREAK(endtagloop
);
2612 default:; // fall through
2619 eltPos
= findLastInTableScope(name
);
2620 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2621 errStrayEndTag(name
);
2622 NS_HTML5_BREAK(endtagloop
);
2624 generateImpliedEndTags();
2625 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2626 errUnclosedElements(eltPos
, name
);
2628 while (currentPtr
>= eltPos
) {
2631 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2633 NS_HTML5_BREAK(endtagloop
);
2636 case TBODY_OR_THEAD_OR_TFOOT
:
2638 if (findLastInTableScope(name
) ==
2639 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2640 MOZ_ASSERT(name
== nsGkAtoms::tbody
|| name
== nsGkAtoms::tfoot
||
2641 name
== nsGkAtoms::thead
|| fragment
||
2642 isTemplateContents());
2643 errStrayEndTag(name
);
2644 NS_HTML5_BREAK(endtagloop
);
2646 closeTheCell(findLastInTableScopeTdTh());
2654 errStrayEndTag(name
);
2655 NS_HTML5_BREAK(endtagloop
);
2657 default:; // fall through
2665 if (!isSecondOnStackBody()) {
2666 MOZ_ASSERT(fragment
|| isTemplateContents());
2667 errStrayEndTag(name
);
2668 NS_HTML5_BREAK(endtagloop
);
2670 MOZ_ASSERT(currentPtr
>= 1);
2671 if (MOZ_UNLIKELY(mViewSource
)) {
2672 for (int32_t i
= 2; i
<= currentPtr
; i
++) {
2673 switch (stack
[i
]->getGroup()) {
2682 case TBODY_OR_THEAD_OR_TFOOT
: {
2686 errEndWithUnclosedElements(name
);
2687 NS_HTML5_BREAK(uncloseloop1
);
2694 NS_HTML5_BREAK(endtagloop
);
2697 if (!isSecondOnStackBody()) {
2698 MOZ_ASSERT(fragment
|| isTemplateContents());
2699 errStrayEndTag(name
);
2700 NS_HTML5_BREAK(endtagloop
);
2702 if (MOZ_UNLIKELY(mViewSource
)) {
2703 for (int32_t i
= 0; i
<= currentPtr
; i
++) {
2704 switch (stack
[i
]->getGroup()) {
2710 case TBODY_OR_THEAD_OR_TFOOT
:
2717 errEndWithUnclosedElements(name
);
2718 NS_HTML5_BREAK(uncloseloop2
);
2727 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU
:
2728 case UL_OR_OL_OR_DL
:
2729 case PRE_OR_LISTING
:
2732 case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY
: {
2733 eltPos
= findLastInScope(name
);
2734 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2735 errStrayEndTag(name
);
2737 generateImpliedEndTags();
2738 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2739 errUnclosedElements(eltPos
, name
);
2741 while (currentPtr
>= eltPos
) {
2745 NS_HTML5_BREAK(endtagloop
);
2748 if (!isTemplateContents()) {
2750 errStrayEndTag(name
);
2751 NS_HTML5_BREAK(endtagloop
);
2753 formPointer
= nullptr;
2754 eltPos
= findLastInScope(name
);
2755 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2756 errStrayEndTag(name
);
2757 NS_HTML5_BREAK(endtagloop
);
2759 generateImpliedEndTags();
2760 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2761 errUnclosedElements(eltPos
, name
);
2763 removeFromStack(eltPos
);
2764 NS_HTML5_BREAK(endtagloop
);
2766 eltPos
= findLastInScope(name
);
2767 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2768 errStrayEndTag(name
);
2769 NS_HTML5_BREAK(endtagloop
);
2771 generateImpliedEndTags();
2772 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2773 errUnclosedElements(eltPos
, name
);
2775 while (currentPtr
>= eltPos
) {
2778 NS_HTML5_BREAK(endtagloop
);
2782 eltPos
= findLastInButtonScope(nsGkAtoms::p
);
2783 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2784 errNoElementToCloseButEndTagSeen(nsGkAtoms::p
);
2785 if (isInForeign()) {
2786 errHtmlStartTagInForeignContext(name
);
2787 while (currentPtr
>= 0 &&
2788 stack
[currentPtr
]->ns
!= kNameSpaceID_XHTML
) {
2792 appendVoidElementToCurrentMayFoster(
2793 elementName
, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
2794 NS_HTML5_BREAK(endtagloop
);
2796 generateImpliedEndTagsExceptFor(nsGkAtoms::p
);
2797 MOZ_ASSERT(eltPos
!= nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
);
2798 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
2799 errUnclosedElements(eltPos
, name
);
2801 while (currentPtr
>= eltPos
) {
2804 NS_HTML5_BREAK(endtagloop
);
2807 eltPos
= findLastInListScope(name
);
2808 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2809 errNoElementToCloseButEndTagSeen(name
);
2811 generateImpliedEndTagsExceptFor(name
);
2812 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
2813 errUnclosedElements(eltPos
, name
);
2815 while (currentPtr
>= eltPos
) {
2819 NS_HTML5_BREAK(endtagloop
);
2822 eltPos
= findLastInScope(name
);
2823 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2824 errNoElementToCloseButEndTagSeen(name
);
2826 generateImpliedEndTagsExceptFor(name
);
2827 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
2828 errUnclosedElements(eltPos
, name
);
2830 while (currentPtr
>= eltPos
) {
2834 NS_HTML5_BREAK(endtagloop
);
2836 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
: {
2837 eltPos
= findLastInScopeHn();
2838 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2839 errStrayEndTag(name
);
2841 generateImpliedEndTags();
2842 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2843 errUnclosedElements(eltPos
, name
);
2845 while (currentPtr
>= eltPos
) {
2849 NS_HTML5_BREAK(endtagloop
);
2852 case MARQUEE_OR_APPLET
: {
2853 eltPos
= findLastInScope(name
);
2854 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
2855 errStrayEndTag(name
);
2857 generateImpliedEndTags();
2858 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2859 errUnclosedElements(eltPos
, name
);
2861 while (currentPtr
>= eltPos
) {
2864 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2866 NS_HTML5_BREAK(endtagloop
);
2870 if (isInForeign()) {
2871 errHtmlStartTagInForeignContext(name
);
2872 while (currentPtr
>= 0 &&
2873 stack
[currentPtr
]->ns
!= kNameSpaceID_XHTML
) {
2877 reconstructTheActiveFormattingElements();
2878 appendVoidElementToCurrentMayFoster(
2879 elementName
, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
2880 NS_HTML5_BREAK(endtagloop
);
2886 #ifdef ENABLE_VOID_MENUITEM
2889 case PARAM_OR_SOURCE_OR_TRACK
:
2902 errStrayEndTag(name
);
2903 NS_HTML5_BREAK(endtagloop
);
2906 if (scriptingEnabled
) {
2907 errStrayEndTag(name
);
2908 NS_HTML5_BREAK(endtagloop
);
2913 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U
:
2916 if (adoptionAgencyEndTag(name
)) {
2917 NS_HTML5_BREAK(endtagloop
);
2922 if (isCurrent(name
)) {
2924 NS_HTML5_BREAK(endtagloop
);
2926 eltPos
= currentPtr
;
2928 nsHtml5StackNode
* node
= stack
[eltPos
];
2929 if (node
->ns
== kNameSpaceID_XHTML
&& node
->name
== name
) {
2930 generateImpliedEndTags();
2931 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(name
)) {
2932 errUnclosedElements(eltPos
, name
);
2934 while (currentPtr
>= eltPos
) {
2937 NS_HTML5_BREAK(endtagloop
);
2938 } else if (!eltPos
|| node
->isSpecial()) {
2939 errStrayEndTag(name
);
2940 NS_HTML5_BREAK(endtagloop
);
2953 NS_HTML5_BREAK(endtagloop
);
2963 endTagTemplateInHead();
2964 NS_HTML5_BREAK(endtagloop
);
2967 errStrayEndTag(name
);
2968 NS_HTML5_BREAK(endtagloop
);
2972 case IN_HEAD_NOSCRIPT
: {
2977 NS_HTML5_BREAK(endtagloop
);
2980 errStrayEndTag(name
);
2986 errStrayEndTag(name
);
2987 NS_HTML5_BREAK(endtagloop
);
2991 case IN_COLUMN_GROUP
: {
2995 stack
[currentPtr
]->getGroup() == nsHtml5TreeBuilder::TEMPLATE
) {
2996 MOZ_ASSERT(fragment
|| isTemplateContents());
2997 errGarbageInColgroup();
2998 NS_HTML5_BREAK(endtagloop
);
3002 NS_HTML5_BREAK(endtagloop
);
3005 errStrayEndTag(name
);
3006 NS_HTML5_BREAK(endtagloop
);
3009 endTagTemplateInHead();
3010 NS_HTML5_BREAK(endtagloop
);
3014 stack
[currentPtr
]->getGroup() == nsHtml5TreeBuilder::TEMPLATE
) {
3015 MOZ_ASSERT(fragment
|| isTemplateContents());
3016 errGarbageInColgroup();
3017 NS_HTML5_BREAK(endtagloop
);
3025 case IN_SELECT_IN_TABLE
: {
3029 case TBODY_OR_THEAD_OR_TFOOT
:
3032 errEndTagSeenWithSelectOpen(name
);
3033 if (findLastInTableScope(name
) !=
3034 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
3035 eltPos
= findLastInTableScope(nsGkAtoms::select
);
3036 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
3037 MOZ_ASSERT(fragment
);
3038 NS_HTML5_BREAK(endtagloop
);
3040 while (currentPtr
>= eltPos
) {
3043 resetTheInsertionMode();
3046 NS_HTML5_BREAK(endtagloop
);
3049 default:; // fall through
3056 if (isCurrent(nsGkAtoms::option
)) {
3058 NS_HTML5_BREAK(endtagloop
);
3060 errStrayEndTag(name
);
3061 NS_HTML5_BREAK(endtagloop
);
3065 if (isCurrent(nsGkAtoms::option
) &&
3066 nsGkAtoms::optgroup
== stack
[currentPtr
- 1]->name
) {
3069 if (isCurrent(nsGkAtoms::optgroup
)) {
3072 errStrayEndTag(name
);
3074 NS_HTML5_BREAK(endtagloop
);
3077 eltPos
= findLastInTableScope(nsGkAtoms::select
);
3078 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
3079 MOZ_ASSERT(fragment
);
3080 errStrayEndTag(name
);
3081 NS_HTML5_BREAK(endtagloop
);
3083 while (currentPtr
>= eltPos
) {
3086 resetTheInsertionMode();
3087 NS_HTML5_BREAK(endtagloop
);
3090 endTagTemplateInHead();
3091 NS_HTML5_BREAK(endtagloop
);
3094 errStrayEndTag(name
);
3095 NS_HTML5_BREAK(endtagloop
);
3103 errStrayEndTag(name
);
3104 NS_HTML5_BREAK(endtagloop
);
3106 mode
= AFTER_AFTER_BODY
;
3107 NS_HTML5_BREAK(endtagloop
);
3111 errEndTagAfterBody();
3112 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3121 MOZ_ASSERT(fragment
);
3122 errStrayEndTag(name
);
3123 NS_HTML5_BREAK(endtagloop
);
3126 if ((!fragment
) && !isCurrent(nsGkAtoms::frameset
)) {
3127 mode
= AFTER_FRAMESET
;
3129 NS_HTML5_BREAK(endtagloop
);
3132 errStrayEndTag(name
);
3133 NS_HTML5_BREAK(endtagloop
);
3137 case AFTER_FRAMESET
: {
3140 mode
= AFTER_AFTER_FRAMESET
;
3141 NS_HTML5_BREAK(endtagloop
);
3144 errStrayEndTag(name
);
3145 NS_HTML5_BREAK(endtagloop
);
3150 errEndTagSeenWithoutDoctype();
3151 documentModeInternal(QUIRKS_MODE
, nullptr, nullptr, false);
3161 appendHtmlElementToDocumentAndPush();
3166 errStrayEndTag(name
);
3167 NS_HTML5_BREAK(endtagloop
);
3177 appendToCurrentNodeAndPushHeadElement(
3178 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
);
3183 errStrayEndTag(name
);
3184 NS_HTML5_BREAK(endtagloop
);
3191 endTagTemplateInHead();
3192 NS_HTML5_BREAK(endtagloop
);
3197 appendToCurrentNodeAndPushBodyElement();
3202 errStrayEndTag(name
);
3203 NS_HTML5_BREAK(endtagloop
);
3207 case AFTER_AFTER_BODY
: {
3208 errStrayEndTag(name
);
3209 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3212 case AFTER_AFTER_FRAMESET
: {
3213 errStrayEndTag(name
);
3214 NS_HTML5_BREAK(endtagloop
);
3218 if (originalMode
== AFTER_HEAD
) {
3221 mode
= originalMode
;
3222 NS_HTML5_BREAK(endtagloop
);
3230 nsHtml5TreeBuilder::endTagTemplateInHead()
3232 int32_t eltPos
= findLast(nsGkAtoms::_template
);
3233 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
3234 errStrayEndTag(nsGkAtoms::_template
);
3237 generateImpliedEndTags();
3238 if (!!MOZ_UNLIKELY(mViewSource
) && !isCurrent(nsGkAtoms::_template
)) {
3239 errUnclosedElements(eltPos
, nsGkAtoms::_template
);
3241 while (currentPtr
>= eltPos
) {
3244 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
3246 resetTheInsertionMode();
3250 nsHtml5TreeBuilder::findLastInTableScopeOrRootTemplateTbodyTheadTfoot()
3252 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3253 if (stack
[i
]->getGroup() == nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT
||
3254 stack
[i
]->getGroup() == nsHtml5TreeBuilder::TEMPLATE
) {
3262 nsHtml5TreeBuilder::findLast(nsAtom
* name
)
3264 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3265 if (stack
[i
]->ns
== kNameSpaceID_XHTML
&& stack
[i
]->name
== name
) {
3269 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3273 nsHtml5TreeBuilder::findLastInTableScope(nsAtom
* name
)
3275 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3276 if (stack
[i
]->ns
== kNameSpaceID_XHTML
) {
3277 if (stack
[i
]->name
== name
) {
3279 } else if (stack
[i
]->name
== nsGkAtoms::table
||
3280 stack
[i
]->name
== nsGkAtoms::_template
) {
3281 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3285 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3289 nsHtml5TreeBuilder::findLastInButtonScope(nsAtom
* name
)
3291 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3292 if (stack
[i
]->ns
== kNameSpaceID_XHTML
) {
3293 if (stack
[i
]->name
== name
) {
3295 } else if (stack
[i
]->name
== nsGkAtoms::button
) {
3296 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3299 if (stack
[i
]->isScoping()) {
3300 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3303 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3307 nsHtml5TreeBuilder::findLastInScope(nsAtom
* name
)
3309 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3310 if (stack
[i
]->ns
== kNameSpaceID_XHTML
&& stack
[i
]->name
== name
) {
3312 } else if (stack
[i
]->isScoping()) {
3313 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3316 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3320 nsHtml5TreeBuilder::findLastInListScope(nsAtom
* name
)
3322 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3323 if (stack
[i
]->ns
== kNameSpaceID_XHTML
) {
3324 if (stack
[i
]->name
== name
) {
3326 } else if (stack
[i
]->name
== nsGkAtoms::ul
||
3327 stack
[i
]->name
== nsGkAtoms::ol
) {
3328 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3331 if (stack
[i
]->isScoping()) {
3332 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3335 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3339 nsHtml5TreeBuilder::findLastInScopeHn()
3341 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3342 if (stack
[i
]->getGroup() ==
3343 nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6
) {
3345 } else if (stack
[i
]->isScoping()) {
3346 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3349 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3353 nsHtml5TreeBuilder::generateImpliedEndTagsExceptFor(nsAtom
* name
)
3356 nsHtml5StackNode
* node
= stack
[currentPtr
];
3357 switch (node
->getGroup()) {
3365 if (node
->ns
== kNameSpaceID_XHTML
&& node
->name
== name
) {
3379 nsHtml5TreeBuilder::generateImpliedEndTags()
3382 switch (stack
[currentPtr
]->getGroup()) {
3401 nsHtml5TreeBuilder::isSecondOnStackBody()
3403 return currentPtr
>= 1 && stack
[1]->getGroup() == nsHtml5TreeBuilder::BODY
;
3407 nsHtml5TreeBuilder::documentModeInternal(
3408 nsHtml5DocumentMode m
,
3409 nsHtml5String publicIdentifier
,
3410 nsHtml5String systemIdentifier
,
3411 bool html4SpecificAdditionalErrorChecks
)
3413 if (isSrcdocDocument
) {
3415 this->documentMode(STANDARDS_MODE
);
3418 quirks
= (m
== QUIRKS_MODE
);
3419 this->documentMode(m
);
3423 nsHtml5TreeBuilder::isAlmostStandards(nsHtml5String publicIdentifier
,
3424 nsHtml5String systemIdentifier
)
3426 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3427 "-//w3c//dtd xhtml 1.0 transitional//en", publicIdentifier
)) {
3430 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3431 "-//w3c//dtd xhtml 1.0 frameset//en", publicIdentifier
)) {
3434 if (systemIdentifier
) {
3435 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3436 "-//w3c//dtd html 4.01 transitional//en", publicIdentifier
)) {
3439 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3440 "-//w3c//dtd html 4.01 frameset//en", publicIdentifier
)) {
3448 nsHtml5TreeBuilder::isQuirky(nsAtom
* name
,
3449 nsHtml5String publicIdentifier
,
3450 nsHtml5String systemIdentifier
,
3456 if (name
!= nsGkAtoms::html
) {
3459 if (publicIdentifier
) {
3460 for (int32_t i
= 0; i
< nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS
.length
; i
++) {
3461 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3462 nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS
[i
], publicIdentifier
)) {
3466 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3467 "-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier
) ||
3468 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3469 "-/w3c/dtd html 4.0 transitional/en", publicIdentifier
) ||
3470 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3471 "html", publicIdentifier
)) {
3475 if (!systemIdentifier
) {
3476 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3477 "-//w3c//dtd html 4.01 transitional//en", publicIdentifier
)) {
3479 } else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3480 "-//w3c//dtd html 4.01 frameset//en", publicIdentifier
)) {
3483 } else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3484 "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd",
3485 systemIdentifier
)) {
3492 nsHtml5TreeBuilder::closeTheCell(int32_t eltPos
)
3494 generateImpliedEndTags();
3495 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
3496 errUnclosedElementsCell(eltPos
);
3498 while (currentPtr
>= eltPos
) {
3501 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
3507 nsHtml5TreeBuilder::findLastInTableScopeTdTh()
3509 for (int32_t i
= currentPtr
; i
> 0; i
--) {
3510 nsAtom
* name
= stack
[i
]->name
;
3511 if (stack
[i
]->ns
== kNameSpaceID_XHTML
) {
3512 if (nsGkAtoms::td
== name
|| nsGkAtoms::th
== name
) {
3514 } else if (name
== nsGkAtoms::table
|| name
== nsGkAtoms::_template
) {
3515 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3519 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
;
3523 nsHtml5TreeBuilder::clearStackBackTo(int32_t eltPos
)
3525 int32_t eltGroup
= stack
[eltPos
]->getGroup();
3526 while (currentPtr
> eltPos
) {
3527 if (stack
[currentPtr
]->ns
== kNameSpaceID_XHTML
&&
3528 stack
[currentPtr
]->getGroup() == TEMPLATE
&&
3529 (eltGroup
== TABLE
|| eltGroup
== TBODY_OR_THEAD_OR_TFOOT
||
3530 eltGroup
== TR
|| !eltPos
)) {
3538 nsHtml5TreeBuilder::resetTheInsertionMode()
3540 nsHtml5StackNode
* node
;
3543 for (int32_t i
= currentPtr
; i
>= 0; i
--) {
3548 if (!(contextNamespace
== kNameSpaceID_XHTML
&&
3549 (contextName
== nsGkAtoms::td
|| contextName
== nsGkAtoms::th
))) {
3552 ns
= contextNamespace
;
3555 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3559 if (nsGkAtoms::select
== name
) {
3560 int32_t ancestorIndex
= i
;
3561 while (ancestorIndex
> 0) {
3562 nsHtml5StackNode
* ancestor
= stack
[ancestorIndex
--];
3563 if (kNameSpaceID_XHTML
== ancestor
->ns
) {
3564 if (nsGkAtoms::_template
== ancestor
->name
) {
3567 if (nsGkAtoms::table
== ancestor
->name
) {
3568 mode
= IN_SELECT_IN_TABLE
;
3575 } else if (nsGkAtoms::td
== name
|| nsGkAtoms::th
== name
) {
3578 } else if (nsGkAtoms::tr
== name
) {
3581 } else if (nsGkAtoms::tbody
== name
|| nsGkAtoms::thead
== name
||
3582 nsGkAtoms::tfoot
== name
) {
3583 mode
= IN_TABLE_BODY
;
3585 } else if (nsGkAtoms::caption
== name
) {
3588 } else if (nsGkAtoms::colgroup
== name
) {
3589 mode
= IN_COLUMN_GROUP
;
3591 } else if (nsGkAtoms::table
== name
) {
3594 } else if (kNameSpaceID_XHTML
!= ns
) {
3595 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3597 } else if (nsGkAtoms::_template
== name
) {
3598 MOZ_ASSERT(templateModePtr
>= 0);
3599 mode
= templateModeStack
[templateModePtr
];
3601 } else if (nsGkAtoms::head
== name
) {
3602 if (name
== contextName
) {
3603 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3608 } else if (nsGkAtoms::body
== name
) {
3609 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3611 } else if (nsGkAtoms::frameset
== name
) {
3614 } else if (nsGkAtoms::html
== name
) {
3622 mode
= framesetOk
? FRAMESET_OK
: IN_BODY
;
3629 nsHtml5TreeBuilder::implicitlyCloseP()
3631 int32_t eltPos
= findLastInButtonScope(nsGkAtoms::p
);
3632 if (eltPos
== nsHtml5TreeBuilder::NOT_FOUND_ON_STACK
) {
3635 generateImpliedEndTagsExceptFor(nsGkAtoms::p
);
3636 if (!!MOZ_UNLIKELY(mViewSource
) && eltPos
!= currentPtr
) {
3637 errUnclosedElementsImplied(eltPos
, nsGkAtoms::p
);
3639 while (currentPtr
>= eltPos
) {
3645 nsHtml5TreeBuilder::debugOnlyClearLastStackSlot()
3647 stack
[currentPtr
] = nullptr;
3652 nsHtml5TreeBuilder::debugOnlyClearLastListSlot()
3654 listOfActiveFormattingElements
[listPtr
] = nullptr;
3659 nsHtml5TreeBuilder::pushTemplateMode(int32_t mode
)
3662 if (templateModePtr
== templateModeStack
.length
) {
3663 jArray
<int32_t, int32_t> newStack
=
3664 jArray
<int32_t, int32_t>::newJArray(templateModeStack
.length
+ 64);
3665 nsHtml5ArrayCopy::arraycopy(
3666 templateModeStack
, newStack
, templateModeStack
.length
);
3667 templateModeStack
= newStack
;
3669 templateModeStack
[templateModePtr
] = mode
;
3673 nsHtml5TreeBuilder::push(nsHtml5StackNode
* node
)
3676 if (currentPtr
== stack
.length
) {
3677 jArray
<nsHtml5StackNode
*, int32_t> newStack
=
3678 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(stack
.length
+ 64);
3679 nsHtml5ArrayCopy::arraycopy(stack
, newStack
, stack
.length
);
3682 stack
[currentPtr
] = node
;
3683 elementPushed(node
->ns
, node
->popName
, node
->node
);
3687 nsHtml5TreeBuilder::silentPush(nsHtml5StackNode
* node
)
3690 if (currentPtr
== stack
.length
) {
3691 jArray
<nsHtml5StackNode
*, int32_t> newStack
=
3692 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(stack
.length
+ 64);
3693 nsHtml5ArrayCopy::arraycopy(stack
, newStack
, stack
.length
);
3696 stack
[currentPtr
] = node
;
3700 nsHtml5TreeBuilder::append(nsHtml5StackNode
* node
)
3703 if (listPtr
== listOfActiveFormattingElements
.length
) {
3704 jArray
<nsHtml5StackNode
*, int32_t> newList
=
3705 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(
3706 listOfActiveFormattingElements
.length
+ 64);
3707 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements
,
3709 listOfActiveFormattingElements
.length
);
3710 listOfActiveFormattingElements
= newList
;
3712 listOfActiveFormattingElements
[listPtr
] = node
;
3716 nsHtml5TreeBuilder::clearTheListOfActiveFormattingElementsUpToTheLastMarker()
3718 while (listPtr
> -1) {
3719 if (!listOfActiveFormattingElements
[listPtr
]) {
3723 listOfActiveFormattingElements
[listPtr
]->release(this);
3729 nsHtml5TreeBuilder::removeFromStack(int32_t pos
)
3731 if (currentPtr
== pos
) {
3735 stack
[pos
]->release(this);
3736 nsHtml5ArrayCopy::arraycopy(stack
, pos
+ 1, pos
, currentPtr
- pos
);
3737 MOZ_ASSERT(debugOnlyClearLastStackSlot());
3743 nsHtml5TreeBuilder::removeFromStack(nsHtml5StackNode
* node
)
3745 if (stack
[currentPtr
] == node
) {
3748 int32_t pos
= currentPtr
- 1;
3749 while (pos
>= 0 && stack
[pos
] != node
) {
3756 node
->release(this);
3757 nsHtml5ArrayCopy::arraycopy(stack
, pos
+ 1, pos
, currentPtr
- pos
);
3763 nsHtml5TreeBuilder::removeFromListOfActiveFormattingElements(int32_t pos
)
3765 MOZ_ASSERT(!!listOfActiveFormattingElements
[pos
]);
3766 listOfActiveFormattingElements
[pos
]->release(this);
3767 if (pos
== listPtr
) {
3768 MOZ_ASSERT(debugOnlyClearLastListSlot());
3772 MOZ_ASSERT(pos
< listPtr
);
3773 nsHtml5ArrayCopy::arraycopy(
3774 listOfActiveFormattingElements
, pos
+ 1, pos
, listPtr
- pos
);
3775 MOZ_ASSERT(debugOnlyClearLastListSlot());
3780 nsHtml5TreeBuilder::adoptionAgencyEndTag(nsAtom
* name
)
3782 if (stack
[currentPtr
]->ns
== kNameSpaceID_XHTML
&&
3783 stack
[currentPtr
]->name
== name
&&
3784 findInListOfActiveFormattingElements(stack
[currentPtr
]) == -1) {
3788 for (int32_t i
= 0; i
< 8; ++i
) {
3789 int32_t formattingEltListPos
= listPtr
;
3790 while (formattingEltListPos
> -1) {
3791 nsHtml5StackNode
* listNode
=
3792 listOfActiveFormattingElements
[formattingEltListPos
];
3794 formattingEltListPos
= -1;
3796 } else if (listNode
->name
== name
) {
3799 formattingEltListPos
--;
3801 if (formattingEltListPos
== -1) {
3804 nsHtml5StackNode
* formattingElt
=
3805 listOfActiveFormattingElements
[formattingEltListPos
];
3806 int32_t formattingEltStackPos
= currentPtr
;
3807 bool inScope
= true;
3808 while (formattingEltStackPos
> -1) {
3809 nsHtml5StackNode
* node
= stack
[formattingEltStackPos
];
3810 if (node
== formattingElt
) {
3812 } else if (node
->isScoping()) {
3815 formattingEltStackPos
--;
3817 if (formattingEltStackPos
== -1) {
3818 errNoElementToCloseButEndTagSeen(name
);
3819 removeFromListOfActiveFormattingElements(formattingEltListPos
);
3823 errNoElementToCloseButEndTagSeen(name
);
3826 if (formattingEltStackPos
!= currentPtr
) {
3827 errEndTagViolatesNestingRules(name
);
3829 int32_t furthestBlockPos
= formattingEltStackPos
+ 1;
3830 while (furthestBlockPos
<= currentPtr
) {
3831 nsHtml5StackNode
* node
= stack
[furthestBlockPos
];
3832 MOZ_ASSERT(furthestBlockPos
> 0,
3833 "How is formattingEltStackPos + 1 not > 0?");
3834 if (node
->isSpecial()) {
3839 if (furthestBlockPos
> currentPtr
) {
3840 while (currentPtr
>= formattingEltStackPos
) {
3843 removeFromListOfActiveFormattingElements(formattingEltListPos
);
3846 nsHtml5StackNode
* commonAncestor
= stack
[formattingEltStackPos
- 1];
3847 nsHtml5StackNode
* furthestBlock
= stack
[furthestBlockPos
];
3848 int32_t bookmark
= formattingEltListPos
;
3849 int32_t nodePos
= furthestBlockPos
;
3850 nsHtml5StackNode
* lastNode
= furthestBlock
;
3855 if (nodePos
== formattingEltStackPos
) {
3858 nsHtml5StackNode
* node
= stack
[nodePos
];
3859 int32_t nodeListPos
= findInListOfActiveFormattingElements(node
);
3860 if (j
> 3 && nodeListPos
!= -1) {
3861 removeFromListOfActiveFormattingElements(nodeListPos
);
3862 if (nodeListPos
<= formattingEltListPos
) {
3863 formattingEltListPos
--;
3865 if (nodeListPos
<= bookmark
) {
3870 if (nodeListPos
== -1) {
3871 MOZ_ASSERT(formattingEltStackPos
< nodePos
);
3872 MOZ_ASSERT(bookmark
< nodePos
);
3873 MOZ_ASSERT(furthestBlockPos
> nodePos
);
3874 removeFromStack(nodePos
);
3878 if (nodePos
== furthestBlockPos
) {
3879 bookmark
= nodeListPos
+ 1;
3881 MOZ_ASSERT(node
== listOfActiveFormattingElements
[nodeListPos
]);
3882 MOZ_ASSERT(node
== stack
[nodePos
]);
3883 nsIContentHandle
* clone
=
3884 createElement(kNameSpaceID_XHTML
,
3886 node
->attributes
->cloneAttributes(nullptr),
3887 commonAncestor
->node
,
3888 htmlCreator(node
->getHtmlCreator()));
3889 nsHtml5StackNode
* newNode
= createStackNode(node
->getFlags(),
3895 node
->getHtmlCreator());
3896 node
->dropAttributes();
3897 stack
[nodePos
] = newNode
;
3899 listOfActiveFormattingElements
[nodeListPos
] = newNode
;
3900 node
->release(this);
3901 node
->release(this);
3903 detachFromParent(lastNode
->node
);
3904 appendElement(lastNode
->node
, node
->node
);
3907 if (commonAncestor
->isFosterParenting()) {
3909 detachFromParent(lastNode
->node
);
3910 insertIntoFosterParent(lastNode
->node
);
3912 detachFromParent(lastNode
->node
);
3913 appendElement(lastNode
->node
, commonAncestor
->node
);
3915 nsIContentHandle
* clone
=
3916 createElement(kNameSpaceID_XHTML
,
3917 formattingElt
->name
,
3918 formattingElt
->attributes
->cloneAttributes(nullptr),
3919 furthestBlock
->node
,
3920 htmlCreator(formattingElt
->getHtmlCreator()));
3921 nsHtml5StackNode
* formattingClone
=
3922 createStackNode(formattingElt
->getFlags(),
3924 formattingElt
->name
,
3926 formattingElt
->popName
,
3927 formattingElt
->attributes
,
3928 formattingElt
->getHtmlCreator());
3929 formattingElt
->dropAttributes();
3930 appendChildrenToNewParent(furthestBlock
->node
, clone
);
3931 appendElement(clone
, furthestBlock
->node
);
3932 removeFromListOfActiveFormattingElements(formattingEltListPos
);
3933 insertIntoListOfActiveFormattingElements(formattingClone
, bookmark
);
3934 MOZ_ASSERT(formattingEltStackPos
< furthestBlockPos
);
3935 removeFromStack(formattingEltStackPos
);
3936 insertIntoStack(formattingClone
, furthestBlockPos
);
3942 nsHtml5TreeBuilder::insertIntoStack(nsHtml5StackNode
* node
, int32_t position
)
3944 MOZ_ASSERT(currentPtr
+ 1 < stack
.length
);
3945 MOZ_ASSERT(position
<= currentPtr
+ 1);
3946 if (position
== currentPtr
+ 1) {
3949 nsHtml5ArrayCopy::arraycopy(
3950 stack
, position
, position
+ 1, (currentPtr
- position
) + 1);
3952 stack
[position
] = node
;
3957 nsHtml5TreeBuilder::insertIntoListOfActiveFormattingElements(
3958 nsHtml5StackNode
* formattingClone
,
3961 formattingClone
->retain();
3962 MOZ_ASSERT(listPtr
+ 1 < listOfActiveFormattingElements
.length
);
3963 if (bookmark
<= listPtr
) {
3964 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements
,
3967 (listPtr
- bookmark
) + 1);
3970 listOfActiveFormattingElements
[bookmark
] = formattingClone
;
3974 nsHtml5TreeBuilder::findInListOfActiveFormattingElements(nsHtml5StackNode
* node
)
3976 for (int32_t i
= listPtr
; i
>= 0; i
--) {
3977 if (node
== listOfActiveFormattingElements
[i
]) {
3985 nsHtml5TreeBuilder::
3986 findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
3989 for (int32_t i
= listPtr
; i
>= 0; i
--) {
3990 nsHtml5StackNode
* node
= listOfActiveFormattingElements
[i
];
3993 } else if (node
->name
== name
) {
4001 nsHtml5TreeBuilder::maybeForgetEarlierDuplicateFormattingElement(
4003 nsHtml5HtmlAttributes
* attributes
)
4005 int32_t candidate
= -1;
4007 for (int32_t i
= listPtr
; i
>= 0; i
--) {
4008 nsHtml5StackNode
* node
= listOfActiveFormattingElements
[i
];
4012 if (node
->name
== name
&& node
->attributes
->equalsAnother(attributes
)) {
4018 removeFromListOfActiveFormattingElements(candidate
);
4023 nsHtml5TreeBuilder::findLastOrRoot(nsAtom
* name
)
4025 for (int32_t i
= currentPtr
; i
> 0; i
--) {
4026 if (stack
[i
]->ns
== kNameSpaceID_XHTML
&& stack
[i
]->name
== name
) {
4034 nsHtml5TreeBuilder::findLastOrRoot(int32_t group
)
4036 for (int32_t i
= currentPtr
; i
> 0; i
--) {
4037 if (stack
[i
]->getGroup() == group
) {
4045 nsHtml5TreeBuilder::addAttributesToBody(nsHtml5HtmlAttributes
* attributes
)
4047 if (currentPtr
>= 1) {
4048 nsHtml5StackNode
* body
= stack
[1];
4049 if (body
->getGroup() == nsHtml5TreeBuilder::BODY
) {
4050 addAttributesToElement(body
->node
, attributes
);
4058 nsHtml5TreeBuilder::addAttributesToHtml(nsHtml5HtmlAttributes
* attributes
)
4060 addAttributesToElement(stack
[0]->node
, attributes
);
4064 nsHtml5TreeBuilder::pushHeadPointerOntoStack()
4066 MOZ_ASSERT(!!headPointer
);
4067 MOZ_ASSERT(mode
== AFTER_HEAD
);
4069 silentPush(createStackNode(nsHtml5ElementName::ELT_HEAD
, headPointer
));
4073 nsHtml5TreeBuilder::reconstructTheActiveFormattingElements()
4075 if (listPtr
== -1) {
4078 nsHtml5StackNode
* mostRecent
= listOfActiveFormattingElements
[listPtr
];
4079 if (!mostRecent
|| isInStack(mostRecent
)) {
4082 int32_t entryPos
= listPtr
;
4085 if (entryPos
== -1) {
4088 if (!listOfActiveFormattingElements
[entryPos
]) {
4091 if (isInStack(listOfActiveFormattingElements
[entryPos
])) {
4095 while (entryPos
< listPtr
) {
4097 nsHtml5StackNode
* entry
= listOfActiveFormattingElements
[entryPos
];
4098 nsHtml5StackNode
* currentNode
= stack
[currentPtr
];
4099 nsIContentHandle
* clone
;
4100 if (currentNode
->isFosterParenting()) {
4101 clone
= createAndInsertFosterParentedElement(
4104 entry
->attributes
->cloneAttributes(nullptr),
4105 htmlCreator(entry
->getHtmlCreator()));
4107 clone
= createElement(kNameSpaceID_XHTML
,
4109 entry
->attributes
->cloneAttributes(nullptr),
4111 htmlCreator(entry
->getHtmlCreator()));
4112 appendElement(clone
, currentNode
->node
);
4114 nsHtml5StackNode
* entryClone
= createStackNode(entry
->getFlags(),
4120 entry
->getHtmlCreator());
4121 entry
->dropAttributes();
4123 listOfActiveFormattingElements
[entryPos
] = entryClone
;
4124 entry
->release(this);
4125 entryClone
->retain();
4130 nsHtml5TreeBuilder::notifyUnusedStackNode(int32_t idxInStackNodes
)
4132 if (idxInStackNodes
< stackNodesIdx
) {
4133 stackNodesIdx
= idxInStackNodes
;
4138 nsHtml5TreeBuilder::getUnusedStackNode()
4140 while (stackNodesIdx
< numStackNodes
) {
4141 if (stackNodes
[stackNodesIdx
]->isUnused()) {
4142 return stackNodes
[stackNodesIdx
++];
4146 if (stackNodesIdx
< stackNodes
.length
) {
4147 stackNodes
[stackNodesIdx
] = new nsHtml5StackNode(stackNodesIdx
);
4149 return stackNodes
[stackNodesIdx
++];
4151 jArray
<nsHtml5StackNode
*, int32_t> newStack
=
4152 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(stackNodes
.length
+ 64);
4153 nsHtml5ArrayCopy::arraycopy(stackNodes
, newStack
, stackNodes
.length
);
4154 stackNodes
= newStack
;
4155 stackNodes
[stackNodesIdx
] = new nsHtml5StackNode(stackNodesIdx
);
4157 return stackNodes
[stackNodesIdx
++];
4161 nsHtml5TreeBuilder::createStackNode(
4165 nsIContentHandle
* node
,
4167 nsHtml5HtmlAttributes
* attributes
,
4168 mozilla::dom::HTMLContentCreatorFunction htmlCreator
)
4170 nsHtml5StackNode
* instance
= getUnusedStackNode();
4171 instance
->setValues(flags
, ns
, name
, node
, popName
, attributes
, htmlCreator
);
4176 nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName
* elementName
,
4177 nsIContentHandle
* node
)
4179 nsHtml5StackNode
* instance
= getUnusedStackNode();
4180 instance
->setValues(elementName
, node
);
4185 nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName
* elementName
,
4186 nsIContentHandle
* node
,
4187 nsHtml5HtmlAttributes
* attributes
)
4189 nsHtml5StackNode
* instance
= getUnusedStackNode();
4190 instance
->setValues(elementName
, node
, attributes
);
4195 nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName
* elementName
,
4196 nsIContentHandle
* node
,
4199 nsHtml5StackNode
* instance
= getUnusedStackNode();
4200 instance
->setValues(elementName
, node
, popName
);
4205 nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName
* elementName
,
4207 nsIContentHandle
* node
)
4209 nsHtml5StackNode
* instance
= getUnusedStackNode();
4210 instance
->setValues(elementName
, popName
, node
);
4215 nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName
* elementName
,
4216 nsIContentHandle
* node
,
4218 bool markAsIntegrationPoint
)
4220 nsHtml5StackNode
* instance
= getUnusedStackNode();
4221 instance
->setValues(elementName
, node
, popName
, markAsIntegrationPoint
);
4226 nsHtml5TreeBuilder::insertIntoFosterParent(nsIContentHandle
* child
)
4228 int32_t tablePos
= findLastOrRoot(nsHtml5TreeBuilder::TABLE
);
4229 int32_t templatePos
= findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE
);
4230 if (templatePos
>= tablePos
) {
4231 appendElement(child
, stack
[templatePos
]->node
);
4234 nsHtml5StackNode
* node
= stack
[tablePos
];
4235 insertFosterParentedChild(child
, node
->node
, stack
[tablePos
- 1]->node
);
4239 nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
4242 nsHtml5HtmlAttributes
* attributes
,
4243 nsHtml5ContentCreatorFunction creator
)
4245 return createAndInsertFosterParentedElement(
4246 ns
, name
, attributes
, nullptr, creator
);
4250 nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
4253 nsHtml5HtmlAttributes
* attributes
,
4254 nsIContentHandle
* form
,
4255 nsHtml5ContentCreatorFunction creator
)
4257 int32_t tablePos
= findLastOrRoot(nsHtml5TreeBuilder::TABLE
);
4258 int32_t templatePos
= findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE
);
4259 if (templatePos
>= tablePos
) {
4260 nsIContentHandle
* child
= createElement(
4261 ns
, name
, attributes
, form
, stack
[templatePos
]->node
, creator
);
4262 appendElement(child
, stack
[templatePos
]->node
);
4265 nsHtml5StackNode
* node
= stack
[tablePos
];
4266 return createAndInsertFosterParentedElement(
4267 ns
, name
, attributes
, form
, node
->node
, stack
[tablePos
- 1]->node
, creator
);
4271 nsHtml5TreeBuilder::isInStack(nsHtml5StackNode
* node
)
4273 for (int32_t i
= currentPtr
; i
>= 0; i
--) {
4274 if (stack
[i
] == node
) {
4282 nsHtml5TreeBuilder::popTemplateMode()
4288 nsHtml5TreeBuilder::pop()
4290 nsHtml5StackNode
* node
= stack
[currentPtr
];
4291 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4293 elementPopped(node
->ns
, node
->popName
, node
->node
);
4294 node
->release(this);
4298 nsHtml5TreeBuilder::silentPop()
4300 nsHtml5StackNode
* node
= stack
[currentPtr
];
4301 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4303 node
->release(this);
4307 nsHtml5TreeBuilder::popOnEof()
4309 nsHtml5StackNode
* node
= stack
[currentPtr
];
4310 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4312 markMalformedIfScript(node
->node
);
4313 elementPopped(node
->ns
, node
->popName
, node
->node
);
4314 node
->release(this);
4318 nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush(
4319 nsHtml5HtmlAttributes
* attributes
)
4321 nsIContentHandle
* elt
= createHtmlElementSetAsRoot(attributes
);
4322 nsHtml5StackNode
* node
= createStackNode(nsHtml5ElementName::ELT_HTML
, elt
);
4327 nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush()
4329 appendHtmlElementToDocumentAndPush(tokenizer
->emptyAttributes());
4333 nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(
4334 nsHtml5HtmlAttributes
* attributes
)
4336 nsIContentHandle
* currentNode
= stack
[currentPtr
]->node
;
4337 nsIContentHandle
* elt
= createElement(kNameSpaceID_XHTML
,
4341 htmlCreator(NS_NewHTMLSharedElement
));
4342 appendElement(elt
, currentNode
);
4344 nsHtml5StackNode
* node
= createStackNode(nsHtml5ElementName::ELT_HEAD
, elt
);
4349 nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement(
4350 nsHtml5HtmlAttributes
* attributes
)
4352 appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_BODY
, attributes
);
4356 nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement()
4358 appendToCurrentNodeAndPushBodyElement(tokenizer
->emptyAttributes());
4362 nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(
4363 nsHtml5HtmlAttributes
* attributes
)
4365 nsIContentHandle
* elt
;
4366 nsHtml5StackNode
* current
= stack
[currentPtr
];
4367 if (current
->isFosterParenting()) {
4370 createAndInsertFosterParentedElement(kNameSpaceID_XHTML
,
4373 htmlCreator(NS_NewHTMLFormElement
));
4375 elt
= createElement(kNameSpaceID_XHTML
,
4379 htmlCreator(NS_NewHTMLFormElement
));
4380 appendElement(elt
, current
->node
);
4382 if (!isTemplateContents()) {
4385 nsHtml5StackNode
* node
= createStackNode(nsHtml5ElementName::ELT_FORM
, elt
);
4390 nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(
4391 nsHtml5ElementName
* elementName
,
4392 nsHtml5HtmlAttributes
* attributes
)
4394 nsHtml5HtmlAttributes
* clone
= attributes
->cloneAttributes(nullptr);
4395 nsIContentHandle
* elt
;
4396 nsHtml5StackNode
* current
= stack
[currentPtr
];
4397 if (current
->isFosterParenting()) {
4399 elt
= createAndInsertFosterParentedElement(
4401 elementName
->getName(),
4403 htmlCreator(elementName
->getHtmlCreator()));
4405 elt
= createElement(kNameSpaceID_XHTML
,
4406 elementName
->getName(),
4409 htmlCreator(elementName
->getHtmlCreator()));
4410 appendElement(elt
, current
->node
);
4412 nsHtml5StackNode
* node
= createStackNode(elementName
, elt
, clone
);
4419 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(
4420 nsHtml5ElementName
* elementName
,
4421 nsHtml5HtmlAttributes
* attributes
)
4423 nsIContentHandle
* currentNode
= stack
[currentPtr
]->node
;
4424 nsIContentHandle
* elt
=
4425 createElement(kNameSpaceID_XHTML
,
4426 elementName
->getName(),
4429 htmlCreator(elementName
->getHtmlCreator()));
4430 appendElement(elt
, currentNode
);
4431 if (nsHtml5ElementName::ELT_TEMPLATE
== elementName
) {
4432 elt
= getDocumentFragmentForTemplate(elt
);
4434 nsHtml5StackNode
* node
= createStackNode(elementName
, elt
);
4439 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
4440 nsHtml5ElementName
* elementName
,
4441 nsHtml5HtmlAttributes
* attributes
)
4443 nsAtom
* popName
= elementName
->getName();
4444 nsIContentHandle
* elt
;
4445 nsHtml5StackNode
* current
= stack
[currentPtr
];
4446 if (current
->isFosterParenting()) {
4448 elt
= createAndInsertFosterParentedElement(
4452 htmlCreator(elementName
->getHtmlCreator()));
4454 elt
= createElement(kNameSpaceID_XHTML
,
4458 htmlCreator(elementName
->getHtmlCreator()));
4459 appendElement(elt
, current
->node
);
4461 nsHtml5StackNode
* node
= createStackNode(elementName
, elt
, popName
);
4466 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(
4467 nsHtml5ElementName
* elementName
,
4468 nsHtml5HtmlAttributes
* attributes
)
4470 nsAtom
* popName
= elementName
->getName();
4471 bool markAsHtmlIntegrationPoint
= false;
4472 if (nsHtml5ElementName::ELT_ANNOTATION_XML
== elementName
&&
4473 annotationXmlEncodingPermitsHtml(attributes
)) {
4474 markAsHtmlIntegrationPoint
= true;
4476 nsIContentHandle
* elt
;
4477 nsHtml5StackNode
* current
= stack
[currentPtr
];
4478 if (current
->isFosterParenting()) {
4480 elt
= createAndInsertFosterParentedElement(
4481 kNameSpaceID_MathML
, popName
, attributes
, htmlCreator(nullptr));
4483 elt
= createElement(kNameSpaceID_MathML
,
4487 htmlCreator(nullptr));
4488 appendElement(elt
, current
->node
);
4490 nsHtml5StackNode
* node
=
4491 createStackNode(elementName
, elt
, popName
, markAsHtmlIntegrationPoint
);
4496 nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(
4497 nsHtml5HtmlAttributes
* attributes
)
4499 nsHtml5String encoding
=
4500 attributes
->getValue(nsHtml5AttributeName::ATTR_ENCODING
);
4504 return nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
4505 "application/xhtml+xml", encoding
) ||
4506 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
4507 "text/html", encoding
);
4511 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(
4512 nsHtml5ElementName
* elementName
,
4513 nsHtml5HtmlAttributes
* attributes
)
4515 nsAtom
* popName
= elementName
->getCamelCaseName();
4516 nsIContentHandle
* elt
;
4517 nsHtml5StackNode
* current
= stack
[currentPtr
];
4518 if (current
->isFosterParenting()) {
4520 elt
= createAndInsertFosterParentedElement(
4524 svgCreator(elementName
->getSvgCreator()));
4526 elt
= createElement(kNameSpaceID_SVG
,
4530 svgCreator(elementName
->getSvgCreator()));
4531 appendElement(elt
, current
->node
);
4533 nsHtml5StackNode
* node
= createStackNode(elementName
, popName
, elt
);
4538 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
4539 nsHtml5ElementName
* elementName
,
4540 nsHtml5HtmlAttributes
* attributes
,
4541 nsIContentHandle
* form
)
4543 nsIContentHandle
* elt
;
4544 nsIContentHandle
* formOwner
=
4545 !form
|| fragment
|| isTemplateContents() ? nullptr : form
;
4546 nsHtml5StackNode
* current
= stack
[currentPtr
];
4547 if (current
->isFosterParenting()) {
4549 elt
= createAndInsertFosterParentedElement(
4551 elementName
->getName(),
4554 htmlCreator(elementName
->getHtmlCreator()));
4556 elt
= createElement(kNameSpaceID_XHTML
,
4557 elementName
->getName(),
4561 htmlCreator(elementName
->getHtmlCreator()));
4562 appendElement(elt
, current
->node
);
4564 nsHtml5StackNode
* node
= createStackNode(elementName
, elt
);
4569 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
4570 nsHtml5ElementName
* elementName
,
4571 nsHtml5HtmlAttributes
* attributes
,
4572 nsIContentHandle
* form
)
4574 nsAtom
* name
= elementName
->getName();
4575 nsIContentHandle
* elt
;
4576 nsIContentHandle
* formOwner
=
4577 !form
|| fragment
|| isTemplateContents() ? nullptr : form
;
4578 nsHtml5StackNode
* current
= stack
[currentPtr
];
4579 if (current
->isFosterParenting()) {
4581 elt
= createAndInsertFosterParentedElement(
4586 htmlCreator(elementName
->getHtmlCreator()));
4588 elt
= createElement(kNameSpaceID_XHTML
,
4593 htmlCreator(elementName
->getHtmlCreator()));
4594 appendElement(elt
, current
->node
);
4596 elementPushed(kNameSpaceID_XHTML
, name
, elt
);
4597 elementPopped(kNameSpaceID_XHTML
, name
, elt
);
4601 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
4602 nsHtml5ElementName
* elementName
,
4603 nsHtml5HtmlAttributes
* attributes
)
4605 nsAtom
* popName
= elementName
->getName();
4606 nsIContentHandle
* elt
;
4607 nsHtml5StackNode
* current
= stack
[currentPtr
];
4608 if (current
->isFosterParenting()) {
4610 elt
= createAndInsertFosterParentedElement(
4614 htmlCreator(elementName
->getHtmlCreator()));
4616 elt
= createElement(kNameSpaceID_XHTML
,
4620 htmlCreator(elementName
->getHtmlCreator()));
4621 appendElement(elt
, current
->node
);
4623 elementPushed(kNameSpaceID_XHTML
, popName
, elt
);
4624 elementPopped(kNameSpaceID_XHTML
, popName
, elt
);
4628 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(
4629 nsHtml5ElementName
* elementName
,
4630 nsHtml5HtmlAttributes
* attributes
)
4632 nsAtom
* popName
= elementName
->getCamelCaseName();
4633 nsIContentHandle
* elt
;
4634 nsHtml5StackNode
* current
= stack
[currentPtr
];
4635 if (current
->isFosterParenting()) {
4637 elt
= createAndInsertFosterParentedElement(
4641 svgCreator(elementName
->getSvgCreator()));
4643 elt
= createElement(kNameSpaceID_SVG
,
4647 svgCreator(elementName
->getSvgCreator()));
4648 appendElement(elt
, current
->node
);
4650 elementPushed(kNameSpaceID_SVG
, popName
, elt
);
4651 elementPopped(kNameSpaceID_SVG
, popName
, elt
);
4655 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(
4656 nsHtml5ElementName
* elementName
,
4657 nsHtml5HtmlAttributes
* attributes
)
4659 nsAtom
* popName
= elementName
->getName();
4660 nsIContentHandle
* elt
;
4661 nsHtml5StackNode
* current
= stack
[currentPtr
];
4662 if (current
->isFosterParenting()) {
4664 elt
= createAndInsertFosterParentedElement(
4665 kNameSpaceID_MathML
, popName
, attributes
, htmlCreator(nullptr));
4667 elt
= createElement(kNameSpaceID_MathML
,
4671 htmlCreator(nullptr));
4672 appendElement(elt
, current
->node
);
4674 elementPushed(kNameSpaceID_MathML
, popName
, elt
);
4675 elementPopped(kNameSpaceID_MathML
, popName
, elt
);
4679 nsHtml5TreeBuilder::appendVoidInputToCurrent(nsHtml5HtmlAttributes
* attributes
,
4680 nsIContentHandle
* form
)
4682 nsIContentHandle
* currentNode
= stack
[currentPtr
]->node
;
4683 nsIContentHandle
* elt
=
4684 createElement(kNameSpaceID_XHTML
,
4687 !form
|| fragment
|| isTemplateContents() ? nullptr : form
,
4689 htmlCreator(NS_NewHTMLInputElement
));
4690 appendElement(elt
, currentNode
);
4691 elementPushed(kNameSpaceID_XHTML
, nsGkAtoms::input
, elt
);
4692 elementPopped(kNameSpaceID_XHTML
, nsGkAtoms::input
, elt
);
4696 nsHtml5TreeBuilder::appendVoidFormToCurrent(nsHtml5HtmlAttributes
* attributes
)
4698 nsIContentHandle
* currentNode
= stack
[currentPtr
]->node
;
4699 nsIContentHandle
* elt
= createElement(kNameSpaceID_XHTML
,
4703 htmlCreator(NS_NewHTMLFormElement
));
4705 appendElement(elt
, currentNode
);
4706 elementPushed(kNameSpaceID_XHTML
, nsGkAtoms::form
, elt
);
4707 elementPopped(kNameSpaceID_XHTML
, nsGkAtoms::form
, elt
);
4711 nsHtml5TreeBuilder::requestSuspension()
4713 tokenizer
->requestSuspension();
4718 nsHtml5TreeBuilder::isInForeign()
4720 return currentPtr
>= 0 && stack
[currentPtr
]->ns
!= kNameSpaceID_XHTML
;
4724 nsHtml5TreeBuilder::isInForeignButNotHtmlOrMathTextIntegrationPoint()
4726 if (currentPtr
< 0) {
4729 return !isSpecialParentInForeign(stack
[currentPtr
]);
4733 nsHtml5TreeBuilder::setFragmentContext(nsAtom
* context
,
4735 nsIContentHandle
* node
,
4738 this->contextName
= context
;
4739 this->contextNamespace
= ns
;
4740 this->contextNode
= node
;
4741 this->fragment
= (!!contextName
);
4742 this->quirks
= quirks
;
4746 nsHtml5TreeBuilder::currentNode()
4748 return stack
[currentPtr
]->node
;
4752 nsHtml5TreeBuilder::isScriptingEnabled()
4754 return scriptingEnabled
;
4758 nsHtml5TreeBuilder::setScriptingEnabled(bool scriptingEnabled
)
4760 this->scriptingEnabled
= scriptingEnabled
;
4764 nsHtml5TreeBuilder::setIsSrcdocDocument(bool isSrcdocDocument
)
4766 this->isSrcdocDocument
= isSrcdocDocument
;
4770 nsHtml5TreeBuilder::flushCharacters()
4772 if (charBufferLen
> 0) {
4773 if ((mode
== IN_TABLE
|| mode
== IN_TABLE_BODY
|| mode
== IN_ROW
) &&
4774 charBufferContainsNonWhitespace()) {
4775 errNonSpaceInTable();
4776 reconstructTheActiveFormattingElements();
4777 if (!stack
[currentPtr
]->isFosterParenting()) {
4778 appendCharacters(currentNode(), charBuffer
, 0, charBufferLen
);
4782 int32_t tablePos
= findLastOrRoot(nsHtml5TreeBuilder::TABLE
);
4783 int32_t templatePos
= findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE
);
4784 if (templatePos
>= tablePos
) {
4786 stack
[templatePos
]->node
, charBuffer
, 0, charBufferLen
);
4790 nsHtml5StackNode
* tableElt
= stack
[tablePos
];
4791 insertFosterParentedCharacters(charBuffer
,
4795 stack
[tablePos
- 1]->node
);
4799 appendCharacters(currentNode(), charBuffer
, 0, charBufferLen
);
4805 nsHtml5TreeBuilder::charBufferContainsNonWhitespace()
4807 for (int32_t i
= 0; i
< charBufferLen
; i
++) {
4808 switch (charBuffer
[i
]) {
4824 nsAHtml5TreeBuilderState
*
4825 nsHtml5TreeBuilder::newSnapshot()
4827 jArray
<nsHtml5StackNode
*, int32_t> listCopy
=
4828 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(listPtr
+ 1);
4829 for (int32_t i
= 0; i
< listCopy
.length
; i
++) {
4830 nsHtml5StackNode
* node
= listOfActiveFormattingElements
[i
];
4832 nsHtml5StackNode
* newNode
= new nsHtml5StackNode(-1);
4833 newNode
->setValues(node
->getFlags(),
4838 node
->attributes
->cloneAttributes(nullptr),
4839 node
->getHtmlCreator());
4840 listCopy
[i
] = newNode
;
4842 listCopy
[i
] = nullptr;
4845 jArray
<nsHtml5StackNode
*, int32_t> stackCopy
=
4846 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(currentPtr
+ 1);
4847 for (int32_t i
= 0; i
< stackCopy
.length
; i
++) {
4848 nsHtml5StackNode
* node
= stack
[i
];
4849 int32_t listIndex
= findInListOfActiveFormattingElements(node
);
4850 if (listIndex
== -1) {
4851 nsHtml5StackNode
* newNode
= new nsHtml5StackNode(-1);
4852 newNode
->setValues(node
->getFlags(),
4858 node
->getHtmlCreator());
4859 stackCopy
[i
] = newNode
;
4861 stackCopy
[i
] = listCopy
[listIndex
];
4862 stackCopy
[i
]->retain();
4865 jArray
<int32_t, int32_t> templateModeStackCopy
=
4866 jArray
<int32_t, int32_t>::newJArray(templateModePtr
+ 1);
4867 nsHtml5ArrayCopy::arraycopy(
4868 templateModeStack
, templateModeStackCopy
, templateModeStackCopy
.length
);
4869 return new nsHtml5StateSnapshot(stackCopy
,
4871 templateModeStackCopy
,
4874 deepTreeSurrogateParent
,
4883 nsHtml5TreeBuilder::snapshotMatches(nsAHtml5TreeBuilderState
* snapshot
)
4885 jArray
<nsHtml5StackNode
*, int32_t> stackCopy
= snapshot
->getStack();
4886 int32_t stackLen
= snapshot
->getStackLength();
4887 jArray
<nsHtml5StackNode
*, int32_t> listCopy
=
4888 snapshot
->getListOfActiveFormattingElements();
4889 int32_t listLen
= snapshot
->getListOfActiveFormattingElementsLength();
4890 jArray
<int32_t, int32_t> templateModeStackCopy
=
4891 snapshot
->getTemplateModeStack();
4892 int32_t templateModeStackLen
= snapshot
->getTemplateModeStackLength();
4893 if (stackLen
!= currentPtr
+ 1 || listLen
!= listPtr
+ 1 ||
4894 templateModeStackLen
!= templateModePtr
+ 1 ||
4895 formPointer
!= snapshot
->getFormPointer() ||
4896 headPointer
!= snapshot
->getHeadPointer() ||
4897 deepTreeSurrogateParent
!= snapshot
->getDeepTreeSurrogateParent() ||
4898 mode
!= snapshot
->getMode() ||
4899 originalMode
!= snapshot
->getOriginalMode() ||
4900 framesetOk
!= snapshot
->isFramesetOk() ||
4901 needToDropLF
!= snapshot
->isNeedToDropLF() ||
4902 quirks
!= snapshot
->isQuirks()) {
4905 for (int32_t i
= listLen
- 1; i
>= 0; i
--) {
4906 if (!listCopy
[i
] && !listOfActiveFormattingElements
[i
]) {
4908 } else if (!listCopy
[i
] || !listOfActiveFormattingElements
[i
]) {
4911 if (listCopy
[i
]->node
!= listOfActiveFormattingElements
[i
]->node
) {
4915 for (int32_t i
= stackLen
- 1; i
>= 0; i
--) {
4916 if (stackCopy
[i
]->node
!= stack
[i
]->node
) {
4920 for (int32_t i
= templateModeStackLen
- 1; i
>= 0; i
--) {
4921 if (templateModeStackCopy
[i
] != templateModeStack
[i
]) {
4929 nsHtml5TreeBuilder::loadState(nsAHtml5TreeBuilderState
* snapshot
,
4930 nsHtml5AtomTable
* interner
)
4932 mCurrentHtmlScriptIsAsyncOrDefer
= false;
4933 jArray
<nsHtml5StackNode
*, int32_t> stackCopy
= snapshot
->getStack();
4934 int32_t stackLen
= snapshot
->getStackLength();
4935 jArray
<nsHtml5StackNode
*, int32_t> listCopy
=
4936 snapshot
->getListOfActiveFormattingElements();
4937 int32_t listLen
= snapshot
->getListOfActiveFormattingElementsLength();
4938 jArray
<int32_t, int32_t> templateModeStackCopy
=
4939 snapshot
->getTemplateModeStack();
4940 int32_t templateModeStackLen
= snapshot
->getTemplateModeStackLength();
4941 for (int32_t i
= 0; i
<= listPtr
; i
++) {
4942 if (listOfActiveFormattingElements
[i
]) {
4943 listOfActiveFormattingElements
[i
]->release(this);
4946 if (listOfActiveFormattingElements
.length
< listLen
) {
4947 listOfActiveFormattingElements
=
4948 jArray
<nsHtml5StackNode
*, int32_t>::newJArray(listLen
);
4950 listPtr
= listLen
- 1;
4951 for (int32_t i
= 0; i
<= currentPtr
; i
++) {
4952 stack
[i
]->release(this);
4954 if (stack
.length
< stackLen
) {
4955 stack
= jArray
<nsHtml5StackNode
*, int32_t>::newJArray(stackLen
);
4957 currentPtr
= stackLen
- 1;
4958 if (templateModeStack
.length
< templateModeStackLen
) {
4960 jArray
<int32_t, int32_t>::newJArray(templateModeStackLen
);
4962 templateModePtr
= templateModeStackLen
- 1;
4963 for (int32_t i
= 0; i
< listLen
; i
++) {
4964 nsHtml5StackNode
* node
= listCopy
[i
];
4966 nsHtml5StackNode
* newNode
= createStackNode(
4969 nsHtml5Portability::newLocalFromLocal(node
->name
, interner
),
4971 nsHtml5Portability::newLocalFromLocal(node
->popName
, interner
),
4972 node
->attributes
->cloneAttributes(nullptr),
4973 node
->getHtmlCreator());
4974 listOfActiveFormattingElements
[i
] = newNode
;
4976 listOfActiveFormattingElements
[i
] = nullptr;
4979 for (int32_t i
= 0; i
< stackLen
; i
++) {
4980 nsHtml5StackNode
* node
= stackCopy
[i
];
4981 int32_t listIndex
= findInArray(node
, listCopy
);
4982 if (listIndex
== -1) {
4983 nsHtml5StackNode
* newNode
= createStackNode(
4986 nsHtml5Portability::newLocalFromLocal(node
->name
, interner
),
4988 nsHtml5Portability::newLocalFromLocal(node
->popName
, interner
),
4990 node
->getHtmlCreator());
4993 stack
[i
] = listOfActiveFormattingElements
[listIndex
];
4997 nsHtml5ArrayCopy::arraycopy(
4998 templateModeStackCopy
, templateModeStack
, templateModeStackLen
);
4999 formPointer
= snapshot
->getFormPointer();
5000 headPointer
= snapshot
->getHeadPointer();
5001 deepTreeSurrogateParent
= snapshot
->getDeepTreeSurrogateParent();
5002 mode
= snapshot
->getMode();
5003 originalMode
= snapshot
->getOriginalMode();
5004 framesetOk
= snapshot
->isFramesetOk();
5005 needToDropLF
= snapshot
->isNeedToDropLF();
5006 quirks
= snapshot
->isQuirks();
5010 nsHtml5TreeBuilder::findInArray(nsHtml5StackNode
* node
,
5011 jArray
<nsHtml5StackNode
*, int32_t> arr
)
5013 for (int32_t i
= listPtr
; i
>= 0; i
--) {
5014 if (node
== arr
[i
]) {
5022 nsHtml5TreeBuilder::getFormPointer()
5028 nsHtml5TreeBuilder::getHeadPointer()
5034 nsHtml5TreeBuilder::getDeepTreeSurrogateParent()
5036 return deepTreeSurrogateParent
;
5039 jArray
<nsHtml5StackNode
*, int32_t>
5040 nsHtml5TreeBuilder::getListOfActiveFormattingElements()
5042 return listOfActiveFormattingElements
;
5045 jArray
<nsHtml5StackNode
*, int32_t>
5046 nsHtml5TreeBuilder::getStack()
5051 jArray
<int32_t, int32_t>
5052 nsHtml5TreeBuilder::getTemplateModeStack()
5054 return templateModeStack
;
5058 nsHtml5TreeBuilder::getMode()
5064 nsHtml5TreeBuilder::getOriginalMode()
5066 return originalMode
;
5070 nsHtml5TreeBuilder::isFramesetOk()
5076 nsHtml5TreeBuilder::isNeedToDropLF()
5078 return needToDropLF
;
5082 nsHtml5TreeBuilder::isQuirks()
5088 nsHtml5TreeBuilder::getListOfActiveFormattingElementsLength()
5094 nsHtml5TreeBuilder::getStackLength()
5096 return currentPtr
+ 1;
5100 nsHtml5TreeBuilder::getTemplateModeStackLength()
5102 return templateModePtr
+ 1;
5106 nsHtml5TreeBuilder::initializeStatics()
5111 nsHtml5TreeBuilder::releaseStatics()
5115 #include "nsHtml5TreeBuilderCppSupplement.h"