Bug 1468361 [wpt PR 11478] - Add test run time to wptreport.json format, a=testonly
[gecko.git] / parser / html / nsHtml5TreeBuilder.cpp
blob37142bba6c954dec1f11757f940c530c25bce069
1 /*
2 * Copyright (c) 2007 Henri Sivonen
3 * Copyright (c) 2007-2015 Mozilla Foundation
4 * Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla
5 * Foundation, and Opera Software ASA.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
27 * THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
28 * Please edit TreeBuilder.java instead and regenerate.
31 #define nsHtml5TreeBuilder_cpp__
33 #include "nsContentUtils.h"
34 #include "nsAtom.h"
35 #include "nsHtml5AtomTable.h"
36 #include "nsITimer.h"
37 #include "nsHtml5String.h"
38 #include "nsNameSpaceManager.h"
39 #include "nsIContent.h"
40 #include "nsTraceRefcnt.h"
41 #include "jArray.h"
42 #include "nsHtml5DocumentMode.h"
43 #include "nsHtml5ArrayCopy.h"
44 #include "nsHtml5Parser.h"
45 #include "nsGkAtoms.h"
46 #include "nsHtml5TreeOperation.h"
47 #include "nsHtml5StateSnapshot.h"
48 #include "nsHtml5StackNode.h"
49 #include "nsHtml5TreeOpExecutor.h"
50 #include "nsHtml5StreamParser.h"
51 #include "nsAHtml5TreeBuilderState.h"
52 #include "nsHtml5Highlighter.h"
53 #include "nsHtml5PlainTextUtils.h"
54 #include "nsHtml5ViewSourceUtils.h"
55 #include "mozilla/Likely.h"
56 #include "nsIContentHandle.h"
57 #include "nsHtml5OplessBuilder.h"
59 #include "nsHtml5AttributeName.h"
60 #include "nsHtml5ElementName.h"
61 #include "nsHtml5Tokenizer.h"
62 #include "nsHtml5MetaScanner.h"
63 #include "nsHtml5StackNode.h"
64 #include "nsHtml5UTF16Buffer.h"
65 #include "nsHtml5StateSnapshot.h"
66 #include "nsHtml5Portability.h"
68 #include "nsHtml5TreeBuilder.h"
70 char16_t nsHtml5TreeBuilder::REPLACEMENT_CHARACTER[] = { 0xfffd };
71 static const char* const QUIRKY_PUBLIC_IDS_DATA[] = {
72 "+//silmaril//dtd html pro v0r11 19970101//",
73 "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
74 "-//as//dtd html 3.0 aswedit + extensions//",
75 "-//ietf//dtd html 2.0 level 1//",
76 "-//ietf//dtd html 2.0 level 2//",
77 "-//ietf//dtd html 2.0 strict level 1//",
78 "-//ietf//dtd html 2.0 strict level 2//",
79 "-//ietf//dtd html 2.0 strict//",
80 "-//ietf//dtd html 2.0//",
81 "-//ietf//dtd html 2.1e//",
82 "-//ietf//dtd html 3.0//",
83 "-//ietf//dtd html 3.2 final//",
84 "-//ietf//dtd html 3.2//",
85 "-//ietf//dtd html 3//",
86 "-//ietf//dtd html level 0//",
87 "-//ietf//dtd html level 1//",
88 "-//ietf//dtd html level 2//",
89 "-//ietf//dtd html level 3//",
90 "-//ietf//dtd html strict level 0//",
91 "-//ietf//dtd html strict level 1//",
92 "-//ietf//dtd html strict level 2//",
93 "-//ietf//dtd html strict level 3//",
94 "-//ietf//dtd html strict//",
95 "-//ietf//dtd html//",
96 "-//metrius//dtd metrius presentational//",
97 "-//microsoft//dtd internet explorer 2.0 html strict//",
98 "-//microsoft//dtd internet explorer 2.0 html//",
99 "-//microsoft//dtd internet explorer 2.0 tables//",
100 "-//microsoft//dtd internet explorer 3.0 html strict//",
101 "-//microsoft//dtd internet explorer 3.0 html//",
102 "-//microsoft//dtd internet explorer 3.0 tables//",
103 "-//netscape comm. corp.//dtd html//",
104 "-//netscape comm. corp.//dtd strict html//",
105 "-//o'reilly and associates//dtd html 2.0//",
106 "-//o'reilly and associates//dtd html extended 1.0//",
107 "-//o'reilly and associates//dtd html extended relaxed 1.0//",
108 "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html "
109 "4.0//",
110 "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
111 "-//spyglass//dtd html 2.0 extended//",
112 "-//sq//dtd html 2.0 hotmetal + extensions//",
113 "-//sun microsystems corp.//dtd hotjava html//",
114 "-//sun microsystems corp.//dtd hotjava strict html//",
115 "-//w3c//dtd html 3 1995-03-24//",
116 "-//w3c//dtd html 3.2 draft//",
117 "-//w3c//dtd html 3.2 final//",
118 "-//w3c//dtd html 3.2//",
119 "-//w3c//dtd html 3.2s draft//",
120 "-//w3c//dtd html 4.0 frameset//",
121 "-//w3c//dtd html 4.0 transitional//",
122 "-//w3c//dtd html experimental 19960712//",
123 "-//w3c//dtd html experimental 970421//",
124 "-//w3c//dtd w3 html//",
125 "-//w3o//dtd w3 html 3.0//",
126 "-//webtechs//dtd mozilla html 2.0//",
127 "-//webtechs//dtd mozilla html//"
129 staticJArray<const char*, int32_t> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = {
130 QUIRKY_PUBLIC_IDS_DATA,
131 MOZ_ARRAY_LENGTH(QUIRKY_PUBLIC_IDS_DATA)
133 void
134 nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self)
136 tokenizer = self;
137 stackNodes = jArray<nsHtml5StackNode*, int32_t>::newJArray(64);
138 stack = jArray<nsHtml5StackNode*, int32_t>::newJArray(64);
139 templateModeStack = jArray<int32_t, int32_t>::newJArray(64);
140 listOfActiveFormattingElements =
141 jArray<nsHtml5StackNode*, int32_t>::newJArray(64);
142 needToDropLF = false;
143 originalMode = INITIAL;
144 templateModePtr = -1;
145 stackNodesIdx = 0;
146 numStackNodes = 0;
147 currentPtr = -1;
148 listPtr = -1;
149 formPointer = nullptr;
150 headPointer = nullptr;
151 deepTreeSurrogateParent = nullptr;
152 start(fragment);
153 charBufferLen = 0;
154 charBuffer = nullptr;
155 framesetOk = true;
156 if (fragment) {
157 nsIContentHandle* elt;
158 if (contextNode) {
159 elt = contextNode;
160 } else {
161 elt = createHtmlElementSetAsRoot(tokenizer->emptyAttributes());
163 if (contextNamespace == kNameSpaceID_SVG) {
164 nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_SVG;
165 if (nsGkAtoms::title == contextName || nsGkAtoms::desc == contextName ||
166 nsGkAtoms::foreignObject == contextName) {
167 elementName = nsHtml5ElementName::ELT_FOREIGNOBJECT;
169 nsHtml5StackNode* node =
170 createStackNode(elementName, elementName->getCamelCaseName(), elt);
171 currentPtr++;
172 stack[currentPtr] = node;
173 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::DATA,
174 contextName);
175 mode = FRAMESET_OK;
176 } else if (contextNamespace == kNameSpaceID_MathML) {
177 nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_MATH;
178 if (nsGkAtoms::mi_ == contextName || nsGkAtoms::mo_ == contextName ||
179 nsGkAtoms::mn_ == contextName || nsGkAtoms::ms_ == contextName ||
180 nsGkAtoms::mtext_ == contextName) {
181 elementName = nsHtml5ElementName::ELT_MTEXT;
182 } else if (nsGkAtoms::annotation_xml_ == contextName) {
183 elementName = nsHtml5ElementName::ELT_ANNOTATION_XML;
185 nsHtml5StackNode* node =
186 createStackNode(elementName, elt, elementName->getName(), false);
187 currentPtr++;
188 stack[currentPtr] = node;
189 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::DATA,
190 contextName);
191 mode = FRAMESET_OK;
192 } else {
193 nsHtml5StackNode* node =
194 createStackNode(nsHtml5ElementName::ELT_HTML, elt);
195 currentPtr++;
196 stack[currentPtr] = node;
197 if (nsGkAtoms::_template == contextName) {
198 pushTemplateMode(IN_TEMPLATE);
200 resetTheInsertionMode();
201 formPointer = getFormPointerForContext(contextNode);
202 if (nsGkAtoms::title == contextName ||
203 nsGkAtoms::textarea == contextName) {
204 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
205 contextName);
206 } else if (nsGkAtoms::style == contextName ||
207 nsGkAtoms::xmp == contextName ||
208 nsGkAtoms::iframe == contextName ||
209 nsGkAtoms::noembed == contextName ||
210 nsGkAtoms::noframes == contextName ||
211 (scriptingEnabled && nsGkAtoms::noscript == contextName)) {
212 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
213 contextName);
214 } else if (nsGkAtoms::plaintext == contextName) {
215 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::PLAINTEXT,
216 contextName);
217 } else if (nsGkAtoms::script == contextName) {
218 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::SCRIPT_DATA,
219 contextName);
220 } else {
221 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::DATA,
222 contextName);
225 contextName = nullptr;
226 contextNode = nullptr;
227 } else {
228 mode = INITIAL;
229 if (tokenizer->isViewingXmlSource()) {
230 nsIContentHandle* elt = createElement(kNameSpaceID_SVG,
231 nsGkAtoms::svg,
232 tokenizer->emptyAttributes(),
233 nullptr,
234 svgCreator(NS_NewSVGSVGElement));
235 nsHtml5StackNode* node =
236 createStackNode(nsHtml5ElementName::ELT_SVG, nsGkAtoms::svg, elt);
237 currentPtr++;
238 stack[currentPtr] = node;
243 void
244 nsHtml5TreeBuilder::doctype(nsAtom* name,
245 nsHtml5String publicIdentifier,
246 nsHtml5String systemIdentifier,
247 bool forceQuirks)
249 needToDropLF = false;
250 if (!isInForeign() && mode == INITIAL) {
251 nsHtml5String emptyString = nsHtml5Portability::newEmptyString();
252 appendDoctypeToDocument(!name ? nsGkAtoms::_empty : name,
253 !publicIdentifier ? emptyString : publicIdentifier,
254 !systemIdentifier ? emptyString : systemIdentifier);
255 emptyString.Release();
256 if (isQuirky(name, publicIdentifier, systemIdentifier, forceQuirks)) {
257 errQuirkyDoctype();
258 documentModeInternal(
259 QUIRKS_MODE, publicIdentifier, systemIdentifier, false);
260 } else if (isAlmostStandards(publicIdentifier, systemIdentifier)) {
261 errAlmostStandardsDoctype();
262 documentModeInternal(
263 ALMOST_STANDARDS_MODE, publicIdentifier, systemIdentifier, false);
264 } else {
265 documentModeInternal(
266 STANDARDS_MODE, publicIdentifier, systemIdentifier, false);
268 mode = BEFORE_HTML;
269 return;
271 errStrayDoctype();
272 return;
275 void
276 nsHtml5TreeBuilder::comment(char16_t* buf, int32_t start, int32_t length)
278 needToDropLF = false;
279 if (!isInForeign()) {
280 switch (mode) {
281 case INITIAL:
282 case BEFORE_HTML:
283 case AFTER_AFTER_BODY:
284 case AFTER_AFTER_FRAMESET: {
285 appendCommentToDocument(buf, start, length);
286 return;
288 case AFTER_BODY: {
289 flushCharacters();
290 appendComment(stack[0]->node, buf, start, length);
291 return;
293 default: {
294 break;
298 flushCharacters();
299 appendComment(stack[currentPtr]->node, buf, start, length);
300 return;
303 void
304 nsHtml5TreeBuilder::characters(const char16_t* buf,
305 int32_t start,
306 int32_t length)
308 if (tokenizer->isViewingXmlSource()) {
309 return;
311 if (needToDropLF) {
312 needToDropLF = false;
313 if (buf[start] == '\n') {
314 start++;
315 length--;
316 if (!length) {
317 return;
321 switch (mode) {
322 case IN_BODY:
323 case IN_CELL:
324 case IN_CAPTION: {
325 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
326 reconstructTheActiveFormattingElements();
328 MOZ_FALLTHROUGH;
330 case TEXT: {
331 accumulateCharacters(buf, start, length);
332 return;
334 case IN_TABLE:
335 case IN_TABLE_BODY:
336 case IN_ROW: {
337 accumulateCharactersForced(buf, start, length);
338 return;
340 default: {
341 int32_t end = start + length;
342 for (int32_t i = start; i < end; i++) {
343 switch (buf[i]) {
344 case ' ':
345 case '\t':
346 case '\n':
347 case '\r':
348 case '\f': {
349 switch (mode) {
350 case INITIAL:
351 case BEFORE_HTML:
352 case BEFORE_HEAD: {
353 start = i + 1;
354 continue;
356 case IN_HEAD:
357 case IN_HEAD_NOSCRIPT:
358 case AFTER_HEAD:
359 case IN_COLUMN_GROUP:
360 case IN_FRAMESET:
361 case AFTER_FRAMESET: {
362 continue;
364 case FRAMESET_OK:
365 case IN_TEMPLATE:
366 case IN_BODY:
367 case IN_CELL:
368 case IN_CAPTION: {
369 if (start < i) {
370 accumulateCharacters(buf, start, i - start);
371 start = i;
373 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
374 flushCharacters();
375 reconstructTheActiveFormattingElements();
377 NS_HTML5_BREAK(charactersloop);
379 case IN_SELECT:
380 case IN_SELECT_IN_TABLE: {
381 NS_HTML5_BREAK(charactersloop);
383 case IN_TABLE:
384 case IN_TABLE_BODY:
385 case IN_ROW: {
386 accumulateCharactersForced(buf, i, 1);
387 start = i + 1;
388 continue;
390 case AFTER_BODY:
391 case AFTER_AFTER_BODY:
392 case AFTER_AFTER_FRAMESET: {
393 if (start < i) {
394 accumulateCharacters(buf, start, i - start);
395 start = i;
397 flushCharacters();
398 reconstructTheActiveFormattingElements();
399 continue;
402 MOZ_FALLTHROUGH_ASSERT();
404 default: {
405 switch (mode) {
406 case INITIAL: {
407 documentModeInternal(QUIRKS_MODE, nullptr, nullptr, false);
408 mode = BEFORE_HTML;
409 i--;
410 continue;
412 case BEFORE_HTML: {
413 appendHtmlElementToDocumentAndPush();
414 mode = BEFORE_HEAD;
415 i--;
416 continue;
418 case BEFORE_HEAD: {
419 if (start < i) {
420 accumulateCharacters(buf, start, i - start);
421 start = i;
423 flushCharacters();
424 appendToCurrentNodeAndPushHeadElement(
425 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
426 mode = IN_HEAD;
427 i--;
428 continue;
430 case IN_HEAD: {
431 if (start < i) {
432 accumulateCharacters(buf, start, i - start);
433 start = i;
435 flushCharacters();
436 pop();
437 mode = AFTER_HEAD;
438 i--;
439 continue;
441 case IN_HEAD_NOSCRIPT: {
442 if (start < i) {
443 accumulateCharacters(buf, start, i - start);
444 start = i;
446 errNonSpaceInNoscriptInHead();
447 flushCharacters();
448 pop();
449 mode = IN_HEAD;
450 i--;
451 continue;
453 case AFTER_HEAD: {
454 if (start < i) {
455 accumulateCharacters(buf, start, i - start);
456 start = i;
458 flushCharacters();
459 appendToCurrentNodeAndPushBodyElement();
460 mode = FRAMESET_OK;
461 i--;
462 continue;
464 case FRAMESET_OK: {
465 framesetOk = false;
466 mode = IN_BODY;
467 i--;
468 continue;
470 case IN_TEMPLATE:
471 case IN_BODY:
472 case IN_CELL:
473 case IN_CAPTION: {
474 if (start < i) {
475 accumulateCharacters(buf, start, i - start);
476 start = i;
478 if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
479 flushCharacters();
480 reconstructTheActiveFormattingElements();
482 NS_HTML5_BREAK(charactersloop);
484 case IN_TABLE:
485 case IN_TABLE_BODY:
486 case IN_ROW: {
487 accumulateCharactersForced(buf, i, 1);
488 start = i + 1;
489 continue;
491 case IN_COLUMN_GROUP: {
492 if (start < i) {
493 accumulateCharacters(buf, start, i - start);
494 start = i;
496 if (!currentPtr || stack[currentPtr]->getGroup() ==
497 nsHtml5TreeBuilder::TEMPLATE) {
498 errNonSpaceInColgroupInFragment();
499 start = i + 1;
500 continue;
502 flushCharacters();
503 pop();
504 mode = IN_TABLE;
505 i--;
506 continue;
508 case IN_SELECT:
509 case IN_SELECT_IN_TABLE: {
510 NS_HTML5_BREAK(charactersloop);
512 case AFTER_BODY: {
513 errNonSpaceAfterBody();
515 mode = framesetOk ? FRAMESET_OK : IN_BODY;
516 i--;
517 continue;
519 case IN_FRAMESET: {
520 if (start < i) {
521 accumulateCharacters(buf, start, i - start);
523 errNonSpaceInFrameset();
524 start = i + 1;
525 continue;
527 case AFTER_FRAMESET: {
528 if (start < i) {
529 accumulateCharacters(buf, start, i - start);
531 errNonSpaceAfterFrameset();
532 start = i + 1;
533 continue;
535 case AFTER_AFTER_BODY: {
536 errNonSpaceInTrailer();
537 mode = framesetOk ? FRAMESET_OK : IN_BODY;
538 i--;
539 continue;
541 case AFTER_AFTER_FRAMESET: {
542 if (start < i) {
543 accumulateCharacters(buf, start, i - start);
545 errNonSpaceInTrailer();
546 start = i + 1;
547 continue;
553 charactersloop_end:;
554 if (start < end) {
555 accumulateCharacters(buf, start, end - start);
561 void
562 nsHtml5TreeBuilder::zeroOriginatingReplacementCharacter()
564 if (mode == TEXT) {
565 accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
566 return;
568 if (currentPtr >= 0) {
569 if (isSpecialParentInForeign(stack[currentPtr])) {
570 return;
572 accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
576 void
577 nsHtml5TreeBuilder::eof()
579 flushCharacters();
580 for (;;) {
581 switch (mode) {
582 case INITIAL: {
583 documentModeInternal(QUIRKS_MODE, nullptr, nullptr, false);
584 mode = BEFORE_HTML;
585 continue;
587 case BEFORE_HTML: {
588 appendHtmlElementToDocumentAndPush();
589 mode = BEFORE_HEAD;
590 continue;
592 case BEFORE_HEAD: {
593 appendToCurrentNodeAndPushHeadElement(
594 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
595 mode = IN_HEAD;
596 continue;
598 case IN_HEAD: {
599 while (currentPtr > 0) {
600 popOnEof();
602 mode = AFTER_HEAD;
603 continue;
605 case IN_HEAD_NOSCRIPT: {
606 while (currentPtr > 1) {
607 popOnEof();
609 mode = IN_HEAD;
610 continue;
612 case AFTER_HEAD: {
613 appendToCurrentNodeAndPushBodyElement();
614 mode = IN_BODY;
615 continue;
617 case IN_TABLE_BODY:
618 case IN_ROW:
619 case IN_TABLE:
620 case IN_SELECT_IN_TABLE:
621 case IN_SELECT:
622 case IN_COLUMN_GROUP:
623 case FRAMESET_OK:
624 case IN_CAPTION:
625 case IN_CELL:
626 case IN_BODY: {
627 if (isTemplateModeStackEmpty()) {
628 NS_HTML5_BREAK(eofloop);
630 MOZ_FALLTHROUGH;
632 case IN_TEMPLATE: {
633 int32_t eltPos = findLast(nsGkAtoms::_template);
634 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
635 MOZ_ASSERT(fragment);
636 NS_HTML5_BREAK(eofloop);
638 if (MOZ_UNLIKELY(mViewSource)) {
639 errUnclosedElements(eltPos, nsGkAtoms::_template);
641 while (currentPtr >= eltPos) {
642 pop();
644 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
645 popTemplateMode();
646 resetTheInsertionMode();
647 continue;
649 case TEXT: {
650 if (originalMode == AFTER_HEAD) {
651 popOnEof();
653 popOnEof();
654 mode = originalMode;
655 continue;
657 case IN_FRAMESET: {
658 NS_HTML5_BREAK(eofloop);
660 case AFTER_BODY:
661 case AFTER_FRAMESET:
662 case AFTER_AFTER_BODY:
663 case AFTER_AFTER_FRAMESET:
664 default: {
665 NS_HTML5_BREAK(eofloop);
669 eofloop_end:;
670 while (currentPtr > 0) {
671 popOnEof();
673 if (!fragment) {
674 popOnEof();
678 void
679 nsHtml5TreeBuilder::endTokenization()
681 formPointer = nullptr;
682 headPointer = nullptr;
683 deepTreeSurrogateParent = nullptr;
684 templateModeStack = nullptr;
685 if (stack) {
686 while (currentPtr > -1) {
687 stack[currentPtr]->release(this);
688 currentPtr--;
690 stack = nullptr;
692 if (listOfActiveFormattingElements) {
693 while (listPtr > -1) {
694 if (listOfActiveFormattingElements[listPtr]) {
695 listOfActiveFormattingElements[listPtr]->release(this);
697 listPtr--;
699 listOfActiveFormattingElements = nullptr;
701 if (stackNodes) {
702 for (int32_t i = 0; i < numStackNodes; i++) {
703 MOZ_ASSERT(stackNodes[i]->isUnused());
704 delete stackNodes[i];
706 numStackNodes = 0;
707 stackNodesIdx = 0;
708 stackNodes = nullptr;
710 charBuffer = nullptr;
711 end();
714 void
715 nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName,
716 nsHtml5HtmlAttributes* attributes,
717 bool selfClosing)
719 flushCharacters();
720 int32_t eltPos;
721 needToDropLF = false;
722 starttagloop:
723 for (;;) {
724 int32_t group = elementName->getGroup();
725 nsAtom* name = elementName->getName();
726 if (isInForeign()) {
727 nsHtml5StackNode* currentNode = stack[currentPtr];
728 int32_t currNs = currentNode->ns;
729 if (!(currentNode->isHtmlIntegrationPoint() ||
730 (currNs == kNameSpaceID_MathML &&
731 ((currentNode->getGroup() == MI_MO_MN_MS_MTEXT &&
732 group != MGLYPH_OR_MALIGNMARK) ||
733 (currentNode->getGroup() == ANNOTATION_XML && group == SVG))))) {
734 switch (group) {
735 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
736 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
737 case BODY:
738 case BR:
739 case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR:
740 case DD_OR_DT:
741 case UL_OR_OL_OR_DL:
742 case EMBED:
743 case IMG:
744 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
745 case HEAD:
746 case HR:
747 case LI:
748 case META:
749 case NOBR:
750 case P:
751 case PRE_OR_LISTING:
752 case TABLE:
753 case FONT: {
754 if (!(group == FONT &&
755 !(attributes->contains(nsHtml5AttributeName::ATTR_COLOR) ||
756 attributes->contains(nsHtml5AttributeName::ATTR_FACE) ||
757 attributes->contains(nsHtml5AttributeName::ATTR_SIZE)))) {
758 errHtmlStartTagInForeignContext(name);
759 if (!fragment) {
760 while (!isSpecialParentInForeign(stack[currentPtr])) {
761 pop();
763 NS_HTML5_CONTINUE(starttagloop);
766 MOZ_FALLTHROUGH;
768 default: {
769 if (kNameSpaceID_SVG == currNs) {
770 attributes->adjustForSvg();
771 if (selfClosing) {
772 appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
773 selfClosing = false;
774 } else {
775 appendToCurrentNodeAndPushElementMayFosterSVG(elementName,
776 attributes);
778 attributes = nullptr;
779 NS_HTML5_BREAK(starttagloop);
780 } else {
781 attributes->adjustForMath();
782 if (selfClosing) {
783 appendVoidElementToCurrentMayFosterMathML(elementName,
784 attributes);
785 selfClosing = false;
786 } else {
787 appendToCurrentNodeAndPushElementMayFosterMathML(elementName,
788 attributes);
790 attributes = nullptr;
791 NS_HTML5_BREAK(starttagloop);
797 switch (mode) {
798 case IN_TEMPLATE: {
799 switch (group) {
800 case COL: {
801 popTemplateMode();
802 pushTemplateMode(IN_COLUMN_GROUP);
803 mode = IN_COLUMN_GROUP;
804 continue;
806 case CAPTION:
807 case COLGROUP:
808 case TBODY_OR_THEAD_OR_TFOOT: {
809 popTemplateMode();
810 pushTemplateMode(IN_TABLE);
811 mode = IN_TABLE;
812 continue;
814 case TR: {
815 popTemplateMode();
816 pushTemplateMode(IN_TABLE_BODY);
817 mode = IN_TABLE_BODY;
818 continue;
820 case TD_OR_TH: {
821 popTemplateMode();
822 pushTemplateMode(IN_ROW);
823 mode = IN_ROW;
824 continue;
826 case META: {
827 checkMetaCharset(attributes);
828 appendVoidElementToCurrentMayFoster(elementName, attributes);
829 selfClosing = false;
830 attributes = nullptr;
831 NS_HTML5_BREAK(starttagloop);
833 case TITLE: {
834 startTagTitleInHead(elementName, attributes);
835 attributes = nullptr;
836 NS_HTML5_BREAK(starttagloop);
838 case BASE:
839 case LINK_OR_BASEFONT_OR_BGSOUND: {
840 appendVoidElementToCurrentMayFoster(elementName, attributes);
841 selfClosing = false;
842 attributes = nullptr;
843 NS_HTML5_BREAK(starttagloop);
845 case SCRIPT: {
846 startTagScriptInHead(elementName, attributes);
847 attributes = nullptr;
848 NS_HTML5_BREAK(starttagloop);
850 case NOFRAMES:
851 case STYLE: {
852 startTagGenericRawText(elementName, attributes);
853 attributes = nullptr;
854 NS_HTML5_BREAK(starttagloop);
856 case TEMPLATE: {
857 startTagTemplateInHead(elementName, attributes);
858 attributes = nullptr;
859 NS_HTML5_BREAK(starttagloop);
861 default: {
862 popTemplateMode();
863 pushTemplateMode(IN_BODY);
864 mode = IN_BODY;
865 continue;
869 case IN_ROW: {
870 switch (group) {
871 case TD_OR_TH: {
872 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TR));
873 appendToCurrentNodeAndPushElement(elementName, attributes);
874 mode = IN_CELL;
875 insertMarker();
876 attributes = nullptr;
877 NS_HTML5_BREAK(starttagloop);
879 case CAPTION:
880 case COL:
881 case COLGROUP:
882 case TBODY_OR_THEAD_OR_TFOOT:
883 case TR: {
884 eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
885 if (!eltPos) {
886 MOZ_ASSERT(fragment || isTemplateContents());
887 errNoTableRowToClose();
888 NS_HTML5_BREAK(starttagloop);
890 clearStackBackTo(eltPos);
891 pop();
892 mode = IN_TABLE_BODY;
893 continue;
895 default:; // fall through
897 MOZ_FALLTHROUGH;
899 case IN_TABLE_BODY: {
900 switch (group) {
901 case TR: {
902 clearStackBackTo(
903 findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
904 appendToCurrentNodeAndPushElement(elementName, attributes);
905 mode = IN_ROW;
906 attributes = nullptr;
907 NS_HTML5_BREAK(starttagloop);
909 case TD_OR_TH: {
910 errStartTagInTableBody(name);
911 clearStackBackTo(
912 findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
913 appendToCurrentNodeAndPushElement(
914 nsHtml5ElementName::ELT_TR,
915 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
916 mode = IN_ROW;
917 continue;
919 case CAPTION:
920 case COL:
921 case COLGROUP:
922 case TBODY_OR_THEAD_OR_TFOOT: {
923 eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
924 if (!eltPos || stack[eltPos]->getGroup() == TEMPLATE) {
925 MOZ_ASSERT(fragment || isTemplateContents());
926 errStrayStartTag(name);
927 NS_HTML5_BREAK(starttagloop);
928 } else {
929 clearStackBackTo(eltPos);
930 pop();
931 mode = IN_TABLE;
932 continue;
935 default:; // fall through
937 MOZ_FALLTHROUGH;
939 case IN_TABLE: {
940 for (;;) {
941 switch (group) {
942 case CAPTION: {
943 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
944 insertMarker();
945 appendToCurrentNodeAndPushElement(elementName, attributes);
946 mode = IN_CAPTION;
947 attributes = nullptr;
948 NS_HTML5_BREAK(starttagloop);
950 case COLGROUP: {
951 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
952 appendToCurrentNodeAndPushElement(elementName, attributes);
953 mode = IN_COLUMN_GROUP;
954 attributes = nullptr;
955 NS_HTML5_BREAK(starttagloop);
957 case COL: {
958 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
959 appendToCurrentNodeAndPushElement(
960 nsHtml5ElementName::ELT_COLGROUP,
961 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
962 mode = IN_COLUMN_GROUP;
963 NS_HTML5_CONTINUE(starttagloop);
965 case TBODY_OR_THEAD_OR_TFOOT: {
966 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
967 appendToCurrentNodeAndPushElement(elementName, attributes);
968 mode = IN_TABLE_BODY;
969 attributes = nullptr;
970 NS_HTML5_BREAK(starttagloop);
972 case TR:
973 case TD_OR_TH: {
974 clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
975 appendToCurrentNodeAndPushElement(
976 nsHtml5ElementName::ELT_TBODY,
977 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
978 mode = IN_TABLE_BODY;
979 NS_HTML5_CONTINUE(starttagloop);
981 case TEMPLATE: {
982 NS_HTML5_BREAK(intableloop);
984 case TABLE: {
985 errTableSeenWhileTableOpen();
986 eltPos = findLastInTableScope(name);
987 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
988 MOZ_ASSERT(fragment || isTemplateContents());
989 NS_HTML5_BREAK(starttagloop);
991 generateImpliedEndTags();
992 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsGkAtoms::table)) {
993 errNoCheckUnclosedElementsOnStack();
995 while (currentPtr >= eltPos) {
996 pop();
998 resetTheInsertionMode();
999 NS_HTML5_CONTINUE(starttagloop);
1001 case SCRIPT: {
1002 appendToCurrentNodeAndPushElement(elementName, attributes);
1003 originalMode = mode;
1004 mode = TEXT;
1005 tokenizer->setStateAndEndTagExpectation(
1006 nsHtml5Tokenizer::SCRIPT_DATA, elementName);
1007 attributes = nullptr;
1008 NS_HTML5_BREAK(starttagloop);
1010 case STYLE: {
1011 appendToCurrentNodeAndPushElement(elementName, attributes);
1012 originalMode = mode;
1013 mode = TEXT;
1014 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
1015 elementName);
1016 attributes = nullptr;
1017 NS_HTML5_BREAK(starttagloop);
1019 case INPUT: {
1020 errStartTagInTable(name);
1021 if (!nsHtml5Portability::
1022 lowerCaseLiteralEqualsIgnoreAsciiCaseString(
1023 "hidden",
1024 attributes->getValue(nsHtml5AttributeName::ATTR_TYPE))) {
1025 NS_HTML5_BREAK(intableloop);
1027 appendVoidInputToCurrent(attributes, formPointer);
1028 selfClosing = false;
1029 attributes = nullptr;
1030 NS_HTML5_BREAK(starttagloop);
1032 case FORM: {
1033 if (!!formPointer || isTemplateContents()) {
1034 errFormWhenFormOpen();
1035 NS_HTML5_BREAK(starttagloop);
1036 } else {
1037 errStartTagInTable(name);
1038 appendVoidFormToCurrent(attributes);
1039 attributes = nullptr;
1040 NS_HTML5_BREAK(starttagloop);
1043 default: {
1044 errStartTagInTable(name);
1045 NS_HTML5_BREAK(intableloop);
1049 intableloop_end:;
1050 MOZ_FALLTHROUGH;
1052 case IN_CAPTION: {
1053 switch (group) {
1054 case CAPTION:
1055 case COL:
1056 case COLGROUP:
1057 case TBODY_OR_THEAD_OR_TFOOT:
1058 case TR:
1059 case TD_OR_TH: {
1060 errStrayStartTag(name);
1061 eltPos = findLastInTableScope(nsGkAtoms::caption);
1062 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
1063 NS_HTML5_BREAK(starttagloop);
1065 generateImpliedEndTags();
1066 if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
1067 errNoCheckUnclosedElementsOnStack();
1069 while (currentPtr >= eltPos) {
1070 pop();
1072 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
1073 mode = IN_TABLE;
1074 continue;
1076 default:; // fall through
1078 MOZ_FALLTHROUGH;
1080 case IN_CELL: {
1081 switch (group) {
1082 case CAPTION:
1083 case COL:
1084 case COLGROUP:
1085 case TBODY_OR_THEAD_OR_TFOOT:
1086 case TR:
1087 case TD_OR_TH: {
1088 eltPos = findLastInTableScopeTdTh();
1089 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
1090 errNoCellToClose();
1091 NS_HTML5_BREAK(starttagloop);
1092 } else {
1093 closeTheCell(eltPos);
1094 continue;
1097 default:; // fall through
1099 MOZ_FALLTHROUGH;
1101 case FRAMESET_OK: {
1102 switch (group) {
1103 case FRAMESET: {
1104 if (mode == FRAMESET_OK) {
1105 if (!currentPtr || stack[1]->getGroup() != BODY) {
1106 MOZ_ASSERT(fragment || isTemplateContents());
1107 errStrayStartTag(name);
1108 NS_HTML5_BREAK(starttagloop);
1109 } else {
1110 errFramesetStart();
1111 detachFromParent(stack[1]->node);
1112 while (currentPtr > 0) {
1113 pop();
1115 appendToCurrentNodeAndPushElement(elementName, attributes);
1116 mode = IN_FRAMESET;
1117 attributes = nullptr;
1118 NS_HTML5_BREAK(starttagloop);
1120 } else {
1121 errStrayStartTag(name);
1122 NS_HTML5_BREAK(starttagloop);
1125 case PRE_OR_LISTING:
1126 case LI:
1127 case DD_OR_DT:
1128 case BUTTON:
1129 case MARQUEE_OR_APPLET:
1130 case OBJECT:
1131 case TABLE:
1132 case AREA_OR_WBR:
1133 case BR:
1134 case EMBED:
1135 case IMG:
1136 case INPUT:
1137 case KEYGEN:
1138 case HR:
1139 case TEXTAREA:
1140 case XMP:
1141 case IFRAME:
1142 case SELECT: {
1143 if (mode == FRAMESET_OK &&
1144 !(group == INPUT &&
1145 nsHtml5Portability::
1146 lowerCaseLiteralEqualsIgnoreAsciiCaseString(
1147 "hidden",
1148 attributes->getValue(nsHtml5AttributeName::ATTR_TYPE)))) {
1149 framesetOk = false;
1150 mode = IN_BODY;
1152 MOZ_FALLTHROUGH;
1154 default:; // fall through
1156 MOZ_FALLTHROUGH;
1158 case IN_BODY: {
1159 for (;;) {
1160 switch (group) {
1161 case HTML: {
1162 errStrayStartTag(name);
1163 if (!fragment && !isTemplateContents()) {
1164 addAttributesToHtml(attributes);
1165 attributes = nullptr;
1167 NS_HTML5_BREAK(starttagloop);
1169 case BASE:
1170 case LINK_OR_BASEFONT_OR_BGSOUND:
1171 case META:
1172 case STYLE:
1173 case SCRIPT:
1174 case TITLE:
1175 case TEMPLATE: {
1176 NS_HTML5_BREAK(inbodyloop);
1178 case BODY: {
1179 if (!currentPtr || stack[1]->getGroup() != BODY ||
1180 isTemplateContents()) {
1181 MOZ_ASSERT(fragment || isTemplateContents());
1182 errStrayStartTag(name);
1183 NS_HTML5_BREAK(starttagloop);
1185 errFooSeenWhenFooOpen(name);
1186 framesetOk = false;
1187 if (mode == FRAMESET_OK) {
1188 mode = IN_BODY;
1190 if (addAttributesToBody(attributes)) {
1191 attributes = nullptr;
1193 NS_HTML5_BREAK(starttagloop);
1195 case P:
1196 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
1197 case UL_OR_OL_OR_DL:
1198 case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY: {
1199 implicitlyCloseP();
1200 appendToCurrentNodeAndPushElementMayFoster(elementName,
1201 attributes);
1202 attributes = nullptr;
1203 NS_HTML5_BREAK(starttagloop);
1205 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: {
1206 implicitlyCloseP();
1207 if (stack[currentPtr]->getGroup() ==
1208 H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
1209 errHeadingWhenHeadingOpen();
1210 pop();
1212 appendToCurrentNodeAndPushElementMayFoster(elementName,
1213 attributes);
1214 attributes = nullptr;
1215 NS_HTML5_BREAK(starttagloop);
1217 case FIELDSET: {
1218 implicitlyCloseP();
1219 appendToCurrentNodeAndPushElementMayFoster(
1220 elementName, attributes, formPointer);
1221 attributes = nullptr;
1222 NS_HTML5_BREAK(starttagloop);
1224 case PRE_OR_LISTING: {
1225 implicitlyCloseP();
1226 appendToCurrentNodeAndPushElementMayFoster(elementName,
1227 attributes);
1228 needToDropLF = true;
1229 attributes = nullptr;
1230 NS_HTML5_BREAK(starttagloop);
1232 case FORM: {
1233 if (!!formPointer && !isTemplateContents()) {
1234 errFormWhenFormOpen();
1235 NS_HTML5_BREAK(starttagloop);
1236 } else {
1237 implicitlyCloseP();
1238 appendToCurrentNodeAndPushFormElementMayFoster(attributes);
1239 attributes = nullptr;
1240 NS_HTML5_BREAK(starttagloop);
1243 case LI:
1244 case DD_OR_DT: {
1245 eltPos = currentPtr;
1246 for (;;) {
1247 nsHtml5StackNode* node = stack[eltPos];
1248 if (node->getGroup() == group) {
1249 generateImpliedEndTagsExceptFor(node->name);
1250 if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
1251 errUnclosedElementsImplied(eltPos, name);
1253 while (currentPtr >= eltPos) {
1254 pop();
1256 break;
1257 } else if (!eltPos || (node->isSpecial() &&
1258 (node->ns != kNameSpaceID_XHTML ||
1259 (node->name != nsGkAtoms::p &&
1260 node->name != nsGkAtoms::address &&
1261 node->name != nsGkAtoms::div)))) {
1262 break;
1264 eltPos--;
1266 implicitlyCloseP();
1267 appendToCurrentNodeAndPushElementMayFoster(elementName,
1268 attributes);
1269 attributes = nullptr;
1270 NS_HTML5_BREAK(starttagloop);
1272 case PLAINTEXT: {
1273 implicitlyCloseP();
1274 appendToCurrentNodeAndPushElementMayFoster(elementName,
1275 attributes);
1276 tokenizer->setStateAndEndTagExpectation(
1277 nsHtml5Tokenizer::PLAINTEXT, elementName);
1278 attributes = nullptr;
1279 NS_HTML5_BREAK(starttagloop);
1281 case A: {
1282 int32_t activeAPos =
1283 findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
1284 nsGkAtoms::a);
1285 if (activeAPos != -1) {
1286 errFooSeenWhenFooOpen(name);
1287 nsHtml5StackNode* activeA =
1288 listOfActiveFormattingElements[activeAPos];
1289 activeA->retain();
1290 adoptionAgencyEndTag(nsGkAtoms::a);
1291 removeFromStack(activeA);
1292 activeAPos = findInListOfActiveFormattingElements(activeA);
1293 if (activeAPos != -1) {
1294 removeFromListOfActiveFormattingElements(activeAPos);
1296 activeA->release(this);
1298 reconstructTheActiveFormattingElements();
1299 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
1300 attributes);
1301 attributes = nullptr;
1302 NS_HTML5_BREAK(starttagloop);
1304 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
1305 case FONT: {
1306 reconstructTheActiveFormattingElements();
1307 maybeForgetEarlierDuplicateFormattingElement(
1308 elementName->getName(), attributes);
1309 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
1310 attributes);
1311 attributes = nullptr;
1312 NS_HTML5_BREAK(starttagloop);
1314 case NOBR: {
1315 reconstructTheActiveFormattingElements();
1316 if (nsHtml5TreeBuilder::NOT_FOUND_ON_STACK !=
1317 findLastInScope(nsGkAtoms::nobr)) {
1318 errFooSeenWhenFooOpen(name);
1319 adoptionAgencyEndTag(nsGkAtoms::nobr);
1320 reconstructTheActiveFormattingElements();
1322 appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
1323 attributes);
1324 attributes = nullptr;
1325 NS_HTML5_BREAK(starttagloop);
1327 case BUTTON: {
1328 eltPos = findLastInScope(name);
1329 if (eltPos != nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
1330 errFooSeenWhenFooOpen(name);
1331 generateImpliedEndTags();
1332 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
1333 errUnclosedElementsImplied(eltPos, name);
1335 while (currentPtr >= eltPos) {
1336 pop();
1338 NS_HTML5_CONTINUE(starttagloop);
1339 } else {
1340 reconstructTheActiveFormattingElements();
1341 appendToCurrentNodeAndPushElementMayFoster(
1342 elementName, attributes, formPointer);
1343 attributes = nullptr;
1344 NS_HTML5_BREAK(starttagloop);
1347 case OBJECT: {
1348 reconstructTheActiveFormattingElements();
1349 appendToCurrentNodeAndPushElementMayFoster(
1350 elementName, attributes, formPointer);
1351 insertMarker();
1352 attributes = nullptr;
1353 NS_HTML5_BREAK(starttagloop);
1355 case MARQUEE_OR_APPLET: {
1356 reconstructTheActiveFormattingElements();
1357 appendToCurrentNodeAndPushElementMayFoster(elementName,
1358 attributes);
1359 insertMarker();
1360 attributes = nullptr;
1361 NS_HTML5_BREAK(starttagloop);
1363 case TABLE: {
1364 if (!quirks) {
1365 implicitlyCloseP();
1367 appendToCurrentNodeAndPushElementMayFoster(elementName,
1368 attributes);
1369 mode = IN_TABLE;
1370 attributes = nullptr;
1371 NS_HTML5_BREAK(starttagloop);
1373 case BR:
1374 case EMBED:
1375 case AREA_OR_WBR: {
1376 reconstructTheActiveFormattingElements();
1377 MOZ_FALLTHROUGH;
1379 #ifdef ENABLE_VOID_MENUITEM
1380 case MENUITEM:
1381 #endif
1382 case PARAM_OR_SOURCE_OR_TRACK: {
1383 appendVoidElementToCurrentMayFoster(elementName, attributes);
1384 selfClosing = false;
1385 attributes = nullptr;
1386 NS_HTML5_BREAK(starttagloop);
1388 case HR: {
1389 implicitlyCloseP();
1390 appendVoidElementToCurrentMayFoster(elementName, attributes);
1391 selfClosing = false;
1392 attributes = nullptr;
1393 NS_HTML5_BREAK(starttagloop);
1395 case IMAGE: {
1396 errImage();
1397 elementName = nsHtml5ElementName::ELT_IMG;
1398 NS_HTML5_CONTINUE(starttagloop);
1400 case IMG:
1401 case KEYGEN:
1402 case INPUT: {
1403 reconstructTheActiveFormattingElements();
1404 appendVoidElementToCurrentMayFoster(
1405 elementName, attributes, formPointer);
1406 selfClosing = false;
1407 attributes = nullptr;
1408 NS_HTML5_BREAK(starttagloop);
1410 case TEXTAREA: {
1411 appendToCurrentNodeAndPushElementMayFoster(
1412 elementName, attributes, formPointer);
1413 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
1414 elementName);
1415 originalMode = mode;
1416 mode = TEXT;
1417 needToDropLF = true;
1418 attributes = nullptr;
1419 NS_HTML5_BREAK(starttagloop);
1421 case XMP: {
1422 implicitlyCloseP();
1423 reconstructTheActiveFormattingElements();
1424 appendToCurrentNodeAndPushElementMayFoster(elementName,
1425 attributes);
1426 originalMode = mode;
1427 mode = TEXT;
1428 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
1429 elementName);
1430 attributes = nullptr;
1431 NS_HTML5_BREAK(starttagloop);
1433 case NOSCRIPT: {
1434 if (!scriptingEnabled) {
1435 reconstructTheActiveFormattingElements();
1436 appendToCurrentNodeAndPushElementMayFoster(elementName,
1437 attributes);
1438 attributes = nullptr;
1439 NS_HTML5_BREAK(starttagloop);
1441 MOZ_FALLTHROUGH;
1443 case NOFRAMES:
1444 case IFRAME:
1445 case NOEMBED: {
1446 startTagGenericRawText(elementName, attributes);
1447 attributes = nullptr;
1448 NS_HTML5_BREAK(starttagloop);
1450 case SELECT: {
1451 reconstructTheActiveFormattingElements();
1452 appendToCurrentNodeAndPushElementMayFoster(
1453 elementName, attributes, formPointer);
1454 switch (mode) {
1455 case IN_TABLE:
1456 case IN_CAPTION:
1457 case IN_COLUMN_GROUP:
1458 case IN_TABLE_BODY:
1459 case IN_ROW:
1460 case IN_CELL: {
1461 mode = IN_SELECT_IN_TABLE;
1462 break;
1464 default: {
1465 mode = IN_SELECT;
1466 break;
1469 attributes = nullptr;
1470 NS_HTML5_BREAK(starttagloop);
1472 case OPTGROUP:
1473 case OPTION: {
1474 if (isCurrent(nsGkAtoms::option)) {
1475 pop();
1477 reconstructTheActiveFormattingElements();
1478 appendToCurrentNodeAndPushElementMayFoster(elementName,
1479 attributes);
1480 attributes = nullptr;
1481 NS_HTML5_BREAK(starttagloop);
1483 case RB_OR_RTC: {
1484 eltPos = findLastInScope(nsGkAtoms::ruby);
1485 if (eltPos != NOT_FOUND_ON_STACK) {
1486 generateImpliedEndTags();
1488 if (eltPos != currentPtr) {
1489 if (eltPos == NOT_FOUND_ON_STACK) {
1490 errStartTagSeenWithoutRuby(name);
1491 } else {
1492 errUnclosedChildrenInRuby();
1495 appendToCurrentNodeAndPushElementMayFoster(elementName,
1496 attributes);
1497 attributes = nullptr;
1498 NS_HTML5_BREAK(starttagloop);
1500 case RT_OR_RP: {
1501 eltPos = findLastInScope(nsGkAtoms::ruby);
1502 if (eltPos != NOT_FOUND_ON_STACK) {
1503 generateImpliedEndTagsExceptFor(nsGkAtoms::rtc);
1505 if (eltPos != currentPtr) {
1506 if (!isCurrent(nsGkAtoms::rtc)) {
1507 if (eltPos == NOT_FOUND_ON_STACK) {
1508 errStartTagSeenWithoutRuby(name);
1509 } else {
1510 errUnclosedChildrenInRuby();
1514 appendToCurrentNodeAndPushElementMayFoster(elementName,
1515 attributes);
1516 attributes = nullptr;
1517 NS_HTML5_BREAK(starttagloop);
1519 case MATH: {
1520 reconstructTheActiveFormattingElements();
1521 attributes->adjustForMath();
1522 if (selfClosing) {
1523 appendVoidElementToCurrentMayFosterMathML(elementName,
1524 attributes);
1525 selfClosing = false;
1526 } else {
1527 appendToCurrentNodeAndPushElementMayFosterMathML(elementName,
1528 attributes);
1530 attributes = nullptr;
1531 NS_HTML5_BREAK(starttagloop);
1533 case SVG: {
1534 reconstructTheActiveFormattingElements();
1535 attributes->adjustForSvg();
1536 if (selfClosing) {
1537 appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
1538 selfClosing = false;
1539 } else {
1540 appendToCurrentNodeAndPushElementMayFosterSVG(elementName,
1541 attributes);
1543 attributes = nullptr;
1544 NS_HTML5_BREAK(starttagloop);
1546 case CAPTION:
1547 case COL:
1548 case COLGROUP:
1549 case TBODY_OR_THEAD_OR_TFOOT:
1550 case TR:
1551 case TD_OR_TH:
1552 case FRAME:
1553 case FRAMESET:
1554 case HEAD: {
1555 errStrayStartTag(name);
1556 NS_HTML5_BREAK(starttagloop);
1558 case OUTPUT: {
1559 reconstructTheActiveFormattingElements();
1560 appendToCurrentNodeAndPushElementMayFoster(
1561 elementName, attributes, formPointer);
1562 attributes = nullptr;
1563 NS_HTML5_BREAK(starttagloop);
1565 default: {
1566 reconstructTheActiveFormattingElements();
1567 appendToCurrentNodeAndPushElementMayFoster(elementName,
1568 attributes);
1569 attributes = nullptr;
1570 NS_HTML5_BREAK(starttagloop);
1574 inbodyloop_end:;
1575 MOZ_FALLTHROUGH;
1577 case IN_HEAD: {
1578 for (;;) {
1579 switch (group) {
1580 case HTML: {
1581 errStrayStartTag(name);
1582 if (!fragment && !isTemplateContents()) {
1583 addAttributesToHtml(attributes);
1584 attributes = nullptr;
1586 NS_HTML5_BREAK(starttagloop);
1588 case BASE:
1589 case LINK_OR_BASEFONT_OR_BGSOUND: {
1590 appendVoidElementToCurrentMayFoster(elementName, attributes);
1591 selfClosing = false;
1592 attributes = nullptr;
1593 NS_HTML5_BREAK(starttagloop);
1595 case META: {
1596 NS_HTML5_BREAK(inheadloop);
1598 case TITLE: {
1599 startTagTitleInHead(elementName, attributes);
1600 attributes = nullptr;
1601 NS_HTML5_BREAK(starttagloop);
1603 case NOSCRIPT: {
1604 if (scriptingEnabled) {
1605 appendToCurrentNodeAndPushElement(elementName, attributes);
1606 originalMode = mode;
1607 mode = TEXT;
1608 tokenizer->setStateAndEndTagExpectation(
1609 nsHtml5Tokenizer::RAWTEXT, elementName);
1610 } else {
1611 appendToCurrentNodeAndPushElementMayFoster(elementName,
1612 attributes);
1613 mode = IN_HEAD_NOSCRIPT;
1615 attributes = nullptr;
1616 NS_HTML5_BREAK(starttagloop);
1618 case SCRIPT: {
1619 startTagScriptInHead(elementName, attributes);
1620 attributes = nullptr;
1621 NS_HTML5_BREAK(starttagloop);
1623 case STYLE:
1624 case NOFRAMES: {
1625 startTagGenericRawText(elementName, attributes);
1626 attributes = nullptr;
1627 NS_HTML5_BREAK(starttagloop);
1629 case HEAD: {
1630 errFooSeenWhenFooOpen(name);
1631 NS_HTML5_BREAK(starttagloop);
1633 case TEMPLATE: {
1634 startTagTemplateInHead(elementName, attributes);
1635 attributes = nullptr;
1636 NS_HTML5_BREAK(starttagloop);
1638 default: {
1639 pop();
1640 mode = AFTER_HEAD;
1641 NS_HTML5_CONTINUE(starttagloop);
1645 inheadloop_end:;
1646 MOZ_FALLTHROUGH;
1648 case IN_HEAD_NOSCRIPT: {
1649 switch (group) {
1650 case HTML: {
1651 errStrayStartTag(name);
1652 if (!fragment && !isTemplateContents()) {
1653 addAttributesToHtml(attributes);
1654 attributes = nullptr;
1656 NS_HTML5_BREAK(starttagloop);
1658 case LINK_OR_BASEFONT_OR_BGSOUND: {
1659 appendVoidElementToCurrentMayFoster(elementName, attributes);
1660 selfClosing = false;
1661 attributes = nullptr;
1662 NS_HTML5_BREAK(starttagloop);
1664 case META: {
1665 checkMetaCharset(attributes);
1666 appendVoidElementToCurrentMayFoster(elementName, attributes);
1667 selfClosing = false;
1668 attributes = nullptr;
1669 NS_HTML5_BREAK(starttagloop);
1671 case STYLE:
1672 case NOFRAMES: {
1673 appendToCurrentNodeAndPushElement(elementName, attributes);
1674 originalMode = mode;
1675 mode = TEXT;
1676 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
1677 elementName);
1678 attributes = nullptr;
1679 NS_HTML5_BREAK(starttagloop);
1681 case HEAD: {
1682 errFooSeenWhenFooOpen(name);
1683 NS_HTML5_BREAK(starttagloop);
1685 case NOSCRIPT: {
1686 errFooSeenWhenFooOpen(name);
1687 NS_HTML5_BREAK(starttagloop);
1689 default: {
1690 errBadStartTagInHead(name);
1691 pop();
1692 mode = IN_HEAD;
1693 continue;
1697 case IN_COLUMN_GROUP: {
1698 switch (group) {
1699 case HTML: {
1700 errStrayStartTag(name);
1701 if (!fragment && !isTemplateContents()) {
1702 addAttributesToHtml(attributes);
1703 attributes = nullptr;
1705 NS_HTML5_BREAK(starttagloop);
1707 case COL: {
1708 appendVoidElementToCurrentMayFoster(elementName, attributes);
1709 selfClosing = false;
1710 attributes = nullptr;
1711 NS_HTML5_BREAK(starttagloop);
1713 case TEMPLATE: {
1714 startTagTemplateInHead(elementName, attributes);
1715 attributes = nullptr;
1716 NS_HTML5_BREAK(starttagloop);
1718 default: {
1719 if (!currentPtr || stack[currentPtr]->getGroup() == TEMPLATE) {
1720 MOZ_ASSERT(fragment || isTemplateContents());
1721 errGarbageInColgroup();
1722 NS_HTML5_BREAK(starttagloop);
1724 pop();
1725 mode = IN_TABLE;
1726 continue;
1730 case IN_SELECT_IN_TABLE: {
1731 switch (group) {
1732 case CAPTION:
1733 case TBODY_OR_THEAD_OR_TFOOT:
1734 case TR:
1735 case TD_OR_TH:
1736 case TABLE: {
1737 errStartTagWithSelectOpen(name);
1738 eltPos = findLastInTableScope(nsGkAtoms::select);
1739 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
1740 MOZ_ASSERT(fragment);
1741 NS_HTML5_BREAK(starttagloop);
1743 while (currentPtr >= eltPos) {
1744 pop();
1746 resetTheInsertionMode();
1747 continue;
1749 default:; // fall through
1751 MOZ_FALLTHROUGH;
1753 case IN_SELECT: {
1754 switch (group) {
1755 case HTML: {
1756 errStrayStartTag(name);
1757 if (!fragment) {
1758 addAttributesToHtml(attributes);
1759 attributes = nullptr;
1761 NS_HTML5_BREAK(starttagloop);
1763 case OPTION: {
1764 if (isCurrent(nsGkAtoms::option)) {
1765 pop();
1767 appendToCurrentNodeAndPushElement(elementName, attributes);
1768 attributes = nullptr;
1769 NS_HTML5_BREAK(starttagloop);
1771 case OPTGROUP: {
1772 if (isCurrent(nsGkAtoms::option)) {
1773 pop();
1775 if (isCurrent(nsGkAtoms::optgroup)) {
1776 pop();
1778 appendToCurrentNodeAndPushElement(elementName, attributes);
1779 attributes = nullptr;
1780 NS_HTML5_BREAK(starttagloop);
1782 case SELECT: {
1783 errStartSelectWhereEndSelectExpected();
1784 eltPos = findLastInTableScope(name);
1785 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
1786 MOZ_ASSERT(fragment);
1787 errNoSelectInTableScope();
1788 NS_HTML5_BREAK(starttagloop);
1789 } else {
1790 while (currentPtr >= eltPos) {
1791 pop();
1793 resetTheInsertionMode();
1794 NS_HTML5_BREAK(starttagloop);
1797 case INPUT:
1798 case TEXTAREA:
1799 case KEYGEN: {
1800 errStartTagWithSelectOpen(name);
1801 eltPos = findLastInTableScope(nsGkAtoms::select);
1802 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
1803 MOZ_ASSERT(fragment);
1804 NS_HTML5_BREAK(starttagloop);
1806 while (currentPtr >= eltPos) {
1807 pop();
1809 resetTheInsertionMode();
1810 continue;
1812 case SCRIPT: {
1813 startTagScriptInHead(elementName, attributes);
1814 attributes = nullptr;
1815 NS_HTML5_BREAK(starttagloop);
1817 case TEMPLATE: {
1818 startTagTemplateInHead(elementName, attributes);
1819 attributes = nullptr;
1820 NS_HTML5_BREAK(starttagloop);
1822 default: {
1823 errStrayStartTag(name);
1824 NS_HTML5_BREAK(starttagloop);
1828 case AFTER_BODY: {
1829 switch (group) {
1830 case HTML: {
1831 errStrayStartTag(name);
1832 if (!fragment && !isTemplateContents()) {
1833 addAttributesToHtml(attributes);
1834 attributes = nullptr;
1836 NS_HTML5_BREAK(starttagloop);
1838 default: {
1839 errStrayStartTag(name);
1840 mode = framesetOk ? FRAMESET_OK : IN_BODY;
1841 continue;
1845 case IN_FRAMESET: {
1846 switch (group) {
1847 case FRAMESET: {
1848 appendToCurrentNodeAndPushElement(elementName, attributes);
1849 attributes = nullptr;
1850 NS_HTML5_BREAK(starttagloop);
1852 case FRAME: {
1853 appendVoidElementToCurrentMayFoster(elementName, attributes);
1854 selfClosing = false;
1855 attributes = nullptr;
1856 NS_HTML5_BREAK(starttagloop);
1858 default:; // fall through
1860 MOZ_FALLTHROUGH;
1862 case AFTER_FRAMESET: {
1863 switch (group) {
1864 case HTML: {
1865 errStrayStartTag(name);
1866 if (!fragment && !isTemplateContents()) {
1867 addAttributesToHtml(attributes);
1868 attributes = nullptr;
1870 NS_HTML5_BREAK(starttagloop);
1872 case NOFRAMES: {
1873 appendToCurrentNodeAndPushElement(elementName, attributes);
1874 originalMode = mode;
1875 mode = TEXT;
1876 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
1877 elementName);
1878 attributes = nullptr;
1879 NS_HTML5_BREAK(starttagloop);
1881 default: {
1882 errStrayStartTag(name);
1883 NS_HTML5_BREAK(starttagloop);
1887 case INITIAL: {
1888 errStartTagWithoutDoctype();
1889 documentModeInternal(QUIRKS_MODE, nullptr, nullptr, false);
1890 mode = BEFORE_HTML;
1891 continue;
1893 case BEFORE_HTML: {
1894 switch (group) {
1895 case HTML: {
1896 if (attributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
1897 appendHtmlElementToDocumentAndPush();
1898 } else {
1899 appendHtmlElementToDocumentAndPush(attributes);
1901 mode = BEFORE_HEAD;
1902 attributes = nullptr;
1903 NS_HTML5_BREAK(starttagloop);
1905 default: {
1906 appendHtmlElementToDocumentAndPush();
1907 mode = BEFORE_HEAD;
1908 continue;
1912 case BEFORE_HEAD: {
1913 switch (group) {
1914 case HTML: {
1915 errStrayStartTag(name);
1916 if (!fragment && !isTemplateContents()) {
1917 addAttributesToHtml(attributes);
1918 attributes = nullptr;
1920 NS_HTML5_BREAK(starttagloop);
1922 case HEAD: {
1923 appendToCurrentNodeAndPushHeadElement(attributes);
1924 mode = IN_HEAD;
1925 attributes = nullptr;
1926 NS_HTML5_BREAK(starttagloop);
1928 default: {
1929 appendToCurrentNodeAndPushHeadElement(
1930 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
1931 mode = IN_HEAD;
1932 continue;
1936 case AFTER_HEAD: {
1937 switch (group) {
1938 case HTML: {
1939 errStrayStartTag(name);
1940 if (!fragment && !isTemplateContents()) {
1941 addAttributesToHtml(attributes);
1942 attributes = nullptr;
1944 NS_HTML5_BREAK(starttagloop);
1946 case BODY: {
1947 if (!attributes->getLength()) {
1948 appendToCurrentNodeAndPushBodyElement();
1949 } else {
1950 appendToCurrentNodeAndPushBodyElement(attributes);
1952 framesetOk = false;
1953 mode = IN_BODY;
1954 attributes = nullptr;
1955 NS_HTML5_BREAK(starttagloop);
1957 case FRAMESET: {
1958 appendToCurrentNodeAndPushElement(elementName, attributes);
1959 mode = IN_FRAMESET;
1960 attributes = nullptr;
1961 NS_HTML5_BREAK(starttagloop);
1963 case TEMPLATE: {
1964 errFooBetweenHeadAndBody(name);
1965 pushHeadPointerOntoStack();
1966 nsHtml5StackNode* headOnStack = stack[currentPtr];
1967 startTagTemplateInHead(elementName, attributes);
1968 removeFromStack(headOnStack);
1969 attributes = nullptr;
1970 NS_HTML5_BREAK(starttagloop);
1972 case BASE:
1973 case LINK_OR_BASEFONT_OR_BGSOUND: {
1974 errFooBetweenHeadAndBody(name);
1975 pushHeadPointerOntoStack();
1976 appendVoidElementToCurrentMayFoster(elementName, attributes);
1977 selfClosing = false;
1978 pop();
1979 attributes = nullptr;
1980 NS_HTML5_BREAK(starttagloop);
1982 case META: {
1983 errFooBetweenHeadAndBody(name);
1984 checkMetaCharset(attributes);
1985 pushHeadPointerOntoStack();
1986 appendVoidElementToCurrentMayFoster(elementName, attributes);
1987 selfClosing = false;
1988 pop();
1989 attributes = nullptr;
1990 NS_HTML5_BREAK(starttagloop);
1992 case SCRIPT: {
1993 errFooBetweenHeadAndBody(name);
1994 pushHeadPointerOntoStack();
1995 appendToCurrentNodeAndPushElement(elementName, attributes);
1996 originalMode = mode;
1997 mode = TEXT;
1998 tokenizer->setStateAndEndTagExpectation(
1999 nsHtml5Tokenizer::SCRIPT_DATA, elementName);
2000 attributes = nullptr;
2001 NS_HTML5_BREAK(starttagloop);
2003 case STYLE:
2004 case NOFRAMES: {
2005 errFooBetweenHeadAndBody(name);
2006 pushHeadPointerOntoStack();
2007 appendToCurrentNodeAndPushElement(elementName, attributes);
2008 originalMode = mode;
2009 mode = TEXT;
2010 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
2011 elementName);
2012 attributes = nullptr;
2013 NS_HTML5_BREAK(starttagloop);
2015 case TITLE: {
2016 errFooBetweenHeadAndBody(name);
2017 pushHeadPointerOntoStack();
2018 appendToCurrentNodeAndPushElement(elementName, attributes);
2019 originalMode = mode;
2020 mode = TEXT;
2021 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
2022 elementName);
2023 attributes = nullptr;
2024 NS_HTML5_BREAK(starttagloop);
2026 case HEAD: {
2027 errStrayStartTag(name);
2028 NS_HTML5_BREAK(starttagloop);
2030 default: {
2031 appendToCurrentNodeAndPushBodyElement();
2032 mode = FRAMESET_OK;
2033 continue;
2037 case AFTER_AFTER_BODY: {
2038 switch (group) {
2039 case HTML: {
2040 errStrayStartTag(name);
2041 if (!fragment && !isTemplateContents()) {
2042 addAttributesToHtml(attributes);
2043 attributes = nullptr;
2045 NS_HTML5_BREAK(starttagloop);
2047 default: {
2048 errStrayStartTag(name);
2050 mode = framesetOk ? FRAMESET_OK : IN_BODY;
2051 continue;
2055 case AFTER_AFTER_FRAMESET: {
2056 switch (group) {
2057 case HTML: {
2058 errStrayStartTag(name);
2059 if (!fragment && !isTemplateContents()) {
2060 addAttributesToHtml(attributes);
2061 attributes = nullptr;
2063 NS_HTML5_BREAK(starttagloop);
2065 case NOFRAMES: {
2066 startTagGenericRawText(elementName, attributes);
2067 attributes = nullptr;
2068 NS_HTML5_BREAK(starttagloop);
2070 default: {
2071 errStrayStartTag(name);
2072 NS_HTML5_BREAK(starttagloop);
2076 case TEXT: {
2077 MOZ_ASSERT(false);
2078 NS_HTML5_BREAK(starttagloop);
2082 starttagloop_end:;
2083 if (selfClosing) {
2084 errSelfClosing();
2086 if (!mBuilder && attributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
2087 delete attributes;
2091 void
2092 nsHtml5TreeBuilder::startTagTitleInHead(nsHtml5ElementName* elementName,
2093 nsHtml5HtmlAttributes* attributes)
2095 appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
2096 originalMode = mode;
2097 mode = TEXT;
2098 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
2099 elementName);
2102 void
2103 nsHtml5TreeBuilder::startTagGenericRawText(nsHtml5ElementName* elementName,
2104 nsHtml5HtmlAttributes* attributes)
2106 appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
2107 originalMode = mode;
2108 mode = TEXT;
2109 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
2110 elementName);
2113 void
2114 nsHtml5TreeBuilder::startTagScriptInHead(nsHtml5ElementName* elementName,
2115 nsHtml5HtmlAttributes* attributes)
2117 appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
2118 originalMode = mode;
2119 mode = TEXT;
2120 tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::SCRIPT_DATA,
2121 elementName);
2124 void
2125 nsHtml5TreeBuilder::startTagTemplateInHead(nsHtml5ElementName* elementName,
2126 nsHtml5HtmlAttributes* attributes)
2128 appendToCurrentNodeAndPushElement(elementName, attributes);
2129 insertMarker();
2130 framesetOk = false;
2131 originalMode = mode;
2132 mode = IN_TEMPLATE;
2133 pushTemplateMode(IN_TEMPLATE);
2136 bool
2137 nsHtml5TreeBuilder::isTemplateContents()
2139 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK !=
2140 findLast(nsGkAtoms::_template);
2143 bool
2144 nsHtml5TreeBuilder::isTemplateModeStackEmpty()
2146 return templateModePtr == -1;
2149 bool
2150 nsHtml5TreeBuilder::isSpecialParentInForeign(nsHtml5StackNode* stackNode)
2152 int32_t ns = stackNode->ns;
2153 return (kNameSpaceID_XHTML == ns) || (stackNode->isHtmlIntegrationPoint()) ||
2154 ((kNameSpaceID_MathML == ns) &&
2155 (stackNode->getGroup() == MI_MO_MN_MS_MTEXT));
2158 nsHtml5String
2159 nsHtml5TreeBuilder::extractCharsetFromContent(nsHtml5String attributeValue,
2160 nsHtml5TreeBuilder* tb)
2162 int32_t charsetState = CHARSET_INITIAL;
2163 int32_t start = -1;
2164 int32_t end = -1;
2165 autoJArray<char16_t, int32_t> buffer =
2166 nsHtml5Portability::newCharArrayFromString(attributeValue);
2167 for (int32_t i = 0; i < buffer.length; i++) {
2168 char16_t c = buffer[i];
2169 switch (charsetState) {
2170 case CHARSET_INITIAL: {
2171 switch (c) {
2172 case 'c':
2173 case 'C': {
2174 charsetState = CHARSET_C;
2175 continue;
2177 default: {
2178 continue;
2182 case CHARSET_C: {
2183 switch (c) {
2184 case 'h':
2185 case 'H': {
2186 charsetState = CHARSET_H;
2187 continue;
2189 default: {
2190 charsetState = CHARSET_INITIAL;
2191 continue;
2195 case CHARSET_H: {
2196 switch (c) {
2197 case 'a':
2198 case 'A': {
2199 charsetState = CHARSET_A;
2200 continue;
2202 default: {
2203 charsetState = CHARSET_INITIAL;
2204 continue;
2208 case CHARSET_A: {
2209 switch (c) {
2210 case 'r':
2211 case 'R': {
2212 charsetState = CHARSET_R;
2213 continue;
2215 default: {
2216 charsetState = CHARSET_INITIAL;
2217 continue;
2221 case CHARSET_R: {
2222 switch (c) {
2223 case 's':
2224 case 'S': {
2225 charsetState = CHARSET_S;
2226 continue;
2228 default: {
2229 charsetState = CHARSET_INITIAL;
2230 continue;
2234 case CHARSET_S: {
2235 switch (c) {
2236 case 'e':
2237 case 'E': {
2238 charsetState = CHARSET_E;
2239 continue;
2241 default: {
2242 charsetState = CHARSET_INITIAL;
2243 continue;
2247 case CHARSET_E: {
2248 switch (c) {
2249 case 't':
2250 case 'T': {
2251 charsetState = CHARSET_T;
2252 continue;
2254 default: {
2255 charsetState = CHARSET_INITIAL;
2256 continue;
2260 case CHARSET_T: {
2261 switch (c) {
2262 case '\t':
2263 case '\n':
2264 case '\f':
2265 case '\r':
2266 case ' ': {
2267 continue;
2269 case '=': {
2270 charsetState = CHARSET_EQUALS;
2271 continue;
2273 default: {
2274 return nullptr;
2278 case CHARSET_EQUALS: {
2279 switch (c) {
2280 case '\t':
2281 case '\n':
2282 case '\f':
2283 case '\r':
2284 case ' ': {
2285 continue;
2287 case '\'': {
2288 start = i + 1;
2289 charsetState = CHARSET_SINGLE_QUOTED;
2290 continue;
2292 case '\"': {
2293 start = i + 1;
2294 charsetState = CHARSET_DOUBLE_QUOTED;
2295 continue;
2297 default: {
2298 start = i;
2299 charsetState = CHARSET_UNQUOTED;
2300 continue;
2304 case CHARSET_SINGLE_QUOTED: {
2305 switch (c) {
2306 case '\'': {
2307 end = i;
2308 NS_HTML5_BREAK(charsetloop);
2310 default: {
2311 continue;
2315 case CHARSET_DOUBLE_QUOTED: {
2316 switch (c) {
2317 case '\"': {
2318 end = i;
2319 NS_HTML5_BREAK(charsetloop);
2321 default: {
2322 continue;
2326 case CHARSET_UNQUOTED: {
2327 switch (c) {
2328 case '\t':
2329 case '\n':
2330 case '\f':
2331 case '\r':
2332 case ' ':
2333 case ';': {
2334 end = i;
2335 NS_HTML5_BREAK(charsetloop);
2337 default: {
2338 continue;
2344 charsetloop_end:;
2345 nsHtml5String charset = nullptr;
2346 if (start != -1) {
2347 if (end == -1) {
2348 end = buffer.length;
2350 charset = nsHtml5Portability::newStringFromBuffer(
2351 buffer, start, end - start, tb, false);
2353 return charset;
2356 void
2357 nsHtml5TreeBuilder::checkMetaCharset(nsHtml5HtmlAttributes* attributes)
2359 nsHtml5String charset =
2360 attributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
2361 if (charset) {
2362 if (tokenizer->internalEncodingDeclaration(charset)) {
2363 requestSuspension();
2364 return;
2366 return;
2368 if (!nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
2369 "content-type",
2370 attributes->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV))) {
2371 return;
2373 nsHtml5String content =
2374 attributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);
2375 if (content) {
2376 nsHtml5String extract =
2377 nsHtml5TreeBuilder::extractCharsetFromContent(content, this);
2378 if (extract) {
2379 if (tokenizer->internalEncodingDeclaration(extract)) {
2380 requestSuspension();
2383 extract.Release();
2387 void
2388 nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName)
2390 flushCharacters();
2391 needToDropLF = false;
2392 int32_t eltPos;
2393 int32_t group = elementName->getGroup();
2394 nsAtom* name = elementName->getName();
2395 for (;;) {
2396 if (isInForeign()) {
2397 if (stack[currentPtr]->name != name) {
2398 if (!currentPtr) {
2399 errStrayEndTag(name);
2400 } else {
2401 errEndTagDidNotMatchCurrentOpenElement(name,
2402 stack[currentPtr]->popName);
2405 eltPos = currentPtr;
2406 for (;;) {
2407 if (!eltPos) {
2408 MOZ_ASSERT(fragment,
2409 "We can get this close to the root of the stack in "
2410 "foreign content only in the fragment case.");
2411 NS_HTML5_BREAK(endtagloop);
2413 if (stack[eltPos]->name == name) {
2414 while (currentPtr >= eltPos) {
2415 pop();
2417 NS_HTML5_BREAK(endtagloop);
2419 if (stack[--eltPos]->ns == kNameSpaceID_XHTML) {
2420 break;
2424 switch (mode) {
2425 case IN_TEMPLATE: {
2426 switch (group) {
2427 case TEMPLATE: {
2428 break;
2430 default: {
2431 errStrayEndTag(name);
2432 NS_HTML5_BREAK(endtagloop);
2435 MOZ_FALLTHROUGH;
2437 case IN_ROW: {
2438 switch (group) {
2439 case TR: {
2440 eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
2441 if (!eltPos) {
2442 MOZ_ASSERT(fragment || isTemplateContents());
2443 errNoTableRowToClose();
2444 NS_HTML5_BREAK(endtagloop);
2446 clearStackBackTo(eltPos);
2447 pop();
2448 mode = IN_TABLE_BODY;
2449 NS_HTML5_BREAK(endtagloop);
2451 case TABLE: {
2452 eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
2453 if (!eltPos) {
2454 MOZ_ASSERT(fragment || isTemplateContents());
2455 errNoTableRowToClose();
2456 NS_HTML5_BREAK(endtagloop);
2458 clearStackBackTo(eltPos);
2459 pop();
2460 mode = IN_TABLE_BODY;
2461 continue;
2463 case TBODY_OR_THEAD_OR_TFOOT: {
2464 if (findLastInTableScope(name) ==
2465 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2466 errStrayEndTag(name);
2467 NS_HTML5_BREAK(endtagloop);
2469 eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
2470 if (!eltPos) {
2471 MOZ_ASSERT(fragment || isTemplateContents());
2472 errNoTableRowToClose();
2473 NS_HTML5_BREAK(endtagloop);
2475 clearStackBackTo(eltPos);
2476 pop();
2477 mode = IN_TABLE_BODY;
2478 continue;
2480 case BODY:
2481 case CAPTION:
2482 case COL:
2483 case COLGROUP:
2484 case HTML:
2485 case TD_OR_TH: {
2486 errStrayEndTag(name);
2487 NS_HTML5_BREAK(endtagloop);
2489 default:; // fall through
2491 MOZ_FALLTHROUGH;
2493 case IN_TABLE_BODY: {
2494 switch (group) {
2495 case TBODY_OR_THEAD_OR_TFOOT: {
2496 eltPos = findLastOrRoot(name);
2497 if (!eltPos) {
2498 errStrayEndTag(name);
2499 NS_HTML5_BREAK(endtagloop);
2501 clearStackBackTo(eltPos);
2502 pop();
2503 mode = IN_TABLE;
2504 NS_HTML5_BREAK(endtagloop);
2506 case TABLE: {
2507 eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
2508 if (!eltPos || stack[eltPos]->getGroup() == TEMPLATE) {
2509 MOZ_ASSERT(fragment || isTemplateContents());
2510 errStrayEndTag(name);
2511 NS_HTML5_BREAK(endtagloop);
2513 clearStackBackTo(eltPos);
2514 pop();
2515 mode = IN_TABLE;
2516 continue;
2518 case BODY:
2519 case CAPTION:
2520 case COL:
2521 case COLGROUP:
2522 case HTML:
2523 case TD_OR_TH:
2524 case TR: {
2525 errStrayEndTag(name);
2526 NS_HTML5_BREAK(endtagloop);
2528 default:; // fall through
2530 MOZ_FALLTHROUGH;
2532 case IN_TABLE: {
2533 switch (group) {
2534 case TABLE: {
2535 eltPos = findLast(nsGkAtoms::table);
2536 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2537 MOZ_ASSERT(fragment || isTemplateContents());
2538 errStrayEndTag(name);
2539 NS_HTML5_BREAK(endtagloop);
2541 while (currentPtr >= eltPos) {
2542 pop();
2544 resetTheInsertionMode();
2545 NS_HTML5_BREAK(endtagloop);
2547 case BODY:
2548 case CAPTION:
2549 case COL:
2550 case COLGROUP:
2551 case HTML:
2552 case TBODY_OR_THEAD_OR_TFOOT:
2553 case TD_OR_TH:
2554 case TR: {
2555 errStrayEndTag(name);
2556 NS_HTML5_BREAK(endtagloop);
2558 case TEMPLATE: {
2559 break;
2561 default: {
2562 errStrayEndTag(name);
2565 MOZ_FALLTHROUGH;
2567 case IN_CAPTION: {
2568 switch (group) {
2569 case CAPTION: {
2570 eltPos = findLastInTableScope(nsGkAtoms::caption);
2571 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2572 NS_HTML5_BREAK(endtagloop);
2574 generateImpliedEndTags();
2575 if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
2576 errUnclosedElements(eltPos, name);
2578 while (currentPtr >= eltPos) {
2579 pop();
2581 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2582 mode = IN_TABLE;
2583 NS_HTML5_BREAK(endtagloop);
2585 case TABLE: {
2586 errTableClosedWhileCaptionOpen();
2587 eltPos = findLastInTableScope(nsGkAtoms::caption);
2588 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2589 NS_HTML5_BREAK(endtagloop);
2591 generateImpliedEndTags();
2592 if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
2593 errUnclosedElements(eltPos, name);
2595 while (currentPtr >= eltPos) {
2596 pop();
2598 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2599 mode = IN_TABLE;
2600 continue;
2602 case BODY:
2603 case COL:
2604 case COLGROUP:
2605 case HTML:
2606 case TBODY_OR_THEAD_OR_TFOOT:
2607 case TD_OR_TH:
2608 case TR: {
2609 errStrayEndTag(name);
2610 NS_HTML5_BREAK(endtagloop);
2612 default:; // fall through
2614 MOZ_FALLTHROUGH;
2616 case IN_CELL: {
2617 switch (group) {
2618 case TD_OR_TH: {
2619 eltPos = findLastInTableScope(name);
2620 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2621 errStrayEndTag(name);
2622 NS_HTML5_BREAK(endtagloop);
2624 generateImpliedEndTags();
2625 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2626 errUnclosedElements(eltPos, name);
2628 while (currentPtr >= eltPos) {
2629 pop();
2631 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2632 mode = IN_ROW;
2633 NS_HTML5_BREAK(endtagloop);
2635 case TABLE:
2636 case TBODY_OR_THEAD_OR_TFOOT:
2637 case TR: {
2638 if (findLastInTableScope(name) ==
2639 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2640 MOZ_ASSERT(name == nsGkAtoms::tbody || name == nsGkAtoms::tfoot ||
2641 name == nsGkAtoms::thead || fragment ||
2642 isTemplateContents());
2643 errStrayEndTag(name);
2644 NS_HTML5_BREAK(endtagloop);
2646 closeTheCell(findLastInTableScopeTdTh());
2647 continue;
2649 case BODY:
2650 case CAPTION:
2651 case COL:
2652 case COLGROUP:
2653 case HTML: {
2654 errStrayEndTag(name);
2655 NS_HTML5_BREAK(endtagloop);
2657 default:; // fall through
2659 MOZ_FALLTHROUGH;
2661 case FRAMESET_OK:
2662 case IN_BODY: {
2663 switch (group) {
2664 case BODY: {
2665 if (!isSecondOnStackBody()) {
2666 MOZ_ASSERT(fragment || isTemplateContents());
2667 errStrayEndTag(name);
2668 NS_HTML5_BREAK(endtagloop);
2670 MOZ_ASSERT(currentPtr >= 1);
2671 if (MOZ_UNLIKELY(mViewSource)) {
2672 for (int32_t i = 2; i <= currentPtr; i++) {
2673 switch (stack[i]->getGroup()) {
2674 case DD_OR_DT:
2675 case LI:
2676 case OPTGROUP:
2677 case OPTION:
2678 case P:
2679 case RB_OR_RTC:
2680 case RT_OR_RP:
2681 case TD_OR_TH:
2682 case TBODY_OR_THEAD_OR_TFOOT: {
2683 break;
2685 default: {
2686 errEndWithUnclosedElements(name);
2687 NS_HTML5_BREAK(uncloseloop1);
2691 uncloseloop1_end:;
2693 mode = AFTER_BODY;
2694 NS_HTML5_BREAK(endtagloop);
2696 case HTML: {
2697 if (!isSecondOnStackBody()) {
2698 MOZ_ASSERT(fragment || isTemplateContents());
2699 errStrayEndTag(name);
2700 NS_HTML5_BREAK(endtagloop);
2702 if (MOZ_UNLIKELY(mViewSource)) {
2703 for (int32_t i = 0; i <= currentPtr; i++) {
2704 switch (stack[i]->getGroup()) {
2705 case DD_OR_DT:
2706 case LI:
2707 case P:
2708 case RB_OR_RTC:
2709 case RT_OR_RP:
2710 case TBODY_OR_THEAD_OR_TFOOT:
2711 case TD_OR_TH:
2712 case BODY:
2713 case HTML: {
2714 break;
2716 default: {
2717 errEndWithUnclosedElements(name);
2718 NS_HTML5_BREAK(uncloseloop2);
2722 uncloseloop2_end:;
2724 mode = AFTER_BODY;
2725 continue;
2727 case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
2728 case UL_OR_OL_OR_DL:
2729 case PRE_OR_LISTING:
2730 case FIELDSET:
2731 case BUTTON:
2732 case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY: {
2733 eltPos = findLastInScope(name);
2734 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2735 errStrayEndTag(name);
2736 } else {
2737 generateImpliedEndTags();
2738 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2739 errUnclosedElements(eltPos, name);
2741 while (currentPtr >= eltPos) {
2742 pop();
2745 NS_HTML5_BREAK(endtagloop);
2747 case FORM: {
2748 if (!isTemplateContents()) {
2749 if (!formPointer) {
2750 errStrayEndTag(name);
2751 NS_HTML5_BREAK(endtagloop);
2753 formPointer = nullptr;
2754 eltPos = findLastInScope(name);
2755 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2756 errStrayEndTag(name);
2757 NS_HTML5_BREAK(endtagloop);
2759 generateImpliedEndTags();
2760 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2761 errUnclosedElements(eltPos, name);
2763 removeFromStack(eltPos);
2764 NS_HTML5_BREAK(endtagloop);
2765 } else {
2766 eltPos = findLastInScope(name);
2767 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2768 errStrayEndTag(name);
2769 NS_HTML5_BREAK(endtagloop);
2771 generateImpliedEndTags();
2772 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2773 errUnclosedElements(eltPos, name);
2775 while (currentPtr >= eltPos) {
2776 pop();
2778 NS_HTML5_BREAK(endtagloop);
2781 case P: {
2782 eltPos = findLastInButtonScope(nsGkAtoms::p);
2783 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2784 errNoElementToCloseButEndTagSeen(nsGkAtoms::p);
2785 if (isInForeign()) {
2786 errHtmlStartTagInForeignContext(name);
2787 while (currentPtr >= 0 &&
2788 stack[currentPtr]->ns != kNameSpaceID_XHTML) {
2789 pop();
2792 appendVoidElementToCurrentMayFoster(
2793 elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
2794 NS_HTML5_BREAK(endtagloop);
2796 generateImpliedEndTagsExceptFor(nsGkAtoms::p);
2797 MOZ_ASSERT(eltPos != nsHtml5TreeBuilder::NOT_FOUND_ON_STACK);
2798 if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
2799 errUnclosedElements(eltPos, name);
2801 while (currentPtr >= eltPos) {
2802 pop();
2804 NS_HTML5_BREAK(endtagloop);
2806 case LI: {
2807 eltPos = findLastInListScope(name);
2808 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2809 errNoElementToCloseButEndTagSeen(name);
2810 } else {
2811 generateImpliedEndTagsExceptFor(name);
2812 if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
2813 errUnclosedElements(eltPos, name);
2815 while (currentPtr >= eltPos) {
2816 pop();
2819 NS_HTML5_BREAK(endtagloop);
2821 case DD_OR_DT: {
2822 eltPos = findLastInScope(name);
2823 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2824 errNoElementToCloseButEndTagSeen(name);
2825 } else {
2826 generateImpliedEndTagsExceptFor(name);
2827 if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
2828 errUnclosedElements(eltPos, name);
2830 while (currentPtr >= eltPos) {
2831 pop();
2834 NS_HTML5_BREAK(endtagloop);
2836 case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: {
2837 eltPos = findLastInScopeHn();
2838 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2839 errStrayEndTag(name);
2840 } else {
2841 generateImpliedEndTags();
2842 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2843 errUnclosedElements(eltPos, name);
2845 while (currentPtr >= eltPos) {
2846 pop();
2849 NS_HTML5_BREAK(endtagloop);
2851 case OBJECT:
2852 case MARQUEE_OR_APPLET: {
2853 eltPos = findLastInScope(name);
2854 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
2855 errStrayEndTag(name);
2856 } else {
2857 generateImpliedEndTags();
2858 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2859 errUnclosedElements(eltPos, name);
2861 while (currentPtr >= eltPos) {
2862 pop();
2864 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
2866 NS_HTML5_BREAK(endtagloop);
2868 case BR: {
2869 errEndTagBr();
2870 if (isInForeign()) {
2871 errHtmlStartTagInForeignContext(name);
2872 while (currentPtr >= 0 &&
2873 stack[currentPtr]->ns != kNameSpaceID_XHTML) {
2874 pop();
2877 reconstructTheActiveFormattingElements();
2878 appendVoidElementToCurrentMayFoster(
2879 elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
2880 NS_HTML5_BREAK(endtagloop);
2882 case TEMPLATE: {
2883 break;
2885 case AREA_OR_WBR:
2886 #ifdef ENABLE_VOID_MENUITEM
2887 case MENUITEM:
2888 #endif
2889 case PARAM_OR_SOURCE_OR_TRACK:
2890 case EMBED:
2891 case IMG:
2892 case IMAGE:
2893 case INPUT:
2894 case KEYGEN:
2895 case HR:
2896 case IFRAME:
2897 case NOEMBED:
2898 case NOFRAMES:
2899 case SELECT:
2900 case TABLE:
2901 case TEXTAREA: {
2902 errStrayEndTag(name);
2903 NS_HTML5_BREAK(endtagloop);
2905 case NOSCRIPT: {
2906 if (scriptingEnabled) {
2907 errStrayEndTag(name);
2908 NS_HTML5_BREAK(endtagloop);
2910 MOZ_FALLTHROUGH;
2912 case A:
2913 case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
2914 case FONT:
2915 case NOBR: {
2916 if (adoptionAgencyEndTag(name)) {
2917 NS_HTML5_BREAK(endtagloop);
2919 MOZ_FALLTHROUGH;
2921 default: {
2922 if (isCurrent(name)) {
2923 pop();
2924 NS_HTML5_BREAK(endtagloop);
2926 eltPos = currentPtr;
2927 for (;;) {
2928 nsHtml5StackNode* node = stack[eltPos];
2929 if (node->ns == kNameSpaceID_XHTML && node->name == name) {
2930 generateImpliedEndTags();
2931 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
2932 errUnclosedElements(eltPos, name);
2934 while (currentPtr >= eltPos) {
2935 pop();
2937 NS_HTML5_BREAK(endtagloop);
2938 } else if (!eltPos || node->isSpecial()) {
2939 errStrayEndTag(name);
2940 NS_HTML5_BREAK(endtagloop);
2942 eltPos--;
2946 MOZ_FALLTHROUGH;
2948 case IN_HEAD: {
2949 switch (group) {
2950 case HEAD: {
2951 pop();
2952 mode = AFTER_HEAD;
2953 NS_HTML5_BREAK(endtagloop);
2955 case BR:
2956 case HTML:
2957 case BODY: {
2958 pop();
2959 mode = AFTER_HEAD;
2960 continue;
2962 case TEMPLATE: {
2963 endTagTemplateInHead();
2964 NS_HTML5_BREAK(endtagloop);
2966 default: {
2967 errStrayEndTag(name);
2968 NS_HTML5_BREAK(endtagloop);
2972 case IN_HEAD_NOSCRIPT: {
2973 switch (group) {
2974 case NOSCRIPT: {
2975 pop();
2976 mode = IN_HEAD;
2977 NS_HTML5_BREAK(endtagloop);
2979 case BR: {
2980 errStrayEndTag(name);
2981 pop();
2982 mode = IN_HEAD;
2983 continue;
2985 default: {
2986 errStrayEndTag(name);
2987 NS_HTML5_BREAK(endtagloop);
2991 case IN_COLUMN_GROUP: {
2992 switch (group) {
2993 case COLGROUP: {
2994 if (!currentPtr ||
2995 stack[currentPtr]->getGroup() == nsHtml5TreeBuilder::TEMPLATE) {
2996 MOZ_ASSERT(fragment || isTemplateContents());
2997 errGarbageInColgroup();
2998 NS_HTML5_BREAK(endtagloop);
3000 pop();
3001 mode = IN_TABLE;
3002 NS_HTML5_BREAK(endtagloop);
3004 case COL: {
3005 errStrayEndTag(name);
3006 NS_HTML5_BREAK(endtagloop);
3008 case TEMPLATE: {
3009 endTagTemplateInHead();
3010 NS_HTML5_BREAK(endtagloop);
3012 default: {
3013 if (!currentPtr ||
3014 stack[currentPtr]->getGroup() == nsHtml5TreeBuilder::TEMPLATE) {
3015 MOZ_ASSERT(fragment || isTemplateContents());
3016 errGarbageInColgroup();
3017 NS_HTML5_BREAK(endtagloop);
3019 pop();
3020 mode = IN_TABLE;
3021 continue;
3025 case IN_SELECT_IN_TABLE: {
3026 switch (group) {
3027 case CAPTION:
3028 case TABLE:
3029 case TBODY_OR_THEAD_OR_TFOOT:
3030 case TR:
3031 case TD_OR_TH: {
3032 errEndTagSeenWithSelectOpen(name);
3033 if (findLastInTableScope(name) !=
3034 nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
3035 eltPos = findLastInTableScope(nsGkAtoms::select);
3036 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
3037 MOZ_ASSERT(fragment);
3038 NS_HTML5_BREAK(endtagloop);
3040 while (currentPtr >= eltPos) {
3041 pop();
3043 resetTheInsertionMode();
3044 continue;
3045 } else {
3046 NS_HTML5_BREAK(endtagloop);
3049 default:; // fall through
3051 MOZ_FALLTHROUGH;
3053 case IN_SELECT: {
3054 switch (group) {
3055 case OPTION: {
3056 if (isCurrent(nsGkAtoms::option)) {
3057 pop();
3058 NS_HTML5_BREAK(endtagloop);
3059 } else {
3060 errStrayEndTag(name);
3061 NS_HTML5_BREAK(endtagloop);
3064 case OPTGROUP: {
3065 if (isCurrent(nsGkAtoms::option) &&
3066 nsGkAtoms::optgroup == stack[currentPtr - 1]->name) {
3067 pop();
3069 if (isCurrent(nsGkAtoms::optgroup)) {
3070 pop();
3071 } else {
3072 errStrayEndTag(name);
3074 NS_HTML5_BREAK(endtagloop);
3076 case SELECT: {
3077 eltPos = findLastInTableScope(nsGkAtoms::select);
3078 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
3079 MOZ_ASSERT(fragment);
3080 errStrayEndTag(name);
3081 NS_HTML5_BREAK(endtagloop);
3083 while (currentPtr >= eltPos) {
3084 pop();
3086 resetTheInsertionMode();
3087 NS_HTML5_BREAK(endtagloop);
3089 case TEMPLATE: {
3090 endTagTemplateInHead();
3091 NS_HTML5_BREAK(endtagloop);
3093 default: {
3094 errStrayEndTag(name);
3095 NS_HTML5_BREAK(endtagloop);
3099 case AFTER_BODY: {
3100 switch (group) {
3101 case HTML: {
3102 if (fragment) {
3103 errStrayEndTag(name);
3104 NS_HTML5_BREAK(endtagloop);
3105 } else {
3106 mode = AFTER_AFTER_BODY;
3107 NS_HTML5_BREAK(endtagloop);
3110 default: {
3111 errEndTagAfterBody();
3112 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3113 continue;
3117 case IN_FRAMESET: {
3118 switch (group) {
3119 case FRAMESET: {
3120 if (!currentPtr) {
3121 MOZ_ASSERT(fragment);
3122 errStrayEndTag(name);
3123 NS_HTML5_BREAK(endtagloop);
3125 pop();
3126 if ((!fragment) && !isCurrent(nsGkAtoms::frameset)) {
3127 mode = AFTER_FRAMESET;
3129 NS_HTML5_BREAK(endtagloop);
3131 default: {
3132 errStrayEndTag(name);
3133 NS_HTML5_BREAK(endtagloop);
3137 case AFTER_FRAMESET: {
3138 switch (group) {
3139 case HTML: {
3140 mode = AFTER_AFTER_FRAMESET;
3141 NS_HTML5_BREAK(endtagloop);
3143 default: {
3144 errStrayEndTag(name);
3145 NS_HTML5_BREAK(endtagloop);
3149 case INITIAL: {
3150 errEndTagSeenWithoutDoctype();
3151 documentModeInternal(QUIRKS_MODE, nullptr, nullptr, false);
3152 mode = BEFORE_HTML;
3153 continue;
3155 case BEFORE_HTML: {
3156 switch (group) {
3157 case HEAD:
3158 case BR:
3159 case HTML:
3160 case BODY: {
3161 appendHtmlElementToDocumentAndPush();
3162 mode = BEFORE_HEAD;
3163 continue;
3165 default: {
3166 errStrayEndTag(name);
3167 NS_HTML5_BREAK(endtagloop);
3171 case BEFORE_HEAD: {
3172 switch (group) {
3173 case HEAD:
3174 case BR:
3175 case HTML:
3176 case BODY: {
3177 appendToCurrentNodeAndPushHeadElement(
3178 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
3179 mode = IN_HEAD;
3180 continue;
3182 default: {
3183 errStrayEndTag(name);
3184 NS_HTML5_BREAK(endtagloop);
3188 case AFTER_HEAD: {
3189 switch (group) {
3190 case TEMPLATE: {
3191 endTagTemplateInHead();
3192 NS_HTML5_BREAK(endtagloop);
3194 case HTML:
3195 case BODY:
3196 case BR: {
3197 appendToCurrentNodeAndPushBodyElement();
3198 mode = FRAMESET_OK;
3199 continue;
3201 default: {
3202 errStrayEndTag(name);
3203 NS_HTML5_BREAK(endtagloop);
3207 case AFTER_AFTER_BODY: {
3208 errStrayEndTag(name);
3209 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3210 continue;
3212 case AFTER_AFTER_FRAMESET: {
3213 errStrayEndTag(name);
3214 NS_HTML5_BREAK(endtagloop);
3216 case TEXT: {
3217 pop();
3218 if (originalMode == AFTER_HEAD) {
3219 silentPop();
3221 mode = originalMode;
3222 NS_HTML5_BREAK(endtagloop);
3226 endtagloop_end:;
3229 void
3230 nsHtml5TreeBuilder::endTagTemplateInHead()
3232 int32_t eltPos = findLast(nsGkAtoms::_template);
3233 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
3234 errStrayEndTag(nsGkAtoms::_template);
3235 return;
3237 generateImpliedEndTags();
3238 if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsGkAtoms::_template)) {
3239 errUnclosedElements(eltPos, nsGkAtoms::_template);
3241 while (currentPtr >= eltPos) {
3242 pop();
3244 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
3245 popTemplateMode();
3246 resetTheInsertionMode();
3249 int32_t
3250 nsHtml5TreeBuilder::findLastInTableScopeOrRootTemplateTbodyTheadTfoot()
3252 for (int32_t i = currentPtr; i > 0; i--) {
3253 if (stack[i]->getGroup() == nsHtml5TreeBuilder::TBODY_OR_THEAD_OR_TFOOT ||
3254 stack[i]->getGroup() == nsHtml5TreeBuilder::TEMPLATE) {
3255 return i;
3258 return 0;
3261 int32_t
3262 nsHtml5TreeBuilder::findLast(nsAtom* name)
3264 for (int32_t i = currentPtr; i > 0; i--) {
3265 if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
3266 return i;
3269 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3272 int32_t
3273 nsHtml5TreeBuilder::findLastInTableScope(nsAtom* name)
3275 for (int32_t i = currentPtr; i > 0; i--) {
3276 if (stack[i]->ns == kNameSpaceID_XHTML) {
3277 if (stack[i]->name == name) {
3278 return i;
3279 } else if (stack[i]->name == nsGkAtoms::table ||
3280 stack[i]->name == nsGkAtoms::_template) {
3281 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3285 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3288 int32_t
3289 nsHtml5TreeBuilder::findLastInButtonScope(nsAtom* name)
3291 for (int32_t i = currentPtr; i > 0; i--) {
3292 if (stack[i]->ns == kNameSpaceID_XHTML) {
3293 if (stack[i]->name == name) {
3294 return i;
3295 } else if (stack[i]->name == nsGkAtoms::button) {
3296 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3299 if (stack[i]->isScoping()) {
3300 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3303 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3306 int32_t
3307 nsHtml5TreeBuilder::findLastInScope(nsAtom* name)
3309 for (int32_t i = currentPtr; i > 0; i--) {
3310 if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
3311 return i;
3312 } else if (stack[i]->isScoping()) {
3313 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3316 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3319 int32_t
3320 nsHtml5TreeBuilder::findLastInListScope(nsAtom* name)
3322 for (int32_t i = currentPtr; i > 0; i--) {
3323 if (stack[i]->ns == kNameSpaceID_XHTML) {
3324 if (stack[i]->name == name) {
3325 return i;
3326 } else if (stack[i]->name == nsGkAtoms::ul ||
3327 stack[i]->name == nsGkAtoms::ol) {
3328 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3331 if (stack[i]->isScoping()) {
3332 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3335 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3338 int32_t
3339 nsHtml5TreeBuilder::findLastInScopeHn()
3341 for (int32_t i = currentPtr; i > 0; i--) {
3342 if (stack[i]->getGroup() ==
3343 nsHtml5TreeBuilder::H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
3344 return i;
3345 } else if (stack[i]->isScoping()) {
3346 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3349 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3352 void
3353 nsHtml5TreeBuilder::generateImpliedEndTagsExceptFor(nsAtom* name)
3355 for (;;) {
3356 nsHtml5StackNode* node = stack[currentPtr];
3357 switch (node->getGroup()) {
3358 case P:
3359 case LI:
3360 case DD_OR_DT:
3361 case OPTION:
3362 case OPTGROUP:
3363 case RB_OR_RTC:
3364 case RT_OR_RP: {
3365 if (node->ns == kNameSpaceID_XHTML && node->name == name) {
3366 return;
3368 pop();
3369 continue;
3371 default: {
3372 return;
3378 void
3379 nsHtml5TreeBuilder::generateImpliedEndTags()
3381 for (;;) {
3382 switch (stack[currentPtr]->getGroup()) {
3383 case P:
3384 case LI:
3385 case DD_OR_DT:
3386 case OPTION:
3387 case OPTGROUP:
3388 case RB_OR_RTC:
3389 case RT_OR_RP: {
3390 pop();
3391 continue;
3393 default: {
3394 return;
3400 bool
3401 nsHtml5TreeBuilder::isSecondOnStackBody()
3403 return currentPtr >= 1 && stack[1]->getGroup() == nsHtml5TreeBuilder::BODY;
3406 void
3407 nsHtml5TreeBuilder::documentModeInternal(
3408 nsHtml5DocumentMode m,
3409 nsHtml5String publicIdentifier,
3410 nsHtml5String systemIdentifier,
3411 bool html4SpecificAdditionalErrorChecks)
3413 if (isSrcdocDocument) {
3414 quirks = false;
3415 this->documentMode(STANDARDS_MODE);
3416 return;
3418 quirks = (m == QUIRKS_MODE);
3419 this->documentMode(m);
3422 bool
3423 nsHtml5TreeBuilder::isAlmostStandards(nsHtml5String publicIdentifier,
3424 nsHtml5String systemIdentifier)
3426 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3427 "-//w3c//dtd xhtml 1.0 transitional//en", publicIdentifier)) {
3428 return true;
3430 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3431 "-//w3c//dtd xhtml 1.0 frameset//en", publicIdentifier)) {
3432 return true;
3434 if (systemIdentifier) {
3435 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3436 "-//w3c//dtd html 4.01 transitional//en", publicIdentifier)) {
3437 return true;
3439 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3440 "-//w3c//dtd html 4.01 frameset//en", publicIdentifier)) {
3441 return true;
3444 return false;
3447 bool
3448 nsHtml5TreeBuilder::isQuirky(nsAtom* name,
3449 nsHtml5String publicIdentifier,
3450 nsHtml5String systemIdentifier,
3451 bool forceQuirks)
3453 if (forceQuirks) {
3454 return true;
3456 if (name != nsGkAtoms::html) {
3457 return true;
3459 if (publicIdentifier) {
3460 for (int32_t i = 0; i < nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS.length; i++) {
3461 if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(
3462 nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS[i], publicIdentifier)) {
3463 return true;
3466 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3467 "-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier) ||
3468 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3469 "-/w3c/dtd html 4.0 transitional/en", publicIdentifier) ||
3470 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3471 "html", publicIdentifier)) {
3472 return true;
3475 if (!systemIdentifier) {
3476 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3477 "-//w3c//dtd html 4.01 transitional//en", publicIdentifier)) {
3478 return true;
3479 } else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3480 "-//w3c//dtd html 4.01 frameset//en", publicIdentifier)) {
3481 return true;
3483 } else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
3484 "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd",
3485 systemIdentifier)) {
3486 return true;
3488 return false;
3491 void
3492 nsHtml5TreeBuilder::closeTheCell(int32_t eltPos)
3494 generateImpliedEndTags();
3495 if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
3496 errUnclosedElementsCell(eltPos);
3498 while (currentPtr >= eltPos) {
3499 pop();
3501 clearTheListOfActiveFormattingElementsUpToTheLastMarker();
3502 mode = IN_ROW;
3503 return;
3506 int32_t
3507 nsHtml5TreeBuilder::findLastInTableScopeTdTh()
3509 for (int32_t i = currentPtr; i > 0; i--) {
3510 nsAtom* name = stack[i]->name;
3511 if (stack[i]->ns == kNameSpaceID_XHTML) {
3512 if (nsGkAtoms::td == name || nsGkAtoms::th == name) {
3513 return i;
3514 } else if (name == nsGkAtoms::table || name == nsGkAtoms::_template) {
3515 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3519 return nsHtml5TreeBuilder::NOT_FOUND_ON_STACK;
3522 void
3523 nsHtml5TreeBuilder::clearStackBackTo(int32_t eltPos)
3525 int32_t eltGroup = stack[eltPos]->getGroup();
3526 while (currentPtr > eltPos) {
3527 if (stack[currentPtr]->ns == kNameSpaceID_XHTML &&
3528 stack[currentPtr]->getGroup() == TEMPLATE &&
3529 (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT ||
3530 eltGroup == TR || !eltPos)) {
3531 return;
3533 pop();
3537 void
3538 nsHtml5TreeBuilder::resetTheInsertionMode()
3540 nsHtml5StackNode* node;
3541 nsAtom* name;
3542 int32_t ns;
3543 for (int32_t i = currentPtr; i >= 0; i--) {
3544 node = stack[i];
3545 name = node->name;
3546 ns = node->ns;
3547 if (!i) {
3548 if (!(contextNamespace == kNameSpaceID_XHTML &&
3549 (contextName == nsGkAtoms::td || contextName == nsGkAtoms::th))) {
3550 if (fragment) {
3551 name = contextName;
3552 ns = contextNamespace;
3554 } else {
3555 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3556 return;
3559 if (nsGkAtoms::select == name) {
3560 int32_t ancestorIndex = i;
3561 while (ancestorIndex > 0) {
3562 nsHtml5StackNode* ancestor = stack[ancestorIndex--];
3563 if (kNameSpaceID_XHTML == ancestor->ns) {
3564 if (nsGkAtoms::_template == ancestor->name) {
3565 break;
3567 if (nsGkAtoms::table == ancestor->name) {
3568 mode = IN_SELECT_IN_TABLE;
3569 return;
3573 mode = IN_SELECT;
3574 return;
3575 } else if (nsGkAtoms::td == name || nsGkAtoms::th == name) {
3576 mode = IN_CELL;
3577 return;
3578 } else if (nsGkAtoms::tr == name) {
3579 mode = IN_ROW;
3580 return;
3581 } else if (nsGkAtoms::tbody == name || nsGkAtoms::thead == name ||
3582 nsGkAtoms::tfoot == name) {
3583 mode = IN_TABLE_BODY;
3584 return;
3585 } else if (nsGkAtoms::caption == name) {
3586 mode = IN_CAPTION;
3587 return;
3588 } else if (nsGkAtoms::colgroup == name) {
3589 mode = IN_COLUMN_GROUP;
3590 return;
3591 } else if (nsGkAtoms::table == name) {
3592 mode = IN_TABLE;
3593 return;
3594 } else if (kNameSpaceID_XHTML != ns) {
3595 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3596 return;
3597 } else if (nsGkAtoms::_template == name) {
3598 MOZ_ASSERT(templateModePtr >= 0);
3599 mode = templateModeStack[templateModePtr];
3600 return;
3601 } else if (nsGkAtoms::head == name) {
3602 if (name == contextName) {
3603 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3604 } else {
3605 mode = IN_HEAD;
3607 return;
3608 } else if (nsGkAtoms::body == name) {
3609 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3610 return;
3611 } else if (nsGkAtoms::frameset == name) {
3612 mode = IN_FRAMESET;
3613 return;
3614 } else if (nsGkAtoms::html == name) {
3615 if (!headPointer) {
3616 mode = BEFORE_HEAD;
3617 } else {
3618 mode = AFTER_HEAD;
3620 return;
3621 } else if (!i) {
3622 mode = framesetOk ? FRAMESET_OK : IN_BODY;
3623 return;
3628 void
3629 nsHtml5TreeBuilder::implicitlyCloseP()
3631 int32_t eltPos = findLastInButtonScope(nsGkAtoms::p);
3632 if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
3633 return;
3635 generateImpliedEndTagsExceptFor(nsGkAtoms::p);
3636 if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
3637 errUnclosedElementsImplied(eltPos, nsGkAtoms::p);
3639 while (currentPtr >= eltPos) {
3640 pop();
3644 bool
3645 nsHtml5TreeBuilder::debugOnlyClearLastStackSlot()
3647 stack[currentPtr] = nullptr;
3648 return true;
3651 bool
3652 nsHtml5TreeBuilder::debugOnlyClearLastListSlot()
3654 listOfActiveFormattingElements[listPtr] = nullptr;
3655 return true;
3658 void
3659 nsHtml5TreeBuilder::pushTemplateMode(int32_t mode)
3661 templateModePtr++;
3662 if (templateModePtr == templateModeStack.length) {
3663 jArray<int32_t, int32_t> newStack =
3664 jArray<int32_t, int32_t>::newJArray(templateModeStack.length + 64);
3665 nsHtml5ArrayCopy::arraycopy(
3666 templateModeStack, newStack, templateModeStack.length);
3667 templateModeStack = newStack;
3669 templateModeStack[templateModePtr] = mode;
3672 void
3673 nsHtml5TreeBuilder::push(nsHtml5StackNode* node)
3675 currentPtr++;
3676 if (currentPtr == stack.length) {
3677 jArray<nsHtml5StackNode*, int32_t> newStack =
3678 jArray<nsHtml5StackNode*, int32_t>::newJArray(stack.length + 64);
3679 nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length);
3680 stack = newStack;
3682 stack[currentPtr] = node;
3683 elementPushed(node->ns, node->popName, node->node);
3686 void
3687 nsHtml5TreeBuilder::silentPush(nsHtml5StackNode* node)
3689 currentPtr++;
3690 if (currentPtr == stack.length) {
3691 jArray<nsHtml5StackNode*, int32_t> newStack =
3692 jArray<nsHtml5StackNode*, int32_t>::newJArray(stack.length + 64);
3693 nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length);
3694 stack = newStack;
3696 stack[currentPtr] = node;
3699 void
3700 nsHtml5TreeBuilder::append(nsHtml5StackNode* node)
3702 listPtr++;
3703 if (listPtr == listOfActiveFormattingElements.length) {
3704 jArray<nsHtml5StackNode*, int32_t> newList =
3705 jArray<nsHtml5StackNode*, int32_t>::newJArray(
3706 listOfActiveFormattingElements.length + 64);
3707 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements,
3708 newList,
3709 listOfActiveFormattingElements.length);
3710 listOfActiveFormattingElements = newList;
3712 listOfActiveFormattingElements[listPtr] = node;
3715 void
3716 nsHtml5TreeBuilder::clearTheListOfActiveFormattingElementsUpToTheLastMarker()
3718 while (listPtr > -1) {
3719 if (!listOfActiveFormattingElements[listPtr]) {
3720 --listPtr;
3721 return;
3723 listOfActiveFormattingElements[listPtr]->release(this);
3724 --listPtr;
3728 void
3729 nsHtml5TreeBuilder::removeFromStack(int32_t pos)
3731 if (currentPtr == pos) {
3732 pop();
3733 } else {
3735 stack[pos]->release(this);
3736 nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos);
3737 MOZ_ASSERT(debugOnlyClearLastStackSlot());
3738 currentPtr--;
3742 void
3743 nsHtml5TreeBuilder::removeFromStack(nsHtml5StackNode* node)
3745 if (stack[currentPtr] == node) {
3746 pop();
3747 } else {
3748 int32_t pos = currentPtr - 1;
3749 while (pos >= 0 && stack[pos] != node) {
3750 pos--;
3752 if (pos == -1) {
3753 return;
3756 node->release(this);
3757 nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos);
3758 currentPtr--;
3762 void
3763 nsHtml5TreeBuilder::removeFromListOfActiveFormattingElements(int32_t pos)
3765 MOZ_ASSERT(!!listOfActiveFormattingElements[pos]);
3766 listOfActiveFormattingElements[pos]->release(this);
3767 if (pos == listPtr) {
3768 MOZ_ASSERT(debugOnlyClearLastListSlot());
3769 listPtr--;
3770 return;
3772 MOZ_ASSERT(pos < listPtr);
3773 nsHtml5ArrayCopy::arraycopy(
3774 listOfActiveFormattingElements, pos + 1, pos, listPtr - pos);
3775 MOZ_ASSERT(debugOnlyClearLastListSlot());
3776 listPtr--;
3779 bool
3780 nsHtml5TreeBuilder::adoptionAgencyEndTag(nsAtom* name)
3782 if (stack[currentPtr]->ns == kNameSpaceID_XHTML &&
3783 stack[currentPtr]->name == name &&
3784 findInListOfActiveFormattingElements(stack[currentPtr]) == -1) {
3785 pop();
3786 return true;
3788 for (int32_t i = 0; i < 8; ++i) {
3789 int32_t formattingEltListPos = listPtr;
3790 while (formattingEltListPos > -1) {
3791 nsHtml5StackNode* listNode =
3792 listOfActiveFormattingElements[formattingEltListPos];
3793 if (!listNode) {
3794 formattingEltListPos = -1;
3795 break;
3796 } else if (listNode->name == name) {
3797 break;
3799 formattingEltListPos--;
3801 if (formattingEltListPos == -1) {
3802 return false;
3804 nsHtml5StackNode* formattingElt =
3805 listOfActiveFormattingElements[formattingEltListPos];
3806 int32_t formattingEltStackPos = currentPtr;
3807 bool inScope = true;
3808 while (formattingEltStackPos > -1) {
3809 nsHtml5StackNode* node = stack[formattingEltStackPos];
3810 if (node == formattingElt) {
3811 break;
3812 } else if (node->isScoping()) {
3813 inScope = false;
3815 formattingEltStackPos--;
3817 if (formattingEltStackPos == -1) {
3818 errNoElementToCloseButEndTagSeen(name);
3819 removeFromListOfActiveFormattingElements(formattingEltListPos);
3820 return true;
3822 if (!inScope) {
3823 errNoElementToCloseButEndTagSeen(name);
3824 return true;
3826 if (formattingEltStackPos != currentPtr) {
3827 errEndTagViolatesNestingRules(name);
3829 int32_t furthestBlockPos = formattingEltStackPos + 1;
3830 while (furthestBlockPos <= currentPtr) {
3831 nsHtml5StackNode* node = stack[furthestBlockPos];
3832 MOZ_ASSERT(furthestBlockPos > 0,
3833 "How is formattingEltStackPos + 1 not > 0?");
3834 if (node->isSpecial()) {
3835 break;
3837 furthestBlockPos++;
3839 if (furthestBlockPos > currentPtr) {
3840 while (currentPtr >= formattingEltStackPos) {
3841 pop();
3843 removeFromListOfActiveFormattingElements(formattingEltListPos);
3844 return true;
3846 nsHtml5StackNode* commonAncestor = stack[formattingEltStackPos - 1];
3847 nsHtml5StackNode* furthestBlock = stack[furthestBlockPos];
3848 int32_t bookmark = formattingEltListPos;
3849 int32_t nodePos = furthestBlockPos;
3850 nsHtml5StackNode* lastNode = furthestBlock;
3851 int32_t j = 0;
3852 for (;;) {
3853 ++j;
3854 nodePos--;
3855 if (nodePos == formattingEltStackPos) {
3856 break;
3858 nsHtml5StackNode* node = stack[nodePos];
3859 int32_t nodeListPos = findInListOfActiveFormattingElements(node);
3860 if (j > 3 && nodeListPos != -1) {
3861 removeFromListOfActiveFormattingElements(nodeListPos);
3862 if (nodeListPos <= formattingEltListPos) {
3863 formattingEltListPos--;
3865 if (nodeListPos <= bookmark) {
3866 bookmark--;
3868 nodeListPos = -1;
3870 if (nodeListPos == -1) {
3871 MOZ_ASSERT(formattingEltStackPos < nodePos);
3872 MOZ_ASSERT(bookmark < nodePos);
3873 MOZ_ASSERT(furthestBlockPos > nodePos);
3874 removeFromStack(nodePos);
3875 furthestBlockPos--;
3876 continue;
3878 if (nodePos == furthestBlockPos) {
3879 bookmark = nodeListPos + 1;
3881 MOZ_ASSERT(node == listOfActiveFormattingElements[nodeListPos]);
3882 MOZ_ASSERT(node == stack[nodePos]);
3883 nsIContentHandle* clone =
3884 createElement(kNameSpaceID_XHTML,
3885 node->name,
3886 node->attributes->cloneAttributes(nullptr),
3887 commonAncestor->node,
3888 htmlCreator(node->getHtmlCreator()));
3889 nsHtml5StackNode* newNode = createStackNode(node->getFlags(),
3890 node->ns,
3891 node->name,
3892 clone,
3893 node->popName,
3894 node->attributes,
3895 node->getHtmlCreator());
3896 node->dropAttributes();
3897 stack[nodePos] = newNode;
3898 newNode->retain();
3899 listOfActiveFormattingElements[nodeListPos] = newNode;
3900 node->release(this);
3901 node->release(this);
3902 node = newNode;
3903 detachFromParent(lastNode->node);
3904 appendElement(lastNode->node, node->node);
3905 lastNode = node;
3907 if (commonAncestor->isFosterParenting()) {
3909 detachFromParent(lastNode->node);
3910 insertIntoFosterParent(lastNode->node);
3911 } else {
3912 detachFromParent(lastNode->node);
3913 appendElement(lastNode->node, commonAncestor->node);
3915 nsIContentHandle* clone =
3916 createElement(kNameSpaceID_XHTML,
3917 formattingElt->name,
3918 formattingElt->attributes->cloneAttributes(nullptr),
3919 furthestBlock->node,
3920 htmlCreator(formattingElt->getHtmlCreator()));
3921 nsHtml5StackNode* formattingClone =
3922 createStackNode(formattingElt->getFlags(),
3923 formattingElt->ns,
3924 formattingElt->name,
3925 clone,
3926 formattingElt->popName,
3927 formattingElt->attributes,
3928 formattingElt->getHtmlCreator());
3929 formattingElt->dropAttributes();
3930 appendChildrenToNewParent(furthestBlock->node, clone);
3931 appendElement(clone, furthestBlock->node);
3932 removeFromListOfActiveFormattingElements(formattingEltListPos);
3933 insertIntoListOfActiveFormattingElements(formattingClone, bookmark);
3934 MOZ_ASSERT(formattingEltStackPos < furthestBlockPos);
3935 removeFromStack(formattingEltStackPos);
3936 insertIntoStack(formattingClone, furthestBlockPos);
3938 return true;
3941 void
3942 nsHtml5TreeBuilder::insertIntoStack(nsHtml5StackNode* node, int32_t position)
3944 MOZ_ASSERT(currentPtr + 1 < stack.length);
3945 MOZ_ASSERT(position <= currentPtr + 1);
3946 if (position == currentPtr + 1) {
3947 push(node);
3948 } else {
3949 nsHtml5ArrayCopy::arraycopy(
3950 stack, position, position + 1, (currentPtr - position) + 1);
3951 currentPtr++;
3952 stack[position] = node;
3956 void
3957 nsHtml5TreeBuilder::insertIntoListOfActiveFormattingElements(
3958 nsHtml5StackNode* formattingClone,
3959 int32_t bookmark)
3961 formattingClone->retain();
3962 MOZ_ASSERT(listPtr + 1 < listOfActiveFormattingElements.length);
3963 if (bookmark <= listPtr) {
3964 nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements,
3965 bookmark,
3966 bookmark + 1,
3967 (listPtr - bookmark) + 1);
3969 listPtr++;
3970 listOfActiveFormattingElements[bookmark] = formattingClone;
3973 int32_t
3974 nsHtml5TreeBuilder::findInListOfActiveFormattingElements(nsHtml5StackNode* node)
3976 for (int32_t i = listPtr; i >= 0; i--) {
3977 if (node == listOfActiveFormattingElements[i]) {
3978 return i;
3981 return -1;
3984 int32_t
3985 nsHtml5TreeBuilder::
3986 findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
3987 nsAtom* name)
3989 for (int32_t i = listPtr; i >= 0; i--) {
3990 nsHtml5StackNode* node = listOfActiveFormattingElements[i];
3991 if (!node) {
3992 return -1;
3993 } else if (node->name == name) {
3994 return i;
3997 return -1;
4000 void
4001 nsHtml5TreeBuilder::maybeForgetEarlierDuplicateFormattingElement(
4002 nsAtom* name,
4003 nsHtml5HtmlAttributes* attributes)
4005 int32_t candidate = -1;
4006 int32_t count = 0;
4007 for (int32_t i = listPtr; i >= 0; i--) {
4008 nsHtml5StackNode* node = listOfActiveFormattingElements[i];
4009 if (!node) {
4010 break;
4012 if (node->name == name && node->attributes->equalsAnother(attributes)) {
4013 candidate = i;
4014 ++count;
4017 if (count >= 3) {
4018 removeFromListOfActiveFormattingElements(candidate);
4022 int32_t
4023 nsHtml5TreeBuilder::findLastOrRoot(nsAtom* name)
4025 for (int32_t i = currentPtr; i > 0; i--) {
4026 if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
4027 return i;
4030 return 0;
4033 int32_t
4034 nsHtml5TreeBuilder::findLastOrRoot(int32_t group)
4036 for (int32_t i = currentPtr; i > 0; i--) {
4037 if (stack[i]->getGroup() == group) {
4038 return i;
4041 return 0;
4044 bool
4045 nsHtml5TreeBuilder::addAttributesToBody(nsHtml5HtmlAttributes* attributes)
4047 if (currentPtr >= 1) {
4048 nsHtml5StackNode* body = stack[1];
4049 if (body->getGroup() == nsHtml5TreeBuilder::BODY) {
4050 addAttributesToElement(body->node, attributes);
4051 return true;
4054 return false;
4057 void
4058 nsHtml5TreeBuilder::addAttributesToHtml(nsHtml5HtmlAttributes* attributes)
4060 addAttributesToElement(stack[0]->node, attributes);
4063 void
4064 nsHtml5TreeBuilder::pushHeadPointerOntoStack()
4066 MOZ_ASSERT(!!headPointer);
4067 MOZ_ASSERT(mode == AFTER_HEAD);
4069 silentPush(createStackNode(nsHtml5ElementName::ELT_HEAD, headPointer));
4072 void
4073 nsHtml5TreeBuilder::reconstructTheActiveFormattingElements()
4075 if (listPtr == -1) {
4076 return;
4078 nsHtml5StackNode* mostRecent = listOfActiveFormattingElements[listPtr];
4079 if (!mostRecent || isInStack(mostRecent)) {
4080 return;
4082 int32_t entryPos = listPtr;
4083 for (;;) {
4084 entryPos--;
4085 if (entryPos == -1) {
4086 break;
4088 if (!listOfActiveFormattingElements[entryPos]) {
4089 break;
4091 if (isInStack(listOfActiveFormattingElements[entryPos])) {
4092 break;
4095 while (entryPos < listPtr) {
4096 entryPos++;
4097 nsHtml5StackNode* entry = listOfActiveFormattingElements[entryPos];
4098 nsHtml5StackNode* currentNode = stack[currentPtr];
4099 nsIContentHandle* clone;
4100 if (currentNode->isFosterParenting()) {
4101 clone = createAndInsertFosterParentedElement(
4102 kNameSpaceID_XHTML,
4103 entry->name,
4104 entry->attributes->cloneAttributes(nullptr),
4105 htmlCreator(entry->getHtmlCreator()));
4106 } else {
4107 clone = createElement(kNameSpaceID_XHTML,
4108 entry->name,
4109 entry->attributes->cloneAttributes(nullptr),
4110 currentNode->node,
4111 htmlCreator(entry->getHtmlCreator()));
4112 appendElement(clone, currentNode->node);
4114 nsHtml5StackNode* entryClone = createStackNode(entry->getFlags(),
4115 entry->ns,
4116 entry->name,
4117 clone,
4118 entry->popName,
4119 entry->attributes,
4120 entry->getHtmlCreator());
4121 entry->dropAttributes();
4122 push(entryClone);
4123 listOfActiveFormattingElements[entryPos] = entryClone;
4124 entry->release(this);
4125 entryClone->retain();
4129 void
4130 nsHtml5TreeBuilder::notifyUnusedStackNode(int32_t idxInStackNodes)
4132 if (idxInStackNodes < stackNodesIdx) {
4133 stackNodesIdx = idxInStackNodes;
4137 nsHtml5StackNode*
4138 nsHtml5TreeBuilder::getUnusedStackNode()
4140 while (stackNodesIdx < numStackNodes) {
4141 if (stackNodes[stackNodesIdx]->isUnused()) {
4142 return stackNodes[stackNodesIdx++];
4144 stackNodesIdx++;
4146 if (stackNodesIdx < stackNodes.length) {
4147 stackNodes[stackNodesIdx] = new nsHtml5StackNode(stackNodesIdx);
4148 numStackNodes++;
4149 return stackNodes[stackNodesIdx++];
4151 jArray<nsHtml5StackNode*, int32_t> newStack =
4152 jArray<nsHtml5StackNode*, int32_t>::newJArray(stackNodes.length + 64);
4153 nsHtml5ArrayCopy::arraycopy(stackNodes, newStack, stackNodes.length);
4154 stackNodes = newStack;
4155 stackNodes[stackNodesIdx] = new nsHtml5StackNode(stackNodesIdx);
4156 numStackNodes++;
4157 return stackNodes[stackNodesIdx++];
4160 nsHtml5StackNode*
4161 nsHtml5TreeBuilder::createStackNode(
4162 int32_t flags,
4163 int32_t ns,
4164 nsAtom* name,
4165 nsIContentHandle* node,
4166 nsAtom* popName,
4167 nsHtml5HtmlAttributes* attributes,
4168 mozilla::dom::HTMLContentCreatorFunction htmlCreator)
4170 nsHtml5StackNode* instance = getUnusedStackNode();
4171 instance->setValues(flags, ns, name, node, popName, attributes, htmlCreator);
4172 return instance;
4175 nsHtml5StackNode*
4176 nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName* elementName,
4177 nsIContentHandle* node)
4179 nsHtml5StackNode* instance = getUnusedStackNode();
4180 instance->setValues(elementName, node);
4181 return instance;
4184 nsHtml5StackNode*
4185 nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName* elementName,
4186 nsIContentHandle* node,
4187 nsHtml5HtmlAttributes* attributes)
4189 nsHtml5StackNode* instance = getUnusedStackNode();
4190 instance->setValues(elementName, node, attributes);
4191 return instance;
4194 nsHtml5StackNode*
4195 nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName* elementName,
4196 nsIContentHandle* node,
4197 nsAtom* popName)
4199 nsHtml5StackNode* instance = getUnusedStackNode();
4200 instance->setValues(elementName, node, popName);
4201 return instance;
4204 nsHtml5StackNode*
4205 nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName* elementName,
4206 nsAtom* popName,
4207 nsIContentHandle* node)
4209 nsHtml5StackNode* instance = getUnusedStackNode();
4210 instance->setValues(elementName, popName, node);
4211 return instance;
4214 nsHtml5StackNode*
4215 nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName* elementName,
4216 nsIContentHandle* node,
4217 nsAtom* popName,
4218 bool markAsIntegrationPoint)
4220 nsHtml5StackNode* instance = getUnusedStackNode();
4221 instance->setValues(elementName, node, popName, markAsIntegrationPoint);
4222 return instance;
4225 void
4226 nsHtml5TreeBuilder::insertIntoFosterParent(nsIContentHandle* child)
4228 int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
4229 int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
4230 if (templatePos >= tablePos) {
4231 appendElement(child, stack[templatePos]->node);
4232 return;
4234 nsHtml5StackNode* node = stack[tablePos];
4235 insertFosterParentedChild(child, node->node, stack[tablePos - 1]->node);
4238 nsIContentHandle*
4239 nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
4240 int32_t ns,
4241 nsAtom* name,
4242 nsHtml5HtmlAttributes* attributes,
4243 nsHtml5ContentCreatorFunction creator)
4245 return createAndInsertFosterParentedElement(
4246 ns, name, attributes, nullptr, creator);
4249 nsIContentHandle*
4250 nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
4251 int32_t ns,
4252 nsAtom* name,
4253 nsHtml5HtmlAttributes* attributes,
4254 nsIContentHandle* form,
4255 nsHtml5ContentCreatorFunction creator)
4257 int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
4258 int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
4259 if (templatePos >= tablePos) {
4260 nsIContentHandle* child = createElement(
4261 ns, name, attributes, form, stack[templatePos]->node, creator);
4262 appendElement(child, stack[templatePos]->node);
4263 return child;
4265 nsHtml5StackNode* node = stack[tablePos];
4266 return createAndInsertFosterParentedElement(
4267 ns, name, attributes, form, node->node, stack[tablePos - 1]->node, creator);
4270 bool
4271 nsHtml5TreeBuilder::isInStack(nsHtml5StackNode* node)
4273 for (int32_t i = currentPtr; i >= 0; i--) {
4274 if (stack[i] == node) {
4275 return true;
4278 return false;
4281 void
4282 nsHtml5TreeBuilder::popTemplateMode()
4284 templateModePtr--;
4287 void
4288 nsHtml5TreeBuilder::pop()
4290 nsHtml5StackNode* node = stack[currentPtr];
4291 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4292 currentPtr--;
4293 elementPopped(node->ns, node->popName, node->node);
4294 node->release(this);
4297 void
4298 nsHtml5TreeBuilder::silentPop()
4300 nsHtml5StackNode* node = stack[currentPtr];
4301 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4302 currentPtr--;
4303 node->release(this);
4306 void
4307 nsHtml5TreeBuilder::popOnEof()
4309 nsHtml5StackNode* node = stack[currentPtr];
4310 MOZ_ASSERT(debugOnlyClearLastStackSlot());
4311 currentPtr--;
4312 markMalformedIfScript(node->node);
4313 elementPopped(node->ns, node->popName, node->node);
4314 node->release(this);
4317 void
4318 nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush(
4319 nsHtml5HtmlAttributes* attributes)
4321 nsIContentHandle* elt = createHtmlElementSetAsRoot(attributes);
4322 nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HTML, elt);
4323 push(node);
4326 void
4327 nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush()
4329 appendHtmlElementToDocumentAndPush(tokenizer->emptyAttributes());
4332 void
4333 nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(
4334 nsHtml5HtmlAttributes* attributes)
4336 nsIContentHandle* currentNode = stack[currentPtr]->node;
4337 nsIContentHandle* elt = createElement(kNameSpaceID_XHTML,
4338 nsGkAtoms::head,
4339 attributes,
4340 currentNode,
4341 htmlCreator(NS_NewHTMLSharedElement));
4342 appendElement(elt, currentNode);
4343 headPointer = elt;
4344 nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HEAD, elt);
4345 push(node);
4348 void
4349 nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement(
4350 nsHtml5HtmlAttributes* attributes)
4352 appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_BODY, attributes);
4355 void
4356 nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement()
4358 appendToCurrentNodeAndPushBodyElement(tokenizer->emptyAttributes());
4361 void
4362 nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(
4363 nsHtml5HtmlAttributes* attributes)
4365 nsIContentHandle* elt;
4366 nsHtml5StackNode* current = stack[currentPtr];
4367 if (current->isFosterParenting()) {
4369 elt =
4370 createAndInsertFosterParentedElement(kNameSpaceID_XHTML,
4371 nsGkAtoms::form,
4372 attributes,
4373 htmlCreator(NS_NewHTMLFormElement));
4374 } else {
4375 elt = createElement(kNameSpaceID_XHTML,
4376 nsGkAtoms::form,
4377 attributes,
4378 current->node,
4379 htmlCreator(NS_NewHTMLFormElement));
4380 appendElement(elt, current->node);
4382 if (!isTemplateContents()) {
4383 formPointer = elt;
4385 nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_FORM, elt);
4386 push(node);
4389 void
4390 nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(
4391 nsHtml5ElementName* elementName,
4392 nsHtml5HtmlAttributes* attributes)
4394 nsHtml5HtmlAttributes* clone = attributes->cloneAttributes(nullptr);
4395 nsIContentHandle* elt;
4396 nsHtml5StackNode* current = stack[currentPtr];
4397 if (current->isFosterParenting()) {
4399 elt = createAndInsertFosterParentedElement(
4400 kNameSpaceID_XHTML,
4401 elementName->getName(),
4402 attributes,
4403 htmlCreator(elementName->getHtmlCreator()));
4404 } else {
4405 elt = createElement(kNameSpaceID_XHTML,
4406 elementName->getName(),
4407 attributes,
4408 current->node,
4409 htmlCreator(elementName->getHtmlCreator()));
4410 appendElement(elt, current->node);
4412 nsHtml5StackNode* node = createStackNode(elementName, elt, clone);
4413 push(node);
4414 append(node);
4415 node->retain();
4418 void
4419 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(
4420 nsHtml5ElementName* elementName,
4421 nsHtml5HtmlAttributes* attributes)
4423 nsIContentHandle* currentNode = stack[currentPtr]->node;
4424 nsIContentHandle* elt =
4425 createElement(kNameSpaceID_XHTML,
4426 elementName->getName(),
4427 attributes,
4428 currentNode,
4429 htmlCreator(elementName->getHtmlCreator()));
4430 appendElement(elt, currentNode);
4431 if (nsHtml5ElementName::ELT_TEMPLATE == elementName) {
4432 elt = getDocumentFragmentForTemplate(elt);
4434 nsHtml5StackNode* node = createStackNode(elementName, elt);
4435 push(node);
4438 void
4439 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
4440 nsHtml5ElementName* elementName,
4441 nsHtml5HtmlAttributes* attributes)
4443 nsAtom* popName = elementName->getName();
4444 nsIContentHandle* elt;
4445 nsHtml5StackNode* current = stack[currentPtr];
4446 if (current->isFosterParenting()) {
4448 elt = createAndInsertFosterParentedElement(
4449 kNameSpaceID_XHTML,
4450 popName,
4451 attributes,
4452 htmlCreator(elementName->getHtmlCreator()));
4453 } else {
4454 elt = createElement(kNameSpaceID_XHTML,
4455 popName,
4456 attributes,
4457 current->node,
4458 htmlCreator(elementName->getHtmlCreator()));
4459 appendElement(elt, current->node);
4461 nsHtml5StackNode* node = createStackNode(elementName, elt, popName);
4462 push(node);
4465 void
4466 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(
4467 nsHtml5ElementName* elementName,
4468 nsHtml5HtmlAttributes* attributes)
4470 nsAtom* popName = elementName->getName();
4471 bool markAsHtmlIntegrationPoint = false;
4472 if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName &&
4473 annotationXmlEncodingPermitsHtml(attributes)) {
4474 markAsHtmlIntegrationPoint = true;
4476 nsIContentHandle* elt;
4477 nsHtml5StackNode* current = stack[currentPtr];
4478 if (current->isFosterParenting()) {
4480 elt = createAndInsertFosterParentedElement(
4481 kNameSpaceID_MathML, popName, attributes, htmlCreator(nullptr));
4482 } else {
4483 elt = createElement(kNameSpaceID_MathML,
4484 popName,
4485 attributes,
4486 current->node,
4487 htmlCreator(nullptr));
4488 appendElement(elt, current->node);
4490 nsHtml5StackNode* node =
4491 createStackNode(elementName, elt, popName, markAsHtmlIntegrationPoint);
4492 push(node);
4495 bool
4496 nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(
4497 nsHtml5HtmlAttributes* attributes)
4499 nsHtml5String encoding =
4500 attributes->getValue(nsHtml5AttributeName::ATTR_ENCODING);
4501 if (!encoding) {
4502 return false;
4504 return nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
4505 "application/xhtml+xml", encoding) ||
4506 nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
4507 "text/html", encoding);
4510 void
4511 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(
4512 nsHtml5ElementName* elementName,
4513 nsHtml5HtmlAttributes* attributes)
4515 nsAtom* popName = elementName->getCamelCaseName();
4516 nsIContentHandle* elt;
4517 nsHtml5StackNode* current = stack[currentPtr];
4518 if (current->isFosterParenting()) {
4520 elt = createAndInsertFosterParentedElement(
4521 kNameSpaceID_SVG,
4522 popName,
4523 attributes,
4524 svgCreator(elementName->getSvgCreator()));
4525 } else {
4526 elt = createElement(kNameSpaceID_SVG,
4527 popName,
4528 attributes,
4529 current->node,
4530 svgCreator(elementName->getSvgCreator()));
4531 appendElement(elt, current->node);
4533 nsHtml5StackNode* node = createStackNode(elementName, popName, elt);
4534 push(node);
4537 void
4538 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(
4539 nsHtml5ElementName* elementName,
4540 nsHtml5HtmlAttributes* attributes,
4541 nsIContentHandle* form)
4543 nsIContentHandle* elt;
4544 nsIContentHandle* formOwner =
4545 !form || fragment || isTemplateContents() ? nullptr : form;
4546 nsHtml5StackNode* current = stack[currentPtr];
4547 if (current->isFosterParenting()) {
4549 elt = createAndInsertFosterParentedElement(
4550 kNameSpaceID_XHTML,
4551 elementName->getName(),
4552 attributes,
4553 formOwner,
4554 htmlCreator(elementName->getHtmlCreator()));
4555 } else {
4556 elt = createElement(kNameSpaceID_XHTML,
4557 elementName->getName(),
4558 attributes,
4559 formOwner,
4560 current->node,
4561 htmlCreator(elementName->getHtmlCreator()));
4562 appendElement(elt, current->node);
4564 nsHtml5StackNode* node = createStackNode(elementName, elt);
4565 push(node);
4568 void
4569 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
4570 nsHtml5ElementName* elementName,
4571 nsHtml5HtmlAttributes* attributes,
4572 nsIContentHandle* form)
4574 nsAtom* name = elementName->getName();
4575 nsIContentHandle* elt;
4576 nsIContentHandle* formOwner =
4577 !form || fragment || isTemplateContents() ? nullptr : form;
4578 nsHtml5StackNode* current = stack[currentPtr];
4579 if (current->isFosterParenting()) {
4581 elt = createAndInsertFosterParentedElement(
4582 kNameSpaceID_XHTML,
4583 name,
4584 attributes,
4585 formOwner,
4586 htmlCreator(elementName->getHtmlCreator()));
4587 } else {
4588 elt = createElement(kNameSpaceID_XHTML,
4589 name,
4590 attributes,
4591 formOwner,
4592 current->node,
4593 htmlCreator(elementName->getHtmlCreator()));
4594 appendElement(elt, current->node);
4596 elementPushed(kNameSpaceID_XHTML, name, elt);
4597 elementPopped(kNameSpaceID_XHTML, name, elt);
4600 void
4601 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(
4602 nsHtml5ElementName* elementName,
4603 nsHtml5HtmlAttributes* attributes)
4605 nsAtom* popName = elementName->getName();
4606 nsIContentHandle* elt;
4607 nsHtml5StackNode* current = stack[currentPtr];
4608 if (current->isFosterParenting()) {
4610 elt = createAndInsertFosterParentedElement(
4611 kNameSpaceID_XHTML,
4612 popName,
4613 attributes,
4614 htmlCreator(elementName->getHtmlCreator()));
4615 } else {
4616 elt = createElement(kNameSpaceID_XHTML,
4617 popName,
4618 attributes,
4619 current->node,
4620 htmlCreator(elementName->getHtmlCreator()));
4621 appendElement(elt, current->node);
4623 elementPushed(kNameSpaceID_XHTML, popName, elt);
4624 elementPopped(kNameSpaceID_XHTML, popName, elt);
4627 void
4628 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(
4629 nsHtml5ElementName* elementName,
4630 nsHtml5HtmlAttributes* attributes)
4632 nsAtom* popName = elementName->getCamelCaseName();
4633 nsIContentHandle* elt;
4634 nsHtml5StackNode* current = stack[currentPtr];
4635 if (current->isFosterParenting()) {
4637 elt = createAndInsertFosterParentedElement(
4638 kNameSpaceID_SVG,
4639 popName,
4640 attributes,
4641 svgCreator(elementName->getSvgCreator()));
4642 } else {
4643 elt = createElement(kNameSpaceID_SVG,
4644 popName,
4645 attributes,
4646 current->node,
4647 svgCreator(elementName->getSvgCreator()));
4648 appendElement(elt, current->node);
4650 elementPushed(kNameSpaceID_SVG, popName, elt);
4651 elementPopped(kNameSpaceID_SVG, popName, elt);
4654 void
4655 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(
4656 nsHtml5ElementName* elementName,
4657 nsHtml5HtmlAttributes* attributes)
4659 nsAtom* popName = elementName->getName();
4660 nsIContentHandle* elt;
4661 nsHtml5StackNode* current = stack[currentPtr];
4662 if (current->isFosterParenting()) {
4664 elt = createAndInsertFosterParentedElement(
4665 kNameSpaceID_MathML, popName, attributes, htmlCreator(nullptr));
4666 } else {
4667 elt = createElement(kNameSpaceID_MathML,
4668 popName,
4669 attributes,
4670 current->node,
4671 htmlCreator(nullptr));
4672 appendElement(elt, current->node);
4674 elementPushed(kNameSpaceID_MathML, popName, elt);
4675 elementPopped(kNameSpaceID_MathML, popName, elt);
4678 void
4679 nsHtml5TreeBuilder::appendVoidInputToCurrent(nsHtml5HtmlAttributes* attributes,
4680 nsIContentHandle* form)
4682 nsIContentHandle* currentNode = stack[currentPtr]->node;
4683 nsIContentHandle* elt =
4684 createElement(kNameSpaceID_XHTML,
4685 nsGkAtoms::input,
4686 attributes,
4687 !form || fragment || isTemplateContents() ? nullptr : form,
4688 currentNode,
4689 htmlCreator(NS_NewHTMLInputElement));
4690 appendElement(elt, currentNode);
4691 elementPushed(kNameSpaceID_XHTML, nsGkAtoms::input, elt);
4692 elementPopped(kNameSpaceID_XHTML, nsGkAtoms::input, elt);
4695 void
4696 nsHtml5TreeBuilder::appendVoidFormToCurrent(nsHtml5HtmlAttributes* attributes)
4698 nsIContentHandle* currentNode = stack[currentPtr]->node;
4699 nsIContentHandle* elt = createElement(kNameSpaceID_XHTML,
4700 nsGkAtoms::form,
4701 attributes,
4702 currentNode,
4703 htmlCreator(NS_NewHTMLFormElement));
4704 formPointer = elt;
4705 appendElement(elt, currentNode);
4706 elementPushed(kNameSpaceID_XHTML, nsGkAtoms::form, elt);
4707 elementPopped(kNameSpaceID_XHTML, nsGkAtoms::form, elt);
4710 void
4711 nsHtml5TreeBuilder::requestSuspension()
4713 tokenizer->requestSuspension();
4717 bool
4718 nsHtml5TreeBuilder::isInForeign()
4720 return currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML;
4723 bool
4724 nsHtml5TreeBuilder::isInForeignButNotHtmlOrMathTextIntegrationPoint()
4726 if (currentPtr < 0) {
4727 return false;
4729 return !isSpecialParentInForeign(stack[currentPtr]);
4732 void
4733 nsHtml5TreeBuilder::setFragmentContext(nsAtom* context,
4734 int32_t ns,
4735 nsIContentHandle* node,
4736 bool quirks)
4738 this->contextName = context;
4739 this->contextNamespace = ns;
4740 this->contextNode = node;
4741 this->fragment = (!!contextName);
4742 this->quirks = quirks;
4745 nsIContentHandle*
4746 nsHtml5TreeBuilder::currentNode()
4748 return stack[currentPtr]->node;
4751 bool
4752 nsHtml5TreeBuilder::isScriptingEnabled()
4754 return scriptingEnabled;
4757 void
4758 nsHtml5TreeBuilder::setScriptingEnabled(bool scriptingEnabled)
4760 this->scriptingEnabled = scriptingEnabled;
4763 void
4764 nsHtml5TreeBuilder::setIsSrcdocDocument(bool isSrcdocDocument)
4766 this->isSrcdocDocument = isSrcdocDocument;
4769 void
4770 nsHtml5TreeBuilder::flushCharacters()
4772 if (charBufferLen > 0) {
4773 if ((mode == IN_TABLE || mode == IN_TABLE_BODY || mode == IN_ROW) &&
4774 charBufferContainsNonWhitespace()) {
4775 errNonSpaceInTable();
4776 reconstructTheActiveFormattingElements();
4777 if (!stack[currentPtr]->isFosterParenting()) {
4778 appendCharacters(currentNode(), charBuffer, 0, charBufferLen);
4779 charBufferLen = 0;
4780 return;
4782 int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
4783 int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
4784 if (templatePos >= tablePos) {
4785 appendCharacters(
4786 stack[templatePos]->node, charBuffer, 0, charBufferLen);
4787 charBufferLen = 0;
4788 return;
4790 nsHtml5StackNode* tableElt = stack[tablePos];
4791 insertFosterParentedCharacters(charBuffer,
4793 charBufferLen,
4794 tableElt->node,
4795 stack[tablePos - 1]->node);
4796 charBufferLen = 0;
4797 return;
4799 appendCharacters(currentNode(), charBuffer, 0, charBufferLen);
4800 charBufferLen = 0;
4804 bool
4805 nsHtml5TreeBuilder::charBufferContainsNonWhitespace()
4807 for (int32_t i = 0; i < charBufferLen; i++) {
4808 switch (charBuffer[i]) {
4809 case ' ':
4810 case '\t':
4811 case '\n':
4812 case '\r':
4813 case '\f': {
4814 continue;
4816 default: {
4817 return true;
4821 return false;
4824 nsAHtml5TreeBuilderState*
4825 nsHtml5TreeBuilder::newSnapshot()
4827 jArray<nsHtml5StackNode*, int32_t> listCopy =
4828 jArray<nsHtml5StackNode*, int32_t>::newJArray(listPtr + 1);
4829 for (int32_t i = 0; i < listCopy.length; i++) {
4830 nsHtml5StackNode* node = listOfActiveFormattingElements[i];
4831 if (node) {
4832 nsHtml5StackNode* newNode = new nsHtml5StackNode(-1);
4833 newNode->setValues(node->getFlags(),
4834 node->ns,
4835 node->name,
4836 node->node,
4837 node->popName,
4838 node->attributes->cloneAttributes(nullptr),
4839 node->getHtmlCreator());
4840 listCopy[i] = newNode;
4841 } else {
4842 listCopy[i] = nullptr;
4845 jArray<nsHtml5StackNode*, int32_t> stackCopy =
4846 jArray<nsHtml5StackNode*, int32_t>::newJArray(currentPtr + 1);
4847 for (int32_t i = 0; i < stackCopy.length; i++) {
4848 nsHtml5StackNode* node = stack[i];
4849 int32_t listIndex = findInListOfActiveFormattingElements(node);
4850 if (listIndex == -1) {
4851 nsHtml5StackNode* newNode = new nsHtml5StackNode(-1);
4852 newNode->setValues(node->getFlags(),
4853 node->ns,
4854 node->name,
4855 node->node,
4856 node->popName,
4857 nullptr,
4858 node->getHtmlCreator());
4859 stackCopy[i] = newNode;
4860 } else {
4861 stackCopy[i] = listCopy[listIndex];
4862 stackCopy[i]->retain();
4865 jArray<int32_t, int32_t> templateModeStackCopy =
4866 jArray<int32_t, int32_t>::newJArray(templateModePtr + 1);
4867 nsHtml5ArrayCopy::arraycopy(
4868 templateModeStack, templateModeStackCopy, templateModeStackCopy.length);
4869 return new nsHtml5StateSnapshot(stackCopy,
4870 listCopy,
4871 templateModeStackCopy,
4872 formPointer,
4873 headPointer,
4874 deepTreeSurrogateParent,
4875 mode,
4876 originalMode,
4877 framesetOk,
4878 needToDropLF,
4879 quirks);
4882 bool
4883 nsHtml5TreeBuilder::snapshotMatches(nsAHtml5TreeBuilderState* snapshot)
4885 jArray<nsHtml5StackNode*, int32_t> stackCopy = snapshot->getStack();
4886 int32_t stackLen = snapshot->getStackLength();
4887 jArray<nsHtml5StackNode*, int32_t> listCopy =
4888 snapshot->getListOfActiveFormattingElements();
4889 int32_t listLen = snapshot->getListOfActiveFormattingElementsLength();
4890 jArray<int32_t, int32_t> templateModeStackCopy =
4891 snapshot->getTemplateModeStack();
4892 int32_t templateModeStackLen = snapshot->getTemplateModeStackLength();
4893 if (stackLen != currentPtr + 1 || listLen != listPtr + 1 ||
4894 templateModeStackLen != templateModePtr + 1 ||
4895 formPointer != snapshot->getFormPointer() ||
4896 headPointer != snapshot->getHeadPointer() ||
4897 deepTreeSurrogateParent != snapshot->getDeepTreeSurrogateParent() ||
4898 mode != snapshot->getMode() ||
4899 originalMode != snapshot->getOriginalMode() ||
4900 framesetOk != snapshot->isFramesetOk() ||
4901 needToDropLF != snapshot->isNeedToDropLF() ||
4902 quirks != snapshot->isQuirks()) {
4903 return false;
4905 for (int32_t i = listLen - 1; i >= 0; i--) {
4906 if (!listCopy[i] && !listOfActiveFormattingElements[i]) {
4907 continue;
4908 } else if (!listCopy[i] || !listOfActiveFormattingElements[i]) {
4909 return false;
4911 if (listCopy[i]->node != listOfActiveFormattingElements[i]->node) {
4912 return false;
4915 for (int32_t i = stackLen - 1; i >= 0; i--) {
4916 if (stackCopy[i]->node != stack[i]->node) {
4917 return false;
4920 for (int32_t i = templateModeStackLen - 1; i >= 0; i--) {
4921 if (templateModeStackCopy[i] != templateModeStack[i]) {
4922 return false;
4925 return true;
4928 void
4929 nsHtml5TreeBuilder::loadState(nsAHtml5TreeBuilderState* snapshot,
4930 nsHtml5AtomTable* interner)
4932 mCurrentHtmlScriptIsAsyncOrDefer = false;
4933 jArray<nsHtml5StackNode*, int32_t> stackCopy = snapshot->getStack();
4934 int32_t stackLen = snapshot->getStackLength();
4935 jArray<nsHtml5StackNode*, int32_t> listCopy =
4936 snapshot->getListOfActiveFormattingElements();
4937 int32_t listLen = snapshot->getListOfActiveFormattingElementsLength();
4938 jArray<int32_t, int32_t> templateModeStackCopy =
4939 snapshot->getTemplateModeStack();
4940 int32_t templateModeStackLen = snapshot->getTemplateModeStackLength();
4941 for (int32_t i = 0; i <= listPtr; i++) {
4942 if (listOfActiveFormattingElements[i]) {
4943 listOfActiveFormattingElements[i]->release(this);
4946 if (listOfActiveFormattingElements.length < listLen) {
4947 listOfActiveFormattingElements =
4948 jArray<nsHtml5StackNode*, int32_t>::newJArray(listLen);
4950 listPtr = listLen - 1;
4951 for (int32_t i = 0; i <= currentPtr; i++) {
4952 stack[i]->release(this);
4954 if (stack.length < stackLen) {
4955 stack = jArray<nsHtml5StackNode*, int32_t>::newJArray(stackLen);
4957 currentPtr = stackLen - 1;
4958 if (templateModeStack.length < templateModeStackLen) {
4959 templateModeStack =
4960 jArray<int32_t, int32_t>::newJArray(templateModeStackLen);
4962 templateModePtr = templateModeStackLen - 1;
4963 for (int32_t i = 0; i < listLen; i++) {
4964 nsHtml5StackNode* node = listCopy[i];
4965 if (node) {
4966 nsHtml5StackNode* newNode = createStackNode(
4967 node->getFlags(),
4968 node->ns,
4969 nsHtml5Portability::newLocalFromLocal(node->name, interner),
4970 node->node,
4971 nsHtml5Portability::newLocalFromLocal(node->popName, interner),
4972 node->attributes->cloneAttributes(nullptr),
4973 node->getHtmlCreator());
4974 listOfActiveFormattingElements[i] = newNode;
4975 } else {
4976 listOfActiveFormattingElements[i] = nullptr;
4979 for (int32_t i = 0; i < stackLen; i++) {
4980 nsHtml5StackNode* node = stackCopy[i];
4981 int32_t listIndex = findInArray(node, listCopy);
4982 if (listIndex == -1) {
4983 nsHtml5StackNode* newNode = createStackNode(
4984 node->getFlags(),
4985 node->ns,
4986 nsHtml5Portability::newLocalFromLocal(node->name, interner),
4987 node->node,
4988 nsHtml5Portability::newLocalFromLocal(node->popName, interner),
4989 nullptr,
4990 node->getHtmlCreator());
4991 stack[i] = newNode;
4992 } else {
4993 stack[i] = listOfActiveFormattingElements[listIndex];
4994 stack[i]->retain();
4997 nsHtml5ArrayCopy::arraycopy(
4998 templateModeStackCopy, templateModeStack, templateModeStackLen);
4999 formPointer = snapshot->getFormPointer();
5000 headPointer = snapshot->getHeadPointer();
5001 deepTreeSurrogateParent = snapshot->getDeepTreeSurrogateParent();
5002 mode = snapshot->getMode();
5003 originalMode = snapshot->getOriginalMode();
5004 framesetOk = snapshot->isFramesetOk();
5005 needToDropLF = snapshot->isNeedToDropLF();
5006 quirks = snapshot->isQuirks();
5009 int32_t
5010 nsHtml5TreeBuilder::findInArray(nsHtml5StackNode* node,
5011 jArray<nsHtml5StackNode*, int32_t> arr)
5013 for (int32_t i = listPtr; i >= 0; i--) {
5014 if (node == arr[i]) {
5015 return i;
5018 return -1;
5021 nsIContentHandle*
5022 nsHtml5TreeBuilder::getFormPointer()
5024 return formPointer;
5027 nsIContentHandle*
5028 nsHtml5TreeBuilder::getHeadPointer()
5030 return headPointer;
5033 nsIContentHandle*
5034 nsHtml5TreeBuilder::getDeepTreeSurrogateParent()
5036 return deepTreeSurrogateParent;
5039 jArray<nsHtml5StackNode*, int32_t>
5040 nsHtml5TreeBuilder::getListOfActiveFormattingElements()
5042 return listOfActiveFormattingElements;
5045 jArray<nsHtml5StackNode*, int32_t>
5046 nsHtml5TreeBuilder::getStack()
5048 return stack;
5051 jArray<int32_t, int32_t>
5052 nsHtml5TreeBuilder::getTemplateModeStack()
5054 return templateModeStack;
5057 int32_t
5058 nsHtml5TreeBuilder::getMode()
5060 return mode;
5063 int32_t
5064 nsHtml5TreeBuilder::getOriginalMode()
5066 return originalMode;
5069 bool
5070 nsHtml5TreeBuilder::isFramesetOk()
5072 return framesetOk;
5075 bool
5076 nsHtml5TreeBuilder::isNeedToDropLF()
5078 return needToDropLF;
5081 bool
5082 nsHtml5TreeBuilder::isQuirks()
5084 return quirks;
5087 int32_t
5088 nsHtml5TreeBuilder::getListOfActiveFormattingElementsLength()
5090 return listPtr + 1;
5093 int32_t
5094 nsHtml5TreeBuilder::getStackLength()
5096 return currentPtr + 1;
5099 int32_t
5100 nsHtml5TreeBuilder::getTemplateModeStackLength()
5102 return templateModePtr + 1;
5105 void
5106 nsHtml5TreeBuilder::initializeStatics()
5110 void
5111 nsHtml5TreeBuilder::releaseStatics()
5115 #include "nsHtml5TreeBuilderCppSupplement.h"