fune/parser/html/nsHtml5TreeBuilder.cpp
Boris Zbarsky 49a90cb122 Bug 1268852. Change <label> elements to not be form-associated anymore. r=bkelly,hsivonen,surkov
The web platform tests changes are just a cherrypick of
https://github.com/w3c/web-platform-tests/pull/2926 so I don't have to add
failure annotations until the next test uplift.

I've audited our uses of nsIFormControl, and this patch looks to me like it
preserves existing behavior in all but the following cases:

1)  nsXBLPrototypeHandler::DispatchXBLCommand, the case of scrolling when space
is pressed while something inside a <label> is focused.  We used to not scroll
in this situation; I think this is a bug, so I'm changing that behavior to
scroll instead.

2)  In Accessible::RelationByType for the RelationType::DEFAULT_BUTTON case,
when mContent is a <label> we used to return its form's default submit element.
Now we will just return Relation().
2016-05-26 19:39:03 -04:00

4520 lines
158 KiB
C++

/*
* Copyright (c) 2007 Henri Sivonen
* Copyright (c) 2007-2015 Mozilla Foundation
* Portions of comments Copyright 2004-2008 Apple Computer, Inc., Mozilla
* Foundation, and Opera Software ASA.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/*
* THIS IS A GENERATED FILE. PLEASE DO NOT EDIT.
* Please edit TreeBuilder.java instead and regenerate.
*/
#define nsHtml5TreeBuilder_cpp__
#include "nsContentUtils.h"
#include "nsIAtom.h"
#include "nsHtml5AtomTable.h"
#include "nsITimer.h"
#include "nsString.h"
#include "nsNameSpaceManager.h"
#include "nsIContent.h"
#include "nsTraceRefcnt.h"
#include "jArray.h"
#include "nsHtml5DocumentMode.h"
#include "nsHtml5ArrayCopy.h"
#include "nsHtml5Parser.h"
#include "nsHtml5Atoms.h"
#include "nsHtml5TreeOperation.h"
#include "nsHtml5StateSnapshot.h"
#include "nsHtml5StackNode.h"
#include "nsHtml5TreeOpExecutor.h"
#include "nsHtml5StreamParser.h"
#include "nsAHtml5TreeBuilderState.h"
#include "nsHtml5Highlighter.h"
#include "nsHtml5PlainTextUtils.h"
#include "nsHtml5ViewSourceUtils.h"
#include "mozilla/Likely.h"
#include "nsIContentHandle.h"
#include "nsHtml5OplessBuilder.h"
#include "nsHtml5Tokenizer.h"
#include "nsHtml5MetaScanner.h"
#include "nsHtml5AttributeName.h"
#include "nsHtml5ElementName.h"
#include "nsHtml5HtmlAttributes.h"
#include "nsHtml5StackNode.h"
#include "nsHtml5UTF16Buffer.h"
#include "nsHtml5StateSnapshot.h"
#include "nsHtml5Portability.h"
#include "nsHtml5TreeBuilder.h"
char16_t nsHtml5TreeBuilder::REPLACEMENT_CHARACTER[] = { 0xfffd };
static const char* const QUIRKY_PUBLIC_IDS_DATA[] = { "+//silmaril//dtd html pro v0r11 19970101//", "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", "-//as//dtd html 3.0 aswedit + extensions//", "-//ietf//dtd html 2.0 level 1//", "-//ietf//dtd html 2.0 level 2//", "-//ietf//dtd html 2.0 strict level 1//", "-//ietf//dtd html 2.0 strict level 2//", "-//ietf//dtd html 2.0 strict//", "-//ietf//dtd html 2.0//", "-//ietf//dtd html 2.1e//", "-//ietf//dtd html 3.0//", "-//ietf//dtd html 3.2 final//", "-//ietf//dtd html 3.2//", "-//ietf//dtd html 3//", "-//ietf//dtd html level 0//", "-//ietf//dtd html level 1//", "-//ietf//dtd html level 2//", "-//ietf//dtd html level 3//", "-//ietf//dtd html strict level 0//", "-//ietf//dtd html strict level 1//", "-//ietf//dtd html strict level 2//", "-//ietf//dtd html strict level 3//", "-//ietf//dtd html strict//", "-//ietf//dtd html//", "-//metrius//dtd metrius presentational//", "-//microsoft//dtd internet explorer 2.0 html strict//", "-//microsoft//dtd internet explorer 2.0 html//", "-//microsoft//dtd internet explorer 2.0 tables//", "-//microsoft//dtd internet explorer 3.0 html strict//", "-//microsoft//dtd internet explorer 3.0 html//", "-//microsoft//dtd internet explorer 3.0 tables//", "-//netscape comm. corp.//dtd html//", "-//netscape comm. corp.//dtd strict html//", "-//o'reilly and associates//dtd html 2.0//", "-//o'reilly and associates//dtd html extended 1.0//", "-//o'reilly and associates//dtd html extended relaxed 1.0//", "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", "-//spyglass//dtd html 2.0 extended//", "-//sq//dtd html 2.0 hotmetal + extensions//", "-//sun microsystems corp.//dtd hotjava html//", "-//sun microsystems corp.//dtd hotjava strict html//", "-//w3c//dtd html 3 1995-03-24//", "-//w3c//dtd html 3.2 draft//", "-//w3c//dtd html 3.2 final//", "-//w3c//dtd html 3.2//", "-//w3c//dtd html 3.2s draft//", "-//w3c//dtd html 4.0 frameset//", "-//w3c//dtd html 4.0 transitional//", "-//w3c//dtd html experimental 19960712//", "-//w3c//dtd html experimental 970421//", "-//w3c//dtd w3 html//", "-//w3o//dtd w3 html 3.0//", "-//webtechs//dtd mozilla html 2.0//", "-//webtechs//dtd mozilla html//" };
staticJArray<const char*,int32_t> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = { QUIRKY_PUBLIC_IDS_DATA, MOZ_ARRAY_LENGTH(QUIRKY_PUBLIC_IDS_DATA) };
void
nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self)
{
tokenizer = self;
stack = jArray<nsHtml5StackNode*,int32_t>::newJArray(64);
templateModeStack = jArray<int32_t,int32_t>::newJArray(64);
listOfActiveFormattingElements = jArray<nsHtml5StackNode*,int32_t>::newJArray(64);
needToDropLF = false;
originalMode = NS_HTML5TREE_BUILDER_INITIAL;
templateModePtr = -1;
currentPtr = -1;
listPtr = -1;
formPointer = nullptr;
headPointer = nullptr;
deepTreeSurrogateParent = nullptr;
start(fragment);
charBufferLen = 0;
charBuffer = nullptr;
framesetOk = true;
if (fragment) {
nsIContentHandle* elt;
if (contextNode) {
elt = contextNode;
} else {
elt = createHtmlElementSetAsRoot(tokenizer->emptyAttributes());
}
if (contextNamespace == kNameSpaceID_SVG) {
nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_SVG;
if (nsHtml5Atoms::title == contextName || nsHtml5Atoms::desc == contextName || nsHtml5Atoms::foreignObject == contextName) {
elementName = nsHtml5ElementName::ELT_FOREIGNOBJECT;
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elementName->camelCaseName, elt);
currentPtr++;
stack[currentPtr] = node;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_DATA, contextName);
mode = NS_HTML5TREE_BUILDER_FRAMESET_OK;
} else if (contextNamespace == kNameSpaceID_MathML) {
nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_MATH;
if (nsHtml5Atoms::mi == contextName || nsHtml5Atoms::mo == contextName || nsHtml5Atoms::mn == contextName || nsHtml5Atoms::ms == contextName || nsHtml5Atoms::mtext == contextName) {
elementName = nsHtml5ElementName::ELT_MTEXT;
} else if (nsHtml5Atoms::annotation_xml == contextName) {
elementName = nsHtml5ElementName::ELT_ANNOTATION_XML;
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, elementName->name, false);
currentPtr++;
stack[currentPtr] = node;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_DATA, contextName);
mode = NS_HTML5TREE_BUILDER_FRAMESET_OK;
} else {
nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HTML, elt);
currentPtr++;
stack[currentPtr] = node;
if (nsHtml5Atoms::template_ == contextName) {
pushTemplateMode(NS_HTML5TREE_BUILDER_IN_TEMPLATE);
}
resetTheInsertionMode();
formPointer = getFormPointerForContext(contextNode);
if (nsHtml5Atoms::title == contextName || nsHtml5Atoms::textarea == contextName) {
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RCDATA, contextName);
} else if (nsHtml5Atoms::style == contextName || nsHtml5Atoms::xmp == contextName || nsHtml5Atoms::iframe == contextName || nsHtml5Atoms::noembed == contextName || nsHtml5Atoms::noframes == contextName || (scriptingEnabled && nsHtml5Atoms::noscript == contextName)) {
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RAWTEXT, contextName);
} else if (nsHtml5Atoms::plaintext == contextName) {
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_PLAINTEXT, contextName);
} else if (nsHtml5Atoms::script == contextName) {
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_SCRIPT_DATA, contextName);
} else {
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_DATA, contextName);
}
}
contextName = nullptr;
contextNode = nullptr;
} else {
mode = NS_HTML5TREE_BUILDER_INITIAL;
if (tokenizer->isViewingXmlSource()) {
nsIContentHandle* elt = createElement(kNameSpaceID_SVG, nsHtml5Atoms::svg, tokenizer->emptyAttributes(), nullptr);
nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_SVG, nsHtml5Atoms::svg, elt);
currentPtr++;
stack[currentPtr] = node;
}
}
}
void
nsHtml5TreeBuilder::doctype(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier, bool forceQuirks)
{
needToDropLF = false;
if (!isInForeign() && mode == NS_HTML5TREE_BUILDER_INITIAL) {
nsString* emptyString = nsHtml5Portability::newEmptyString();
appendDoctypeToDocument(!name ? nsHtml5Atoms::emptystring : name, !publicIdentifier ? emptyString : publicIdentifier, !systemIdentifier ? emptyString : systemIdentifier);
nsHtml5Portability::releaseString(emptyString);
if (isQuirky(name, publicIdentifier, systemIdentifier, forceQuirks)) {
errQuirkyDoctype();
documentModeInternal(QUIRKS_MODE, publicIdentifier, systemIdentifier, false);
} else if (isAlmostStandards(publicIdentifier, systemIdentifier)) {
errAlmostStandardsDoctype();
documentModeInternal(ALMOST_STANDARDS_MODE, publicIdentifier, systemIdentifier, false);
} else {
documentModeInternal(STANDARDS_MODE, publicIdentifier, systemIdentifier, false);
}
mode = NS_HTML5TREE_BUILDER_BEFORE_HTML;
return;
}
errStrayDoctype();
return;
}
void
nsHtml5TreeBuilder::comment(char16_t* buf, int32_t start, int32_t length)
{
needToDropLF = false;
if (!isInForeign()) {
switch(mode) {
case NS_HTML5TREE_BUILDER_INITIAL:
case NS_HTML5TREE_BUILDER_BEFORE_HTML:
case NS_HTML5TREE_BUILDER_AFTER_AFTER_BODY:
case NS_HTML5TREE_BUILDER_AFTER_AFTER_FRAMESET: {
appendCommentToDocument(buf, start, length);
return;
}
case NS_HTML5TREE_BUILDER_AFTER_BODY: {
flushCharacters();
appendComment(stack[0]->node, buf, start, length);
return;
}
default: {
break;
}
}
}
flushCharacters();
appendComment(stack[currentPtr]->node, buf, start, length);
return;
}
void
nsHtml5TreeBuilder::characters(const char16_t* buf, int32_t start, int32_t length)
{
if (tokenizer->isViewingXmlSource()) {
return;
}
if (needToDropLF) {
needToDropLF = false;
if (buf[start] == '\n') {
start++;
length--;
if (!length) {
return;
}
}
}
switch(mode) {
case NS_HTML5TREE_BUILDER_IN_BODY:
case NS_HTML5TREE_BUILDER_IN_CELL:
case NS_HTML5TREE_BUILDER_IN_CAPTION: {
if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
reconstructTheActiveFormattingElements();
}
}
case NS_HTML5TREE_BUILDER_TEXT: {
accumulateCharacters(buf, start, length);
return;
}
case NS_HTML5TREE_BUILDER_IN_TABLE:
case NS_HTML5TREE_BUILDER_IN_TABLE_BODY:
case NS_HTML5TREE_BUILDER_IN_ROW: {
accumulateCharactersForced(buf, start, length);
return;
}
default: {
int32_t end = start + length;
for (int32_t i = start; i < end; i++) {
switch(buf[i]) {
case ' ':
case '\t':
case '\n':
case '\r':
case '\f': {
switch(mode) {
case NS_HTML5TREE_BUILDER_INITIAL:
case NS_HTML5TREE_BUILDER_BEFORE_HTML:
case NS_HTML5TREE_BUILDER_BEFORE_HEAD: {
start = i + 1;
continue;
}
case NS_HTML5TREE_BUILDER_IN_HEAD:
case NS_HTML5TREE_BUILDER_IN_HEAD_NOSCRIPT:
case NS_HTML5TREE_BUILDER_AFTER_HEAD:
case NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP:
case NS_HTML5TREE_BUILDER_IN_FRAMESET:
case NS_HTML5TREE_BUILDER_AFTER_FRAMESET: {
continue;
}
case NS_HTML5TREE_BUILDER_FRAMESET_OK:
case NS_HTML5TREE_BUILDER_IN_TEMPLATE:
case NS_HTML5TREE_BUILDER_IN_BODY:
case NS_HTML5TREE_BUILDER_IN_CELL:
case NS_HTML5TREE_BUILDER_IN_CAPTION: {
if (start < i) {
accumulateCharacters(buf, start, i - start);
start = i;
}
if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
flushCharacters();
reconstructTheActiveFormattingElements();
}
NS_HTML5_BREAK(charactersloop);
}
case NS_HTML5TREE_BUILDER_IN_SELECT:
case NS_HTML5TREE_BUILDER_IN_SELECT_IN_TABLE: {
NS_HTML5_BREAK(charactersloop);
}
case NS_HTML5TREE_BUILDER_IN_TABLE:
case NS_HTML5TREE_BUILDER_IN_TABLE_BODY:
case NS_HTML5TREE_BUILDER_IN_ROW: {
accumulateCharactersForced(buf, i, 1);
start = i + 1;
continue;
}
case NS_HTML5TREE_BUILDER_AFTER_BODY:
case NS_HTML5TREE_BUILDER_AFTER_AFTER_BODY:
case NS_HTML5TREE_BUILDER_AFTER_AFTER_FRAMESET: {
if (start < i) {
accumulateCharacters(buf, start, i - start);
start = i;
}
flushCharacters();
reconstructTheActiveFormattingElements();
continue;
}
}
}
default: {
switch(mode) {
case NS_HTML5TREE_BUILDER_INITIAL: {
documentModeInternal(QUIRKS_MODE, nullptr, nullptr, false);
mode = NS_HTML5TREE_BUILDER_BEFORE_HTML;
i--;
continue;
}
case NS_HTML5TREE_BUILDER_BEFORE_HTML: {
appendHtmlElementToDocumentAndPush();
mode = NS_HTML5TREE_BUILDER_BEFORE_HEAD;
i--;
continue;
}
case NS_HTML5TREE_BUILDER_BEFORE_HEAD: {
if (start < i) {
accumulateCharacters(buf, start, i - start);
start = i;
}
flushCharacters();
appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
mode = NS_HTML5TREE_BUILDER_IN_HEAD;
i--;
continue;
}
case NS_HTML5TREE_BUILDER_IN_HEAD: {
if (start < i) {
accumulateCharacters(buf, start, i - start);
start = i;
}
flushCharacters();
pop();
mode = NS_HTML5TREE_BUILDER_AFTER_HEAD;
i--;
continue;
}
case NS_HTML5TREE_BUILDER_IN_HEAD_NOSCRIPT: {
if (start < i) {
accumulateCharacters(buf, start, i - start);
start = i;
}
errNonSpaceInNoscriptInHead();
flushCharacters();
pop();
mode = NS_HTML5TREE_BUILDER_IN_HEAD;
i--;
continue;
}
case NS_HTML5TREE_BUILDER_AFTER_HEAD: {
if (start < i) {
accumulateCharacters(buf, start, i - start);
start = i;
}
flushCharacters();
appendToCurrentNodeAndPushBodyElement();
mode = NS_HTML5TREE_BUILDER_FRAMESET_OK;
i--;
continue;
}
case NS_HTML5TREE_BUILDER_FRAMESET_OK: {
framesetOk = false;
mode = NS_HTML5TREE_BUILDER_IN_BODY;
i--;
continue;
}
case NS_HTML5TREE_BUILDER_IN_TEMPLATE:
case NS_HTML5TREE_BUILDER_IN_BODY:
case NS_HTML5TREE_BUILDER_IN_CELL:
case NS_HTML5TREE_BUILDER_IN_CAPTION: {
if (start < i) {
accumulateCharacters(buf, start, i - start);
start = i;
}
if (!isInForeignButNotHtmlOrMathTextIntegrationPoint()) {
flushCharacters();
reconstructTheActiveFormattingElements();
}
NS_HTML5_BREAK(charactersloop);
}
case NS_HTML5TREE_BUILDER_IN_TABLE:
case NS_HTML5TREE_BUILDER_IN_TABLE_BODY:
case NS_HTML5TREE_BUILDER_IN_ROW: {
accumulateCharactersForced(buf, i, 1);
start = i + 1;
continue;
}
case NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP: {
if (start < i) {
accumulateCharacters(buf, start, i - start);
start = i;
}
if (!currentPtr || stack[currentPtr]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE) {
errNonSpaceInColgroupInFragment();
start = i + 1;
continue;
}
flushCharacters();
pop();
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
i--;
continue;
}
case NS_HTML5TREE_BUILDER_IN_SELECT:
case NS_HTML5TREE_BUILDER_IN_SELECT_IN_TABLE: {
NS_HTML5_BREAK(charactersloop);
}
case NS_HTML5TREE_BUILDER_AFTER_BODY: {
errNonSpaceAfterBody();
mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
i--;
continue;
}
case NS_HTML5TREE_BUILDER_IN_FRAMESET: {
if (start < i) {
accumulateCharacters(buf, start, i - start);
}
errNonSpaceInFrameset();
start = i + 1;
continue;
}
case NS_HTML5TREE_BUILDER_AFTER_FRAMESET: {
if (start < i) {
accumulateCharacters(buf, start, i - start);
}
errNonSpaceAfterFrameset();
start = i + 1;
continue;
}
case NS_HTML5TREE_BUILDER_AFTER_AFTER_BODY: {
errNonSpaceInTrailer();
mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
i--;
continue;
}
case NS_HTML5TREE_BUILDER_AFTER_AFTER_FRAMESET: {
if (start < i) {
accumulateCharacters(buf, start, i - start);
}
errNonSpaceInTrailer();
start = i + 1;
continue;
}
}
}
}
}
charactersloop_end: ;
if (start < end) {
accumulateCharacters(buf, start, end - start);
}
}
}
}
void
nsHtml5TreeBuilder::zeroOriginatingReplacementCharacter()
{
if (mode == NS_HTML5TREE_BUILDER_TEXT) {
accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
return;
}
if (currentPtr >= 0) {
if (isSpecialParentInForeign(stack[currentPtr])) {
return;
}
accumulateCharacters(REPLACEMENT_CHARACTER, 0, 1);
}
}
void
nsHtml5TreeBuilder::eof()
{
flushCharacters();
for (; ; ) {
switch(mode) {
case NS_HTML5TREE_BUILDER_INITIAL: {
documentModeInternal(QUIRKS_MODE, nullptr, nullptr, false);
mode = NS_HTML5TREE_BUILDER_BEFORE_HTML;
continue;
}
case NS_HTML5TREE_BUILDER_BEFORE_HTML: {
appendHtmlElementToDocumentAndPush();
mode = NS_HTML5TREE_BUILDER_BEFORE_HEAD;
continue;
}
case NS_HTML5TREE_BUILDER_BEFORE_HEAD: {
appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
mode = NS_HTML5TREE_BUILDER_IN_HEAD;
continue;
}
case NS_HTML5TREE_BUILDER_IN_HEAD: {
while (currentPtr > 0) {
popOnEof();
}
mode = NS_HTML5TREE_BUILDER_AFTER_HEAD;
continue;
}
case NS_HTML5TREE_BUILDER_IN_HEAD_NOSCRIPT: {
while (currentPtr > 1) {
popOnEof();
}
mode = NS_HTML5TREE_BUILDER_IN_HEAD;
continue;
}
case NS_HTML5TREE_BUILDER_AFTER_HEAD: {
appendToCurrentNodeAndPushBodyElement();
mode = NS_HTML5TREE_BUILDER_IN_BODY;
continue;
}
case NS_HTML5TREE_BUILDER_IN_TABLE_BODY:
case NS_HTML5TREE_BUILDER_IN_ROW:
case NS_HTML5TREE_BUILDER_IN_TABLE:
case NS_HTML5TREE_BUILDER_IN_SELECT_IN_TABLE:
case NS_HTML5TREE_BUILDER_IN_SELECT:
case NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP:
case NS_HTML5TREE_BUILDER_FRAMESET_OK:
case NS_HTML5TREE_BUILDER_IN_CAPTION:
case NS_HTML5TREE_BUILDER_IN_CELL:
case NS_HTML5TREE_BUILDER_IN_BODY: {
if (isTemplateModeStackEmpty()) {
NS_HTML5_BREAK(eofloop);
}
}
case NS_HTML5TREE_BUILDER_IN_TEMPLATE: {
int32_t eltPos = findLast(nsHtml5Atoms::template_);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment);
NS_HTML5_BREAK(eofloop);
}
if (MOZ_UNLIKELY(mViewSource)) {
errUnclosedElements(eltPos, nsHtml5Atoms::template_);
}
while (currentPtr >= eltPos) {
pop();
}
clearTheListOfActiveFormattingElementsUpToTheLastMarker();
popTemplateMode();
resetTheInsertionMode();
continue;
}
case NS_HTML5TREE_BUILDER_TEXT: {
if (originalMode == NS_HTML5TREE_BUILDER_AFTER_HEAD) {
popOnEof();
}
popOnEof();
mode = originalMode;
continue;
}
case NS_HTML5TREE_BUILDER_IN_FRAMESET: {
NS_HTML5_BREAK(eofloop);
}
case NS_HTML5TREE_BUILDER_AFTER_BODY:
case NS_HTML5TREE_BUILDER_AFTER_FRAMESET:
case NS_HTML5TREE_BUILDER_AFTER_AFTER_BODY:
case NS_HTML5TREE_BUILDER_AFTER_AFTER_FRAMESET:
default: {
NS_HTML5_BREAK(eofloop);
}
}
}
eofloop_end: ;
while (currentPtr > 0) {
popOnEof();
}
if (!fragment) {
popOnEof();
}
}
void
nsHtml5TreeBuilder::endTokenization()
{
formPointer = nullptr;
headPointer = nullptr;
deepTreeSurrogateParent = nullptr;
templateModeStack = nullptr;
if (stack) {
while (currentPtr > -1) {
stack[currentPtr]->release();
currentPtr--;
}
stack = nullptr;
}
if (listOfActiveFormattingElements) {
while (listPtr > -1) {
if (listOfActiveFormattingElements[listPtr]) {
listOfActiveFormattingElements[listPtr]->release();
}
listPtr--;
}
listOfActiveFormattingElements = nullptr;
}
charBuffer = nullptr;
end();
}
void
nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, bool selfClosing)
{
flushCharacters();
int32_t eltPos;
needToDropLF = false;
starttagloop: for (; ; ) {
int32_t group = elementName->getGroup();
nsIAtom* name = elementName->name;
if (isInForeign()) {
nsHtml5StackNode* currentNode = stack[currentPtr];
int32_t currNs = currentNode->ns;
if (!(currentNode->isHtmlIntegrationPoint() || (currNs == kNameSpaceID_MathML && ((currentNode->getGroup() == NS_HTML5TREE_BUILDER_MI_MO_MN_MS_MTEXT && group != NS_HTML5TREE_BUILDER_MGLYPH_OR_MALIGNMARK) || (currentNode->getGroup() == NS_HTML5TREE_BUILDER_ANNOTATION_XML && group == NS_HTML5TREE_BUILDER_SVG))))) {
switch(group) {
case NS_HTML5TREE_BUILDER_B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
case NS_HTML5TREE_BUILDER_DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
case NS_HTML5TREE_BUILDER_BODY:
case NS_HTML5TREE_BUILDER_BR:
case NS_HTML5TREE_BUILDER_RUBY_OR_SPAN_OR_SUB_OR_SUP_OR_VAR:
case NS_HTML5TREE_BUILDER_DD_OR_DT:
case NS_HTML5TREE_BUILDER_UL_OR_OL_OR_DL:
case NS_HTML5TREE_BUILDER_EMBED:
case NS_HTML5TREE_BUILDER_IMG:
case NS_HTML5TREE_BUILDER_H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6:
case NS_HTML5TREE_BUILDER_HEAD:
case NS_HTML5TREE_BUILDER_HR:
case NS_HTML5TREE_BUILDER_LI:
case NS_HTML5TREE_BUILDER_META:
case NS_HTML5TREE_BUILDER_NOBR:
case NS_HTML5TREE_BUILDER_P:
case NS_HTML5TREE_BUILDER_PRE_OR_LISTING:
case NS_HTML5TREE_BUILDER_TABLE:
case NS_HTML5TREE_BUILDER_FONT: {
if (!(group == NS_HTML5TREE_BUILDER_FONT && !(attributes->contains(nsHtml5AttributeName::ATTR_COLOR) || attributes->contains(nsHtml5AttributeName::ATTR_FACE) || attributes->contains(nsHtml5AttributeName::ATTR_SIZE)))) {
errHtmlStartTagInForeignContext(name);
if (!fragment) {
while (!isSpecialParentInForeign(stack[currentPtr])) {
pop();
}
NS_HTML5_CONTINUE(starttagloop);
}
}
}
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 NS_HTML5TREE_BUILDER_IN_TEMPLATE: {
switch(group) {
case NS_HTML5TREE_BUILDER_COL: {
popTemplateMode();
pushTemplateMode(NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP);
mode = NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP;
continue;
}
case NS_HTML5TREE_BUILDER_CAPTION:
case NS_HTML5TREE_BUILDER_COLGROUP:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT: {
popTemplateMode();
pushTemplateMode(NS_HTML5TREE_BUILDER_IN_TABLE);
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
continue;
}
case NS_HTML5TREE_BUILDER_TR: {
popTemplateMode();
pushTemplateMode(NS_HTML5TREE_BUILDER_IN_TABLE_BODY);
mode = NS_HTML5TREE_BUILDER_IN_TABLE_BODY;
continue;
}
case NS_HTML5TREE_BUILDER_TD_OR_TH: {
popTemplateMode();
pushTemplateMode(NS_HTML5TREE_BUILDER_IN_ROW);
mode = NS_HTML5TREE_BUILDER_IN_ROW;
continue;
}
case NS_HTML5TREE_BUILDER_META: {
checkMetaCharset(attributes);
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_TITLE: {
startTagTitleInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_BASE:
case NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND: {
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_SCRIPT: {
startTagScriptInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_NOFRAMES:
case NS_HTML5TREE_BUILDER_STYLE: {
startTagGenericRawText(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_TEMPLATE: {
startTagTemplateInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
popTemplateMode();
pushTemplateMode(NS_HTML5TREE_BUILDER_IN_BODY);
mode = NS_HTML5TREE_BUILDER_IN_BODY;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_IN_ROW: {
switch(group) {
case NS_HTML5TREE_BUILDER_TD_OR_TH: {
clearStackBackTo(findLastOrRoot(NS_HTML5TREE_BUILDER_TR));
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = NS_HTML5TREE_BUILDER_IN_CELL;
insertMarker();
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_CAPTION:
case NS_HTML5TREE_BUILDER_COL:
case NS_HTML5TREE_BUILDER_COLGROUP:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT:
case NS_HTML5TREE_BUILDER_TR: {
eltPos = findLastOrRoot(NS_HTML5TREE_BUILDER_TR);
if (!eltPos) {
MOZ_ASSERT(fragment || isTemplateContents());
errNoTableRowToClose();
NS_HTML5_BREAK(starttagloop);
}
clearStackBackTo(eltPos);
pop();
mode = NS_HTML5TREE_BUILDER_IN_TABLE_BODY;
continue;
}
default:
; // fall through
}
}
case NS_HTML5TREE_BUILDER_IN_TABLE_BODY: {
switch(group) {
case NS_HTML5TREE_BUILDER_TR: {
clearStackBackTo(findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = NS_HTML5TREE_BUILDER_IN_ROW;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_TD_OR_TH: {
errStartTagInTableBody(name);
clearStackBackTo(findLastInTableScopeOrRootTemplateTbodyTheadTfoot());
appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_TR, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
mode = NS_HTML5TREE_BUILDER_IN_ROW;
continue;
}
case NS_HTML5TREE_BUILDER_CAPTION:
case NS_HTML5TREE_BUILDER_COL:
case NS_HTML5TREE_BUILDER_COLGROUP:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT: {
eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
if (!eltPos || stack[eltPos]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE) {
MOZ_ASSERT(fragment || isTemplateContents());
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
} else {
clearStackBackTo(eltPos);
pop();
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
continue;
}
}
default:
; // fall through
}
}
case NS_HTML5TREE_BUILDER_IN_TABLE: {
for (; ; ) {
switch(group) {
case NS_HTML5TREE_BUILDER_CAPTION: {
clearStackBackTo(findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE));
insertMarker();
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = NS_HTML5TREE_BUILDER_IN_CAPTION;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_COLGROUP: {
clearStackBackTo(findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE));
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_COL: {
clearStackBackTo(findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE));
appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_COLGROUP, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
mode = NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP;
NS_HTML5_CONTINUE(starttagloop);
}
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT: {
clearStackBackTo(findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE));
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = NS_HTML5TREE_BUILDER_IN_TABLE_BODY;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_TR:
case NS_HTML5TREE_BUILDER_TD_OR_TH: {
clearStackBackTo(findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE));
appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_TBODY, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
mode = NS_HTML5TREE_BUILDER_IN_TABLE_BODY;
NS_HTML5_CONTINUE(starttagloop);
}
case NS_HTML5TREE_BUILDER_TEMPLATE: {
NS_HTML5_BREAK(intableloop);
}
case NS_HTML5TREE_BUILDER_TABLE: {
errTableSeenWhileTableOpen();
eltPos = findLastInTableScope(name);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment || isTemplateContents());
NS_HTML5_BREAK(starttagloop);
}
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsHtml5Atoms::table)) {
errNoCheckUnclosedElementsOnStack();
}
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
NS_HTML5_CONTINUE(starttagloop);
}
case NS_HTML5TREE_BUILDER_SCRIPT: {
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_SCRIPT_DATA, elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_STYLE: {
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RAWTEXT, elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_INPUT: {
errStartTagInTable(name);
if (!nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("hidden", attributes->getValue(nsHtml5AttributeName::ATTR_TYPE))) {
NS_HTML5_BREAK(intableloop);
}
appendVoidElementToCurrent(name, attributes, formPointer);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_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: ;
}
case NS_HTML5TREE_BUILDER_IN_CAPTION: {
switch(group) {
case NS_HTML5TREE_BUILDER_CAPTION:
case NS_HTML5TREE_BUILDER_COL:
case NS_HTML5TREE_BUILDER_COLGROUP:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT:
case NS_HTML5TREE_BUILDER_TR:
case NS_HTML5TREE_BUILDER_TD_OR_TH: {
errStrayStartTag(name);
eltPos = findLastInTableScope(nsHtml5Atoms::caption);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
NS_HTML5_BREAK(starttagloop);
}
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
errNoCheckUnclosedElementsOnStack();
}
while (currentPtr >= eltPos) {
pop();
}
clearTheListOfActiveFormattingElementsUpToTheLastMarker();
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
continue;
}
default:
; // fall through
}
}
case NS_HTML5TREE_BUILDER_IN_CELL: {
switch(group) {
case NS_HTML5TREE_BUILDER_CAPTION:
case NS_HTML5TREE_BUILDER_COL:
case NS_HTML5TREE_BUILDER_COLGROUP:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT:
case NS_HTML5TREE_BUILDER_TR:
case NS_HTML5TREE_BUILDER_TD_OR_TH: {
eltPos = findLastInTableScopeTdTh();
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errNoCellToClose();
NS_HTML5_BREAK(starttagloop);
} else {
closeTheCell(eltPos);
continue;
}
}
default:
; // fall through
}
}
case NS_HTML5TREE_BUILDER_FRAMESET_OK: {
switch(group) {
case NS_HTML5TREE_BUILDER_FRAMESET: {
if (mode == NS_HTML5TREE_BUILDER_FRAMESET_OK) {
if (!currentPtr || stack[1]->getGroup() != NS_HTML5TREE_BUILDER_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 = NS_HTML5TREE_BUILDER_IN_FRAMESET;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
} else {
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
}
case NS_HTML5TREE_BUILDER_PRE_OR_LISTING:
case NS_HTML5TREE_BUILDER_LI:
case NS_HTML5TREE_BUILDER_DD_OR_DT:
case NS_HTML5TREE_BUILDER_BUTTON:
case NS_HTML5TREE_BUILDER_MARQUEE_OR_APPLET:
case NS_HTML5TREE_BUILDER_OBJECT:
case NS_HTML5TREE_BUILDER_TABLE:
case NS_HTML5TREE_BUILDER_AREA_OR_WBR:
case NS_HTML5TREE_BUILDER_BR:
case NS_HTML5TREE_BUILDER_EMBED:
case NS_HTML5TREE_BUILDER_IMG:
case NS_HTML5TREE_BUILDER_INPUT:
case NS_HTML5TREE_BUILDER_KEYGEN:
case NS_HTML5TREE_BUILDER_HR:
case NS_HTML5TREE_BUILDER_TEXTAREA:
case NS_HTML5TREE_BUILDER_XMP:
case NS_HTML5TREE_BUILDER_IFRAME:
case NS_HTML5TREE_BUILDER_SELECT: {
if (mode == NS_HTML5TREE_BUILDER_FRAMESET_OK && !(group == NS_HTML5TREE_BUILDER_INPUT && nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("hidden", attributes->getValue(nsHtml5AttributeName::ATTR_TYPE)))) {
framesetOk = false;
mode = NS_HTML5TREE_BUILDER_IN_BODY;
}
}
default:
; // fall through
}
}
case NS_HTML5TREE_BUILDER_IN_BODY: {
for (; ; ) {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_BASE:
case NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND:
case NS_HTML5TREE_BUILDER_META:
case NS_HTML5TREE_BUILDER_STYLE:
case NS_HTML5TREE_BUILDER_SCRIPT:
case NS_HTML5TREE_BUILDER_TITLE:
case NS_HTML5TREE_BUILDER_TEMPLATE: {
NS_HTML5_BREAK(inbodyloop);
}
case NS_HTML5TREE_BUILDER_BODY: {
if (!currentPtr || stack[1]->getGroup() != NS_HTML5TREE_BUILDER_BODY || isTemplateContents()) {
MOZ_ASSERT(fragment || isTemplateContents());
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
errFooSeenWhenFooOpen(name);
framesetOk = false;
if (mode == NS_HTML5TREE_BUILDER_FRAMESET_OK) {
mode = NS_HTML5TREE_BUILDER_IN_BODY;
}
if (addAttributesToBody(attributes)) {
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_P:
case NS_HTML5TREE_BUILDER_DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
case NS_HTML5TREE_BUILDER_UL_OR_OL_OR_DL:
case NS_HTML5TREE_BUILDER_ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY: {
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: {
implicitlyCloseP();
if (stack[currentPtr]->getGroup() == NS_HTML5TREE_BUILDER_H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
errHeadingWhenHeadingOpen();
pop();
}
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_FIELDSET: {
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes, formPointer);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_PRE_OR_LISTING: {
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
needToDropLF = true;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_FORM: {
if (!!formPointer && !isTemplateContents()) {
errFormWhenFormOpen();
NS_HTML5_BREAK(starttagloop);
} else {
implicitlyCloseP();
appendToCurrentNodeAndPushFormElementMayFoster(attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
}
case NS_HTML5TREE_BUILDER_LI:
case NS_HTML5TREE_BUILDER_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 != nsHtml5Atoms::p && node->name != nsHtml5Atoms::address && node->name != nsHtml5Atoms::div)))) {
break;
}
eltPos--;
}
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_PLAINTEXT: {
implicitlyCloseP();
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_PLAINTEXT, elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_A: {
int32_t activeAPos = findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(nsHtml5Atoms::a);
if (activeAPos != -1) {
errFooSeenWhenFooOpen(name);
nsHtml5StackNode* activeA = listOfActiveFormattingElements[activeAPos];
activeA->retain();
adoptionAgencyEndTag(nsHtml5Atoms::a);
removeFromStack(activeA);
activeAPos = findInListOfActiveFormattingElements(activeA);
if (activeAPos != -1) {
removeFromListOfActiveFormattingElements(activeAPos);
}
activeA->release();
}
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushFormattingElementMayFoster(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
case NS_HTML5TREE_BUILDER_FONT: {
reconstructTheActiveFormattingElements();
maybeForgetEarlierDuplicateFormattingElement(elementName->name, attributes);
appendToCurrentNodeAndPushFormattingElementMayFoster(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_NOBR: {
reconstructTheActiveFormattingElements();
if (NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK != findLastInScope(nsHtml5Atoms::nobr)) {
errFooSeenWhenFooOpen(name);
adoptionAgencyEndTag(nsHtml5Atoms::nobr);
reconstructTheActiveFormattingElements();
}
appendToCurrentNodeAndPushFormattingElementMayFoster(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_BUTTON: {
eltPos = findLastInScope(name);
if (eltPos != NS_HTML5TREE_BUILDER_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 NS_HTML5TREE_BUILDER_OBJECT: {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes, formPointer);
insertMarker();
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_MARQUEE_OR_APPLET: {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
insertMarker();
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_TABLE: {
if (!quirks) {
implicitlyCloseP();
}
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_BR:
case NS_HTML5TREE_BUILDER_EMBED:
case NS_HTML5TREE_BUILDER_AREA_OR_WBR: {
reconstructTheActiveFormattingElements();
}
#ifdef ENABLE_VOID_MENUITEM
case NS_HTML5TREE_BUILDER_MENUITEM:
#endif
case NS_HTML5TREE_BUILDER_PARAM_OR_SOURCE_OR_TRACK: {
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_HR: {
implicitlyCloseP();
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_IMAGE: {
errImage();
elementName = nsHtml5ElementName::ELT_IMG;
NS_HTML5_CONTINUE(starttagloop);
}
case NS_HTML5TREE_BUILDER_IMG:
case NS_HTML5TREE_BUILDER_KEYGEN:
case NS_HTML5TREE_BUILDER_INPUT: {
reconstructTheActiveFormattingElements();
appendVoidElementToCurrentMayFoster(name, attributes, formPointer);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_ISINDEX: {
errIsindex();
if (!!formPointer && !isTemplateContents()) {
NS_HTML5_BREAK(starttagloop);
}
implicitlyCloseP();
nsHtml5HtmlAttributes* formAttrs = new nsHtml5HtmlAttributes(0);
int32_t actionIndex = attributes->getIndex(nsHtml5AttributeName::ATTR_ACTION);
if (actionIndex > -1) {
formAttrs->addAttribute(nsHtml5AttributeName::ATTR_ACTION, attributes->getValueNoBoundsCheck(actionIndex));
}
appendToCurrentNodeAndPushFormElementMayFoster(formAttrs);
appendVoidElementToCurrentMayFoster(nsHtml5ElementName::ELT_HR, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName::ELT_LABEL, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
int32_t promptIndex = attributes->getIndex(nsHtml5AttributeName::ATTR_PROMPT);
if (promptIndex > -1) {
autoJArray<char16_t,int32_t> prompt = nsHtml5Portability::newCharArrayFromString(attributes->getValueNoBoundsCheck(promptIndex));
appendCharacters(stack[currentPtr]->node, prompt, 0, prompt.length);
} else {
appendIsindexPrompt(stack[currentPtr]->node);
}
nsHtml5HtmlAttributes* inputAttributes = new nsHtml5HtmlAttributes(0);
inputAttributes->addAttribute(nsHtml5AttributeName::ATTR_NAME, nsHtml5Portability::newStringFromLiteral("isindex"));
for (int32_t i = 0; i < attributes->getLength(); i++) {
nsHtml5AttributeName* attributeQName = attributes->getAttributeNameNoBoundsCheck(i);
if (nsHtml5AttributeName::ATTR_NAME == attributeQName || nsHtml5AttributeName::ATTR_PROMPT == attributeQName) {
attributes->releaseValue(i);
} else if (nsHtml5AttributeName::ATTR_ACTION != attributeQName) {
inputAttributes->addAttribute(attributeQName, attributes->getValueNoBoundsCheck(i));
}
}
attributes->clearWithoutReleasingContents();
appendVoidElementToCurrentMayFoster(nsHtml5Atoms::input, inputAttributes, formPointer);
pop();
appendVoidElementToCurrentMayFoster(nsHtml5ElementName::ELT_HR, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
pop();
if (!isTemplateContents()) {
formPointer = nullptr;
}
selfClosing = false;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_TEXTAREA: {
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes, formPointer);
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RCDATA, elementName);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
needToDropLF = true;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_XMP: {
implicitlyCloseP();
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RAWTEXT, elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_NOSCRIPT: {
if (!scriptingEnabled) {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
} else {
}
}
case NS_HTML5TREE_BUILDER_NOFRAMES:
case NS_HTML5TREE_BUILDER_IFRAME:
case NS_HTML5TREE_BUILDER_NOEMBED: {
startTagGenericRawText(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_SELECT: {
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes, formPointer);
switch(mode) {
case NS_HTML5TREE_BUILDER_IN_TABLE:
case NS_HTML5TREE_BUILDER_IN_CAPTION:
case NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP:
case NS_HTML5TREE_BUILDER_IN_TABLE_BODY:
case NS_HTML5TREE_BUILDER_IN_ROW:
case NS_HTML5TREE_BUILDER_IN_CELL: {
mode = NS_HTML5TREE_BUILDER_IN_SELECT_IN_TABLE;
break;
}
default: {
mode = NS_HTML5TREE_BUILDER_IN_SELECT;
break;
}
}
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_OPTGROUP:
case NS_HTML5TREE_BUILDER_OPTION: {
if (isCurrent(nsHtml5Atoms::option)) {
pop();
}
reconstructTheActiveFormattingElements();
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_RB_OR_RTC: {
eltPos = findLastInScope(nsHtml5Atoms::ruby);
if (eltPos != NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
generateImpliedEndTags();
}
if (eltPos != currentPtr) {
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errStartTagSeenWithoutRuby(name);
} else {
errUnclosedChildrenInRuby();
}
}
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_RT_OR_RP: {
eltPos = findLastInScope(nsHtml5Atoms::ruby);
if (eltPos != NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
generateImpliedEndTagsExceptFor(nsHtml5Atoms::rtc);
}
if (eltPos != currentPtr) {
if (!isCurrent(nsHtml5Atoms::rtc)) {
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errStartTagSeenWithoutRuby(name);
} else {
errUnclosedChildrenInRuby();
}
}
}
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_MATH: {
reconstructTheActiveFormattingElements();
attributes->adjustForMath();
if (selfClosing) {
appendVoidElementToCurrentMayFosterMathML(elementName, attributes);
selfClosing = false;
} else {
appendToCurrentNodeAndPushElementMayFosterMathML(elementName, attributes);
}
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_SVG: {
reconstructTheActiveFormattingElements();
attributes->adjustForSvg();
if (selfClosing) {
appendVoidElementToCurrentMayFosterSVG(elementName, attributes);
selfClosing = false;
} else {
appendToCurrentNodeAndPushElementMayFosterSVG(elementName, attributes);
}
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_CAPTION:
case NS_HTML5TREE_BUILDER_COL:
case NS_HTML5TREE_BUILDER_COLGROUP:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT:
case NS_HTML5TREE_BUILDER_TR:
case NS_HTML5TREE_BUILDER_TD_OR_TH:
case NS_HTML5TREE_BUILDER_FRAME:
case NS_HTML5TREE_BUILDER_FRAMESET:
case NS_HTML5TREE_BUILDER_HEAD: {
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_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: ;
}
case NS_HTML5TREE_BUILDER_IN_HEAD: {
for (; ; ) {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_BASE:
case NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND: {
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_META: {
NS_HTML5_BREAK(inheadloop);
}
case NS_HTML5TREE_BUILDER_TITLE: {
startTagTitleInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_NOSCRIPT: {
if (scriptingEnabled) {
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RAWTEXT, elementName);
} else {
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
mode = NS_HTML5TREE_BUILDER_IN_HEAD_NOSCRIPT;
}
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_SCRIPT: {
startTagScriptInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_STYLE:
case NS_HTML5TREE_BUILDER_NOFRAMES: {
startTagGenericRawText(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_HEAD: {
errFooSeenWhenFooOpen(name);
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_TEMPLATE: {
startTagTemplateInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
pop();
mode = NS_HTML5TREE_BUILDER_AFTER_HEAD;
NS_HTML5_CONTINUE(starttagloop);
}
}
}
inheadloop_end: ;
}
case NS_HTML5TREE_BUILDER_IN_HEAD_NOSCRIPT: {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND: {
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_META: {
checkMetaCharset(attributes);
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_STYLE:
case NS_HTML5TREE_BUILDER_NOFRAMES: {
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RAWTEXT, elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_HEAD: {
errFooSeenWhenFooOpen(name);
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_NOSCRIPT: {
errFooSeenWhenFooOpen(name);
NS_HTML5_BREAK(starttagloop);
}
default: {
errBadStartTagInHead(name);
pop();
mode = NS_HTML5TREE_BUILDER_IN_HEAD;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP: {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_COL: {
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_TEMPLATE: {
startTagTemplateInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
if (!currentPtr || stack[currentPtr]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE) {
MOZ_ASSERT(fragment || isTemplateContents());
errGarbageInColgroup();
NS_HTML5_BREAK(starttagloop);
}
pop();
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_IN_SELECT_IN_TABLE: {
switch(group) {
case NS_HTML5TREE_BUILDER_CAPTION:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT:
case NS_HTML5TREE_BUILDER_TR:
case NS_HTML5TREE_BUILDER_TD_OR_TH:
case NS_HTML5TREE_BUILDER_TABLE: {
errStartTagWithSelectOpen(name);
eltPos = findLastInTableScope(nsHtml5Atoms::select);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment);
NS_HTML5_BREAK(starttagloop);
}
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
continue;
}
default:
; // fall through
}
}
case NS_HTML5TREE_BUILDER_IN_SELECT: {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
errStrayStartTag(name);
if (!fragment) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_OPTION: {
if (isCurrent(nsHtml5Atoms::option)) {
pop();
}
appendToCurrentNodeAndPushElement(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_OPTGROUP: {
if (isCurrent(nsHtml5Atoms::option)) {
pop();
}
if (isCurrent(nsHtml5Atoms::optgroup)) {
pop();
}
appendToCurrentNodeAndPushElement(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_SELECT: {
errStartSelectWhereEndSelectExpected();
eltPos = findLastInTableScope(name);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment);
errNoSelectInTableScope();
NS_HTML5_BREAK(starttagloop);
} else {
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
NS_HTML5_BREAK(starttagloop);
}
}
case NS_HTML5TREE_BUILDER_INPUT:
case NS_HTML5TREE_BUILDER_TEXTAREA:
case NS_HTML5TREE_BUILDER_KEYGEN: {
errStartTagWithSelectOpen(name);
eltPos = findLastInTableScope(nsHtml5Atoms::select);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment);
NS_HTML5_BREAK(starttagloop);
}
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
continue;
}
case NS_HTML5TREE_BUILDER_SCRIPT: {
startTagScriptInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_TEMPLATE: {
startTagTemplateInHead(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
}
}
case NS_HTML5TREE_BUILDER_AFTER_BODY: {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
default: {
errStrayStartTag(name);
mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_IN_FRAMESET: {
switch(group) {
case NS_HTML5TREE_BUILDER_FRAMESET: {
appendToCurrentNodeAndPushElement(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_FRAME: {
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default:
; // fall through
}
}
case NS_HTML5TREE_BUILDER_AFTER_FRAMESET: {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_NOFRAMES: {
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RAWTEXT, elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
}
}
case NS_HTML5TREE_BUILDER_INITIAL: {
errStartTagWithoutDoctype();
documentModeInternal(QUIRKS_MODE, nullptr, nullptr, false);
mode = NS_HTML5TREE_BUILDER_BEFORE_HTML;
continue;
}
case NS_HTML5TREE_BUILDER_BEFORE_HTML: {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
if (attributes == nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
appendHtmlElementToDocumentAndPush();
} else {
appendHtmlElementToDocumentAndPush(attributes);
}
mode = NS_HTML5TREE_BUILDER_BEFORE_HEAD;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
appendHtmlElementToDocumentAndPush();
mode = NS_HTML5TREE_BUILDER_BEFORE_HEAD;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_BEFORE_HEAD: {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_HEAD: {
appendToCurrentNodeAndPushHeadElement(attributes);
mode = NS_HTML5TREE_BUILDER_IN_HEAD;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
mode = NS_HTML5TREE_BUILDER_IN_HEAD;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_AFTER_HEAD: {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_BODY: {
if (!attributes->getLength()) {
appendToCurrentNodeAndPushBodyElement();
} else {
appendToCurrentNodeAndPushBodyElement(attributes);
}
framesetOk = false;
mode = NS_HTML5TREE_BUILDER_IN_BODY;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_FRAMESET: {
appendToCurrentNodeAndPushElement(elementName, attributes);
mode = NS_HTML5TREE_BUILDER_IN_FRAMESET;
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_TEMPLATE: {
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
nsHtml5StackNode* headOnStack = stack[currentPtr];
startTagTemplateInHead(elementName, attributes);
removeFromStack(headOnStack);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_BASE:
case NS_HTML5TREE_BUILDER_LINK_OR_BASEFONT_OR_BGSOUND: {
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
pop();
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_META: {
errFooBetweenHeadAndBody(name);
checkMetaCharset(attributes);
pushHeadPointerOntoStack();
appendVoidElementToCurrentMayFoster(elementName, attributes);
selfClosing = false;
pop();
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_SCRIPT: {
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_SCRIPT_DATA, elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_STYLE:
case NS_HTML5TREE_BUILDER_NOFRAMES: {
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RAWTEXT, elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_TITLE: {
errFooBetweenHeadAndBody(name);
pushHeadPointerOntoStack();
appendToCurrentNodeAndPushElement(elementName, attributes);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RCDATA, elementName);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_HEAD: {
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
default: {
appendToCurrentNodeAndPushBodyElement();
mode = NS_HTML5TREE_BUILDER_FRAMESET_OK;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_AFTER_AFTER_BODY: {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
default: {
errStrayStartTag(name);
mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_AFTER_AFTER_FRAMESET: {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
errStrayStartTag(name);
if (!fragment && !isTemplateContents()) {
addAttributesToHtml(attributes);
attributes = nullptr;
}
NS_HTML5_BREAK(starttagloop);
}
case NS_HTML5TREE_BUILDER_NOFRAMES: {
startTagGenericRawText(elementName, attributes);
attributes = nullptr;
NS_HTML5_BREAK(starttagloop);
}
default: {
errStrayStartTag(name);
NS_HTML5_BREAK(starttagloop);
}
}
}
case NS_HTML5TREE_BUILDER_TEXT: {
MOZ_ASSERT(false);
NS_HTML5_BREAK(starttagloop);
}
}
}
starttagloop_end: ;
if (selfClosing) {
errSelfClosing();
}
if (!mBuilder && attributes != nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES) {
delete attributes;
}
}
void
nsHtml5TreeBuilder::startTagTitleInHead(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RCDATA, elementName);
}
void
nsHtml5TreeBuilder::startTagGenericRawText(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_RAWTEXT, elementName);
}
void
nsHtml5TreeBuilder::startTagScriptInHead(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
appendToCurrentNodeAndPushElementMayFoster(elementName, attributes);
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_TEXT;
tokenizer->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_SCRIPT_DATA, elementName);
}
void
nsHtml5TreeBuilder::startTagTemplateInHead(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
appendToCurrentNodeAndPushElement(elementName, attributes);
insertMarker();
framesetOk = false;
originalMode = mode;
mode = NS_HTML5TREE_BUILDER_IN_TEMPLATE;
pushTemplateMode(NS_HTML5TREE_BUILDER_IN_TEMPLATE);
}
bool
nsHtml5TreeBuilder::isTemplateContents()
{
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK != findLast(nsHtml5Atoms::template_);
}
bool
nsHtml5TreeBuilder::isTemplateModeStackEmpty()
{
return templateModePtr == -1;
}
bool
nsHtml5TreeBuilder::isSpecialParentInForeign(nsHtml5StackNode* stackNode)
{
int32_t ns = stackNode->ns;
return (kNameSpaceID_XHTML == ns) || (stackNode->isHtmlIntegrationPoint()) || ((kNameSpaceID_MathML == ns) && (stackNode->getGroup() == NS_HTML5TREE_BUILDER_MI_MO_MN_MS_MTEXT));
}
nsString*
nsHtml5TreeBuilder::extractCharsetFromContent(nsString* attributeValue, nsHtml5TreeBuilder* tb)
{
int32_t charsetState = NS_HTML5TREE_BUILDER_CHARSET_INITIAL;
int32_t start = -1;
int32_t end = -1;
autoJArray<char16_t,int32_t> buffer = nsHtml5Portability::newCharArrayFromString(attributeValue);
for (int32_t i = 0; i < buffer.length; i++) {
char16_t c = buffer[i];
switch(charsetState) {
case NS_HTML5TREE_BUILDER_CHARSET_INITIAL: {
switch(c) {
case 'c':
case 'C': {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_C;
continue;
}
default: {
continue;
}
}
}
case NS_HTML5TREE_BUILDER_CHARSET_C: {
switch(c) {
case 'h':
case 'H': {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_H;
continue;
}
default: {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_INITIAL;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_CHARSET_H: {
switch(c) {
case 'a':
case 'A': {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_A;
continue;
}
default: {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_INITIAL;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_CHARSET_A: {
switch(c) {
case 'r':
case 'R': {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_R;
continue;
}
default: {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_INITIAL;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_CHARSET_R: {
switch(c) {
case 's':
case 'S': {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_S;
continue;
}
default: {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_INITIAL;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_CHARSET_S: {
switch(c) {
case 'e':
case 'E': {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_E;
continue;
}
default: {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_INITIAL;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_CHARSET_E: {
switch(c) {
case 't':
case 'T': {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_T;
continue;
}
default: {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_INITIAL;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_CHARSET_T: {
switch(c) {
case '\t':
case '\n':
case '\f':
case '\r':
case ' ': {
continue;
}
case '=': {
charsetState = NS_HTML5TREE_BUILDER_CHARSET_EQUALS;
continue;
}
default: {
return nullptr;
}
}
}
case NS_HTML5TREE_BUILDER_CHARSET_EQUALS: {
switch(c) {
case '\t':
case '\n':
case '\f':
case '\r':
case ' ': {
continue;
}
case '\'': {
start = i + 1;
charsetState = NS_HTML5TREE_BUILDER_CHARSET_SINGLE_QUOTED;
continue;
}
case '\"': {
start = i + 1;
charsetState = NS_HTML5TREE_BUILDER_CHARSET_DOUBLE_QUOTED;
continue;
}
default: {
start = i;
charsetState = NS_HTML5TREE_BUILDER_CHARSET_UNQUOTED;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_CHARSET_SINGLE_QUOTED: {
switch(c) {
case '\'': {
end = i;
NS_HTML5_BREAK(charsetloop);
}
default: {
continue;
}
}
}
case NS_HTML5TREE_BUILDER_CHARSET_DOUBLE_QUOTED: {
switch(c) {
case '\"': {
end = i;
NS_HTML5_BREAK(charsetloop);
}
default: {
continue;
}
}
}
case NS_HTML5TREE_BUILDER_CHARSET_UNQUOTED: {
switch(c) {
case '\t':
case '\n':
case '\f':
case '\r':
case ' ':
case ';': {
end = i;
NS_HTML5_BREAK(charsetloop);
}
default: {
continue;
}
}
}
}
}
charsetloop_end: ;
nsString* charset = nullptr;
if (start != -1) {
if (end == -1) {
end = buffer.length;
}
charset = nsHtml5Portability::newStringFromBuffer(buffer, start, end - start, tb);
}
return charset;
}
void
nsHtml5TreeBuilder::checkMetaCharset(nsHtml5HtmlAttributes* attributes)
{
nsString* charset = attributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
if (charset) {
if (tokenizer->internalEncodingDeclaration(charset)) {
requestSuspension();
return;
}
return;
}
if (!nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("content-type", attributes->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV))) {
return;
}
nsString* content = attributes->getValue(nsHtml5AttributeName::ATTR_CONTENT);
if (content) {
nsString* extract = nsHtml5TreeBuilder::extractCharsetFromContent(content, this);
if (extract) {
if (tokenizer->internalEncodingDeclaration(extract)) {
requestSuspension();
}
}
nsHtml5Portability::releaseString(extract);
}
}
void
nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName)
{
flushCharacters();
needToDropLF = false;
int32_t eltPos;
int32_t group = elementName->getGroup();
nsIAtom* name = elementName->name;
for (; ; ) {
if (isInForeign()) {
if (stack[currentPtr]->name != name) {
if (!currentPtr) {
errStrayEndTag(name);
} else {
errEndTagDidNotMatchCurrentOpenElement(name, stack[currentPtr]->popName);
}
}
eltPos = currentPtr;
for (; ; ) {
if (!eltPos) {
MOZ_ASSERT(fragment, "We can get this close to the root of the stack in foreign content only in the fragment case.");
NS_HTML5_BREAK(endtagloop);
}
if (stack[eltPos]->name == name) {
while (currentPtr >= eltPos) {
pop();
}
NS_HTML5_BREAK(endtagloop);
}
if (stack[--eltPos]->ns == kNameSpaceID_XHTML) {
break;
}
}
}
switch(mode) {
case NS_HTML5TREE_BUILDER_IN_TEMPLATE: {
switch(group) {
case NS_HTML5TREE_BUILDER_TEMPLATE: {
break;
}
default: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
}
}
case NS_HTML5TREE_BUILDER_IN_ROW: {
switch(group) {
case NS_HTML5TREE_BUILDER_TR: {
eltPos = findLastOrRoot(NS_HTML5TREE_BUILDER_TR);
if (!eltPos) {
MOZ_ASSERT(fragment || isTemplateContents());
errNoTableRowToClose();
NS_HTML5_BREAK(endtagloop);
}
clearStackBackTo(eltPos);
pop();
mode = NS_HTML5TREE_BUILDER_IN_TABLE_BODY;
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_TABLE: {
eltPos = findLastOrRoot(NS_HTML5TREE_BUILDER_TR);
if (!eltPos) {
MOZ_ASSERT(fragment || isTemplateContents());
errNoTableRowToClose();
NS_HTML5_BREAK(endtagloop);
}
clearStackBackTo(eltPos);
pop();
mode = NS_HTML5TREE_BUILDER_IN_TABLE_BODY;
continue;
}
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT: {
if (findLastInTableScope(name) == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
eltPos = findLastOrRoot(NS_HTML5TREE_BUILDER_TR);
if (!eltPos) {
MOZ_ASSERT(fragment || isTemplateContents());
errNoTableRowToClose();
NS_HTML5_BREAK(endtagloop);
}
clearStackBackTo(eltPos);
pop();
mode = NS_HTML5TREE_BUILDER_IN_TABLE_BODY;
continue;
}
case NS_HTML5TREE_BUILDER_BODY:
case NS_HTML5TREE_BUILDER_CAPTION:
case NS_HTML5TREE_BUILDER_COL:
case NS_HTML5TREE_BUILDER_COLGROUP:
case NS_HTML5TREE_BUILDER_HTML:
case NS_HTML5TREE_BUILDER_TD_OR_TH: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
default:
; // fall through
}
}
case NS_HTML5TREE_BUILDER_IN_TABLE_BODY: {
switch(group) {
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT: {
eltPos = findLastOrRoot(name);
if (!eltPos) {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
clearStackBackTo(eltPos);
pop();
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_TABLE: {
eltPos = findLastInTableScopeOrRootTemplateTbodyTheadTfoot();
if (!eltPos || stack[eltPos]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE) {
MOZ_ASSERT(fragment || isTemplateContents());
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
clearStackBackTo(eltPos);
pop();
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
continue;
}
case NS_HTML5TREE_BUILDER_BODY:
case NS_HTML5TREE_BUILDER_CAPTION:
case NS_HTML5TREE_BUILDER_COL:
case NS_HTML5TREE_BUILDER_COLGROUP:
case NS_HTML5TREE_BUILDER_HTML:
case NS_HTML5TREE_BUILDER_TD_OR_TH:
case NS_HTML5TREE_BUILDER_TR: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
default:
; // fall through
}
}
case NS_HTML5TREE_BUILDER_IN_TABLE: {
switch(group) {
case NS_HTML5TREE_BUILDER_TABLE: {
eltPos = findLast(nsHtml5Atoms::table);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment || isTemplateContents());
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_BODY:
case NS_HTML5TREE_BUILDER_CAPTION:
case NS_HTML5TREE_BUILDER_COL:
case NS_HTML5TREE_BUILDER_COLGROUP:
case NS_HTML5TREE_BUILDER_HTML:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT:
case NS_HTML5TREE_BUILDER_TD_OR_TH:
case NS_HTML5TREE_BUILDER_TR: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_TEMPLATE: {
break;
}
default: {
errStrayEndTag(name);
}
}
}
case NS_HTML5TREE_BUILDER_IN_CAPTION: {
switch(group) {
case NS_HTML5TREE_BUILDER_CAPTION: {
eltPos = findLastInTableScope(nsHtml5Atoms::caption);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
NS_HTML5_BREAK(endtagloop);
}
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
errUnclosedElements(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
clearTheListOfActiveFormattingElementsUpToTheLastMarker();
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_TABLE: {
errTableClosedWhileCaptionOpen();
eltPos = findLastInTableScope(nsHtml5Atoms::caption);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
NS_HTML5_BREAK(endtagloop);
}
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && currentPtr != eltPos) {
errUnclosedElements(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
clearTheListOfActiveFormattingElementsUpToTheLastMarker();
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
continue;
}
case NS_HTML5TREE_BUILDER_BODY:
case NS_HTML5TREE_BUILDER_COL:
case NS_HTML5TREE_BUILDER_COLGROUP:
case NS_HTML5TREE_BUILDER_HTML:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT:
case NS_HTML5TREE_BUILDER_TD_OR_TH:
case NS_HTML5TREE_BUILDER_TR: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
default:
; // fall through
}
}
case NS_HTML5TREE_BUILDER_IN_CELL: {
switch(group) {
case NS_HTML5TREE_BUILDER_TD_OR_TH: {
eltPos = findLastInTableScope(name);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
errUnclosedElements(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
clearTheListOfActiveFormattingElementsUpToTheLastMarker();
mode = NS_HTML5TREE_BUILDER_IN_ROW;
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_TABLE:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT:
case NS_HTML5TREE_BUILDER_TR: {
if (findLastInTableScope(name) == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
MOZ_ASSERT(name == nsHtml5Atoms::tbody || name == nsHtml5Atoms::tfoot || name == nsHtml5Atoms::thead || fragment || isTemplateContents());
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
closeTheCell(findLastInTableScopeTdTh());
continue;
}
case NS_HTML5TREE_BUILDER_BODY:
case NS_HTML5TREE_BUILDER_CAPTION:
case NS_HTML5TREE_BUILDER_COL:
case NS_HTML5TREE_BUILDER_COLGROUP:
case NS_HTML5TREE_BUILDER_HTML: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
default:
; // fall through
}
}
case NS_HTML5TREE_BUILDER_FRAMESET_OK:
case NS_HTML5TREE_BUILDER_IN_BODY: {
switch(group) {
case NS_HTML5TREE_BUILDER_BODY: {
if (!isSecondOnStackBody()) {
MOZ_ASSERT(fragment || isTemplateContents());
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
MOZ_ASSERT(currentPtr >= 1);
if (MOZ_UNLIKELY(mViewSource)) {
for (int32_t i = 2; i <= currentPtr; i++) {
switch(stack[i]->getGroup()) {
case NS_HTML5TREE_BUILDER_DD_OR_DT:
case NS_HTML5TREE_BUILDER_LI:
case NS_HTML5TREE_BUILDER_OPTGROUP:
case NS_HTML5TREE_BUILDER_OPTION:
case NS_HTML5TREE_BUILDER_P:
case NS_HTML5TREE_BUILDER_RB_OR_RTC:
case NS_HTML5TREE_BUILDER_RT_OR_RP:
case NS_HTML5TREE_BUILDER_TD_OR_TH:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT: {
break;
}
default: {
errEndWithUnclosedElements(name);
NS_HTML5_BREAK(uncloseloop1);
}
}
}
uncloseloop1_end: ;
}
mode = NS_HTML5TREE_BUILDER_AFTER_BODY;
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_HTML: {
if (!isSecondOnStackBody()) {
MOZ_ASSERT(fragment || isTemplateContents());
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
if (MOZ_UNLIKELY(mViewSource)) {
for (int32_t i = 0; i <= currentPtr; i++) {
switch(stack[i]->getGroup()) {
case NS_HTML5TREE_BUILDER_DD_OR_DT:
case NS_HTML5TREE_BUILDER_LI:
case NS_HTML5TREE_BUILDER_P:
case NS_HTML5TREE_BUILDER_RB_OR_RTC:
case NS_HTML5TREE_BUILDER_RT_OR_RP:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT:
case NS_HTML5TREE_BUILDER_TD_OR_TH:
case NS_HTML5TREE_BUILDER_BODY:
case NS_HTML5TREE_BUILDER_HTML: {
break;
}
default: {
errEndWithUnclosedElements(name);
NS_HTML5_BREAK(uncloseloop2);
}
}
}
uncloseloop2_end: ;
}
mode = NS_HTML5TREE_BUILDER_AFTER_BODY;
continue;
}
case NS_HTML5TREE_BUILDER_DIV_OR_BLOCKQUOTE_OR_CENTER_OR_MENU:
case NS_HTML5TREE_BUILDER_UL_OR_OL_OR_DL:
case NS_HTML5TREE_BUILDER_PRE_OR_LISTING:
case NS_HTML5TREE_BUILDER_FIELDSET:
case NS_HTML5TREE_BUILDER_BUTTON:
case NS_HTML5TREE_BUILDER_ADDRESS_OR_ARTICLE_OR_ASIDE_OR_DETAILS_OR_DIR_OR_FIGCAPTION_OR_FIGURE_OR_FOOTER_OR_HEADER_OR_HGROUP_OR_MAIN_OR_NAV_OR_SECTION_OR_SUMMARY: {
eltPos = findLastInScope(name);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errStrayEndTag(name);
} else {
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
errUnclosedElements(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
}
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_FORM: {
if (!isTemplateContents()) {
if (!formPointer) {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
formPointer = nullptr;
eltPos = findLastInScope(name);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
errUnclosedElements(eltPos, name);
}
removeFromStack(eltPos);
NS_HTML5_BREAK(endtagloop);
} else {
eltPos = findLastInScope(name);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
errUnclosedElements(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
NS_HTML5_BREAK(endtagloop);
}
}
case NS_HTML5TREE_BUILDER_P: {
eltPos = findLastInButtonScope(nsHtml5Atoms::p);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errNoElementToCloseButEndTagSeen(nsHtml5Atoms::p);
if (isInForeign()) {
errHtmlStartTagInForeignContext(name);
while (currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML) {
pop();
}
}
appendVoidElementToCurrentMayFoster(elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
NS_HTML5_BREAK(endtagloop);
}
generateImpliedEndTagsExceptFor(nsHtml5Atoms::p);
MOZ_ASSERT(eltPos != NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK);
if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
errUnclosedElements(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_LI: {
eltPos = findLastInListScope(name);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errNoElementToCloseButEndTagSeen(name);
} else {
generateImpliedEndTagsExceptFor(name);
if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
errUnclosedElements(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
}
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_DD_OR_DT: {
eltPos = findLastInScope(name);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errNoElementToCloseButEndTagSeen(name);
} else {
generateImpliedEndTagsExceptFor(name);
if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
errUnclosedElements(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
}
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6: {
eltPos = findLastInScopeHn();
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errStrayEndTag(name);
} else {
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
errUnclosedElements(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
}
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_OBJECT:
case NS_HTML5TREE_BUILDER_MARQUEE_OR_APPLET: {
eltPos = findLastInScope(name);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errStrayEndTag(name);
} else {
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
errUnclosedElements(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
clearTheListOfActiveFormattingElementsUpToTheLastMarker();
}
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_BR: {
errEndTagBr();
if (isInForeign()) {
errHtmlStartTagInForeignContext(name);
while (currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML) {
pop();
}
}
reconstructTheActiveFormattingElements();
appendVoidElementToCurrentMayFoster(elementName, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_TEMPLATE: {
break;
}
case NS_HTML5TREE_BUILDER_AREA_OR_WBR:
#ifdef ENABLE_VOID_MENUITEM
case NS_HTML5TREE_BUILDER_MENUITEM:
#endif
case NS_HTML5TREE_BUILDER_PARAM_OR_SOURCE_OR_TRACK:
case NS_HTML5TREE_BUILDER_EMBED:
case NS_HTML5TREE_BUILDER_IMG:
case NS_HTML5TREE_BUILDER_IMAGE:
case NS_HTML5TREE_BUILDER_INPUT:
case NS_HTML5TREE_BUILDER_KEYGEN:
case NS_HTML5TREE_BUILDER_HR:
case NS_HTML5TREE_BUILDER_ISINDEX:
case NS_HTML5TREE_BUILDER_IFRAME:
case NS_HTML5TREE_BUILDER_NOEMBED:
case NS_HTML5TREE_BUILDER_NOFRAMES:
case NS_HTML5TREE_BUILDER_SELECT:
case NS_HTML5TREE_BUILDER_TABLE:
case NS_HTML5TREE_BUILDER_TEXTAREA: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_NOSCRIPT: {
if (scriptingEnabled) {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
} else {
}
}
case NS_HTML5TREE_BUILDER_A:
case NS_HTML5TREE_BUILDER_B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
case NS_HTML5TREE_BUILDER_FONT:
case NS_HTML5TREE_BUILDER_NOBR: {
if (adoptionAgencyEndTag(name)) {
NS_HTML5_BREAK(endtagloop);
}
}
default: {
if (isCurrent(name)) {
pop();
NS_HTML5_BREAK(endtagloop);
}
eltPos = currentPtr;
for (; ; ) {
nsHtml5StackNode* node = stack[eltPos];
if (node->ns == kNameSpaceID_XHTML && node->name == name) {
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(name)) {
errUnclosedElements(eltPos, name);
}
while (currentPtr >= eltPos) {
pop();
}
NS_HTML5_BREAK(endtagloop);
} else if (!eltPos || node->isSpecial()) {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
eltPos--;
}
}
}
}
case NS_HTML5TREE_BUILDER_IN_HEAD: {
switch(group) {
case NS_HTML5TREE_BUILDER_HEAD: {
pop();
mode = NS_HTML5TREE_BUILDER_AFTER_HEAD;
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_BR:
case NS_HTML5TREE_BUILDER_HTML:
case NS_HTML5TREE_BUILDER_BODY: {
pop();
mode = NS_HTML5TREE_BUILDER_AFTER_HEAD;
continue;
}
case NS_HTML5TREE_BUILDER_TEMPLATE: {
endTagTemplateInHead();
NS_HTML5_BREAK(endtagloop);
}
default: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
}
}
case NS_HTML5TREE_BUILDER_IN_HEAD_NOSCRIPT: {
switch(group) {
case NS_HTML5TREE_BUILDER_NOSCRIPT: {
pop();
mode = NS_HTML5TREE_BUILDER_IN_HEAD;
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_BR: {
errStrayEndTag(name);
pop();
mode = NS_HTML5TREE_BUILDER_IN_HEAD;
continue;
}
default: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
}
}
case NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP: {
switch(group) {
case NS_HTML5TREE_BUILDER_COLGROUP: {
if (!currentPtr || stack[currentPtr]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE) {
MOZ_ASSERT(fragment || isTemplateContents());
errGarbageInColgroup();
NS_HTML5_BREAK(endtagloop);
}
pop();
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_COL: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_TEMPLATE: {
endTagTemplateInHead();
NS_HTML5_BREAK(endtagloop);
}
default: {
if (!currentPtr || stack[currentPtr]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE) {
MOZ_ASSERT(fragment || isTemplateContents());
errGarbageInColgroup();
NS_HTML5_BREAK(endtagloop);
}
pop();
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_IN_SELECT_IN_TABLE: {
switch(group) {
case NS_HTML5TREE_BUILDER_CAPTION:
case NS_HTML5TREE_BUILDER_TABLE:
case NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT:
case NS_HTML5TREE_BUILDER_TR:
case NS_HTML5TREE_BUILDER_TD_OR_TH: {
errEndTagSeenWithSelectOpen(name);
if (findLastInTableScope(name) != NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
eltPos = findLastInTableScope(nsHtml5Atoms::select);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment);
NS_HTML5_BREAK(endtagloop);
}
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
continue;
} else {
NS_HTML5_BREAK(endtagloop);
}
}
default:
; // fall through
}
}
case NS_HTML5TREE_BUILDER_IN_SELECT: {
switch(group) {
case NS_HTML5TREE_BUILDER_OPTION: {
if (isCurrent(nsHtml5Atoms::option)) {
pop();
NS_HTML5_BREAK(endtagloop);
} else {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
}
case NS_HTML5TREE_BUILDER_OPTGROUP: {
if (isCurrent(nsHtml5Atoms::option) && nsHtml5Atoms::optgroup == stack[currentPtr - 1]->name) {
pop();
}
if (isCurrent(nsHtml5Atoms::optgroup)) {
pop();
} else {
errStrayEndTag(name);
}
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_SELECT: {
eltPos = findLastInTableScope(nsHtml5Atoms::select);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
MOZ_ASSERT(fragment);
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
while (currentPtr >= eltPos) {
pop();
}
resetTheInsertionMode();
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_TEMPLATE: {
endTagTemplateInHead();
NS_HTML5_BREAK(endtagloop);
}
default: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
}
}
case NS_HTML5TREE_BUILDER_AFTER_BODY: {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
if (fragment) {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
} else {
mode = NS_HTML5TREE_BUILDER_AFTER_AFTER_BODY;
NS_HTML5_BREAK(endtagloop);
}
}
default: {
errEndTagAfterBody();
mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
continue;
}
}
}
case NS_HTML5TREE_BUILDER_IN_FRAMESET: {
switch(group) {
case NS_HTML5TREE_BUILDER_FRAMESET: {
if (!currentPtr) {
MOZ_ASSERT(fragment);
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
pop();
if ((!fragment) && !isCurrent(nsHtml5Atoms::frameset)) {
mode = NS_HTML5TREE_BUILDER_AFTER_FRAMESET;
}
NS_HTML5_BREAK(endtagloop);
}
default: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
}
}
case NS_HTML5TREE_BUILDER_AFTER_FRAMESET: {
switch(group) {
case NS_HTML5TREE_BUILDER_HTML: {
mode = NS_HTML5TREE_BUILDER_AFTER_AFTER_FRAMESET;
NS_HTML5_BREAK(endtagloop);
}
default: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
}
}
case NS_HTML5TREE_BUILDER_INITIAL: {
errEndTagSeenWithoutDoctype();
documentModeInternal(QUIRKS_MODE, nullptr, nullptr, false);
mode = NS_HTML5TREE_BUILDER_BEFORE_HTML;
continue;
}
case NS_HTML5TREE_BUILDER_BEFORE_HTML: {
switch(group) {
case NS_HTML5TREE_BUILDER_HEAD:
case NS_HTML5TREE_BUILDER_BR:
case NS_HTML5TREE_BUILDER_HTML:
case NS_HTML5TREE_BUILDER_BODY: {
appendHtmlElementToDocumentAndPush();
mode = NS_HTML5TREE_BUILDER_BEFORE_HEAD;
continue;
}
default: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
}
}
case NS_HTML5TREE_BUILDER_BEFORE_HEAD: {
switch(group) {
case NS_HTML5TREE_BUILDER_HEAD:
case NS_HTML5TREE_BUILDER_BR:
case NS_HTML5TREE_BUILDER_HTML:
case NS_HTML5TREE_BUILDER_BODY: {
appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES);
mode = NS_HTML5TREE_BUILDER_IN_HEAD;
continue;
}
default: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
}
}
case NS_HTML5TREE_BUILDER_AFTER_HEAD: {
switch(group) {
case NS_HTML5TREE_BUILDER_TEMPLATE: {
endTagTemplateInHead();
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_HTML:
case NS_HTML5TREE_BUILDER_BODY:
case NS_HTML5TREE_BUILDER_BR: {
appendToCurrentNodeAndPushBodyElement();
mode = NS_HTML5TREE_BUILDER_FRAMESET_OK;
continue;
}
default: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
}
}
case NS_HTML5TREE_BUILDER_AFTER_AFTER_BODY: {
errStrayEndTag(name);
mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
continue;
}
case NS_HTML5TREE_BUILDER_AFTER_AFTER_FRAMESET: {
errStrayEndTag(name);
NS_HTML5_BREAK(endtagloop);
}
case NS_HTML5TREE_BUILDER_TEXT: {
pop();
if (originalMode == NS_HTML5TREE_BUILDER_AFTER_HEAD) {
silentPop();
}
mode = originalMode;
NS_HTML5_BREAK(endtagloop);
}
}
}
endtagloop_end: ;
}
void
nsHtml5TreeBuilder::endTagTemplateInHead()
{
int32_t eltPos = findLast(nsHtml5Atoms::template_);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
errStrayEndTag(nsHtml5Atoms::template_);
return;
}
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && !isCurrent(nsHtml5Atoms::template_)) {
errUnclosedElements(eltPos, nsHtml5Atoms::template_);
}
while (currentPtr >= eltPos) {
pop();
}
clearTheListOfActiveFormattingElementsUpToTheLastMarker();
popTemplateMode();
resetTheInsertionMode();
}
int32_t
nsHtml5TreeBuilder::findLastInTableScopeOrRootTemplateTbodyTheadTfoot()
{
for (int32_t i = currentPtr; i > 0; i--) {
if (stack[i]->getGroup() == NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT || stack[i]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE) {
return i;
}
}
return 0;
}
int32_t
nsHtml5TreeBuilder::findLast(nsIAtom* name)
{
for (int32_t i = currentPtr; i > 0; i--) {
if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
return i;
}
}
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
int32_t
nsHtml5TreeBuilder::findLastInTableScope(nsIAtom* name)
{
for (int32_t i = currentPtr; i > 0; i--) {
if (stack[i]->ns == kNameSpaceID_XHTML) {
if (stack[i]->name == name) {
return i;
} else if (stack[i]->name == nsHtml5Atoms::table || stack[i]->name == nsHtml5Atoms::template_) {
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
}
}
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
int32_t
nsHtml5TreeBuilder::findLastInButtonScope(nsIAtom* name)
{
for (int32_t i = currentPtr; i > 0; i--) {
if (stack[i]->ns == kNameSpaceID_XHTML) {
if (stack[i]->name == name) {
return i;
} else if (stack[i]->name == nsHtml5Atoms::button) {
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
}
if (stack[i]->isScoping()) {
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
}
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
int32_t
nsHtml5TreeBuilder::findLastInScope(nsIAtom* name)
{
for (int32_t i = currentPtr; i > 0; i--) {
if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
return i;
} else if (stack[i]->isScoping()) {
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
}
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
int32_t
nsHtml5TreeBuilder::findLastInListScope(nsIAtom* name)
{
for (int32_t i = currentPtr; i > 0; i--) {
if (stack[i]->ns == kNameSpaceID_XHTML) {
if (stack[i]->name == name) {
return i;
} else if (stack[i]->name == nsHtml5Atoms::ul || stack[i]->name == nsHtml5Atoms::ol) {
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
}
if (stack[i]->isScoping()) {
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
}
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
int32_t
nsHtml5TreeBuilder::findLastInScopeHn()
{
for (int32_t i = currentPtr; i > 0; i--) {
if (stack[i]->getGroup() == NS_HTML5TREE_BUILDER_H1_OR_H2_OR_H3_OR_H4_OR_H5_OR_H6) {
return i;
} else if (stack[i]->isScoping()) {
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
}
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
void
nsHtml5TreeBuilder::generateImpliedEndTagsExceptFor(nsIAtom* name)
{
for (; ; ) {
nsHtml5StackNode* node = stack[currentPtr];
switch(node->getGroup()) {
case NS_HTML5TREE_BUILDER_P:
case NS_HTML5TREE_BUILDER_LI:
case NS_HTML5TREE_BUILDER_DD_OR_DT:
case NS_HTML5TREE_BUILDER_OPTION:
case NS_HTML5TREE_BUILDER_OPTGROUP:
case NS_HTML5TREE_BUILDER_RB_OR_RTC:
case NS_HTML5TREE_BUILDER_RT_OR_RP: {
if (node->ns == kNameSpaceID_XHTML && node->name == name) {
return;
}
pop();
continue;
}
default: {
return;
}
}
}
}
void
nsHtml5TreeBuilder::generateImpliedEndTags()
{
for (; ; ) {
switch(stack[currentPtr]->getGroup()) {
case NS_HTML5TREE_BUILDER_P:
case NS_HTML5TREE_BUILDER_LI:
case NS_HTML5TREE_BUILDER_DD_OR_DT:
case NS_HTML5TREE_BUILDER_OPTION:
case NS_HTML5TREE_BUILDER_OPTGROUP:
case NS_HTML5TREE_BUILDER_RB_OR_RTC:
case NS_HTML5TREE_BUILDER_RT_OR_RP: {
pop();
continue;
}
default: {
return;
}
}
}
}
bool
nsHtml5TreeBuilder::isSecondOnStackBody()
{
return currentPtr >= 1 && stack[1]->getGroup() == NS_HTML5TREE_BUILDER_BODY;
}
void
nsHtml5TreeBuilder::documentModeInternal(nsHtml5DocumentMode m, nsString* publicIdentifier, nsString* systemIdentifier, bool html4SpecificAdditionalErrorChecks)
{
if (isSrcdocDocument) {
quirks = false;
this->documentMode(STANDARDS_MODE);
return;
}
quirks = (m == QUIRKS_MODE);
this->documentMode(m);
}
bool
nsHtml5TreeBuilder::isAlmostStandards(nsString* publicIdentifier, nsString* systemIdentifier)
{
if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("-//w3c//dtd xhtml 1.0 transitional//en", publicIdentifier)) {
return true;
}
if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("-//w3c//dtd xhtml 1.0 frameset//en", publicIdentifier)) {
return true;
}
if (systemIdentifier) {
if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("-//w3c//dtd html 4.01 transitional//en", publicIdentifier)) {
return true;
}
if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("-//w3c//dtd html 4.01 frameset//en", publicIdentifier)) {
return true;
}
}
return false;
}
bool
nsHtml5TreeBuilder::isQuirky(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier, bool forceQuirks)
{
if (forceQuirks) {
return true;
}
if (name != nsHtml5Atoms::html) {
return true;
}
if (publicIdentifier) {
for (int32_t i = 0; i < nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS.length; i++) {
if (nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS[i], publicIdentifier)) {
return true;
}
}
if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("-//w3o//dtd w3 html strict 3.0//en//", publicIdentifier) || nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("-/w3c/dtd html 4.0 transitional/en", publicIdentifier) || nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("html", publicIdentifier)) {
return true;
}
}
if (!systemIdentifier) {
if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("-//w3c//dtd html 4.01 transitional//en", publicIdentifier)) {
return true;
} else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("-//w3c//dtd html 4.01 frameset//en", publicIdentifier)) {
return true;
}
} else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd", systemIdentifier)) {
return true;
}
return false;
}
void
nsHtml5TreeBuilder::closeTheCell(int32_t eltPos)
{
generateImpliedEndTags();
if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
errUnclosedElementsCell(eltPos);
}
while (currentPtr >= eltPos) {
pop();
}
clearTheListOfActiveFormattingElementsUpToTheLastMarker();
mode = NS_HTML5TREE_BUILDER_IN_ROW;
return;
}
int32_t
nsHtml5TreeBuilder::findLastInTableScopeTdTh()
{
for (int32_t i = currentPtr; i > 0; i--) {
nsIAtom* name = stack[i]->name;
if (stack[i]->ns == kNameSpaceID_XHTML) {
if (nsHtml5Atoms::td == name || nsHtml5Atoms::th == name) {
return i;
} else if (name == nsHtml5Atoms::table || name == nsHtml5Atoms::template_) {
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
}
}
return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
}
void
nsHtml5TreeBuilder::clearStackBackTo(int32_t eltPos)
{
int32_t eltGroup = stack[eltPos]->getGroup();
while (currentPtr > eltPos) {
if (stack[currentPtr]->ns == kNameSpaceID_XHTML && stack[currentPtr]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE && (eltGroup == NS_HTML5TREE_BUILDER_TABLE || eltGroup == NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT || eltGroup == NS_HTML5TREE_BUILDER_TR || !eltPos)) {
return;
}
pop();
}
}
void
nsHtml5TreeBuilder::resetTheInsertionMode()
{
nsHtml5StackNode* node;
nsIAtom* name;
int32_t ns;
for (int32_t i = currentPtr; i >= 0; i--) {
node = stack[i];
name = node->name;
ns = node->ns;
if (!i) {
if (!(contextNamespace == kNameSpaceID_XHTML && (contextName == nsHtml5Atoms::td || contextName == nsHtml5Atoms::th))) {
if (fragment) {
name = contextName;
ns = contextNamespace;
}
} else {
mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
return;
}
}
if (nsHtml5Atoms::select == name) {
int32_t ancestorIndex = i;
while (ancestorIndex > 0) {
nsHtml5StackNode* ancestor = stack[ancestorIndex--];
if (kNameSpaceID_XHTML == ancestor->ns) {
if (nsHtml5Atoms::template_ == ancestor->name) {
break;
}
if (nsHtml5Atoms::table == ancestor->name) {
mode = NS_HTML5TREE_BUILDER_IN_SELECT_IN_TABLE;
return;
}
}
}
mode = NS_HTML5TREE_BUILDER_IN_SELECT;
return;
} else if (nsHtml5Atoms::td == name || nsHtml5Atoms::th == name) {
mode = NS_HTML5TREE_BUILDER_IN_CELL;
return;
} else if (nsHtml5Atoms::tr == name) {
mode = NS_HTML5TREE_BUILDER_IN_ROW;
return;
} else if (nsHtml5Atoms::tbody == name || nsHtml5Atoms::thead == name || nsHtml5Atoms::tfoot == name) {
mode = NS_HTML5TREE_BUILDER_IN_TABLE_BODY;
return;
} else if (nsHtml5Atoms::caption == name) {
mode = NS_HTML5TREE_BUILDER_IN_CAPTION;
return;
} else if (nsHtml5Atoms::colgroup == name) {
mode = NS_HTML5TREE_BUILDER_IN_COLUMN_GROUP;
return;
} else if (nsHtml5Atoms::table == name) {
mode = NS_HTML5TREE_BUILDER_IN_TABLE;
return;
} else if (kNameSpaceID_XHTML != ns) {
mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
return;
} else if (nsHtml5Atoms::template_ == name) {
MOZ_ASSERT(templateModePtr >= 0);
mode = templateModeStack[templateModePtr];
return;
} else if (nsHtml5Atoms::head == name) {
if (name == contextName) {
mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
} else {
mode = NS_HTML5TREE_BUILDER_IN_HEAD;
}
return;
} else if (nsHtml5Atoms::body == name) {
mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
return;
} else if (nsHtml5Atoms::frameset == name) {
mode = NS_HTML5TREE_BUILDER_IN_FRAMESET;
return;
} else if (nsHtml5Atoms::html == name) {
if (!headPointer) {
mode = NS_HTML5TREE_BUILDER_BEFORE_HEAD;
} else {
mode = NS_HTML5TREE_BUILDER_AFTER_HEAD;
}
return;
} else if (!i) {
mode = framesetOk ? NS_HTML5TREE_BUILDER_FRAMESET_OK : NS_HTML5TREE_BUILDER_IN_BODY;
return;
}
}
}
void
nsHtml5TreeBuilder::implicitlyCloseP()
{
int32_t eltPos = findLastInButtonScope(nsHtml5Atoms::p);
if (eltPos == NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK) {
return;
}
generateImpliedEndTagsExceptFor(nsHtml5Atoms::p);
if (!!MOZ_UNLIKELY(mViewSource) && eltPos != currentPtr) {
errUnclosedElementsImplied(eltPos, nsHtml5Atoms::p);
}
while (currentPtr >= eltPos) {
pop();
}
}
bool
nsHtml5TreeBuilder::debugOnlyClearLastStackSlot()
{
stack[currentPtr] = nullptr;
return true;
}
bool
nsHtml5TreeBuilder::debugOnlyClearLastListSlot()
{
listOfActiveFormattingElements[listPtr] = nullptr;
return true;
}
void
nsHtml5TreeBuilder::pushTemplateMode(int32_t mode)
{
templateModePtr++;
if (templateModePtr == templateModeStack.length) {
jArray<int32_t,int32_t> newStack = jArray<int32_t,int32_t>::newJArray(templateModeStack.length + 64);
nsHtml5ArrayCopy::arraycopy(templateModeStack, newStack, templateModeStack.length);
templateModeStack = newStack;
}
templateModeStack[templateModePtr] = mode;
}
void
nsHtml5TreeBuilder::push(nsHtml5StackNode* node)
{
currentPtr++;
if (currentPtr == stack.length) {
jArray<nsHtml5StackNode*,int32_t> newStack = jArray<nsHtml5StackNode*,int32_t>::newJArray(stack.length + 64);
nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length);
stack = newStack;
}
stack[currentPtr] = node;
elementPushed(node->ns, node->popName, node->node);
}
void
nsHtml5TreeBuilder::silentPush(nsHtml5StackNode* node)
{
currentPtr++;
if (currentPtr == stack.length) {
jArray<nsHtml5StackNode*,int32_t> newStack = jArray<nsHtml5StackNode*,int32_t>::newJArray(stack.length + 64);
nsHtml5ArrayCopy::arraycopy(stack, newStack, stack.length);
stack = newStack;
}
stack[currentPtr] = node;
}
void
nsHtml5TreeBuilder::append(nsHtml5StackNode* node)
{
listPtr++;
if (listPtr == listOfActiveFormattingElements.length) {
jArray<nsHtml5StackNode*,int32_t> newList = jArray<nsHtml5StackNode*,int32_t>::newJArray(listOfActiveFormattingElements.length + 64);
nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, newList, listOfActiveFormattingElements.length);
listOfActiveFormattingElements = newList;
}
listOfActiveFormattingElements[listPtr] = node;
}
void
nsHtml5TreeBuilder::clearTheListOfActiveFormattingElementsUpToTheLastMarker()
{
while (listPtr > -1) {
if (!listOfActiveFormattingElements[listPtr]) {
--listPtr;
return;
}
listOfActiveFormattingElements[listPtr]->release();
--listPtr;
}
}
void
nsHtml5TreeBuilder::removeFromStack(int32_t pos)
{
if (currentPtr == pos) {
pop();
} else {
stack[pos]->release();
nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos);
MOZ_ASSERT(debugOnlyClearLastStackSlot());
currentPtr--;
}
}
void
nsHtml5TreeBuilder::removeFromStack(nsHtml5StackNode* node)
{
if (stack[currentPtr] == node) {
pop();
} else {
int32_t pos = currentPtr - 1;
while (pos >= 0 && stack[pos] != node) {
pos--;
}
if (pos == -1) {
return;
}
node->release();
nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos);
currentPtr--;
}
}
void
nsHtml5TreeBuilder::removeFromListOfActiveFormattingElements(int32_t pos)
{
MOZ_ASSERT(!!listOfActiveFormattingElements[pos]);
listOfActiveFormattingElements[pos]->release();
if (pos == listPtr) {
MOZ_ASSERT(debugOnlyClearLastListSlot());
listPtr--;
return;
}
MOZ_ASSERT(pos < listPtr);
nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, pos + 1, pos, listPtr - pos);
MOZ_ASSERT(debugOnlyClearLastListSlot());
listPtr--;
}
bool
nsHtml5TreeBuilder::adoptionAgencyEndTag(nsIAtom* name)
{
if (stack[currentPtr]->ns == kNameSpaceID_XHTML && stack[currentPtr]->name == name && findInListOfActiveFormattingElements(stack[currentPtr]) == -1) {
pop();
return true;
}
for (int32_t i = 0; i < 8; ++i) {
int32_t formattingEltListPos = listPtr;
while (formattingEltListPos > -1) {
nsHtml5StackNode* listNode = listOfActiveFormattingElements[formattingEltListPos];
if (!listNode) {
formattingEltListPos = -1;
break;
} else if (listNode->name == name) {
break;
}
formattingEltListPos--;
}
if (formattingEltListPos == -1) {
return false;
}
nsHtml5StackNode* formattingElt = listOfActiveFormattingElements[formattingEltListPos];
int32_t formattingEltStackPos = currentPtr;
bool inScope = true;
while (formattingEltStackPos > -1) {
nsHtml5StackNode* node = stack[formattingEltStackPos];
if (node == formattingElt) {
break;
} else if (node->isScoping()) {
inScope = false;
}
formattingEltStackPos--;
}
if (formattingEltStackPos == -1) {
errNoElementToCloseButEndTagSeen(name);
removeFromListOfActiveFormattingElements(formattingEltListPos);
return true;
}
if (!inScope) {
errNoElementToCloseButEndTagSeen(name);
return true;
}
if (formattingEltStackPos != currentPtr) {
errEndTagViolatesNestingRules(name);
}
int32_t furthestBlockPos = formattingEltStackPos + 1;
while (furthestBlockPos <= currentPtr) {
nsHtml5StackNode* node = stack[furthestBlockPos];
MOZ_ASSERT(furthestBlockPos > 0, "How is formattingEltStackPos + 1 not > 0?");
if (node->isSpecial()) {
break;
}
furthestBlockPos++;
}
if (furthestBlockPos > currentPtr) {
while (currentPtr >= formattingEltStackPos) {
pop();
}
removeFromListOfActiveFormattingElements(formattingEltListPos);
return true;
}
nsHtml5StackNode* commonAncestor = stack[formattingEltStackPos - 1];
nsHtml5StackNode* furthestBlock = stack[furthestBlockPos];
int32_t bookmark = formattingEltListPos;
int32_t nodePos = furthestBlockPos;
nsHtml5StackNode* lastNode = furthestBlock;
int32_t j = 0;
for (; ; ) {
++j;
nodePos--;
if (nodePos == formattingEltStackPos) {
break;
}
nsHtml5StackNode* node = stack[nodePos];
int32_t nodeListPos = findInListOfActiveFormattingElements(node);
if (j > 3 && nodeListPos != -1) {
removeFromListOfActiveFormattingElements(nodeListPos);
if (nodeListPos <= formattingEltListPos) {
formattingEltListPos--;
}
if (nodeListPos <= bookmark) {
bookmark--;
}
nodeListPos = -1;
}
if (nodeListPos == -1) {
MOZ_ASSERT(formattingEltStackPos < nodePos);
MOZ_ASSERT(bookmark < nodePos);
MOZ_ASSERT(furthestBlockPos > nodePos);
removeFromStack(nodePos);
furthestBlockPos--;
continue;
}
if (nodePos == furthestBlockPos) {
bookmark = nodeListPos + 1;
}
MOZ_ASSERT(node == listOfActiveFormattingElements[nodeListPos]);
MOZ_ASSERT(node == stack[nodePos]);
nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes(nullptr), commonAncestor->node);
nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, node->name, clone, node->popName, node->attributes);
node->dropAttributes();
stack[nodePos] = newNode;
newNode->retain();
listOfActiveFormattingElements[nodeListPos] = newNode;
node->release();
node->release();
node = newNode;
detachFromParent(lastNode->node);
appendElement(lastNode->node, node->node);
lastNode = node;
}
if (commonAncestor->isFosterParenting()) {
detachFromParent(lastNode->node);
insertIntoFosterParent(lastNode->node);
} else {
detachFromParent(lastNode->node);
appendElement(lastNode->node, commonAncestor->node);
}
nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, formattingElt->name, formattingElt->attributes->cloneAttributes(nullptr), furthestBlock->node);
nsHtml5StackNode* formattingClone = new nsHtml5StackNode(formattingElt->getFlags(), formattingElt->ns, formattingElt->name, clone, formattingElt->popName, formattingElt->attributes);
formattingElt->dropAttributes();
appendChildrenToNewParent(furthestBlock->node, clone);
appendElement(clone, furthestBlock->node);
removeFromListOfActiveFormattingElements(formattingEltListPos);
insertIntoListOfActiveFormattingElements(formattingClone, bookmark);
MOZ_ASSERT(formattingEltStackPos < furthestBlockPos);
removeFromStack(formattingEltStackPos);
insertIntoStack(formattingClone, furthestBlockPos);
}
return true;
}
void
nsHtml5TreeBuilder::insertIntoStack(nsHtml5StackNode* node, int32_t position)
{
MOZ_ASSERT(currentPtr + 1 < stack.length);
MOZ_ASSERT(position <= currentPtr + 1);
if (position == currentPtr + 1) {
push(node);
} else {
nsHtml5ArrayCopy::arraycopy(stack, position, position + 1, (currentPtr - position) + 1);
currentPtr++;
stack[position] = node;
}
}
void
nsHtml5TreeBuilder::insertIntoListOfActiveFormattingElements(nsHtml5StackNode* formattingClone, int32_t bookmark)
{
formattingClone->retain();
MOZ_ASSERT(listPtr + 1 < listOfActiveFormattingElements.length);
if (bookmark <= listPtr) {
nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, bookmark, bookmark + 1, (listPtr - bookmark) + 1);
}
listPtr++;
listOfActiveFormattingElements[bookmark] = formattingClone;
}
int32_t
nsHtml5TreeBuilder::findInListOfActiveFormattingElements(nsHtml5StackNode* node)
{
for (int32_t i = listPtr; i >= 0; i--) {
if (node == listOfActiveFormattingElements[i]) {
return i;
}
}
return -1;
}
int32_t
nsHtml5TreeBuilder::findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(nsIAtom* name)
{
for (int32_t i = listPtr; i >= 0; i--) {
nsHtml5StackNode* node = listOfActiveFormattingElements[i];
if (!node) {
return -1;
} else if (node->name == name) {
return i;
}
}
return -1;
}
void
nsHtml5TreeBuilder::maybeForgetEarlierDuplicateFormattingElement(nsIAtom* name, nsHtml5HtmlAttributes* attributes)
{
int32_t candidate = -1;
int32_t count = 0;
for (int32_t i = listPtr; i >= 0; i--) {
nsHtml5StackNode* node = listOfActiveFormattingElements[i];
if (!node) {
break;
}
if (node->name == name && node->attributes->equalsAnother(attributes)) {
candidate = i;
++count;
}
}
if (count >= 3) {
removeFromListOfActiveFormattingElements(candidate);
}
}
int32_t
nsHtml5TreeBuilder::findLastOrRoot(nsIAtom* name)
{
for (int32_t i = currentPtr; i > 0; i--) {
if (stack[i]->ns == kNameSpaceID_XHTML && stack[i]->name == name) {
return i;
}
}
return 0;
}
int32_t
nsHtml5TreeBuilder::findLastOrRoot(int32_t group)
{
for (int32_t i = currentPtr; i > 0; i--) {
if (stack[i]->getGroup() == group) {
return i;
}
}
return 0;
}
bool
nsHtml5TreeBuilder::addAttributesToBody(nsHtml5HtmlAttributes* attributes)
{
if (currentPtr >= 1) {
nsHtml5StackNode* body = stack[1];
if (body->getGroup() == NS_HTML5TREE_BUILDER_BODY) {
addAttributesToElement(body->node, attributes);
return true;
}
}
return false;
}
void
nsHtml5TreeBuilder::addAttributesToHtml(nsHtml5HtmlAttributes* attributes)
{
addAttributesToElement(stack[0]->node, attributes);
}
void
nsHtml5TreeBuilder::pushHeadPointerOntoStack()
{
MOZ_ASSERT(!!headPointer);
MOZ_ASSERT(mode == NS_HTML5TREE_BUILDER_AFTER_HEAD);
silentPush(new nsHtml5StackNode(nsHtml5ElementName::ELT_HEAD, headPointer));
}
void
nsHtml5TreeBuilder::reconstructTheActiveFormattingElements()
{
if (listPtr == -1) {
return;
}
nsHtml5StackNode* mostRecent = listOfActiveFormattingElements[listPtr];
if (!mostRecent || isInStack(mostRecent)) {
return;
}
int32_t entryPos = listPtr;
for (; ; ) {
entryPos--;
if (entryPos == -1) {
break;
}
if (!listOfActiveFormattingElements[entryPos]) {
break;
}
if (isInStack(listOfActiveFormattingElements[entryPos])) {
break;
}
}
while (entryPos < listPtr) {
entryPos++;
nsHtml5StackNode* entry = listOfActiveFormattingElements[entryPos];
nsHtml5StackNode* currentNode = stack[currentPtr];
nsIContentHandle* clone;
if (currentNode->isFosterParenting()) {
clone = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr));
} else {
clone = createElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr), currentNode->node);
appendElement(clone, currentNode->node);
}
nsHtml5StackNode* entryClone = new nsHtml5StackNode(entry->getFlags(), entry->ns, entry->name, clone, entry->popName, entry->attributes);
entry->dropAttributes();
push(entryClone);
listOfActiveFormattingElements[entryPos] = entryClone;
entry->release();
entryClone->retain();
}
}
void
nsHtml5TreeBuilder::insertIntoFosterParent(nsIContentHandle* child)
{
int32_t tablePos = findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE);
int32_t templatePos = findLastOrRoot(NS_HTML5TREE_BUILDER_TEMPLATE);
if (templatePos >= tablePos) {
appendElement(child, stack[templatePos]->node);
return;
}
nsHtml5StackNode* node = stack[tablePos];
insertFosterParentedChild(child, node->node, stack[tablePos - 1]->node);
}
nsIContentHandle*
nsHtml5TreeBuilder::createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes)
{
return createAndInsertFosterParentedElement(ns, name, attributes, nullptr);
}
nsIContentHandle*
nsHtml5TreeBuilder::createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
{
int32_t tablePos = findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE);
int32_t templatePos = findLastOrRoot(NS_HTML5TREE_BUILDER_TEMPLATE);
if (templatePos >= tablePos) {
nsIContentHandle* child = createElement(ns, name, attributes, form, stack[templatePos]->node);
appendElement(child, stack[templatePos]->node);
return child;
}
nsHtml5StackNode* node = stack[tablePos];
return createAndInsertFosterParentedElement(ns, name, attributes, form, node->node, stack[tablePos - 1]->node);
}
bool
nsHtml5TreeBuilder::isInStack(nsHtml5StackNode* node)
{
for (int32_t i = currentPtr; i >= 0; i--) {
if (stack[i] == node) {
return true;
}
}
return false;
}
void
nsHtml5TreeBuilder::popTemplateMode()
{
templateModePtr--;
}
void
nsHtml5TreeBuilder::pop()
{
nsHtml5StackNode* node = stack[currentPtr];
MOZ_ASSERT(debugOnlyClearLastStackSlot());
currentPtr--;
elementPopped(node->ns, node->popName, node->node);
node->release();
}
void
nsHtml5TreeBuilder::silentPop()
{
nsHtml5StackNode* node = stack[currentPtr];
MOZ_ASSERT(debugOnlyClearLastStackSlot());
currentPtr--;
node->release();
}
void
nsHtml5TreeBuilder::popOnEof()
{
nsHtml5StackNode* node = stack[currentPtr];
MOZ_ASSERT(debugOnlyClearLastStackSlot());
currentPtr--;
markMalformedIfScript(node->node);
elementPopped(node->ns, node->popName, node->node);
node->release();
}
void
nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush(nsHtml5HtmlAttributes* attributes)
{
nsIContentHandle* elt = createHtmlElementSetAsRoot(attributes);
nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HTML, elt);
push(node);
}
void
nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush()
{
appendHtmlElementToDocumentAndPush(tokenizer->emptyAttributes());
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes)
{
nsIContentHandle* currentNode = stack[currentPtr]->node;
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::head, attributes, currentNode);
appendElement(elt, currentNode);
headPointer = elt;
nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HEAD, elt);
push(node);
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement(nsHtml5HtmlAttributes* attributes)
{
appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_BODY, attributes);
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement()
{
appendToCurrentNodeAndPushBodyElement(tokenizer->emptyAttributes());
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormElementMayFoster(nsHtml5HtmlAttributes* attributes)
{
nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes);
} else {
elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes, current->node);
appendElement(elt, current->node);
}
if (!isTemplateContents()) {
formPointer = elt;
}
nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_FORM, elt);
push(node);
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsHtml5HtmlAttributes* clone = attributes->cloneAttributes(nullptr);
nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, elementName->name, attributes);
} else {
elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, current->node);
appendElement(elt, current->node);
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, clone);
push(node);
append(node);
node->retain();
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIContentHandle* currentNode = stack[currentPtr]->node;
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, currentNode);
appendElement(elt, currentNode);
if (nsHtml5ElementName::ELT_TEMPLATE == elementName) {
elt = getDocumentFragmentForTemplate(elt);
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt);
push(node);
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIAtom* popName = elementName->name;
nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, popName, attributes);
} else {
elt = createElement(kNameSpaceID_XHTML, popName, attributes, current->node);
appendElement(elt, current->node);
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName);
push(node);
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIAtom* popName = elementName->name;
bool markAsHtmlIntegrationPoint = false;
if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName && annotationXmlEncodingPermitsHtml(attributes)) {
markAsHtmlIntegrationPoint = true;
}
nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
elt = createAndInsertFosterParentedElement(kNameSpaceID_MathML, popName, attributes);
} else {
elt = createElement(kNameSpaceID_MathML, popName, attributes, current->node);
appendElement(elt, current->node);
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName, markAsHtmlIntegrationPoint);
push(node);
}
bool
nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(nsHtml5HtmlAttributes* attributes)
{
nsString* encoding = attributes->getValue(nsHtml5AttributeName::ATTR_ENCODING);
if (!encoding) {
return false;
}
return nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("application/xhtml+xml", encoding) || nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("text/html", encoding);
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIAtom* popName = elementName->camelCaseName;
nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
elt = createAndInsertFosterParentedElement(kNameSpaceID_SVG, popName, attributes);
} else {
elt = createElement(kNameSpaceID_SVG, popName, attributes, current->node);
appendElement(elt, current->node);
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, popName, elt);
push(node);
}
void
nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
{
nsIContentHandle* elt;
nsIContentHandle* formOwner = !form || fragment || isTemplateContents() ? nullptr : form;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, elementName->name, attributes, formOwner);
} else {
elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, formOwner, current->node);
appendElement(elt, current->node);
}
nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt);
push(node);
}
void
nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
{
nsIContentHandle* elt;
nsIContentHandle* formOwner = !form || fragment || isTemplateContents() ? nullptr : form;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, name, attributes, formOwner);
} else {
elt = createElement(kNameSpaceID_XHTML, name, attributes, formOwner, current->node);
appendElement(elt, current->node);
}
elementPushed(kNameSpaceID_XHTML, name, elt);
elementPopped(kNameSpaceID_XHTML, name, elt);
}
void
nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIAtom* popName = elementName->name;
nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, popName, attributes);
} else {
elt = createElement(kNameSpaceID_XHTML, popName, attributes, current->node);
appendElement(elt, current->node);
}
elementPushed(kNameSpaceID_XHTML, popName, elt);
elementPopped(kNameSpaceID_XHTML, popName, elt);
}
void
nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIAtom* popName = elementName->camelCaseName;
nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
elt = createAndInsertFosterParentedElement(kNameSpaceID_SVG, popName, attributes);
} else {
elt = createElement(kNameSpaceID_SVG, popName, attributes, current->node);
appendElement(elt, current->node);
}
elementPushed(kNameSpaceID_SVG, popName, elt);
elementPopped(kNameSpaceID_SVG, popName, elt);
}
void
nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
{
nsIAtom* popName = elementName->name;
nsIContentHandle* elt;
nsHtml5StackNode* current = stack[currentPtr];
if (current->isFosterParenting()) {
elt = createAndInsertFosterParentedElement(kNameSpaceID_MathML, popName, attributes);
} else {
elt = createElement(kNameSpaceID_MathML, popName, attributes, current->node);
appendElement(elt, current->node);
}
elementPushed(kNameSpaceID_MathML, popName, elt);
elementPopped(kNameSpaceID_MathML, popName, elt);
}
void
nsHtml5TreeBuilder::appendVoidElementToCurrent(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
{
nsIContentHandle* currentNode = stack[currentPtr]->node;
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, name, attributes, !form || fragment || isTemplateContents() ? nullptr : form, currentNode);
appendElement(elt, currentNode);
elementPushed(kNameSpaceID_XHTML, name, elt);
elementPopped(kNameSpaceID_XHTML, name, elt);
}
void
nsHtml5TreeBuilder::appendVoidFormToCurrent(nsHtml5HtmlAttributes* attributes)
{
nsIContentHandle* currentNode = stack[currentPtr]->node;
nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, nsHtml5Atoms::form, attributes, currentNode);
formPointer = elt;
appendElement(elt, currentNode);
elementPushed(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt);
elementPopped(kNameSpaceID_XHTML, nsHtml5Atoms::form, elt);
}
void
nsHtml5TreeBuilder::requestSuspension()
{
tokenizer->requestSuspension();
}
;bool
nsHtml5TreeBuilder::isInForeign()
{
return currentPtr >= 0 && stack[currentPtr]->ns != kNameSpaceID_XHTML;
}
bool
nsHtml5TreeBuilder::isInForeignButNotHtmlOrMathTextIntegrationPoint()
{
if (currentPtr < 0) {
return false;
}
return !isSpecialParentInForeign(stack[currentPtr]);
}
void
nsHtml5TreeBuilder::setFragmentContext(nsIAtom* context, int32_t ns, nsIContentHandle* node, bool quirks)
{
this->contextName = context;
this->contextNamespace = ns;
this->contextNode = node;
this->fragment = (!!contextName);
this->quirks = quirks;
}
nsIContentHandle*
nsHtml5TreeBuilder::currentNode()
{
return stack[currentPtr]->node;
}
bool
nsHtml5TreeBuilder::isScriptingEnabled()
{
return scriptingEnabled;
}
void
nsHtml5TreeBuilder::setScriptingEnabled(bool scriptingEnabled)
{
this->scriptingEnabled = scriptingEnabled;
}
void
nsHtml5TreeBuilder::setIsSrcdocDocument(bool isSrcdocDocument)
{
this->isSrcdocDocument = isSrcdocDocument;
}
void
nsHtml5TreeBuilder::flushCharacters()
{
if (charBufferLen > 0) {
if ((mode == NS_HTML5TREE_BUILDER_IN_TABLE || mode == NS_HTML5TREE_BUILDER_IN_TABLE_BODY || mode == NS_HTML5TREE_BUILDER_IN_ROW) && charBufferContainsNonWhitespace()) {
errNonSpaceInTable();
reconstructTheActiveFormattingElements();
if (!stack[currentPtr]->isFosterParenting()) {
appendCharacters(currentNode(), charBuffer, 0, charBufferLen);
charBufferLen = 0;
return;
}
int32_t tablePos = findLastOrRoot(NS_HTML5TREE_BUILDER_TABLE);
int32_t templatePos = findLastOrRoot(NS_HTML5TREE_BUILDER_TEMPLATE);
if (templatePos >= tablePos) {
appendCharacters(stack[templatePos]->node, charBuffer, 0, charBufferLen);
charBufferLen = 0;
return;
}
nsHtml5StackNode* tableElt = stack[tablePos];
insertFosterParentedCharacters(charBuffer, 0, charBufferLen, tableElt->node, stack[tablePos - 1]->node);
charBufferLen = 0;
return;
}
appendCharacters(currentNode(), charBuffer, 0, charBufferLen);
charBufferLen = 0;
}
}
bool
nsHtml5TreeBuilder::charBufferContainsNonWhitespace()
{
for (int32_t i = 0; i < charBufferLen; i++) {
switch(charBuffer[i]) {
case ' ':
case '\t':
case '\n':
case '\r':
case '\f': {
continue;
}
default: {
return true;
}
}
}
return false;
}
nsAHtml5TreeBuilderState*
nsHtml5TreeBuilder::newSnapshot()
{
jArray<nsHtml5StackNode*,int32_t> listCopy = jArray<nsHtml5StackNode*,int32_t>::newJArray(listPtr + 1);
for (int32_t i = 0; i < listCopy.length; i++) {
nsHtml5StackNode* node = listOfActiveFormattingElements[i];
if (node) {
nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, node->name, node->node, node->popName, node->attributes->cloneAttributes(nullptr));
listCopy[i] = newNode;
} else {
listCopy[i] = nullptr;
}
}
jArray<nsHtml5StackNode*,int32_t> stackCopy = jArray<nsHtml5StackNode*,int32_t>::newJArray(currentPtr + 1);
for (int32_t i = 0; i < stackCopy.length; i++) {
nsHtml5StackNode* node = stack[i];
int32_t listIndex = findInListOfActiveFormattingElements(node);
if (listIndex == -1) {
nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, node->name, node->node, node->popName, nullptr);
stackCopy[i] = newNode;
} else {
stackCopy[i] = listCopy[listIndex];
stackCopy[i]->retain();
}
}
jArray<int32_t,int32_t> templateModeStackCopy = jArray<int32_t,int32_t>::newJArray(templateModePtr + 1);
nsHtml5ArrayCopy::arraycopy(templateModeStack, templateModeStackCopy, templateModeStackCopy.length);
return new nsHtml5StateSnapshot(stackCopy, listCopy, templateModeStackCopy, formPointer, headPointer, deepTreeSurrogateParent, mode, originalMode, framesetOk, needToDropLF, quirks);
}
bool
nsHtml5TreeBuilder::snapshotMatches(nsAHtml5TreeBuilderState* snapshot)
{
jArray<nsHtml5StackNode*,int32_t> stackCopy = snapshot->getStack();
int32_t stackLen = snapshot->getStackLength();
jArray<nsHtml5StackNode*,int32_t> listCopy = snapshot->getListOfActiveFormattingElements();
int32_t listLen = snapshot->getListOfActiveFormattingElementsLength();
jArray<int32_t,int32_t> templateModeStackCopy = snapshot->getTemplateModeStack();
int32_t templateModeStackLen = snapshot->getTemplateModeStackLength();
if (stackLen != currentPtr + 1 || listLen != listPtr + 1 || templateModeStackLen != templateModePtr + 1 || formPointer != snapshot->getFormPointer() || headPointer != snapshot->getHeadPointer() || deepTreeSurrogateParent != snapshot->getDeepTreeSurrogateParent() || mode != snapshot->getMode() || originalMode != snapshot->getOriginalMode() || framesetOk != snapshot->isFramesetOk() || needToDropLF != snapshot->isNeedToDropLF() || quirks != snapshot->isQuirks()) {
return false;
}
for (int32_t i = listLen - 1; i >= 0; i--) {
if (!listCopy[i] && !listOfActiveFormattingElements[i]) {
continue;
} else if (!listCopy[i] || !listOfActiveFormattingElements[i]) {
return false;
}
if (listCopy[i]->node != listOfActiveFormattingElements[i]->node) {
return false;
}
}
for (int32_t i = stackLen - 1; i >= 0; i--) {
if (stackCopy[i]->node != stack[i]->node) {
return false;
}
}
for (int32_t i = templateModeStackLen - 1; i >= 0; i--) {
if (templateModeStackCopy[i] != templateModeStack[i]) {
return false;
}
}
return true;
}
void
nsHtml5TreeBuilder::loadState(nsAHtml5TreeBuilderState* snapshot, nsHtml5AtomTable* interner)
{
jArray<nsHtml5StackNode*,int32_t> stackCopy = snapshot->getStack();
int32_t stackLen = snapshot->getStackLength();
jArray<nsHtml5StackNode*,int32_t> listCopy = snapshot->getListOfActiveFormattingElements();
int32_t listLen = snapshot->getListOfActiveFormattingElementsLength();
jArray<int32_t,int32_t> templateModeStackCopy = snapshot->getTemplateModeStack();
int32_t templateModeStackLen = snapshot->getTemplateModeStackLength();
for (int32_t i = 0; i <= listPtr; i++) {
if (listOfActiveFormattingElements[i]) {
listOfActiveFormattingElements[i]->release();
}
}
if (listOfActiveFormattingElements.length < listLen) {
listOfActiveFormattingElements = jArray<nsHtml5StackNode*,int32_t>::newJArray(listLen);
}
listPtr = listLen - 1;
for (int32_t i = 0; i <= currentPtr; i++) {
stack[i]->release();
}
if (stack.length < stackLen) {
stack = jArray<nsHtml5StackNode*,int32_t>::newJArray(stackLen);
}
currentPtr = stackLen - 1;
if (templateModeStack.length < templateModeStackLen) {
templateModeStack = jArray<int32_t,int32_t>::newJArray(templateModeStackLen);
}
templateModePtr = templateModeStackLen - 1;
for (int32_t i = 0; i < listLen; i++) {
nsHtml5StackNode* node = listCopy[i];
if (node) {
nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, nsHtml5Portability::newLocalFromLocal(node->name, interner), node->node, nsHtml5Portability::newLocalFromLocal(node->popName, interner), node->attributes->cloneAttributes(nullptr));
listOfActiveFormattingElements[i] = newNode;
} else {
listOfActiveFormattingElements[i] = nullptr;
}
}
for (int32_t i = 0; i < stackLen; i++) {
nsHtml5StackNode* node = stackCopy[i];
int32_t listIndex = findInArray(node, listCopy);
if (listIndex == -1) {
nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, nsHtml5Portability::newLocalFromLocal(node->name, interner), node->node, nsHtml5Portability::newLocalFromLocal(node->popName, interner), nullptr);
stack[i] = newNode;
} else {
stack[i] = listOfActiveFormattingElements[listIndex];
stack[i]->retain();
}
}
nsHtml5ArrayCopy::arraycopy(templateModeStackCopy, templateModeStack, templateModeStackLen);
formPointer = snapshot->getFormPointer();
headPointer = snapshot->getHeadPointer();
deepTreeSurrogateParent = snapshot->getDeepTreeSurrogateParent();
mode = snapshot->getMode();
originalMode = snapshot->getOriginalMode();
framesetOk = snapshot->isFramesetOk();
needToDropLF = snapshot->isNeedToDropLF();
quirks = snapshot->isQuirks();
}
int32_t
nsHtml5TreeBuilder::findInArray(nsHtml5StackNode* node, jArray<nsHtml5StackNode*,int32_t> arr)
{
for (int32_t i = listPtr; i >= 0; i--) {
if (node == arr[i]) {
return i;
}
}
return -1;
}
nsIContentHandle*
nsHtml5TreeBuilder::getFormPointer()
{
return formPointer;
}
nsIContentHandle*
nsHtml5TreeBuilder::getHeadPointer()
{
return headPointer;
}
nsIContentHandle*
nsHtml5TreeBuilder::getDeepTreeSurrogateParent()
{
return deepTreeSurrogateParent;
}
jArray<nsHtml5StackNode*,int32_t>
nsHtml5TreeBuilder::getListOfActiveFormattingElements()
{
return listOfActiveFormattingElements;
}
jArray<nsHtml5StackNode*,int32_t>
nsHtml5TreeBuilder::getStack()
{
return stack;
}
jArray<int32_t,int32_t>
nsHtml5TreeBuilder::getTemplateModeStack()
{
return templateModeStack;
}
int32_t
nsHtml5TreeBuilder::getMode()
{
return mode;
}
int32_t
nsHtml5TreeBuilder::getOriginalMode()
{
return originalMode;
}
bool
nsHtml5TreeBuilder::isFramesetOk()
{
return framesetOk;
}
bool
nsHtml5TreeBuilder::isNeedToDropLF()
{
return needToDropLF;
}
bool
nsHtml5TreeBuilder::isQuirks()
{
return quirks;
}
int32_t
nsHtml5TreeBuilder::getListOfActiveFormattingElementsLength()
{
return listPtr + 1;
}
int32_t
nsHtml5TreeBuilder::getStackLength()
{
return currentPtr + 1;
}
int32_t
nsHtml5TreeBuilder::getTemplateModeStackLength()
{
return templateModePtr + 1;
}
void
nsHtml5TreeBuilder::initializeStatics()
{
}
void
nsHtml5TreeBuilder::releaseStatics()
{
}
#include "nsHtml5TreeBuilderCppSupplement.h"