in parser/html/javasrc/TreeBuilder.java [1477:2934]
public final void startTag(ElementName elementName,
HtmlAttributes attributes, boolean selfClosing) throws SAXException {
flushCharacters();
// [NOCPP[
boolean wasSelfClosing = selfClosing;
boolean voidElement = false;
if (errorHandler != null) {
// ID uniqueness
@IdType String id = attributes.getId();
if (id != null && !isTemplateContents()) {
LocatorImpl oldLoc = idLocations.get(id);
if (oldLoc != null) {
err("Duplicate ID \u201C" + id + "\u201D.");
errorHandler.warning(new SAXParseException(
"The first occurrence of ID \u201C" + id
+ "\u201D was here.", oldLoc));
} else {
idLocations.put(id, new LocatorImpl(tokenizer));
}
}
}
// ]NOCPP]
int eltPos;
needToDropLF = false;
starttagloop: for (;;) {
int group = elementName.getGroup();
@Local String name = elementName.getName();
if (isInForeign()) {
StackNode<T> currentNode = stack[currentPtr];
@NsUri String currNs = currentNode.ns;
if (!(currentNode.isHtmlIntegrationPoint() || (currNs == "http://www.w3.org/1998/Math/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:
// re-check FONT to deal with the special case
if (!(group == FONT && !(attributes.contains(AttributeName.COLOR)
|| attributes.contains(AttributeName.FACE) || attributes.contains(AttributeName.SIZE)))) {
errHtmlStartTagInForeignContext(name);
if (!fragment) {
while (!isSpecialParentInForeign(stack[currentPtr])) {
popForeign(-1, -1);
}
continue starttagloop;
} // else fall thru
}
// CPPONLY: MOZ_FALLTHROUGH;
default:
if ("http://www.w3.org/2000/svg" == currNs) {
attributes.adjustForSvg();
if (selfClosing) {
appendVoidElementToCurrentMayFosterSVG(
elementName, attributes);
selfClosing = false;
} else {
appendToCurrentNodeAndPushElementMayFosterSVG(
elementName, attributes);
}
attributes = null; // CPP
break starttagloop;
} else {
attributes.adjustForMath();
if (selfClosing) {
appendVoidElementToCurrentMayFosterMathML(
elementName, attributes);
selfClosing = false;
} else {
appendToCurrentNodeAndPushElementMayFosterMathML(
elementName, attributes);
}
attributes = null; // CPP
break starttagloop;
}
} // switch
} // foreignObject / annotation-xml
}
switch (mode) {
case IN_TEMPLATE:
switch (group) {
case COL:
popTemplateMode();
pushTemplateMode(IN_COLUMN_GROUP);
mode = IN_COLUMN_GROUP;
// Reprocess token.
continue;
case CAPTION:
case COLGROUP:
case TBODY_OR_THEAD_OR_TFOOT:
popTemplateMode();
pushTemplateMode(IN_TABLE);
mode = IN_TABLE;
// Reprocess token.
continue;
case TR:
popTemplateMode();
pushTemplateMode(IN_TABLE_BODY);
mode = IN_TABLE_BODY;
// Reprocess token.
continue;
case TD_OR_TH:
popTemplateMode();
pushTemplateMode(IN_ROW);
mode = IN_ROW;
// Reprocess token.
continue;
case META:
checkMetaCharset(attributes);
appendVoidElementToCurrentMayFoster(
elementName,
attributes);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
attributes = null; // CPP
break starttagloop;
case TITLE:
startTagTitleInHead(elementName, attributes);
attributes = null; // CPP
break starttagloop;
case BASE:
case LINK_OR_BASEFONT_OR_BGSOUND:
appendVoidElementToCurrentMayFoster(
elementName,
attributes);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
attributes = null; // CPP
break starttagloop;
case SCRIPT:
startTagScriptInHead(elementName, attributes);
attributes = null; // CPP
break starttagloop;
case NOFRAMES:
case STYLE:
startTagGenericRawText(elementName, attributes);
attributes = null; // CPP
break starttagloop;
case TEMPLATE:
startTagTemplateInHead(elementName, attributes);
attributes = null; // CPP
break starttagloop;
default:
popTemplateMode();
pushTemplateMode(IN_BODY);
mode = IN_BODY;
// Reprocess token.
continue;
}
case IN_ROW:
switch (group) {
case TD_OR_TH:
clearStackBackTo(findLastOrRoot(TreeBuilder.TR));
appendToCurrentNodeAndPushElement(
elementName,
attributes);
mode = IN_CELL;
insertMarker();
attributes = null; // CPP
break starttagloop;
case CAPTION:
case COL:
case COLGROUP:
case TBODY_OR_THEAD_OR_TFOOT:
case TR:
eltPos = findLastOrRoot(TreeBuilder.TR);
if (eltPos == 0) {
assert fragment || isTemplateContents();
errNoTableRowToClose();
break starttagloop;
}
clearStackBackTo(eltPos);
pop();
mode = IN_TABLE_BODY;
continue;
default:
// fall through to IN_TABLE
}
// CPPONLY: MOZ_FALLTHROUGH;
case IN_TABLE_BODY:
switch (group) {
case TR:
clearStackBackTo(findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
appendToCurrentNodeAndPushElement(
elementName,
attributes);
mode = IN_ROW;
attributes = null; // CPP
break starttagloop;
case TD_OR_TH:
errStartTagInTableBody(name);
clearStackBackTo(findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
appendToCurrentNodeAndPushElement(
ElementName.TR,
HtmlAttributes.EMPTY_ATTRIBUTES);
mode = IN_ROW;
continue;
case CAPTION:
case COL:
case COLGROUP:
case TBODY_OR_THEAD_OR_TFOOT:
eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
if (eltPos == 0 || stack[eltPos].getGroup() == TEMPLATE) {
assert fragment || isTemplateContents();
errStrayStartTag(name);
break starttagloop;
} else {
clearStackBackTo(eltPos);
pop();
mode = IN_TABLE;
continue;
}
default:
// fall through to IN_TABLE
}
// CPPONLY: MOZ_FALLTHROUGH;
case IN_TABLE:
intableloop: for (;;) {
switch (group) {
case CAPTION:
clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
insertMarker();
appendToCurrentNodeAndPushElement(
elementName,
attributes);
mode = IN_CAPTION;
attributes = null; // CPP
break starttagloop;
case COLGROUP:
clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
appendToCurrentNodeAndPushElement(
elementName,
attributes);
mode = IN_COLUMN_GROUP;
attributes = null; // CPP
break starttagloop;
case COL:
clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
appendToCurrentNodeAndPushElement(
ElementName.COLGROUP,
HtmlAttributes.EMPTY_ATTRIBUTES);
mode = IN_COLUMN_GROUP;
continue starttagloop;
case TBODY_OR_THEAD_OR_TFOOT:
clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
appendToCurrentNodeAndPushElement(
elementName,
attributes);
mode = IN_TABLE_BODY;
attributes = null; // CPP
break starttagloop;
case TR:
case TD_OR_TH:
clearStackBackTo(findLastOrRoot(TreeBuilder.TABLE));
appendToCurrentNodeAndPushElement(
ElementName.TBODY,
HtmlAttributes.EMPTY_ATTRIBUTES);
mode = IN_TABLE_BODY;
continue starttagloop;
case TEMPLATE:
// fall through to IN_HEAD
break intableloop;
case TABLE:
errTableSeenWhileTableOpen();
eltPos = findLastInTableScope(name);
if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
assert fragment || isTemplateContents();
break starttagloop;
}
generateImpliedEndTags();
if (errorHandler != null && !isCurrent("table")) {
errNoCheckUnclosedElementsOnStack();
}
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
continue starttagloop;
case SCRIPT:
// XXX need to manage much more stuff
// here if
// supporting
// document.write()
appendToCurrentNodeAndPushElement(
elementName,
attributes);
originalMode = mode;
mode = TEXT;
tokenizer.setStateAndEndTagExpectation(
Tokenizer.SCRIPT_DATA, elementName);
attributes = null; // CPP
break starttagloop;
case STYLE:
appendToCurrentNodeAndPushElement(
elementName,
attributes);
originalMode = mode;
mode = TEXT;
tokenizer.setStateAndEndTagExpectation(
Tokenizer.RAWTEXT, elementName);
attributes = null; // CPP
break starttagloop;
case INPUT:
errStartTagInTable(name);
if (!Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
"hidden",
attributes.getValue(AttributeName.TYPE))) {
break intableloop;
}
appendVoidInputToCurrent(
attributes,
formPointer);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
attributes = null; // CPP
break starttagloop;
case FORM:
if (formPointer != null || isTemplateContents()) {
errFormWhenFormOpen();
break starttagloop;
} else {
errStartTagInTable(name);
appendVoidFormToCurrent(attributes);
attributes = null; // CPP
break starttagloop;
}
default:
errStartTagInTable(name);
// fall through to IN_BODY
break intableloop;
}
}
// CPPONLY: MOZ_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("caption");
if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
assert fragment || isTemplateContents();
errStrayStartTag(name);
break starttagloop;
}
generateImpliedEndTags();
if (errorHandler != null && currentPtr != eltPos) {
errNoCheckUnclosedElementsOnStack();
}
while (currentPtr >= eltPos) {
pop();
}
clearTheListOfActiveFormattingElementsUpToTheLastMarker();
mode = IN_TABLE;
continue;
default:
// fall through to IN_BODY
}
// CPPONLY: MOZ_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 == TreeBuilder.NOT_FOUND_ON_STACK) {
errNoCellToClose();
break starttagloop;
} else {
closeTheCell(eltPos);
continue;
}
default:
// fall through to IN_BODY
}
// CPPONLY: MOZ_FALLTHROUGH;
case FRAMESET_OK:
switch (group) {
case FRAMESET:
if (mode == FRAMESET_OK) {
if (currentPtr == 0 || stack[1].getGroup() != BODY) {
assert fragment || isTemplateContents();
errStrayStartTag(name);
break starttagloop;
} else {
errFramesetStart();
detachFromParent(stack[1].node);
while (currentPtr > 0) {
pop();
}
appendToCurrentNodeAndPushElement(
elementName,
attributes);
mode = IN_FRAMESET;
attributes = null; // CPP
break starttagloop;
}
} else {
errStrayStartTag(name);
break starttagloop;
}
// NOT falling through!
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 && Portability.lowerCaseLiteralEqualsIgnoreAsciiCaseString(
"hidden",
attributes.getValue(AttributeName.TYPE)))) {
framesetOk = false;
mode = IN_BODY;
}
// CPPONLY: MOZ_FALLTHROUGH;
default:
// fall through to IN_BODY
}
// CPPONLY: MOZ_FALLTHROUGH;
case IN_BODY:
inbodyloop: for (;;) {
switch (group) {
case HTML:
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = null; // CPP
}
break starttagloop;
case BASE:
case LINK_OR_BASEFONT_OR_BGSOUND:
case META:
case STYLE:
case SCRIPT:
case TITLE:
case TEMPLATE:
// Fall through to IN_HEAD
break inbodyloop;
case BODY:
if (currentPtr == 0 || stack[1].getGroup() != BODY || isTemplateContents()) {
assert fragment || isTemplateContents();
errStrayStartTag(name);
break starttagloop;
}
errFooSeenWhenFooOpen(name);
framesetOk = false;
if (mode == FRAMESET_OK) {
mode = IN_BODY;
}
if (addAttributesToBody(attributes)) {
attributes = null; // CPP
}
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 = null; // CPP
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 = null; // CPP
break starttagloop;
case FIELDSET:
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes, formPointer);
attributes = null; // CPP
break starttagloop;
case PRE_OR_LISTING:
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes);
needToDropLF = true;
attributes = null; // CPP
break starttagloop;
case FORM:
if (formPointer != null && !isTemplateContents()) {
errFormWhenFormOpen();
break starttagloop;
} else {
implicitlyCloseP();
appendToCurrentNodeAndPushFormElementMayFoster(attributes);
attributes = null; // CPP
break starttagloop;
}
case LI:
case DD_OR_DT:
eltPos = currentPtr;
for (;;) {
StackNode<T> node = stack[eltPos]; // weak
// ref
if (node.getGroup() == group) { // LI or
// DD_OR_DT
generateImpliedEndTagsExceptFor(node.name);
if (errorHandler != null
&& eltPos != currentPtr) {
errUnclosedElementsImplied(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
break;
} else if (eltPos == 0 || (node.isSpecial()
&& (node.ns != "http://www.w3.org/1999/xhtml"
|| (node.name != "p"
&& node.name != "address"
&& node.name != "div")))) {
break;
}
eltPos--;
}
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes);
attributes = null; // CPP
break starttagloop;
case PLAINTEXT:
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes);
tokenizer.setStateAndEndTagExpectation(
Tokenizer.PLAINTEXT, elementName);
attributes = null; // CPP
break starttagloop;
case A:
int activeAPos = findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker("a");
if (activeAPos != -1) {
errFooSeenWhenFooOpen(name);
StackNode<T> activeA = listOfActiveFormattingElements[activeAPos];
activeA.retain();
adoptionAgencyEndTag("a");
removeFromStack(activeA);
activeAPos = findInListOfActiveFormattingElements(activeA);
if (activeAPos != -1) {
removeFromListOfActiveFormattingElements(activeAPos);
}
activeA.release(this);
}
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushFormattingElementMayFoster(
elementName,
attributes);
attributes = null; // CPP
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 = null; // CPP
break starttagloop;
case NOBR:
reconstructTheActiveFormattingElements();
if (TreeBuilder.NOT_FOUND_ON_STACK != findLastInScope("nobr")) {
errFooSeenWhenFooOpen(name);
adoptionAgencyEndTag("nobr");
reconstructTheActiveFormattingElements();
}
appendToCurrentNodeAndPushFormattingElementMayFoster(
elementName,
attributes);
attributes = null; // CPP
break starttagloop;
case BUTTON:
eltPos = findLastInScope(name);
if (eltPos != TreeBuilder.NOT_FOUND_ON_STACK) {
errFooSeenWhenFooOpen(name);
generateImpliedEndTags();
if (errorHandler != null
&& !isCurrent(name)) {
errUnclosedElementsImplied(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
continue starttagloop;
} else {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes, formPointer);
attributes = null; // CPP
break starttagloop;
}
case OBJECT:
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes, formPointer);
insertMarker();
attributes = null; // CPP
break starttagloop;
case MARQUEE_OR_APPLET:
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes);
insertMarker();
attributes = null; // CPP
break starttagloop;
case TABLE:
// The only quirk. Blame Hixie and
// Acid2.
if (!quirks) {
implicitlyCloseP();
}
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes);
mode = IN_TABLE;
attributes = null; // CPP
break starttagloop;
case BR:
case EMBED:
case AREA_OR_WBR:
case KEYGEN:
reconstructTheActiveFormattingElements();
// FALL THROUGH to PARAM_OR_SOURCE_OR_TRACK
// CPPONLY: MOZ_FALLTHROUGH;
case PARAM_OR_SOURCE_OR_TRACK:
appendVoidElementToCurrentMayFoster(
elementName,
attributes);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
attributes = null; // CPP
break starttagloop;
case HR:
implicitlyCloseP();
appendVoidElementToCurrentMayFoster(
elementName,
attributes);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
attributes = null; // CPP
break starttagloop;
case IMAGE:
errImage();
elementName = ElementName.IMG;
continue starttagloop;
case IMG:
case INPUT:
reconstructTheActiveFormattingElements();
appendVoidElementToCurrentMayFoster(
elementName, attributes,
formPointer);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
attributes = null; // CPP
break starttagloop;
case TEXTAREA:
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes, formPointer);
tokenizer.setStateAndEndTagExpectation(
Tokenizer.RCDATA, elementName);
originalMode = mode;
mode = TEXT;
needToDropLF = true;
attributes = null; // CPP
break starttagloop;
case XMP:
implicitlyCloseP();
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes);
originalMode = mode;
mode = TEXT;
tokenizer.setStateAndEndTagExpectation(
Tokenizer.RAWTEXT, elementName);
attributes = null; // CPP
break starttagloop;
case NOSCRIPT:
if (!scriptingEnabled) {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes);
attributes = null; // CPP
break starttagloop;
}
// CPPONLY: MOZ_FALLTHROUGH;
case NOFRAMES:
case IFRAME:
case NOEMBED:
startTagGenericRawText(elementName, attributes);
attributes = null; // CPP
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 = null; // CPP
break starttagloop;
case OPTGROUP:
case OPTION:
if (isCurrent("option")) {
pop();
}
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes);
attributes = null; // CPP
break starttagloop;
case RB_OR_RTC:
eltPos = findLastInScope("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 = null; // CPP
break starttagloop;
case RT_OR_RP:
eltPos = findLastInScope("ruby");
if (eltPos != NOT_FOUND_ON_STACK) {
generateImpliedEndTagsExceptFor("rtc");
}
if (eltPos != currentPtr) {
if (!isCurrent("rtc")) {
if (eltPos == NOT_FOUND_ON_STACK) {
errStartTagSeenWithoutRuby(name);
} else {
errUnclosedChildrenInRuby();
}
}
}
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes);
attributes = null; // CPP
break starttagloop;
case MATH:
reconstructTheActiveFormattingElements();
attributes.adjustForMath();
if (selfClosing) {
appendVoidElementToCurrentMayFosterMathML(
elementName, attributes);
selfClosing = false;
} else {
appendToCurrentNodeAndPushElementMayFosterMathML(
elementName, attributes);
}
attributes = null; // CPP
break starttagloop;
case SVG:
reconstructTheActiveFormattingElements();
attributes.adjustForSvg();
if (selfClosing) {
appendVoidElementToCurrentMayFosterSVG(
elementName,
attributes);
selfClosing = false;
} else {
appendToCurrentNodeAndPushElementMayFosterSVG(
elementName, attributes);
}
attributes = null; // CPP
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);
break starttagloop;
case OUTPUT:
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes, formPointer);
attributes = null; // CPP
break starttagloop;
default:
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes);
attributes = null; // CPP
break starttagloop;
}
}
// CPPONLY: MOZ_FALLTHROUGH;
case IN_HEAD:
inheadloop: for (;;) {
switch (group) {
case HTML:
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = null; // CPP
}
break starttagloop;
case BASE:
case LINK_OR_BASEFONT_OR_BGSOUND:
appendVoidElementToCurrentMayFoster(
elementName,
attributes);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
attributes = null; // CPP
break starttagloop;
case META:
// Fall through to IN_HEAD_NOSCRIPT
break inheadloop;
case TITLE:
startTagTitleInHead(elementName, attributes);
attributes = null; // CPP
break starttagloop;
case NOSCRIPT:
if (scriptingEnabled) {
appendToCurrentNodeAndPushElement(
elementName,
attributes);
originalMode = mode;
mode = TEXT;
tokenizer.setStateAndEndTagExpectation(
Tokenizer.RAWTEXT, elementName);
} else {
appendToCurrentNodeAndPushElementMayFoster(
elementName,
attributes);
mode = IN_HEAD_NOSCRIPT;
}
attributes = null; // CPP
break starttagloop;
case SCRIPT:
startTagScriptInHead(elementName, attributes);
attributes = null; // CPP
break starttagloop;
case STYLE:
case NOFRAMES:
startTagGenericRawText(elementName, attributes);
attributes = null; // CPP
break starttagloop;
case HEAD:
/* Parse error. */
errFooSeenWhenFooOpen(name);
/* Ignore the token. */
break starttagloop;
case TEMPLATE:
startTagTemplateInHead(elementName, attributes);
attributes = null; // CPP
break starttagloop;
default:
pop();
mode = AFTER_HEAD;
continue starttagloop;
}
}
// CPPONLY: MOZ_FALLTHROUGH;
case IN_HEAD_NOSCRIPT:
switch (group) {
case HTML:
// XXX did Hixie really mean to omit "base"
// here?
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = null; // CPP
}
break starttagloop;
case LINK_OR_BASEFONT_OR_BGSOUND:
appendVoidElementToCurrentMayFoster(
elementName,
attributes);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
attributes = null; // CPP
break starttagloop;
case META:
checkMetaCharset(attributes);
appendVoidElementToCurrentMayFoster(
elementName,
attributes);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
attributes = null; // CPP
break starttagloop;
case STYLE:
case NOFRAMES:
appendToCurrentNodeAndPushElement(
elementName,
attributes);
originalMode = mode;
mode = TEXT;
tokenizer.setStateAndEndTagExpectation(
Tokenizer.RAWTEXT, elementName);
attributes = null; // CPP
break starttagloop;
case HEAD:
errFooSeenWhenFooOpen(name);
break starttagloop;
case NOSCRIPT:
errFooSeenWhenFooOpen(name);
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 = null; // CPP
}
break starttagloop;
case COL:
appendVoidElementToCurrentMayFoster(
elementName,
attributes);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
attributes = null; // CPP
break starttagloop;
case TEMPLATE:
startTagTemplateInHead(elementName, attributes);
attributes = null; // CPP
break starttagloop;
default:
if (currentPtr == 0 || stack[currentPtr].getGroup() == TEMPLATE) {
assert fragment || isTemplateContents();
errGarbageInColgroup();
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("select");
if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
assert fragment;
break starttagloop; // http://www.w3.org/Bugs/Public/show_bug.cgi?id=8375
}
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
continue;
default:
// fall through to IN_SELECT
}
// CPPONLY: MOZ_FALLTHROUGH;
case IN_SELECT:
switch (group) {
case HTML:
errStrayStartTag(name);
if (!fragment) {
addAttributesToHtml(attributes);
attributes = null; // CPP
}
break starttagloop;
case OPTION:
if (isCurrent("option")) {
pop();
}
appendToCurrentNodeAndPushElement(
elementName,
attributes);
attributes = null; // CPP
break starttagloop;
case OPTGROUP:
if (isCurrent("option")) {
pop();
}
if (isCurrent("optgroup")) {
pop();
}
appendToCurrentNodeAndPushElement(
elementName,
attributes);
attributes = null; // CPP
break starttagloop;
case SELECT:
errStartSelectWhereEndSelectExpected();
eltPos = findLastInTableScope(name);
if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
assert fragment;
errNoSelectInTableScope();
break starttagloop;
} else {
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
break starttagloop;
}
case INPUT:
case TEXTAREA:
errStartTagWithSelectOpen(name);
eltPos = findLastInTableScope("select");
if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
assert fragment;
break starttagloop;
}
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
continue;
case SCRIPT:
startTagScriptInHead(elementName, attributes);
attributes = null; // CPP
break starttagloop;
case TEMPLATE:
startTagTemplateInHead(elementName, attributes);
attributes = null; // CPP
break starttagloop;
case HR:
if (isCurrent("option")) {
pop();
}
if (isCurrent("optgroup")) {
pop();
}
appendVoidElementToCurrent(elementName, attributes);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
attributes = null; // CPP
break starttagloop;
default:
errStrayStartTag(name);
break starttagloop;
}
case AFTER_BODY:
switch (group) {
case HTML:
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = null; // CPP
}
break starttagloop;
default:
errStrayStartTag(name);
mode = framesetOk ? FRAMESET_OK : IN_BODY;
continue;
}
case IN_FRAMESET:
switch (group) {
case FRAMESET:
appendToCurrentNodeAndPushElement(
elementName,
attributes);
attributes = null; // CPP
break starttagloop;
case FRAME:
appendVoidElementToCurrentMayFoster(
elementName,
attributes);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
attributes = null; // CPP
break starttagloop;
default:
// fall through to AFTER_FRAMESET
}
// CPPONLY: MOZ_FALLTHROUGH;
case AFTER_FRAMESET:
switch (group) {
case HTML:
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = null; // CPP
}
break starttagloop;
case NOFRAMES:
appendToCurrentNodeAndPushElement(
elementName,
attributes);
originalMode = mode;
mode = TEXT;
tokenizer.setStateAndEndTagExpectation(
Tokenizer.RAWTEXT, elementName);
attributes = null; // CPP
break starttagloop;
default:
errStrayStartTag(name);
break starttagloop;
}
case INITIAL:
/*
* Parse error.
*/
errStartTagWithoutDoctype();
/*
*
* Set the document to quirks mode.
*/
documentModeInternal(DocumentMode.QUIRKS_MODE, null, null);
/*
* Then, switch to the root element mode of the tree
* construction stage
*/
mode = BEFORE_HTML;
/*
* and reprocess the current token.
*/
continue;
case BEFORE_HTML:
switch (group) {
case HTML:
// optimize error check and streaming SAX by
// hoisting
// "html" handling here.
if (attributes == HtmlAttributes.EMPTY_ATTRIBUTES) {
// This has the right magic side effect
// that
// it
// makes attributes in SAX Tree mutable.
appendHtmlElementToDocumentAndPush();
} else {
appendHtmlElementToDocumentAndPush(attributes);
}
// XXX application cache should fire here
mode = BEFORE_HEAD;
attributes = null; // CPP
break starttagloop;
default:
/*
* Create an HTMLElement node with the tag name
* html, in the HTML namespace. Append it to the
* Document object.
*/
appendHtmlElementToDocumentAndPush();
/* Switch to the main mode */
mode = BEFORE_HEAD;
/*
* reprocess the current token.
*/
continue;
}
case BEFORE_HEAD:
switch (group) {
case HTML:
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = null; // CPP
}
break starttagloop;
case HEAD:
/*
* A start tag whose tag name is "head"
*
* Create an element for the token.
*
* Set the head element pointer to this new element
* node.
*
* Append the new element to the current node and
* push it onto the stack of open elements.
*/
appendToCurrentNodeAndPushHeadElement(attributes);
/*
* Change the insertion mode to "in head".
*/
mode = IN_HEAD;
attributes = null; // CPP
break starttagloop;
default:
/*
* Any other start tag token
*
* Act as if a start tag token with the tag name
* "head" and no attributes had been seen,
*/
appendToCurrentNodeAndPushHeadElement(HtmlAttributes.EMPTY_ATTRIBUTES);
mode = IN_HEAD;
/*
* then reprocess the current token.
*
* This will result in an empty head element being
* generated, with the current token being
* reprocessed in the "after head" insertion mode.
*/
continue;
}
case AFTER_HEAD:
switch (group) {
case HTML:
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = null; // CPP
}
break starttagloop;
case BODY:
if (attributes.getLength() == 0) {
// This has the right magic side effect
// that
// it
// makes attributes in SAX Tree mutable.
appendToCurrentNodeAndPushBodyElement();
} else {
appendToCurrentNodeAndPushBodyElement(attributes);
}
framesetOk = false;
mode = IN_BODY;
attributes = null; // CPP
break starttagloop;
case FRAMESET:
appendToCurrentNodeAndPushElement(
elementName,
attributes);
mode = IN_FRAMESET;
attributes = null; // CPP
break starttagloop;
case TEMPLATE:
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
StackNode<T> headOnStack = stack[currentPtr];
startTagTemplateInHead(elementName, attributes);
removeFromStack(headOnStack);
attributes = null; // CPP
break starttagloop;
case BASE:
case LINK_OR_BASEFONT_OR_BGSOUND:
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
appendVoidElementToCurrentMayFoster(
elementName,
attributes);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
pop(); // head
attributes = null; // CPP
break starttagloop;
case META:
errFooBetweenHeadAndBody(name);
checkMetaCharset(attributes);
pushHeadPointerOntoStack();
appendVoidElementToCurrentMayFoster(
elementName,
attributes);
selfClosing = false;
// [NOCPP[
voidElement = true;
// ]NOCPP]
pop(); // head
attributes = null; // CPP
break starttagloop;
case SCRIPT:
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
appendToCurrentNodeAndPushElement(
elementName,
attributes);
originalMode = mode;
mode = TEXT;
tokenizer.setStateAndEndTagExpectation(
Tokenizer.SCRIPT_DATA, elementName);
attributes = null; // CPP
break starttagloop;
case STYLE:
case NOFRAMES:
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
appendToCurrentNodeAndPushElement(
elementName,
attributes);
originalMode = mode;
mode = TEXT;
tokenizer.setStateAndEndTagExpectation(
Tokenizer.RAWTEXT, elementName);
attributes = null; // CPP
break starttagloop;
case TITLE:
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
appendToCurrentNodeAndPushElement(
elementName,
attributes);
originalMode = mode;
mode = TEXT;
tokenizer.setStateAndEndTagExpectation(
Tokenizer.RCDATA, elementName);
attributes = null; // CPP
break starttagloop;
case HEAD:
errStrayStartTag(name);
break starttagloop;
default:
appendToCurrentNodeAndPushBodyElement();
mode = FRAMESET_OK;
continue;
}
case AFTER_AFTER_BODY:
switch (group) {
case HTML:
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = null; // CPP
}
break starttagloop;
default:
errStrayStartTag(name);
fatal();
mode = framesetOk ? FRAMESET_OK : IN_BODY;
continue;
}
case AFTER_AFTER_FRAMESET:
switch (group) {
case HTML:
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = null; // CPP
}
break starttagloop;
case NOFRAMES:
startTagGenericRawText(elementName, attributes);
attributes = null; // CPP
break starttagloop;
default:
errStrayStartTag(name);
break starttagloop;
}
case TEXT:
assert false;
break starttagloop; // Avoid infinite loop if the assertion
// fails
}
}
if (selfClosing) {
errSelfClosing();
// [NOCPP[
} else if (wasSelfClosing && voidElement
&& tokenizer.getErrorProfile() != null
&& tokenizer.getErrorProfile().get("html-strict") != null) {
warn("Trailing slash on void elements has no effect and interacts"
+ " badly with unquoted attribute values.");
// ]NOCPP]
}
// CPPONLY: if (mBuilder == null && attributes != HtmlAttributes.EMPTY_ATTRIBUTES) {
// CPPONLY: Portability.delete(attributes);
// CPPONLY: }
}