/*
 * Copyright (C) 2010 Google, Inc. All Rights Reserved.
 * Copyright (C) 2011, 2014 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 "core/html/parser/HTMLTreeBuilder.h"

#include "bindings/core/v8/ExceptionStatePlaceholder.h"
#include "core/HTMLNames.h"
#include "core/MathMLNames.h"
#include "core/SVGNames.h"
#include "core/XLinkNames.h"
#include "core/XMLNSNames.h"
#include "core/XMLNames.h"
#include "core/dom/Document.h"
#include "core/dom/DocumentFragment.h"
#include "core/dom/ElementTraversal.h"
#include "core/frame/UseCounter.h"
#include "core/html/HTMLFormElement.h"
#include "core/html/HTMLTemplateElement.h"
#include "core/html/parser/AtomicHTMLToken.h"
#include "core/html/parser/HTMLDocumentParser.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/html/parser/HTMLStackItem.h"
#include "core/html/parser/HTMLToken.h"
#include "core/html/parser/HTMLTokenizer.h"
#include "platform/text/PlatformLocale.h"
#include "wtf/text/CharacterNames.h"
#include <memory>

namespace blink {

using namespace HTMLNames;

namespace {

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

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

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

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);
}

// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#formatting
static bool isFormattingTag(const AtomicString& tagName) {
  return tagName == aTag || isNonAnchorFormattingTag(tagName);
}

class HTMLTreeBuilder::CharacterTokenBuffer {
  WTF_MAKE_NONCOPYABLE(CharacterTokenBuffer);

 public:
  explicit CharacterTokenBuffer(AtomicHTMLToken* token)
      : m_characters(token->characters().impl()),
        m_current(0),
        m_end(token->characters().length()) {
    ASSERT(!isEmpty());
  }

  explicit CharacterTokenBuffer(const String& characters)
      : m_characters(characters.impl()),
        m_current(0),
        m_end(characters.length()) {
    ASSERT(!isEmpty());
  }

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

  bool isEmpty() const { return m_current == m_end; }

  void skipAtMostOneLeadingNewline() {
    ASSERT(!isEmpty());
    if ((*m_characters)[m_current] == '\n')
      ++m_current;
  }

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

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

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

  void skipRemaining() { m_current = m_end; }

  String takeRemaining() {
    ASSERT(!isEmpty());
    unsigned start = m_current;
    m_current = m_end;
    // Notice that substring is smart enough to return *this when start == 0.
    return String(m_characters->substring(start, m_end - start));
  }

  void giveRemainingTo(StringBuilder& recipient) {
    if (m_characters->is8Bit())
      recipient.append(m_characters->characters8() + m_current,
                       m_end - m_current);
    else
      recipient.append(m_characters->characters16() + m_current,
                       m_end - m_current);
    m_current = m_end;
  }

  String takeRemainingWhitespace() {
    ASSERT(!isEmpty());
    const unsigned start = m_current;
    m_current = m_end;  // One way or another, we're taking everything!

    unsigned length = 0;
    for (unsigned i = start; i < m_end; ++i) {
      if (isHTMLSpace<UChar>((*m_characters)[i]))
        ++length;
    }
    // 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 (!length)
      return String();
    if (length == start - m_end)  // It's all whitespace.
      return String(m_characters->substring(start, start - m_end));

    StringBuilder result;
    result.reserveCapacity(length);
    for (unsigned i = start; i < m_end; ++i) {
      UChar c = (*m_characters)[i];
      if (isHTMLSpace<UChar>(c))
        result.append(c);
    }

    return result.toString();
  }

 private:
  template <bool characterPredicate(UChar)>
  void skipLeading() {
    ASSERT(!isEmpty());
    while (characterPredicate((*m_characters)[m_current])) {
      if (++m_current == m_end)
        return;
    }
  }

  template <bool characterPredicate(UChar)>
  String takeLeading() {
    ASSERT(!isEmpty());
    const unsigned start = m_current;
    skipLeading<characterPredicate>();
    if (start == m_current)
      return String();
    return String(m_characters->substring(start, m_current - start));
  }

  RefPtr<StringImpl> m_characters;
  unsigned m_current;
  unsigned m_end;
};

HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser,
                                 Document& document,
                                 ParserContentPolicy parserContentPolicy,
                                 const HTMLParserOptions& options)
    : m_framesetOk(true)
#if ENABLE(ASSERT)
      ,
      m_isAttached(true)
#endif
      ,
      m_tree(parser->reentryPermit(), document, parserContentPolicy),
      m_insertionMode(InitialMode),
      m_originalInsertionMode(InitialMode),
      m_shouldSkipLeadingNewline(false),
      m_parser(parser),
      m_scriptToProcessStartPosition(uninitializedPositionValue1()),
      m_options(options) {
}

HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser,
                                 DocumentFragment* fragment,
                                 Element* contextElement,
                                 ParserContentPolicy parserContentPolicy,
                                 const HTMLParserOptions& options)
    : HTMLTreeBuilder(parser,
                      fragment->document(),
                      parserContentPolicy,
                      options) {
  ASSERT(isMainThread());
  ASSERT(contextElement);
  m_tree.initFragmentParsing(fragment, contextElement);
  m_fragmentContext.init(fragment, contextElement);

  // Steps 4.2-4.6 of the HTML5 Fragment Case parsing algorithm:
  // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#fragment-case
  // For efficiency, we skip step 4.2 ("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, HTMLStackItem::ItemForDocumentFragmentNode));

  if (isHTMLTemplateElement(*contextElement))
    m_templateInsertionModes.append(TemplateContentsMode);

  resetInsertionModeAppropriately();
}

HTMLTreeBuilder::~HTMLTreeBuilder() {}

void HTMLTreeBuilder::FragmentParsingContext::init(DocumentFragment* fragment,
                                                   Element* contextElement) {
  DCHECK(fragment);
  DCHECK(!fragment->hasChildren());
  m_fragment = fragment;
  m_contextElementStackItem = HTMLStackItem::create(
      contextElement, HTMLStackItem::ItemForContextElement);
}

DEFINE_TRACE(HTMLTreeBuilder::FragmentParsingContext) {
  visitor->trace(m_fragment);
  visitor->trace(m_contextElementStackItem);
}

DEFINE_TRACE(HTMLTreeBuilder) {
  visitor->trace(m_fragmentContext);
  visitor->trace(m_tree);
  visitor->trace(m_parser);
  visitor->trace(m_scriptToProcess);
}

void HTMLTreeBuilder::detach() {
#if ENABLE(ASSERT)
  // This call makes little sense in fragment mode, but for consistency
  // DocumentParser expects detach() to always be called before it's destroyed.
  m_isAttached = false;
#endif
  // HTMLConstructionSite might be on the callstack when detach() is called
  // otherwise we'd just call m_tree.clear() here instead.
  m_tree.detach();
}

Element* HTMLTreeBuilder::takeScriptToProcess(
    TextPosition& scriptStartPosition) {
  ASSERT(m_scriptToProcess);
  ASSERT(!m_tree.hasPendingTasks());
  // 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 m_scriptToProcess.release();
}

void HTMLTreeBuilder::constructTree(AtomicHTMLToken* token) {
  if (shouldProcessTokenInForeignContent(token))
    processTokenInForeignContent(token);
  else
    processToken(token);

  if (m_parser->tokenizer()) {
    bool inForeignContent = false;
    if (!m_tree.isEmpty()) {
      HTMLStackItem* adjustedCurrentNode = adjustedCurrentStackItem();
      inForeignContent =
          !adjustedCurrentNode->isInHTMLNamespace() &&
          !HTMLElementStack::isHTMLIntegrationPoint(adjustedCurrentNode) &&
          !HTMLElementStack::isMathMLTextIntegrationPoint(adjustedCurrentNode);
    }

    m_parser->tokenizer()->setForceNullCharacterReplacement(
        m_insertionMode == TextMode || inForeignContent);
    m_parser->tokenizer()->setShouldAllowCDATA(inForeignContent);
  }

  m_tree.executeQueuedTasks();
  // We might be detached now.
}

void HTMLTreeBuilder::processToken(AtomicHTMLToken* token) {
  if (token->type() == HTMLToken::Character) {
    processCharacter(token);
    return;
  }

  // Any non-character token needs to cause us to flush any pending text
  // immediately. NOTE: flush() can cause any queued tasks to execute, possibly
  // re-entering the parser.
  m_tree.flush(FlushAlways);
  m_shouldSkipLeadingNewline = false;

  switch (token->type()) {
    case HTMLToken::Uninitialized:
    case HTMLToken::Character:
      ASSERT_NOT_REACHED();
      break;
    case HTMLToken::DOCTYPE:
      processDoctypeToken(token);
      break;
    case HTMLToken::StartTag:
      processStartTag(token);
      break;
    case HTMLToken::EndTag:
      processEndTag(token);
      break;
    case HTMLToken::Comment:
      processComment(token);
      break;
    case HTMLToken::EndOfFile:
      processEndOfFile(token);
      break;
  }
}

void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken* token) {
  ASSERT(token->type() == HTMLToken::DOCTYPE);
  if (m_insertionMode == InitialMode) {
    m_tree.insertDoctype(token);
    setInsertionMode(BeforeHTMLMode);
    return;
  }
  if (m_insertionMode == InTableTextMode) {
    defaultForInTableText();
    processDoctypeToken(token);
    return;
  }
  parseError(token);
}

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

void HTMLTreeBuilder::processFakeEndTag(const AtomicString& tagName) {
  AtomicHTMLToken fakeToken(HTMLToken::EndTag, tagName);
  processEndTag(&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::processFakePEndTagIfPInButtonScope() {
  if (!m_tree.openElements()->inButtonScope(pTag.localName()))
    return;
  AtomicHTMLToken endP(HTMLToken::EndTag, pTag.localName());
  processEndTag(&endP);
}

namespace {

bool isLi(const HTMLStackItem* item) {
  return item->hasTagName(liTag);
}

bool isDdOrDt(const HTMLStackItem* item) {
  return item->hasTagName(ddTag) || item->hasTagName(dtTag);
}

}  // namespace

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

typedef HashMap<AtomicString, QualifiedName> PrefixedNameToQualifiedNameMap;

template <typename TableQualifiedName>
static void mapLoweredLocalNameToName(PrefixedNameToQualifiedNameMap* map,
                                      const TableQualifiedName* const* names,
                                      size_t length) {
  for (size_t i = 0; i < length; ++i) {
    const QualifiedName& name = *names[i];
    const AtomicString& localName = name.localName();
    AtomicString loweredLocalName = localName.lower();
    if (loweredLocalName != localName)
      map->add(loweredLocalName, name);
  }
}

static void adjustSVGTagNameCase(AtomicHTMLToken* token) {
  static PrefixedNameToQualifiedNameMap* caseMap = 0;
  if (!caseMap) {
    caseMap = new PrefixedNameToQualifiedNameMap;
    std::unique_ptr<const SVGQualifiedName* []> svgTags =
        SVGNames::getSVGTags();
    mapLoweredLocalNameToName(caseMap, svgTags.get(), SVGNames::SVGTagsCount);
  }

  const QualifiedName& casedName = caseMap->get(token->name());
  if (casedName.localName().isNull())
    return;
  token->setName(casedName.localName());
}

template <std::unique_ptr<const QualifiedName* []> getAttrs(), unsigned length>
static void adjustAttributes(AtomicHTMLToken* token) {
  static PrefixedNameToQualifiedNameMap* caseMap = 0;
  if (!caseMap) {
    caseMap = new PrefixedNameToQualifiedNameMap;
    std::unique_ptr<const QualifiedName* []> attrs = getAttrs();
    mapLoweredLocalNameToName(caseMap, attrs.get(), length);
  }

  for (unsigned i = 0; i < token->attributes().size(); ++i) {
    Attribute& tokenAttribute = token->attributes().at(i);
    const QualifiedName& casedName = caseMap->get(tokenAttribute.localName());
    if (!casedName.localName().isNull())
      tokenAttribute.parserSetName(casedName);
  }
}

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

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

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

static void adjustForeignAttributes(AtomicHTMLToken* token) {
  static PrefixedNameToQualifiedNameMap* map = 0;
  if (!map) {
    map = new PrefixedNameToQualifiedNameMap;

    std::unique_ptr<const QualifiedName* []> attrs =
        XLinkNames::getXLinkAttrs();
    addNamesWithPrefix(map, xlinkAtom, attrs.get(),
                       XLinkNames::XLinkAttrsCount);

    std::unique_ptr<const QualifiedName* []> xmlAttrs = XMLNames::getXMLAttrs();
    addNamesWithPrefix(map, xmlAtom, xmlAttrs.get(), XMLNames::XMLAttrsCount);

    map->add(WTF::xmlnsAtom, XMLNSNames::xmlnsAttr);
    map->add("xmlns:xlink", QualifiedName(xmlnsAtom, xlinkAtom,
                                          XMLNSNames::xmlnsNamespaceURI));
  }

  for (unsigned i = 0; i < token->attributes().size(); ++i) {
    Attribute& tokenAttribute = token->attributes().at(i);
    const QualifiedName& name = map->get(tokenAttribute.localName());
    if (!name.localName().isNull())
      tokenAttribute.parserSetName(name);
  }
}

void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token) {
  ASSERT(token->type() == HTMLToken::StartTag);
  if (token->name() == htmlTag) {
    processHtmlStartTagForInBody(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(token);
    ASSERT_UNUSED(didProcess, didProcess);
    return;
  }
  if (token->name() == bodyTag) {
    parseError(token);
    if (!m_tree.openElements()->secondElementIsHTMLBodyElement() ||
        m_tree.openElements()->hasOnlyOneElement() ||
        m_tree.openElements()->hasTemplateInHTMLScope()) {
      ASSERT(isParsingFragmentOrTemplateContents());
      return;
    }
    m_framesetOk = false;
    m_tree.insertHTMLBodyStartTagInBody(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(ASSERT_NO_EXCEPTION);
    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 in Blink's implementation.
    DCHECK(!isParsingTemplateContents());
    DCHECK(!isParsingFragment() ||
           toDocumentFragment(m_tree.openElements()->topNode()));
    DCHECK(isParsingFragment() ||
           m_tree.openElements()->top() ==
               m_tree.openElements()->htmlElement());
    m_tree.insertHTMLElement(token);
    setInsertionMode(InFramesetMode);
    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(token);
    return;
  }
  if (isNumberedHeaderTag(token->name())) {
    processFakePEndTagIfPInButtonScope();
    if (m_tree.currentStackItem()->isNumberedHeaderElement()) {
      parseError(token);
      m_tree.openElements()->pop();
    }
    m_tree.insertHTMLElement(token);
    return;
  }
  if (token->name() == preTag || token->name() == listingTag) {
    processFakePEndTagIfPInButtonScope();
    m_tree.insertHTMLElement(token);
    m_shouldSkipLeadingNewline = true;
    m_framesetOk = false;
    return;
  }
  if (token->name() == formTag) {
    if (m_tree.isFormElementPointerNonNull() && !isParsingTemplateContents()) {
      parseError(token);
      return;
    }
    processFakePEndTagIfPInButtonScope();
    m_tree.insertHTMLFormElement(token);
    return;
  }
  if (token->name() == liTag) {
    processCloseWhenNestedTag<isLi>(token);
    return;
  }
  if (token->name() == ddTag || token->name() == dtTag) {
    processCloseWhenNestedTag<isDdOrDt>(token);
    return;
  }
  if (token->name() == plaintextTag) {
    processFakePEndTagIfPInButtonScope();
    m_tree.insertHTMLElement(token);
    if (m_parser->tokenizer())
      m_parser->tokenizer()->setState(HTMLTokenizer::PLAINTEXTState);
    return;
  }
  if (token->name() == buttonTag) {
    if (m_tree.openElements()->inScope(buttonTag)) {
      parseError(token);
      processFakeEndTag(buttonTag);
      processStartTag(token);  // FIXME: Could we just fall through here?
      return;
    }
    m_tree.reconstructTheActiveFormattingElements();
    m_tree.insertHTMLElement(token);
    m_framesetOk = false;
    return;
  }
  if (token->name() == aTag) {
    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(token);
    return;
  }
  if (isNonAnchorNonNobrFormattingTag(token->name())) {
    m_tree.reconstructTheActiveFormattingElements();
    m_tree.insertFormattingElement(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(token);
    return;
  }
  if (token->name() == appletTag || token->name() == embedTag ||
      token->name() == objectTag) {
    if (!pluginContentIsAllowed(m_tree.getParserContentPolicy()))
      return;
  }
  if (token->name() == appletTag || token->name() == marqueeTag ||
      token->name() == objectTag) {
    m_tree.reconstructTheActiveFormattingElements();
    m_tree.insertHTMLElement(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(token);
    m_framesetOk = false;
    setInsertionMode(InTableMode);
    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.insertSelfClosingHTMLElementDestroyingToken(token);
    m_framesetOk = false;
    return;
  }
  if (token->name() == inputTag) {
    // Per spec https://html.spec.whatwg.org/#parsing-main-inbody,
    // section "A start tag whose tag name is "input""

    Attribute* typeAttribute = token->getAttributeItem(typeAttr);
    bool disableFrameset =
        !typeAttribute || !equalIgnoringCase(typeAttribute->value(), "hidden");

    m_tree.reconstructTheActiveFormattingElements();
    m_tree.insertSelfClosingHTMLElementDestroyingToken(token);

    if (disableFrameset)
      m_framesetOk = false;
    return;
  }
  if ((RuntimeEnabledFeatures::contextMenuEnabled() &&
       token->name() == menuitemTag) ||
      token->name() == paramTag || token->name() == sourceTag ||
      token->name() == trackTag) {
    m_tree.insertSelfClosingHTMLElementDestroyingToken(token);
    return;
  }
  if (token->name() == hrTag) {
    processFakePEndTagIfPInButtonScope();
    m_tree.insertSelfClosingHTMLElementDestroyingToken(token);
    m_framesetOk = false;
    return;
  }
  if (token->name() == textareaTag) {
    m_tree.insertHTMLElement(token);
    m_shouldSkipLeadingNewline = true;
    if (m_parser->tokenizer())
      m_parser->tokenizer()->setState(HTMLTokenizer::RCDATAState);
    m_originalInsertionMode = m_insertionMode;
    m_framesetOk = false;
    setInsertionMode(TextMode);
    return;
  }
  if (token->name() == xmpTag) {
    processFakePEndTagIfPInButtonScope();
    m_tree.reconstructTheActiveFormattingElements();
    m_framesetOk = false;
    processGenericRawTextStartTag(token);
    return;
  }
  if (token->name() == iframeTag) {
    m_framesetOk = false;
    processGenericRawTextStartTag(token);
    return;
  }
  if (token->name() == noembedTag && m_options.pluginsEnabled) {
    processGenericRawTextStartTag(token);
    return;
  }
  if (token->name() == noscriptTag && m_options.scriptEnabled) {
    processGenericRawTextStartTag(token);
    return;
  }
  if (token->name() == selectTag) {
    m_tree.reconstructTheActiveFormattingElements();
    m_tree.insertHTMLElement(token);
    m_framesetOk = false;
    if (m_insertionMode == InTableMode || m_insertionMode == InCaptionMode ||
        m_insertionMode == InColumnGroupMode ||
        m_insertionMode == InTableBodyMode || m_insertionMode == InRowMode ||
        m_insertionMode == InCellMode)
      setInsertionMode(InSelectInTableMode);
    else
      setInsertionMode(InSelectMode);
    return;
  }
  if (token->name() == optgroupTag || token->name() == optionTag) {
    if (m_tree.currentStackItem()->hasTagName(optionTag)) {
      AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
      processEndTag(&endOption);
    }
    m_tree.reconstructTheActiveFormattingElements();
    m_tree.insertHTMLElement(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(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(token);
    return;
  }
  if (token->name() == MathMLNames::mathTag.localName()) {
    m_tree.reconstructTheActiveFormattingElements();
    adjustMathMLAttributes(token);
    adjustForeignAttributes(token);
    m_tree.insertForeignElement(token, MathMLNames::mathmlNamespaceURI);
    return;
  }
  if (token->name() == SVGNames::svgTag.localName()) {
    m_tree.reconstructTheActiveFormattingElements();
    adjustSVGAttributes(token);
    adjustForeignAttributes(token);
    m_tree.insertForeignElement(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) {
    processTemplateStartTag(token);
    return;
  }
  m_tree.reconstructTheActiveFormattingElements();
  m_tree.insertHTMLElement(token);
}

void HTMLTreeBuilder::processTemplateStartTag(AtomicHTMLToken* token) {
  m_tree.activeFormattingElements()->appendMarker();
  m_tree.insertHTMLElement(token);
  m_framesetOk = false;
  m_templateInsertionModes.append(TemplateContentsMode);
  setInsertionMode(TemplateContentsMode);
}

bool HTMLTreeBuilder::processTemplateEndTag(AtomicHTMLToken* token) {
  ASSERT(token->name() == templateTag.localName());
  if (!m_tree.openElements()->hasTemplateInHTMLScope()) {
    ASSERT(m_templateInsertionModes.isEmpty() ||
           (m_templateInsertionModes.size() == 1 &&
            isHTMLTemplateElement(m_fragmentContext.contextElement())));
    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(&endTemplate))
    return false;

  processEndOfFile(token);
  return true;
}

bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup() {
  if (m_tree.currentIsRootNode() ||
      isHTMLTemplateElement(*m_tree.currentNode())) {
    ASSERT(isParsingFragmentOrTemplateContents());
    // FIXME: parse error
    return false;
  }
  m_tree.openElements()->pop();
  setInsertionMode(InTableMode);
  return true;
}

// 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/tokenization.html#close-the-cell
void HTMLTreeBuilder::closeTheCell() {
  ASSERT(getInsertionMode() == InCellMode);
  if (m_tree.openElements()->inTableScope(tdTag)) {
    ASSERT(!m_tree.openElements()->inTableScope(thTag));
    processFakeEndTag(tdTag);
    return;
  }
  ASSERT(m_tree.openElements()->inTableScope(thTag));
  processFakeEndTag(thTag);
  ASSERT(getInsertionMode() == InRowMode);
}

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(token);
    setInsertionMode(InCaptionMode);
    return;
  }
  if (token->name() == colgroupTag) {
    m_tree.openElements()->popUntilTableScopeMarker();
    m_tree.insertHTMLElement(token);
    setInsertionMode(InColumnGroupMode);
    return;
  }
  if (token->name() == colTag) {
    processFakeStartTag(colgroupTag);
    ASSERT(InColumnGroupMode);
    processStartTag(token);
    return;
  }
  if (isTableBodyContextTag(token->name())) {
    m_tree.openElements()->popUntilTableScopeMarker();
    m_tree.insertHTMLElement(token);
    setInsertionMode(InTableBodyMode);
    return;
  }
  if (isTableCellContextTag(token->name()) || token->name() == trTag) {
    processFakeStartTag(tbodyTag);
    ASSERT(getInsertionMode() == InTableBodyMode);
    processStartTag(token);
    return;
  }
  if (token->name() == tableTag) {
    parseError(token);
    if (!processTableEndTagForInTable()) {
      ASSERT(isParsingFragmentOrTemplateContents());
      return;
    }
    processStartTag(token);
    return;
  }
  if (token->name() == styleTag || token->name() == scriptTag) {
    processStartTagForInHead(token);
    return;
  }
  if (token->name() == inputTag) {
    Attribute* typeAttribute = token->getAttributeItem(typeAttr);
    if (typeAttribute && equalIgnoringCase(typeAttribute->value(), "hidden")) {
      parseError(token);
      m_tree.insertSelfClosingHTMLElementDestroyingToken(token);
      return;
    }
    // Fall through to "anything else" case.
  }
  if (token->name() == formTag) {
    parseError(token);
    if (m_tree.isFormElementPointerNonNull() && !isParsingTemplateContents())
      return;
    m_tree.insertHTMLFormElement(token, true);
    m_tree.openElements()->pop();
    return;
  }
  if (token->name() == templateTag) {
    processTemplateStartTag(token);
    return;
  }
  parseError(token);
  HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
  processStartTagForInBody(token);
}

void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token) {
  ASSERT(token->type() == HTMLToken::StartTag);
  switch (getInsertionMode()) {
    case InitialMode:
      ASSERT(getInsertionMode() == InitialMode);
      defaultForInitial();
    // Fall through.
    case BeforeHTMLMode:
      ASSERT(getInsertionMode() == BeforeHTMLMode);
      if (token->name() == htmlTag) {
        m_tree.insertHTMLHtmlStartTagBeforeHTML(token);
        setInsertionMode(BeforeHeadMode);
        return;
      }
      defaultForBeforeHTML();
    // Fall through.
    case BeforeHeadMode:
      ASSERT(getInsertionMode() == BeforeHeadMode);
      if (token->name() == htmlTag) {
        processHtmlStartTagForInBody(token);
        return;
      }
      if (token->name() == headTag) {
        m_tree.insertHTMLHeadElement(token);
        setInsertionMode(InHeadMode);
        return;
      }
      defaultForBeforeHead();
    // Fall through.
    case InHeadMode:
      ASSERT(getInsertionMode() == InHeadMode);
      if (processStartTagForInHead(token))
        return;
      defaultForInHead();
    // Fall through.
    case AfterHeadMode:
      ASSERT(getInsertionMode() == AfterHeadMode);
      if (token->name() == htmlTag) {
        processHtmlStartTagForInBody(token);
        return;
      }
      if (token->name() == bodyTag) {
        m_framesetOk = false;
        m_tree.insertHTMLBodyElement(token);
        setInsertionMode(InBodyMode);
        return;
      }
      if (token->name() == framesetTag) {
        m_tree.insertHTMLElement(token);
        setInsertionMode(InFramesetMode);
        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.head());
        m_tree.openElements()->pushHTMLHeadElement(m_tree.headStackItem());
        processStartTagForInHead(token);
        m_tree.openElements()->removeHTMLHeadElement(m_tree.head());
        return;
      }
      if (token->name() == headTag) {
        parseError(token);
        return;
      }
      defaultForAfterHead();
    // Fall through
    case InBodyMode:
      ASSERT(getInsertionMode() == InBodyMode);
      processStartTagForInBody(token);
      break;
    case InTableMode:
      ASSERT(getInsertionMode() == InTableMode);
      processStartTagForInTable(token);
      break;
    case InCaptionMode:
      ASSERT(getInsertionMode() == InCaptionMode);
      if (isCaptionColOrColgroupTag(token->name()) ||
          isTableBodyContextTag(token->name()) ||
          isTableCellContextTag(token->name()) || token->name() == trTag) {
        parseError(token);
        if (!processCaptionEndTagForInCaption()) {
          ASSERT(isParsingFragment());
          return;
        }
        processStartTag(token);
        return;
      }
      processStartTagForInBody(token);
      break;
    case InColumnGroupMode:
      ASSERT(getInsertionMode() == InColumnGroupMode);
      if (token->name() == htmlTag) {
        processHtmlStartTagForInBody(token);
        return;
      }
      if (token->name() == colTag) {
        m_tree.insertSelfClosingHTMLElementDestroyingToken(token);
        return;
      }
      if (token->name() == templateTag) {
        processTemplateStartTag(token);
        return;
      }
      if (!processColgroupEndTagForInColumnGroup()) {
        ASSERT(isParsingFragmentOrTemplateContents());
        return;
      }
      processStartTag(token);
      break;
    case InTableBodyMode:
      ASSERT(getInsertionMode() == InTableBodyMode);
      if (token->name() == trTag) {
        // How is there ever anything to pop?
        m_tree.openElements()->popUntilTableBodyScopeMarker();
        m_tree.insertHTMLElement(token);
        setInsertionMode(InRowMode);
        return;
      }
      if (isTableCellContextTag(token->name())) {
        parseError(token);
        processFakeStartTag(trTag);
        ASSERT(getInsertionMode() == InRowMode);
        processStartTag(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(token);
        return;
      }
      processStartTagForInTable(token);
      break;
    case InRowMode:
      ASSERT(getInsertionMode() == InRowMode);
      if (isTableCellContextTag(token->name())) {
        m_tree.openElements()->popUntilTableRowScopeMarker();
        m_tree.insertHTMLElement(token);
        setInsertionMode(InCellMode);
        m_tree.activeFormattingElements()->appendMarker();
        return;
      }
      if (token->name() == trTag || isCaptionColOrColgroupTag(token->name()) ||
          isTableBodyContextTag(token->name())) {
        if (!processTrEndTagForInRow()) {
          ASSERT(isParsingFragmentOrTemplateContents());
          return;
        }
        ASSERT(getInsertionMode() == InTableBodyMode);
        processStartTag(token);
        return;
      }
      processStartTagForInTable(token);
      break;
    case InCellMode:
      ASSERT(getInsertionMode() == InCellMode);
      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(token);
        return;
      }
      processStartTagForInBody(token);
      break;
    case AfterBodyMode:
    case AfterAfterBodyMode:
      ASSERT(getInsertionMode() == AfterBodyMode ||
             getInsertionMode() == AfterAfterBodyMode);
      if (token->name() == htmlTag) {
        processHtmlStartTagForInBody(token);
        return;
      }
      setInsertionMode(InBodyMode);
      processStartTag(token);
      break;
    case InHeadNoscriptMode:
      ASSERT(getInsertionMode() == InHeadNoscriptMode);
      if (token->name() == htmlTag) {
        processHtmlStartTagForInBody(token);
        return;
      }
      if (token->name() == basefontTag || token->name() == bgsoundTag ||
          token->name() == linkTag || token->name() == metaTag ||
          token->name() == noframesTag || token->name() == styleTag) {
        bool didProcess = processStartTagForInHead(token);
        ASSERT_UNUSED(didProcess, didProcess);
        return;
      }
      if (token->name() == htmlTag || token->name() == noscriptTag) {
        parseError(token);
        return;
      }
      defaultForInHeadNoscript();
      processToken(token);
      break;
    case InFramesetMode:
      ASSERT(getInsertionMode() == InFramesetMode);
      if (token->name() == htmlTag) {
        processHtmlStartTagForInBody(token);
        return;
      }
      if (token->name() == framesetTag) {
        m_tree.insertHTMLElement(token);
        return;
      }
      if (token->name() == frameTag) {
        m_tree.insertSelfClosingHTMLElementDestroyingToken(token);
        return;
      }
      if (token->name() == noframesTag) {
        processStartTagForInHead(token);
        return;
      }
      if (token->name() == templateTag) {
        processTemplateStartTag(token);
        return;
      }
      parseError(token);
      break;
    case AfterFramesetMode:
    case AfterAfterFramesetMode:
      ASSERT(getInsertionMode() == AfterFramesetMode ||
             getInsertionMode() == AfterAfterFramesetMode);
      if (token->name() == htmlTag) {
        processHtmlStartTagForInBody(token);
        return;
      }
      if (token->name() == noframesTag) {
        processStartTagForInHead(token);
        return;
      }
      parseError(token);
      break;
    case InSelectInTableMode:
      ASSERT(getInsertionMode() == InSelectInTableMode);
      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(&endSelect);
        processStartTag(token);
        return;
      }
    // Fall through
    case InSelectMode:
      ASSERT(getInsertionMode() == InSelectMode ||
             getInsertionMode() == InSelectInTableMode);
      if (token->name() == htmlTag) {
        processHtmlStartTagForInBody(token);
        return;
      }
      if (token->name() == optionTag) {
        if (m_tree.currentStackItem()->hasTagName(optionTag)) {
          AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
          processEndTag(&endOption);
        }
        m_tree.insertHTMLElement(token);
        return;
      }
      if (token->name() == optgroupTag) {
        if (m_tree.currentStackItem()->hasTagName(optionTag)) {
          AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
          processEndTag(&endOption);
        }
        if (m_tree.currentStackItem()->hasTagName(optgroupTag)) {
          AtomicHTMLToken endOptgroup(HTMLToken::EndTag,
                                      optgroupTag.localName());
          processEndTag(&endOptgroup);
        }
        m_tree.insertHTMLElement(token);
        return;
      }
      if (token->name() == selectTag) {
        parseError(token);
        AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
        processEndTag(&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(&endSelect);
        processStartTag(token);
        return;
      }
      if (token->name() == scriptTag) {
        bool didProcess = processStartTagForInHead(token);
        ASSERT_UNUSED(didProcess, didProcess);
        return;
      }
      if (token->name() == templateTag) {
        processTemplateStartTag(token);
        return;
      }
      break;
    case InTableTextMode:
      defaultForInTableText();
      processStartTag(token);
      break;
    case TextMode:
      ASSERT_NOT_REACHED();
      break;
    case TemplateContentsMode:
      if (token->name() == templateTag) {
        processTemplateStartTag(token);
        return;
      }

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

      InsertionMode insertionMode = TemplateContentsMode;
      if (token->name() == frameTag)
        insertionMode = InFramesetMode;
      else if (token->name() == colTag)
        insertionMode = InColumnGroupMode;
      else if (isCaptionColOrColgroupTag(token->name()) ||
               isTableBodyContextTag(token->name()))
        insertionMode = InTableMode;
      else if (token->name() == trTag)
        insertionMode = InTableBodyMode;
      else if (isTableCellContextTag(token->name()))
        insertionMode = InRowMode;
      else
        insertionMode = InBodyMode;

      ASSERT(insertionMode != TemplateContentsMode);
      ASSERT(m_templateInsertionModes.last() == TemplateContentsMode);
      m_templateInsertionModes.last() = insertionMode;
      setInsertionMode(insertionMode);

      processStartTag(token);
      break;
  }
}

void HTMLTreeBuilder::processHtmlStartTagForInBody(AtomicHTMLToken* token) {
  parseError(token);
  if (m_tree.openElements()->hasTemplateInHTMLScope()) {
    ASSERT(isParsingTemplateContents());
    return;
  }
  m_tree.insertHTMLHtmlStartTagInBody(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;
  }
  // Emit a more specific parse error based on stack contents.
  DVLOG(1) << "Not implmeneted.";
  setInsertionMode(AfterBodyMode);
  return true;
}

void HTMLTreeBuilder::processAnyOtherEndTagForInBody(AtomicHTMLToken* token) {
  ASSERT(token->type() == HTMLToken::EndTag);
  if (token->name() == menuitemTag)
    UseCounter::count(m_tree.currentNode()->document(),
                      UseCounter::MenuItemCloseTag);
  HTMLElementStack::ElementRecord* record = m_tree.openElements()->topRecord();
  while (1) {
    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 (item->isSpecialNode()) {
      parseError(token);
      return;
    }
    record = record->next();
  }
}

// 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.
    Element* formattingElement =
        m_tree.activeFormattingElements()->closestElementInScopeWithName(
            token->name());
    // 4.a
    if (!formattingElement)
      return processAnyOtherEndTagForInBody(token);
    // 4.c
    if ((m_tree.openElements()->contains(formattingElement)) &&
        !m_tree.openElements()->inScope(formattingElement)) {
      parseError(token);
      // Check the stack of open elements for a more specific parse error.
      DVLOG(1) << "Not implemented.";
      return;
    }
    // 4.b
    HTMLElementStack::ElementRecord* 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.
    HTMLElementStack::ElementRecord* 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));
    HTMLStackItem* commonAncestor =
        formattingElementRecord->next()->stackItem();
    // 8.
    HTMLFormattingElementList::Bookmark bookmark =
        m_tree.activeFormattingElements()->bookmarkFor(formattingElement);
    // 9.
    HTMLElementStack::ElementRecord* node = furthestBlock;
    HTMLElementStack::ElementRecord* nextNode = node->next();
    HTMLElementStack::ElementRecord* 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);
      // Save node->next() for the next iteration in case node is deleted in
      // 9.5.
      nextNode = node->next();
      // 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
      HTMLStackItem* newItem =
          m_tree.createElementFromSavedToken(node->stackItem());

      HTMLFormattingElementList::Entry* nodeEntry =
          m_tree.activeFormattingElements()->find(node->element());
      nodeEntry->replaceElement(newItem);
      node->replaceElement(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, lastNode);
    // 11.
    HTMLStackItem* newItem = m_tree.createElementFromSavedToken(
        formattingElementRecord->stackItem());
    // 12.
    m_tree.takeAllChildren(newItem, furthestBlock);
    // 13.
    m_tree.reparent(furthestBlock, newItem);
    // 14.
    m_tree.activeFormattingElements()->swapTo(formattingElement, newItem,
                                              bookmark);
    // 15.
    m_tree.openElements()->remove(formattingElement);
    m_tree.openElements()->insertAbove(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;
  HTMLElementStack::ElementRecord* nodeRecord =
      m_tree.openElements()->topRecord();
  while (1) {
    HTMLStackItem* item = nodeRecord->stackItem();
    if (item->node() == m_tree.openElements()->rootNode()) {
      last = true;
      if (isParsingFragment())
        item = m_fragmentContext.contextElementStackItem();
    }
    if (item->hasTagName(templateTag))
      return setInsertionMode(m_templateInsertionModes.last());
    if (item->hasTagName(selectTag)) {
      if (!last) {
        while (item->node() != m_tree.openElements()->rootNode() &&
               !item->hasTagName(templateTag)) {
          nodeRecord = nodeRecord->next();
          item = nodeRecord->stackItem();
          if (item->hasTagName(tableTag))
            return setInsertionMode(InSelectInTableMode);
        }
      }
      return setInsertionMode(InSelectMode);
    }
    if (item->hasTagName(tdTag) || item->hasTagName(thTag))
      return setInsertionMode(InCellMode);
    if (item->hasTagName(trTag))
      return setInsertionMode(InRowMode);
    if (item->hasTagName(tbodyTag) || item->hasTagName(theadTag) ||
        item->hasTagName(tfootTag))
      return setInsertionMode(InTableBodyMode);
    if (item->hasTagName(captionTag))
      return setInsertionMode(InCaptionMode);
    if (item->hasTagName(colgroupTag)) {
      return setInsertionMode(InColumnGroupMode);
    }
    if (item->hasTagName(tableTag))
      return setInsertionMode(InTableMode);
    if (item->hasTagName(headTag)) {
      if (!m_fragmentContext.fragment() ||
          m_fragmentContext.contextElement() != item->node())
        return setInsertionMode(InHeadMode);
      return setInsertionMode(InBodyMode);
    }
    if (item->hasTagName(bodyTag))
      return setInsertionMode(InBodyMode);
    if (item->hasTagName(framesetTag)) {
      return setInsertionMode(InFramesetMode);
    }
    if (item->hasTagName(htmlTag)) {
      if (m_tree.headStackItem())
        return setInsertionMode(AfterHeadMode);

      ASSERT(isParsingFragment());
      return setInsertionMode(BeforeHeadMode);
    }
    if (last) {
      ASSERT(isParsingFragment());
      return setInsertionMode(InBodyMode);
    }
    nodeRecord = nodeRecord->next();
  }
}

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();
    setInsertionMode(InTableMode);
    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(token);
    return;
  }
  if (token->name() == bodyTag || isCaptionColOrColgroupTag(token->name()) ||
      token->name() == htmlTag || isTableCellContextTag(token->name()) ||
      token->name() == trTag) {
    parseError(token);
    return;
  }
  processEndTagForInTable(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(getInsertionMode() == InTableBodyMode);
    processEndTag(token);
    return;
  }
  if (isTableBodyContextTag(token->name())) {
    if (!m_tree.openElements()->inTableScope(token->name())) {
      parseError(token);
      return;
    }
    processFakeEndTag(trTag);
    ASSERT(getInsertionMode() == InTableBodyMode);
    processEndTag(token);
    return;
  }
  if (token->name() == bodyTag || isCaptionColOrColgroupTag(token->name()) ||
      token->name() == htmlTag || isTableCellContextTag(token->name())) {
    parseError(token);
    return;
  }
  processEndTagForInTable(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();
    setInsertionMode(InRowMode);
    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(token);
    return;
  }
  processEndTagForInBody(token);
}

void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token) {
  ASSERT(token->type() == HTMLToken::EndTag);
  if (token->name() == bodyTag) {
    processBodyEndTagForInBody(token);
    return;
  }
  if (token->name() == htmlTag) {
    AtomicHTMLToken endBody(HTMLToken::EndTag, bodyTag.localName());
    if (processBodyEndTagForInBody(&endBody))
      processEndTag(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 && !isParsingTemplateContents()) {
    Element* node = m_tree.takeForm();
    if (!node || !m_tree.openElements()->inScope(node)) {
      parseError(token);
      return;
    }
    m_tree.generateImpliedEndTags();
    if (m_tree.currentElement() != node)
      parseError(token);
    m_tree.openElements()->remove(node);
  }
  if (token->name() == pTag) {
    if (!m_tree.openElements()->inButtonScope(token->name())) {
      parseError(token);
      processFakeStartTag(pTag);
      ASSERT(m_tree.openElements()->inScope(token->name()));
      processEndTag(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 (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(token);
    return;
  }
  processAnyOtherEndTagForInBody(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();
  setInsertionMode(InTableMode);
  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();
  setInsertionMode(InTableBodyMode);
  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(token);
}

void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token) {
  ASSERT(token->type() == HTMLToken::EndTag);
  switch (getInsertionMode()) {
    case InitialMode:
      ASSERT(getInsertionMode() == InitialMode);
      defaultForInitial();
    // Fall through.
    case BeforeHTMLMode:
      ASSERT(getInsertionMode() == BeforeHTMLMode);
      if (token->name() != headTag && token->name() != bodyTag &&
          token->name() != htmlTag && token->name() != brTag) {
        parseError(token);
        return;
      }
      defaultForBeforeHTML();
    // Fall through.
    case BeforeHeadMode:
      ASSERT(getInsertionMode() == BeforeHeadMode);
      if (token->name() != headTag && token->name() != bodyTag &&
          token->name() != htmlTag && token->name() != brTag) {
        parseError(token);
        return;
      }
      defaultForBeforeHead();
    // Fall through.
    case InHeadMode:
      ASSERT(getInsertionMode() == InHeadMode);
      // 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 AfterHeadMode, that gets a little messy.
      if (token->name() == templateTag) {
        processTemplateEndTag(token);
        return;
      }
      if (token->name() == headTag) {
        m_tree.openElements()->popHTMLHeadElement();
        setInsertionMode(AfterHeadMode);
        return;
      }
      if (token->name() != bodyTag && token->name() != htmlTag &&
          token->name() != brTag) {
        parseError(token);
        return;
      }
      defaultForInHead();
    // Fall through.
    case AfterHeadMode:
      ASSERT(getInsertionMode() == AfterHeadMode);
      if (token->name() != bodyTag && token->name() != htmlTag &&
          token->name() != brTag) {
        parseError(token);
        return;
      }
      defaultForAfterHead();
    // Fall through
    case InBodyMode:
      ASSERT(getInsertionMode() == InBodyMode);
      processEndTagForInBody(token);
      break;
    case InTableMode:
      ASSERT(getInsertionMode() == InTableMode);
      processEndTagForInTable(token);
      break;
    case InCaptionMode:
      ASSERT(getInsertionMode() == InCaptionMode);
      if (token->name() == captionTag) {
        processCaptionEndTagForInCaption();
        return;
      }
      if (token->name() == tableTag) {
        parseError(token);
        if (!processCaptionEndTagForInCaption()) {
          ASSERT(isParsingFragment());
          return;
        }
        processEndTag(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(token);
      break;
    case InColumnGroupMode:
      ASSERT(getInsertionMode() == InColumnGroupMode);
      if (token->name() == colgroupTag) {
        processColgroupEndTagForInColumnGroup();
        return;
      }
      if (token->name() == colTag) {
        parseError(token);
        return;
      }
      if (token->name() == templateTag) {
        processTemplateEndTag(token);
        return;
      }
      if (!processColgroupEndTagForInColumnGroup()) {
        ASSERT(isParsingFragmentOrTemplateContents());
        return;
      }
      processEndTag(token);
      break;
    case InRowMode:
      ASSERT(getInsertionMode() == InRowMode);
      processEndTagForInRow(token);
      break;
    case InCellMode:
      ASSERT(getInsertionMode() == InCellMode);
      processEndTagForInCell(token);
      break;
    case InTableBodyMode:
      ASSERT(getInsertionMode() == InTableBodyMode);
      processEndTagForInTableBody(token);
      break;
    case AfterBodyMode:
      ASSERT(getInsertionMode() == AfterBodyMode);
      if (token->name() == htmlTag) {
        if (isParsingFragment()) {
          parseError(token);
          return;
        }
        setInsertionMode(AfterAfterBodyMode);
        return;
      }
    // Fall through.
    case AfterAfterBodyMode:
      ASSERT(getInsertionMode() == AfterBodyMode ||
             getInsertionMode() == AfterAfterBodyMode);
      parseError(token);
      setInsertionMode(InBodyMode);
      processEndTag(token);
      break;
    case InHeadNoscriptMode:
      ASSERT(getInsertionMode() == InHeadNoscriptMode);
      if (token->name() == noscriptTag) {
        ASSERT(m_tree.currentStackItem()->hasTagName(noscriptTag));
        m_tree.openElements()->pop();
        ASSERT(m_tree.currentStackItem()->hasTagName(headTag));
        setInsertionMode(InHeadMode);
        return;
      }
      if (token->name() != brTag) {
        parseError(token);
        return;
      }
      defaultForInHeadNoscript();
      processToken(token);
      break;
    case TextMode:
      if (token->name() == scriptTag &&
          m_tree.currentStackItem()->hasTagName(scriptTag)) {
        // Pause ourselves so that parsing stops until the script can be
        // processed by the caller.
        if (scriptingContentIsAllowed(m_tree.getParserContentPolicy()))
          m_scriptToProcess = m_tree.currentElement();
        m_tree.openElements()->pop();
        setInsertionMode(m_originalInsertionMode);

        if (m_parser->tokenizer()) {
          // We must set the tokenizer's state to DataState explicitly if the
          // tokenizer didn't have a chance to.
          m_parser->tokenizer()->setState(HTMLTokenizer::DataState);
        }
        return;
      }
      m_tree.openElements()->pop();
      setInsertionMode(m_originalInsertionMode);
      break;
    case InFramesetMode:
      ASSERT(getInsertionMode() == InFramesetMode);
      if (token->name() == framesetTag) {
        bool ignoreFramesetForFragmentParsing = m_tree.currentIsRootNode();
        ignoreFramesetForFragmentParsing =
            ignoreFramesetForFragmentParsing ||
            m_tree.openElements()->hasTemplateInHTMLScope();
        if (ignoreFramesetForFragmentParsing) {
          ASSERT(isParsingFragmentOrTemplateContents());
          parseError(token);
          return;
        }
        m_tree.openElements()->pop();
        if (!isParsingFragment() &&
            !m_tree.currentStackItem()->hasTagName(framesetTag))
          setInsertionMode(AfterFramesetMode);
        return;
      }
      if (token->name() == templateTag) {
        processTemplateEndTag(token);
        return;
      }
      break;
    case AfterFramesetMode:
      ASSERT(getInsertionMode() == AfterFramesetMode);
      if (token->name() == htmlTag) {
        setInsertionMode(AfterAfterFramesetMode);
        return;
      }
    // Fall through.
    case AfterAfterFramesetMode:
      ASSERT(getInsertionMode() == AfterFramesetMode ||
             getInsertionMode() == AfterAfterFramesetMode);
      parseError(token);
      break;
    case InSelectInTableMode:
      ASSERT(getInsertionMode() == InSelectInTableMode);
      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(&endSelect);
          processEndTag(token);
        }
        return;
      }
    // Fall through.
    case InSelectMode:
      ASSERT(getInsertionMode() == InSelectMode ||
             getInsertionMode() == InSelectInTableMode);
      if (token->name() == optgroupTag) {
        if (m_tree.currentStackItem()->hasTagName(optionTag) &&
            m_tree.oneBelowTop() &&
            m_tree.oneBelowTop()->hasTagName(optgroupTag))
          processFakeEndTag(optionTag);
        if (m_tree.currentStackItem()->hasTagName(optgroupTag)) {
          m_tree.openElements()->pop();
          return;
        }
        parseError(token);
        return;
      }
      if (token->name() == optionTag) {
        if (m_tree.currentStackItem()->hasTagName(optionTag)) {
          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(token);
        return;
      }
      break;
    case InTableTextMode:
      defaultForInTableText();
      processEndTag(token);
      break;
    case TemplateContentsMode:
      if (token->name() == templateTag) {
        processTemplateEndTag(token);
        return;
      }
      break;
  }
}

void HTMLTreeBuilder::processComment(AtomicHTMLToken* token) {
  ASSERT(token->type() == HTMLToken::Comment);
  if (m_insertionMode == InitialMode || m_insertionMode == BeforeHTMLMode ||
      m_insertionMode == AfterAfterBodyMode ||
      m_insertionMode == AfterAfterFramesetMode) {
    m_tree.insertCommentOnDocument(token);
    return;
  }
  if (m_insertionMode == AfterBodyMode) {
    m_tree.insertCommentOnHTMLHtmlElement(token);
    return;
  }
  if (m_insertionMode == InTableTextMode) {
    defaultForInTableText();
    processComment(token);
    return;
  }
  m_tree.insertComment(token);
}

void HTMLTreeBuilder::processCharacter(AtomicHTMLToken* token) {
  ASSERT(token->type() == HTMLToken::Character);
  CharacterTokenBuffer buffer(token);
  processCharacterBuffer(buffer);
}

void HTMLTreeBuilder::processCharacterBuffer(CharacterTokenBuffer& 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 (getInsertionMode()) {
    case InitialMode: {
      ASSERT(getInsertionMode() == InitialMode);
      buffer.skipLeadingWhitespace();
      if (buffer.isEmpty())
        return;
      defaultForInitial();
      // Fall through.
    }
    case BeforeHTMLMode: {
      ASSERT(getInsertionMode() == BeforeHTMLMode);
      buffer.skipLeadingWhitespace();
      if (buffer.isEmpty())
        return;
      defaultForBeforeHTML();
      if (m_parser->isStopped()) {
        buffer.skipRemaining();
        return;
      }
      // Fall through.
    }
    case BeforeHeadMode: {
      ASSERT(getInsertionMode() == BeforeHeadMode);
      buffer.skipLeadingWhitespace();
      if (buffer.isEmpty())
        return;
      defaultForBeforeHead();
      // Fall through.
    }
    case InHeadMode: {
      ASSERT(getInsertionMode() == InHeadMode);
      String leadingWhitespace = buffer.takeLeadingWhitespace();
      if (!leadingWhitespace.isEmpty())
        m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
      if (buffer.isEmpty())
        return;
      defaultForInHead();
      // Fall through.
    }
    case AfterHeadMode: {
      ASSERT(getInsertionMode() == AfterHeadMode);
      String leadingWhitespace = buffer.takeLeadingWhitespace();
      if (!leadingWhitespace.isEmpty())
        m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
      if (buffer.isEmpty())
        return;
      defaultForAfterHead();
      // Fall through.
    }
    case InBodyMode:
    case InCaptionMode:
    case TemplateContentsMode:
    case InCellMode: {
      ASSERT(getInsertionMode() == InBodyMode ||
             getInsertionMode() == InCaptionMode ||
             getInsertionMode() == InCellMode ||
             getInsertionMode() == TemplateContentsMode);
      processCharacterBufferForInBody(buffer);
      break;
    }
    case InTableMode:
    case InTableBodyMode:
    case InRowMode: {
      ASSERT(getInsertionMode() == InTableMode ||
             getInsertionMode() == InTableBodyMode ||
             getInsertionMode() == InRowMode);
      ASSERT(m_pendingTableCharacters.isEmpty());
      if (m_tree.currentStackItem()->isElementNode() &&
          (m_tree.currentStackItem()->hasTagName(tableTag) ||
           m_tree.currentStackItem()->hasTagName(tbodyTag) ||
           m_tree.currentStackItem()->hasTagName(tfootTag) ||
           m_tree.currentStackItem()->hasTagName(theadTag) ||
           m_tree.currentStackItem()->hasTagName(trTag))) {
        m_originalInsertionMode = m_insertionMode;
        setInsertionMode(InTableTextMode);
        // Note that we fall through to the InTableTextMode case below.
      } else {
        HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
        processCharacterBufferForInBody(buffer);
        break;
      }
      // Fall through.
    }
    case InTableTextMode: {
      buffer.giveRemainingTo(m_pendingTableCharacters);
      break;
    }
    case InColumnGroupMode: {
      ASSERT(getInsertionMode() == InColumnGroupMode);
      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 AfterBodyMode:
    case AfterAfterBodyMode: {
      ASSERT(getInsertionMode() == AfterBodyMode ||
             getInsertionMode() == AfterAfterBodyMode);
      // FIXME: parse error
      setInsertionMode(InBodyMode);
      goto ReprocessBuffer;
    }
    case TextMode: {
      ASSERT(getInsertionMode() == TextMode);
      m_tree.insertTextNode(buffer.takeRemaining());
      break;
    }
    case InHeadNoscriptMode: {
      ASSERT(getInsertionMode() == InHeadNoscriptMode);
      String leadingWhitespace = buffer.takeLeadingWhitespace();
      if (!leadingWhitespace.isEmpty())
        m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
      if (buffer.isEmpty())
        return;
      defaultForInHeadNoscript();
      goto ReprocessBuffer;
    }
    case InFramesetMode:
    case AfterFramesetMode: {
      ASSERT(getInsertionMode() == InFramesetMode ||
             getInsertionMode() == AfterFramesetMode ||
             getInsertionMode() == AfterAfterFramesetMode);
      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 InSelectInTableMode:
    case InSelectMode: {
      ASSERT(getInsertionMode() == InSelectMode ||
             getInsertionMode() == InSelectInTableMode);
      m_tree.insertTextNode(buffer.takeRemaining());
      break;
    }
    case AfterAfterFramesetMode: {
      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(
    CharacterTokenBuffer& buffer) {
  m_tree.reconstructTheActiveFormattingElements();
  const String& characters = buffer.takeRemaining();
  m_tree.insertTextNode(characters);
  if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
    m_framesetOk = false;
}

void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken* token) {
  ASSERT(token->type() == HTMLToken::EndOfFile);
  switch (getInsertionMode()) {
    case InitialMode:
      ASSERT(getInsertionMode() == InitialMode);
      defaultForInitial();
    // Fall through.
    case BeforeHTMLMode:
      ASSERT(getInsertionMode() == BeforeHTMLMode);
      defaultForBeforeHTML();
    // Fall through.
    case BeforeHeadMode:
      ASSERT(getInsertionMode() == BeforeHeadMode);
      defaultForBeforeHead();
    // Fall through.
    case InHeadMode:
      ASSERT(getInsertionMode() == InHeadMode);
      defaultForInHead();
    // Fall through.
    case AfterHeadMode:
      ASSERT(getInsertionMode() == AfterHeadMode);
      defaultForAfterHead();
    // Fall through
    case InBodyMode:
    case InCellMode:
    case InCaptionMode:
    case InRowMode:
      ASSERT(getInsertionMode() == InBodyMode ||
             getInsertionMode() == InCellMode ||
             getInsertionMode() == InCaptionMode ||
             getInsertionMode() == InRowMode ||
             getInsertionMode() == TemplateContentsMode);
      // Emit parse error based on what elements are still open.
      DVLOG(1) << "Not implemented.";
      if (!m_templateInsertionModes.isEmpty() &&
          processEndOfFileForInTemplateContents(token))
        return;
      break;
    case AfterBodyMode:
    case AfterAfterBodyMode:
      ASSERT(getInsertionMode() == AfterBodyMode ||
             getInsertionMode() == AfterAfterBodyMode);
      break;
    case InHeadNoscriptMode:
      ASSERT(getInsertionMode() == InHeadNoscriptMode);
      defaultForInHeadNoscript();
      processEndOfFile(token);
      return;
    case AfterFramesetMode:
    case AfterAfterFramesetMode:
      ASSERT(getInsertionMode() == AfterFramesetMode ||
             getInsertionMode() == AfterAfterFramesetMode);
      break;
    case InColumnGroupMode:
      if (m_tree.currentIsRootNode()) {
        ASSERT(isParsingFragment());
        return;  // FIXME: Should we break here instead of returning?
      }
      ASSERT(m_tree.currentNode()->hasTagName(colgroupTag) ||
             isHTMLTemplateElement(m_tree.currentNode()));
      processColgroupEndTagForInColumnGroup();
    // Fall through
    case InFramesetMode:
    case InTableMode:
    case InTableBodyMode:
    case InSelectInTableMode:
    case InSelectMode:
      ASSERT(getInsertionMode() == InSelectMode ||
             getInsertionMode() == InSelectInTableMode ||
             getInsertionMode() == InTableMode ||
             getInsertionMode() == InFramesetMode ||
             getInsertionMode() == InTableBodyMode ||
             getInsertionMode() == InColumnGroupMode);
      if (m_tree.currentNode() != m_tree.openElements()->rootNode())
        parseError(token);
      if (!m_templateInsertionModes.isEmpty() &&
          processEndOfFileForInTemplateContents(token))
        return;
      break;
    case InTableTextMode:
      defaultForInTableText();
      processEndOfFile(token);
      return;
    case TextMode:
      parseError(token);
      if (m_tree.currentStackItem()->hasTagName(scriptTag)) {
        // Mark the script element as "already started".
        DVLOG(1) << "Not implemented.";
      }
      m_tree.openElements()->pop();
      ASSERT(m_originalInsertionMode != TextMode);
      setInsertionMode(m_originalInsertionMode);
      processEndOfFile(token);
      return;
    case TemplateContentsMode:
      if (processEndOfFileForInTemplateContents(token))
        return;
      break;
  }
  m_tree.processEndOfFile();
}

void HTMLTreeBuilder::defaultForInitial() {
  DVLOG(1) << "Not implemented.";
  m_tree.setDefaultCompatibilityMode();
  // FIXME: parse error
  setInsertionMode(BeforeHTMLMode);
}

void HTMLTreeBuilder::defaultForBeforeHTML() {
  AtomicHTMLToken startHTML(HTMLToken::StartTag, htmlTag.localName());
  m_tree.insertHTMLHtmlStartTagBeforeHTML(&startHTML);
  setInsertionMode(BeforeHeadMode);
}

void HTMLTreeBuilder::defaultForBeforeHead() {
  AtomicHTMLToken startHead(HTMLToken::StartTag, headTag.localName());
  processStartTag(&startHead);
}

void HTMLTreeBuilder::defaultForInHead() {
  AtomicHTMLToken endHead(HTMLToken::EndTag, headTag.localName());
  processEndTag(&endHead);
}

void HTMLTreeBuilder::defaultForInHeadNoscript() {
  AtomicHTMLToken endNoscript(HTMLToken::EndTag, noscriptTag.localName());
  processEndTag(&endNoscript);
}

void HTMLTreeBuilder::defaultForAfterHead() {
  AtomicHTMLToken startBody(HTMLToken::StartTag, bodyTag.localName());
  processStartTag(&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;
    setInsertionMode(m_originalInsertionMode);
    return;
  }
  m_tree.insertTextNode(characters);
  setInsertionMode(m_originalInsertionMode);
}

bool HTMLTreeBuilder::processStartTagForInHead(AtomicHTMLToken* token) {
  ASSERT(token->type() == HTMLToken::StartTag);
  if (token->name() == htmlTag) {
    processHtmlStartTagForInBody(token);
    return true;
  }
  if (token->name() == baseTag || token->name() == basefontTag ||
      token->name() == bgsoundTag || token->name() == commandTag ||
      token->name() == linkTag || token->name() == metaTag) {
    m_tree.insertSelfClosingHTMLElementDestroyingToken(token);
    // Note: The custom processing for the <meta> tag is done in
    // HTMLMetaElement::process().
    return true;
  }
  if (token->name() == titleTag) {
    processGenericRCDATAStartTag(token);
    return true;
  }
  if (token->name() == noscriptTag) {
    if (m_options.scriptEnabled) {
      processGenericRawTextStartTag(token);
      return true;
    }
    m_tree.insertHTMLElement(token);
    setInsertionMode(InHeadNoscriptMode);
    return true;
  }
  if (token->name() == noframesTag || token->name() == styleTag) {
    processGenericRawTextStartTag(token);
    return true;
  }
  if (token->name() == scriptTag) {
    processScriptStartTag(token);
    return true;
  }
  if (token->name() == templateTag) {
    processTemplateStartTag(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(token);
  if (m_parser->tokenizer())
    m_parser->tokenizer()->setState(HTMLTokenizer::RCDATAState);
  m_originalInsertionMode = m_insertionMode;
  setInsertionMode(TextMode);
}

void HTMLTreeBuilder::processGenericRawTextStartTag(AtomicHTMLToken* token) {
  ASSERT(token->type() == HTMLToken::StartTag);
  m_tree.insertHTMLElement(token);
  if (m_parser->tokenizer())
    m_parser->tokenizer()->setState(HTMLTokenizer::RAWTEXTState);
  m_originalInsertionMode = m_insertionMode;
  setInsertionMode(TextMode);
}

void HTMLTreeBuilder::processScriptStartTag(AtomicHTMLToken* token) {
  ASSERT(token->type() == HTMLToken::StartTag);
  m_tree.insertScriptElement(token);
  if (m_parser->tokenizer())
    m_parser->tokenizer()->setState(HTMLTokenizer::ScriptDataState);
  m_originalInsertionMode = m_insertionMode;

  TextPosition position = m_parser->textPosition();

  m_scriptToProcessStartPosition = position;

  setInsertionMode(TextMode);
}

// http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#tree-construction
bool HTMLTreeBuilder::shouldProcessTokenInForeignContent(
    AtomicHTMLToken* token) {
  if (m_tree.isEmpty())
    return false;
  HTMLStackItem* adjustedCurrentNode = adjustedCurrentStackItem();

  if (adjustedCurrentNode->isInHTMLNamespace())
    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;
}

void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token) {
  if (token->type() == HTMLToken::Character) {
    const String& characters = token->characters();
    m_tree.insertTextNode(characters);
    if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
      m_framesetOk = false;
    return;
  }

  m_tree.flush(FlushAlways);
  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 && (token->getAttributeItem(colorAttr) ||
                                        token->getAttributeItem(faceAttr) ||
                                        token->getAttributeItem(sizeAttr)))) {
        parseError(token);
        m_tree.openElements()->popUntilForeignContentScopeMarker();
        processStartTag(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(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.getParserContentPolicy()))
          m_scriptToProcess = m_tree.currentElement();
        m_tree.openElements()->pop();
        return;
      }
      if (!m_tree.currentStackItem()->isInHTMLNamespace()) {
        // FIXME: This code just wants an Element* iterator, instead of an
        // ElementRecord*
        HTMLElementStack::ElementRecord* nodeRecord =
            m_tree.openElements()->topRecord();
        if (!nodeRecord->stackItem()->hasLocalName(token->name()))
          parseError(token);
        while (1) {
          if (nodeRecord->stackItem()->hasLocalName(token->name())) {
            m_tree.openElements()->popUntilPopped(nodeRecord->element());
            return;
          }
          nodeRecord = nodeRecord->next();

          if (nodeRecord->stackItem()->isInHTMLNamespace())
            break;
        }
      }
      // Otherwise, process the token according to the rules given in the
      // section corresponding to the current insertion mode in HTML content.
      processEndTag(token);
      break;
    }
    case HTMLToken::Comment:
      m_tree.insertComment(token);
      break;
    case HTMLToken::Character:
    case HTMLToken::EndOfFile:
      ASSERT_NOT_REACHED();
      break;
  }
}

void HTMLTreeBuilder::finished() {
  if (isParsingFragment())
    return;

  ASSERT(m_templateInsertionModes.isEmpty());
  ASSERT(m_isAttached);
  // Warning, this may detach the parser. Do not do anything else after this.
  m_tree.finishedParsing();
}

void HTMLTreeBuilder::parseError(AtomicHTMLToken*) {}

#ifndef NDEBUG
const char* HTMLTreeBuilder::toString(HTMLTreeBuilder::InsertionMode mode) {
  switch (mode) {
#define DEFINE_STRINGIFY(mode) \
  case mode:                   \
    return #mode;
    DEFINE_STRINGIFY(InitialMode)
    DEFINE_STRINGIFY(BeforeHTMLMode)
    DEFINE_STRINGIFY(BeforeHeadMode)
    DEFINE_STRINGIFY(InHeadMode)
    DEFINE_STRINGIFY(InHeadNoscriptMode)
    DEFINE_STRINGIFY(AfterHeadMode)
    DEFINE_STRINGIFY(TemplateContentsMode)
    DEFINE_STRINGIFY(InBodyMode)
    DEFINE_STRINGIFY(TextMode)
    DEFINE_STRINGIFY(InTableMode)
    DEFINE_STRINGIFY(InTableTextMode)
    DEFINE_STRINGIFY(InCaptionMode)
    DEFINE_STRINGIFY(InColumnGroupMode)
    DEFINE_STRINGIFY(InTableBodyMode)
    DEFINE_STRINGIFY(InRowMode)
    DEFINE_STRINGIFY(InCellMode)
    DEFINE_STRINGIFY(InSelectMode)
    DEFINE_STRINGIFY(InSelectInTableMode)
    DEFINE_STRINGIFY(AfterBodyMode)
    DEFINE_STRINGIFY(InFramesetMode)
    DEFINE_STRINGIFY(AfterFramesetMode)
    DEFINE_STRINGIFY(AfterAfterBodyMode)
    DEFINE_STRINGIFY(AfterAfterFramesetMode)
#undef DEFINE_STRINGIFY
  }
  return "<unknown>";
}
#endif

}  // namespace blink
