in parser/html/nsHtml5TreeBuilder.cpp [675:2057]
void nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName,
nsHtml5HtmlAttributes* attributes,
bool selfClosing) {
flushCharacters();
int32_t eltPos;
needToDropLF = false;
starttagloop:
for (;;) {
int32_t group = elementName->getGroup();
nsAtom* name = elementName->getName();
if (isInForeign()) {
nsHtml5StackNode* currentNode = stack[currentPtr];
int32_t currNs = currentNode->ns;
if (!(currentNode->isHtmlIntegrationPoint() ||
(currNs == kNameSpaceID_MathML &&
((currentNode->getGroup() == MI_MO_MN_MS_MTEXT &&
group != MGLYPH_OR_MALIGNMARK) ||
(currentNode->getGroup() == ANNOTATION_XML && group == SVG))))) {
switch (group) {
case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
case BODY:
case BR:
case RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR:
case DD_OR_DT:
case UL_OR_OL_OR_DL:
case EMBED:
case IMG:
case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
case HEAD:
case HR:
case LI:
case META:
case NOBR:
case P:
case PRE_OR_LISTING:
case TABLE:
case FONT: {
if (!(group == FONT &&
!(attributes->contains(nsHtml5AttributeName::ATTR_COLOR) ||
attributes->contains(nsHtml5AttributeName::ATTR_FACE) ||
attributes->contains(nsHtml5AttributeName::ATTR_SIZE)))) {
errHtmlStartTagInForeignContext(name);
if (!fragment) {
while (!isSpecialParentInForeign(stack[currentPtr])) {
popForeign(-1, -1);
}
NS_HTML5_CONTINUE(starttagloop);
}
}
[[fallthrough]];
}
default: {
if (kNameSpaceID_SVG == currNs) {
attributes->adjustForSvg();
if (selfClosing) {
appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
selfClosing = false;
} else {
appendToCurrentNodeAndPushElementMayFosterSVG(elementName,
attributes);
}
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
} else {
attributes->adjustForMath();
if (selfClosing) {
appendVoidElementToCurrentMayFosterMathML(elementName,
attributes);
selfClosing = false;
} else {
appendToCurrentNodeAndPushElementMayFosterMathML(elementName,
attributes);
}
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
}
}
}
}
switch (mode) {
case IN_TEMPLATE: {
switch (group) {
case COL: {
popTemplateMode();
pushTemplateMode(IN_COLUMN_GROUP);
mode = IN_COLUMN_GROUP;
continue;
}
case CAPTION:
case COLGROUP:
case TBODY_OR_THEAD_OR_TFOOT: {
popTemplateMode();
pushTemplateMode(IN_TABLE);
mode = IN_TABLE;
continue;
}
case TR: {
popTemplateMode();
pushTemplateMode(IN_TABLE_BODY);
mode = IN_TABLE_BODY;
continue;
}
case TD_OR_TH: {
popTemplateMode();
pushTemplateMode(IN_ROW);
mode = IN_ROW;
continue;
}
case META: {
checkMetaCharset(attributes);
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case TITLE: {
startTagTitleInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case BASE:
case LINK_OR_BASEFONT_OR_BGSOUND: {
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case SCRIPT: {
startTagScriptInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NOFRAMES:
case STYLE: {
startTagGenericRawText(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case TEMPLATE: {
startTagTemplateInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
popTemplateMode();
pushTemplateMode(IN_BODY);
mode = IN_BODY;
continue;
}
}
}
case IN_ROW: {
switch (group) {
case TD_OR_TH: {
clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TR));
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = IN_CELL;
insertMarker();
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case CAPTION:
case COL:
case COLGROUP:
case TBODY_OR_THEAD_OR_TFOOT:
case TR: {
eltPos = findLastOrRoot(nsHtml5TreeBuilder::TR);
if (!eltPos) {
MOZ_ASSERT(fragment || isTemplateContents());
errNoTableRowToClose();
NS_HTML5_BREAK(starttagloop);
}
clearStackBackTo(eltPos);
pop();
mode = IN_TABLE_BODY;
continue;
}
default:; // fall through
}
[[fallthrough]];
}
case IN_TABLE_BODY: {
switch (group) {
case TR: {
clearStackBackTo(
findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = IN_ROW;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case TD_OR_TH: {
errStartTagInTableBody(name);
clearStackBackTo(
findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
appendToCurrentNodeAndPushElement(
nsHtml5ElementName::ELT_TR,
nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
mode = IN_ROW;
continue;
}
case CAPTION:
case COL:
case COLGROUP:
case TBODY_OR_THEAD_OR_TFOOT: {
eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
if (!eltPos || stack[eltPos]->getGroup() == TEMPLATE) {
MOZ_ASSERT(fragment || isTemplateContents());
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
} else {
clearStackBackTo(eltPos);
pop();
mode = IN_TABLE;
continue;
}
}
default:; // fall through
}
[[fallthrough]];
}
case IN_TABLE: {
for (;;) {
switch (group) {
case CAPTION: {
clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
insertMarker();
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = IN_CAPTION;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case COLGROUP: {
clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = IN_COLUMN_GROUP;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case COL: {
clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
appendToCurrentNodeAndPushElement(
nsHtml5ElementName::ELT_COLGROUP,
nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
mode = IN_COLUMN_GROUP;
NS_HTML5_CONTINUE(starttagloop);
}
case TBODY_OR_THEAD_OR_TFOOT: {
clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = IN_TABLE_BODY;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case TR:
case TD_OR_TH: {
clearStackBackTo(findLastOrRoot(nsHtml5TreeBuilder::TABLE));
appendToCurrentNodeAndPushElement(
nsHtml5ElementName::ELT_TBODY,
nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
mode = IN_TABLE_BODY;
NS_HTML5_CONTINUE(starttagloop);
}
case TEMPLATE: {
NS_HTML5_BREAK(intableloop);
}
case TABLE: {
errTableSeenWhileTableOpen();
eltPos = findLastInTableScope(name);
if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment || isTemplateContents());
NS_HTML5_BREAK(starttagloop);
}
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsGkAtoms::table)) {
errNoCheckUnclosedElementsOnStack();
}
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
NS_HTML5_CONTINUE(starttagloop);
}
case SCRIPT: {
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = TEXT;
tokenizer->setStateAndEndTagExpectation(
nsHtml5Tokenizer::SCRIPT_DATA, elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case STYLE: {
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = TEXT;
tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case INPUT: {
errStartTagInTable(name);
if (!nsHtml5Portability::
lowerCaseLiteralEqualsIgnoreAsciiCaseString(
"hidden", attributes->getValue(
nsHtml5AttributeName::ATTR_TYPE))) {
NS_HTML5_BREAK(intableloop);
}
appendVoidInputToCurrent(attributes, formPointer);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case FORM: {
if (!!formPointer || isTemplateContents()) {
errFormWhenFormOpen();
NS_HTML5_BREAK(starttagloop);
} else {
errStartTagInTable(name);
appendVoidFormToCurrent(attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
}
default: {
errStartTagInTable(name);
NS_HTML5_BREAK(intableloop);
}
}
}
intableloop_end:;
[[fallthrough]];
}
case IN_CAPTION: {
switch (group) {
case CAPTION:
case COL:
case COLGROUP:
case TBODY_OR_THEAD_OR_TFOOT:
case TR:
case TD_OR_TH: {
eltPos = findLastInTableScope(nsGkAtoms::caption);
if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment || isTemplateContents());
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
errNoCheckUnclosedElementsOnStack();
}
while (currentPtr >= eltPos) {
pop();
}
clearTheListOfActiveFormattingElementsUpToTheLastMarker();
mode = IN_TABLE;
continue;
}
default:; // fall through
}
[[fallthrough]];
}
case IN_CELL: {
switch (group) {
case CAPTION:
case COL:
case COLGROUP:
case TBODY_OR_THEAD_OR_TFOOT:
case TR:
case TD_OR_TH: {
eltPos = findLastInTableScopeTdTh();
if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
errNoCellToClose();
NS_HTML5_BREAK(starttagloop);
} else {
closeTheCell(eltPos);
continue;
}
}
default:; // fall through
}
[[fallthrough]];
}
case FRAMESET_OK: {
switch (group) {
case FRAMESET: {
if (mode == FRAMESET_OK) {
if (!currentPtr || stack[1]->getGroup() != BODY) {
MOZ_ASSERT(fragment || isTemplateContents());
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
} else {
errFramesetStart();
detachFromParent(stack[1]->node);
while (currentPtr > 0) {
pop();
}
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = IN_FRAMESET;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
} else {
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
}
case PRE_OR_LISTING:
case LI:
case DD_OR_DT:
case BUTTON:
case MARQUEE_OR_APPLET:
case OBJECT:
case TABLE:
case AREA_OR_WBR:
case KEYGEN:
case BR:
case EMBED:
case IMG:
case INPUT:
case HR:
case TEXTAREA:
case XMP:
case IFRAME:
case SELECT: {
if (mode == FRAMESET_OK &&
!(group == INPUT &&
nsHtml5Portability::
lowerCaseLiteralEqualsIgnoreAsciiCaseString(
"hidden", attributes->getValue(
nsHtml5AttributeName::ATTR_TYPE)))) {
framesetOk = false;
mode = IN_BODY;
}
[[fallthrough]];
}
default:; // fall through
}
[[fallthrough]];
}
case IN_BODY: {
for (;;) {
switch (group) {
case HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case BASE:
case LINK_OR_BASEFONT_OR_BGSOUND:
case META:
case STYLE:
case SCRIPT:
case TITLE:
case TEMPLATE: {
NS_HTML5_BREAK(inbodyloop);
}
case BODY: {
if (!currentPtr || stack[1]->getGroup() != BODY ||
isTemplateContents()) {
MOZ_ASSERT(fragment || isTemplateContents());
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
errFooSeenWhenFooOpen(name);
framesetOk = false;
if (mode == FRAMESET_OK) {
mode = IN_BODY;
}
if (addAttributesToBody(attributes)) {
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case P:
case DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
case UL_OR_OL_OR_DL:
case ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIALOG_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SEARCH_OR_SECTION_OR_SUMMARY: {
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: {
implicitlyCloseP();
if (stack[currentPtr]->getGroup() ==
H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
errHeadingWhenHeadingOpen();
pop();
}
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case FIELDSET: {
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(
elementName, attributes, formPointer);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case PRE_OR_LISTING: {
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
needToDropLF = true;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case FORM: {
if (!!formPointer && !isTemplateContents()) {
errFormWhenFormOpen();
NS_HTML5_BREAK(starttagloop);
} else {
implicitlyCloseP();
appendToCurrentNodeAndPushFormElementMayFoster(attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
}
case LI:
case DD_OR_DT: {
eltPos = currentPtr;
for (;;) {
nsHtml5StackNode* node = stack[eltPos];
if (node->getGroup() == group) {
generateImpliedEndTagsExceptFor(node->name);
if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
errUnclosedElementsImplied(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
break;
} else if (!eltPos || (node->isSpecial() &&
(node->ns != kNameSpaceID_XHTML ||
(node->name != nsGkAtoms::p &&
node->name != nsGkAtoms::address &&
node->name != nsGkAtoms::div)))) {
break;
}
eltPos--;
}
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case PLAINTEXT: {
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
tokenizer->setStateAndEndTagExpectation(
nsHtml5Tokenizer::PLAINTEXT, elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case A: {
int32_t activeAPos =
findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(
nsGkAtoms::a);
if (activeAPos != -1) {
errFooSeenWhenFooOpen(name);
nsHtml5StackNode* activeA =
listOfActiveFormattingElements[activeAPos];
activeA->retain();
adoptionAgencyEndTag(nsGkAtoms::a);
removeFromStack(activeA);
activeAPos = findInListOfActiveFormattingElements(activeA);
if (activeAPos != -1) {
removeFromListOfActiveFormattingElements(activeAPos);
}
activeA->release(this);
}
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
case FONT: {
reconstructTheActiveFormattingElements();
maybeForgetEarlierDuplicateFormattingElement(
elementName->getName(), attributes);
appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NOBR: {
reconstructTheActiveFormattingElements();
if (nsHtml5TreeBuilder::NOT_FOUND_ON_STACK !=
findLastInScope(nsGkAtoms::nobr)) {
errFooSeenWhenFooOpen(name);
adoptionAgencyEndTag(nsGkAtoms::nobr);
reconstructTheActiveFormattingElements();
}
appendToCurrentNodeAndPushFormattingElementMayFoster(elementName,
attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case BUTTON: {
eltPos = findLastInScope(name);
if (eltPos != nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
errFooSeenWhenFooOpen(name);
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
errUnclosedElementsImplied(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
NS_HTML5_CONTINUE(starttagloop);
} else {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(
elementName, attributes, formPointer);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
}
case OBJECT: {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(
elementName, attributes, formPointer);
insertMarker();
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case MARQUEE_OR_APPLET: {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
insertMarker();
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case TABLE: {
if (!quirks) {
implicitlyCloseP();
}
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
mode = IN_TABLE;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case BR:
case EMBED:
case AREA_OR_WBR:
case KEYGEN: {
reconstructTheActiveFormattingElements();
[[fallthrough]];
}
case PARAM_OR_SOURCE_OR_TRACK: {
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case HR: {
implicitlyCloseP();
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case IMAGE: {
errImage();
elementName = nsHtml5ElementName::ELT_IMG;
NS_HTML5_CONTINUE(starttagloop);
}
case IMG:
case INPUT: {
reconstructTheActiveFormattingElements();
appendVoidElementToCurrentMayFoster(elementName, attributes,
formPointer);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case TEXTAREA: {
appendToCurrentNodeAndPushElementMayFoster(
elementName, attributes, formPointer);
tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
elementName);
originalMode = mode;
mode = TEXT;
needToDropLF = true;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case XMP: {
implicitlyCloseP();
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
originalMode = mode;
mode = TEXT;
tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NOSCRIPT: {
if (!scriptingEnabled) {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
[[fallthrough]];
}
case NOFRAMES:
case IFRAME:
case NOEMBED: {
startTagGenericRawText(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case SELECT: {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(
elementName, attributes, formPointer);
switch (mode) {
case IN_TABLE:
case IN_CAPTION:
case IN_COLUMN_GROUP:
case IN_TABLE_BODY:
case IN_ROW:
case IN_CELL: {
mode = IN_SELECT_IN_TABLE;
break;
}
default: {
mode = IN_SELECT;
break;
}
}
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case OPTGROUP:
case OPTION: {
if (isCurrent(nsGkAtoms::option)) {
pop();
}
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case RB_OR_RTC: {
eltPos = findLastInScope(nsGkAtoms::ruby);
if (eltPos != NOT_FOUND_ON_STACK) {
generateImpliedEndTags();
}
if (eltPos != currentPtr) {
if (eltPos == NOT_FOUND_ON_STACK) {
errStartTagSeenWithoutRuby(name);
} else {
errUnclosedChildrenInRuby();
}
}
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case RT_OR_RP: {
eltPos = findLastInScope(nsGkAtoms::ruby);
if (eltPos != NOT_FOUND_ON_STACK) {
generateImpliedEndTagsExceptFor(nsGkAtoms::rtc);
}
if (eltPos != currentPtr) {
if (!isCurrent(nsGkAtoms::rtc)) {
if (eltPos == NOT_FOUND_ON_STACK) {
errStartTagSeenWithoutRuby(name);
} else {
errUnclosedChildrenInRuby();
}
}
}
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case MATH: {
reconstructTheActiveFormattingElements();
attributes->adjustForMath();
if (selfClosing) {
appendVoidElementToCurrentMayFosterMathML(elementName,
attributes);
selfClosing = false;
} else {
appendToCurrentNodeAndPushElementMayFosterMathML(elementName,
attributes);
}
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case SVG: {
reconstructTheActiveFormattingElements();
attributes->adjustForSvg();
if (selfClosing) {
appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
selfClosing = false;
} else {
appendToCurrentNodeAndPushElementMayFosterSVG(elementName,
attributes);
}
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case CAPTION:
case COL:
case COLGROUP:
case TBODY_OR_THEAD_OR_TFOOT:
case TR:
case TD_OR_TH:
case FRAME:
case FRAMESET:
case HEAD: {
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
case OUTPUT: {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(
elementName, attributes, formPointer);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
}
}
inbodyloop_end:;
[[fallthrough]];
}
case IN_HEAD: {
for (;;) {
switch (group) {
case HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case BASE:
case LINK_OR_BASEFONT_OR_BGSOUND: {
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case META: {
NS_HTML5_BREAK(inheadloop);
}
case TITLE: {
startTagTitleInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NOSCRIPT: {
if (scriptingEnabled) {
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = TEXT;
tokenizer->setStateAndEndTagExpectation(
nsHtml5Tokenizer::RAWTEXT, elementName);
} else {
appendToCurrentNodeAndPushElementMayFoster(elementName,
attributes);
mode = IN_HEAD_NOSCRIPT;
}
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case SCRIPT: {
startTagScriptInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case STYLE:
case NOFRAMES: {
startTagGenericRawText(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case HEAD: {
errFooSeenWhenFooOpen(name);
NS_HTML5_BREAK(starttagloop);
}
case TEMPLATE: {
startTagTemplateInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
pop();
mode = AFTER_HEAD;
NS_HTML5_CONTINUE(starttagloop);
}
}
}
inheadloop_end:;
[[fallthrough]];
}
case IN_HEAD_NOSCRIPT: {
switch (group) {
case HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case LINK_OR_BASEFONT_OR_BGSOUND: {
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case META: {
checkMetaCharset(attributes);
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case STYLE:
case NOFRAMES: {
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = TEXT;
tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case HEAD: {
errFooSeenWhenFooOpen(name);
NS_HTML5_BREAK(starttagloop);
}
case NOSCRIPT: {
errFooSeenWhenFooOpen(name);
NS_HTML5_BREAK(starttagloop);
}
default: {
errBadStartTagInNoscriptInHead(name);
pop();
mode = IN_HEAD;
continue;
}
}
}
case IN_COLUMN_GROUP: {
switch (group) {
case HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case COL: {
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case TEMPLATE: {
startTagTemplateInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
if (!currentPtr || stack[currentPtr]->getGroup() == TEMPLATE) {
MOZ_ASSERT(fragment || isTemplateContents());
errGarbageInColgroup();
NS_HTML5_BREAK(starttagloop);
}
pop();
mode = IN_TABLE;
continue;
}
}
}
case IN_SELECT_IN_TABLE: {
switch (group) {
case CAPTION:
case TBODY_OR_THEAD_OR_TFOOT:
case TR:
case TD_OR_TH:
case TABLE: {
errStartTagWithSelectOpen(name);
eltPos = findLastInTableScope(nsGkAtoms::select);
if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment);
NS_HTML5_BREAK(starttagloop);
}
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
continue;
}
default:; // fall through
}
[[fallthrough]];
}
case IN_SELECT: {
switch (group) {
case HTML: {
errStrayStartTag(name);
if (!fragment) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case OPTION: {
if (isCurrent(nsGkAtoms::option)) {
pop();
}
appendToCurrentNodeAndPushElement(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case OPTGROUP: {
if (isCurrent(nsGkAtoms::option)) {
pop();
}
if (isCurrent(nsGkAtoms::optgroup)) {
pop();
}
appendToCurrentNodeAndPushElement(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case SELECT: {
errStartSelectWhereEndSelectExpected();
eltPos = findLastInTableScope(name);
if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment);
errNoSelectInTableScope();
NS_HTML5_BREAK(starttagloop);
} else {
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
NS_HTML5_BREAK(starttagloop);
}
}
case INPUT:
case TEXTAREA: {
errStartTagWithSelectOpen(name);
eltPos = findLastInTableScope(nsGkAtoms::select);
if (eltPos == nsHtml5TreeBuilder::NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment);
NS_HTML5_BREAK(starttagloop);
}
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
continue;
}
case SCRIPT: {
startTagScriptInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case TEMPLATE: {
startTagTemplateInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case HR: {
if (isCurrent(nsGkAtoms::option)) {
pop();
}
if (isCurrent(nsGkAtoms::optgroup)) {
pop();
}
appendVoidElementToCurrent(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
}
}
case AFTER_BODY: {
switch (group) {
case HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
default: {
errStrayStartTag(name);
mode = framesetOk ? FRAMESET_OK : IN_BODY;
continue;
}
}
}
case IN_FRAMESET: {
switch (group) {
case FRAMESET: {
appendToCurrentNodeAndPushElement(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case FRAME: {
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default:; // fall through
}
[[fallthrough]];
}
case AFTER_FRAMESET: {
switch (group) {
case HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case NOFRAMES: {
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = TEXT;
tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
}
}
case INITIAL: {
errStartTagWithoutDoctype();
documentModeInternal(QUIRKS_MODE, nullptr, nullptr);
mode = BEFORE_HTML;
continue;
}
case BEFORE_HTML: {
switch (group) {
case HTML: {
if (attributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
appendHtmlElementToDocumentAndPush();
} else {
appendHtmlElementToDocumentAndPush(attributes);
}
mode = BEFORE_HEAD;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
appendHtmlElementToDocumentAndPush();
mode = BEFORE_HEAD;
continue;
}
}
}
case BEFORE_HEAD: {
switch (group) {
case HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case HEAD: {
appendToCurrentNodeAndPushHeadElement(attributes);
mode = IN_HEAD;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
appendToCurrentNodeAndPushHeadElement(
nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
mode = IN_HEAD;
continue;
}
}
}
case AFTER_HEAD: {
switch (group) {
case HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case BODY: {
if (!attributes->getLength()) {
appendToCurrentNodeAndPushBodyElement();
} else {
appendToCurrentNodeAndPushBodyElement(attributes);
}
framesetOk = false;
mode = IN_BODY;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case FRAMESET: {
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = IN_FRAMESET;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case TEMPLATE: {
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
nsHtml5StackNode* headOnStack = stack[currentPtr];
startTagTemplateInHead(elementName, attributes);
removeFromStack(headOnStack);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case BASE:
case LINK_OR_BASEFONT_OR_BGSOUND: {
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
pop();
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case META: {
errFooBetweenHeadAndBody(name);
checkMetaCharset(attributes);
pushHeadPointerOntoStack();
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
pop();
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case SCRIPT: {
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = TEXT;
tokenizer->setStateAndEndTagExpectation(
nsHtml5Tokenizer::SCRIPT_DATA, elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case STYLE:
case NOFRAMES: {
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = TEXT;
tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RAWTEXT,
elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case TITLE: {
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = TEXT;
tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::RCDATA,
elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case HEAD: {
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
default: {
appendToCurrentNodeAndPushBodyElement();
mode = FRAMESET_OK;
continue;
}
}
}
case AFTER_AFTER_BODY: {
switch (group) {
case HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
default: {
errStrayStartTag(name);
mode = framesetOk ? FRAMESET_OK : IN_BODY;
continue;
}
}
}
case AFTER_AFTER_FRAMESET: {
switch (group) {
case HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case NOFRAMES: {
startTagGenericRawText(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
}
}
case TEXT: {
MOZ_ASSERT(false);
NS_HTML5_BREAK(starttagloop);
}
}
}
starttagloop_end:;
if (selfClosing) {
errSelfClosing();
}
if (!mBuilder && attributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
delete attributes;
}
}