Bug 1921090 - Fix fenix lint failure CLOSED TREE
[gecko.git] / parser / html / nsHtml5TreeBuilder.cpp
blobef4de158fec5248f3e4aae42e37988f09e7e3744
1 /*
2 * Copyright (c) 2007 Henri Sivonen
3 * Copyright (c) 2007-2017 Mozilla Foundation
4 * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla
5 * Foundation, and Opera Software ASA.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
27 * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
28 * Please edit TreeBuilder.java instead and regenerate.
31 #define nsHtml5TreeBuilder_cpp__
33 #include "nsHtml5AttributeName.h"
34 #include "nsHtml5ElementName.h"
35 #include "nsHtml5Tokenizer.h"
36 #include "nsHtml5StackNode.h"
37 #include "nsHtml5UTF16Buffer.h"
38 #include "nsHtml5StateSnapshot.h"
39 #include "nsHtml5Portability.h"
41 #include "nsHtml5TreeBuilder.h"
43 char16_t nsHtml5TreeBuilder::REPLACEMENT_CHARACTER[] = {0xfffd};
44 static const char* const QUIRKY_PUBLIC_IDS_DATA[] = {
45 "+//silmaril//dtd html pro v0r11 19970101//",
46 "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
47 "-//as//dtd html 3.0 aswedit + extensions//",
48 "-//ietf//dtd html 2.0 level 1//",
49 "-//ietf//dtd html 2.0 level 2//",
50 "-//ietf//dtd html 2.0 strict level 1//",
51 "-//ietf//dtd html 2.0 strict level 2//",
52 "-//ietf//dtd html 2.0 strict//",
53 "-//ietf//dtd html 2.0//",
54 "-//ietf//dtd html 2.1e//",
55 "-//ietf//dtd html 3.0//",
56 "-//ietf//dtd html 3.2 final//",
57 "-//ietf//dtd html 3.2//",
58 "-//ietf//dtd html 3//",
59 "-//ietf//dtd html level 0//",
60 "-//ietf//dtd html level 1//",
61 "-//ietf//dtd html level 2//",
62 "-//ietf//dtd html level 3//",
63 "-//ietf//dtd html strict level 0//",
64 "-//ietf//dtd html strict level 1//",
65 "-//ietf//dtd html strict level 2//",
66 "-//ietf//dtd html strict level 3//",
67 "-//ietf//dtd html strict//",
68 "-//ietf//dtd html//",
69 "-//metrius//dtd metrius presentational//",
70 "-//microsoft//dtd internet explorer 2.0 html strict//",
71 "-//microsoft//dtd internet explorer 2.0 html//",
72 "-//microsoft//dtd internet explorer 2.0 tables//",
73 "-//microsoft//dtd internet explorer 3.0 html strict//",
74 "-//microsoft//dtd internet explorer 3.0 html//",
75 "-//microsoft//dtd internet explorer 3.0 tables//",
76 "-//netscape comm. corp.//dtd html//",
77 "-//netscape comm. corp.//dtd strict html//",
78 "-//o'reilly and associates//dtd html 2.0//",
79 "-//o'reilly and associates//dtd html extended 1.0//",
80 "-//o'reilly and associates//dtd html extended relaxed 1.0//",
81 "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html "
82 "4.0//",
83 "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
84 "-//spyglass//dtd html 2.0 extended//",
85 "-//sq//dtd html 2.0 hotmetal + extensions//",
86 "-//sun microsystems corp.//dtd hotjava html//",
87 "-//sun microsystems corp.//dtd hotjava strict html//",
88 "-//w3c//dtd html 3 1995-03-24//",
89 "-//w3c//dtd html 3.2 draft//",
90 "-//w3c//dtd html 3.2 final//",
91 "-//w3c//dtd html 3.2//",
92 "-//w3c//dtd html 3.2s draft//",
93 "-//w3c//dtd html 4.0 frameset//",
94 "-//w3c//dtd html 4.0 transitional//",
95 "-//w3c//dtd html experimental 19960712//",
96 "-//w3c//dtd html experimental 970421//",
97 "-//w3c//dtd w3 html//",
98 "-//w3o//dtd w3 html 3.0//",
99 "-//webtechs//dtd mozilla html 2.0//",
100 "-//webtechs//dtd mozilla html//"};
101 staticJArray<const char*, int32_t> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = {
102 QUIRKY_PUBLIC_IDS_DATA, MOZ_ARRAY_LENGTH(QUIRKY_PUBLIC_IDS_DATA)};
103 void nsHtml5TreeBuilder::setKeepBuffer(bool keepBuffer) {
104 this->keepBuffer = keepBuffer;
107 bool nsHtml5TreeBuilder::dropBufferIfLongerThan(int32_t length) {
108 if (charBuffer.length > length) {
109 charBuffer = nullptr;
110 return true;
112 return false;
115 void nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) {
116 tokenizer = self;
117 stackNodes = jArray<nsHtml5StackNode*, int32_t>::newJArray(64);
118 stack = jArray<nsHtml5StackNode*, int32_t>::newJArray(64);
119 templateModeStack = jArray<int32_t, int32_t>::newJArray(64);
120 listOfActiveFormattingElements =
121 jArray<nsHtml5StackNode*, int32_t>::newJArray(64);
122 needToDropLF = false;
123 originalMode = INITIAL;
124 templateModePtr = -1;
125 stackNodesIdx = 0;
126 numStackNodes = 0;
127 currentPtr = -1;
128 listPtr = -1;
129 formPointer = nullptr;
130 headPointer = nullptr;
131 start(fragment);
132 charBufferLen = 0;
133 if (!keepBuffer) {
134 charBuffer = nullptr;
136 framesetOk = true;
137 if (fragment) {
138 nsIContentHandle* elt;
139 if (contextNode) {
140 elt = contextNode;
141 } else {
142 elt = createHtmlElementSetAsRoot(tokenizer->emptyAttributes());
144 if (contextNamespace == kNameSpaceID_SVG) {
145 nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_SVG;
146 if (nsGkAtoms::title == contextName || nsGkAtoms::desc == contextName ||
147 nsGkAtoms::foreignObject == contextName) {
148 elementName = nsHtml5ElementName::ELT_FOREIGNOBJECT;
150 nsHtml5StackNode* node =
151 createStackNode(elementName, elementName->getCamelCaseName(), elt);
152 currentPtr++;
153 stack[currentPtr] = node;
154 tokenizer->setState(nsHtml5Tokenizer::DATA);
155 mode = FRAMESET_OK;
156 } else if (contextNamespace == kNameSpaceID_MathML) {
157 nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_MATH;
158 if (nsGkAtoms::mi_ == contextName || nsGkAtoms::mo_ == contextName ||
159 nsGkAtoms::mn_ == contextName || nsGkAtoms::ms_ == contextName ||
160 nsGkAtoms::mtext_ == contextName) {
161 elementName = nsHtml5ElementName::ELT_MTEXT;
162 } else if (nsGkAtoms::annotation_xml_ == contextName) {
163 elementName = nsHtml5ElementName::ELT_ANNOTATION_XML;
165 nsHtml5StackNode* node =
166 createStackNode(elementName, elt, elementName->getName(), false);
167 currentPtr++;
168 stack[currentPtr] = node;
169 tokenizer->setState(nsHtml5Tokenizer::DATA);
170 mode = FRAMESET_OK;
171 } else {
172 nsHtml5StackNode* node =
173 createStackNode(nsHtml5ElementName::ELT_HTML, elt);
174 currentPtr++;
175 stack[currentPtr] = node;
176 if (nsGkAtoms::_template == contextName) {
177 pushTemplateMode(IN_TEMPLATE);
179 resetTheInsertionMode();
180 formPointer = getFormPointerForContext(contextNode);
181 if (nsGkAtoms::title == contextName ||
182 nsGkAtoms::textarea == contextName) {
183 tokenizer->setState(nsHtml5Tokenizer::RCDATA);
184 } else if (nsGkAtoms::style == contextName ||
185 nsGkAtoms::xmp == contextName ||
186 nsGkAtoms::iframe == contextName ||
187 nsGkAtoms::noembed == contextName ||
188 nsGkAtoms::noframes == contextName ||
189 (scriptingEnabled && nsGkAtoms::noscript == contextName)) {
190 tokenizer->setState(nsHtml5Tokenizer::RAWTEXT);
191 } else if (nsGkAtoms::plaintext == contextName) {
192 tokenizer->setState(nsHtml5Tokenizer::PLAINTEXT);
193 } else if (nsGkAtoms::script == contextName) {
194 tokenizer->setState(nsHtml5Tokenizer::SCRIPT_DATA);
195 } else {
196 tokenizer->setState(nsHtml5Tokenizer::DATA);
199 } else {
200 mode = INITIAL;
201 if (tokenizer->isViewingXmlSource()) {
202 nsIContentHandle* elt = createElement(
203 kNameSpaceID_SVG, nsGkAtoms::svg, tokenizer->emptyAttributes(),
204 nullptr, svgCreator(NS_NewSVGSVGElement));
205 nsHtml5StackNode* node =
206 createStackNode(nsHtml5ElementName::ELT_SVG, nsGkAtoms::svg, elt);
207 currentPtr++;
208 stack[currentPtr] = node;
213 void nsHtml5TreeBuilder::doctype(nsAtom* name, nsHtml5String publicIdentifier,
214 nsHtml5String systemIdentifier,
215 bool forceQuirks) {
216 needToDropLF = false;
217 if (!isInForeign() && mode == INITIAL) {
218 nsHtml5String emptyString = nsHtml5Portability::newEmptyString();
219 appendDoctypeToDocument(!name ? nsGkAtoms::_empty : name,
220 !publicIdentifier ? emptyString : publicIdentifier,
221 !systemIdentifier ? emptyString : systemIdentifier);
222 emptyString.Release();
223 if (isQuirky(name, publicIdentifier, systemIdentifier, forceQuirks)) {
224 errQuirkyDoctype();
225 documentModeInternal(QUIRKS_MODE, publicIdentifier, systemIdentifier);
226 } else if (isAlmostStandards(publicIdentifier, systemIdentifier)) {
227 errAlmostStandardsDoctype();
228 documentModeInternal(ALMOST_STANDARDS_MODE, publicIdentifier,
229 systemIdentifier);
230 } else {
231 documentModeInternal(STANDARDS_MODE, publicIdentifier, systemIdentifier);
233 mode = BEFORE_HTML;
234 return;
236 errStrayDoctype();
237 return;
240 void nsHtml5TreeBuilder::comment(char16_t* buf, int32_t start, int32_t length) {
241 needToDropLF = false;
242 if (!isInForeign()) {
243 switch (mode) {
244 case INITIAL:
245 case BEFORE_HTML:
246 case AFTER_AFTER_BODY:
247 case AFTER_AFTER_FRAMESET: {
248 appendCommentToDocument(buf, start, length);
249 return;
251 case AFTER_BODY: {
252 flushCharacters();
253 appendComment(stack[0]->node, buf, start, length);
254 return;
256 default: {
257 break;
261 flushCharacters();
262 appendComment(stack[currentPtr]->node, buf, start, length);
263 return;
266 void nsHtml5TreeBuilder::characters(const char16_t* buf, int32_t start,
267 int32_t length) {
268 if (tokenizer->isViewingXmlSource()) {
269 return;
271 if (needToDropLF) {
272 needToDropLF = false;
273 if (buf[start] == '\n') {
274 start++;
275 length--;
276 if (!length) {
277 return;
281 switch (mode) {
282 case IN_BODY:
283 case IN_CELL:
284 case IN_CAPTION: {
285 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
286 reconstructTheActiveFormattingElements();
288 [[fallthrough]];
290 case TEXT: {
291 accumulateCharacters(buf, start, length);
292 return;
294 case IN_TABLE:
295 case IN_TABLE_BODY:
296 case IN_ROW: {
297 accumulateCharactersForced(buf, start, length);
298 return;
300 default: {
301 int32_t end = start + length;
302 for (int32_t i = start; i < end; i++) {
303 switch (buf[i]) {
304 case ' ':
305 case '\t':
306 case '\n':
307 case '\r':
308 case '\f': {
309 switch (mode) {
310 case INITIAL:
311 case BEFORE_HTML:
312 case BEFORE_HEAD: {
313 start = i + 1;
314 continue;
316 case IN_HEAD:
317 case IN_HEAD_NOSCRIPT:
318 case AFTER_HEAD:
319 case IN_COLUMN_GROUP:
320 case IN_FRAMESET:
321 case AFTER_FRAMESET: {
322 continue;
324 case FRAMESET_OK:
325 case IN_TEMPLATE:
326 case IN_BODY:
327 case IN_CELL:
328 case IN_CAPTION: {
329 if (start < i) {
330 accumulateCharacters(buf, start, i - start);
331 start = i;
333 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
334 flushCharacters();
335 reconstructTheActiveFormattingElements();
337 NS_HTML5_BREAK(charactersloop);
339 case IN_SELECT:
340 case IN_SELECT_IN_TABLE: {
341 NS_HTML5_BREAK(charactersloop);
343 case IN_TABLE:
344 case IN_TABLE_BODY:
345 case IN_ROW: {
346 accumulateCharactersForced(buf, i, 1);
347 start = i + 1;
348 continue;
350 case AFTER_BODY:
351 case AFTER_AFTER_BODY:
352 case AFTER_AFTER_FRAMESET: {
353 if (start < i) {
354 accumulateCharacters(buf, start, i - start);
355 start = i;
357 flushCharacters();
358 reconstructTheActiveFormattingElements();
359 continue;
362 MOZ_FALLTHROUGH_ASSERT();
364 default: {
365 switch (mode) {
366 case INITIAL: {
367 documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
368 mode = BEFORE_HTML;
369 i--;
370 continue;
372 case BEFORE_HTML: {
373 appendHtmlElementToDocumentAndPush();
374 mode = BEFORE_HEAD;
375 i--;
376 continue;
378 case BEFORE_HEAD: {
379 if (start < i) {
380 accumulateCharacters(buf, start, i - start);
381 start = i;
383 flushCharacters();
384 appendToCurrentNodeAndPushHeadElement(
385 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
386 mode = IN_HEAD;
387 i--;
388 continue;
390 case IN_HEAD: {
391 if (start < i) {
392 accumulateCharacters(buf, start, i - start);
393 start = i;
395 flushCharacters();
396 pop();
397 mode = AFTER_HEAD;
398 i--;
399 continue;
401 case IN_HEAD_NOSCRIPT: {
402 if (start < i) {
403 accumulateCharacters(buf, start, i - start);
404 start = i;
406 errNonSpaceInNoscriptInHead();
407 flushCharacters();
408 pop();
409 mode = IN_HEAD;
410 i--;
411 continue;
413 case AFTER_HEAD: {
414 if (start < i) {
415 accumulateCharacters(buf, start, i - start);
416 start = i;
418 flushCharacters();
419 appendToCurrentNodeAndPushBodyElement();
420 mode = FRAMESET_OK;
421 i--;
422 continue;
424 case FRAMESET_OK: {
425 framesetOk = false;
426 mode = IN_BODY;
427 i--;
428 continue;
430 case IN_TEMPLATE:
431 case IN_BODY:
432 case IN_CELL:
433 case IN_CAPTION: {
434 if (start < i) {
435 accumulateCharacters(buf, start, i - start);
436 start = i;
438 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
439 flushCharacters();
440 reconstructTheActiveFormattingElements();
442 NS_HTML5_BREAK(charactersloop);
444 case IN_TABLE:
445 case IN_TABLE_BODY:
446 case IN_ROW: {
447 accumulateCharactersForced(buf, i, 1);
448 start = i + 1;
449 continue;
451 case IN_COLUMN_GROUP: {
452 if (start < i) {
453 accumulateCharacters(buf, start, i - start);
454 start = i;
456 if (!currentPtr || stack[currentPtr]->getGroup() ==
457 nsHtml5TreeBuilder::TEMPLATE) {
458 errNonSpaceInColgroupInFragment();
459 start = i + 1;
460 continue;
462 flushCharacters();
463 pop();
464 mode = IN_TABLE;
465 i--;
466 continue;
468 case IN_SELECT:
469 case IN_SELECT_IN_TABLE: {
470 NS_HTML5_BREAK(charactersloop);
472 case AFTER_BODY: {
473 errNonSpaceAfterBody();
475 mode = framesetOk ? FRAMESET_OK : IN_BODY;
476 i--;
477 continue;
479 case IN_FRAMESET: {
480 if (start < i) {
481 accumulateCharacters(buf, start, i - start);
483 errNonSpaceInFrameset();
484 start = i + 1;
485 continue;
487 case AFTER_FRAMESET: {
488 if (start < i) {
489 accumulateCharacters(buf, start, i - start);
491 errNonSpaceAfterFrameset();
492 start = i + 1;
493 continue;
495 case AFTER_AFTER_BODY: {
496 errNonSpaceInTrailer();
497 mode = framesetOk ? FRAMESET_OK : IN_BODY;
498 i--;
499 continue;
501 case AFTER_AFTER_FRAMESET: {
502 if (start < i) {
503 accumulateCharacters(buf, start, i - start);
505 errNonSpaceInTrailer();
506 start = i + 1;
507 continue;
513 charactersloop_end:;
514 if (start < end) {
515 accumulateCharacters(buf, start, end - start);
521 void nsHtml5TreeBuilder::zeroOriginatingReplacementCharacter() {
522 if (mode == TEXT) {
523 accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
524 return;
526 if (currentPtr >= 0) {
527 if (isSpecialParentInForeign(stack[currentPtr])) {
528 return;
530 accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
534 void nsHtml5TreeBuilder::zeroOrReplacementCharacter() {
535 zeroOriginatingReplacementCharacter();
538 void nsHtml5TreeBuilder::eof() {
539 flushCharacters();
540 for (;;) {
541 switch (mode) {
542 case INITIAL: {
543 documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
544 mode = BEFORE_HTML;
545 continue;
547 case BEFORE_HTML: {
548 appendHtmlElementToDocumentAndPush();
549 mode = BEFORE_HEAD;
550 continue;
552 case BEFORE_HEAD: {
553 appendToCurrentNodeAndPushHeadElement(
554 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
555 mode = IN_HEAD;
556 continue;
558 case IN_HEAD: {
559 while (currentPtr > 0) {
560 popOnEof();
562 mode = AFTER_HEAD;
563 continue;
565 case IN_HEAD_NOSCRIPT: {
566 while (currentPtr > 1) {
567 popOnEof();
569 mode = IN_HEAD;
570 continue;
572 case AFTER_HEAD: {
573 appendToCurrentNodeAndPushBodyElement();
574 mode = IN_BODY;
575 continue;
577 case IN_TABLE_BODY:
578 case IN_ROW:
579 case IN_TABLE:
580 case IN_SELECT_IN_TABLE:
581 case IN_SELECT:
582 case IN_COLUMN_GROUP:
583 case FRAMESET_OK:
584 case IN_CAPTION:
585 case IN_CELL:
586 case IN_BODY: {
587 if (isTemplateModeStackEmpty()) {
588 NS_HTML5_BREAK(eofloop);
590 [[fallthrough]];
592 case IN_TEMPLATE: {
593 int32_t eltPos = findLast(nsGkAtoms::_template);
594 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
595 MOZ_ASSERT(fragment);
596 NS_HTML5_BREAK(eofloop);
598 if (MOZ_UNLIKELY(mViewSource)) {
599 errListUnclosedStartTags(0);
601 while (currentPtr >= eltPos) {
602 pop();
604 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
605 popTemplateMode();
606 resetTheInsertionMode();
607 continue;
609 case TEXT: {
610 if (originalMode == AFTER_HEAD) {
611 popOnEof();
613 popOnEof();
614 mode = originalMode;
615 continue;
617 case IN_FRAMESET: {
618 NS_HTML5_BREAK(eofloop);
620 case AFTER_BODY:
621 case AFTER_FRAMESET:
622 case AFTER_AFTER_BODY:
623 case AFTER_AFTER_FRAMESET:
624 default: {
625 NS_HTML5_BREAK(eofloop);
629 eofloop_end:;
630 while (currentPtr > 0) {
631 popOnEof();
633 if (!fragment) {
634 popOnEof();
638 void nsHtml5TreeBuilder::endTokenization() {
639 formPointer = nullptr;
640 headPointer = nullptr;
641 contextName = nullptr;
642 contextNode = nullptr;
643 templateModeStack = nullptr;
644 if (stack) {
645 while (currentPtr > -1) {
646 stack[currentPtr]->release(this);
647 currentPtr--;
649 stack = nullptr;
651 if (listOfActiveFormattingElements) {
652 while (listPtr > -1) {
653 if (listOfActiveFormattingElements[listPtr]) {
654 listOfActiveFormattingElements[listPtr]->release(this);
656 listPtr--;
658 listOfActiveFormattingElements = nullptr;
660 if (stackNodes) {
661 for (int32_t i = 0; i < numStackNodes; i++) {
662 MOZ_ASSERT(stackNodes[i]->isUnused());
663 delete stackNodes[i];
665 numStackNodes = 0;
666 stackNodesIdx = 0;
667 stackNodes = nullptr;
669 if (!keepBuffer) {
670 charBuffer = nullptr;
672 end();
675 void nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName,
676 nsHtml5HtmlAttributes* attributes,
677 bool selfClosing) {
678 flushCharacters();
679 int32_t eltPos;
680 needToDropLF = false;
681 starttagloop:
682 for (;;) {
683 int32_t group = elementName->getGroup();
684 nsAtom* name = elementName->getName();
685 if (isInForeign()) {
686 nsHtml5StackNode* currentNode = stack[currentPtr];
687 int32_t currNs = currentNode->ns;
688 if (!(currentNode->isHtmlIntegrationPoint() ||
689 (currNs == kNameSpaceID_MathML &&
690 ((currentNode->getGroup() == MI_MO_MN_MS_MTEXT &&
691 group != MGLYPH_OR_MALIGNMARK) ||
692 (currentNode->getGroup() == ANNOTATION_XML && group == SVG))))) {
693 switch (group) {
694 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
695 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
696 case BODY:
697 case BR:
698 case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR:
699 case DD_OR_DT:
700 case UL_OR_OL_OR_DL:
701 case EMBED:
702 case IMG:
703 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
704 case HEAD:
705 case HR:
706 case LI:
707 case META:
708 case NOBR:
709 case P:
710 case PRE_OR_LISTING:
711 case TABLE:
712 case FONT: {
713 if (!(group == FONT &&
714 !(attributes->contains(nsHtml5AttributeName::ATTR_COLOR) ||
715 attributes->contains(nsHtml5AttributeName::ATTR_FACE) ||
716 attributes->contains(nsHtml5AttributeName::ATTR_SIZE)))) {
717 errHtmlStartTagInForeignContext(name);
718 if (!fragment) {
719 while (!isSpecialParentInForeign(stack[currentPtr])) {
720 popForeign(-1, -1);
722 NS_HTML5_CONTINUE(starttagloop);
725 [[fallthrough]];
727 default: {
728 if (kNameSpaceID_SVG == currNs) {
729 attributes->adjustForSvg();
730 if (selfClosing) {
731 appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
732 selfClosing = false;
733 } else {
734 appendToCurrentNodeAndPushElementMayFosterSVG(elementName,
735 attributes);
737 attributes = nullptr;
738 NS_HTML5_BREAK(starttagloop);
739 } else {
740 attributes->adjustForMath();
741 if (selfClosing) {
742 appendVoidElementToCurrentMayFosterMathML(elementName,
743 attributes);
744 selfClosing = false;
745 } else {
746 appendToCurrentNodeAndPushElementMayFosterMathML(elementName,
747 attributes);
749 attributes = nullptr;
750 NS_HTML5_BREAK(starttagloop);
756 switch (mode) {
757 case IN_TEMPLATE: {
758 switch (group) {
759 case COL: {
760 popTemplateMode();
761 pushTemplateMode(IN_COLUMN_GROUP);
762 mode = IN_COLUMN_GROUP;
763 continue;
765 case CAPTION:
766 case COLGROUP:
767 case TBODY_OR_THEAD_OR_TFOOT: {
768 popTemplateMode();
769 pushTemplateMode(IN_TABLE);
770 mode = IN_TABLE;
771 continue;
773 case TR: {
774 popTemplateMode();
775 pushTemplateMode(IN_TABLE_BODY);
776 mode = IN_TABLE_BODY;
777 continue;
779 case TD_OR_TH: {
780 popTemplateMode();
781 pushTemplateMode(IN_ROW);
782 mode = IN_ROW;
783 continue;
785 case META: {
786 checkMetaCharset(attributes);
787 appendVoidElementToCurrentMayFoster(elementName, attributes);
788 selfClosing = false;
789 attributes = nullptr;
790 NS_HTML5_BREAK(starttagloop);
792 case TITLE: {
793 startTagTitleInHead(elementName, attributes);
794 attributes = nullptr;
795 NS_HTML5_BREAK(starttagloop);
797 case BASE:
798 case LINK_OR_BASEFONT_OR_BGSOUND: {
799 appendVoidElementToCurrentMayFoster(elementName, attributes);
800 selfClosing = false;
801 attributes = nullptr;
802 NS_HTML5_BREAK(starttagloop);
804 case SCRIPT: {
805 startTagScriptInHead(elementName, attributes);
806 attributes = nullptr;
807 NS_HTML5_BREAK(starttagloop);
809 case NOFRAMES:
810 case STYLE: {
811 startTagGenericRawText(elementName, attributes);
812 attributes = nullptr;
813 NS_HTML5_BREAK(starttagloop);
815 case TEMPLATE: {
816 startTagTemplateInHead(elementName, attributes);
817 attributes = nullptr;
818 NS_HTML5_BREAK(starttagloop);
820 default: {
821 popTemplateMode();
822 pushTemplateMode(IN_BODY);
823 mode = IN_BODY;
824 continue;
828 case IN_ROW: {
829 switch (group) {
830 case TD_OR_TH: {
831 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TR));
832 appendToCurrentNodeAndPushElement(elementName, attributes);
833 mode = IN_CELL;
834 insertMarker();
835 attributes = nullptr;
836 NS_HTML5_BREAK(starttagloop);
838 case CAPTION:
839 case COL:
840 case COLGROUP:
841 case TBODY_OR_THEAD_OR_TFOOT:
842 case TR: {
843 eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
844 if (!eltPos) {
845 MOZ_ASSERT(fragment || isTemplateContents());
846 errNoTableRowToClose();
847 NS_HTML5_BREAK(starttagloop);
849 clearStackBackTo(eltPos);
850 pop();
851 mode = IN_TABLE_BODY;
852 continue;
854 default:; // fall through
856 [[fallthrough]];
858 case IN_TABLE_BODY: {
859 switch (group) {
860 case TR: {
861 clearStackBackTo(
862 findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
863 appendToCurrentNodeAndPushElement(elementName, attributes);
864 mode = IN_ROW;
865 attributes = nullptr;
866 NS_HTML5_BREAK(starttagloop);
868 case TD_OR_TH: {
869 errStartTagInTableBody(name);
870 clearStackBackTo(
871 findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
872 appendToCurrentNodeAndPushElement(
873 nsHtml5ElementName::ELT_TR,
874 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
875 mode = IN_ROW;
876 continue;
878 case CAPTION:
879 case COL:
880 case COLGROUP:
881 case TBODY_OR_THEAD_OR_TFOOT: {
882 eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
883 if (!eltPos || stack[eltPos]->getGroup() == TEMPLATE) {
884 MOZ_ASSERT(fragment || isTemplateContents());
885 errStrayStartTag(name);
886 NS_HTML5_BREAK(starttagloop);
887 } else {
888 clearStackBackTo(eltPos);
889 pop();
890 mode = IN_TABLE;
891 continue;
894 default:; // fall through
896 [[fallthrough]];
898 case IN_TABLE: {
899 for (;;) {
900 switch (group) {
901 case CAPTION: {
902 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
903 insertMarker();
904 appendToCurrentNodeAndPushElement(elementName, attributes);
905 mode = IN_CAPTION;
906 attributes = nullptr;
907 NS_HTML5_BREAK(starttagloop);
909 case COLGROUP: {
910 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
911 appendToCurrentNodeAndPushElement(elementName, attributes);
912 mode = IN_COLUMN_GROUP;
913 attributes = nullptr;
914 NS_HTML5_BREAK(starttagloop);
916 case COL: {
917 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
918 appendToCurrentNodeAndPushElement(
919 nsHtml5ElementName::ELT_COLGROUP,
920 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
921 mode = IN_COLUMN_GROUP;
922 NS_HTML5_CONTINUE(starttagloop);
924 case TBODY_OR_THEAD_OR_TFOOT: {
925 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
926 appendToCurrentNodeAndPushElement(elementName, attributes);
927 mode = IN_TABLE_BODY;
928 attributes = nullptr;
929 NS_HTML5_BREAK(starttagloop);
931 case TR:
932 case TD_OR_TH: {
933 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
934 appendToCurrentNodeAndPushElement(
935 nsHtml5ElementName::ELT_TBODY,
936 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
937 mode = IN_TABLE_BODY;
938 NS_HTML5_CONTINUE(starttagloop);
940 case TEMPLATE: {
941 NS_HTML5_BREAK(intableloop);
943 case TABLE: {
944 errTableSeenWhileTableOpen();
945 eltPos = findLastInTableScope(name);
946 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
947 MOZ_ASSERT(fragment || isTemplateContents());
948 NS_HTML5_BREAK(starttagloop);
950 generateImpliedEndTags();
951 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsGkAtoms::table)) {
952 errNoCheckUnclosedElementsOnStack();
954 while (currentPtr >= eltPos) {
955 pop();
957 resetTheInsertionMode();
958 NS_HTML5_CONTINUE(starttagloop);
960 case SCRIPT: {
961 appendToCurrentNodeAndPushElement(elementName, attributes);
962 originalMode = mode;
963 mode = TEXT;
964 tokenizer->setStateAndEndTagExpectation(
965 nsHtml5Tokenizer::SCRIPT_DATA, elementName);
966 attributes = nullptr;
967 NS_HTML5_BREAK(starttagloop);
969 case STYLE: {
970 appendToCurrentNodeAndPushElement(elementName, attributes);
971 originalMode = mode;
972 mode = TEXT;
973 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
974 elementName);
975 attributes = nullptr;
976 NS_HTML5_BREAK(starttagloop);
978 case INPUT: {
979 errStartTagInTable(name);
980 if (!nsHtml5Portability::
981 lowerCaseLiteralEqualsIgnoreAsciiCaseString(
982 "hidden", attributes->getValue(
983 nsHtml5AttributeName::ATTR_TYPE))) {
984 NS_HTML5_BREAK(intableloop);
986 appendVoidInputToCurrent(attributes, formPointer);
987 selfClosing = false;
988 attributes = nullptr;
989 NS_HTML5_BREAK(starttagloop);
991 case FORM: {
992 if (!!formPointer || isTemplateContents()) {
993 errFormWhenFormOpen();
994 NS_HTML5_BREAK(starttagloop);
995 } else {
996 errStartTagInTable(name);
997 appendVoidFormToCurrent(attributes);
998 attributes = nullptr;
999 NS_HTML5_BREAK(starttagloop);
1002 default: {
1003 errStartTagInTable(name);
1004 NS_HTML5_BREAK(intableloop);
1008 intableloop_end:;
1009 [[fallthrough]];
1011 case IN_CAPTION: {
1012 switch (group) {
1013 case CAPTION:
1014 case COL:
1015 case COLGROUP:
1016 case TBODY_OR_THEAD_OR_TFOOT:
1017 case TR:
1018 case TD_OR_TH: {
1019 eltPos = findLastInTableScope(nsGkAtoms::caption);
1020 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
1021 MOZ_ASSERT(fragment || isTemplateContents());
1022 errStrayStartTag(name);
1023 NS_HTML5_BREAK(starttagloop);
1025 generateImpliedEndTags();
1026 if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
1027 errNoCheckUnclosedElementsOnStack();
1029 while (currentPtr >= eltPos) {
1030 pop();
1032 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
1033 mode = IN_TABLE;
1034 continue;
1036 default:; // fall through
1038 [[fallthrough]];
1040 case IN_CELL: {
1041 switch (group) {
1042 case CAPTION:
1043 case COL:
1044 case COLGROUP:
1045 case TBODY_OR_THEAD_OR_TFOOT:
1046 case TR:
1047 case TD_OR_TH: {
1048 eltPos = findLastInTableScopeTdTh();
1049 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
1050 errNoCellToClose();
1051 NS_HTML5_BREAK(starttagloop);
1052 } else {
1053 closeTheCell(eltPos);
1054 continue;
1057 default:; // fall through
1059 [[fallthrough]];
1061 case FRAMESET_OK: {
1062 switch (group) {
1063 case FRAMESET: {
1064 if (mode == FRAMESET_OK) {
1065 if (!currentPtr || stack[1]->getGroup() != BODY) {
1066 MOZ_ASSERT(fragment || isTemplateContents());
1067 errStrayStartTag(name);
1068 NS_HTML5_BREAK(starttagloop);
1069 } else {
1070 errFramesetStart();
1071 detachFromParent(stack[1]->node);
1072 while (currentPtr > 0) {
1073 pop();
1075 appendToCurrentNodeAndPushElement(elementName, attributes);
1076 mode = IN_FRAMESET;
1077 attributes = nullptr;
1078 NS_HTML5_BREAK(starttagloop);
1080 } else {
1081 errStrayStartTag(name);
1082 NS_HTML5_BREAK(starttagloop);
1085 case PRE_OR_LISTING:
1086 case LI:
1087 case DD_OR_DT:
1088 case BUTTON:
1089 case MARQUEE_OR_APPLET:
1090 case OBJECT:
1091 case TABLE:
1092 case AREA_OR_WBR:
1093 case KEYGEN:
1094 case BR:
1095 case EMBED:
1096 case IMG:
1097 case INPUT:
1098 case HR:
1099 case TEXTAREA:
1100 case XMP:
1101 case IFRAME:
1102 case SELECT: {
1103 if (mode == FRAMESET_OK &&
1104 !(group == INPUT &&
1105 nsHtml5Portability::
1106 lowerCaseLiteralEqualsIgnoreAsciiCaseString(
1107 "hidden", attributes->getValue(
1108 nsHtml5AttributeName::ATTR_TYPE)))) {
1109 framesetOk = false;
1110 mode = IN_BODY;
1112 [[fallthrough]];
1114 default:; // fall through
1116 [[fallthrough]];
1118 case IN_BODY: {
1119 for (;;) {
1120 switch (group) {
1121 case HTML: {
1122 errStrayStartTag(name);
1123 if (!fragment && !isTemplateContents()) {
1124 addAttributesToHtml(attributes);
1125 attributes = nullptr;
1127 NS_HTML5_BREAK(starttagloop);
1129 case BASE:
1130 case LINK_OR_BASEFONT_OR_BGSOUND:
1131 case META:
1132 case STYLE:
1133 case SCRIPT:
1134 case TITLE:
1135 case TEMPLATE: {
1136 NS_HTML5_BREAK(inbodyloop);
1138 case BODY: {
1139 if (!currentPtr || stack[1]->getGroup() != BODY ||
1140 isTemplateContents()) {
1141 MOZ_ASSERT(fragment || isTemplateContents());
1142 errStrayStartTag(name);
1143 NS_HTML5_BREAK(starttagloop);
1145 errFooSeenWhenFooOpen(name);
1146 framesetOk = false;
1147 if (mode == FRAMESET_OK) {
1148 mode = IN_BODY;
1150 if (addAttributesToBody(attributes)) {
1151 attributes = nullptr;
1153 NS_HTML5_BREAK(starttagloop);
1155 case P:
1156 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
1157 case UL_OR_OL_OR_DL:
1158 case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SEARCH_OR_SECTION_OR_SUMMARY: {
1159 implicitlyCloseP();
1160 appendToCurrentNodeAndPushElementMayFoster(elementName,
1161 attributes);
1162 attributes = nullptr;
1163 NS_HTML5_BREAK(starttagloop);
1165 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: {
1166 implicitlyCloseP();
1167 if (stack[currentPtr]->getGroup() ==
1168 H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
1169 errHeadingWhenHeadingOpen();
1170 pop();
1172 appendToCurrentNodeAndPushElementMayFoster(elementName,
1173 attributes);
1174 attributes = nullptr;
1175 NS_HTML5_BREAK(starttagloop);
1177 case FIELDSET: {
1178 implicitlyCloseP();
1179 appendToCurrentNodeAndPushElementMayFoster(
1180 elementName, attributes, formPointer);
1181 attributes = nullptr;
1182 NS_HTML5_BREAK(starttagloop);
1184 case PRE_OR_LISTING: {
1185 implicitlyCloseP();
1186 appendToCurrentNodeAndPushElementMayFoster(elementName,
1187 attributes);
1188 needToDropLF = true;
1189 attributes = nullptr;
1190 NS_HTML5_BREAK(starttagloop);
1192 case FORM: {
1193 if (!!formPointer && !isTemplateContents()) {
1194 errFormWhenFormOpen();
1195 NS_HTML5_BREAK(starttagloop);
1196 } else {
1197 implicitlyCloseP();
1198 appendToCurrentNodeAndPushFormElementMayFoster(attributes);
1199 attributes = nullptr;
1200 NS_HTML5_BREAK(starttagloop);
1203 case LI:
1204 case DD_OR_DT: {
1205 eltPos = currentPtr;
1206 for (;;) {
1207 nsHtml5StackNode* node = stack[eltPos];
1208 if (node->getGroup() == group) {
1209 generateImpliedEndTagsExceptFor(node->name);
1210 if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
1211 errUnclosedElementsImplied(eltPos, name);
1213 while (currentPtr >= eltPos) {
1214 pop();
1216 break;
1217 } else if (!eltPos || (node->isSpecial() &&
1218 (node->ns != kNameSpaceID_XHTML ||
1219 (node->name != nsGkAtoms::p &&
1220 node->name != nsGkAtoms::address &&
1221 node->name != nsGkAtoms::div)))) {
1222 break;
1224 eltPos--;
1226 implicitlyCloseP();
1227 appendToCurrentNodeAndPushElementMayFoster(elementName,
1228 attributes);
1229 attributes = nullptr;
1230 NS_HTML5_BREAK(starttagloop);
1232 case PLAINTEXT: {
1233 implicitlyCloseP();
1234 appendToCurrentNodeAndPushElementMayFoster(elementName,
1235 attributes);
1236 tokenizer->setStateAndEndTagExpectation(
1237 nsHtml5Tokenizer::PLAINTEXT, elementName);
1238 attributes = nullptr;
1239 NS_HTML5_BREAK(starttagloop);
1241 case A: {
1242 int32_t activeAPos =
1243 findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
1244 nsGkAtoms::a);
1245 if (activeAPos != -1) {
1246 errFooSeenWhenFooOpen(name);
1247 nsHtml5StackNode* activeA =
1248 listOfActiveFormattingElements[activeAPos];
1249 activeA->retain();
1250 adoptionAgencyEndTag(nsGkAtoms::a);
1251 removeFromStack(activeA);
1252 activeAPos = findInListOfActiveFormattingElements(activeA);
1253 if (activeAPos != -1) {
1254 removeFromListOfActiveFormattingElements(activeAPos);
1256 activeA->release(this);
1258 reconstructTheActiveFormattingElements();
1259 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
1260 attributes);
1261 attributes = nullptr;
1262 NS_HTML5_BREAK(starttagloop);
1264 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
1265 case FONT: {
1266 reconstructTheActiveFormattingElements();
1267 maybeForgetEarlierDuplicateFormattingElement(
1268 elementName->getName(), attributes);
1269 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
1270 attributes);
1271 attributes = nullptr;
1272 NS_HTML5_BREAK(starttagloop);
1274 case NOBR: {
1275 reconstructTheActiveFormattingElements();
1276 if (nsHtml5TreeBuilder::NOT_FOUND_ON_STACK !=
1277 findLastInScope(nsGkAtoms::nobr)) {
1278 errFooSeenWhenFooOpen(name);
1279 adoptionAgencyEndTag(nsGkAtoms::nobr);
1280 reconstructTheActiveFormattingElements();
1282 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
1283 attributes);
1284 attributes = nullptr;
1285 NS_HTML5_BREAK(starttagloop);
1287 case BUTTON: {
1288 eltPos = findLastInScope(name);
1289 if (eltPos != nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
1290 errFooSeenWhenFooOpen(name);
1291 generateImpliedEndTags();
1292 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
1293 errUnclosedElementsImplied(eltPos, name);
1295 while (currentPtr >= eltPos) {
1296 pop();
1298 NS_HTML5_CONTINUE(starttagloop);
1299 } else {
1300 reconstructTheActiveFormattingElements();
1301 appendToCurrentNodeAndPushElementMayFoster(
1302 elementName, attributes, formPointer);
1303 attributes = nullptr;
1304 NS_HTML5_BREAK(starttagloop);
1307 case OBJECT: {
1308 reconstructTheActiveFormattingElements();
1309 appendToCurrentNodeAndPushElementMayFoster(
1310 elementName, attributes, formPointer);
1311 insertMarker();
1312 attributes = nullptr;
1313 NS_HTML5_BREAK(starttagloop);
1315 case MARQUEE_OR_APPLET: {
1316 reconstructTheActiveFormattingElements();
1317 appendToCurrentNodeAndPushElementMayFoster(elementName,
1318 attributes);
1319 insertMarker();
1320 attributes = nullptr;
1321 NS_HTML5_BREAK(starttagloop);
1323 case TABLE: {
1324 if (!quirks) {
1325 implicitlyCloseP();
1327 appendToCurrentNodeAndPushElementMayFoster(elementName,
1328 attributes);
1329 mode = IN_TABLE;
1330 attributes = nullptr;
1331 NS_HTML5_BREAK(starttagloop);
1333 case BR:
1334 case EMBED:
1335 case AREA_OR_WBR:
1336 case KEYGEN: {
1337 reconstructTheActiveFormattingElements();
1338 [[fallthrough]];
1340 case PARAM_OR_SOURCE_OR_TRACK: {
1341 appendVoidElementToCurrentMayFoster(elementName, attributes);
1342 selfClosing = false;
1343 attributes = nullptr;
1344 NS_HTML5_BREAK(starttagloop);
1346 case HR: {
1347 implicitlyCloseP();
1348 appendVoidElementToCurrentMayFoster(elementName, attributes);
1349 selfClosing = false;
1350 attributes = nullptr;
1351 NS_HTML5_BREAK(starttagloop);
1353 case IMAGE: {
1354 errImage();
1355 elementName = nsHtml5ElementName::ELT_IMG;
1356 NS_HTML5_CONTINUE(starttagloop);
1358 case IMG:
1359 case INPUT: {
1360 reconstructTheActiveFormattingElements();
1361 appendVoidElementToCurrentMayFoster(elementName, attributes,
1362 formPointer);
1363 selfClosing = false;
1364 attributes = nullptr;
1365 NS_HTML5_BREAK(starttagloop);
1367 case TEXTAREA: {
1368 appendToCurrentNodeAndPushElementMayFoster(
1369 elementName, attributes, formPointer);
1370 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
1371 elementName);
1372 originalMode = mode;
1373 mode = TEXT;
1374 needToDropLF = true;
1375 attributes = nullptr;
1376 NS_HTML5_BREAK(starttagloop);
1378 case XMP: {
1379 implicitlyCloseP();
1380 reconstructTheActiveFormattingElements();
1381 appendToCurrentNodeAndPushElementMayFoster(elementName,
1382 attributes);
1383 originalMode = mode;
1384 mode = TEXT;
1385 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
1386 elementName);
1387 attributes = nullptr;
1388 NS_HTML5_BREAK(starttagloop);
1390 case NOSCRIPT: {
1391 if (!scriptingEnabled) {
1392 reconstructTheActiveFormattingElements();
1393 appendToCurrentNodeAndPushElementMayFoster(elementName,
1394 attributes);
1395 attributes = nullptr;
1396 NS_HTML5_BREAK(starttagloop);
1398 [[fallthrough]];
1400 case NOFRAMES:
1401 case IFRAME:
1402 case NOEMBED: {
1403 startTagGenericRawText(elementName, attributes);
1404 attributes = nullptr;
1405 NS_HTML5_BREAK(starttagloop);
1407 case SELECT: {
1408 reconstructTheActiveFormattingElements();
1409 appendToCurrentNodeAndPushElementMayFoster(
1410 elementName, attributes, formPointer);
1411 switch (mode) {
1412 case IN_TABLE:
1413 case IN_CAPTION:
1414 case IN_COLUMN_GROUP:
1415 case IN_TABLE_BODY:
1416 case IN_ROW:
1417 case IN_CELL: {
1418 mode = IN_SELECT_IN_TABLE;
1419 break;
1421 default: {
1422 mode = IN_SELECT;
1423 break;
1426 attributes = nullptr;
1427 NS_HTML5_BREAK(starttagloop);
1429 case OPTGROUP:
1430 case OPTION: {
1431 if (isCurrent(nsGkAtoms::option)) {
1432 pop();
1434 reconstructTheActiveFormattingElements();
1435 appendToCurrentNodeAndPushElementMayFoster(elementName,
1436 attributes);
1437 attributes = nullptr;
1438 NS_HTML5_BREAK(starttagloop);
1440 case RB_OR_RTC: {
1441 eltPos = findLastInScope(nsGkAtoms::ruby);
1442 if (eltPos != NOT_FOUND_ON_STACK) {
1443 generateImpliedEndTags();
1445 if (eltPos != currentPtr) {
1446 if (eltPos == NOT_FOUND_ON_STACK) {
1447 errStartTagSeenWithoutRuby(name);
1448 } else {
1449 errUnclosedChildrenInRuby();
1452 appendToCurrentNodeAndPushElementMayFoster(elementName,
1453 attributes);
1454 attributes = nullptr;
1455 NS_HTML5_BREAK(starttagloop);
1457 case RT_OR_RP: {
1458 eltPos = findLastInScope(nsGkAtoms::ruby);
1459 if (eltPos != NOT_FOUND_ON_STACK) {
1460 generateImpliedEndTagsExceptFor(nsGkAtoms::rtc);
1462 if (eltPos != currentPtr) {
1463 if (!isCurrent(nsGkAtoms::rtc)) {
1464 if (eltPos == NOT_FOUND_ON_STACK) {
1465 errStartTagSeenWithoutRuby(name);
1466 } else {
1467 errUnclosedChildrenInRuby();
1471 appendToCurrentNodeAndPushElementMayFoster(elementName,
1472 attributes);
1473 attributes = nullptr;
1474 NS_HTML5_BREAK(starttagloop);
1476 case MATH: {
1477 reconstructTheActiveFormattingElements();
1478 attributes->adjustForMath();
1479 if (selfClosing) {
1480 appendVoidElementToCurrentMayFosterMathML(elementName,
1481 attributes);
1482 selfClosing = false;
1483 } else {
1484 appendToCurrentNodeAndPushElementMayFosterMathML(elementName,
1485 attributes);
1487 attributes = nullptr;
1488 NS_HTML5_BREAK(starttagloop);
1490 case SVG: {
1491 reconstructTheActiveFormattingElements();
1492 attributes->adjustForSvg();
1493 if (selfClosing) {
1494 appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
1495 selfClosing = false;
1496 } else {
1497 appendToCurrentNodeAndPushElementMayFosterSVG(elementName,
1498 attributes);
1500 attributes = nullptr;
1501 NS_HTML5_BREAK(starttagloop);
1503 case CAPTION:
1504 case COL:
1505 case COLGROUP:
1506 case TBODY_OR_THEAD_OR_TFOOT:
1507 case TR:
1508 case TD_OR_TH:
1509 case FRAME:
1510 case FRAMESET:
1511 case HEAD: {
1512 errStrayStartTag(name);
1513 NS_HTML5_BREAK(starttagloop);
1515 case OUTPUT: {
1516 reconstructTheActiveFormattingElements();
1517 appendToCurrentNodeAndPushElementMayFoster(
1518 elementName, attributes, formPointer);
1519 attributes = nullptr;
1520 NS_HTML5_BREAK(starttagloop);
1522 default: {
1523 reconstructTheActiveFormattingElements();
1524 appendToCurrentNodeAndPushElementMayFoster(elementName,
1525 attributes);
1526 attributes = nullptr;
1527 NS_HTML5_BREAK(starttagloop);
1531 inbodyloop_end:;
1532 [[fallthrough]];
1534 case IN_HEAD: {
1535 for (;;) {
1536 switch (group) {
1537 case HTML: {
1538 errStrayStartTag(name);
1539 if (!fragment && !isTemplateContents()) {
1540 addAttributesToHtml(attributes);
1541 attributes = nullptr;
1543 NS_HTML5_BREAK(starttagloop);
1545 case BASE:
1546 case LINK_OR_BASEFONT_OR_BGSOUND: {
1547 appendVoidElementToCurrentMayFoster(elementName, attributes);
1548 selfClosing = false;
1549 attributes = nullptr;
1550 NS_HTML5_BREAK(starttagloop);
1552 case META: {
1553 NS_HTML5_BREAK(inheadloop);
1555 case TITLE: {
1556 startTagTitleInHead(elementName, attributes);
1557 attributes = nullptr;
1558 NS_HTML5_BREAK(starttagloop);
1560 case NOSCRIPT: {
1561 if (scriptingEnabled) {
1562 appendToCurrentNodeAndPushElement(elementName, attributes);
1563 originalMode = mode;
1564 mode = TEXT;
1565 tokenizer->setStateAndEndTagExpectation(
1566 nsHtml5Tokenizer::RAWTEXT, elementName);
1567 } else {
1568 appendToCurrentNodeAndPushElementMayFoster(elementName,
1569 attributes);
1570 mode = IN_HEAD_NOSCRIPT;
1572 attributes = nullptr;
1573 NS_HTML5_BREAK(starttagloop);
1575 case SCRIPT: {
1576 startTagScriptInHead(elementName, attributes);
1577 attributes = nullptr;
1578 NS_HTML5_BREAK(starttagloop);
1580 case STYLE:
1581 case NOFRAMES: {
1582 startTagGenericRawText(elementName, attributes);
1583 attributes = nullptr;
1584 NS_HTML5_BREAK(starttagloop);
1586 case HEAD: {
1587 errFooSeenWhenFooOpen(name);
1588 NS_HTML5_BREAK(starttagloop);
1590 case TEMPLATE: {
1591 startTagTemplateInHead(elementName, attributes);
1592 attributes = nullptr;
1593 NS_HTML5_BREAK(starttagloop);
1595 default: {
1596 pop();
1597 mode = AFTER_HEAD;
1598 NS_HTML5_CONTINUE(starttagloop);
1602 inheadloop_end:;
1603 [[fallthrough]];
1605 case IN_HEAD_NOSCRIPT: {
1606 switch (group) {
1607 case HTML: {
1608 errStrayStartTag(name);
1609 if (!fragment && !isTemplateContents()) {
1610 addAttributesToHtml(attributes);
1611 attributes = nullptr;
1613 NS_HTML5_BREAK(starttagloop);
1615 case LINK_OR_BASEFONT_OR_BGSOUND: {
1616 appendVoidElementToCurrentMayFoster(elementName, attributes);
1617 selfClosing = false;
1618 attributes = nullptr;
1619 NS_HTML5_BREAK(starttagloop);
1621 case META: {
1622 checkMetaCharset(attributes);
1623 appendVoidElementToCurrentMayFoster(elementName, attributes);
1624 selfClosing = false;
1625 attributes = nullptr;
1626 NS_HTML5_BREAK(starttagloop);
1628 case STYLE:
1629 case NOFRAMES: {
1630 appendToCurrentNodeAndPushElement(elementName, attributes);
1631 originalMode = mode;
1632 mode = TEXT;
1633 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
1634 elementName);
1635 attributes = nullptr;
1636 NS_HTML5_BREAK(starttagloop);
1638 case HEAD: {
1639 errFooSeenWhenFooOpen(name);
1640 NS_HTML5_BREAK(starttagloop);
1642 case NOSCRIPT: {
1643 errFooSeenWhenFooOpen(name);
1644 NS_HTML5_BREAK(starttagloop);
1646 default: {
1647 errBadStartTagInNoscriptInHead(name);
1648 pop();
1649 mode = IN_HEAD;
1650 continue;
1654 case IN_COLUMN_GROUP: {
1655 switch (group) {
1656 case HTML: {
1657 errStrayStartTag(name);
1658 if (!fragment && !isTemplateContents()) {
1659 addAttributesToHtml(attributes);
1660 attributes = nullptr;
1662 NS_HTML5_BREAK(starttagloop);
1664 case COL: {
1665 appendVoidElementToCurrentMayFoster(elementName, attributes);
1666 selfClosing = false;
1667 attributes = nullptr;
1668 NS_HTML5_BREAK(starttagloop);
1670 case TEMPLATE: {
1671 startTagTemplateInHead(elementName, attributes);
1672 attributes = nullptr;
1673 NS_HTML5_BREAK(starttagloop);
1675 default: {
1676 if (!currentPtr || stack[currentPtr]->getGroup() == TEMPLATE) {
1677 MOZ_ASSERT(fragment || isTemplateContents());
1678 errGarbageInColgroup();
1679 NS_HTML5_BREAK(starttagloop);
1681 pop();
1682 mode = IN_TABLE;
1683 continue;
1687 case IN_SELECT_IN_TABLE: {
1688 switch (group) {
1689 case CAPTION:
1690 case TBODY_OR_THEAD_OR_TFOOT:
1691 case TR:
1692 case TD_OR_TH:
1693 case TABLE: {
1694 errStartTagWithSelectOpen(name);
1695 eltPos = findLastInTableScope(nsGkAtoms::select);
1696 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
1697 MOZ_ASSERT(fragment);
1698 NS_HTML5_BREAK(starttagloop);
1700 while (currentPtr >= eltPos) {
1701 pop();
1703 resetTheInsertionMode();
1704 continue;
1706 default:; // fall through
1708 [[fallthrough]];
1710 case IN_SELECT: {
1711 switch (group) {
1712 case HTML: {
1713 errStrayStartTag(name);
1714 if (!fragment) {
1715 addAttributesToHtml(attributes);
1716 attributes = nullptr;
1718 NS_HTML5_BREAK(starttagloop);
1720 case OPTION: {
1721 if (isCurrent(nsGkAtoms::option)) {
1722 pop();
1724 appendToCurrentNodeAndPushElement(elementName, attributes);
1725 attributes = nullptr;
1726 NS_HTML5_BREAK(starttagloop);
1728 case OPTGROUP: {
1729 if (isCurrent(nsGkAtoms::option)) {
1730 pop();
1732 if (isCurrent(nsGkAtoms::optgroup)) {
1733 pop();
1735 appendToCurrentNodeAndPushElement(elementName, attributes);
1736 attributes = nullptr;
1737 NS_HTML5_BREAK(starttagloop);
1739 case SELECT: {
1740 errStartSelectWhereEndSelectExpected();
1741 eltPos = findLastInTableScope(name);
1742 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
1743 MOZ_ASSERT(fragment);
1744 errNoSelectInTableScope();
1745 NS_HTML5_BREAK(starttagloop);
1746 } else {
1747 while (currentPtr >= eltPos) {
1748 pop();
1750 resetTheInsertionMode();
1751 NS_HTML5_BREAK(starttagloop);
1754 case INPUT:
1755 case TEXTAREA: {
1756 errStartTagWithSelectOpen(name);
1757 eltPos = findLastInTableScope(nsGkAtoms::select);
1758 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
1759 MOZ_ASSERT(fragment);
1760 NS_HTML5_BREAK(starttagloop);
1762 while (currentPtr >= eltPos) {
1763 pop();
1765 resetTheInsertionMode();
1766 continue;
1768 case SCRIPT: {
1769 startTagScriptInHead(elementName, attributes);
1770 attributes = nullptr;
1771 NS_HTML5_BREAK(starttagloop);
1773 case TEMPLATE: {
1774 startTagTemplateInHead(elementName, attributes);
1775 attributes = nullptr;
1776 NS_HTML5_BREAK(starttagloop);
1778 case HR: {
1779 if (isCurrent(nsGkAtoms::option)) {
1780 pop();
1782 if (isCurrent(nsGkAtoms::optgroup)) {
1783 pop();
1785 appendVoidElementToCurrent(elementName, attributes);
1786 selfClosing = false;
1787 attributes = nullptr;
1788 NS_HTML5_BREAK(starttagloop);
1790 default: {
1791 errStrayStartTag(name);
1792 NS_HTML5_BREAK(starttagloop);
1796 case AFTER_BODY: {
1797 switch (group) {
1798 case HTML: {
1799 errStrayStartTag(name);
1800 if (!fragment && !isTemplateContents()) {
1801 addAttributesToHtml(attributes);
1802 attributes = nullptr;
1804 NS_HTML5_BREAK(starttagloop);
1806 default: {
1807 errStrayStartTag(name);
1808 mode = framesetOk ? FRAMESET_OK : IN_BODY;
1809 continue;
1813 case IN_FRAMESET: {
1814 switch (group) {
1815 case FRAMESET: {
1816 appendToCurrentNodeAndPushElement(elementName, attributes);
1817 attributes = nullptr;
1818 NS_HTML5_BREAK(starttagloop);
1820 case FRAME: {
1821 appendVoidElementToCurrentMayFoster(elementName, attributes);
1822 selfClosing = false;
1823 attributes = nullptr;
1824 NS_HTML5_BREAK(starttagloop);
1826 default:; // fall through
1828 [[fallthrough]];
1830 case AFTER_FRAMESET: {
1831 switch (group) {
1832 case HTML: {
1833 errStrayStartTag(name);
1834 if (!fragment && !isTemplateContents()) {
1835 addAttributesToHtml(attributes);
1836 attributes = nullptr;
1838 NS_HTML5_BREAK(starttagloop);
1840 case NOFRAMES: {
1841 appendToCurrentNodeAndPushElement(elementName, attributes);
1842 originalMode = mode;
1843 mode = TEXT;
1844 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
1845 elementName);
1846 attributes = nullptr;
1847 NS_HTML5_BREAK(starttagloop);
1849 default: {
1850 errStrayStartTag(name);
1851 NS_HTML5_BREAK(starttagloop);
1855 case INITIAL: {
1856 errStartTagWithoutDoctype();
1857 documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
1858 mode = BEFORE_HTML;
1859 continue;
1861 case BEFORE_HTML: {
1862 switch (group) {
1863 case HTML: {
1864 if (attributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
1865 appendHtmlElementToDocumentAndPush();
1866 } else {
1867 appendHtmlElementToDocumentAndPush(attributes);
1869 mode = BEFORE_HEAD;
1870 attributes = nullptr;
1871 NS_HTML5_BREAK(starttagloop);
1873 default: {
1874 appendHtmlElementToDocumentAndPush();
1875 mode = BEFORE_HEAD;
1876 continue;
1880 case BEFORE_HEAD: {
1881 switch (group) {
1882 case HTML: {
1883 errStrayStartTag(name);
1884 if (!fragment && !isTemplateContents()) {
1885 addAttributesToHtml(attributes);
1886 attributes = nullptr;
1888 NS_HTML5_BREAK(starttagloop);
1890 case HEAD: {
1891 appendToCurrentNodeAndPushHeadElement(attributes);
1892 mode = IN_HEAD;
1893 attributes = nullptr;
1894 NS_HTML5_BREAK(starttagloop);
1896 default: {
1897 appendToCurrentNodeAndPushHeadElement(
1898 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
1899 mode = IN_HEAD;
1900 continue;
1904 case AFTER_HEAD: {
1905 switch (group) {
1906 case HTML: {
1907 errStrayStartTag(name);
1908 if (!fragment && !isTemplateContents()) {
1909 addAttributesToHtml(attributes);
1910 attributes = nullptr;
1912 NS_HTML5_BREAK(starttagloop);
1914 case BODY: {
1915 if (!attributes->getLength()) {
1916 appendToCurrentNodeAndPushBodyElement();
1917 } else {
1918 appendToCurrentNodeAndPushBodyElement(attributes);
1920 framesetOk = false;
1921 mode = IN_BODY;
1922 attributes = nullptr;
1923 NS_HTML5_BREAK(starttagloop);
1925 case FRAMESET: {
1926 appendToCurrentNodeAndPushElement(elementName, attributes);
1927 mode = IN_FRAMESET;
1928 attributes = nullptr;
1929 NS_HTML5_BREAK(starttagloop);
1931 case TEMPLATE: {
1932 errFooBetweenHeadAndBody(name);
1933 pushHeadPointerOntoStack();
1934 nsHtml5StackNode* headOnStack = stack[currentPtr];
1935 startTagTemplateInHead(elementName, attributes);
1936 removeFromStack(headOnStack);
1937 attributes = nullptr;
1938 NS_HTML5_BREAK(starttagloop);
1940 case BASE:
1941 case LINK_OR_BASEFONT_OR_BGSOUND: {
1942 errFooBetweenHeadAndBody(name);
1943 pushHeadPointerOntoStack();
1944 appendVoidElementToCurrentMayFoster(elementName, attributes);
1945 selfClosing = false;
1946 pop();
1947 attributes = nullptr;
1948 NS_HTML5_BREAK(starttagloop);
1950 case META: {
1951 errFooBetweenHeadAndBody(name);
1952 checkMetaCharset(attributes);
1953 pushHeadPointerOntoStack();
1954 appendVoidElementToCurrentMayFoster(elementName, attributes);
1955 selfClosing = false;
1956 pop();
1957 attributes = nullptr;
1958 NS_HTML5_BREAK(starttagloop);
1960 case SCRIPT: {
1961 errFooBetweenHeadAndBody(name);
1962 pushHeadPointerOntoStack();
1963 appendToCurrentNodeAndPushElement(elementName, attributes);
1964 originalMode = mode;
1965 mode = TEXT;
1966 tokenizer->setStateAndEndTagExpectation(
1967 nsHtml5Tokenizer::SCRIPT_DATA, elementName);
1968 attributes = nullptr;
1969 NS_HTML5_BREAK(starttagloop);
1971 case STYLE:
1972 case NOFRAMES: {
1973 errFooBetweenHeadAndBody(name);
1974 pushHeadPointerOntoStack();
1975 appendToCurrentNodeAndPushElement(elementName, attributes);
1976 originalMode = mode;
1977 mode = TEXT;
1978 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
1979 elementName);
1980 attributes = nullptr;
1981 NS_HTML5_BREAK(starttagloop);
1983 case TITLE: {
1984 errFooBetweenHeadAndBody(name);
1985 pushHeadPointerOntoStack();
1986 appendToCurrentNodeAndPushElement(elementName, attributes);
1987 originalMode = mode;
1988 mode = TEXT;
1989 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
1990 elementName);
1991 attributes = nullptr;
1992 NS_HTML5_BREAK(starttagloop);
1994 case HEAD: {
1995 errStrayStartTag(name);
1996 NS_HTML5_BREAK(starttagloop);
1998 default: {
1999 appendToCurrentNodeAndPushBodyElement();
2000 mode = FRAMESET_OK;
2001 continue;
2005 case AFTER_AFTER_BODY: {
2006 switch (group) {
2007 case HTML: {
2008 errStrayStartTag(name);
2009 if (!fragment && !isTemplateContents()) {
2010 addAttributesToHtml(attributes);
2011 attributes = nullptr;
2013 NS_HTML5_BREAK(starttagloop);
2015 default: {
2016 errStrayStartTag(name);
2018 mode = framesetOk ? FRAMESET_OK : IN_BODY;
2019 continue;
2023 case AFTER_AFTER_FRAMESET: {
2024 switch (group) {
2025 case HTML: {
2026 errStrayStartTag(name);
2027 if (!fragment && !isTemplateContents()) {
2028 addAttributesToHtml(attributes);
2029 attributes = nullptr;
2031 NS_HTML5_BREAK(starttagloop);
2033 case NOFRAMES: {
2034 startTagGenericRawText(elementName, attributes);
2035 attributes = nullptr;
2036 NS_HTML5_BREAK(starttagloop);
2038 default: {
2039 errStrayStartTag(name);
2040 NS_HTML5_BREAK(starttagloop);
2044 case TEXT: {
2045 MOZ_ASSERT(false);
2046 NS_HTML5_BREAK(starttagloop);
2050 starttagloop_end:;
2051 if (selfClosing) {
2052 errSelfClosing();
2054 if (!mBuilder && attributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
2055 delete attributes;
2059 void nsHtml5TreeBuilder::startTagTitleInHead(
2060 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
2061 appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
2062 originalMode = mode;
2063 mode = TEXT;
2064 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
2065 elementName);
2068 void nsHtml5TreeBuilder::startTagGenericRawText(
2069 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
2070 appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
2071 originalMode = mode;
2072 mode = TEXT;
2073 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
2074 elementName);
2077 void nsHtml5TreeBuilder::startTagScriptInHead(
2078 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
2079 appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
2080 originalMode = mode;
2081 mode = TEXT;
2082 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::SCRIPT_DATA,
2083 elementName);
2086 void nsHtml5TreeBuilder::startTagTemplateInHead(
2087 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
2088 appendToCurrentNodeAndPushElement(elementName, attributes);
2089 insertMarker();
2090 framesetOk = false;
2091 originalMode = mode;
2092 mode = IN_TEMPLATE;
2093 pushTemplateMode(IN_TEMPLATE);
2096 bool nsHtml5TreeBuilder::isTemplateContents() {
2097 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK !=
2098 findLast(nsGkAtoms::_template);
2101 bool nsHtml5TreeBuilder::isTemplateModeStackEmpty() {
2102 return templateModePtr == -1;
2105 bool nsHtml5TreeBuilder::isSpecialParentInForeign(nsHtml5StackNode* stackNode) {
2106 int32_t ns = stackNode->ns;
2107 return (kNameSpaceID_XHTML == ns) || (stackNode->isHtmlIntegrationPoint()) ||
2108 ((kNameSpaceID_MathML == ns) &&
2109 (stackNode->getGroup() == MI_MO_MN_MS_MTEXT));
2112 nsIContentHandle* nsHtml5TreeBuilder::getDeclarativeShadowRoot(
2113 nsIContentHandle* currentNode, nsIContentHandle* templateNode,
2114 nsHtml5HtmlAttributes* attributes) {
2115 if (!isAllowDeclarativeShadowRoots()) {
2116 return nullptr;
2118 nsHtml5String shadowRootMode =
2119 attributes->getValue(nsHtml5AttributeName::ATTR_SHADOWROOTMODE);
2120 if (!shadowRootMode) {
2121 return nullptr;
2123 bool shadowRootIsClonable =
2124 attributes->contains(nsHtml5AttributeName::ATTR_SHADOWROOTCLONABLE);
2125 bool shadowRootIsSerializable =
2126 attributes->contains(nsHtml5AttributeName::ATTR_SHADOWROOTSERIALIZABLE);
2127 bool shadowRootDelegatesFocus =
2128 attributes->contains(nsHtml5AttributeName::ATTR_SHADOWROOTDELEGATESFOCUS);
2129 return getShadowRootFromHost(currentNode, templateNode, shadowRootMode,
2130 shadowRootIsClonable, shadowRootIsSerializable,
2131 shadowRootDelegatesFocus);
2134 nsHtml5String nsHtml5TreeBuilder::extractCharsetFromContent(
2135 nsHtml5String attributeValue, nsHtml5TreeBuilder* tb) {
2136 int32_t charsetState = CHARSET_INITIAL;
2137 int32_t start = -1;
2138 int32_t end = -1;
2139 autoJArray<char16_t, int32_t> buffer =
2140 nsHtml5Portability::newCharArrayFromString(attributeValue);
2141 for (int32_t i = 0; i < buffer.length; i++) {
2142 char16_t c = buffer[i];
2143 switch (charsetState) {
2144 case CHARSET_INITIAL: {
2145 switch (c) {
2146 case 'c':
2147 case 'C': {
2148 charsetState = CHARSET_C;
2149 continue;
2151 default: {
2152 continue;
2156 case CHARSET_C: {
2157 switch (c) {
2158 case 'h':
2159 case 'H': {
2160 charsetState = CHARSET_H;
2161 continue;
2163 default: {
2164 charsetState = CHARSET_INITIAL;
2165 continue;
2169 case CHARSET_H: {
2170 switch (c) {
2171 case 'a':
2172 case 'A': {
2173 charsetState = CHARSET_A;
2174 continue;
2176 default: {
2177 charsetState = CHARSET_INITIAL;
2178 continue;
2182 case CHARSET_A: {
2183 switch (c) {
2184 case 'r':
2185 case 'R': {
2186 charsetState = CHARSET_R;
2187 continue;
2189 default: {
2190 charsetState = CHARSET_INITIAL;
2191 continue;
2195 case CHARSET_R: {
2196 switch (c) {
2197 case 's':
2198 case 'S': {
2199 charsetState = CHARSET_S;
2200 continue;
2202 default: {
2203 charsetState = CHARSET_INITIAL;
2204 continue;
2208 case CHARSET_S: {
2209 switch (c) {
2210 case 'e':
2211 case 'E': {
2212 charsetState = CHARSET_E;
2213 continue;
2215 default: {
2216 charsetState = CHARSET_INITIAL;
2217 continue;
2221 case CHARSET_E: {
2222 switch (c) {
2223 case 't':
2224 case 'T': {
2225 charsetState = CHARSET_T;
2226 continue;
2228 default: {
2229 charsetState = CHARSET_INITIAL;
2230 continue;
2234 case CHARSET_T: {
2235 switch (c) {
2236 case '\t':
2237 case '\n':
2238 case '\f':
2239 case '\r':
2240 case ' ': {
2241 continue;
2243 case '=': {
2244 charsetState = CHARSET_EQUALS;
2245 continue;
2247 default: {
2248 return nullptr;
2252 case CHARSET_EQUALS: {
2253 switch (c) {
2254 case '\t':
2255 case '\n':
2256 case '\f':
2257 case '\r':
2258 case ' ': {
2259 continue;
2261 case '\'': {
2262 start = i + 1;
2263 charsetState = CHARSET_SINGLE_QUOTED;
2264 continue;
2266 case '\"': {
2267 start = i + 1;
2268 charsetState = CHARSET_DOUBLE_QUOTED;
2269 continue;
2271 default: {
2272 start = i;
2273 charsetState = CHARSET_UNQUOTED;
2274 continue;
2278 case CHARSET_SINGLE_QUOTED: {
2279 switch (c) {
2280 case '\'': {
2281 end = i;
2282 NS_HTML5_BREAK(charsetloop);
2284 default: {
2285 continue;
2289 case CHARSET_DOUBLE_QUOTED: {
2290 switch (c) {
2291 case '\"': {
2292 end = i;
2293 NS_HTML5_BREAK(charsetloop);
2295 default: {
2296 continue;
2300 case CHARSET_UNQUOTED: {
2301 switch (c) {
2302 case '\t':
2303 case '\n':
2304 case '\f':
2305 case '\r':
2306 case ' ':
2307 case ';': {
2308 end = i;
2309 NS_HTML5_BREAK(charsetloop);
2311 default: {
2312 continue;
2318 charsetloop_end:;
2319 if (start != -1) {
2320 if (end == -1) {
2321 if (charsetState == CHARSET_UNQUOTED) {
2322 end = buffer.length;
2323 } else {
2324 return nullptr;
2327 return nsHtml5Portability::newStringFromBuffer(buffer, start, end - start,
2328 tb, false);
2330 return nullptr;
2333 void nsHtml5TreeBuilder::checkMetaCharset(nsHtml5HtmlAttributes* attributes) {
2334 nsHtml5String charset =
2335 attributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
2336 if (charset) {
2337 if (tokenizer->internalEncodingDeclaration(charset)) {
2338 requestSuspension();
2339 return;
2341 return;
2343 if (!nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
2344 "content-type",
2345 attributes->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV))) {
2346 return;
2348 nsHtml5String content =
2349 attributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);
2350 if (content) {
2351 nsHtml5String extract =
2352 nsHtml5TreeBuilder::extractCharsetFromContent(content, this);
2353 if (extract) {
2354 if (tokenizer->internalEncodingDeclaration(extract)) {
2355 requestSuspension();
2358 extract.Release();
2362 void nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName) {
2363 flushCharacters();
2364 needToDropLF = false;
2365 int32_t eltPos;
2366 int32_t group = elementName->getGroup();
2367 nsAtom* name = elementName->getName();
2368 for (;;) {
2369 if (isInForeign()) {
2370 if (stack[currentPtr]->name != name) {
2371 if (!currentPtr) {
2372 errStrayEndTag(name);
2373 } else {
2374 errEndTagDidNotMatchCurrentOpenElement(name,
2375 stack[currentPtr]->popName);
2378 eltPos = currentPtr;
2379 int32_t origPos = currentPtr;
2380 for (;;) {
2381 if (!eltPos) {
2382 MOZ_ASSERT(fragment,
2383 "We can get this close to the root of the stack in "
2384 "foreign content only in the fragment case.");
2385 NS_HTML5_BREAK(endtagloop);
2387 if (stack[eltPos]->name == name) {
2388 while (currentPtr >= eltPos) {
2389 popForeign(origPos, eltPos);
2391 NS_HTML5_BREAK(endtagloop);
2393 if (stack[--eltPos]->ns == kNameSpaceID_XHTML) {
2394 break;
2398 switch (mode) {
2399 case IN_TEMPLATE: {
2400 switch (group) {
2401 case TEMPLATE: {
2402 break;
2404 default: {
2405 errStrayEndTag(name);
2406 NS_HTML5_BREAK(endtagloop);
2409 [[fallthrough]];
2411 case IN_ROW: {
2412 switch (group) {
2413 case TR: {
2414 eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
2415 if (!eltPos) {
2416 MOZ_ASSERT(fragment || isTemplateContents());
2417 errNoTableRowToClose();
2418 NS_HTML5_BREAK(endtagloop);
2420 clearStackBackTo(eltPos);
2421 pop();
2422 mode = IN_TABLE_BODY;
2423 NS_HTML5_BREAK(endtagloop);
2425 case TABLE: {
2426 eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
2427 if (!eltPos) {
2428 MOZ_ASSERT(fragment || isTemplateContents());
2429 errNoTableRowToClose();
2430 NS_HTML5_BREAK(endtagloop);
2432 clearStackBackTo(eltPos);
2433 pop();
2434 mode = IN_TABLE_BODY;
2435 continue;
2437 case TBODY_OR_THEAD_OR_TFOOT: {
2438 if (findLastInTableScope(name) ==
2439 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2440 errStrayEndTag(name);
2441 NS_HTML5_BREAK(endtagloop);
2443 eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
2444 if (!eltPos) {
2445 MOZ_ASSERT(fragment || isTemplateContents());
2446 errNoTableRowToClose();
2447 NS_HTML5_BREAK(endtagloop);
2449 clearStackBackTo(eltPos);
2450 pop();
2451 mode = IN_TABLE_BODY;
2452 continue;
2454 case BODY:
2455 case CAPTION:
2456 case COL:
2457 case COLGROUP:
2458 case HTML:
2459 case TD_OR_TH: {
2460 errStrayEndTag(name);
2461 NS_HTML5_BREAK(endtagloop);
2463 default:; // fall through
2465 [[fallthrough]];
2467 case IN_TABLE_BODY: {
2468 switch (group) {
2469 case TBODY_OR_THEAD_OR_TFOOT: {
2470 eltPos = findLastOrRoot(name);
2471 if (!eltPos) {
2472 errStrayEndTag(name);
2473 NS_HTML5_BREAK(endtagloop);
2475 clearStackBackTo(eltPos);
2476 pop();
2477 mode = IN_TABLE;
2478 NS_HTML5_BREAK(endtagloop);
2480 case TABLE: {
2481 eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
2482 if (!eltPos || stack[eltPos]->getGroup() == TEMPLATE) {
2483 MOZ_ASSERT(fragment || isTemplateContents());
2484 errStrayEndTag(name);
2485 NS_HTML5_BREAK(endtagloop);
2487 clearStackBackTo(eltPos);
2488 pop();
2489 mode = IN_TABLE;
2490 continue;
2492 case BODY:
2493 case CAPTION:
2494 case COL:
2495 case COLGROUP:
2496 case HTML:
2497 case TD_OR_TH:
2498 case TR: {
2499 errStrayEndTag(name);
2500 NS_HTML5_BREAK(endtagloop);
2502 default:; // fall through
2504 [[fallthrough]];
2506 case IN_TABLE: {
2507 switch (group) {
2508 case TABLE: {
2509 eltPos = findLast(nsGkAtoms::table);
2510 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2511 MOZ_ASSERT(fragment || isTemplateContents());
2512 errStrayEndTag(name);
2513 NS_HTML5_BREAK(endtagloop);
2515 while (currentPtr >= eltPos) {
2516 pop();
2518 resetTheInsertionMode();
2519 NS_HTML5_BREAK(endtagloop);
2521 case BODY:
2522 case CAPTION:
2523 case COL:
2524 case COLGROUP:
2525 case HTML:
2526 case TBODY_OR_THEAD_OR_TFOOT:
2527 case TD_OR_TH:
2528 case TR: {
2529 errStrayEndTag(name);
2530 NS_HTML5_BREAK(endtagloop);
2532 case TEMPLATE: {
2533 break;
2535 default: {
2536 errStrayEndTag(name);
2539 [[fallthrough]];
2541 case IN_CAPTION: {
2542 switch (group) {
2543 case CAPTION: {
2544 eltPos = findLastInTableScope(nsGkAtoms::caption);
2545 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2546 NS_HTML5_BREAK(endtagloop);
2548 generateImpliedEndTags();
2549 if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
2550 errUnclosedElements(eltPos, name);
2552 while (currentPtr >= eltPos) {
2553 pop();
2555 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2556 mode = IN_TABLE;
2557 NS_HTML5_BREAK(endtagloop);
2559 case TABLE: {
2560 eltPos = findLastInTableScope(nsGkAtoms::caption);
2561 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2562 MOZ_ASSERT(fragment || isTemplateContents());
2563 errStrayEndTag(name);
2564 NS_HTML5_BREAK(endtagloop);
2566 generateImpliedEndTags();
2567 if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
2568 errUnclosedElements(eltPos, name);
2570 while (currentPtr >= eltPos) {
2571 pop();
2573 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2574 mode = IN_TABLE;
2575 continue;
2577 case BODY:
2578 case COL:
2579 case COLGROUP:
2580 case HTML:
2581 case TBODY_OR_THEAD_OR_TFOOT:
2582 case TD_OR_TH:
2583 case TR: {
2584 errStrayEndTag(name);
2585 NS_HTML5_BREAK(endtagloop);
2587 default:; // fall through
2589 [[fallthrough]];
2591 case IN_CELL: {
2592 switch (group) {
2593 case TD_OR_TH: {
2594 eltPos = findLastInTableScope(name);
2595 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2596 errStrayEndTag(name);
2597 NS_HTML5_BREAK(endtagloop);
2599 generateImpliedEndTags();
2600 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2601 errUnclosedElements(eltPos, name);
2603 while (currentPtr >= eltPos) {
2604 pop();
2606 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2607 mode = IN_ROW;
2608 NS_HTML5_BREAK(endtagloop);
2610 case TABLE:
2611 case TBODY_OR_THEAD_OR_TFOOT:
2612 case TR: {
2613 if (findLastInTableScope(name) ==
2614 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2615 MOZ_ASSERT(name == nsGkAtoms::tbody || name == nsGkAtoms::tfoot ||
2616 name == nsGkAtoms::thead || fragment ||
2617 isTemplateContents());
2618 errStrayEndTag(name);
2619 NS_HTML5_BREAK(endtagloop);
2621 closeTheCell(findLastInTableScopeTdTh());
2622 continue;
2624 case BODY:
2625 case CAPTION:
2626 case COL:
2627 case COLGROUP:
2628 case HTML: {
2629 errStrayEndTag(name);
2630 NS_HTML5_BREAK(endtagloop);
2632 default:; // fall through
2634 [[fallthrough]];
2636 case FRAMESET_OK:
2637 case IN_BODY: {
2638 switch (group) {
2639 case BODY: {
2640 if (!isSecondOnStackBody()) {
2641 MOZ_ASSERT(fragment || isTemplateContents());
2642 errStrayEndTag(name);
2643 NS_HTML5_BREAK(endtagloop);
2645 MOZ_ASSERT(currentPtr >= 1);
2646 if (MOZ_UNLIKELY(mViewSource)) {
2647 for (int32_t i = 2; i <= currentPtr; i++) {
2648 switch (stack[i]->getGroup()) {
2649 case DD_OR_DT:
2650 case LI:
2651 case OPTGROUP:
2652 case OPTION:
2653 case P:
2654 case RB_OR_RTC:
2655 case RT_OR_RP:
2656 case TD_OR_TH:
2657 case TBODY_OR_THEAD_OR_TFOOT: {
2658 break;
2660 default: {
2661 errEndWithUnclosedElements(name);
2662 NS_HTML5_BREAK(uncloseloop1);
2666 uncloseloop1_end:;
2668 mode = AFTER_BODY;
2669 NS_HTML5_BREAK(endtagloop);
2671 case HTML: {
2672 if (!isSecondOnStackBody()) {
2673 MOZ_ASSERT(fragment || isTemplateContents());
2674 errStrayEndTag(name);
2675 NS_HTML5_BREAK(endtagloop);
2677 if (MOZ_UNLIKELY(mViewSource)) {
2678 for (int32_t i = 0; i <= currentPtr; i++) {
2679 switch (stack[i]->getGroup()) {
2680 case DD_OR_DT:
2681 case LI:
2682 case P:
2683 case RB_OR_RTC:
2684 case RT_OR_RP:
2685 case TBODY_OR_THEAD_OR_TFOOT:
2686 case TD_OR_TH:
2687 case BODY:
2688 case HTML: {
2689 break;
2691 default: {
2692 errEndWithUnclosedElements(name);
2693 NS_HTML5_BREAK(uncloseloop2);
2697 uncloseloop2_end:;
2699 mode = AFTER_BODY;
2700 continue;
2702 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
2703 case UL_OR_OL_OR_DL:
2704 case PRE_OR_LISTING:
2705 case FIELDSET:
2706 case BUTTON:
2707 case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SEARCH_OR_SECTION_OR_SUMMARY: {
2708 eltPos = findLastInScope(name);
2709 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2710 errStrayEndTag(name);
2711 } else {
2712 generateImpliedEndTags();
2713 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2714 errUnclosedElements(eltPos, name);
2716 while (currentPtr >= eltPos) {
2717 pop();
2720 NS_HTML5_BREAK(endtagloop);
2722 case FORM: {
2723 if (!isTemplateContents()) {
2724 if (!formPointer) {
2725 errStrayEndTag(name);
2726 NS_HTML5_BREAK(endtagloop);
2728 formPointer = nullptr;
2729 eltPos = findLastInScope(name);
2730 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2731 errStrayEndTag(name);
2732 NS_HTML5_BREAK(endtagloop);
2734 generateImpliedEndTags();
2735 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2736 errUnclosedElements(eltPos, name);
2738 removeFromStack(eltPos);
2739 NS_HTML5_BREAK(endtagloop);
2740 } else {
2741 eltPos = findLastInScope(name);
2742 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2743 errStrayEndTag(name);
2744 NS_HTML5_BREAK(endtagloop);
2746 generateImpliedEndTags();
2747 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2748 errUnclosedElements(eltPos, name);
2750 while (currentPtr >= eltPos) {
2751 pop();
2753 NS_HTML5_BREAK(endtagloop);
2756 case P: {
2757 eltPos = findLastInButtonScope(nsGkAtoms::p);
2758 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2759 errNoElementToCloseButEndTagSeen(nsGkAtoms::p);
2760 if (isInForeign()) {
2761 errHtmlStartTagInForeignContext(name);
2762 while (currentPtr >= 0 &&
2763 stack[currentPtr]->ns != kNameSpaceID_XHTML) {
2764 pop();
2767 appendVoidElementToCurrentMayFoster(
2768 elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
2769 NS_HTML5_BREAK(endtagloop);
2771 generateImpliedEndTagsExceptFor(nsGkAtoms::p);
2772 MOZ_ASSERT(eltPos != nsHtml5TreeBuilder::NOT_FOUND_ON_STACK);
2773 if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
2774 errUnclosedElements(eltPos, name);
2776 while (currentPtr >= eltPos) {
2777 pop();
2779 NS_HTML5_BREAK(endtagloop);
2781 case LI: {
2782 eltPos = findLastInListScope(name);
2783 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2784 errNoElementToCloseButEndTagSeen(name);
2785 } else {
2786 generateImpliedEndTagsExceptFor(name);
2787 if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
2788 errUnclosedElements(eltPos, name);
2790 while (currentPtr >= eltPos) {
2791 pop();
2794 NS_HTML5_BREAK(endtagloop);
2796 case DD_OR_DT: {
2797 eltPos = findLastInScope(name);
2798 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2799 errNoElementToCloseButEndTagSeen(name);
2800 } else {
2801 generateImpliedEndTagsExceptFor(name);
2802 if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
2803 errUnclosedElements(eltPos, name);
2805 while (currentPtr >= eltPos) {
2806 pop();
2809 NS_HTML5_BREAK(endtagloop);
2811 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: {
2812 eltPos = findLastInScopeHn();
2813 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2814 errStrayEndTag(name);
2815 } else {
2816 generateImpliedEndTags();
2817 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2818 errUnclosedElements(eltPos, name);
2820 while (currentPtr >= eltPos) {
2821 pop();
2824 NS_HTML5_BREAK(endtagloop);
2826 case OBJECT:
2827 case MARQUEE_OR_APPLET: {
2828 eltPos = findLastInScope(name);
2829 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2830 errStrayEndTag(name);
2831 } else {
2832 generateImpliedEndTags();
2833 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2834 errUnclosedElements(eltPos, name);
2836 while (currentPtr >= eltPos) {
2837 pop();
2839 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2841 NS_HTML5_BREAK(endtagloop);
2843 case BR: {
2844 errEndTagBr();
2845 if (isInForeign()) {
2846 errHtmlStartTagInForeignContext(name);
2847 while (currentPtr >= 0 &&
2848 stack[currentPtr]->ns != kNameSpaceID_XHTML) {
2849 pop();
2852 reconstructTheActiveFormattingElements();
2853 appendVoidElementToCurrentMayFoster(
2854 elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
2855 NS_HTML5_BREAK(endtagloop);
2857 case TEMPLATE: {
2858 break;
2860 case AREA_OR_WBR:
2861 case KEYGEN:
2862 case PARAM_OR_SOURCE_OR_TRACK:
2863 case EMBED:
2864 case IMG:
2865 case IMAGE:
2866 case INPUT:
2867 case HR:
2868 case IFRAME:
2869 case NOEMBED:
2870 case NOFRAMES:
2871 case SELECT:
2872 case TABLE:
2873 case TEXTAREA: {
2874 errStrayEndTag(name);
2875 NS_HTML5_BREAK(endtagloop);
2877 case NOSCRIPT: {
2878 if (scriptingEnabled) {
2879 errStrayEndTag(name);
2880 NS_HTML5_BREAK(endtagloop);
2882 [[fallthrough]];
2884 case A:
2885 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
2886 case FONT:
2887 case NOBR: {
2888 if (adoptionAgencyEndTag(name)) {
2889 NS_HTML5_BREAK(endtagloop);
2891 [[fallthrough]];
2893 default: {
2894 if (isCurrent(name)) {
2895 pop();
2896 NS_HTML5_BREAK(endtagloop);
2898 eltPos = currentPtr;
2899 for (;;) {
2900 nsHtml5StackNode* node = stack[eltPos];
2901 if (node->ns == kNameSpaceID_XHTML && node->name == name) {
2902 generateImpliedEndTags();
2903 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2904 errUnclosedElements(eltPos, name);
2906 while (currentPtr >= eltPos) {
2907 pop();
2909 NS_HTML5_BREAK(endtagloop);
2910 } else if (!eltPos || node->isSpecial()) {
2911 errStrayEndTag(name);
2912 NS_HTML5_BREAK(endtagloop);
2914 eltPos--;
2918 [[fallthrough]];
2920 case IN_HEAD: {
2921 switch (group) {
2922 case HEAD: {
2923 pop();
2924 mode = AFTER_HEAD;
2925 NS_HTML5_BREAK(endtagloop);
2927 case BR:
2928 case HTML:
2929 case BODY: {
2930 pop();
2931 mode = AFTER_HEAD;
2932 continue;
2934 case TEMPLATE: {
2935 endTagTemplateInHead();
2936 NS_HTML5_BREAK(endtagloop);
2938 default: {
2939 errStrayEndTag(name);
2940 NS_HTML5_BREAK(endtagloop);
2944 case IN_HEAD_NOSCRIPT: {
2945 switch (group) {
2946 case NOSCRIPT: {
2947 pop();
2948 mode = IN_HEAD;
2949 NS_HTML5_BREAK(endtagloop);
2951 case BR: {
2952 errStrayEndTag(name);
2953 pop();
2954 mode = IN_HEAD;
2955 continue;
2957 default: {
2958 errStrayEndTag(name);
2959 NS_HTML5_BREAK(endtagloop);
2963 case IN_COLUMN_GROUP: {
2964 switch (group) {
2965 case COLGROUP: {
2966 if (!currentPtr ||
2967 stack[currentPtr]->getGroup() == nsHtml5TreeBuilder::TEMPLATE) {
2968 MOZ_ASSERT(fragment || isTemplateContents());
2969 errGarbageInColgroup();
2970 NS_HTML5_BREAK(endtagloop);
2972 pop();
2973 mode = IN_TABLE;
2974 NS_HTML5_BREAK(endtagloop);
2976 case COL: {
2977 errStrayEndTag(name);
2978 NS_HTML5_BREAK(endtagloop);
2980 case TEMPLATE: {
2981 endTagTemplateInHead();
2982 NS_HTML5_BREAK(endtagloop);
2984 default: {
2985 if (!currentPtr ||
2986 stack[currentPtr]->getGroup() == nsHtml5TreeBuilder::TEMPLATE) {
2987 MOZ_ASSERT(fragment || isTemplateContents());
2988 errGarbageInColgroup();
2989 NS_HTML5_BREAK(endtagloop);
2991 pop();
2992 mode = IN_TABLE;
2993 continue;
2997 case IN_SELECT_IN_TABLE: {
2998 switch (group) {
2999 case CAPTION:
3000 case TABLE:
3001 case TBODY_OR_THEAD_OR_TFOOT:
3002 case TR:
3003 case TD_OR_TH: {
3004 errEndTagSeenWithSelectOpen(name);
3005 if (findLastInTableScope(name) !=
3006 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
3007 eltPos = findLastInTableScope(nsGkAtoms::select);
3008 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
3009 MOZ_ASSERT(fragment);
3010 NS_HTML5_BREAK(endtagloop);
3012 while (currentPtr >= eltPos) {
3013 pop();
3015 resetTheInsertionMode();
3016 continue;
3017 } else {
3018 NS_HTML5_BREAK(endtagloop);
3021 default:; // fall through
3023 [[fallthrough]];
3025 case IN_SELECT: {
3026 switch (group) {
3027 case OPTION: {
3028 if (isCurrent(nsGkAtoms::option)) {
3029 pop();
3030 NS_HTML5_BREAK(endtagloop);
3031 } else {
3032 errStrayEndTag(name);
3033 NS_HTML5_BREAK(endtagloop);
3036 case OPTGROUP: {
3037 if (isCurrent(nsGkAtoms::option) &&
3038 nsGkAtoms::optgroup == stack[currentPtr - 1]->name) {
3039 pop();
3041 if (isCurrent(nsGkAtoms::optgroup)) {
3042 pop();
3043 } else {
3044 errStrayEndTag(name);
3046 NS_HTML5_BREAK(endtagloop);
3048 case SELECT: {
3049 eltPos = findLastInTableScope(nsGkAtoms::select);
3050 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
3051 MOZ_ASSERT(fragment);
3052 errStrayEndTag(name);
3053 NS_HTML5_BREAK(endtagloop);
3055 while (currentPtr >= eltPos) {
3056 pop();
3058 resetTheInsertionMode();
3059 NS_HTML5_BREAK(endtagloop);
3061 case TEMPLATE: {
3062 endTagTemplateInHead();
3063 NS_HTML5_BREAK(endtagloop);
3065 default: {
3066 errStrayEndTag(name);
3067 NS_HTML5_BREAK(endtagloop);
3071 case AFTER_BODY: {
3072 switch (group) {
3073 case HTML: {
3074 if (fragment) {
3075 errStrayEndTag(name);
3076 NS_HTML5_BREAK(endtagloop);
3077 } else {
3078 mode = AFTER_AFTER_BODY;
3079 NS_HTML5_BREAK(endtagloop);
3082 default: {
3083 errEndTagAfterBody();
3084 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3085 continue;
3089 case IN_FRAMESET: {
3090 switch (group) {
3091 case FRAMESET: {
3092 if (!currentPtr) {
3093 MOZ_ASSERT(fragment);
3094 errStrayEndTag(name);
3095 NS_HTML5_BREAK(endtagloop);
3097 pop();
3098 if ((!fragment) && !isCurrent(nsGkAtoms::frameset)) {
3099 mode = AFTER_FRAMESET;
3101 NS_HTML5_BREAK(endtagloop);
3103 default: {
3104 errStrayEndTag(name);
3105 NS_HTML5_BREAK(endtagloop);
3109 case AFTER_FRAMESET: {
3110 switch (group) {
3111 case HTML: {
3112 mode = AFTER_AFTER_FRAMESET;
3113 NS_HTML5_BREAK(endtagloop);
3115 default: {
3116 errStrayEndTag(name);
3117 NS_HTML5_BREAK(endtagloop);
3121 case INITIAL: {
3122 errEndTagSeenWithoutDoctype();
3123 documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
3124 mode = BEFORE_HTML;
3125 continue;
3127 case BEFORE_HTML: {
3128 switch (group) {
3129 case HEAD:
3130 case BR:
3131 case HTML:
3132 case BODY: {
3133 appendHtmlElementToDocumentAndPush();
3134 mode = BEFORE_HEAD;
3135 continue;
3137 default: {
3138 errStrayEndTag(name);
3139 NS_HTML5_BREAK(endtagloop);
3143 case BEFORE_HEAD: {
3144 switch (group) {
3145 case HEAD:
3146 case BR:
3147 case HTML:
3148 case BODY: {
3149 appendToCurrentNodeAndPushHeadElement(
3150 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
3151 mode = IN_HEAD;
3152 continue;
3154 default: {
3155 errStrayEndTag(name);
3156 NS_HTML5_BREAK(endtagloop);
3160 case AFTER_HEAD: {
3161 switch (group) {
3162 case TEMPLATE: {
3163 endTagTemplateInHead();
3164 NS_HTML5_BREAK(endtagloop);
3166 case HTML:
3167 case BODY:
3168 case BR: {
3169 appendToCurrentNodeAndPushBodyElement();
3170 mode = FRAMESET_OK;
3171 continue;
3173 default: {
3174 errStrayEndTag(name);
3175 NS_HTML5_BREAK(endtagloop);
3179 case AFTER_AFTER_BODY: {
3180 errStrayEndTag(name);
3181 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3182 continue;
3184 case AFTER_AFTER_FRAMESET: {
3185 errStrayEndTag(name);
3186 NS_HTML5_BREAK(endtagloop);
3188 case TEXT: {
3189 pop();
3190 if (originalMode == AFTER_HEAD) {
3191 silentPop();
3193 mode = originalMode;
3194 NS_HTML5_BREAK(endtagloop);
3198 endtagloop_end:;
3201 void nsHtml5TreeBuilder::endTagTemplateInHead() {
3202 int32_t eltPos = findLast(nsGkAtoms::_template);
3203 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
3204 errStrayEndTag(nsGkAtoms::_template);
3205 return;
3207 generateImpliedEndTagsThoroughly();
3208 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsGkAtoms::_template)) {
3209 errUnclosedElements(eltPos, nsGkAtoms::_template);
3211 while (currentPtr >= eltPos) {
3212 pop();
3214 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
3215 popTemplateMode();
3216 resetTheInsertionMode();
3219 int32_t
3220 nsHtml5TreeBuilder::findLastInTableScopeOrRootTemplateTbodyTheadTfoot() {
3221 for (int32_t i = currentPtr; i > 0; i--) {
3222 if (stack[i]->ns == kNameSpaceID_XHTML &&
3223 (stack[i]->getGroup() == nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT ||
3224 stack[i]->getGroup() == nsHtml5TreeBuilder::TEMPLATE)) {
3225 return i;
3228 return 0;
3231 int32_t nsHtml5TreeBuilder::findLast(nsAtom* name) {
3232 for (int32_t i = currentPtr; i > 0; i--) {
3233 if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
3234 return i;
3237 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3240 int32_t nsHtml5TreeBuilder::findLastInTableScope(nsAtom* name) {
3241 for (int32_t i = currentPtr; i > 0; i--) {
3242 if (stack[i]->ns == kNameSpaceID_XHTML) {
3243 if (stack[i]->name == name) {
3244 return i;
3245 } else if (stack[i]->name == nsGkAtoms::table ||
3246 stack[i]->name == nsGkAtoms::_template) {
3247 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3251 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3254 int32_t nsHtml5TreeBuilder::findLastInButtonScope(nsAtom* name) {
3255 for (int32_t i = currentPtr; i > 0; i--) {
3256 if (stack[i]->ns == kNameSpaceID_XHTML) {
3257 if (stack[i]->name == name) {
3258 return i;
3259 } else if (stack[i]->name == nsGkAtoms::button) {
3260 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3263 if (stack[i]->isScoping()) {
3264 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3267 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3270 int32_t nsHtml5TreeBuilder::findLastInScope(nsAtom* name) {
3271 for (int32_t i = currentPtr; i > 0; i--) {
3272 if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
3273 return i;
3274 } else if (stack[i]->isScoping()) {
3275 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3278 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3281 int32_t nsHtml5TreeBuilder::findLastInListScope(nsAtom* name) {
3282 for (int32_t i = currentPtr; i > 0; i--) {
3283 if (stack[i]->ns == kNameSpaceID_XHTML) {
3284 if (stack[i]->name == name) {
3285 return i;
3286 } else if (stack[i]->name == nsGkAtoms::ul ||
3287 stack[i]->name == nsGkAtoms::ol) {
3288 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3291 if (stack[i]->isScoping()) {
3292 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3295 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3298 int32_t nsHtml5TreeBuilder::findLastInScopeHn() {
3299 for (int32_t i = currentPtr; i > 0; i--) {
3300 if (stack[i]->getGroup() ==
3301 nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
3302 return i;
3303 } else if (stack[i]->isScoping()) {
3304 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3307 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3310 void nsHtml5TreeBuilder::generateImpliedEndTagsExceptFor(nsAtom* name) {
3311 for (;;) {
3312 nsHtml5StackNode* node = stack[currentPtr];
3313 switch (node->getGroup()) {
3314 case P:
3315 case LI:
3316 case DD_OR_DT:
3317 case OPTION:
3318 case OPTGROUP:
3319 case RB_OR_RTC:
3320 case RT_OR_RP: {
3321 if (node->ns == kNameSpaceID_XHTML && node->name == name) {
3322 return;
3324 pop();
3325 continue;
3327 default: {
3328 return;
3334 void nsHtml5TreeBuilder::generateImpliedEndTags() {
3335 for (;;) {
3336 switch (stack[currentPtr]->getGroup()) {
3337 case P:
3338 case LI:
3339 case DD_OR_DT:
3340 case OPTION:
3341 case OPTGROUP:
3342 case RB_OR_RTC:
3343 case RT_OR_RP: {
3344 pop();
3345 continue;
3347 default: {
3348 return;
3354 void nsHtml5TreeBuilder::generateImpliedEndTagsThoroughly() {
3355 for (;;) {
3356 switch (stack[currentPtr]->getGroup()) {
3357 case CAPTION:
3358 case COLGROUP:
3359 case DD_OR_DT:
3360 case LI:
3361 case OPTGROUP:
3362 case OPTION:
3363 case P:
3364 case RB_OR_RTC:
3365 case RT_OR_RP:
3366 case TBODY_OR_THEAD_OR_TFOOT:
3367 case TD_OR_TH:
3368 case TR: {
3369 pop();
3370 continue;
3372 default: {
3373 return;
3379 bool nsHtml5TreeBuilder::isSecondOnStackBody() {
3380 return currentPtr >= 1 && stack[1]->getGroup() == nsHtml5TreeBuilder::BODY;
3383 void nsHtml5TreeBuilder::documentModeInternal(nsHtml5DocumentMode m,
3384 nsHtml5String publicIdentifier,
3385 nsHtml5String systemIdentifier) {
3386 if (forceNoQuirks) {
3387 quirks = false;
3388 this->documentMode(STANDARDS_MODE);
3389 return;
3391 quirks = (m == QUIRKS_MODE);
3392 this->documentMode(m);
3395 bool nsHtml5TreeBuilder::isAlmostStandards(nsHtml5String publicIdentifier,
3396 nsHtml5String systemIdentifier) {
3397 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3398 "-//w3c//dtd xhtml 1.0 transitional//", publicIdentifier)) {
3399 return true;
3401 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3402 "-//w3c//dtd xhtml 1.0 frameset//", publicIdentifier)) {
3403 return true;
3405 if (systemIdentifier) {
3406 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3407 "-//w3c//dtd html 4.01 transitional//", publicIdentifier)) {
3408 return true;
3410 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3411 "-//w3c//dtd html 4.01 frameset//", publicIdentifier)) {
3412 return true;
3415 return false;
3418 bool nsHtml5TreeBuilder::isQuirky(nsAtom* name, nsHtml5String publicIdentifier,
3419 nsHtml5String systemIdentifier,
3420 bool forceQuirks) {
3421 if (forceQuirks) {
3422 return true;
3424 if (name != nsGkAtoms::html) {
3425 return true;
3427 if (publicIdentifier) {
3428 for (int32_t i = 0; i < nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS.length; i++) {
3429 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3430 nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS[i], publicIdentifier)) {
3431 return true;
3434 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3435 "-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier) ||
3436 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3437 "-/w3c/dtd html 4.0 transitional/en", publicIdentifier) ||
3438 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3439 "html", publicIdentifier)) {
3440 return true;
3443 if (!systemIdentifier) {
3444 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3445 "-//w3c//dtd html 4.01 transitional//", publicIdentifier)) {
3446 return true;
3447 } else if (nsHtml5Portability::
3448 lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3449 "-//w3c//dtd html 4.01 frameset//", publicIdentifier)) {
3450 return true;
3452 } else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3453 "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd",
3454 systemIdentifier)) {
3455 return true;
3457 return false;
3460 void nsHtml5TreeBuilder::closeTheCell(int32_t eltPos) {
3461 generateImpliedEndTags();
3462 if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
3463 errUnclosedElementsCell(eltPos);
3465 while (currentPtr >= eltPos) {
3466 pop();
3468 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
3469 mode = IN_ROW;
3470 return;
3473 int32_t nsHtml5TreeBuilder::findLastInTableScopeTdTh() {
3474 for (int32_t i = currentPtr; i > 0; i--) {
3475 nsAtom* name = stack[i]->name;
3476 if (stack[i]->ns == kNameSpaceID_XHTML) {
3477 if (nsGkAtoms::td == name || nsGkAtoms::th == name) {
3478 return i;
3479 } else if (name == nsGkAtoms::table || name == nsGkAtoms::_template) {
3480 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3484 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3487 void nsHtml5TreeBuilder::clearStackBackTo(int32_t eltPos) {
3488 int32_t eltGroup = stack[eltPos]->getGroup();
3489 while (currentPtr > eltPos) {
3490 if (stack[currentPtr]->ns == kNameSpaceID_XHTML &&
3491 stack[currentPtr]->getGroup() == TEMPLATE &&
3492 (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT ||
3493 eltGroup == TR || !eltPos)) {
3494 return;
3496 pop();
3500 void nsHtml5TreeBuilder::resetTheInsertionMode() {
3501 nsHtml5StackNode* node;
3502 nsAtom* name;
3503 int32_t ns;
3504 for (int32_t i = currentPtr; i >= 0; i--) {
3505 node = stack[i];
3506 name = node->name;
3507 ns = node->ns;
3508 if (!i) {
3509 if (!(contextNamespace == kNameSpaceID_XHTML &&
3510 (contextName == nsGkAtoms::td || contextName == nsGkAtoms::th))) {
3511 if (fragment) {
3512 name = contextName;
3513 ns = contextNamespace;
3515 } else {
3516 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3517 return;
3520 if (nsGkAtoms::select == name) {
3521 int32_t ancestorIndex = i;
3522 while (ancestorIndex > 0) {
3523 nsHtml5StackNode* ancestor = stack[ancestorIndex--];
3524 if (kNameSpaceID_XHTML == ancestor->ns) {
3525 if (nsGkAtoms::_template == ancestor->name) {
3526 break;
3528 if (nsGkAtoms::table == ancestor->name) {
3529 mode = IN_SELECT_IN_TABLE;
3530 return;
3534 mode = IN_SELECT;
3535 return;
3536 } else if (nsGkAtoms::td == name || nsGkAtoms::th == name) {
3537 mode = IN_CELL;
3538 return;
3539 } else if (nsGkAtoms::tr == name) {
3540 mode = IN_ROW;
3541 return;
3542 } else if (nsGkAtoms::tbody == name || nsGkAtoms::thead == name ||
3543 nsGkAtoms::tfoot == name) {
3544 mode = IN_TABLE_BODY;
3545 return;
3546 } else if (nsGkAtoms::caption == name) {
3547 mode = IN_CAPTION;
3548 return;
3549 } else if (nsGkAtoms::colgroup == name) {
3550 mode = IN_COLUMN_GROUP;
3551 return;
3552 } else if (nsGkAtoms::table == name) {
3553 mode = IN_TABLE;
3554 return;
3555 } else if (kNameSpaceID_XHTML != ns) {
3556 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3557 return;
3558 } else if (nsGkAtoms::_template == name) {
3559 MOZ_ASSERT(templateModePtr >= 0);
3560 mode = templateModeStack[templateModePtr];
3561 return;
3562 } else if (nsGkAtoms::head == name) {
3563 if (name == contextName) {
3564 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3565 } else {
3566 mode = IN_HEAD;
3568 return;
3569 } else if (nsGkAtoms::body == name) {
3570 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3571 return;
3572 } else if (nsGkAtoms::frameset == name) {
3573 mode = IN_FRAMESET;
3574 return;
3575 } else if (nsGkAtoms::html == name) {
3576 if (!headPointer) {
3577 mode = BEFORE_HEAD;
3578 } else {
3579 mode = AFTER_HEAD;
3581 return;
3582 } else if (!i) {
3583 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3584 return;
3589 void nsHtml5TreeBuilder::implicitlyCloseP() {
3590 int32_t eltPos = findLastInButtonScope(nsGkAtoms::p);
3591 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
3592 return;
3594 generateImpliedEndTagsExceptFor(nsGkAtoms::p);
3595 if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
3596 errUnclosedElementsImplied(eltPos, nsGkAtoms::p);
3598 while (currentPtr >= eltPos) {
3599 pop();
3603 bool nsHtml5TreeBuilder::debugOnlyClearLastStackSlot() {
3604 stack[currentPtr] = nullptr;
3605 return true;
3608 bool nsHtml5TreeBuilder::debugOnlyClearLastListSlot() {
3609 listOfActiveFormattingElements[listPtr] = nullptr;
3610 return true;
3613 void nsHtml5TreeBuilder::pushTemplateMode(int32_t mode) {
3614 templateModePtr++;
3615 if (templateModePtr == templateModeStack.length) {
3616 jArray<int32_t, int32_t> newStack =
3617 jArray<int32_t, int32_t>::newJArray(templateModeStack.length + 64);
3618 nsHtml5ArrayCopy::arraycopy(templateModeStack, newStack,
3619 templateModeStack.length);
3620 templateModeStack = newStack;
3622 templateModeStack[templateModePtr] = mode;
3625 void nsHtml5TreeBuilder::push(nsHtml5StackNode* node) {
3626 currentPtr++;
3627 if (currentPtr == stack.length) {
3628 jArray<nsHtml5StackNode*, int32_t> newStack =
3629 jArray<nsHtml5StackNode*, int32_t>::newJArray(stack.length + 64);
3630 nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length);
3631 stack = newStack;
3633 stack[currentPtr] = node;
3634 elementPushed(node->ns, node->popName, node->node);
3637 void nsHtml5TreeBuilder::silentPush(nsHtml5StackNode* node) {
3638 currentPtr++;
3639 if (currentPtr == stack.length) {
3640 jArray<nsHtml5StackNode*, int32_t> newStack =
3641 jArray<nsHtml5StackNode*, int32_t>::newJArray(stack.length + 64);
3642 nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length);
3643 stack = newStack;
3645 stack[currentPtr] = node;
3648 void nsHtml5TreeBuilder::append(nsHtml5StackNode* node) {
3649 listPtr++;
3650 if (listPtr == listOfActiveFormattingElements.length) {
3651 jArray<nsHtml5StackNode*, int32_t> newList =
3652 jArray<nsHtml5StackNode*, int32_t>::newJArray(
3653 listOfActiveFormattingElements.length + 64);
3654 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, newList,
3655 listOfActiveFormattingElements.length);
3656 listOfActiveFormattingElements = newList;
3658 listOfActiveFormattingElements[listPtr] = node;
3661 void nsHtml5TreeBuilder::
3662 clearTheListOfActiveFormattingElementsUpToTheLastMarker() {
3663 while (listPtr > -1) {
3664 if (!listOfActiveFormattingElements[listPtr]) {
3665 --listPtr;
3666 return;
3668 listOfActiveFormattingElements[listPtr]->release(this);
3669 --listPtr;
3673 void nsHtml5TreeBuilder::removeFromStack(int32_t pos) {
3674 if (currentPtr == pos) {
3675 pop();
3676 } else {
3677 stack[pos]->release(this);
3678 nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos);
3679 MOZ_ASSERT(debugOnlyClearLastStackSlot());
3680 currentPtr--;
3684 void nsHtml5TreeBuilder::removeFromStack(nsHtml5StackNode* node) {
3685 if (stack[currentPtr] == node) {
3686 pop();
3687 } else {
3688 int32_t pos = currentPtr - 1;
3689 while (pos >= 0 && stack[pos] != node) {
3690 pos--;
3692 if (pos == -1) {
3693 return;
3696 node->release(this);
3697 nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos);
3698 currentPtr--;
3702 void nsHtml5TreeBuilder::removeFromListOfActiveFormattingElements(int32_t pos) {
3703 MOZ_ASSERT(!!listOfActiveFormattingElements[pos]);
3704 listOfActiveFormattingElements[pos]->release(this);
3705 if (pos == listPtr) {
3706 MOZ_ASSERT(debugOnlyClearLastListSlot());
3707 listPtr--;
3708 return;
3710 MOZ_ASSERT(pos < listPtr);
3711 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, pos + 1, pos,
3712 listPtr - pos);
3713 MOZ_ASSERT(debugOnlyClearLastListSlot());
3714 listPtr--;
3717 bool nsHtml5TreeBuilder::adoptionAgencyEndTag(nsAtom* name) {
3718 if (stack[currentPtr]->ns == kNameSpaceID_XHTML &&
3719 stack[currentPtr]->name == name &&
3720 findInListOfActiveFormattingElements(stack[currentPtr]) == -1) {
3721 pop();
3722 return true;
3724 for (int32_t i = 0; i < 8; ++i) {
3725 int32_t formattingEltListPos = listPtr;
3726 while (formattingEltListPos > -1) {
3727 nsHtml5StackNode* listNode =
3728 listOfActiveFormattingElements[formattingEltListPos];
3729 if (!listNode) {
3730 formattingEltListPos = -1;
3731 break;
3732 } else if (listNode->name == name) {
3733 break;
3735 formattingEltListPos--;
3737 if (formattingEltListPos == -1) {
3738 return false;
3740 nsHtml5StackNode* formattingElt =
3741 listOfActiveFormattingElements[formattingEltListPos];
3742 int32_t formattingEltStackPos = currentPtr;
3743 bool inScope = true;
3744 while (formattingEltStackPos > -1) {
3745 nsHtml5StackNode* node = stack[formattingEltStackPos];
3746 if (node == formattingElt) {
3747 break;
3748 } else if (node->isScoping()) {
3749 inScope = false;
3751 formattingEltStackPos--;
3753 if (formattingEltStackPos == -1) {
3754 errNoElementToCloseButEndTagSeen(name);
3755 removeFromListOfActiveFormattingElements(formattingEltListPos);
3756 return true;
3758 if (!inScope) {
3759 errNoElementToCloseButEndTagSeen(name);
3760 return true;
3762 if (formattingEltStackPos != currentPtr) {
3763 errEndTagViolatesNestingRules(name);
3765 int32_t furthestBlockPos = formattingEltStackPos + 1;
3766 while (furthestBlockPos <= currentPtr) {
3767 nsHtml5StackNode* node = stack[furthestBlockPos];
3768 MOZ_ASSERT(furthestBlockPos > 0,
3769 "How is formattingEltStackPos + 1 not > 0?");
3770 if (node->isSpecial()) {
3771 break;
3773 furthestBlockPos++;
3775 if (furthestBlockPos > currentPtr) {
3776 while (currentPtr >= formattingEltStackPos) {
3777 pop();
3779 removeFromListOfActiveFormattingElements(formattingEltListPos);
3780 return true;
3782 nsHtml5StackNode* commonAncestor = stack[formattingEltStackPos - 1];
3783 nsIContentHandle* insertionCommonAncestor =
3784 nodeFromStackWithBlinkCompat(formattingEltStackPos - 1);
3785 nsHtml5StackNode* furthestBlock = stack[furthestBlockPos];
3786 int32_t bookmark = formattingEltListPos;
3787 int32_t nodePos = furthestBlockPos;
3788 nsHtml5StackNode* lastNode = furthestBlock;
3789 int32_t j = 0;
3790 for (;;) {
3791 ++j;
3792 nodePos--;
3793 if (nodePos == formattingEltStackPos) {
3794 break;
3796 nsHtml5StackNode* node = stack[nodePos];
3797 int32_t nodeListPos = findInListOfActiveFormattingElements(node);
3798 if (j > 3 && nodeListPos != -1) {
3799 removeFromListOfActiveFormattingElements(nodeListPos);
3800 if (nodeListPos <= formattingEltListPos) {
3801 formattingEltListPos--;
3803 if (nodeListPos <= bookmark) {
3804 bookmark--;
3806 nodeListPos = -1;
3808 if (nodeListPos == -1) {
3809 MOZ_ASSERT(formattingEltStackPos < nodePos);
3810 MOZ_ASSERT(bookmark < nodePos);
3811 MOZ_ASSERT(furthestBlockPos > nodePos);
3812 removeFromStack(nodePos);
3813 furthestBlockPos--;
3814 continue;
3816 if (nodePos == furthestBlockPos) {
3817 bookmark = nodeListPos + 1;
3819 MOZ_ASSERT(node == listOfActiveFormattingElements[nodeListPos]);
3820 MOZ_ASSERT(node == stack[nodePos]);
3821 nsIContentHandle* clone = createElement(
3822 kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes(),
3823 insertionCommonAncestor, htmlCreator(node->getHtmlCreator()));
3824 nsHtml5StackNode* newNode = createStackNode(
3825 node->getFlags(), node->ns, node->name, clone, node->popName,
3826 node->attributes, node->getHtmlCreator());
3827 node->dropAttributes();
3828 stack[nodePos] = newNode;
3829 newNode->retain();
3830 listOfActiveFormattingElements[nodeListPos] = newNode;
3831 node->release(this);
3832 node->release(this);
3833 node = newNode;
3834 detachFromParent(lastNode->node);
3835 appendElement(lastNode->node, nodeFromStackWithBlinkCompat(nodePos));
3836 lastNode = node;
3838 if (commonAncestor->isFosterParenting()) {
3839 detachFromParent(lastNode->node);
3840 insertIntoFosterParent(lastNode->node);
3841 } else {
3842 detachFromParent(lastNode->node);
3843 appendElement(lastNode->node, insertionCommonAncestor);
3845 nsIContentHandle* clone = createElement(
3846 kNameSpaceID_XHTML, formattingElt->name,
3847 formattingElt->attributes->cloneAttributes(), furthestBlock->node,
3848 htmlCreator(formattingElt->getHtmlCreator()));
3849 nsHtml5StackNode* formattingClone = createStackNode(
3850 formattingElt->getFlags(), formattingElt->ns, formattingElt->name,
3851 clone, formattingElt->popName, formattingElt->attributes,
3852 formattingElt->getHtmlCreator());
3853 formattingElt->dropAttributes();
3854 appendChildrenToNewParent(furthestBlock->node, clone);
3855 appendElement(clone, furthestBlock->node);
3856 removeFromListOfActiveFormattingElements(formattingEltListPos);
3857 insertIntoListOfActiveFormattingElements(formattingClone, bookmark);
3858 MOZ_ASSERT(formattingEltStackPos < furthestBlockPos);
3859 removeFromStack(formattingEltStackPos);
3860 insertIntoStack(formattingClone, furthestBlockPos);
3862 return true;
3865 void nsHtml5TreeBuilder::insertIntoStack(nsHtml5StackNode* node,
3866 int32_t position) {
3867 MOZ_ASSERT(currentPtr + 1 < stack.length);
3868 MOZ_ASSERT(position <= currentPtr + 1);
3869 if (position == currentPtr + 1) {
3870 push(node);
3871 } else {
3872 nsHtml5ArrayCopy::arraycopy(stack, position, position + 1,
3873 (currentPtr - position) + 1);
3874 currentPtr++;
3875 stack[position] = node;
3879 void nsHtml5TreeBuilder::insertIntoListOfActiveFormattingElements(
3880 nsHtml5StackNode* formattingClone, int32_t bookmark) {
3881 formattingClone->retain();
3882 MOZ_ASSERT(listPtr + 1 < listOfActiveFormattingElements.length);
3883 if (bookmark <= listPtr) {
3884 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, bookmark,
3885 bookmark + 1, (listPtr - bookmark) + 1);
3887 listPtr++;
3888 listOfActiveFormattingElements[bookmark] = formattingClone;
3891 int32_t nsHtml5TreeBuilder::findInListOfActiveFormattingElements(
3892 nsHtml5StackNode* node) {
3893 for (int32_t i = listPtr; i >= 0; i--) {
3894 if (node == listOfActiveFormattingElements[i]) {
3895 return i;
3898 return -1;
3901 int32_t nsHtml5TreeBuilder::
3902 findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
3903 nsAtom* name) {
3904 for (int32_t i = listPtr; i >= 0; i--) {
3905 nsHtml5StackNode* node = listOfActiveFormattingElements[i];
3906 if (!node) {
3907 return -1;
3908 } else if (node->name == name) {
3909 return i;
3912 return -1;
3915 void nsHtml5TreeBuilder::maybeForgetEarlierDuplicateFormattingElement(
3916 nsAtom* name, nsHtml5HtmlAttributes* attributes) {
3917 int32_t candidate = -1;
3918 int32_t count = 0;
3919 for (int32_t i = listPtr; i >= 0; i--) {
3920 nsHtml5StackNode* node = listOfActiveFormattingElements[i];
3921 if (!node) {
3922 break;
3924 if (node->name == name && node->attributes->equalsAnother(attributes)) {
3925 candidate = i;
3926 ++count;
3929 if (count >= 3) {
3930 removeFromListOfActiveFormattingElements(candidate);
3934 int32_t nsHtml5TreeBuilder::findLastOrRoot(nsAtom* name) {
3935 for (int32_t i = currentPtr; i > 0; i--) {
3936 if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
3937 return i;
3940 return 0;
3943 int32_t nsHtml5TreeBuilder::findLastOrRoot(int32_t group) {
3944 for (int32_t i = currentPtr; i > 0; i--) {
3945 if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->getGroup() == group) {
3946 return i;
3949 return 0;
3952 bool nsHtml5TreeBuilder::addAttributesToBody(
3953 nsHtml5HtmlAttributes* attributes) {
3954 if (currentPtr >= 1) {
3955 nsHtml5StackNode* body = stack[1];
3956 if (body->getGroup() == nsHtml5TreeBuilder::BODY) {
3957 addAttributesToElement(body->node, attributes);
3958 return true;
3961 return false;
3964 void nsHtml5TreeBuilder::addAttributesToHtml(
3965 nsHtml5HtmlAttributes* attributes) {
3966 addAttributesToElement(stack[0]->node, attributes);
3969 void nsHtml5TreeBuilder::pushHeadPointerOntoStack() {
3970 MOZ_ASSERT(!!headPointer);
3971 MOZ_ASSERT(mode == AFTER_HEAD);
3973 silentPush(createStackNode(nsHtml5ElementName::ELT_HEAD, headPointer));
3976 void nsHtml5TreeBuilder::reconstructTheActiveFormattingElements() {
3977 if (listPtr == -1) {
3978 return;
3980 nsHtml5StackNode* mostRecent = listOfActiveFormattingElements[listPtr];
3981 if (!mostRecent || isInStack(mostRecent)) {
3982 return;
3984 int32_t entryPos = listPtr;
3985 for (;;) {
3986 entryPos--;
3987 if (entryPos == -1) {
3988 break;
3990 if (!listOfActiveFormattingElements[entryPos]) {
3991 break;
3993 if (isInStack(listOfActiveFormattingElements[entryPos])) {
3994 break;
3997 while (entryPos < listPtr) {
3998 entryPos++;
3999 nsHtml5StackNode* entry = listOfActiveFormattingElements[entryPos];
4000 nsHtml5StackNode* current = stack[currentPtr];
4001 nsIContentHandle* clone;
4002 if (current->isFosterParenting()) {
4003 clone = createAndInsertFosterParentedElement(
4004 kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(),
4005 htmlCreator(entry->getHtmlCreator()));
4006 } else {
4007 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4008 clone = createElement(kNameSpaceID_XHTML, entry->name,
4009 entry->attributes->cloneAttributes(), currentNode,
4010 htmlCreator(entry->getHtmlCreator()));
4011 appendElement(clone, currentNode);
4013 nsHtml5StackNode* entryClone = createStackNode(
4014 entry->getFlags(), entry->ns, entry->name, clone, entry->popName,
4015 entry->attributes, entry->getHtmlCreator());
4016 entry->dropAttributes();
4017 push(entryClone);
4018 listOfActiveFormattingElements[entryPos] = entryClone;
4019 entry->release(this);
4020 entryClone->retain();
4024 void nsHtml5TreeBuilder::notifyUnusedStackNode(int32_t idxInStackNodes) {
4025 if (idxInStackNodes < stackNodesIdx) {
4026 stackNodesIdx = idxInStackNodes;
4030 nsHtml5StackNode* nsHtml5TreeBuilder::getUnusedStackNode() {
4031 while (stackNodesIdx < numStackNodes) {
4032 if (stackNodes[stackNodesIdx]->isUnused()) {
4033 return stackNodes[stackNodesIdx++];
4035 stackNodesIdx++;
4037 if (stackNodesIdx < stackNodes.length) {
4038 stackNodes[stackNodesIdx] = new nsHtml5StackNode(stackNodesIdx);
4039 numStackNodes++;
4040 return stackNodes[stackNodesIdx++];
4042 jArray<nsHtml5StackNode*, int32_t> newStack =
4043 jArray<nsHtml5StackNode*, int32_t>::newJArray(stackNodes.length + 64);
4044 nsHtml5ArrayCopy::arraycopy(stackNodes, newStack, stackNodes.length);
4045 stackNodes = newStack;
4046 stackNodes[stackNodesIdx] = new nsHtml5StackNode(stackNodesIdx);
4047 numStackNodes++;
4048 return stackNodes[stackNodesIdx++];
4051 nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
4052 int32_t flags, int32_t ns, nsAtom* name, nsIContentHandle* node,
4053 nsAtom* popName, nsHtml5HtmlAttributes* attributes,
4054 mozilla::dom::HTMLContentCreatorFunction htmlCreator) {
4055 nsHtml5StackNode* instance = getUnusedStackNode();
4056 instance->setValues(flags, ns, name, node, popName, attributes, htmlCreator);
4057 return instance;
4060 nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
4061 nsHtml5ElementName* elementName, nsIContentHandle* node) {
4062 nsHtml5StackNode* instance = getUnusedStackNode();
4063 instance->setValues(elementName, node);
4064 return instance;
4067 nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
4068 nsHtml5ElementName* elementName, nsIContentHandle* node,
4069 nsHtml5HtmlAttributes* attributes) {
4070 nsHtml5StackNode* instance = getUnusedStackNode();
4071 instance->setValues(elementName, node, attributes);
4072 return instance;
4075 nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
4076 nsHtml5ElementName* elementName, nsIContentHandle* node, nsAtom* popName) {
4077 nsHtml5StackNode* instance = getUnusedStackNode();
4078 instance->setValues(elementName, node, popName);
4079 return instance;
4082 nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
4083 nsHtml5ElementName* elementName, nsAtom* popName, nsIContentHandle* node) {
4084 nsHtml5StackNode* instance = getUnusedStackNode();
4085 instance->setValues(elementName, popName, node);
4086 return instance;
4089 nsHtml5StackNode* nsHtml5TreeBuilder::createStackNode(
4090 nsHtml5ElementName* elementName, nsIContentHandle* node, nsAtom* popName,
4091 bool markAsIntegrationPoint) {
4092 nsHtml5StackNode* instance = getUnusedStackNode();
4093 instance->setValues(elementName, node, popName, markAsIntegrationPoint);
4094 return instance;
4097 void nsHtml5TreeBuilder::insertIntoFosterParent(nsIContentHandle* child) {
4098 int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
4099 int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
4100 if (templatePos >= tablePos) {
4101 appendElement(child, stack[templatePos]->node);
4102 return;
4104 nsHtml5StackNode* node = stack[tablePos];
4105 insertFosterParentedChild(child, node->node, stack[tablePos - 1]->node);
4108 nsIContentHandle* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
4109 int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes,
4110 nsHtml5ContentCreatorFunction creator) {
4111 return createAndInsertFosterParentedElement(ns, name, attributes, nullptr,
4112 creator);
4115 nsIContentHandle* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
4116 int32_t ns, nsAtom* name, nsHtml5HtmlAttributes* attributes,
4117 nsIContentHandle* form, nsHtml5ContentCreatorFunction creator) {
4118 int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
4119 int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
4120 if (templatePos >= tablePos) {
4121 nsIContentHandle* child = createElement(ns, name, attributes, form,
4122 stack[templatePos]->node, creator);
4123 appendElement(child, stack[templatePos]->node);
4124 return child;
4126 nsHtml5StackNode* node = stack[tablePos];
4127 return createAndInsertFosterParentedElement(
4128 ns, name, attributes, form, node->node, stack[tablePos - 1]->node,
4129 creator);
4132 bool nsHtml5TreeBuilder::isInStack(nsHtml5StackNode* node) {
4133 for (int32_t i = currentPtr; i >= 0; i--) {
4134 if (stack[i] == node) {
4135 return true;
4138 return false;
4141 void nsHtml5TreeBuilder::popTemplateMode() { templateModePtr--; }
4143 void nsHtml5TreeBuilder::pop() {
4144 nsHtml5StackNode* node = stack[currentPtr];
4145 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4146 currentPtr--;
4147 elementPopped(node->ns, node->popName, node->node);
4148 node->release(this);
4151 void nsHtml5TreeBuilder::popForeign(int32_t origPos, int32_t eltPos) {
4152 nsHtml5StackNode* node = stack[currentPtr];
4153 if (origPos != currentPtr || eltPos != currentPtr) {
4154 markMalformedIfScript(node->node);
4156 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4157 currentPtr--;
4158 elementPopped(node->ns, node->popName, node->node);
4159 node->release(this);
4162 void nsHtml5TreeBuilder::silentPop() {
4163 nsHtml5StackNode* node = stack[currentPtr];
4164 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4165 currentPtr--;
4166 node->release(this);
4169 void nsHtml5TreeBuilder::popOnEof() {
4170 nsHtml5StackNode* node = stack[currentPtr];
4171 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4172 currentPtr--;
4173 markMalformedIfScript(node->node);
4174 elementPopped(node->ns, node->popName, node->node);
4175 node->release(this);
4178 void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush(
4179 nsHtml5HtmlAttributes* attributes) {
4180 nsIContentHandle* elt = createHtmlElementSetAsRoot(attributes);
4181 nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HTML, elt);
4182 push(node);
4185 void nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush() {
4186 appendHtmlElementToDocumentAndPush(tokenizer->emptyAttributes());
4189 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(
4190 nsHtml5HtmlAttributes* attributes) {
4191 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4192 nsIContentHandle* elt =
4193 createElement(kNameSpaceID_XHTML, nsGkAtoms::head, attributes,
4194 currentNode, htmlCreator(NS_NewHTMLSharedElement));
4195 appendElement(elt, currentNode);
4196 headPointer = elt;
4197 nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HEAD, elt);
4198 push(node);
4201 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement(
4202 nsHtml5HtmlAttributes* attributes) {
4203 appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_BODY, attributes);
4206 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement() {
4207 appendToCurrentNodeAndPushBodyElement(tokenizer->emptyAttributes());
4210 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(
4211 nsHtml5HtmlAttributes* attributes) {
4212 nsIContentHandle* elt;
4213 nsHtml5StackNode* current = stack[currentPtr];
4214 if (current->isFosterParenting()) {
4215 elt = createAndInsertFosterParentedElement(
4216 kNameSpaceID_XHTML, nsGkAtoms::form, attributes,
4217 htmlCreator(NS_NewHTMLFormElement));
4218 } else {
4219 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4220 elt = createElement(kNameSpaceID_XHTML, nsGkAtoms::form, attributes,
4221 currentNode, htmlCreator(NS_NewHTMLFormElement));
4222 appendElement(elt, currentNode);
4224 if (!isTemplateContents()) {
4225 formPointer = elt;
4227 nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_FORM, elt);
4228 push(node);
4231 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(
4232 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
4233 nsHtml5HtmlAttributes* clone = attributes->cloneAttributes();
4234 nsIContentHandle* elt;
4235 nsHtml5StackNode* current = stack[currentPtr];
4236 if (current->isFosterParenting()) {
4237 elt = createAndInsertFosterParentedElement(
4238 kNameSpaceID_XHTML, elementName->getName(), attributes,
4239 htmlCreator(elementName->getHtmlCreator()));
4240 } else {
4241 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4242 elt =
4243 createElement(kNameSpaceID_XHTML, elementName->getName(), attributes,
4244 currentNode, htmlCreator(elementName->getHtmlCreator()));
4245 appendElement(elt, currentNode);
4247 nsHtml5StackNode* node = createStackNode(elementName, elt, clone);
4248 push(node);
4249 append(node);
4250 node->retain();
4253 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(
4254 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
4255 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4256 nsIContentHandle* elt =
4257 createElement(kNameSpaceID_XHTML, elementName->getName(), attributes,
4258 currentNode, htmlCreator(elementName->getHtmlCreator()));
4259 if (nsHtml5ElementName::ELT_TEMPLATE == elementName) {
4260 nsIContentHandle* root =
4261 getDeclarativeShadowRoot(currentNode, elt, attributes);
4262 if (root) {
4263 setDocumentFragmentForTemplate(elt, root);
4264 elt = root;
4265 } else {
4266 appendElement(elt, currentNode);
4267 elt = getDocumentFragmentForTemplate(elt);
4269 } else {
4270 appendElement(elt, currentNode);
4272 nsHtml5StackNode* node = createStackNode(elementName, elt);
4273 push(node);
4276 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
4277 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
4278 nsAtom* popName = elementName->getName();
4279 nsIContentHandle* elt;
4280 nsHtml5StackNode* current = stack[currentPtr];
4281 if (current->isFosterParenting()) {
4282 elt = createAndInsertFosterParentedElement(
4283 kNameSpaceID_XHTML, popName, attributes,
4284 htmlCreator(elementName->getHtmlCreator()));
4285 } else {
4286 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4287 elt = createElement(kNameSpaceID_XHTML, popName, attributes, currentNode,
4288 htmlCreator(elementName->getHtmlCreator()));
4289 appendElement(elt, currentNode);
4291 nsHtml5StackNode* node = createStackNode(elementName, elt, popName);
4292 push(node);
4295 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(
4296 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
4297 nsAtom* popName = elementName->getName();
4298 bool markAsHtmlIntegrationPoint = false;
4299 if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName &&
4300 annotationXmlEncodingPermitsHtml(attributes)) {
4301 markAsHtmlIntegrationPoint = true;
4303 nsIContentHandle* elt;
4304 nsHtml5StackNode* current = stack[currentPtr];
4305 if (current->isFosterParenting()) {
4306 elt = createAndInsertFosterParentedElement(
4307 kNameSpaceID_MathML, popName, attributes, htmlCreator(nullptr));
4308 } else {
4309 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4310 elt = createElement(kNameSpaceID_MathML, popName, attributes, currentNode,
4311 htmlCreator(nullptr));
4312 appendElement(elt, currentNode);
4314 nsHtml5StackNode* node =
4315 createStackNode(elementName, elt, popName, markAsHtmlIntegrationPoint);
4316 push(node);
4319 bool nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(
4320 nsHtml5HtmlAttributes* attributes) {
4321 nsHtml5String encoding =
4322 attributes->getValue(nsHtml5AttributeName::ATTR_ENCODING);
4323 if (!encoding) {
4324 return false;
4326 return nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
4327 "application/xhtml+xml", encoding) ||
4328 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
4329 "text/html", encoding);
4332 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(
4333 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
4334 nsAtom* popName = elementName->getCamelCaseName();
4335 nsIContentHandle* elt;
4336 nsHtml5StackNode* current = stack[currentPtr];
4337 if (current->isFosterParenting()) {
4338 elt = createAndInsertFosterParentedElement(
4339 kNameSpaceID_SVG, popName, attributes,
4340 svgCreator(elementName->getSvgCreator()));
4341 } else {
4342 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4343 elt = createElement(kNameSpaceID_SVG, popName, attributes, currentNode,
4344 svgCreator(elementName->getSvgCreator()));
4345 appendElement(elt, currentNode);
4347 nsHtml5StackNode* node = createStackNode(elementName, popName, elt);
4348 push(node);
4351 void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
4352 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes,
4353 nsIContentHandle* form) {
4354 nsIContentHandle* elt;
4355 nsIContentHandle* formOwner =
4356 !form || fragment || isTemplateContents() ? nullptr : form;
4357 nsHtml5StackNode* current = stack[currentPtr];
4358 if (current->isFosterParenting()) {
4359 elt = createAndInsertFosterParentedElement(
4360 kNameSpaceID_XHTML, elementName->getName(), attributes, formOwner,
4361 htmlCreator(elementName->getHtmlCreator()));
4362 } else {
4363 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4364 elt = createElement(kNameSpaceID_XHTML, elementName->getName(), attributes,
4365 formOwner, currentNode,
4366 htmlCreator(elementName->getHtmlCreator()));
4367 appendElement(elt, currentNode);
4369 nsHtml5StackNode* node = createStackNode(elementName, elt);
4370 push(node);
4373 void nsHtml5TreeBuilder::appendVoidElementToCurrent(
4374 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
4375 nsAtom* popName = elementName->getName();
4376 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4377 nsIContentHandle* elt =
4378 createElement(kNameSpaceID_XHTML, popName, attributes, currentNode,
4379 htmlCreator(elementName->getHtmlCreator()));
4380 appendElement(elt, currentNode);
4381 elementPushed(kNameSpaceID_XHTML, popName, elt);
4382 elementPopped(kNameSpaceID_XHTML, popName, elt);
4385 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
4386 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes,
4387 nsIContentHandle* form) {
4388 nsAtom* name = elementName->getName();
4389 nsIContentHandle* elt;
4390 nsIContentHandle* formOwner =
4391 !form || fragment || isTemplateContents() ? nullptr : form;
4392 nsHtml5StackNode* current = stack[currentPtr];
4393 if (current->isFosterParenting()) {
4394 elt = createAndInsertFosterParentedElement(
4395 kNameSpaceID_XHTML, name, attributes, formOwner,
4396 htmlCreator(elementName->getHtmlCreator()));
4397 } else {
4398 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4399 elt =
4400 createElement(kNameSpaceID_XHTML, name, attributes, formOwner,
4401 currentNode, htmlCreator(elementName->getHtmlCreator()));
4402 appendElement(elt, currentNode);
4404 elementPushed(kNameSpaceID_XHTML, name, elt);
4405 elementPopped(kNameSpaceID_XHTML, name, elt);
4408 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
4409 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
4410 nsAtom* popName = elementName->getName();
4411 nsIContentHandle* elt;
4412 nsHtml5StackNode* current = stack[currentPtr];
4413 if (current->isFosterParenting()) {
4414 elt = createAndInsertFosterParentedElement(
4415 kNameSpaceID_XHTML, popName, attributes,
4416 htmlCreator(elementName->getHtmlCreator()));
4417 } else {
4418 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4419 elt = createElement(kNameSpaceID_XHTML, popName, attributes, currentNode,
4420 htmlCreator(elementName->getHtmlCreator()));
4421 appendElement(elt, currentNode);
4423 elementPushed(kNameSpaceID_XHTML, popName, elt);
4424 elementPopped(kNameSpaceID_XHTML, popName, elt);
4427 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(
4428 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
4429 nsAtom* popName = elementName->getCamelCaseName();
4430 nsIContentHandle* elt;
4431 nsHtml5StackNode* current = stack[currentPtr];
4432 if (current->isFosterParenting()) {
4433 elt = createAndInsertFosterParentedElement(
4434 kNameSpaceID_SVG, popName, attributes,
4435 svgCreator(elementName->getSvgCreator()));
4436 } else {
4437 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4438 elt = createElement(kNameSpaceID_SVG, popName, attributes, currentNode,
4439 svgCreator(elementName->getSvgCreator()));
4440 appendElement(elt, currentNode);
4442 elementPushed(kNameSpaceID_SVG, popName, elt);
4443 elementPopped(kNameSpaceID_SVG, popName, elt);
4446 void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(
4447 nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) {
4448 nsAtom* popName = elementName->getName();
4449 nsIContentHandle* elt;
4450 nsHtml5StackNode* current = stack[currentPtr];
4451 if (current->isFosterParenting()) {
4452 elt = createAndInsertFosterParentedElement(
4453 kNameSpaceID_MathML, popName, attributes, htmlCreator(nullptr));
4454 } else {
4455 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4456 elt = createElement(kNameSpaceID_MathML, popName, attributes, currentNode,
4457 htmlCreator(nullptr));
4458 appendElement(elt, currentNode);
4460 elementPushed(kNameSpaceID_MathML, popName, elt);
4461 elementPopped(kNameSpaceID_MathML, popName, elt);
4464 void nsHtml5TreeBuilder::appendVoidInputToCurrent(
4465 nsHtml5HtmlAttributes* attributes, nsIContentHandle* form) {
4466 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4467 nsIContentHandle* elt =
4468 createElement(kNameSpaceID_XHTML, nsGkAtoms::input, attributes,
4469 !form || fragment || isTemplateContents() ? nullptr : form,
4470 currentNode, htmlCreator(NS_NewHTMLInputElement));
4471 appendElement(elt, currentNode);
4472 elementPushed(kNameSpaceID_XHTML, nsGkAtoms::input, elt);
4473 elementPopped(kNameSpaceID_XHTML, nsGkAtoms::input, elt);
4476 void nsHtml5TreeBuilder::appendVoidFormToCurrent(
4477 nsHtml5HtmlAttributes* attributes) {
4478 nsIContentHandle* currentNode = nodeFromStackWithBlinkCompat(currentPtr);
4479 nsIContentHandle* elt =
4480 createElement(kNameSpaceID_XHTML, nsGkAtoms::form, attributes,
4481 currentNode, htmlCreator(NS_NewHTMLFormElement));
4482 formPointer = elt;
4483 appendElement(elt, currentNode);
4484 elementPushed(kNameSpaceID_XHTML, nsGkAtoms::form, elt);
4485 elementPopped(kNameSpaceID_XHTML, nsGkAtoms::form, elt);
4488 void nsHtml5TreeBuilder::requestSuspension() {
4489 tokenizer->requestSuspension();
4493 bool nsHtml5TreeBuilder::isInForeign() {
4494 return currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML;
4497 bool nsHtml5TreeBuilder::isInForeignButNotHtmlOrMathTextIntegrationPoint() {
4498 if (currentPtr < 0) {
4499 return false;
4501 return !isSpecialParentInForeign(stack[currentPtr]);
4504 void nsHtml5TreeBuilder::setFragmentContext(nsAtom* context, int32_t ns,
4505 nsIContentHandle* node,
4506 bool quirks) {
4507 this->contextName = context;
4508 this->contextNamespace = ns;
4509 this->contextNode = node;
4510 this->fragment = (!!contextName);
4511 this->quirks = quirks;
4514 nsIContentHandle* nsHtml5TreeBuilder::currentNode() {
4515 return stack[currentPtr]->node;
4518 bool nsHtml5TreeBuilder::isScriptingEnabled() { return scriptingEnabled; }
4520 void nsHtml5TreeBuilder::setScriptingEnabled(bool scriptingEnabled) {
4521 this->scriptingEnabled = scriptingEnabled;
4524 void nsHtml5TreeBuilder::setForceNoQuirks(bool forceNoQuirks) {
4525 this->forceNoQuirks = forceNoQuirks;
4528 void nsHtml5TreeBuilder::setIsSrcdocDocument(bool isSrcdocDocument) {
4529 this->setForceNoQuirks(isSrcdocDocument);
4532 bool nsHtml5TreeBuilder::isAllowDeclarativeShadowRoots() {
4533 return allowDeclarativeShadowRoots;
4536 void nsHtml5TreeBuilder::setAllowDeclarativeShadowRoots(bool allow) {
4537 allowDeclarativeShadowRoots = allow;
4540 void nsHtml5TreeBuilder::flushCharacters() {
4541 if (charBufferLen > 0) {
4542 if ((mode == IN_TABLE || mode == IN_TABLE_BODY || mode == IN_ROW) &&
4543 charBufferContainsNonWhitespace()) {
4544 errNonSpaceInTable();
4545 reconstructTheActiveFormattingElements();
4546 if (!stack[currentPtr]->isFosterParenting()) {
4547 appendCharacters(currentNode(), charBuffer, 0, charBufferLen);
4548 charBufferLen = 0;
4549 return;
4551 int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
4552 int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
4553 if (templatePos >= tablePos) {
4554 appendCharacters(stack[templatePos]->node, charBuffer, 0,
4555 charBufferLen);
4556 charBufferLen = 0;
4557 return;
4559 nsHtml5StackNode* tableElt = stack[tablePos];
4560 insertFosterParentedCharacters(charBuffer, 0, charBufferLen,
4561 tableElt->node, stack[tablePos - 1]->node);
4562 charBufferLen = 0;
4563 return;
4565 appendCharacters(currentNode(), charBuffer, 0, charBufferLen);
4566 charBufferLen = 0;
4570 bool nsHtml5TreeBuilder::charBufferContainsNonWhitespace() {
4571 for (int32_t i = 0; i < charBufferLen; i++) {
4572 switch (charBuffer[i]) {
4573 case ' ':
4574 case '\t':
4575 case '\n':
4576 case '\r':
4577 case '\f': {
4578 continue;
4580 default: {
4581 return true;
4585 return false;
4588 nsAHtml5TreeBuilderState* nsHtml5TreeBuilder::newSnapshot() {
4589 jArray<nsHtml5StackNode*, int32_t> listCopy =
4590 jArray<nsHtml5StackNode*, int32_t>::newJArray(listPtr + 1);
4591 for (int32_t i = 0; i < listCopy.length; i++) {
4592 nsHtml5StackNode* node = listOfActiveFormattingElements[i];
4593 if (node) {
4594 nsHtml5StackNode* newNode = new nsHtml5StackNode(-1);
4595 newNode->setValues(node->getFlags(), node->ns, node->name, node->node,
4596 node->popName, node->attributes->cloneAttributes(),
4597 node->getHtmlCreator());
4598 listCopy[i] = newNode;
4599 } else {
4600 listCopy[i] = nullptr;
4603 jArray<nsHtml5StackNode*, int32_t> stackCopy =
4604 jArray<nsHtml5StackNode*, int32_t>::newJArray(currentPtr + 1);
4605 for (int32_t i = 0; i < stackCopy.length; i++) {
4606 nsHtml5StackNode* node = stack[i];
4607 int32_t listIndex = findInListOfActiveFormattingElements(node);
4608 if (listIndex == -1) {
4609 nsHtml5StackNode* newNode = new nsHtml5StackNode(-1);
4610 newNode->setValues(node->getFlags(), node->ns, node->name, node->node,
4611 node->popName, nullptr, node->getHtmlCreator());
4612 stackCopy[i] = newNode;
4613 } else {
4614 stackCopy[i] = listCopy[listIndex];
4615 stackCopy[i]->retain();
4618 jArray<int32_t, int32_t> templateModeStackCopy =
4619 jArray<int32_t, int32_t>::newJArray(templateModePtr + 1);
4620 nsHtml5ArrayCopy::arraycopy(templateModeStack, templateModeStackCopy,
4621 templateModeStackCopy.length);
4622 return new nsHtml5StateSnapshot(stackCopy, listCopy, templateModeStackCopy,
4623 formPointer, headPointer, mode, originalMode,
4624 framesetOk, needToDropLF, quirks);
4627 bool nsHtml5TreeBuilder::snapshotMatches(nsAHtml5TreeBuilderState* snapshot) {
4628 jArray<nsHtml5StackNode*, int32_t> stackCopy = snapshot->getStack();
4629 int32_t stackLen = snapshot->getStackLength();
4630 jArray<nsHtml5StackNode*, int32_t> listCopy =
4631 snapshot->getListOfActiveFormattingElements();
4632 int32_t listLen = snapshot->getListOfActiveFormattingElementsLength();
4633 jArray<int32_t, int32_t> templateModeStackCopy =
4634 snapshot->getTemplateModeStack();
4635 int32_t templateModeStackLen = snapshot->getTemplateModeStackLength();
4636 if (stackLen != currentPtr + 1 || listLen != listPtr + 1 ||
4637 templateModeStackLen != templateModePtr + 1 ||
4638 formPointer != snapshot->getFormPointer() ||
4639 headPointer != snapshot->getHeadPointer() ||
4640 mode != snapshot->getMode() ||
4641 originalMode != snapshot->getOriginalMode() ||
4642 framesetOk != snapshot->isFramesetOk() ||
4643 needToDropLF != snapshot->isNeedToDropLF() ||
4644 quirks != snapshot->isQuirks()) {
4645 return false;
4647 for (int32_t i = listLen - 1; i >= 0; i--) {
4648 if (!listCopy[i] && !listOfActiveFormattingElements[i]) {
4649 continue;
4650 } else if (!listCopy[i] || !listOfActiveFormattingElements[i]) {
4651 return false;
4653 if (listCopy[i]->node != listOfActiveFormattingElements[i]->node) {
4654 return false;
4657 for (int32_t i = stackLen - 1; i >= 0; i--) {
4658 if (stackCopy[i]->node != stack[i]->node) {
4659 return false;
4662 for (int32_t i = templateModeStackLen - 1; i >= 0; i--) {
4663 if (templateModeStackCopy[i] != templateModeStack[i]) {
4664 return false;
4667 return true;
4670 void nsHtml5TreeBuilder::loadState(nsAHtml5TreeBuilderState* snapshot) {
4671 mCurrentHtmlScriptCannotDocumentWriteOrBlock = false;
4672 jArray<nsHtml5StackNode*, int32_t> stackCopy = snapshot->getStack();
4673 int32_t stackLen = snapshot->getStackLength();
4674 jArray<nsHtml5StackNode*, int32_t> listCopy =
4675 snapshot->getListOfActiveFormattingElements();
4676 int32_t listLen = snapshot->getListOfActiveFormattingElementsLength();
4677 jArray<int32_t, int32_t> templateModeStackCopy =
4678 snapshot->getTemplateModeStack();
4679 int32_t templateModeStackLen = snapshot->getTemplateModeStackLength();
4680 for (int32_t i = 0; i <= listPtr; i++) {
4681 if (listOfActiveFormattingElements[i]) {
4682 listOfActiveFormattingElements[i]->release(this);
4685 if (listOfActiveFormattingElements.length < listLen) {
4686 listOfActiveFormattingElements =
4687 jArray<nsHtml5StackNode*, int32_t>::newJArray(listLen);
4689 listPtr = listLen - 1;
4690 for (int32_t i = 0; i <= currentPtr; i++) {
4691 stack[i]->release(this);
4693 if (stack.length < stackLen) {
4694 stack = jArray<nsHtml5StackNode*, int32_t>::newJArray(stackLen);
4696 currentPtr = stackLen - 1;
4697 if (templateModeStack.length < templateModeStackLen) {
4698 templateModeStack =
4699 jArray<int32_t, int32_t>::newJArray(templateModeStackLen);
4701 templateModePtr = templateModeStackLen - 1;
4702 for (int32_t i = 0; i < listLen; i++) {
4703 nsHtml5StackNode* node = listCopy[i];
4704 if (node) {
4705 nsHtml5StackNode* newNode = createStackNode(
4706 node->getFlags(), node->ns, node->name, node->node, node->popName,
4707 node->attributes->cloneAttributes(), node->getHtmlCreator());
4708 listOfActiveFormattingElements[i] = newNode;
4709 } else {
4710 listOfActiveFormattingElements[i] = nullptr;
4713 for (int32_t i = 0; i < stackLen; i++) {
4714 nsHtml5StackNode* node = stackCopy[i];
4715 int32_t listIndex = findInArray(node, listCopy);
4716 if (listIndex == -1) {
4717 nsHtml5StackNode* newNode =
4718 createStackNode(node->getFlags(), node->ns, node->name, node->node,
4719 node->popName, nullptr, node->getHtmlCreator());
4720 stack[i] = newNode;
4721 } else {
4722 stack[i] = listOfActiveFormattingElements[listIndex];
4723 stack[i]->retain();
4726 nsHtml5ArrayCopy::arraycopy(templateModeStackCopy, templateModeStack,
4727 templateModeStackLen);
4728 formPointer = snapshot->getFormPointer();
4729 headPointer = snapshot->getHeadPointer();
4730 mode = snapshot->getMode();
4731 originalMode = snapshot->getOriginalMode();
4732 framesetOk = snapshot->isFramesetOk();
4733 needToDropLF = snapshot->isNeedToDropLF();
4734 quirks = snapshot->isQuirks();
4737 int32_t nsHtml5TreeBuilder::findInArray(
4738 nsHtml5StackNode* node, jArray<nsHtml5StackNode*, int32_t> arr) {
4739 for (int32_t i = listPtr; i >= 0; i--) {
4740 if (node == arr[i]) {
4741 return i;
4744 return -1;
4747 nsIContentHandle* nsHtml5TreeBuilder::nodeFromStackWithBlinkCompat(
4748 int32_t stackPos) {
4749 if (stackPos > 511) {
4750 errDeepTree();
4751 return stack[511]->node;
4753 return stack[stackPos]->node;
4756 nsIContentHandle* nsHtml5TreeBuilder::getFormPointer() { return formPointer; }
4758 nsIContentHandle* nsHtml5TreeBuilder::getHeadPointer() { return headPointer; }
4760 jArray<nsHtml5StackNode*, int32_t>
4761 nsHtml5TreeBuilder::getListOfActiveFormattingElements() {
4762 return listOfActiveFormattingElements;
4765 jArray<nsHtml5StackNode*, int32_t> nsHtml5TreeBuilder::getStack() {
4766 return stack;
4769 jArray<int32_t, int32_t> nsHtml5TreeBuilder::getTemplateModeStack() {
4770 return templateModeStack;
4773 int32_t nsHtml5TreeBuilder::getMode() { return mode; }
4775 int32_t nsHtml5TreeBuilder::getOriginalMode() { return originalMode; }
4777 bool nsHtml5TreeBuilder::isFramesetOk() { return framesetOk; }
4779 bool nsHtml5TreeBuilder::isNeedToDropLF() { return needToDropLF; }
4781 bool nsHtml5TreeBuilder::isQuirks() { return quirks; }
4783 int32_t nsHtml5TreeBuilder::getListOfActiveFormattingElementsLength() {
4784 return listPtr + 1;
4787 int32_t nsHtml5TreeBuilder::getStackLength() { return currentPtr + 1; }
4789 int32_t nsHtml5TreeBuilder::getTemplateModeStackLength() {
4790 return templateModePtr + 1;
4793 void nsHtml5TreeBuilder::initializeStatics() {}
4795 void nsHtml5TreeBuilder::releaseStatics() {}
4797 #include "nsHtml5TreeBuilderCppSupplement.h"