/*
 * Copyright (C) 2010 Google, Inc. All Rights Reserved.
 * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GOOGLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "HTMLTreeBuilder.h"

#include "DocumentFragment.h"
#include "HTMLDocument.h"
#include "HTMLDocumentParser.h"
#include "HTMLFormControlElement.h"
#include "HTMLFormElement.h"
#include "HTMLInputElement.h"
#include "HTMLOptGroupElement.h"
#include "HTMLOptionElement.h"
#include "HTMLParserIdioms.h"
#include "HTMLScriptElement.h"
#include "HTMLTableElement.h"
#include "JSCustomElementInterface.h"
#include "LocalizedStrings.h"
#include "NotImplemented.h"
#include "SVGScriptElement.h"
#include "XLinkNames.h"
#include "XMLNSNames.h"
#include "XMLNames.h"
#include <wtf/NeverDestroyed.h>
#include <wtf/unicode/CharacterNames.h>

#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS_FAMILY)
#include "TelephoneNumberDetector.h"
#endif

namespace WebCore {

using namespace HTMLNames;

CustomElementConstructionData::CustomElementConstructionData(Ref<JSCustomElementInterface>&& customElementInterface, const AtomicString& name, Vector<Attribute>&& attributes)
    : elementInterface(WTFMove(customElementInterface))
    , name(name)
    , attributes(WTFMove(attributes))
{
}

CustomElementConstructionData::~CustomElementConstructionData() = default;

namespace {

inline bool isHTMLSpaceOrReplacementCharacter(UChar character)
{
    return isHTMLSpace(character) || character == replacementCharacter;
}

}

static inline TextPosition uninitializedPositionValue1()
{
    return TextPosition(OrdinalNumber::fromOneBasedInt(-1), OrdinalNumber());
}

static inline bool isAllWhitespace(const String& string)
{
    return string.isAllSpecialCharacters<isHTMLSpace>();
}

static inline bool isAllWhitespaceOrReplacementCharacters(const String& string)
{
    return string.isAllSpecialCharacters<isHTMLSpaceOrReplacementCharacter>();
}

static bool isNumberedHeaderTag(const AtomicString& tagName)
{
    return tagName == h1Tag
        || tagName == h2Tag
        || tagName == h3Tag
        || tagName == h4Tag
        || tagName == h5Tag
        || tagName == h6Tag;
}

static bool isCaptionColOrColgroupTag(const AtomicString& tagName)
{
    return tagName == captionTag || tagName == colTag || tagName == colgroupTag;
}

static bool isTableCellContextTag(const AtomicString& tagName)
{
    return tagName == thTag || tagName == tdTag;
}

static bool isTableBodyContextTag(const AtomicString& tagName)
{
    return tagName == tbodyTag || tagName == tfootTag || tagName == theadTag;
}

static bool isNonAnchorNonNobrFormattingTag(const AtomicString& tagName)
{
    return tagName == bTag
        || tagName == bigTag
        || tagName == codeTag
        || tagName == emTag
        || tagName == fontTag
        || tagName == iTag
        || tagName == sTag
        || tagName == smallTag
        || tagName == strikeTag
        || tagName == strongTag
        || tagName == ttTag
        || tagName == uTag;
}

static bool isNonAnchorFormattingTag(const AtomicString& tagName)
{
    return tagName == nobrTag || isNonAnchorNonNobrFormattingTag(tagName);
}

// https://html.spec.whatwg.org/multipage/syntax.html#formatting
bool HTMLConstructionSite::isFormattingTag(const AtomicString& tagName)
{
    return tagName == aTag || isNonAnchorFormattingTag(tagName);
}

class HTMLTreeBuilder::ExternalCharacterTokenBuffer {
public:
    explicit ExternalCharacterTokenBuffer(AtomicHTMLToken& token)
        : m_text(token.characters(), token.charactersLength())
        , m_isAll8BitData(token.charactersIsAll8BitData())
    {
        ASSERT(!isEmpty());
    }

    explicit ExternalCharacterTokenBuffer(const String& string)
        : m_text(string)
        , m_isAll8BitData(m_text.is8Bit())
    {
        ASSERT(!isEmpty());
    }

    ~ExternalCharacterTokenBuffer()
    {
        ASSERT(isEmpty());
    }

    bool isEmpty() const { return m_text.isEmpty(); }

    bool isAll8BitData() const { return m_isAll8BitData; }

    void skipAtMostOneLeadingNewline()
    {
        ASSERT(!isEmpty());
        if (m_text[0] == '\n')
            m_text = m_text.substring(1);
    }

    void skipLeadingWhitespace()
    {
        skipLeading<isHTMLSpace>();
    }

    String takeLeadingWhitespace()
    {
        return takeLeading<isHTMLSpace>();
    }

    void skipLeadingNonWhitespace()
    {
        skipLeading<isNotHTMLSpace>();
    }

    String takeRemaining()
    {
        String result = makeString(m_text);
        m_text = StringView();
        return result;
    }

    void giveRemainingTo(StringBuilder& recipient)
    {
        recipient.append(m_text);
        m_text = StringView();
    }

    String takeRemainingWhitespace()
    {
        ASSERT(!isEmpty());
        Vector<LChar, 8> whitespace;
        do {
            UChar character = m_text[0];
            if (isHTMLSpace(character))
                whitespace.append(character);
            m_text = m_text.substring(1);
        } while (!m_text.isEmpty());

        // Returning the null string when there aren't any whitespace
        // characters is slightly cleaner semantically because we don't want
        // to insert a text node (as opposed to inserting an empty text node).
        if (whitespace.isEmpty())
            return String();

        return String::adopt(WTFMove(whitespace));
    }

private:
    template<bool characterPredicate(UChar)> void skipLeading()
    {
        ASSERT(!isEmpty());
        while (characterPredicate(m_text[0])) {
            m_text = m_text.substring(1);
            if (m_text.isEmpty())
                return;
        }
    }

    template<bool characterPredicate(UChar)> String takeLeading()
    {
        ASSERT(!isEmpty());
        StringView start = m_text;
        skipLeading<characterPredicate>();
        if (start.length() == m_text.length())
            return String();
        return makeString(start.substring(0, start.length() - m_text.length()));
    }

    String makeString(StringView stringView) const
    {
        if (stringView.is8Bit() || !isAll8BitData())
            return stringView.toString();
        return String::make8BitFrom16BitSource(stringView.characters16(), stringView.length());
    }

    StringView m_text;
    bool m_isAll8BitData;
};

inline bool HTMLTreeBuilder::isParsingTemplateContents() const
{
    return m_tree.openElements().hasTemplateInHTMLScope();
}

inline bool HTMLTreeBuilder::isParsingFragmentOrTemplateContents() const
{
    return isParsingFragment() || isParsingTemplateContents();
}

HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser& parser, HTMLDocument& document, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options)
    : m_parser(parser)
    , m_options(options)
    , m_tree(document, parserContentPolicy, options.maximumDOMTreeDepth)
    , m_scriptToProcessStartPosition(uninitializedPositionValue1())
{
#if !ASSERT_DISABLED
    m_destructionProhibited = false;
#endif
}

HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser& parser, DocumentFragment& fragment, Element& contextElement, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options)
    : m_parser(parser)
    , m_options(options)
    , m_fragmentContext(fragment, contextElement)
    , m_tree(fragment, parserContentPolicy, options.maximumDOMTreeDepth)
    , m_scriptToProcessStartPosition(uninitializedPositionValue1())
{
    ASSERT(isMainThread());

    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-html-fragments
    // For efficiency, we skip step 5 ("Let root be a new html element with no attributes") and instead use the DocumentFragment as a root node.
    m_tree.openElements().pushRootNode(HTMLStackItem::create(fragment));

    if (contextElement.hasTagName(templateTag))
        m_templateInsertionModes.append(InsertionMode::TemplateContents);

    resetInsertionModeAppropriately();

    m_tree.setForm(is<HTMLFormElement>(contextElement) ? &downcast<HTMLFormElement>(contextElement) : HTMLFormElement::findClosestFormAncestor(contextElement));

#if !ASSERT_DISABLED
    m_destructionProhibited = false;
#endif
}

HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext()
{
}

HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment& fragment, Element& contextElement)
    : m_fragment(&fragment)
{
    ASSERT(!fragment.hasChildNodes());
    m_contextElementStackItem = HTMLStackItem::create(contextElement);
}

inline Element& HTMLTreeBuilder::FragmentParsingContext::contextElement() const
{
    return contextElementStackItem().element();
}

inline HTMLStackItem& HTMLTreeBuilder::FragmentParsingContext::contextElementStackItem() const
{
    ASSERT(m_fragment);
    return *m_contextElementStackItem;
}

RefPtr<ScriptElement> HTMLTreeBuilder::takeScriptToProcess(TextPosition& scriptStartPosition)
{
    ASSERT(!m_destroyed);

    if (!m_scriptToProcess)
        return nullptr;

    // Unpause ourselves, callers may pause us again when processing the script.
    // The HTML5 spec is written as though scripts are executed inside the tree builder.
    // We pause the parser to exit the tree builder, and then resume before running scripts.
    scriptStartPosition = m_scriptToProcessStartPosition;
    m_scriptToProcessStartPosition = uninitializedPositionValue1();
    return WTFMove(m_scriptToProcess);
}

void HTMLTreeBuilder::constructTree(AtomicHTMLToken&& token)
{
#if !ASSERT_DISABLED
    ASSERT(!m_destroyed);
    ASSERT(!m_destructionProhibited);
    m_destructionProhibited = true;
#endif

    if (shouldProcessTokenInForeignContent(token))
        processTokenInForeignContent(WTFMove(token));
    else
        processToken(WTFMove(token));

    bool inForeignContent = !m_tree.isEmpty()
        && !isInHTMLNamespace(adjustedCurrentStackItem())
        && !HTMLElementStack::isHTMLIntegrationPoint(m_tree.currentStackItem())
        && !HTMLElementStack::isMathMLTextIntegrationPoint(m_tree.currentStackItem());

    m_parser.tokenizer().setForceNullCharacterReplacement(m_insertionMode == InsertionMode::Text || inForeignContent);
    m_parser.tokenizer().setShouldAllowCDATA(inForeignContent);

#if !ASSERT_DISABLED
    m_destructionProhibited = false;
#endif

    m_tree.executeQueuedTasks();
    // The tree builder might have been destroyed as an indirect result of executing the queued tasks.
}

void HTMLTreeBuilder::processToken(AtomicHTMLToken&& token)
{
    switch (token.type()) {
    case HTMLToken::Uninitialized:
        ASSERT_NOT_REACHED();
        break;
    case HTMLToken::DOCTYPE:
        m_shouldSkipLeadingNewline = false;
        processDoctypeToken(WTFMove(token));
        break;
    case HTMLToken::StartTag:
        m_shouldSkipLeadingNewline = false;
        processStartTag(WTFMove(token));
        break;
    case HTMLToken::EndTag:
        m_shouldSkipLeadingNewline = false;
        processEndTag(WTFMove(token));
        break;
    case HTMLToken::Comment:
        m_shouldSkipLeadingNewline = false;
        processComment(WTFMove(token));
        return;
    case HTMLToken::Character:
        processCharacter(WTFMove(token));
        break;
    case HTMLToken::EndOfFile:
        m_shouldSkipLeadingNewline = false;
        processEndOfFile(WTFMove(token));
        break;
    }
}

void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::DOCTYPE);
    if (m_insertionMode == InsertionMode::Initial) {
        m_tree.insertDoctype(WTFMove(token));
        m_insertionMode = InsertionMode::BeforeHTML;
        return;
    }
    if (m_insertionMode == InsertionMode::InTableText) {
        defaultForInTableText();
        processDoctypeToken(WTFMove(token));
        return;
    }
    parseError(token);
}

void HTMLTreeBuilder::processFakeStartTag(const QualifiedName& tagName, Vector<Attribute>&& attributes)
{
    // FIXME: We'll need a fancier conversion than just "localName" for SVG/MathML tags.
    AtomicHTMLToken fakeToken(HTMLToken::StartTag, tagName.localName(), WTFMove(attributes));
    processStartTag(WTFMove(fakeToken));
}

void HTMLTreeBuilder::processFakeEndTag(const AtomicString& tagName)
{
    AtomicHTMLToken fakeToken(HTMLToken::EndTag, tagName);
    processEndTag(WTFMove(fakeToken));
}

void HTMLTreeBuilder::processFakeEndTag(const QualifiedName& tagName)
{
    // FIXME: We'll need a fancier conversion than just "localName" for SVG/MathML tags.
    processFakeEndTag(tagName.localName());
}

void HTMLTreeBuilder::processFakeCharacters(const String& characters)
{
    ASSERT(!characters.isEmpty());
    ExternalCharacterTokenBuffer buffer(characters);
    processCharacterBuffer(buffer);
}

void HTMLTreeBuilder::processFakePEndTagIfPInButtonScope()
{
    if (!m_tree.openElements().inButtonScope(pTag->localName()))
        return;
    AtomicHTMLToken endP(HTMLToken::EndTag, pTag->localName());
    processEndTag(WTFMove(endP));
}

namespace {

bool isLi(const HTMLStackItem& item)
{
    return item.hasTagName(liTag);
}

bool isDdOrDt(const HTMLStackItem& item)
{
    return item.hasTagName(ddTag) || item.hasTagName(dtTag);
}

}

template <bool shouldClose(const HTMLStackItem&)> void HTMLTreeBuilder::processCloseWhenNestedTag(AtomicHTMLToken&& token)
{
    m_framesetOk = false;
    for (auto* nodeRecord = &m_tree.openElements().topRecord(); ; nodeRecord = nodeRecord->next()) {
        HTMLStackItem& item = nodeRecord->stackItem();
        if (shouldClose(item)) {
            ASSERT(item.isElement());
            processFakeEndTag(item.localName());
            break;
        }
        if (isSpecialNode(item) && !item.hasTagName(addressTag) && !item.hasTagName(divTag) && !item.hasTagName(pTag))
            break;
    }
    processFakePEndTagIfPInButtonScope();
    m_tree.insertHTMLElement(WTFMove(token));
}

template <typename TableQualifiedName> static HashMap<AtomicString, QualifiedName> createCaseMap(const TableQualifiedName* const names[], unsigned length)
{
    HashMap<AtomicString, QualifiedName> map;
    for (unsigned i = 0; i < length; ++i) {
        const QualifiedName& name = *names[i];
        const AtomicString& localName = name.localName();
        AtomicString loweredLocalName = localName.convertToASCIILowercase();
        if (loweredLocalName != localName)
            map.add(loweredLocalName, name);
    }
    return map;
}

static void adjustSVGTagNameCase(AtomicHTMLToken& token)
{
    static NeverDestroyed<HashMap<AtomicString, QualifiedName>> map = createCaseMap(SVGNames::getSVGTags(), SVGNames::SVGTagsCount);
    const QualifiedName& casedName = map.get().get(token.name());
    if (casedName.localName().isNull())
        return;
    token.setName(casedName.localName());
}

static inline void adjustAttributes(HashMap<AtomicString, QualifiedName>& map, AtomicHTMLToken& token)
{
    for (auto& attribute : token.attributes()) {
        const QualifiedName& casedName = map.get(attribute.localName());
        if (!casedName.localName().isNull())
            attribute.parserSetName(casedName);
    }
}

template<const QualifiedName* const* attributesTable(), unsigned attributesTableLength> static void adjustAttributes(AtomicHTMLToken& token)
{
    static NeverDestroyed<HashMap<AtomicString, QualifiedName>> map = createCaseMap(attributesTable(), attributesTableLength);
    adjustAttributes(map, token);
}

static inline void adjustSVGAttributes(AtomicHTMLToken& token)
{
    adjustAttributes<SVGNames::getSVGAttrs, SVGNames::SVGAttrsCount>(token);
}

static inline void adjustMathMLAttributes(AtomicHTMLToken& token)
{
    adjustAttributes<MathMLNames::getMathMLAttrs, MathMLNames::MathMLAttrsCount>(token);
}

static void addNamesWithPrefix(HashMap<AtomicString, QualifiedName>& map, const AtomicString& prefix, const QualifiedName* const names[], unsigned length)
{
    for (unsigned i = 0; i < length; ++i) {
        const QualifiedName& name = *names[i];
        const AtomicString& localName = name.localName();
        map.add(prefix + ':' + localName, QualifiedName(prefix, localName, name.namespaceURI()));
    }
}

static HashMap<AtomicString, QualifiedName> createForeignAttributesMap()
{
    HashMap<AtomicString, QualifiedName> map;

    AtomicString xlinkName("xlink", AtomicString::ConstructFromLiteral);
    addNamesWithPrefix(map, xlinkName, XLinkNames::getXLinkAttrs(), XLinkNames::XLinkAttrsCount);
    addNamesWithPrefix(map, xmlAtom(), XMLNames::getXMLAttrs(), XMLNames::XMLAttrsCount);

    map.add(WTF::xmlnsAtom(), XMLNSNames::xmlnsAttr);
    map.add("xmlns:xlink", QualifiedName(xmlnsAtom(), xlinkName, XMLNSNames::xmlnsNamespaceURI));

    return map;
}

static void adjustForeignAttributes(AtomicHTMLToken& token)
{
    static NeverDestroyed<HashMap<AtomicString, QualifiedName>> map = createForeignAttributesMap();
    adjustAttributes(map, token);
}

void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::StartTag);
    if (token.name() == htmlTag) {
        processHtmlStartTagForInBody(WTFMove(token));
        return;
    }
    if (token.name() == baseTag
        || token.name() == basefontTag
        || token.name() == bgsoundTag
        || token.name() == commandTag
        || token.name() == linkTag
        || token.name() == metaTag
        || token.name() == noframesTag
        || token.name() == scriptTag
        || token.name() == styleTag
        || token.name() == titleTag) {
        bool didProcess = processStartTagForInHead(WTFMove(token));
        ASSERT_UNUSED(didProcess, didProcess);
        return;
    }
    if (token.name() == bodyTag) {
        parseError(token);
        bool fragmentOrTemplateCase = !m_tree.openElements().secondElementIsHTMLBodyElement() || m_tree.openElements().hasOnlyOneElement()
            || m_tree.openElements().hasTemplateInHTMLScope();
        if (fragmentOrTemplateCase) {
            ASSERT(isParsingFragmentOrTemplateContents());
            return;
        }
        m_framesetOk = false;
        m_tree.insertHTMLBodyStartTagInBody(WTFMove(token));
        return;
    }
    if (token.name() == framesetTag) {
        parseError(token);
        if (!m_tree.openElements().secondElementIsHTMLBodyElement() || m_tree.openElements().hasOnlyOneElement()) {
            ASSERT(isParsingFragmentOrTemplateContents());
            return;
        }
        if (!m_framesetOk)
            return;
        m_tree.openElements().bodyElement().remove();
        m_tree.openElements().popUntil(m_tree.openElements().bodyElement());
        m_tree.openElements().popHTMLBodyElement();
        // Note: in the fragment case the root is a DocumentFragment instead of a proper html element which is a quirk / optimization in WebKit.
        ASSERT(!isParsingFragment() || is<DocumentFragment>(m_tree.openElements().topNode()));
        ASSERT(isParsingFragment() || &m_tree.openElements().top() == &m_tree.openElements().htmlElement());
        m_tree.insertHTMLElement(WTFMove(token));
        m_insertionMode = InsertionMode::InFrameset;
        return;
    }
    if (token.name() == addressTag
        || token.name() == articleTag
        || token.name() == asideTag
        || token.name() == blockquoteTag
        || token.name() == centerTag
        || token.name() == detailsTag
        || token.name() == dirTag
        || token.name() == divTag
        || token.name() == dlTag
        || token.name() == fieldsetTag
        || token.name() == figcaptionTag
        || token.name() == figureTag
        || token.name() == footerTag
        || token.name() == headerTag
        || token.name() == hgroupTag
        || token.name() == mainTag
        || token.name() == menuTag
        || token.name() == navTag
        || token.name() == olTag
        || token.name() == pTag
        || token.name() == sectionTag
        || token.name() == summaryTag
        || token.name() == ulTag) {
        processFakePEndTagIfPInButtonScope();
        m_tree.insertHTMLElement(WTFMove(token));
        return;
    }
    if (isNumberedHeaderTag(token.name())) {
        processFakePEndTagIfPInButtonScope();
        if (isNumberedHeaderElement(m_tree.currentStackItem())) {
            parseError(token);
            m_tree.openElements().pop();
        }
        m_tree.insertHTMLElement(WTFMove(token));
        return;
    }
    if (token.name() == preTag || token.name() == listingTag) {
        processFakePEndTagIfPInButtonScope();
        m_tree.insertHTMLElement(WTFMove(token));
        m_shouldSkipLeadingNewline = true;
        m_framesetOk = false;
        return;
    }
    if (token.name() == formTag) {
        if (m_tree.form() && !isParsingTemplateContents()) {
            parseError(token);
            return;
        }
        processFakePEndTagIfPInButtonScope();
        m_tree.insertHTMLFormElement(WTFMove(token));
        return;
    }
    if (token.name() == liTag) {
        processCloseWhenNestedTag<isLi>(WTFMove(token));
        return;
    }
    if (token.name() == ddTag || token.name() == dtTag) {
        processCloseWhenNestedTag<isDdOrDt>(WTFMove(token));
        return;
    }
    if (token.name() == plaintextTag) {
        processFakePEndTagIfPInButtonScope();
        m_tree.insertHTMLElement(WTFMove(token));
        m_parser.tokenizer().setPLAINTEXTState();
        return;
    }
    if (token.name() == buttonTag) {
        if (m_tree.openElements().inScope(buttonTag)) {
            parseError(token);
            processFakeEndTag(buttonTag);
            processStartTag(WTFMove(token)); // FIXME: Could we just fall through here?
            return;
        }
        m_tree.reconstructTheActiveFormattingElements();
        m_tree.insertHTMLElement(WTFMove(token));
        m_framesetOk = false;
        return;
    }
    if (token.name() == aTag) {
        RefPtr<Element> activeATag = m_tree.activeFormattingElements().closestElementInScopeWithName(aTag->localName());
        if (activeATag) {
            parseError(token);
            processFakeEndTag(aTag);
            m_tree.activeFormattingElements().remove(*activeATag);
            if (m_tree.openElements().contains(*activeATag))
                m_tree.openElements().remove(*activeATag);
        }
        m_tree.reconstructTheActiveFormattingElements();
        m_tree.insertFormattingElement(WTFMove(token));
        return;
    }
    if (isNonAnchorNonNobrFormattingTag(token.name())) {
        m_tree.reconstructTheActiveFormattingElements();
        m_tree.insertFormattingElement(WTFMove(token));
        return;
    }
    if (token.name() == nobrTag) {
        m_tree.reconstructTheActiveFormattingElements();
        if (m_tree.openElements().inScope(nobrTag)) {
            parseError(token);
            processFakeEndTag(nobrTag);
            m_tree.reconstructTheActiveFormattingElements();
        }
        m_tree.insertFormattingElement(WTFMove(token));
        return;
    }
    if (token.name() == appletTag || token.name() == embedTag || token.name() == objectTag) {
        if (!pluginContentIsAllowed(m_tree.parserContentPolicy()))
            return;
    }
    if (token.name() == appletTag || token.name() == marqueeTag || token.name() == objectTag) {
        m_tree.reconstructTheActiveFormattingElements();
        m_tree.insertHTMLElement(WTFMove(token));
        m_tree.activeFormattingElements().appendMarker();
        m_framesetOk = false;
        return;
    }
    if (token.name() == tableTag) {
        if (!m_tree.inQuirksMode() && m_tree.openElements().inButtonScope(pTag))
            processFakeEndTag(pTag);
        m_tree.insertHTMLElement(WTFMove(token));
        m_framesetOk = false;
        m_insertionMode = InsertionMode::InTable;
        return;
    }
    if (token.name() == imageTag) {
        parseError(token);
        // Apparently we're not supposed to ask.
        token.setName(imgTag->localName());
        // Note the fall through to the imgTag handling below!
    }
    if (token.name() == areaTag
        || token.name() == brTag
        || token.name() == embedTag
        || token.name() == imgTag
        || token.name() == keygenTag
        || token.name() == wbrTag) {
        m_tree.reconstructTheActiveFormattingElements();
        m_tree.insertSelfClosingHTMLElement(WTFMove(token));
        m_framesetOk = false;
        return;
    }
    if (token.name() == inputTag) {
        m_tree.reconstructTheActiveFormattingElements();
        auto* typeAttribute = findAttribute(token.attributes(), typeAttr);
        bool shouldClearFramesetOK = !typeAttribute || !equalLettersIgnoringASCIICase(typeAttribute->value(), "hidden");
        m_tree.insertSelfClosingHTMLElement(WTFMove(token));
        if (shouldClearFramesetOK)
            m_framesetOk = false;
        return;
    }
    if (token.name() == paramTag || token.name() == sourceTag || token.name() == trackTag) {
        m_tree.insertSelfClosingHTMLElement(WTFMove(token));
        return;
    }
    if (token.name() == hrTag) {
        processFakePEndTagIfPInButtonScope();
        m_tree.insertSelfClosingHTMLElement(WTFMove(token));
        m_framesetOk = false;
        return;
    }
    if (token.name() == textareaTag) {
        m_tree.insertHTMLElement(WTFMove(token));
        m_shouldSkipLeadingNewline = true;
        m_parser.tokenizer().setRCDATAState();
        m_originalInsertionMode = m_insertionMode;
        m_framesetOk = false;
        m_insertionMode = InsertionMode::Text;
        return;
    }
    if (token.name() == xmpTag) {
        processFakePEndTagIfPInButtonScope();
        m_tree.reconstructTheActiveFormattingElements();
        m_framesetOk = false;
        processGenericRawTextStartTag(WTFMove(token));
        return;
    }
    if (token.name() == iframeTag) {
        m_framesetOk = false;
        processGenericRawTextStartTag(WTFMove(token));
        return;
    }
    if (token.name() == noembedTag) {
        processGenericRawTextStartTag(WTFMove(token));
        return;
    }
    if (token.name() == noscriptTag && m_options.scriptEnabled) {
        processGenericRawTextStartTag(WTFMove(token));
        return;
    }
    if (token.name() == selectTag) {
        m_tree.reconstructTheActiveFormattingElements();
        m_tree.insertHTMLElement(WTFMove(token));
        m_framesetOk = false;
        if (m_insertionMode == InsertionMode::InTable
            || m_insertionMode == InsertionMode::InCaption
            || m_insertionMode == InsertionMode::InColumnGroup
            || m_insertionMode == InsertionMode::InTableBody
            || m_insertionMode == InsertionMode::InRow
            || m_insertionMode == InsertionMode::InCell)
            m_insertionMode = InsertionMode::InSelectInTable;
        else
            m_insertionMode = InsertionMode::InSelect;
        return;
    }
    if (token.name() == optgroupTag || token.name() == optionTag) {
        if (is<HTMLOptionElement>(m_tree.currentStackItem().node())) {
            AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag->localName());
            processEndTag(WTFMove(endOption));
        }
        m_tree.reconstructTheActiveFormattingElements();
        m_tree.insertHTMLElement(WTFMove(token));
        return;
    }
    if (token.name() == rbTag || token.name() == rtcTag) {
        if (m_tree.openElements().inScope(rubyTag->localName())) {
            m_tree.generateImpliedEndTags();
            if (!m_tree.currentStackItem().hasTagName(rubyTag))
                parseError(token);
        }
        m_tree.insertHTMLElement(WTFMove(token));
        return;
    }
    if (token.name() == rtTag || token.name() == rpTag) {
        if (m_tree.openElements().inScope(rubyTag->localName())) {
            m_tree.generateImpliedEndTagsWithExclusion(rtcTag->localName());
            if (!m_tree.currentStackItem().hasTagName(rubyTag) && !m_tree.currentStackItem().hasTagName(rtcTag))
                parseError(token);
        }
        m_tree.insertHTMLElement(WTFMove(token));
        return;
    }
    if (token.name() == MathMLNames::mathTag->localName()) {
        m_tree.reconstructTheActiveFormattingElements();
        adjustMathMLAttributes(token);
        adjustForeignAttributes(token);
        m_tree.insertForeignElement(WTFMove(token), MathMLNames::mathmlNamespaceURI);
        return;
    }
    if (token.name() == SVGNames::svgTag->localName()) {
        m_tree.reconstructTheActiveFormattingElements();
        adjustSVGAttributes(token);
        adjustForeignAttributes(token);
        m_tree.insertForeignElement(WTFMove(token), SVGNames::svgNamespaceURI);
        return;
    }
    if (isCaptionColOrColgroupTag(token.name())
        || token.name() == frameTag
        || token.name() == headTag
        || isTableBodyContextTag(token.name())
        || isTableCellContextTag(token.name())
        || token.name() == trTag) {
        parseError(token);
        return;
    }
    if (token.name() == templateTag) {
        m_framesetOk = false;
        processTemplateStartTag(WTFMove(token));
        return;
    }
    m_tree.reconstructTheActiveFormattingElements();
    insertGenericHTMLElement(WTFMove(token));
}

inline void HTMLTreeBuilder::insertGenericHTMLElement(AtomicHTMLToken&& token)
{
    m_customElementToConstruct = m_tree.insertHTMLElementOrFindCustomElementInterface(WTFMove(token));
}

void HTMLTreeBuilder::didCreateCustomOrFallbackElement(Ref<Element>&& element, CustomElementConstructionData& data)
{
    m_tree.insertCustomElement(WTFMove(element), data.name, WTFMove(data.attributes));
}

void HTMLTreeBuilder::processTemplateStartTag(AtomicHTMLToken&& token)
{
    m_tree.activeFormattingElements().appendMarker();
    m_tree.insertHTMLElement(WTFMove(token));
    m_templateInsertionModes.append(InsertionMode::TemplateContents);
    m_insertionMode = InsertionMode::TemplateContents;
}

bool HTMLTreeBuilder::processTemplateEndTag(AtomicHTMLToken&& token)
{
    ASSERT(token.name() == templateTag->localName());
    if (!m_tree.openElements().hasTemplateInHTMLScope()) {
        ASSERT(m_templateInsertionModes.isEmpty() || (m_templateInsertionModes.size() == 1 && m_fragmentContext.contextElement().hasTagName(templateTag)));
        parseError(token);
        return false;
    }
    m_tree.generateImpliedEndTags();
    if (!m_tree.currentStackItem().hasTagName(templateTag))
        parseError(token);
    m_tree.openElements().popUntilPopped(templateTag);
    m_tree.activeFormattingElements().clearToLastMarker();
    m_templateInsertionModes.removeLast();
    resetInsertionModeAppropriately();
    return true;
}

bool HTMLTreeBuilder::processEndOfFileForInTemplateContents(AtomicHTMLToken&& token)
{
    AtomicHTMLToken endTemplate(HTMLToken::EndTag, templateTag->localName());
    if (!processTemplateEndTag(WTFMove(endTemplate)))
        return false;

    processEndOfFile(WTFMove(token));
    return true;
}

bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup()
{
    bool ignoreFakeEndTag = m_tree.currentIsRootNode() || m_tree.currentNode().hasTagName(templateTag);

    if (ignoreFakeEndTag) {
        ASSERT(isParsingFragmentOrTemplateContents());
        // FIXME: parse error
        return false;
    }
    m_tree.openElements().pop();
    m_insertionMode = InsertionMode::InTable;
    return true;
}

// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#close-the-cell
void HTMLTreeBuilder::closeTheCell()
{
    ASSERT(m_insertionMode == InsertionMode::InCell);
    if (m_tree.openElements().inTableScope(tdTag)) {
        ASSERT(!m_tree.openElements().inTableScope(thTag));
        processFakeEndTag(tdTag);
        return;
    }
    ASSERT(m_tree.openElements().inTableScope(thTag));
    processFakeEndTag(thTag);
    ASSERT(m_insertionMode == InsertionMode::InRow);
}

void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::StartTag);
    if (token.name() == captionTag) {
        m_tree.openElements().popUntilTableScopeMarker();
        m_tree.activeFormattingElements().appendMarker();
        m_tree.insertHTMLElement(WTFMove(token));
        m_insertionMode = InsertionMode::InCaption;
        return;
    }
    if (token.name() == colgroupTag) {
        m_tree.openElements().popUntilTableScopeMarker();
        m_tree.insertHTMLElement(WTFMove(token));
        m_insertionMode = InsertionMode::InColumnGroup;
        return;
    }
    if (token.name() == colTag) {
        processFakeStartTag(colgroupTag);
        ASSERT(m_insertionMode == InsertionMode::InColumnGroup);
        processStartTag(WTFMove(token));
        return;
    }
    if (isTableBodyContextTag(token.name())) {
        m_tree.openElements().popUntilTableScopeMarker();
        m_tree.insertHTMLElement(WTFMove(token));
        m_insertionMode = InsertionMode::InTableBody;
        return;
    }
    if (isTableCellContextTag(token.name()) || token.name() == trTag) {
        processFakeStartTag(tbodyTag);
        ASSERT(m_insertionMode == InsertionMode::InTableBody);
        processStartTag(WTFMove(token));
        return;
    }
    if (token.name() == tableTag) {
        parseError(token);
        if (!processTableEndTagForInTable()) {
            ASSERT(isParsingFragmentOrTemplateContents());
            return;
        }
        processStartTag(WTFMove(token));
        return;
    }
    if (token.name() == styleTag || token.name() == scriptTag) {
        processStartTagForInHead(WTFMove(token));
        return;
    }
    if (token.name() == inputTag) {
        auto* typeAttribute = findAttribute(token.attributes(), typeAttr);
        if (typeAttribute && equalLettersIgnoringASCIICase(typeAttribute->value(), "hidden")) {
            parseError(token);
            m_tree.insertSelfClosingHTMLElement(WTFMove(token));
            return;
        }
        // Fall through to "anything else" case.
    }
    if (token.name() == formTag) {
        parseError(token);
        if (m_tree.form() && !isParsingTemplateContents())
            return;
        m_tree.insertHTMLFormElement(WTFMove(token), true);
        m_tree.openElements().pop();
        return;
    }
    if (token.name() == templateTag) {
        processTemplateStartTag(WTFMove(token));
        return;
    }
    parseError(token);
    HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
    processStartTagForInBody(WTFMove(token));
}

void HTMLTreeBuilder::processStartTag(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::StartTag);
    switch (m_insertionMode) {
    case InsertionMode::Initial:
        defaultForInitial();
        ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
        FALLTHROUGH;
    case InsertionMode::BeforeHTML:
        if (token.name() == htmlTag) {
            m_tree.insertHTMLHtmlStartTagBeforeHTML(WTFMove(token));
            m_insertionMode = InsertionMode::BeforeHead;
            return;
        }
        defaultForBeforeHTML();
        ASSERT(m_insertionMode == InsertionMode::BeforeHead);
        FALLTHROUGH;
    case InsertionMode::BeforeHead:
        if (token.name() == htmlTag) {
            processHtmlStartTagForInBody(WTFMove(token));
            return;
        }
        if (token.name() == headTag) {
            m_tree.insertHTMLHeadElement(WTFMove(token));
            m_insertionMode = InsertionMode::InHead;
            return;
        }
        defaultForBeforeHead();
        ASSERT(m_insertionMode == InsertionMode::InHead);
        FALLTHROUGH;
    case InsertionMode::InHead:
        if (processStartTagForInHead(WTFMove(token)))
            return;
        defaultForInHead();
        ASSERT(m_insertionMode == InsertionMode::AfterHead);
        FALLTHROUGH;
    case InsertionMode::AfterHead:
        if (token.name() == htmlTag) {
            processHtmlStartTagForInBody(WTFMove(token));
            return;
        }
        if (token.name() == bodyTag) {
            m_framesetOk = false;
            m_tree.insertHTMLBodyElement(WTFMove(token));
            m_insertionMode = InsertionMode::InBody;
            return;
        }
        if (token.name() == framesetTag) {
            m_tree.insertHTMLElement(WTFMove(token));
            m_insertionMode = InsertionMode::InFrameset;
            return;
        }
        if (token.name() == baseTag
            || token.name() == basefontTag
            || token.name() == bgsoundTag
            || token.name() == linkTag
            || token.name() == metaTag
            || token.name() == noframesTag
            || token.name() == scriptTag
            || token.name() == styleTag
            || token.name() == templateTag
            || token.name() == titleTag) {
            parseError(token);
            ASSERT(m_tree.headStackItem());
            m_tree.openElements().pushHTMLHeadElement(*m_tree.headStackItem());
            processStartTagForInHead(WTFMove(token));
            m_tree.openElements().removeHTMLHeadElement(m_tree.head());
            return;
        }
        if (token.name() == headTag) {
            parseError(token);
            return;
        }
        defaultForAfterHead();
        ASSERT(m_insertionMode == InsertionMode::InBody);
        FALLTHROUGH;
    case InsertionMode::InBody:
        processStartTagForInBody(WTFMove(token));
        break;
    case InsertionMode::InTable:
        processStartTagForInTable(WTFMove(token));
        break;
    case InsertionMode::InCaption:
        if (isCaptionColOrColgroupTag(token.name())
            || isTableBodyContextTag(token.name())
            || isTableCellContextTag(token.name())
            || token.name() == trTag) {
            parseError(token);
            if (!processCaptionEndTagForInCaption()) {
                ASSERT(isParsingFragment());
                return;
            }
            processStartTag(WTFMove(token));
            return;
        }
        processStartTagForInBody(WTFMove(token));
        break;
    case InsertionMode::InColumnGroup:
        if (token.name() == htmlTag) {
            processHtmlStartTagForInBody(WTFMove(token));
            return;
        }
        if (token.name() == colTag) {
            m_tree.insertSelfClosingHTMLElement(WTFMove(token));
            return;
        }
        if (token.name() == templateTag) {
            processTemplateStartTag(WTFMove(token));
            return;
        }
        if (!processColgroupEndTagForInColumnGroup()) {
            ASSERT(isParsingFragmentOrTemplateContents());
            return;
        }
        processStartTag(WTFMove(token));
        break;
    case InsertionMode::InTableBody:
        if (token.name() == trTag) {
            m_tree.openElements().popUntilTableBodyScopeMarker(); // How is there ever anything to pop?
            m_tree.insertHTMLElement(WTFMove(token));
            m_insertionMode = InsertionMode::InRow;
            return;
        }
        if (isTableCellContextTag(token.name())) {
            parseError(token);
            processFakeStartTag(trTag);
            ASSERT(m_insertionMode == InsertionMode::InRow);
            processStartTag(WTFMove(token));
            return;
        }
        if (isCaptionColOrColgroupTag(token.name()) || isTableBodyContextTag(token.name())) {
            // FIXME: This is slow.
            if (!m_tree.openElements().inTableScope(tbodyTag) && !m_tree.openElements().inTableScope(theadTag) && !m_tree.openElements().inTableScope(tfootTag)) {
                ASSERT(isParsingFragmentOrTemplateContents());
                parseError(token);
                return;
            }
            m_tree.openElements().popUntilTableBodyScopeMarker();
            ASSERT(isTableBodyContextTag(m_tree.currentStackItem().localName()));
            processFakeEndTag(m_tree.currentStackItem().localName());
            processStartTag(WTFMove(token));
            return;
        }
        processStartTagForInTable(WTFMove(token));
        break;
    case InsertionMode::InRow:
        if (isTableCellContextTag(token.name())) {
            m_tree.openElements().popUntilTableRowScopeMarker();
            m_tree.insertHTMLElement(WTFMove(token));
            m_insertionMode = InsertionMode::InCell;
            m_tree.activeFormattingElements().appendMarker();
            return;
        }
        if (token.name() == trTag
            || isCaptionColOrColgroupTag(token.name())
            || isTableBodyContextTag(token.name())) {
            if (!processTrEndTagForInRow()) {
                ASSERT(isParsingFragmentOrTemplateContents());
                return;
            }
            ASSERT(m_insertionMode == InsertionMode::InTableBody);
            processStartTag(WTFMove(token));
            return;
        }
        processStartTagForInTable(WTFMove(token));
        break;
    case InsertionMode::InCell:
        if (isCaptionColOrColgroupTag(token.name())
            || isTableCellContextTag(token.name())
            || token.name() == trTag
            || isTableBodyContextTag(token.name())) {
            // FIXME: This could be more efficient.
            if (!m_tree.openElements().inTableScope(tdTag) && !m_tree.openElements().inTableScope(thTag)) {
                ASSERT(isParsingFragment());
                parseError(token);
                return;
            }
            closeTheCell();
            processStartTag(WTFMove(token));
            return;
        }
        processStartTagForInBody(WTFMove(token));
        break;
    case InsertionMode::AfterBody:
    case InsertionMode::AfterAfterBody:
        if (token.name() == htmlTag) {
            processHtmlStartTagForInBody(WTFMove(token));
            return;
        }
        m_insertionMode = InsertionMode::InBody;
        processStartTag(WTFMove(token));
        break;
    case InsertionMode::InHeadNoscript:
        if (token.name() == htmlTag) {
            processHtmlStartTagForInBody(WTFMove(token));
            return;
        }
        if (token.name() == basefontTag
            || token.name() == bgsoundTag
            || token.name() == linkTag
            || token.name() == metaTag
            || token.name() == noframesTag
            || token.name() == styleTag) {
            bool didProcess = processStartTagForInHead(WTFMove(token));
            ASSERT_UNUSED(didProcess, didProcess);
            return;
        }
        if (token.name() == htmlTag || token.name() == noscriptTag) {
            parseError(token);
            return;
        }
        defaultForInHeadNoscript();
        processToken(WTFMove(token));
        break;
    case InsertionMode::InFrameset:
        if (token.name() == htmlTag) {
            processHtmlStartTagForInBody(WTFMove(token));
            return;
        }
        if (token.name() == framesetTag) {
            m_tree.insertHTMLElement(WTFMove(token));
            return;
        }
        if (token.name() == frameTag) {
            m_tree.insertSelfClosingHTMLElement(WTFMove(token));
            return;
        }
        if (token.name() == noframesTag) {
            processStartTagForInHead(WTFMove(token));
            return;
        }
        parseError(token);
        break;
    case InsertionMode::AfterFrameset:
    case InsertionMode::AfterAfterFrameset:
        if (token.name() == htmlTag) {
            processHtmlStartTagForInBody(WTFMove(token));
            return;
        }
        if (token.name() == noframesTag) {
            processStartTagForInHead(WTFMove(token));
            return;
        }
        parseError(token);
        break;
    case InsertionMode::InSelectInTable:
        if (token.name() == captionTag
            || token.name() == tableTag
            || isTableBodyContextTag(token.name())
            || token.name() == trTag
            || isTableCellContextTag(token.name())) {
            parseError(token);
            AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag->localName());
            processEndTag(WTFMove(endSelect));
            processStartTag(WTFMove(token));
            return;
        }
        FALLTHROUGH;
    case InsertionMode::InSelect:
        if (token.name() == htmlTag) {
            processHtmlStartTagForInBody(WTFMove(token));
            return;
        }
        if (token.name() == optionTag) {
            if (is<HTMLOptionElement>(m_tree.currentStackItem().node())) {
                AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag->localName());
                processEndTag(WTFMove(endOption));
            }
            m_tree.insertHTMLElement(WTFMove(token));
            return;
        }
        if (token.name() == optgroupTag) {
            if (is<HTMLOptionElement>(m_tree.currentStackItem().node())) {
                AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag->localName());
                processEndTag(WTFMove(endOption));
            }
            if (is<HTMLOptGroupElement>(m_tree.currentStackItem().node())) {
                AtomicHTMLToken endOptgroup(HTMLToken::EndTag, optgroupTag->localName());
                processEndTag(WTFMove(endOptgroup));
            }
            m_tree.insertHTMLElement(WTFMove(token));
            return;
        }
        if (token.name() == selectTag) {
            parseError(token);
            AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag->localName());
            processEndTag(WTFMove(endSelect));
            return;
        }
        if (token.name() == inputTag || token.name() == keygenTag || token.name() == textareaTag) {
            parseError(token);
            if (!m_tree.openElements().inSelectScope(selectTag)) {
                ASSERT(isParsingFragment());
                return;
            }
            AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag->localName());
            processEndTag(WTFMove(endSelect));
            processStartTag(WTFMove(token));
            return;
        }
        if (token.name() == scriptTag) {
            bool didProcess = processStartTagForInHead(WTFMove(token));
            ASSERT_UNUSED(didProcess, didProcess);
            return;
        }
        if (token.name() == templateTag) {
            processTemplateStartTag(WTFMove(token));
            return;
        }
        break;
    case InsertionMode::InTableText:
        defaultForInTableText();
        processStartTag(WTFMove(token));
        break;
    case InsertionMode::Text:
        ASSERT_NOT_REACHED();
        break;
    case InsertionMode::TemplateContents:
        if (token.name() == templateTag) {
            processTemplateStartTag(WTFMove(token));
            return;
        }

        if (token.name() == linkTag
            || token.name() == scriptTag
            || token.name() == styleTag
            || token.name() == metaTag) {
            processStartTagForInHead(WTFMove(token));
            return;
        }

        InsertionMode insertionMode = InsertionMode::TemplateContents;
        if (token.name() == colTag)
            insertionMode = InsertionMode::InColumnGroup;
        else if (isCaptionColOrColgroupTag(token.name()) || isTableBodyContextTag(token.name()))
            insertionMode = InsertionMode::InTable;
        else if (token.name() == trTag)
            insertionMode = InsertionMode::InTableBody;
        else if (isTableCellContextTag(token.name()))
            insertionMode = InsertionMode::InRow;
        else
            insertionMode = InsertionMode::InBody;

        ASSERT(insertionMode != InsertionMode::TemplateContents);
        ASSERT(m_templateInsertionModes.last() == InsertionMode::TemplateContents);
        m_templateInsertionModes.last() = insertionMode;
        m_insertionMode = insertionMode;

        processStartTag(WTFMove(token));
        break;
    }
}

void HTMLTreeBuilder::processHtmlStartTagForInBody(AtomicHTMLToken&& token)
{
    parseError(token);
    if (m_tree.openElements().hasTemplateInHTMLScope()) {
        ASSERT(isParsingTemplateContents());
        return;
    }
    m_tree.insertHTMLHtmlStartTagInBody(WTFMove(token));
}

bool HTMLTreeBuilder::processBodyEndTagForInBody(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::EndTag);
    ASSERT(token.name() == bodyTag);
    if (!m_tree.openElements().inScope(bodyTag->localName())) {
        parseError(token);
        return false;
    }
    notImplemented(); // Emit a more specific parse error based on stack contents.
    m_insertionMode = InsertionMode::AfterBody;
    return true;
}

void HTMLTreeBuilder::processAnyOtherEndTagForInBody(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::EndTag);
    for (auto* record = &m_tree.openElements().topRecord(); ; record = record->next()) {
        HTMLStackItem& item = record->stackItem();
        if (item.matchesHTMLTag(token.name())) {
            m_tree.generateImpliedEndTagsWithExclusion(token.name());
            if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
                parseError(token);
            m_tree.openElements().popUntilPopped(item.element());
            return;
        }
        if (isSpecialNode(item)) {
            parseError(token);
            return;
        }
    }
}

// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-inbody
void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken& token)
{
    // The adoption agency algorithm is N^2. We limit the number of iterations
    // to stop from hanging the whole browser. This limit is specified in the
    // adoption agency algorithm: 
    // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#parsing-main-inbody
    static const int outerIterationLimit = 8;
    static const int innerIterationLimit = 3;

    // 1, 2, 3 and 16 are covered by the for() loop.
    for (int i = 0; i < outerIterationLimit; ++i) {
        // 4.
        RefPtr<Element> formattingElement = m_tree.activeFormattingElements().closestElementInScopeWithName(token.name());
        // 4.a
        if (!formattingElement)
            return processAnyOtherEndTagForInBody(WTFMove(token));
        // 4.c
        if ((m_tree.openElements().contains(*formattingElement)) && !m_tree.openElements().inScope(*formattingElement)) {
            parseError(token);
            notImplemented(); // Check the stack of open elements for a more specific parse error.
            return;
        }
        // 4.b
        auto* formattingElementRecord = m_tree.openElements().find(*formattingElement);
        if (!formattingElementRecord) {
            parseError(token);
            m_tree.activeFormattingElements().remove(*formattingElement);
            return;
        }
        // 4.d
        if (formattingElement != &m_tree.currentElement())
            parseError(token);
        // 5.
        auto* furthestBlock = m_tree.openElements().furthestBlockForFormattingElement(*formattingElement);
        // 6.
        if (!furthestBlock) {
            m_tree.openElements().popUntilPopped(*formattingElement);
            m_tree.activeFormattingElements().remove(*formattingElement);
            return;
        }
        // 7.
        ASSERT(furthestBlock->isAbove(*formattingElementRecord));
        Ref<HTMLStackItem> commonAncestor = formattingElementRecord->next()->stackItem();
        // 8.
        HTMLFormattingElementList::Bookmark bookmark = m_tree.activeFormattingElements().bookmarkFor(*formattingElement);
        // 9.
        auto* node = furthestBlock;
        auto* nextNode = node->next();
        auto* lastNode = furthestBlock;
        // 9.1, 9.2, 9.3 and 9.11 are covered by the for() loop.
        for (int i = 0; i < innerIterationLimit; ++i) {
            // 9.4
            node = nextNode;
            ASSERT(node);
            nextNode = node->next(); // Save node->next() for the next iteration in case node is deleted in 9.5.
            // 9.5
            if (!m_tree.activeFormattingElements().contains(node->element())) {
                m_tree.openElements().remove(node->element());
                node = 0;
                continue;
            }
            // 9.6
            if (node == formattingElementRecord)
                break;
            // 9.7
            auto newItem = m_tree.createElementFromSavedToken(node->stackItem());

            HTMLFormattingElementList::Entry* nodeEntry = m_tree.activeFormattingElements().find(node->element());
            nodeEntry->replaceElement(newItem.copyRef());
            node->replaceElement(WTFMove(newItem));

            // 9.8
            if (lastNode == furthestBlock)
                bookmark.moveToAfter(*nodeEntry);
            // 9.9
            m_tree.reparent(*node, *lastNode);
            // 9.10
            lastNode = node;
        }
        // 10.
        m_tree.insertAlreadyParsedChild(commonAncestor.get(), *lastNode);
        // 11.
        auto newItem = m_tree.createElementFromSavedToken(formattingElementRecord->stackItem());
        // 12. & 13.
        m_tree.takeAllChildrenAndReparent(newItem, *furthestBlock);
        // 14.
        m_tree.activeFormattingElements().swapTo(*formattingElement, newItem.copyRef(), bookmark);
        // 15.
        m_tree.openElements().remove(*formattingElement);
        m_tree.openElements().insertAbove(WTFMove(newItem), *furthestBlock);
    }
}

void HTMLTreeBuilder::resetInsertionModeAppropriately()
{
    // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#reset-the-insertion-mode-appropriately
    bool last = false;
    for (auto* record = &m_tree.openElements().topRecord(); ; record = record->next()) {
        RefPtr<HTMLStackItem> item = &record->stackItem();
        if (&item->node() == &m_tree.openElements().rootNode()) {
            last = true;
            bool shouldCreateItem = isParsingFragment();
            if (shouldCreateItem)
                item = &m_fragmentContext.contextElementStackItem();
        }

        if (item->hasTagName(templateTag)) {
            m_insertionMode = m_templateInsertionModes.last();
            return;
        }

        if (item->hasTagName(selectTag)) {
            if (!last) {
                while (&item->node() != &m_tree.openElements().rootNode() && !item->hasTagName(templateTag)) {
                    record = record->next();
                    item = &record->stackItem();
                    if (is<HTMLTableElement>(item->node())) {
                        m_insertionMode = InsertionMode::InSelectInTable;
                        return;
                    }
                }
            }
            m_insertionMode = InsertionMode::InSelect;
            return;
        }
        if (item->hasTagName(tdTag) || item->hasTagName(thTag)) {
            m_insertionMode = InsertionMode::InCell;
            return;
        }
        if (item->hasTagName(trTag)) {
            m_insertionMode = InsertionMode::InRow;
            return;
        }
        if (item->hasTagName(tbodyTag) || item->hasTagName(theadTag) || item->hasTagName(tfootTag)) {
            m_insertionMode = InsertionMode::InTableBody;
            return;
        }
        if (item->hasTagName(captionTag)) {
            m_insertionMode = InsertionMode::InCaption;
            return;
        }
        if (item->hasTagName(colgroupTag)) {
            m_insertionMode = InsertionMode::InColumnGroup;
            return;
        }
        if (is<HTMLTableElement>(item->node())) {
            m_insertionMode = InsertionMode::InTable;
            return;
        }
        if (item->hasTagName(headTag)) {
            if (!m_fragmentContext.fragment() || &m_fragmentContext.contextElement() != &item->node()) {
                m_insertionMode = InsertionMode::InHead;
                return;
            }
            m_insertionMode = InsertionMode::InBody;
            return;
        }
        if (item->hasTagName(bodyTag)) {
            m_insertionMode = InsertionMode::InBody;
            return;
        }
        if (item->hasTagName(framesetTag)) {
            m_insertionMode = InsertionMode::InFrameset;
            return;
        }
        if (item->hasTagName(htmlTag)) {
            if (m_tree.headStackItem()) {
                m_insertionMode = InsertionMode::AfterHead;
                return;
            }
            ASSERT(isParsingFragment());
            m_insertionMode = InsertionMode::BeforeHead;
            return;
        }
        if (last) {
            ASSERT(isParsingFragment());
            m_insertionMode = InsertionMode::InBody;
            return;
        }
    }
}

void HTMLTreeBuilder::processEndTagForInTableBody(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::EndTag);
    if (isTableBodyContextTag(token.name())) {
        if (!m_tree.openElements().inTableScope(token.name())) {
            parseError(token);
            return;
        }
        m_tree.openElements().popUntilTableBodyScopeMarker();
        m_tree.openElements().pop();
        m_insertionMode = InsertionMode::InTable;
        return;
    }
    if (token.name() == tableTag) {
        // FIXME: This is slow.
        if (!m_tree.openElements().inTableScope(tbodyTag) && !m_tree.openElements().inTableScope(theadTag) && !m_tree.openElements().inTableScope(tfootTag)) {
            ASSERT(isParsingFragmentOrTemplateContents());
            parseError(token);
            return;
        }
        m_tree.openElements().popUntilTableBodyScopeMarker();
        ASSERT(isTableBodyContextTag(m_tree.currentStackItem().localName()));
        processFakeEndTag(m_tree.currentStackItem().localName());
        processEndTag(WTFMove(token));
        return;
    }
    if (token.name() == bodyTag
        || isCaptionColOrColgroupTag(token.name())
        || token.name() == htmlTag
        || isTableCellContextTag(token.name())
        || token.name() == trTag) {
        parseError(token);
        return;
    }
    processEndTagForInTable(WTFMove(token));
}

void HTMLTreeBuilder::processEndTagForInRow(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::EndTag);
    if (token.name() == trTag) {
        processTrEndTagForInRow();
        return;
    }
    if (token.name() == tableTag) {
        if (!processTrEndTagForInRow()) {
            ASSERT(isParsingFragmentOrTemplateContents());
            return;
        }
        ASSERT(m_insertionMode == InsertionMode::InTableBody);
        processEndTag(WTFMove(token));
        return;
    }
    if (isTableBodyContextTag(token.name())) {
        if (!m_tree.openElements().inTableScope(token.name())) {
            parseError(token);
            return;
        }
        processFakeEndTag(trTag);
        ASSERT(m_insertionMode == InsertionMode::InTableBody);
        processEndTag(WTFMove(token));
        return;
    }
    if (token.name() == bodyTag
        || isCaptionColOrColgroupTag(token.name())
        || token.name() == htmlTag
        || isTableCellContextTag(token.name())) {
        parseError(token);
        return;
    }
    processEndTagForInTable(WTFMove(token));
}

void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::EndTag);
    if (isTableCellContextTag(token.name())) {
        if (!m_tree.openElements().inTableScope(token.name())) {
            parseError(token);
            return;
        }
        m_tree.generateImpliedEndTags();
        if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
            parseError(token);
        m_tree.openElements().popUntilPopped(token.name());
        m_tree.activeFormattingElements().clearToLastMarker();
        m_insertionMode = InsertionMode::InRow;
        return;
    }
    if (token.name() == bodyTag
        || isCaptionColOrColgroupTag(token.name())
        || token.name() == htmlTag) {
        parseError(token);
        return;
    }
    if (token.name() == tableTag
        || token.name() == trTag
        || isTableBodyContextTag(token.name())) {
        if (!m_tree.openElements().inTableScope(token.name())) {
            ASSERT(isTableBodyContextTag(token.name()) || m_tree.openElements().inTableScope(templateTag) || isParsingFragment());
            parseError(token);
            return;
        }
        closeTheCell();
        processEndTag(WTFMove(token));
        return;
    }
    processEndTagForInBody(WTFMove(token));
}

void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::EndTag);
    if (token.name() == bodyTag) {
        processBodyEndTagForInBody(WTFMove(token));
        return;
    }
    if (token.name() == htmlTag) {
        AtomicHTMLToken endBody(HTMLToken::EndTag, bodyTag->localName());
        if (processBodyEndTagForInBody(WTFMove(endBody)))
            processEndTag(WTFMove(token));
        return;
    }
    if (token.name() == addressTag
        || token.name() == articleTag
        || token.name() == asideTag
        || token.name() == blockquoteTag
        || token.name() == buttonTag
        || token.name() == centerTag
        || token.name() == detailsTag
        || token.name() == dirTag
        || token.name() == divTag
        || token.name() == dlTag
        || token.name() == fieldsetTag
        || token.name() == figcaptionTag
        || token.name() == figureTag
        || token.name() == footerTag
        || token.name() == headerTag
        || token.name() == hgroupTag
        || token.name() == listingTag
        || token.name() == mainTag
        || token.name() == menuTag
        || token.name() == navTag
        || token.name() == olTag
        || token.name() == preTag
        || token.name() == sectionTag
        || token.name() == summaryTag
        || token.name() == ulTag) {
        if (!m_tree.openElements().inScope(token.name())) {
            parseError(token);
            return;
        }
        m_tree.generateImpliedEndTags();
        if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
            parseError(token);
        m_tree.openElements().popUntilPopped(token.name());
        return;
    }
    if (token.name() == formTag) {
        if (!isParsingTemplateContents()) {
            RefPtr<Element> formElement = m_tree.takeForm();
            if (!formElement || !m_tree.openElements().inScope(*formElement)) {
                parseError(token);
                return;
            }
            m_tree.generateImpliedEndTags();
            if (&m_tree.currentNode() != formElement.get())
                parseError(token);
            m_tree.openElements().remove(*formElement);
        } else {
            if (!m_tree.openElements().inScope(token.name())) {
                parseError(token);
                return;
            }
            m_tree.generateImpliedEndTags();
            if (!m_tree.currentNode().hasTagName(formTag))
                parseError(token);
            m_tree.openElements().popUntilPopped(token.name());
        }
    }
    if (token.name() == pTag) {
        if (!m_tree.openElements().inButtonScope(token.name())) {
            parseError(token);
            processFakeStartTag(pTag);
            ASSERT(m_tree.openElements().inScope(token.name()));
            processEndTag(WTFMove(token));
            return;
        }
        m_tree.generateImpliedEndTagsWithExclusion(token.name());
        if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
            parseError(token);
        m_tree.openElements().popUntilPopped(token.name());
        return;
    }
    if (token.name() == liTag) {
        if (!m_tree.openElements().inListItemScope(token.name())) {
            parseError(token);
            return;
        }
        m_tree.generateImpliedEndTagsWithExclusion(token.name());
        if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
            parseError(token);
        m_tree.openElements().popUntilPopped(token.name());
        return;
    }
    if (token.name() == ddTag || token.name() == dtTag) {
        if (!m_tree.openElements().inScope(token.name())) {
            parseError(token);
            return;
        }
        m_tree.generateImpliedEndTagsWithExclusion(token.name());
        if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
            parseError(token);
        m_tree.openElements().popUntilPopped(token.name());
        return;
    }
    if (isNumberedHeaderTag(token.name())) {
        if (!m_tree.openElements().hasNumberedHeaderElementInScope()) {
            parseError(token);
            return;
        }
        m_tree.generateImpliedEndTags();
        if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
            parseError(token);
        m_tree.openElements().popUntilNumberedHeaderElementPopped();
        return;
    }
    if (HTMLConstructionSite::isFormattingTag(token.name())) {
        callTheAdoptionAgency(token);
        return;
    }
    if (token.name() == appletTag || token.name() == marqueeTag || token.name() == objectTag) {
        if (!m_tree.openElements().inScope(token.name())) {
            parseError(token);
            return;
        }
        m_tree.generateImpliedEndTags();
        if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
            parseError(token);
        m_tree.openElements().popUntilPopped(token.name());
        m_tree.activeFormattingElements().clearToLastMarker();
        return;
    }
    if (token.name() == brTag) {
        parseError(token);
        processFakeStartTag(brTag);
        return;
    }
    if (token.name() == templateTag) {
        processTemplateEndTag(WTFMove(token));
        return;
    }
    processAnyOtherEndTagForInBody(WTFMove(token));
}

bool HTMLTreeBuilder::processCaptionEndTagForInCaption()
{
    if (!m_tree.openElements().inTableScope(captionTag->localName())) {
        ASSERT(isParsingFragment());
        // FIXME: parse error
        return false;
    }
    m_tree.generateImpliedEndTags();
    // FIXME: parse error if (!m_tree.currentStackItem().hasTagName(captionTag))
    m_tree.openElements().popUntilPopped(captionTag->localName());
    m_tree.activeFormattingElements().clearToLastMarker();
    m_insertionMode = InsertionMode::InTable;
    return true;
}

bool HTMLTreeBuilder::processTrEndTagForInRow()
{
    if (!m_tree.openElements().inTableScope(trTag)) {
        ASSERT(isParsingFragmentOrTemplateContents());
        // FIXME: parse error
        return false;
    }
    m_tree.openElements().popUntilTableRowScopeMarker();
    ASSERT(m_tree.currentStackItem().hasTagName(trTag));
    m_tree.openElements().pop();
    m_insertionMode = InsertionMode::InTableBody;
    return true;
}

bool HTMLTreeBuilder::processTableEndTagForInTable()
{
    if (!m_tree.openElements().inTableScope(tableTag)) {
        ASSERT(isParsingFragmentOrTemplateContents());
        // FIXME: parse error.
        return false;
    }
    m_tree.openElements().popUntilPopped(tableTag->localName());
    resetInsertionModeAppropriately();
    return true;
}

void HTMLTreeBuilder::processEndTagForInTable(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::EndTag);
    if (token.name() == tableTag) {
        processTableEndTagForInTable();
        return;
    }
    if (token.name() == bodyTag
        || isCaptionColOrColgroupTag(token.name())
        || token.name() == htmlTag
        || isTableBodyContextTag(token.name())
        || isTableCellContextTag(token.name())
        || token.name() == trTag) {
        parseError(token);
        return;
    }
    parseError(token);
    // Is this redirection necessary here?
    HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
    processEndTagForInBody(WTFMove(token));
}

void HTMLTreeBuilder::processEndTag(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::EndTag);
    switch (m_insertionMode) {
    case InsertionMode::Initial:
        defaultForInitial();
        ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
        FALLTHROUGH;
    case InsertionMode::BeforeHTML:
        if (token.name() != headTag && token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
            parseError(token);
            return;
        }
        defaultForBeforeHTML();
        ASSERT(m_insertionMode == InsertionMode::BeforeHead);
        FALLTHROUGH;
    case InsertionMode::BeforeHead:
        if (token.name() != headTag && token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
            parseError(token);
            return;
        }
        defaultForBeforeHead();
        ASSERT(m_insertionMode == InsertionMode::InHead);
        FALLTHROUGH;
    case InsertionMode::InHead:
        // FIXME: This case should be broken out into processEndTagForInHead,
        // because other end tag cases now refer to it ("process the token for using the rules of the "in head" insertion mode").
        // but because the logic falls through to InsertionMode::AfterHead, that gets a little messy.
        if (token.name() == templateTag) {
            processTemplateEndTag(WTFMove(token));
            return;
        }
        if (token.name() == headTag) {
            m_tree.openElements().popHTMLHeadElement();
            m_insertionMode = InsertionMode::AfterHead;
            return;
        }
        if (token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
            parseError(token);
            return;
        }
        defaultForInHead();
        ASSERT(m_insertionMode == InsertionMode::AfterHead);
        FALLTHROUGH;
    case InsertionMode::AfterHead:
        if (token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
            parseError(token);
            return;
        }
        defaultForAfterHead();
        ASSERT(m_insertionMode == InsertionMode::InBody);
        FALLTHROUGH;
    case InsertionMode::InBody:
        processEndTagForInBody(WTFMove(token));
        break;
    case InsertionMode::InTable:
        processEndTagForInTable(WTFMove(token));
        break;
    case InsertionMode::InCaption:
        if (token.name() == captionTag) {
            processCaptionEndTagForInCaption();
            return;
        }
        if (token.name() == tableTag) {
            parseError(token);
            if (!processCaptionEndTagForInCaption()) {
                ASSERT(isParsingFragment());
                return;
            }
            processEndTag(WTFMove(token));
            return;
        }
        if (token.name() == bodyTag
            || token.name() == colTag
            || token.name() == colgroupTag
            || token.name() == htmlTag
            || isTableBodyContextTag(token.name())
            || isTableCellContextTag(token.name())
            || token.name() == trTag) {
            parseError(token);
            return;
        }
        processEndTagForInBody(WTFMove(token));
        break;
    case InsertionMode::InColumnGroup:
        if (token.name() == colgroupTag) {
            processColgroupEndTagForInColumnGroup();
            return;
        }
        if (token.name() == colTag) {
            parseError(token);
            return;
        }
        if (token.name() == templateTag) {
            processTemplateEndTag(WTFMove(token));
            return;
        }
        if (!processColgroupEndTagForInColumnGroup()) {
            ASSERT(isParsingFragmentOrTemplateContents());
            return;
        }
        processEndTag(WTFMove(token));
        break;
    case InsertionMode::InRow:
        processEndTagForInRow(WTFMove(token));
        break;
    case InsertionMode::InCell:
        processEndTagForInCell(WTFMove(token));
        break;
    case InsertionMode::InTableBody:
        processEndTagForInTableBody(WTFMove(token));
        break;
    case InsertionMode::AfterBody:
        if (token.name() == htmlTag) {
            if (isParsingFragment()) {
                parseError(token);
                return;
            }
            m_insertionMode = InsertionMode::AfterAfterBody;
            return;
        }
        FALLTHROUGH;
    case InsertionMode::AfterAfterBody:
        ASSERT(m_insertionMode == InsertionMode::AfterBody || m_insertionMode == InsertionMode::AfterAfterBody);
        parseError(token);
        m_insertionMode = InsertionMode::InBody;
        processEndTag(WTFMove(token));
        break;
    case InsertionMode::InHeadNoscript:
        if (token.name() == noscriptTag) {
            ASSERT(m_tree.currentStackItem().hasTagName(noscriptTag));
            m_tree.openElements().pop();
            ASSERT(m_tree.currentStackItem().hasTagName(headTag));
            m_insertionMode = InsertionMode::InHead;
            return;
        }
        if (token.name() != brTag) {
            parseError(token);
            return;
        }
        defaultForInHeadNoscript();
        processToken(WTFMove(token));
        break;
    case InsertionMode::Text:
        if (token.name() == scriptTag) {
            // Pause ourselves so that parsing stops until the script can be processed by the caller.
            ASSERT(m_tree.currentStackItem().hasTagName(scriptTag));
            if (scriptingContentIsAllowed(m_tree.parserContentPolicy()))
                m_scriptToProcess = &downcast<HTMLScriptElement>(m_tree.currentElement());
            m_tree.openElements().pop();
            m_insertionMode = m_originalInsertionMode;

            // This token will not have been created by the tokenizer if a
            // self-closing script tag was encountered and pre-HTML5 parser
            // quirks are enabled. We must set the tokenizer's state to
            // DataState explicitly if the tokenizer didn't have a chance to.
            ASSERT(m_parser.tokenizer().isInDataState() || m_options.usePreHTML5ParserQuirks);
            m_parser.tokenizer().setDataState();
            return;
        }
        m_tree.openElements().pop();
        m_insertionMode = m_originalInsertionMode;
        break;
    case InsertionMode::InFrameset:
        if (token.name() == framesetTag) {
            bool ignoreFramesetForFragmentParsing  = m_tree.currentIsRootNode() || m_tree.openElements().hasTemplateInHTMLScope();
            if (ignoreFramesetForFragmentParsing) {
                ASSERT(isParsingFragmentOrTemplateContents());
                parseError(token);
                return;
            }
            m_tree.openElements().pop();
            if (!isParsingFragment() && !m_tree.currentStackItem().hasTagName(framesetTag))
                m_insertionMode = InsertionMode::AfterFrameset;
            return;
        }
        break;
    case InsertionMode::AfterFrameset:
        if (token.name() == htmlTag) {
            m_insertionMode = InsertionMode::AfterAfterFrameset;
            return;
        }
        FALLTHROUGH;
    case InsertionMode::AfterAfterFrameset:
        ASSERT(m_insertionMode == InsertionMode::AfterFrameset || m_insertionMode == InsertionMode::AfterAfterFrameset);
        parseError(token);
        break;
    case InsertionMode::InSelectInTable:
        if (token.name() == captionTag
            || token.name() == tableTag
            || isTableBodyContextTag(token.name())
            || token.name() == trTag
            || isTableCellContextTag(token.name())) {
            parseError(token);
            if (m_tree.openElements().inTableScope(token.name())) {
                AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag->localName());
                processEndTag(WTFMove(endSelect));
                processEndTag(WTFMove(token));
            }
            return;
        }
        FALLTHROUGH;
    case InsertionMode::InSelect:
        ASSERT(m_insertionMode == InsertionMode::InSelect || m_insertionMode == InsertionMode::InSelectInTable);
        if (token.name() == optgroupTag) {
            if (is<HTMLOptionElement>(m_tree.currentStackItem().node()) && m_tree.oneBelowTop() && is<HTMLOptGroupElement>(m_tree.oneBelowTop()->node()))
                processFakeEndTag(optionTag);
            if (is<HTMLOptGroupElement>(m_tree.currentStackItem().node())) {
                m_tree.openElements().pop();
                return;
            }
            parseError(token);
            return;
        }
        if (token.name() == optionTag) {
            if (is<HTMLOptionElement>(m_tree.currentStackItem().node())) {
                m_tree.openElements().pop();
                return;
            }
            parseError(token);
            return;
        }
        if (token.name() == selectTag) {
            if (!m_tree.openElements().inSelectScope(token.name())) {
                ASSERT(isParsingFragment());
                parseError(token);
                return;
            }
            m_tree.openElements().popUntilPopped(selectTag->localName());
            resetInsertionModeAppropriately();
            return;
        }
        if (token.name() == templateTag) {
            processTemplateEndTag(WTFMove(token));
            return;
        }
        break;
    case InsertionMode::InTableText:
        defaultForInTableText();
        processEndTag(WTFMove(token));
        break;
    case InsertionMode::TemplateContents:
        if (token.name() == templateTag) {
            processTemplateEndTag(WTFMove(token));
            return;
        }
        break;
    }
}

void HTMLTreeBuilder::processComment(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::Comment);
    if (m_insertionMode == InsertionMode::Initial
        || m_insertionMode == InsertionMode::BeforeHTML
        || m_insertionMode == InsertionMode::AfterAfterBody
        || m_insertionMode == InsertionMode::AfterAfterFrameset) {
        m_tree.insertCommentOnDocument(WTFMove(token));
        return;
    }
    if (m_insertionMode == InsertionMode::AfterBody) {
        m_tree.insertCommentOnHTMLHtmlElement(WTFMove(token));
        return;
    }
    if (m_insertionMode == InsertionMode::InTableText) {
        defaultForInTableText();
        processComment(WTFMove(token));
        return;
    }
    m_tree.insertComment(WTFMove(token));
}

void HTMLTreeBuilder::processCharacter(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::Character);
    ExternalCharacterTokenBuffer buffer(token);
    processCharacterBuffer(buffer);
}

#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS_FAMILY)

// FIXME: Extract the following iOS-specific code into a separate file.
// From the string 4089961010, creates a link of the form <a href="tel:4089961010">4089961010</a> and inserts it.
void HTMLTreeBuilder::insertPhoneNumberLink(const String& string)
{
    Vector<Attribute> attributes;
    attributes.append(Attribute(HTMLNames::hrefAttr, makeString("tel:"_s, string)));

    const AtomicString& aTagLocalName = aTag->localName();
    AtomicHTMLToken aStartToken(HTMLToken::StartTag, aTagLocalName, WTFMove(attributes));
    AtomicHTMLToken aEndToken(HTMLToken::EndTag, aTagLocalName);

    processStartTag(WTFMove(aStartToken));
    m_tree.executeQueuedTasks();
    m_tree.insertTextNode(string);
    processEndTag(WTFMove(aEndToken));
}

// Locates the phone numbers in the string and deals with it
// 1. Appends the text before the phone number as a text node.
// 2. Wraps the phone number in a tel: link.
// 3. Goes back to step 1 if a phone number is found in the rest of the string.
// 4. Appends the rest of the string as a text node.
void HTMLTreeBuilder::linkifyPhoneNumbers(const String& string)
{
    ASSERT(TelephoneNumberDetector::isSupported());

    // relativeStartPosition and relativeEndPosition are the endpoints of the phone number range,
    // relative to the scannerPosition
    unsigned length = string.length();
    unsigned scannerPosition = 0;
    int relativeStartPosition = 0;
    int relativeEndPosition = 0;

    auto characters = StringView(string).upconvertedCharacters();

    // While there's a phone number in the rest of the string...
    while (scannerPosition < length && TelephoneNumberDetector::find(&characters[scannerPosition], length - scannerPosition, &relativeStartPosition, &relativeEndPosition)) {
        // The convention in the Data Detectors framework is that the end position is the first character NOT in the phone number
        // (that is, the length of the range is relativeEndPosition - relativeStartPosition). So substract 1 to get the same
        // convention as the old WebCore phone number parser (so that the rest of the code is still valid if we want to go back
        // to the old parser).
        --relativeEndPosition;

        ASSERT(scannerPosition + relativeEndPosition < length);

        m_tree.insertTextNode(string.substring(scannerPosition, relativeStartPosition));
        insertPhoneNumberLink(string.substring(scannerPosition + relativeStartPosition, relativeEndPosition - relativeStartPosition + 1));

        scannerPosition += relativeEndPosition + 1;
    }

    // Append the rest as a text node.
    if (scannerPosition > 0) {
        if (scannerPosition < length) {
            String after = string.substring(scannerPosition, length - scannerPosition);
            m_tree.insertTextNode(after);
        }
    } else
        m_tree.insertTextNode(string);
}

// Looks at the ancestors of the element to determine whether we're inside an element which disallows parsing phone numbers.
static inline bool disallowTelephoneNumberParsing(const ContainerNode& node)
{
    return node.isLink()
        || node.hasTagName(scriptTag)
        || is<HTMLFormControlElement>(node)
        || node.hasTagName(styleTag)
        || node.hasTagName(ttTag)
        || node.hasTagName(preTag)
        || node.hasTagName(codeTag);
}

static inline bool shouldParseTelephoneNumbersInNode(const ContainerNode& node)
{
    for (const ContainerNode* ancestor = &node; ancestor; ancestor = ancestor->parentNode()) {
        if (disallowTelephoneNumberParsing(*ancestor))
            return false;
    }
    return true;
}

#endif // ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS_FAMILY)

void HTMLTreeBuilder::processCharacterBuffer(ExternalCharacterTokenBuffer& buffer)
{
ReprocessBuffer:
    // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-inbody
    // Note that this logic is different than the generic \r\n collapsing
    // handled in the input stream preprocessor. This logic is here as an
    // "authoring convenience" so folks can write:
    //
    // <pre>
    // lorem ipsum
    // lorem ipsum
    // </pre>
    //
    // without getting an extra newline at the start of their <pre> element.
    if (m_shouldSkipLeadingNewline) {
        m_shouldSkipLeadingNewline = false;
        buffer.skipAtMostOneLeadingNewline();
        if (buffer.isEmpty())
            return;
    }

    switch (m_insertionMode) {
    case InsertionMode::Initial:
        buffer.skipLeadingWhitespace();
        if (buffer.isEmpty())
            return;
        defaultForInitial();
        ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
        FALLTHROUGH;
    case InsertionMode::BeforeHTML:
        buffer.skipLeadingWhitespace();
        if (buffer.isEmpty())
            return;
        defaultForBeforeHTML();
        ASSERT(m_insertionMode == InsertionMode::BeforeHead);
        FALLTHROUGH;
    case InsertionMode::BeforeHead:
        buffer.skipLeadingWhitespace();
        if (buffer.isEmpty())
            return;
        defaultForBeforeHead();
        ASSERT(m_insertionMode == InsertionMode::InHead);
        FALLTHROUGH;
    case InsertionMode::InHead: {
        String leadingWhitespace = buffer.takeLeadingWhitespace();
        if (!leadingWhitespace.isEmpty())
            m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
        if (buffer.isEmpty())
            return;
        defaultForInHead();
        ASSERT(m_insertionMode == InsertionMode::AfterHead);
        FALLTHROUGH;
    }
    case InsertionMode::AfterHead: {
        String leadingWhitespace = buffer.takeLeadingWhitespace();
        if (!leadingWhitespace.isEmpty())
            m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
        if (buffer.isEmpty())
            return;
        defaultForAfterHead();
        ASSERT(m_insertionMode == InsertionMode::InBody);
        FALLTHROUGH;
    }
    case InsertionMode::InBody:
    case InsertionMode::InCaption:
    case InsertionMode::InCell:
    case InsertionMode::TemplateContents:
        processCharacterBufferForInBody(buffer);
        break;
    case InsertionMode::InTable:
    case InsertionMode::InTableBody:
    case InsertionMode::InRow:
        ASSERT(m_pendingTableCharacters.isEmpty());
        if (is<HTMLTableElement>(m_tree.currentStackItem().node())
            || m_tree.currentStackItem().hasTagName(HTMLNames::tbodyTag)
            || m_tree.currentStackItem().hasTagName(HTMLNames::tfootTag)
            || m_tree.currentStackItem().hasTagName(HTMLNames::theadTag)
            || m_tree.currentStackItem().hasTagName(HTMLNames::trTag)) {

            m_originalInsertionMode = m_insertionMode;
            m_insertionMode = InsertionMode::InTableText;
            // Note that we fall through to the InsertionMode::InTableText case below.
        } else {
            HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
            processCharacterBufferForInBody(buffer);
            break;
        }
        FALLTHROUGH;
    case InsertionMode::InTableText:
        buffer.giveRemainingTo(m_pendingTableCharacters);
        break;
    case InsertionMode::InColumnGroup: {
        String leadingWhitespace = buffer.takeLeadingWhitespace();
        if (!leadingWhitespace.isEmpty())
            m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
        if (buffer.isEmpty())
            return;
        if (!processColgroupEndTagForInColumnGroup()) {
            ASSERT(isParsingFragmentOrTemplateContents());
            // The spec tells us to drop these characters on the floor.
            buffer.skipLeadingNonWhitespace();
            if (buffer.isEmpty())
                return;
        }
        goto ReprocessBuffer;
    }
    case InsertionMode::AfterBody:
    case InsertionMode::AfterAfterBody:
        // FIXME: parse error
        m_insertionMode = InsertionMode::InBody;
        goto ReprocessBuffer;
    case InsertionMode::Text:
        m_tree.insertTextNode(buffer.takeRemaining());
        break;
    case InsertionMode::InHeadNoscript: {
        String leadingWhitespace = buffer.takeLeadingWhitespace();
        if (!leadingWhitespace.isEmpty())
            m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
        if (buffer.isEmpty())
            return;
        defaultForInHeadNoscript();
        goto ReprocessBuffer;
    }
    case InsertionMode::InFrameset:
    case InsertionMode::AfterFrameset: {
        String leadingWhitespace = buffer.takeRemainingWhitespace();
        if (!leadingWhitespace.isEmpty())
            m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
        // FIXME: We should generate a parse error if we skipped over any
        // non-whitespace characters.
        break;
    }
    case InsertionMode::InSelectInTable:
    case InsertionMode::InSelect:
        m_tree.insertTextNode(buffer.takeRemaining());
        break;
    case InsertionMode::AfterAfterFrameset: {
        String leadingWhitespace = buffer.takeRemainingWhitespace();
        if (!leadingWhitespace.isEmpty()) {
            m_tree.reconstructTheActiveFormattingElements();
            m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
        }
        // FIXME: We should generate a parse error if we skipped over any
        // non-whitespace characters.
        break;
    }
    }
}

void HTMLTreeBuilder::processCharacterBufferForInBody(ExternalCharacterTokenBuffer& buffer)
{
    m_tree.reconstructTheActiveFormattingElements();
    String characters = buffer.takeRemaining();
#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS_FAMILY)
    if (!isParsingFragment() && m_tree.isTelephoneNumberParsingEnabled() && shouldParseTelephoneNumbersInNode(m_tree.currentNode()) && TelephoneNumberDetector::isSupported())
        linkifyPhoneNumbers(characters);
    else
        m_tree.insertTextNode(characters);
#else
    m_tree.insertTextNode(characters);
#endif
    if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
        m_framesetOk = false;
}

void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::EndOfFile);
    switch (m_insertionMode) {
    case InsertionMode::Initial:
        defaultForInitial();
        ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
        FALLTHROUGH;
    case InsertionMode::BeforeHTML:
        defaultForBeforeHTML();
        ASSERT(m_insertionMode == InsertionMode::BeforeHead);
        FALLTHROUGH;
    case InsertionMode::BeforeHead:
        defaultForBeforeHead();
        ASSERT(m_insertionMode == InsertionMode::InHead);
        FALLTHROUGH;
    case InsertionMode::InHead:
        defaultForInHead();
        ASSERT(m_insertionMode == InsertionMode::AfterHead);
        FALLTHROUGH;
    case InsertionMode::AfterHead:
        defaultForAfterHead();
        ASSERT(m_insertionMode == InsertionMode::InBody);
        FALLTHROUGH;
    case InsertionMode::InBody:
    case InsertionMode::InCell:
    case InsertionMode::InCaption:
    case InsertionMode::InRow:
        notImplemented(); // Emit parse error based on what elements are still open.
        if (!m_templateInsertionModes.isEmpty()) {
            if (processEndOfFileForInTemplateContents(WTFMove(token)))
                return;
        }
        break;
    case InsertionMode::AfterBody:
    case InsertionMode::AfterAfterBody:
        break;
    case InsertionMode::InHeadNoscript:
        defaultForInHeadNoscript();
        processEndOfFile(WTFMove(token));
        return;
    case InsertionMode::AfterFrameset:
    case InsertionMode::AfterAfterFrameset:
        break;
    case InsertionMode::InColumnGroup:
        if (m_tree.currentIsRootNode()) {
            ASSERT(isParsingFragment());
            return; // FIXME: Should we break here instead of returning?
        }
        ASSERT(m_tree.currentNode().hasTagName(colgroupTag) || m_tree.currentNode().hasTagName(templateTag));
        processColgroupEndTagForInColumnGroup();
        FALLTHROUGH;
    case InsertionMode::InFrameset:
    case InsertionMode::InTable:
    case InsertionMode::InTableBody:
    case InsertionMode::InSelectInTable:
    case InsertionMode::InSelect:
        ASSERT(m_insertionMode == InsertionMode::InSelect || m_insertionMode == InsertionMode::InSelectInTable || m_insertionMode == InsertionMode::InTable || m_insertionMode == InsertionMode::InFrameset || m_insertionMode == InsertionMode::InTableBody || m_insertionMode == InsertionMode::InColumnGroup);
        if (&m_tree.currentNode() != &m_tree.openElements().rootNode())
            parseError(token);
        if (!m_templateInsertionModes.isEmpty()) {
            if (processEndOfFileForInTemplateContents(WTFMove(token)))
                return;
        }
        break;
    case InsertionMode::InTableText:
        defaultForInTableText();
        processEndOfFile(WTFMove(token));
        return;
    case InsertionMode::Text:
        parseError(token);
        if (m_tree.currentStackItem().hasTagName(scriptTag))
            notImplemented(); // mark the script element as "already started".
        m_tree.openElements().pop();
        ASSERT(m_originalInsertionMode != InsertionMode::Text);
        m_insertionMode = m_originalInsertionMode;
        processEndOfFile(WTFMove(token));
        return;
    case InsertionMode::TemplateContents:
        if (processEndOfFileForInTemplateContents(WTFMove(token)))
            return;
        break;
    }
    m_tree.openElements().popAll();
}

void HTMLTreeBuilder::defaultForInitial()
{
    notImplemented();
    m_tree.setDefaultCompatibilityMode();
    // FIXME: parse error
    m_insertionMode = InsertionMode::BeforeHTML;
}

void HTMLTreeBuilder::defaultForBeforeHTML()
{
    AtomicHTMLToken startHTML(HTMLToken::StartTag, htmlTag->localName());
    m_tree.insertHTMLHtmlStartTagBeforeHTML(WTFMove(startHTML));
    m_insertionMode = InsertionMode::BeforeHead;
}

void HTMLTreeBuilder::defaultForBeforeHead()
{
    AtomicHTMLToken startHead(HTMLToken::StartTag, headTag->localName());
    processStartTag(WTFMove(startHead));
}

void HTMLTreeBuilder::defaultForInHead()
{
    AtomicHTMLToken endHead(HTMLToken::EndTag, headTag->localName());
    processEndTag(WTFMove(endHead));
}

void HTMLTreeBuilder::defaultForInHeadNoscript()
{
    AtomicHTMLToken endNoscript(HTMLToken::EndTag, noscriptTag->localName());
    processEndTag(WTFMove(endNoscript));
}

void HTMLTreeBuilder::defaultForAfterHead()
{
    AtomicHTMLToken startBody(HTMLToken::StartTag, bodyTag->localName());
    processStartTag(WTFMove(startBody));
    m_framesetOk = true;
}

void HTMLTreeBuilder::defaultForInTableText()
{
    String characters = m_pendingTableCharacters.toString();
    m_pendingTableCharacters.clear();
    if (!isAllWhitespace(characters)) {
        // FIXME: parse error
        HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
        m_tree.reconstructTheActiveFormattingElements();
        m_tree.insertTextNode(characters, NotAllWhitespace);
        m_framesetOk = false;
        m_insertionMode = m_originalInsertionMode;
        return;
    }
    m_tree.insertTextNode(characters);
    m_insertionMode = m_originalInsertionMode;
}

bool HTMLTreeBuilder::processStartTagForInHead(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::StartTag);
    if (token.name() == htmlTag) {
        processHtmlStartTagForInBody(WTFMove(token));
        return true;
    }
    if (token.name() == baseTag
        || token.name() == basefontTag
        || token.name() == bgsoundTag
        || token.name() == commandTag
        || token.name() == linkTag
        || token.name() == metaTag) {
        m_tree.insertSelfClosingHTMLElement(WTFMove(token));
        // Note: The custom processing for the <meta> tag is done in HTMLMetaElement::process().
        return true;
    }
    if (token.name() == titleTag) {
        processGenericRCDATAStartTag(WTFMove(token));
        return true;
    }
    if (token.name() == noscriptTag) {
        if (m_options.scriptEnabled) {
            processGenericRawTextStartTag(WTFMove(token));
            return true;
        }
        m_tree.insertHTMLElement(WTFMove(token));
        m_insertionMode = InsertionMode::InHeadNoscript;
        return true;
    }
    if (token.name() == noframesTag || token.name() == styleTag) {
        processGenericRawTextStartTag(WTFMove(token));
        return true;
    }
    if (token.name() == scriptTag) {
        bool isSelfClosing = token.selfClosing();
        processScriptStartTag(WTFMove(token));
        if (m_options.usePreHTML5ParserQuirks && isSelfClosing)
            processFakeEndTag(scriptTag);
        return true;
    }
    if (token.name() == templateTag) {
        m_framesetOk = false;
        processTemplateStartTag(WTFMove(token));
        return true;
    }
    if (token.name() == headTag) {
        parseError(token);
        return true;
    }
    return false;
}

void HTMLTreeBuilder::processGenericRCDATAStartTag(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::StartTag);
    m_tree.insertHTMLElement(WTFMove(token));
    m_parser.tokenizer().setRCDATAState();
    m_originalInsertionMode = m_insertionMode;
    m_insertionMode = InsertionMode::Text;
}

void HTMLTreeBuilder::processGenericRawTextStartTag(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::StartTag);
    m_tree.insertHTMLElement(WTFMove(token));
    m_parser.tokenizer().setRAWTEXTState();
    m_originalInsertionMode = m_insertionMode;
    m_insertionMode = InsertionMode::Text;
}

void HTMLTreeBuilder::processScriptStartTag(AtomicHTMLToken&& token)
{
    ASSERT(token.type() == HTMLToken::StartTag);
    m_tree.insertScriptElement(WTFMove(token));
    m_parser.tokenizer().setScriptDataState();
    m_originalInsertionMode = m_insertionMode;

    TextPosition position = m_parser.textPosition();

    m_scriptToProcessStartPosition = position;

    m_insertionMode = InsertionMode::Text;
}

// http://www.whatwg.org/specs/web-apps/current-work/#adjusted-current-node
HTMLStackItem& HTMLTreeBuilder::adjustedCurrentStackItem() const
{
    ASSERT(!m_tree.isEmpty());
    if (isParsingFragment() && m_tree.openElements().hasOnlyOneElement())
        return m_fragmentContext.contextElementStackItem();

    return m_tree.currentStackItem();
}

// http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#tree-construction
bool HTMLTreeBuilder::shouldProcessTokenInForeignContent(const AtomicHTMLToken& token)
{
    if (m_tree.isEmpty())
        return false;
    HTMLStackItem& adjustedCurrentNode = adjustedCurrentStackItem();
    if (isInHTMLNamespace(adjustedCurrentNode))
        return false;
    if (HTMLElementStack::isMathMLTextIntegrationPoint(adjustedCurrentNode)) {
        if (token.type() == HTMLToken::StartTag
            && token.name() != MathMLNames::mglyphTag
            && token.name() != MathMLNames::malignmarkTag)
            return false;
        if (token.type() == HTMLToken::Character)
            return false;
    }
    if (adjustedCurrentNode.hasTagName(MathMLNames::annotation_xmlTag)
        && token.type() == HTMLToken::StartTag
        && token.name() == SVGNames::svgTag)
        return false;
    if (HTMLElementStack::isHTMLIntegrationPoint(adjustedCurrentNode)) {
        if (token.type() == HTMLToken::StartTag)
            return false;
        if (token.type() == HTMLToken::Character)
            return false;
    }
    if (token.type() == HTMLToken::EndOfFile)
        return false;
    return true;
}

static bool hasAttribute(const AtomicHTMLToken& token, const QualifiedName& name)
{
    return findAttribute(token.attributes(), name);
}

void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken&& token)
{
    HTMLStackItem& adjustedCurrentNode = adjustedCurrentStackItem();
    
    switch (token.type()) {
    case HTMLToken::Uninitialized:
        ASSERT_NOT_REACHED();
        break;
    case HTMLToken::DOCTYPE:
        parseError(token);
        break;
    case HTMLToken::StartTag: {
        if (token.name() == bTag
            || token.name() == bigTag
            || token.name() == blockquoteTag
            || token.name() == bodyTag
            || token.name() == brTag
            || token.name() == centerTag
            || token.name() == codeTag
            || token.name() == ddTag
            || token.name() == divTag
            || token.name() == dlTag
            || token.name() == dtTag
            || token.name() == emTag
            || token.name() == embedTag
            || isNumberedHeaderTag(token.name())
            || token.name() == headTag
            || token.name() == hrTag
            || token.name() == iTag
            || token.name() == imgTag
            || token.name() == liTag
            || token.name() == listingTag
            || token.name() == menuTag
            || token.name() == metaTag
            || token.name() == nobrTag
            || token.name() == olTag
            || token.name() == pTag
            || token.name() == preTag
            || token.name() == rubyTag
            || token.name() == sTag
            || token.name() == smallTag
            || token.name() == spanTag
            || token.name() == strongTag
            || token.name() == strikeTag
            || token.name() == subTag
            || token.name() == supTag
            || token.name() == tableTag
            || token.name() == ttTag
            || token.name() == uTag
            || token.name() == ulTag
            || token.name() == varTag
            || (token.name() == fontTag && (hasAttribute(token, colorAttr) || hasAttribute(token, faceAttr) || hasAttribute(token, sizeAttr)))) {
            parseError(token);
            m_tree.openElements().popUntilForeignContentScopeMarker();
            processStartTag(WTFMove(token));
            return;
        }
        const AtomicString& currentNamespace = adjustedCurrentNode.namespaceURI();
        if (currentNamespace == MathMLNames::mathmlNamespaceURI)
            adjustMathMLAttributes(token);
        if (currentNamespace == SVGNames::svgNamespaceURI) {
            adjustSVGTagNameCase(token);
            adjustSVGAttributes(token);
        }
        adjustForeignAttributes(token);
        m_tree.insertForeignElement(WTFMove(token), currentNamespace);
        break;
    }
    case HTMLToken::EndTag: {
        if (adjustedCurrentNode.namespaceURI() == SVGNames::svgNamespaceURI)
            adjustSVGTagNameCase(token);

        if (token.name() == SVGNames::scriptTag && m_tree.currentStackItem().hasTagName(SVGNames::scriptTag)) {
            if (scriptingContentIsAllowed(m_tree.parserContentPolicy()))
                m_scriptToProcess = &downcast<SVGScriptElement>(m_tree.currentElement());
            m_tree.openElements().pop();
            return;
        }
        if (!isInHTMLNamespace(m_tree.currentStackItem())) {
            // FIXME: This code just wants an Element* iterator, instead of an ElementRecord*
            auto* nodeRecord = &m_tree.openElements().topRecord();
            if (nodeRecord->stackItem().localName() != token.name())
                parseError(token);
            while (1) {
                if (nodeRecord->stackItem().localName() == token.name()) {
                    m_tree.openElements().popUntilPopped(nodeRecord->element());
                    return;
                }
                nodeRecord = nodeRecord->next();

                if (isInHTMLNamespace(nodeRecord->stackItem()))
                    break;
            }
        }
        // Otherwise, process the token according to the rules given in the section corresponding to the current insertion mode in HTML content.
        processEndTag(WTFMove(token));
        break;
    }
    case HTMLToken::Comment:
        m_tree.insertComment(WTFMove(token));
        return;
    case HTMLToken::Character: {
        String characters = String(token.characters(), token.charactersLength());
        m_tree.insertTextNode(characters);
        if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
            m_framesetOk = false;
        break;
    }
    case HTMLToken::EndOfFile:
        ASSERT_NOT_REACHED();
        break;
    }
}

void HTMLTreeBuilder::finished()
{
    ASSERT(!m_destroyed);

    if (isParsingFragment())
        return;

    ASSERT(m_templateInsertionModes.isEmpty());

    m_tree.finishedParsing();
    // The tree builder might have been destroyed as an indirect result of finishing the parsing.
}

inline void HTMLTreeBuilder::parseError(const AtomicHTMLToken&)
{
}

}
