Re-land the HTMLTreeBuilder change with the assertion fixed.
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Jan 2015 18:17:05 +0000 (18:17 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Jan 2015 18:17:05 +0000 (18:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=140032

Reviewed by Andreas Kling.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@177863 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/html/parser/HTMLDocumentParser.cpp
Source/WebCore/html/parser/HTMLTreeBuilder.cpp
Source/WebCore/html/parser/HTMLTreeBuilder.h
Source/WebCore/html/parser/TextDocumentParser.cpp

index 58fe5c3bbe4141d52fee2f9ea8596bdadf04285d..0a53b146219bf6977ba1c63f6160f6c481bf653b 100644 (file)
@@ -1,3 +1,10 @@
+2015-01-02  Darin Adler  <darin@apple.com>
+
+        Re-land the HTMLTreeBuilder change with the assertion fixed.
+        https://bugs.webkit.org/show_bug.cgi?id=140032
+
+        Reviewed by Andreas Kling.
+
 2015-01-02  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r177859 and r177861.
index e0fb5fcab57893044ebca3c26d44cf326bffe7cc..20cff5c0fd7ea89115a06cf494856b845557efdd 100644 (file)
@@ -92,7 +92,7 @@ HTMLDocumentParser::HTMLDocumentParser(DocumentFragment& fragment, Element* cont
     , m_options(fragment.document())
     , m_token(std::make_unique<HTMLToken>())
     , m_tokenizer(std::make_unique<HTMLTokenizer>(m_options))
-    , m_treeBuilder(std::make_unique<HTMLTreeBuilder>(*this, fragment, contextElement, this->parserContentPolicy(), m_options))
+    , m_treeBuilder(std::make_unique<HTMLTreeBuilder>(*this, fragment, *contextElement, this->parserContentPolicy(), m_options))
     , m_xssAuditorDelegate(fragment.document())
     , m_endWasDelayed(false)
     , m_haveBackgroundParser(false)
@@ -118,7 +118,6 @@ void HTMLDocumentParser::detach()
 
     if (m_scriptRunner)
         m_scriptRunner->detach();
-    m_treeBuilder->detach();
     // FIXME: It seems wrong that we would have a preload scanner here.
     // Yet during fast/dom/HTMLScriptElement/script-load-events.html we do.
     m_preloadScanner = nullptr;
@@ -349,7 +348,7 @@ void HTMLDocumentParser::constructTreeFromHTMLToken(HTMLToken& rawToken)
     if (rawToken.type() != HTMLToken::Character)
         rawToken.clear();
 
-    m_treeBuilder->constructTree(&token);
+    m_treeBuilder->constructTree(token);
 
     if (!rawToken.isUninitialized()) {
         ASSERT(rawToken.type() == HTMLToken::Character);
index 19588ae7cb10d5259ea7e719d9c27f05ef30a5d5..bf03bba6a4ed63e7da3cc334043fa90e3c33f42e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 Google, Inc. All Rights Reserved.
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "HTMLFormControlElement.h"
 #include "HTMLFormElement.h"
 #include "HTMLOptGroupElement.h"
-#include "HTMLOptionElement.h"
 #include "HTMLParserIdioms.h"
-#include "HTMLTableElement.h"
-#include "HTMLTemplateElement.h"
 #include "LocalizedStrings.h"
 #include "NotImplemented.h"
 #include "XLinkNames.h"
 #include "XMLNSNames.h"
 #include "XMLNames.h"
-#include <wtf/MainThread.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/unicode/CharacterNames.h>
 
-#if ENABLE(TELEPHONE_NUMBER_DETECTION)
+#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
 #include "TelephoneNumberDetector.h"
 #endif
 
@@ -63,7 +59,7 @@ inline bool isHTMLSpaceOrReplacementCharacter(UChar character)
 
 }
 
-static TextPosition uninitializedPositionValue1()
+static inline TextPosition uninitializedPositionValue1()
 {
     return TextPosition(OrdinalNumber::fromOneBasedInt(-1), OrdinalNumber::first());
 }
@@ -90,9 +86,7 @@ static bool isNumberedHeaderTag(const AtomicString& tagName)
 
 static bool isCaptionColOrColgroupTag(const AtomicString& tagName)
 {
-    return tagName == captionTag
-        || tagName == colTag
-        || tagName == colgroupTag;
+    return tagName == captionTag || tagName == colTag || tagName == colgroupTag;
 }
 
 static bool isTableCellContextTag(const AtomicString& tagName)
@@ -102,9 +96,7 @@ static bool isTableCellContextTag(const AtomicString& tagName)
 
 static bool isTableBodyContextTag(const AtomicString& tagName)
 {
-    return tagName == tbodyTag
-        || tagName == tfootTag
-        || tagName == theadTag;
+    return tagName == tbodyTag || tagName == tfootTag || tagName == theadTag;
 }
 
 static bool isNonAnchorNonNobrFormattingTag(const AtomicString& tagName)
@@ -125,29 +117,27 @@ static bool isNonAnchorNonNobrFormattingTag(const AtomicString& tagName)
 
 static bool isNonAnchorFormattingTag(const AtomicString& tagName)
 {
-    return tagName == nobrTag
-        || isNonAnchorNonNobrFormattingTag(tagName);
+    return tagName == nobrTag || isNonAnchorNonNobrFormattingTag(tagName);
 }
 
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#formatting
+// https://html.spec.whatwg.org/multipage/syntax.html#formatting
 static bool isFormattingTag(const AtomicString& tagName)
 {
     return tagName == aTag || isNonAnchorFormattingTag(tagName);
 }
 
 class HTMLTreeBuilder::ExternalCharacterTokenBuffer {
-    WTF_MAKE_NONCOPYABLE(ExternalCharacterTokenBuffer);
 public:
-    explicit ExternalCharacterTokenBuffer(AtomicHTMLToken* token)
-        : m_text(token->characters(), token->charactersLength())
-        , m_isAll8BitData(token->isAll8BitData())
+    explicit ExternalCharacterTokenBuffer(AtomicHTMLToken& token)
+        : m_text(token.characters(), token.charactersLength())
+        , m_isAll8BitData(token.isAll8BitData())
     {
         ASSERT(!isEmpty());
     }
 
     explicit ExternalCharacterTokenBuffer(const String& string)
         : m_text(string)
-        , m_isAll8BitData(m_text.length() && m_text.is8Bit())
+        , m_isAll8BitData(m_text.is8Bit())
     {
         ASSERT(!isEmpty());
     }
@@ -185,11 +175,7 @@ public:
 
     String takeRemaining()
     {
-        String result;
-        if (m_text.is8Bit() || !isAll8BitData())
-            result = m_text.toString();
-        else
-            result = String::make8BitFrom16BitSource(m_text.characters16(), m_text.length());
+        String result = makeString(m_text);
         m_text = StringView();
         return result;
     }
@@ -221,8 +207,7 @@ public:
     }
 
 private:
-    template<bool characterPredicate(UChar)>
-    void skipLeading()
+    template<bool characterPredicate(UChar)> void skipLeading()
     {
         ASSERT(!isEmpty());
         while (characterPredicate(m_text[0])) {
@@ -232,122 +217,124 @@ private:
         }
     }
 
-    template<bool characterPredicate(UChar)>
-    String takeLeading()
+    template<bool characterPredicate(UChar)> String takeLeading()
     {
         ASSERT(!isEmpty());
         StringView start = m_text;
         skipLeading<characterPredicate>();
         if (start.length() == m_text.length())
             return String();
-        StringView leading = start.substring(0, start.length() - m_text.length());
-        if (leading.is8Bit() || !isAll8BitData())
-            return leading.toString();
-        return String::make8BitFrom16BitSource(leading.characters16(), leading.length());
+        return makeString(start.substring(0, start.length() - m_text.length()));
+    }
+
+    String makeString(StringView stringView) const
+    {
+        if (stringView.is8Bit() || !isAll8BitData())
+            return stringView.toString();
+        return String::make8BitFrom16BitSource(stringView.characters16(), stringView.length());
     }
 
     StringView m_text;
     bool m_isAll8BitData;
 };
 
-
-HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser& parser, HTMLDocument& document, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options)
-    : m_framesetOk(true)
-#ifndef NDEBUG
-    , m_isAttached(true)
+inline bool HTMLTreeBuilder::isParsingTemplateContents() const
+{
+#if ENABLE(TEMPLATE_ELEMENT)
+    return m_tree.openElements()->hasTemplateInHTMLScope();
+#else
+    return false;
 #endif
+}
+
+inline bool HTMLTreeBuilder::isParsingFragmentOrTemplateContents() const
+{
+    return isParsingFragment() || isParsingTemplateContents();
+}
+
+HTMLTreeBuilder::HTMLTreeBuilder(const HTMLDocumentParser& parser, HTMLDocument& document, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options)
+    : m_parser(parser)
+    , m_options(options)
     , m_tree(document, parserContentPolicy, options.maximumDOMTreeDepth)
-    , m_insertionMode(InsertionMode::Initial)
-    , m_originalInsertionMode(InsertionMode::Initial)
-    , m_shouldSkipLeadingNewline(false)
-    , m_parser(parser)
     , m_scriptToProcessStartPosition(uninitializedPositionValue1())
-    , m_options(options)
 {
+#if !ASSERT_DISABLED
+    m_destructionProhibited = false;
+#endif
 }
 
-// FIXME: Member variables should be grouped into self-initializing structs to
-// minimize code duplication between these constructors.
-HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser& parser, DocumentFragment& fragment, Element* contextElement, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options)
-    : m_framesetOk(true)
-#ifndef NDEBUG
-    , m_isAttached(true)
-#endif
+HTMLTreeBuilder::HTMLTreeBuilder(const HTMLDocumentParser& parser, DocumentFragment& fragment, Element& contextElement, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options)
+    : m_parser(parser)
+    , m_options(options)
     , m_fragmentContext(fragment, contextElement)
     , m_tree(fragment, parserContentPolicy, options.maximumDOMTreeDepth)
-    , m_insertionMode(InsertionMode::Initial)
-    , m_originalInsertionMode(InsertionMode::Initial)
-    , m_shouldSkipLeadingNewline(false)
-    , m_parser(parser)
     , m_scriptToProcessStartPosition(uninitializedPositionValue1())
-    , m_options(options)
 {
     ASSERT(isMainThread());
-    // FIXME: This assertion will become invalid if <http://webkit.org/b/60316> is fixed.
-    ASSERT(contextElement);
-    if (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));
+
+    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-html-fragments
+    // For efficiency, we skip step 5 ("Let root be a new html element with no attributes") and instead use the DocumentFragment as a root node.
+    m_tree.openElements()->pushRootNode(HTMLStackItem::create(&fragment, HTMLStackItem::ItemForDocumentFragmentNode));
 
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (contextElement->hasTagName(templateTag))
-            m_templateInsertionModes.append(InsertionMode::TemplateContents);
+    if (contextElement.hasTagName(templateTag))
+        m_templateInsertionModes.append(InsertionMode::TemplateContents);
 #endif
 
-        resetInsertionModeAppropriately();
-        m_tree.setForm(!contextElement || is<HTMLFormElement>(*contextElement) ? downcast<HTMLFormElement>(contextElement) : HTMLFormElement::findClosestFormAncestor(*contextElement));
-    }
-}
+    resetInsertionModeAppropriately();
 
-HTMLTreeBuilder::~HTMLTreeBuilder()
-{
-}
+    m_tree.setForm(is<HTMLFormElement>(contextElement) ? &downcast<HTMLFormElement>(contextElement) : HTMLFormElement::findClosestFormAncestor(contextElement));
 
-void HTMLTreeBuilder::detach()
-{
-#ifndef NDEBUG
-    // 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;
+#if !ASSERT_DISABLED
+    m_destructionProhibited = 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();
 }
 
 HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext()
-    : m_fragment(0)
 {
 }
 
-HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment& fragment, Element* contextElement)
+HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment& fragment, Element& contextElement)
     : m_fragment(&fragment)
 {
     ASSERT(!fragment.hasChildNodes());
-    m_contextElementStackItem = HTMLStackItem::create(contextElement, HTMLStackItem::ItemForContextElement);
+    m_contextElementStackItem = HTMLStackItem::create(&contextElement, HTMLStackItem::ItemForContextElement);
 }
 
-HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext()
+inline Element& HTMLTreeBuilder::FragmentParsingContext::contextElement() const
 {
+    return *contextElementStackItem().element();
 }
 
-PassRefPtr<Element> HTMLTreeBuilder::takeScriptToProcess(TextPosition& scriptStartPosition)
+inline HTMLStackItem& HTMLTreeBuilder::FragmentParsingContext::contextElementStackItem() const
 {
-    ASSERT(m_scriptToProcess);
+    ASSERT(m_fragment);
+    return *m_contextElementStackItem;
+}
+
+RefPtr<Element> HTMLTreeBuilder::takeScriptToProcess(TextPosition& scriptStartPosition)
+{
+    ASSERT(!m_destroyed);
+
+    if (!m_scriptToProcess)
+        return nullptr;
+
     // Unpause ourselves, callers may pause us again when processing the script.
-    // The HTML5 spec is written as though scripts are executed inside the tree
-    // builder.  We pause the parser to exit the tree builder, and then resume
-    // before running scripts.
+    // 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();
+    return WTF::move(m_scriptToProcess);
 }
 
-void HTMLTreeBuilder::constructTree(AtomicHTMLToken* token)
+void HTMLTreeBuilder::constructTree(AtomicHTMLToken& token)
 {
+#if !ASSERT_DISABLED
+    ASSERT(!m_destroyed);
+    ASSERT(!m_destructionProhibited);
+    m_destructionProhibited = true;
+#endif
+
     if (shouldProcessTokenInForeignContent(token))
         processTokenInForeignContent(token);
     else
@@ -355,7 +342,7 @@ void HTMLTreeBuilder::constructTree(AtomicHTMLToken* token)
 
     if (m_parser.tokenizer()) {
         bool inForeignContent = !m_tree.isEmpty()
-            && !adjustedCurrentStackItem()->isInHTMLNamespace()
+            && !adjustedCurrentStackItem().isInHTMLNamespace()
             && !HTMLElementStack::isHTMLIntegrationPoint(m_tree.currentStackItem())
             && !HTMLElementStack::isMathMLTextIntegrationPoint(m_tree.currentStackItem());
 
@@ -363,13 +350,17 @@ void HTMLTreeBuilder::constructTree(AtomicHTMLToken* token)
         m_parser.tokenizer()->setShouldAllowCDATA(inForeignContent);
     }
 
+#if !ASSERT_DISABLED
+    m_destructionProhibited = false;
+#endif
+
     m_tree.executeQueuedTasks();
-    // We might be detached now.
+    // The tree builder might have been destroyed as an indirect result of executing the queued tasks.
 }
 
-void HTMLTreeBuilder::processToken(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processToken(AtomicHTMLToken& token)
 {
-    switch (token->type()) {
+    switch (token.type()) {
     case HTMLToken::Uninitialized:
         ASSERT_NOT_REACHED();
         break;
@@ -399,12 +390,12 @@ void HTMLTreeBuilder::processToken(AtomicHTMLToken* token)
     }
 }
 
-void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::DOCTYPE);
+    ASSERT(token.type() == HTMLToken::DOCTYPE);
     if (m_insertionMode == InsertionMode::Initial) {
-        m_tree.insertDoctype(token);
-        setInsertionMode(InsertionMode::BeforeHTML);
+        m_tree.insertDoctype(&token);
+        m_insertionMode = InsertionMode::BeforeHTML;
         return;
     }
     if (m_insertionMode == InsertionMode::InTableText) {
@@ -415,17 +406,17 @@ void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken* token)
     parseError(token);
 }
 
-void HTMLTreeBuilder::processFakeStartTag(const QualifiedName& tagName, const Vector<Attribute>& attributes)
+void HTMLTreeBuilder::processFakeStartTag(const QualifiedName& tagName, Vector<Attribute>&& attributes)
 {
     // FIXME: We'll need a fancier conversion than just "localName" for SVG/MathML tags.
-    AtomicHTMLToken fakeToken(HTMLToken::StartTag, tagName.localName(), attributes);
-    processStartTag(&fakeToken);
+    AtomicHTMLToken fakeToken(HTMLToken::StartTag, tagName.localName(), WTF::move(attributes));
+    processStartTag(fakeToken);
 }
 
 void HTMLTreeBuilder::processFakeEndTag(const AtomicString& tagName)
 {
     AtomicHTMLToken fakeToken(HTMLToken::EndTag, tagName);
-    processEndTag(&fakeToken);
+    processEndTag(fakeToken);
 }
 
 void HTMLTreeBuilder::processFakeEndTag(const QualifiedName& tagName)
@@ -446,12 +437,12 @@ void HTMLTreeBuilder::processFakePEndTagIfPInButtonScope()
     if (!m_tree.openElements()->inButtonScope(pTag.localName()))
         return;
     AtomicHTMLToken endP(HTMLToken::EndTag, pTag.localName());
-    processEndTag(&endP);
+    processEndTag(endP);
 }
 
-Vector<Attribute> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken* token)
+Vector<Attribute> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken& token)
 {
-    Vector<Attribute> attributes = token->attributes();
+    Vector<Attribute> attributes = token.attributes();
     for (int i = attributes.size() - 1; i >= 0; --i) {
         const QualifiedName& name = attributes.at(i).name();
         if (name.matches(nameAttr) || name.matches(actionAttr) || name.matches(promptAttr))
@@ -462,21 +453,21 @@ Vector<Attribute> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken* to
     return attributes;
 }
 
-void HTMLTreeBuilder::processIsindexStartTagForInBody(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processIsindexStartTagForInBody(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::StartTag);
-    ASSERT(token->name() == isindexTag);
+    ASSERT(token.type() == HTMLToken::StartTag);
+    ASSERT(token.name() == isindexTag);
     parseError(token);
     if (m_tree.form() && !isParsingTemplateContents())
         return;
     notImplemented(); // Acknowledge self-closing flag
     processFakeStartTag(formTag);
-    Attribute* actionAttribute = token->getAttributeItem(actionAttr);
+    Attribute* actionAttribute = token.getAttributeItem(actionAttr);
     if (actionAttribute)
         m_tree.form()->setAttribute(actionAttr, actionAttribute->value());
     processFakeStartTag(hrTag);
     processFakeStartTag(labelTag);
-    Attribute* promptAttribute = token->getAttributeItem(promptAttr);
+    Attribute* promptAttribute = token.getAttributeItem(promptAttr);
     if (promptAttribute)
         processFakeCharacters(promptAttribute->value());
     else
@@ -490,41 +481,36 @@ void HTMLTreeBuilder::processIsindexStartTagForInBody(AtomicHTMLToken* token)
 
 namespace {
 
-bool isLi(const HTMLStackItem* item)
+bool isLi(const HTMLStackItem& item)
 {
-    return item->hasTagName(liTag);
+    return item.hasTagName(liTag);
 }
 
-bool isDdOrDt(const HTMLStackItem* item)
+bool isDdOrDt(const HTMLStackItem& item)
 {
-    return item->hasTagName(ddTag)
-        || item->hasTagName(dtTag);
+    return item.hasTagName(ddTag) || item.hasTagName(dtTag);
 }
 
 }
 
-template <bool shouldClose(const HTMLStackItem*)>
-void HTMLTreeBuilder::processCloseWhenNestedTag(AtomicHTMLToken* token)
+template <bool shouldClose(const HTMLStackItem&)> void HTMLTreeBuilder::processCloseWhenNestedTag(AtomicHTMLToken& token)
 {
     m_framesetOk = false;
-    HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord();
-    while (1) {
-        RefPtr<HTMLStackItem> item = nodeRecord->stackItem();
-        if (shouldClose(item.get())) {
-            ASSERT(item->isElementNode());
-            processFakeEndTag(item->localName());
+    for (auto* nodeRecord = m_tree.openElements()->topRecord(); ; nodeRecord = nodeRecord->next()) {
+        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))
+        if (item.isSpecialNode() && !item.hasTagName(addressTag) && !item.hasTagName(divTag) && !item.hasTagName(pTag))
             break;
-        nodeRecord = nodeRecord->next();
     }
     processFakePEndTagIfPInButtonScope();
-    m_tree.insertHTMLElement(token);
+    m_tree.insertHTMLElement(&token);
 }
 
-template <typename TableQualifiedName>
-static HashMap<AtomicString, QualifiedName> createCaseMap(const TableQualifiedName* const names[], unsigned length)
+template <typename TableQualifiedName> static HashMap<AtomicString, QualifiedName> createCaseMap(const TableQualifiedName* const names[], unsigned length)
 {
     HashMap<AtomicString, QualifiedName> map;
     for (unsigned i = 0; i < length; ++i) {
@@ -555,8 +541,7 @@ static inline void adjustAttributes(HashMap<AtomicString, QualifiedName>& map, A
     }
 }
 
-template<const QualifiedName* const* attributesTable(), unsigned attributesTableLength>
-static void adjustAttributes(AtomicHTMLToken& token)
+template<const QualifiedName* const* attributesTable(), unsigned attributesTableLength> static void adjustAttributes(AtomicHTMLToken& token)
 {
     static NeverDestroyed<HashMap<AtomicString, QualifiedName>> map = createCaseMap(attributesTable(), attributesTableLength);
     adjustAttributes(map, token);
@@ -600,28 +585,28 @@ static void adjustForeignAttributes(AtomicHTMLToken& token)
     adjustAttributes(map, token);
 }
 
-void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::StartTag);
-    if (token->name() == htmlTag) {
+    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) {
+    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) {
+    if (token.name() == bodyTag) {
         parseError(token);
         bool fragmentOrTemplateCase = !m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement();
 #if ENABLE(TEMPLATE_ELEMENT)
@@ -632,10 +617,10 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_framesetOk = false;
-        m_tree.insertHTMLBodyStartTagInBody(token);
+        m_tree.insertHTMLBodyStartTagInBody(&token);
         return;
     }
-    if (token->name() == framesetTag) {
+    if (token.name() == framesetTag) {
         parseError(token);
         if (!m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement()) {
             ASSERT(isParsingFragmentOrTemplateContents());
@@ -647,78 +632,78 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
         m_tree.openElements()->popUntil(m_tree.openElements()->bodyElement());
         m_tree.openElements()->popHTMLBodyElement();
         ASSERT(m_tree.openElements()->top() == m_tree.openElements()->htmlElement());
-        m_tree.insertHTMLElement(token);
-        setInsertionMode(InsertionMode::InFrameset);
-        return;
-    }
-    if (token->name() == addressTag
-        || token->name() == articleTag
-        || token->name() == asideTag
-        || token->name() == blockquoteTag
-        || token->name() == centerTag
-        || token->name() == detailsTag
-        || token->name() == dirTag
-        || token->name() == divTag
-        || token->name() == dlTag
-        || token->name() == fieldsetTag
-        || token->name() == figcaptionTag
-        || token->name() == figureTag
-        || token->name() == footerTag
-        || token->name() == headerTag
-        || token->name() == hgroupTag
-        || token->name() == mainTag
-        || token->name() == menuTag
-        || token->name() == navTag
-        || token->name() == olTag
-        || token->name() == pTag
-        || token->name() == sectionTag
-        || token->name() == summaryTag
-        || token->name() == ulTag) {
+        m_tree.insertHTMLElement(&token);
+        m_insertionMode = InsertionMode::InFrameset;
+        return;
+    }
+    if (token.name() == addressTag
+        || token.name() == articleTag
+        || token.name() == asideTag
+        || token.name() == blockquoteTag
+        || token.name() == centerTag
+        || token.name() == detailsTag
+        || token.name() == dirTag
+        || token.name() == divTag
+        || token.name() == dlTag
+        || token.name() == fieldsetTag
+        || token.name() == figcaptionTag
+        || token.name() == figureTag
+        || token.name() == footerTag
+        || token.name() == headerTag
+        || token.name() == hgroupTag
+        || token.name() == mainTag
+        || token.name() == menuTag
+        || token.name() == navTag
+        || token.name() == olTag
+        || token.name() == pTag
+        || token.name() == sectionTag
+        || token.name() == summaryTag
+        || token.name() == ulTag) {
         processFakePEndTagIfPInButtonScope();
-        m_tree.insertHTMLElement(token);
+        m_tree.insertHTMLElement(&token);
         return;
     }
-    if (isNumberedHeaderTag(token->name())) {
+    if (isNumberedHeaderTag(token.name())) {
         processFakePEndTagIfPInButtonScope();
         if (m_tree.currentStackItem()->isNumberedHeaderElement()) {
             parseError(token);
             m_tree.openElements()->pop();
         }
-        m_tree.insertHTMLElement(token);
+        m_tree.insertHTMLElement(&token);
         return;
     }
-    if (token->name() == preTag || token->name() == listingTag) {
+    if (token.name() == preTag || token.name() == listingTag) {
         processFakePEndTagIfPInButtonScope();
-        m_tree.insertHTMLElement(token);
+        m_tree.insertHTMLElement(&token);
         m_shouldSkipLeadingNewline = true;
         m_framesetOk = false;
         return;
     }
-    if (token->name() == formTag) {
+    if (token.name() == formTag) {
         if (m_tree.form() && !isParsingTemplateContents()) {
             parseError(token);
             return;
         }
         processFakePEndTagIfPInButtonScope();
-        m_tree.insertHTMLFormElement(token);
+        m_tree.insertHTMLFormElement(&token);
         return;
     }
-    if (token->name() == liTag) {
+    if (token.name() == liTag) {
         processCloseWhenNestedTag<isLi>(token);
         return;
     }
-    if (token->name() == ddTag || token->name() == dtTag) {
+    if (token.name() == ddTag || token.name() == dtTag) {
         processCloseWhenNestedTag<isDdOrDt>(token);
         return;
     }
-    if (token->name() == plaintextTag) {
+    if (token.name() == plaintextTag) {
         processFakePEndTagIfPInButtonScope();
-        m_tree.insertHTMLElement(token);
+        m_tree.insertHTMLElement(&token);
         if (m_parser.tokenizer())
             m_parser.tokenizer()->setState(HTMLTokenizer::PLAINTEXTState);
         return;
     }
-    if (token->name() == buttonTag) {
+    if (token.name() == buttonTag) {
         if (m_tree.openElements()->inScope(buttonTag)) {
             parseError(token);
             processFakeEndTag(buttonTag);
@@ -726,11 +711,11 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.reconstructTheActiveFormattingElements();
-        m_tree.insertHTMLElement(token);
+        m_tree.insertHTMLElement(&token);
         m_framesetOk = false;
         return;
     }
-    if (token->name() == aTag) {
+    if (token.name() == aTag) {
         Element* activeATag = m_tree.activeFormattingElements()->closestElementInScopeWithName(aTag.localName());
         if (activeATag) {
             parseError(token);
@@ -740,121 +725,117 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
                 m_tree.openElements()->remove(activeATag);
         }
         m_tree.reconstructTheActiveFormattingElements();
-        m_tree.insertFormattingElement(token);
+        m_tree.insertFormattingElement(&token);
         return;
     }
-    if (isNonAnchorNonNobrFormattingTag(token->name())) {
+    if (isNonAnchorNonNobrFormattingTag(token.name())) {
         m_tree.reconstructTheActiveFormattingElements();
-        m_tree.insertFormattingElement(token);
+        m_tree.insertFormattingElement(&token);
         return;
     }
-    if (token->name() == nobrTag) {
+    if (token.name() == nobrTag) {
         m_tree.reconstructTheActiveFormattingElements();
         if (m_tree.openElements()->inScope(nobrTag)) {
             parseError(token);
             processFakeEndTag(nobrTag);
             m_tree.reconstructTheActiveFormattingElements();
         }
-        m_tree.insertFormattingElement(token);
+        m_tree.insertFormattingElement(&token);
         return;
     }
-    if (token->name() == appletTag
-        || token->name() == embedTag
-        || token->name() == objectTag) {
+    if (token.name() == appletTag || token.name() == embedTag || token.name() == objectTag) {
         if (!pluginContentIsAllowed(m_tree.parserContentPolicy()))
             return;
     }
-    if (token->name() == appletTag
-        || token->name() == marqueeTag
-        || token->name() == objectTag) {
+    if (token.name() == appletTag || token.name() == marqueeTag || token.name() == objectTag) {
         m_tree.reconstructTheActiveFormattingElements();
-        m_tree.insertHTMLElement(token);
+        m_tree.insertHTMLElement(&token);
         m_tree.activeFormattingElements()->appendMarker();
         m_framesetOk = false;
         return;
     }
-    if (token->name() == tableTag) {
+    if (token.name() == tableTag) {
         if (!m_tree.inQuirksMode() && m_tree.openElements()->inButtonScope(pTag))
             processFakeEndTag(pTag);
-        m_tree.insertHTMLElement(token);
+        m_tree.insertHTMLElement(&token);
         m_framesetOk = false;
-        setInsertionMode(InsertionMode::InTable);
+        m_insertionMode = InsertionMode::InTable;
         return;
     }
-    if (token->name() == imageTag) {
+    if (token.name() == imageTag) {
         parseError(token);
         // Apparently we're not supposed to ask.
-        token->setName(imgTag.localName());
+        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) {
+    if (token.name() == areaTag
+        || token.name() == brTag
+        || token.name() == embedTag
+        || token.name() == imgTag
+        || token.name() == keygenTag
+        || token.name() == wbrTag) {
         m_tree.reconstructTheActiveFormattingElements();
-        m_tree.insertSelfClosingHTMLElement(token);
+        m_tree.insertSelfClosingHTMLElement(&token);
         m_framesetOk = false;
         return;
     }
-    if (token->name() == inputTag) {
-        Attribute* typeAttribute = token->getAttributeItem(typeAttr);
+    if (token.name() == inputTag) {
+        Attribute* typeAttribute = token.getAttributeItem(typeAttr);
         m_tree.reconstructTheActiveFormattingElements();
-        m_tree.insertSelfClosingHTMLElement(token);
+        m_tree.insertSelfClosingHTMLElement(&token);
         if (!typeAttribute || !equalIgnoringCase(typeAttribute->value(), "hidden"))
             m_framesetOk = false;
         return;
     }
-    if (token->name() == paramTag
-        || token->name() == sourceTag
-        || token->name() == trackTag) {
-        m_tree.insertSelfClosingHTMLElement(token);
+    if (token.name() == paramTag
+        || token.name() == sourceTag
+        || token.name() == trackTag) {
+        m_tree.insertSelfClosingHTMLElement(&token);
         return;
     }
-    if (token->name() == hrTag) {
+    if (token.name() == hrTag) {
         processFakePEndTagIfPInButtonScope();
-        m_tree.insertSelfClosingHTMLElement(token);
+        m_tree.insertSelfClosingHTMLElement(&token);
         m_framesetOk = false;
         return;
     }
-    if (token->name() == isindexTag) {
+    if (token.name() == isindexTag) {
         processIsindexStartTagForInBody(token);
         return;
     }
-    if (token->name() == textareaTag) {
-        m_tree.insertHTMLElement(token);
+    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(InsertionMode::Text);
+        m_insertionMode = InsertionMode::Text;
         return;
     }
-    if (token->name() == xmpTag) {
+    if (token.name() == xmpTag) {
         processFakePEndTagIfPInButtonScope();
         m_tree.reconstructTheActiveFormattingElements();
         m_framesetOk = false;
         processGenericRawTextStartTag(token);
         return;
     }
-    if (token->name() == iframeTag) {
+    if (token.name() == iframeTag) {
         m_framesetOk = false;
         processGenericRawTextStartTag(token);
         return;
     }
-    if (token->name() == noembedTag && m_options.pluginsEnabled) {
+    if (token.name() == noembedTag && m_options.pluginsEnabled) {
         processGenericRawTextStartTag(token);
         return;
     }
-    if (token->name() == noscriptTag && m_options.scriptEnabled) {
+    if (token.name() == noscriptTag && m_options.scriptEnabled) {
         processGenericRawTextStartTag(token);
         return;
     }
-    if (token->name() == selectTag) {
+    if (token.name() == selectTag) {
         m_tree.reconstructTheActiveFormattingElements();
-        m_tree.insertHTMLElement(token);
+        m_tree.insertHTMLElement(&token);
         m_framesetOk = false;
         if (m_insertionMode == InsertionMode::InTable
             || m_insertionMode == InsertionMode::InCaption
@@ -862,85 +843,86 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
             || m_insertionMode == InsertionMode::InTableBody
             || m_insertionMode == InsertionMode::InRow
             || m_insertionMode == InsertionMode::InCell)
-            setInsertionMode(InsertionMode::InSelectInTable);
+            m_insertionMode = InsertionMode::InSelectInTable;
         else
-            setInsertionMode(InsertionMode::InSelect);
+            m_insertionMode = InsertionMode::InSelect;
         return;
     }
-    if (token->name() == optgroupTag || token->name() == optionTag) {
+    if (token.name() == optgroupTag || token.name() == optionTag) {
         if (is<HTMLOptionElement>(*m_tree.currentStackItem()->node())) {
             AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
-            processEndTag(&endOption);
+            processEndTag(endOption);
         }
         m_tree.reconstructTheActiveFormattingElements();
-        m_tree.insertHTMLElement(token);
+        m_tree.insertHTMLElement(&token);
         return;
     }
-    if (token->name() == rbTag || token->name() == rtcTag) {
+    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);
+        m_tree.insertHTMLElement(&token);
         return;
     }
-    if (token->name() == rtTag || token->name() == rpTag) {
+    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);
+        m_tree.insertHTMLElement(&token);
         return;
     }
-    if (token->name() == MathMLNames::mathTag.localName()) {
+    if (token.name() == MathMLNames::mathTag.localName()) {
         m_tree.reconstructTheActiveFormattingElements();
-        adjustMathMLAttributes(*token);
-        adjustForeignAttributes(*token);
-        m_tree.insertForeignElement(token, MathMLNames::mathmlNamespaceURI);
+        adjustMathMLAttributes(token);
+        adjustForeignAttributes(token);
+        m_tree.insertForeignElement(&token, MathMLNames::mathmlNamespaceURI);
         return;
     }
-    if (token->name() == SVGNames::svgTag.localName()) {
+    if (token.name() == SVGNames::svgTag.localName()) {
         m_tree.reconstructTheActiveFormattingElements();
-        adjustSVGAttributes(*token);
-        adjustForeignAttributes(*token);
-        m_tree.insertForeignElement(token, SVGNames::svgNamespaceURI);
+        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) {
+    if (isCaptionColOrColgroupTag(token.name())
+        || token.name() == frameTag
+        || token.name() == headTag
+        || isTableBodyContextTag(token.name())
+        || isTableCellContextTag(token.name())
+        || token.name() == trTag) {
         parseError(token);
         return;
     }
 #if ENABLE(TEMPLATE_ELEMENT)
-    if (token->name() == templateTag) {
+    if (token.name() == templateTag) {
         processTemplateStartTag(token);
         return;
     }
 #endif
     m_tree.reconstructTheActiveFormattingElements();
-    m_tree.insertHTMLElement(token);
+    m_tree.insertHTMLElement(&token);
 }
 
 #if ENABLE(TEMPLATE_ELEMENT)
-void HTMLTreeBuilder::processTemplateStartTag(AtomicHTMLToken* token)
+
+void HTMLTreeBuilder::processTemplateStartTag(AtomicHTMLToken& token)
 {
     m_tree.activeFormattingElements()->appendMarker();
-    m_tree.insertHTMLElement(token);
+    m_tree.insertHTMLElement(&token);
     m_templateInsertionModes.append(InsertionMode::TemplateContents);
-    setInsertionMode(InsertionMode::TemplateContents);
+    m_insertionMode = InsertionMode::TemplateContents;
 }
 
-bool HTMLTreeBuilder::processTemplateEndTag(AtomicHTMLToken* token)
+bool HTMLTreeBuilder::processTemplateEndTag(AtomicHTMLToken& token)
 {
-    ASSERT(token->name() == templateTag.localName());
+    ASSERT(token.name() == templateTag.localName());
     if (!m_tree.openElements()->hasTemplateInHTMLScope()) {
-        ASSERT(m_templateInsertionModes.isEmpty() || (m_templateInsertionModes.size() == 1 && m_fragmentContext.contextElement()->hasTagName(templateTag)));
+        ASSERT(m_templateInsertionModes.isEmpty() || (m_templateInsertionModes.size() == 1 && m_fragmentContext.contextElement().hasTagName(templateTag)));
         parseError(token);
         return false;
     }
@@ -954,15 +936,16 @@ bool HTMLTreeBuilder::processTemplateEndTag(AtomicHTMLToken* token)
     return true;
 }
 
-bool HTMLTreeBuilder::processEndOfFileForInTemplateContents(AtomicHTMLToken* token)
+bool HTMLTreeBuilder::processEndOfFileForInTemplateContents(AtomicHTMLToken& token)
 {
     AtomicHTMLToken endTemplate(HTMLToken::EndTag, templateTag.localName());
-    if (!processTemplateEndTag(&endTemplate))
+    if (!processTemplateEndTag(endTemplate))
         return false;
 
     processEndOfFile(token);
     return true;
 }
+
 #endif
 
 bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup()
@@ -978,14 +961,14 @@ bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup()
         return false;
     }
     m_tree.openElements()->pop();
-    setInsertionMode(InsertionMode::InTable);
+    m_insertionMode = InsertionMode::InTable;
     return true;
 }
 
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#close-the-cell
 void HTMLTreeBuilder::closeTheCell()
 {
-    ASSERT(insertionMode() == InsertionMode::InCell);
+    ASSERT(m_insertionMode == InsertionMode::InCell);
     if (m_tree.openElements()->inTableScope(tdTag)) {
         ASSERT(!m_tree.openElements()->inTableScope(thTag));
         processFakeEndTag(tdTag);
@@ -993,45 +976,44 @@ void HTMLTreeBuilder::closeTheCell()
     }
     ASSERT(m_tree.openElements()->inTableScope(thTag));
     processFakeEndTag(thTag);
-    ASSERT(insertionMode() == InsertionMode::InRow);
+    ASSERT(m_insertionMode == InsertionMode::InRow);
 }
 
-void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::StartTag);
-    if (token->name() == captionTag) {
+    ASSERT(token.type() == HTMLToken::StartTag);
+    if (token.name() == captionTag) {
         m_tree.openElements()->popUntilTableScopeMarker();
         m_tree.activeFormattingElements()->appendMarker();
-        m_tree.insertHTMLElement(token);
-        setInsertionMode(InsertionMode::InCaption);
+        m_tree.insertHTMLElement(&token);
+        m_insertionMode = InsertionMode::InCaption;
         return;
     }
-    if (token->name() == colgroupTag) {
+    if (token.name() == colgroupTag) {
         m_tree.openElements()->popUntilTableScopeMarker();
-        m_tree.insertHTMLElement(token);
-        setInsertionMode(InsertionMode::InColumnGroup);
+        m_tree.insertHTMLElement(&token);
+        m_insertionMode = InsertionMode::InColumnGroup;
         return;
     }
-    if (token->name() == colTag) {
+    if (token.name() == colTag) {
         processFakeStartTag(colgroupTag);
-        ASSERT(insertionMode() == InsertionMode::InColumnGroup);
+        ASSERT(m_insertionMode == InsertionMode::InColumnGroup);
         processStartTag(token);
         return;
     }
-    if (isTableBodyContextTag(token->name())) {
+    if (isTableBodyContextTag(token.name())) {
         m_tree.openElements()->popUntilTableScopeMarker();
-        m_tree.insertHTMLElement(token);
-        setInsertionMode(InsertionMode::InTableBody);
+        m_tree.insertHTMLElement(&token);
+        m_insertionMode = InsertionMode::InTableBody;
         return;
     }
-    if (isTableCellContextTag(token->name())
-        || token->name() == trTag) {
+    if (isTableCellContextTag(token.name()) || token.name() == trTag) {
         processFakeStartTag(tbodyTag);
-        ASSERT(insertionMode() == InsertionMode::InTableBody);
+        ASSERT(m_insertionMode == InsertionMode::InTableBody);
         processStartTag(token);
         return;
     }
-    if (token->name() == tableTag) {
+    if (token.name() == tableTag) {
         parseError(token);
         if (!processTableEndTagForInTable()) {
             ASSERT(isParsingFragmentOrTemplateContents());
@@ -1040,29 +1022,29 @@ void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken* token)
         processStartTag(token);
         return;
     }
-    if (token->name() == styleTag || token->name() == scriptTag) {
+    if (token.name() == styleTag || token.name() == scriptTag) {
         processStartTagForInHead(token);
         return;
     }
-    if (token->name() == inputTag) {
-        Attribute* typeAttribute = token->getAttributeItem(typeAttr);
+    if (token.name() == inputTag) {
+        Attribute* typeAttribute = token.getAttributeItem(typeAttr);
         if (typeAttribute && equalIgnoringCase(typeAttribute->value(), "hidden")) {
             parseError(token);
-            m_tree.insertSelfClosingHTMLElement(token);
+            m_tree.insertSelfClosingHTMLElement(&token);
             return;
         }
         // Fall through to "anything else" case.
     }
-    if (token->name() == formTag) {
+    if (token.name() == formTag) {
         parseError(token);
         if (m_tree.form() && !isParsingTemplateContents())
             return;
-        m_tree.insertHTMLFormElement(token, true);
+        m_tree.insertHTMLFormElement(&token, true);
         m_tree.openElements()->pop();
         return;
     }
 #if ENABLE(TEMPLATE_ELEMENT)
-    if (token->name() == templateTag) {
+    if (token.name() == templateTag) {
         processTemplateStartTag(token);
         return;
     }
@@ -1072,71 +1054,70 @@ void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken* token)
     processStartTagForInBody(token);
 }
 
-void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::StartTag);
-    switch (insertionMode()) {
+    ASSERT(token.type() == HTMLToken::StartTag);
+    switch (m_insertionMode) {
     case InsertionMode::Initial:
-        ASSERT(insertionMode() == InsertionMode::Initial);
         defaultForInitial();
+        ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
         FALLTHROUGH;
     case InsertionMode::BeforeHTML:
-        ASSERT(insertionMode() == InsertionMode::BeforeHTML);
-        if (token->name() == htmlTag) {
-            m_tree.insertHTMLHtmlStartTagBeforeHTML(token);
-            setInsertionMode(InsertionMode::BeforeHead);
+        if (token.name() == htmlTag) {
+            m_tree.insertHTMLHtmlStartTagBeforeHTML(&token);
+            m_insertionMode = InsertionMode::BeforeHead;
             return;
         }
         defaultForBeforeHTML();
+        ASSERT(m_insertionMode == InsertionMode::BeforeHead);
         FALLTHROUGH;
     case InsertionMode::BeforeHead:
-        ASSERT(insertionMode() == InsertionMode::BeforeHead);
-        if (token->name() == htmlTag) {
+        if (token.name() == htmlTag) {
             processHtmlStartTagForInBody(token);
             return;
         }
-        if (token->name() == headTag) {
-            m_tree.insertHTMLHeadElement(token);
-            setInsertionMode(InsertionMode::InHead);
+        if (token.name() == headTag) {
+            m_tree.insertHTMLHeadElement(&token);
+            m_insertionMode = InsertionMode::InHead;
             return;
         }
         defaultForBeforeHead();
+        ASSERT(m_insertionMode == InsertionMode::InHead);
         FALLTHROUGH;
     case InsertionMode::InHead:
-        ASSERT(insertionMode() == InsertionMode::InHead);
         if (processStartTagForInHead(token))
             return;
         defaultForInHead();
+        ASSERT(m_insertionMode == InsertionMode::AfterHead);
         FALLTHROUGH;
     case InsertionMode::AfterHead:
-        ASSERT(insertionMode() == InsertionMode::AfterHead);
-        if (token->name() == htmlTag) {
+        if (token.name() == htmlTag) {
             processHtmlStartTagForInBody(token);
             return;
         }
-        if (token->name() == bodyTag) {
+        if (token.name() == bodyTag) {
             m_framesetOk = false;
-            m_tree.insertHTMLBodyElement(token);
-            setInsertionMode(InsertionMode::InBody);
+            m_tree.insertHTMLBodyElement(&token);
+            m_insertionMode = InsertionMode::InBody;
             return;
         }
-        if (token->name() == framesetTag) {
-            m_tree.insertHTMLElement(token);
-            setInsertionMode(InsertionMode::InFrameset);
+        if (token.name() == framesetTag) {
+            m_tree.insertHTMLElement(&token);
+            m_insertionMode = InsertionMode::InFrameset;
             return;
         }
-        if (token->name() == baseTag
-            || token->name() == basefontTag
-            || token->name() == bgsoundTag
-            || token->name() == linkTag
-            || token->name() == metaTag
-            || token->name() == noframesTag
-            || token->name() == scriptTag
-            || token->name() == styleTag
+        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
 #if ENABLE(TEMPLATE_ELEMENT)
-            || token->name() == templateTag
+            || token.name() == templateTag
 #endif
-            || token->name() == titleTag) {
+            || token.name() == titleTag) {
             parseError(token);
             ASSERT(m_tree.head());
             m_tree.openElements()->pushHTMLHeadElement(m_tree.headStackItem());
@@ -1144,26 +1125,24 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
             m_tree.openElements()->removeHTMLHeadElement(m_tree.head());
             return;
         }
-        if (token->name() == headTag) {
+        if (token.name() == headTag) {
             parseError(token);
             return;
         }
         defaultForAfterHead();
+        ASSERT(m_insertionMode == InsertionMode::InBody);
         FALLTHROUGH;
     case InsertionMode::InBody:
-        ASSERT(insertionMode() == InsertionMode::InBody);
         processStartTagForInBody(token);
         break;
     case InsertionMode::InTable:
-        ASSERT(insertionMode() == InsertionMode::InTable);
         processStartTagForInTable(token);
         break;
     case InsertionMode::InCaption:
-        ASSERT(insertionMode() == InsertionMode::InCaption);
-        if (isCaptionColOrColgroupTag(token->name())
-            || isTableBodyContextTag(token->name())
-            || isTableCellContextTag(token->name())
-            || token->name() == trTag) {
+        if (isCaptionColOrColgroupTag(token.name())
+            || isTableBodyContextTag(token.name())
+            || isTableCellContextTag(token.name())
+            || token.name() == trTag) {
             parseError(token);
             if (!processCaptionEndTagForInCaption()) {
                 ASSERT(isParsingFragment());
@@ -1175,17 +1154,16 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
         processStartTagForInBody(token);
         break;
     case InsertionMode::InColumnGroup:
-        ASSERT(insertionMode() == InsertionMode::InColumnGroup);
-        if (token->name() == htmlTag) {
+        if (token.name() == htmlTag) {
             processHtmlStartTagForInBody(token);
             return;
         }
-        if (token->name() == colTag) {
-            m_tree.insertSelfClosingHTMLElement(token);
+        if (token.name() == colTag) {
+            m_tree.insertSelfClosingHTMLElement(&token);
             return;
         }
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (token->name() == templateTag) {
+        if (token.name() == templateTag) {
             processTemplateStartTag(token);
             return;
         }
@@ -1197,21 +1175,20 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
         processStartTag(token);
         break;
     case InsertionMode::InTableBody:
-        ASSERT(insertionMode() == InsertionMode::InTableBody);
-        if (token->name() == trTag) {
+        if (token.name() == trTag) {
             m_tree.openElements()->popUntilTableBodyScopeMarker(); // How is there ever anything to pop?
-            m_tree.insertHTMLElement(token);
-            setInsertionMode(InsertionMode::InRow);
+            m_tree.insertHTMLElement(&token);
+            m_insertionMode = InsertionMode::InRow;
             return;
         }
-        if (isTableCellContextTag(token->name())) {
+        if (isTableCellContextTag(token.name())) {
             parseError(token);
             processFakeStartTag(trTag);
-            ASSERT(insertionMode() == InsertionMode::InRow);
+            ASSERT(m_insertionMode == InsertionMode::InRow);
             processStartTag(token);
             return;
         }
-        if (isCaptionColOrColgroupTag(token->name()) || isTableBodyContextTag(token->name())) {
+        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());
@@ -1227,33 +1204,31 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
         processStartTagForInTable(token);
         break;
     case InsertionMode::InRow:
-        ASSERT(insertionMode() == InsertionMode::InRow);
-        if (isTableCellContextTag(token->name())) {
+        if (isTableCellContextTag(token.name())) {
             m_tree.openElements()->popUntilTableRowScopeMarker();
-            m_tree.insertHTMLElement(token);
-            setInsertionMode(InsertionMode::InCell);
+            m_tree.insertHTMLElement(&token);
+            m_insertionMode = InsertionMode::InCell;
             m_tree.activeFormattingElements()->appendMarker();
             return;
         }
-        if (token->name() == trTag
-            || isCaptionColOrColgroupTag(token->name())
-            || isTableBodyContextTag(token->name())) {
+        if (token.name() == trTag
+            || isCaptionColOrColgroupTag(token.name())
+            || isTableBodyContextTag(token.name())) {
             if (!processTrEndTagForInRow()) {
                 ASSERT(isParsingFragmentOrTemplateContents());
                 return;
             }
-            ASSERT(insertionMode() == InsertionMode::InTableBody);
+            ASSERT(m_insertionMode == InsertionMode::InTableBody);
             processStartTag(token);
             return;
         }
         processStartTagForInTable(token);
         break;
     case InsertionMode::InCell:
-        ASSERT(insertionMode() == InsertionMode::InCell);
-        if (isCaptionColOrColgroupTag(token->name())
-            || isTableCellContextTag(token->name())
-            || token->name() == trTag
-            || isTableBodyContextTag(token->name())) {
+        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());
@@ -1268,31 +1243,29 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
         break;
     case InsertionMode::AfterBody:
     case InsertionMode::AfterAfterBody:
-        ASSERT(insertionMode() == InsertionMode::AfterBody || insertionMode() == InsertionMode::AfterAfterBody);
-        if (token->name() == htmlTag) {
+        if (token.name() == htmlTag) {
             processHtmlStartTagForInBody(token);
             return;
         }
-        setInsertionMode(InsertionMode::InBody);
+        m_insertionMode = InsertionMode::InBody;
         processStartTag(token);
         break;
     case InsertionMode::InHeadNoscript:
-        ASSERT(insertionMode() == InsertionMode::InHeadNoscript);
-        if (token->name() == htmlTag) {
+        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) {
+        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) {
+        if (token.name() == htmlTag || token.name() == noscriptTag) {
             parseError(token);
             return;
         }
@@ -1300,25 +1273,24 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
         processToken(token);
         break;
     case InsertionMode::InFrameset:
-        ASSERT(insertionMode() == InsertionMode::InFrameset);
-        if (token->name() == htmlTag) {
+        if (token.name() == htmlTag) {
             processHtmlStartTagForInBody(token);
             return;
         }
-        if (token->name() == framesetTag) {
-            m_tree.insertHTMLElement(token);
+        if (token.name() == framesetTag) {
+            m_tree.insertHTMLElement(&token);
             return;
         }
-        if (token->name() == frameTag) {
-            m_tree.insertSelfClosingHTMLElement(token);
+        if (token.name() == frameTag) {
+            m_tree.insertSelfClosingHTMLElement(&token);
             return;
         }
-        if (token->name() == noframesTag) {
+        if (token.name() == noframesTag) {
             processStartTagForInHead(token);
             return;
         }
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (token->name() == templateTag) {
+        if (token.name() == templateTag) {
             processTemplateStartTag(token);
             return;
         }
@@ -1327,83 +1299,78 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
         break;
     case InsertionMode::AfterFrameset:
     case InsertionMode::AfterAfterFrameset:
-        ASSERT(insertionMode() == InsertionMode::AfterFrameset || insertionMode() == InsertionMode::AfterAfterFrameset);
-        if (token->name() == htmlTag) {
+        if (token.name() == htmlTag) {
             processHtmlStartTagForInBody(token);
             return;
         }
-        if (token->name() == noframesTag) {
+        if (token.name() == noframesTag) {
             processStartTagForInHead(token);
             return;
         }
         parseError(token);
         break;
     case InsertionMode::InSelectInTable:
-        ASSERT(insertionMode() == InsertionMode::InSelectInTable);
-        if (token->name() == captionTag
-            || token->name() == tableTag
-            || isTableBodyContextTag(token->name())
-            || token->name() == trTag
-            || isTableCellContextTag(token->name())) {
+        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);
+            processEndTag(endSelect);
             processStartTag(token);
             return;
         }
         FALLTHROUGH;
     case InsertionMode::InSelect:
-        ASSERT(insertionMode() == InsertionMode::InSelect || insertionMode() == InsertionMode::InSelectInTable);
-        if (token->name() == htmlTag) {
+        if (token.name() == htmlTag) {
             processHtmlStartTagForInBody(token);
             return;
         }
-        if (token->name() == optionTag) {
+        if (token.name() == optionTag) {
             if (is<HTMLOptionElement>(*m_tree.currentStackItem()->node())) {
                 AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
-                processEndTag(&endOption);
+                processEndTag(endOption);
             }
-            m_tree.insertHTMLElement(token);
+            m_tree.insertHTMLElement(&token);
             return;
         }
-        if (token->name() == optgroupTag) {
+        if (token.name() == optgroupTag) {
             if (is<HTMLOptionElement>(*m_tree.currentStackItem()->node())) {
                 AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
-                processEndTag(&endOption);
+                processEndTag(endOption);
             }
             if (is<HTMLOptGroupElement>(*m_tree.currentStackItem()->node())) {
                 AtomicHTMLToken endOptgroup(HTMLToken::EndTag, optgroupTag.localName());
-                processEndTag(&endOptgroup);
+                processEndTag(endOptgroup);
             }
-            m_tree.insertHTMLElement(token);
+            m_tree.insertHTMLElement(&token);
             return;
         }
-        if (token->name() == selectTag) {
+        if (token.name() == selectTag) {
             parseError(token);
             AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
-            processEndTag(&endSelect);
+            processEndTag(endSelect);
             return;
         }
-        if (token->name() == inputTag
-            || token->name() == keygenTag
-            || token->name() == textareaTag) {
+        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);
+            processEndTag(endSelect);
             processStartTag(token);
             return;
         }
-        if (token->name() == scriptTag) {
+        if (token.name() == scriptTag) {
             bool didProcess = processStartTagForInHead(token);
             ASSERT_UNUSED(didProcess, didProcess);
             return;
         }
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (token->name() == templateTag) {
+        if (token.name() == templateTag) {
             processTemplateStartTag(token);
             return;
         }
@@ -1416,31 +1383,31 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
     case InsertionMode::Text:
         ASSERT_NOT_REACHED();
         break;
-    case InsertionMode::TemplateContents:
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (token->name() == templateTag) {
+    case InsertionMode::TemplateContents:
+        if (token.name() == templateTag) {
             processTemplateStartTag(token);
             return;
         }
 
-        if (token->name() == linkTag
-            || token->name() == scriptTag
-            || token->name() == styleTag
-            || token->name() == metaTag) {
+        if (token.name() == linkTag
+            || token.name() == scriptTag
+            || token.name() == styleTag
+            || token.name() == metaTag) {
             processStartTagForInHead(token);
             return;
         }
 
         InsertionMode insertionMode = InsertionMode::TemplateContents;
-        if (token->name() == frameTag)
+        if (token.name() == frameTag)
             insertionMode = InsertionMode::InFrameset;
-        else if (token->name() == colTag)
+        else if (token.name() == colTag)
             insertionMode = InsertionMode::InColumnGroup;
-        else if (isCaptionColOrColgroupTag(token->name()) || isTableBodyContextTag(token->name()))
+        else if (isCaptionColOrColgroupTag(token.name()) || isTableBodyContextTag(token.name()))
             insertionMode = InsertionMode::InTable;
-        else if (token->name() == trTag)
+        else if (token.name() == trTag)
             insertionMode = InsertionMode::InTableBody;
-        else if (isTableCellContextTag(token->name()))
+        else if (isTableCellContextTag(token.name()))
             insertionMode = InsertionMode::InRow;
         else
             insertionMode = InsertionMode::InBody;
@@ -1448,17 +1415,15 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
         ASSERT(insertionMode != InsertionMode::TemplateContents);
         ASSERT(m_templateInsertionModes.last() == InsertionMode::TemplateContents);
         m_templateInsertionModes.last() = insertionMode;
-        setInsertionMode(insertionMode);
+        m_insertionMode = insertionMode;
 
         processStartTag(token);
-#else
-        ASSERT_NOT_REACHED();
-#endif
         break;
+#endif
     }
 }
 
-void HTMLTreeBuilder::processHtmlStartTagForInBody(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processHtmlStartTagForInBody(AtomicHTMLToken& token)
 {
     parseError(token);
 #if ENABLE(TEMPLATE_ELEMENT)
@@ -1467,45 +1432,43 @@ void HTMLTreeBuilder::processHtmlStartTagForInBody(AtomicHTMLToken* token)
         return;
     }
 #endif
-    m_tree.insertHTMLHtmlStartTagInBody(token);
+    m_tree.insertHTMLHtmlStartTagInBody(&token);
 }
 
-bool HTMLTreeBuilder::processBodyEndTagForInBody(AtomicHTMLToken* token)
+bool HTMLTreeBuilder::processBodyEndTagForInBody(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::EndTag);
-    ASSERT(token->name() == bodyTag);
+    ASSERT(token.type() == HTMLToken::EndTag);
+    ASSERT(token.name() == bodyTag);
     if (!m_tree.openElements()->inScope(bodyTag.localName())) {
         parseError(token);
         return false;
     }
     notImplemented(); // Emit a more specific parse error based on stack contents.
-    setInsertionMode(InsertionMode::AfterBody);
+    m_insertionMode = InsertionMode::AfterBody;
     return true;
 }
 
-void HTMLTreeBuilder::processAnyOtherEndTagForInBody(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processAnyOtherEndTagForInBody(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::EndTag);
-    HTMLElementStack::ElementRecord* record = m_tree.openElements()->topRecord();
-    while (1) {
-        RefPtr<HTMLStackItem> item = record->stackItem();
-        if (item->matchesHTMLTag(token->name())) {
-            m_tree.generateImpliedEndTagsWithExclusion(token->name());
-            if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
+    ASSERT(token.type() == HTMLToken::EndTag);
+    for (auto* record = m_tree.openElements()->topRecord(); ; record = record->next()) {
+        HTMLStackItem& item = *record->stackItem();
+        if (item.matchesHTMLTag(token.name())) {
+            m_tree.generateImpliedEndTagsWithExclusion(token.name());
+            if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
                 parseError(token);
-            m_tree.openElements()->popUntilPopped(item->element());
+            m_tree.openElements()->popUntilPopped(item.element());
             return;
         }
-        if (item->isSpecialNode()) {
+        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)
+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
@@ -1517,7 +1480,7 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token)
     // 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());
+        Element* formattingElement = m_tree.activeFormattingElements()->closestElementInScopeWithName(token.name());
         // 4.a
         if (!formattingElement)
             return processAnyOtherEndTagForInBody(token);
@@ -1528,7 +1491,7 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token)
             return;
         }
         // 4.b
-        HTMLElementStack::ElementRecord* formattingElementRecord = m_tree.openElements()->find(formattingElement);
+        auto* formattingElementRecord = m_tree.openElements()->find(formattingElement);
         if (!formattingElementRecord) {
             parseError(token);
             m_tree.activeFormattingElements()->remove(formattingElement);
@@ -1538,7 +1501,7 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token)
         if (formattingElement != m_tree.currentElement())
             parseError(token);
         // 5.
-        HTMLElementStack::ElementRecord* furthestBlock = m_tree.openElements()->furthestBlockForFormattingElement(formattingElement);
+        auto* furthestBlock = m_tree.openElements()->furthestBlockForFormattingElement(formattingElement);
         // 6.
         if (!furthestBlock) {
             m_tree.openElements()->popUntilPopped(formattingElement);
@@ -1551,9 +1514,9 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token)
         // 8.
         HTMLFormattingElementList::Bookmark bookmark = m_tree.activeFormattingElements()->bookmarkFor(formattingElement);
         // 9.
-        HTMLElementStack::ElementRecord* node = furthestBlock;
-        HTMLElementStack::ElementRecord* nextNode = node->next();
-        HTMLElementStack::ElementRecord* lastNode = furthestBlock;
+        auto* node = furthestBlock;
+        auto* nextNode = node->next();
+        auto* lastNode = furthestBlock;
         // 9.1, 9.2, 9.3 and 9.11 are covered by the for() loop.
         for (int i = 0; i < innerIterationLimit; ++i) {
             // 9.4
@@ -1604,9 +1567,8 @@ 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) {
-        RefPtr<HTMLStackItem> item = nodeRecord->stackItem();
+    for (auto* record = m_tree.openElements()->topRecord(); ; record = record->next()) {
+        HTMLStackItem* item = record->stackItem().get();
         if (item->node() == m_tree.openElements()->rootNode()) {
             last = true;
 #if ENABLE(TEMPLATE_ELEMENT)
@@ -1616,78 +1578,104 @@ void HTMLTreeBuilder::resetInsertionModeAppropriately()
             bool shouldCreateItem = true;
 #endif
             if (shouldCreateItem)
-                item = m_fragmentContext.contextElementStackItem();
+                item = &m_fragmentContext.contextElementStackItem();
         }
+
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (item->hasTagName(templateTag))
-            return setInsertionMode(m_templateInsertionModes.last());
+        if (item->hasTagName(templateTag)) {
+            m_insertionMode = m_templateInsertionModes.last();
+            return;
+        }
 #endif
         if (item->hasTagName(selectTag)) {
 #if ENABLE(TEMPLATE_ELEMENT)
             if (!last) {
                 while (item->node() != m_tree.openElements()->rootNode() && !item->hasTagName(templateTag)) {
-                    nodeRecord = nodeRecord->next();
-                    item = nodeRecord->stackItem();
-                    if (is<HTMLTableElement>(*item->node()))
-                        return setInsertionMode(InsertionMode::InSelectInTable);
+                    record = record->next();
+                    item = record->stackItem().get();
+                    if (is<HTMLTableElement>(*item->node())) {
+                        m_insertionMode = InsertionMode::InSelectInTable;
+                        return;
+                    }
                 }
             }
 #endif
-            return setInsertionMode(InsertionMode::InSelect);
-        }
-        if (item->hasTagName(tdTag) || item->hasTagName(thTag))
-            return setInsertionMode(InsertionMode::InCell);
-        if (item->hasTagName(trTag))
-            return setInsertionMode(InsertionMode::InRow);
-        if (item->hasTagName(tbodyTag) || item->hasTagName(theadTag) || item->hasTagName(tfootTag))
-            return setInsertionMode(InsertionMode::InTableBody);
-        if (item->hasTagName(captionTag))
-            return setInsertionMode(InsertionMode::InCaption);
+            m_insertionMode = InsertionMode::InSelect;
+            return;
+        }
+        if (item->hasTagName(tdTag) || item->hasTagName(thTag)) {
+            m_insertionMode = InsertionMode::InCell;
+            return;
+        }
+        if (item->hasTagName(trTag)) {
+            m_insertionMode = InsertionMode::InRow;
+            return;
+        }
+        if (item->hasTagName(tbodyTag) || item->hasTagName(theadTag) || item->hasTagName(tfootTag)) {
+            m_insertionMode = InsertionMode::InTableBody;
+            return;
+        }
+        if (item->hasTagName(captionTag)) {
+            m_insertionMode = InsertionMode::InCaption;
+            return;
+        }
         if (item->hasTagName(colgroupTag)) {
-            return setInsertionMode(InsertionMode::InColumnGroup);
+            m_insertionMode = InsertionMode::InColumnGroup;
+            return;
+        }
+        if (is<HTMLTableElement>(*item->node())) {
+            m_insertionMode = InsertionMode::InTable;
+            return;
         }
-        if (is<HTMLTableElement>(*item->node()))
-            return setInsertionMode(InsertionMode::InTable);
         if (item->hasTagName(headTag)) {
 #if ENABLE(TEMPLATE_ELEMENT)
-            if (!m_fragmentContext.fragment() || m_fragmentContext.contextElement() != item->node())
-                return setInsertionMode(InsertionMode::InHead);
+            if (!m_fragmentContext.fragment() || &m_fragmentContext.contextElement() != item->node()) {
+                m_insertionMode = InsertionMode::InHead;
+                return;
+            }
 #endif
-            return setInsertionMode(InsertionMode::InBody);
+            m_insertionMode = InsertionMode::InBody;
+            return;
+        }
+        if (item->hasTagName(bodyTag)) {
+            m_insertionMode = InsertionMode::InBody;
+            return;
         }
-        if (item->hasTagName(bodyTag))
-            return setInsertionMode(InsertionMode::InBody);
         if (item->hasTagName(framesetTag)) {
-            return setInsertionMode(InsertionMode::InFrameset);
+            m_insertionMode = InsertionMode::InFrameset;
+            return;
         }
         if (item->hasTagName(htmlTag)) {
-            if (m_tree.headStackItem())
-                return setInsertionMode(InsertionMode::AfterHead);
+            if (m_tree.headStackItem()) {
+                m_insertionMode = InsertionMode::AfterHead;
+                return;
+            }
             ASSERT(isParsingFragment());
-            return setInsertionMode(InsertionMode::BeforeHead);
+            m_insertionMode = InsertionMode::BeforeHead;
+            return;
         }
         if (last) {
             ASSERT(isParsingFragment());
-            return setInsertionMode(InsertionMode::InBody);
+            m_insertionMode = InsertionMode::InBody;
+            return;
         }
-        nodeRecord = nodeRecord->next();
     }
 }
 
-void HTMLTreeBuilder::processEndTagForInTableBody(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processEndTagForInTableBody(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::EndTag);
-    if (isTableBodyContextTag(token->name())) {
-        if (!m_tree.openElements()->inTableScope(token->name())) {
+    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(InsertionMode::InTable);
+        m_insertionMode = InsertionMode::InTable;
         return;
     }
-    if (token->name() == tableTag) {
+    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());
@@ -1700,83 +1688,83 @@ void HTMLTreeBuilder::processEndTagForInTableBody(AtomicHTMLToken* token)
         processEndTag(token);
         return;
     }
-    if (token->name() == bodyTag
-        || isCaptionColOrColgroupTag(token->name())
-        || token->name() == htmlTag
-        || isTableCellContextTag(token->name())
-        || token->name() == trTag) {
+    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)
+void HTMLTreeBuilder::processEndTagForInRow(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::EndTag);
-    if (token->name() == trTag) {
+    ASSERT(token.type() == HTMLToken::EndTag);
+    if (token.name() == trTag) {
         processTrEndTagForInRow();
         return;
     }
-    if (token->name() == tableTag) {
+    if (token.name() == tableTag) {
         if (!processTrEndTagForInRow()) {
             ASSERT(isParsingFragmentOrTemplateContents());
             return;
         }
-        ASSERT(insertionMode() == InsertionMode::InTableBody);
+        ASSERT(m_insertionMode == InsertionMode::InTableBody);
         processEndTag(token);
         return;
     }
-    if (isTableBodyContextTag(token->name())) {
-        if (!m_tree.openElements()->inTableScope(token->name())) {
+    if (isTableBodyContextTag(token.name())) {
+        if (!m_tree.openElements()->inTableScope(token.name())) {
             parseError(token);
             return;
         }
         processFakeEndTag(trTag);
-        ASSERT(insertionMode() == InsertionMode::InTableBody);
+        ASSERT(m_insertionMode == InsertionMode::InTableBody);
         processEndTag(token);
         return;
     }
-    if (token->name() == bodyTag
-        || isCaptionColOrColgroupTag(token->name())
-        || token->name() == htmlTag
-        || isTableCellContextTag(token->name())) {
+    if (token.name() == bodyTag
+        || isCaptionColOrColgroupTag(token.name())
+        || token.name() == htmlTag
+        || isTableCellContextTag(token.name())) {
         parseError(token);
         return;
     }
     processEndTagForInTable(token);
 }
 
-void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::EndTag);
-    if (isTableCellContextTag(token->name())) {
-        if (!m_tree.openElements()->inTableScope(token->name())) {
+    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()))
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
             parseError(token);
-        m_tree.openElements()->popUntilPopped(token->name());
+        m_tree.openElements()->popUntilPopped(token.name());
         m_tree.activeFormattingElements()->clearToLastMarker();
-        setInsertionMode(InsertionMode::InRow);
+        m_insertionMode = InsertionMode::InRow;
         return;
     }
-    if (token->name() == bodyTag
-        || isCaptionColOrColgroupTag(token->name())
-        || token->name() == htmlTag) {
+    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())) {
+    if (token.name() == tableTag
+        || token.name() == trTag
+        || isTableBodyContextTag(token.name())) {
+        if (!m_tree.openElements()->inTableScope(token.name())) {
 #if ENABLE(TEMPLATE_ELEMENT)
-            ASSERT(isTableBodyContextTag(token->name()) || m_tree.openElements()->inTableScope(templateTag) || isParsingFragment());
+            ASSERT(isTableBodyContextTag(token.name()) || m_tree.openElements()->inTableScope(templateTag) || isParsingFragment());
 #else
-            ASSERT(isTableBodyContextTag(token->name()) || isParsingFragment());
+            ASSERT(isTableBodyContextTag(token.name()) || isParsingFragment());
 #endif
             parseError(token);
             return;
@@ -1788,55 +1776,55 @@ void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken* token)
     processEndTagForInBody(token);
 }
 
-void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::EndTag);
-    if (token->name() == bodyTag) {
+    ASSERT(token.type() == HTMLToken::EndTag);
+    if (token.name() == bodyTag) {
         processBodyEndTagForInBody(token);
         return;
     }
-    if (token->name() == htmlTag) {
+    if (token.name() == htmlTag) {
         AtomicHTMLToken endBody(HTMLToken::EndTag, bodyTag.localName());
-        if (processBodyEndTagForInBody(&endBody))
+        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())) {
+    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()))
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
             parseError(token);
-        m_tree.openElements()->popUntilPopped(token->name());
+        m_tree.openElements()->popUntilPopped(token.name());
         return;
     }
-    if (token->name() == formTag) {
+    if (token.name() == formTag) {
         if (!isParsingTemplateContents()) {
             RefPtr<Element> node = m_tree.takeForm();
             if (!node || !m_tree.openElements()->inScope(node.get())) {
@@ -1848,89 +1836,86 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
                 parseError(token);
             m_tree.openElements()->remove(node.get());
         } else {
-            if (!m_tree.openElements()->inScope(token->name())) {
+            if (!m_tree.openElements()->inScope(token.name())) {
                 parseError(token);
                 return;
             }
             m_tree.generateImpliedEndTags();
             if (!m_tree.currentNode()->hasTagName(formTag))
                 parseError(token);
-            m_tree.openElements()->popUntilPopped(token->name());
+            m_tree.openElements()->popUntilPopped(token.name());
         }
     }
-    if (token->name() == pTag) {
-        if (!m_tree.openElements()->inButtonScope(token->name())) {
+    if (token.name() == pTag) {
+        if (!m_tree.openElements()->inButtonScope(token.name())) {
             parseError(token);
             processFakeStartTag(pTag);
-            ASSERT(m_tree.openElements()->inScope(token->name()));
+            ASSERT(m_tree.openElements()->inScope(token.name()));
             processEndTag(token);
             return;
         }
-        m_tree.generateImpliedEndTagsWithExclusion(token->name());
-        if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
+        m_tree.generateImpliedEndTagsWithExclusion(token.name());
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
             parseError(token);
-        m_tree.openElements()->popUntilPopped(token->name());
+        m_tree.openElements()->popUntilPopped(token.name());
         return;
     }
-    if (token->name() == liTag) {
-        if (!m_tree.openElements()->inListItemScope(token->name())) {
+    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()))
+        m_tree.generateImpliedEndTagsWithExclusion(token.name());
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
             parseError(token);
-        m_tree.openElements()->popUntilPopped(token->name());
+        m_tree.openElements()->popUntilPopped(token.name());
         return;
     }
-    if (token->name() == ddTag
-        || token->name() == dtTag) {
-        if (!m_tree.openElements()->inScope(token->name())) {
+    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()))
+        m_tree.generateImpliedEndTagsWithExclusion(token.name());
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
             parseError(token);
-        m_tree.openElements()->popUntilPopped(token->name());
+        m_tree.openElements()->popUntilPopped(token.name());
         return;
     }
-    if (isNumberedHeaderTag(token->name())) {
+    if (isNumberedHeaderTag(token.name())) {
         if (!m_tree.openElements()->hasNumberedHeaderElementInScope()) {
             parseError(token);
             return;
         }
         m_tree.generateImpliedEndTags();
-        if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
             parseError(token);
         m_tree.openElements()->popUntilNumberedHeaderElementPopped();
         return;
     }
-    if (isFormattingTag(token->name())) {
+    if (isFormattingTag(token.name())) {
         callTheAdoptionAgency(token);
         return;
     }
-    if (token->name() == appletTag
-        || token->name() == marqueeTag
-        || token->name() == objectTag) {
-        if (!m_tree.openElements()->inScope(token->name())) {
+    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()))
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token.name()))
             parseError(token);
-        m_tree.openElements()->popUntilPopped(token->name());
+        m_tree.openElements()->popUntilPopped(token.name());
         m_tree.activeFormattingElements()->clearToLastMarker();
         return;
     }
-    if (token->name() == brTag) {
+    if (token.name() == brTag) {
         parseError(token);
         processFakeStartTag(brTag);
         return;
     }
 #if ENABLE(TEMPLATE_ELEMENT)
-    if (token->name() == templateTag) {
+    if (token.name() == templateTag) {
         processTemplateEndTag(token);
         return;
     }
@@ -1949,7 +1934,7 @@ bool HTMLTreeBuilder::processCaptionEndTagForInCaption()
     // FIXME: parse error if (!m_tree.currentStackItem()->hasTagName(captionTag))
     m_tree.openElements()->popUntilPopped(captionTag.localName());
     m_tree.activeFormattingElements()->clearToLastMarker();
-    setInsertionMode(InsertionMode::InTable);
+    m_insertionMode = InsertionMode::InTable;
     return true;
 }
 
@@ -1963,7 +1948,7 @@ bool HTMLTreeBuilder::processTrEndTagForInRow()
     m_tree.openElements()->popUntilTableRowScopeMarker();
     ASSERT(m_tree.currentStackItem()->hasTagName(trTag));
     m_tree.openElements()->pop();
-    setInsertionMode(InsertionMode::InTableBody);
+    m_insertionMode = InsertionMode::InTableBody;
     return true;
 }
 
@@ -1979,19 +1964,19 @@ bool HTMLTreeBuilder::processTableEndTagForInTable()
     return true;
 }
 
-void HTMLTreeBuilder::processEndTagForInTable(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processEndTagForInTable(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::EndTag);
-    if (token->name() == tableTag) {
+    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) {
+    if (token.name() == bodyTag
+        || isCaptionColOrColgroupTag(token.name())
+        || token.name() == htmlTag
+        || isTableBodyContextTag(token.name())
+        || isTableCellContextTag(token.name())
+        || token.name() == trTag) {
         parseError(token);
         return;
     }
@@ -2001,75 +1986,73 @@ void HTMLTreeBuilder::processEndTagForInTable(AtomicHTMLToken* token)
     processEndTagForInBody(token);
 }
 
-void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::EndTag);
-    switch (insertionMode()) {
+    ASSERT(token.type() == HTMLToken::EndTag);
+    switch (m_insertionMode) {
     case InsertionMode::Initial:
-        ASSERT(insertionMode() == InsertionMode::Initial);
+        ASSERT(m_insertionMode == InsertionMode::Initial);
         defaultForInitial();
         FALLTHROUGH;
     case InsertionMode::BeforeHTML:
-        ASSERT(insertionMode() == InsertionMode::BeforeHTML);
-        if (token->name() != headTag && token->name() != bodyTag && token->name() != htmlTag && token->name() != brTag) {
+        ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
+        if (token.name() != headTag && token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
             parseError(token);
             return;
         }
         defaultForBeforeHTML();
+        ASSERT(m_insertionMode == InsertionMode::BeforeHead);
         FALLTHROUGH;
     case InsertionMode::BeforeHead:
-        ASSERT(insertionMode() == InsertionMode::BeforeHead);
-        if (token->name() != headTag && token->name() != bodyTag && token->name() != htmlTag && token->name() != brTag) {
+        if (token.name() != headTag && token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
             parseError(token);
             return;
         }
         defaultForBeforeHead();
+        ASSERT(m_insertionMode == InsertionMode::InHead);
         FALLTHROUGH;
     case InsertionMode::InHead:
-        ASSERT(insertionMode() == InsertionMode::InHead);
         // FIXME: This case should be broken out into processEndTagForInHead,
         // because other end tag cases now refer to it ("process the token for using the rules of the "in head" insertion mode").
         // but because the logic falls through to InsertionMode::AfterHead, that gets a little messy.
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (token->name() == templateTag) {
+        if (token.name() == templateTag) {
             processTemplateEndTag(token);
             return;
         }
 #endif
-        if (token->name() == headTag) {
+        if (token.name() == headTag) {
             m_tree.openElements()->popHTMLHeadElement();
-            setInsertionMode(InsertionMode::AfterHead);
+            m_insertionMode = InsertionMode::AfterHead;
             return;
         }
-        if (token->name() != bodyTag && token->name() != htmlTag && token->name() != brTag) {
+        if (token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
             parseError(token);
             return;
         }
         defaultForInHead();
+        ASSERT(m_insertionMode == InsertionMode::AfterHead);
         FALLTHROUGH;
     case InsertionMode::AfterHead:
-        ASSERT(insertionMode() == InsertionMode::AfterHead);
-        if (token->name() != bodyTag && token->name() != htmlTag && token->name() != brTag) {
+        if (token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
             parseError(token);
             return;
         }
         defaultForAfterHead();
+        ASSERT(m_insertionMode == InsertionMode::InBody);
         FALLTHROUGH;
     case InsertionMode::InBody:
-        ASSERT(insertionMode() == InsertionMode::InBody);
         processEndTagForInBody(token);
         break;
     case InsertionMode::InTable:
-        ASSERT(insertionMode() == InsertionMode::InTable);
         processEndTagForInTable(token);
         break;
     case InsertionMode::InCaption:
-        ASSERT(insertionMode() == InsertionMode::InCaption);
-        if (token->name() == captionTag) {
+        if (token.name() == captionTag) {
             processCaptionEndTagForInCaption();
             return;
         }
-        if (token->name() == tableTag) {
+        if (token.name() == tableTag) {
             parseError(token);
             if (!processCaptionEndTagForInCaption()) {
                 ASSERT(isParsingFragment());
@@ -2078,30 +2061,29 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
             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) {
+        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 InsertionMode::InColumnGroup:
-        ASSERT(insertionMode() == InsertionMode::InColumnGroup);
-        if (token->name() == colgroupTag) {
+        if (token.name() == colgroupTag) {
             processColgroupEndTagForInColumnGroup();
             return;
         }
-        if (token->name() == colTag) {
+        if (token.name() == colTag) {
             parseError(token);
             return;
         }
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (token->name() == templateTag) {
+        if (token.name() == templateTag) {
             processTemplateEndTag(token);
             return;
         }
@@ -2113,44 +2095,39 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
         processEndTag(token);
         break;
     case InsertionMode::InRow:
-        ASSERT(insertionMode() == InsertionMode::InRow);
         processEndTagForInRow(token);
         break;
     case InsertionMode::InCell:
-        ASSERT(insertionMode() == InsertionMode::InCell);
         processEndTagForInCell(token);
         break;
     case InsertionMode::InTableBody:
-        ASSERT(insertionMode() == InsertionMode::InTableBody);
         processEndTagForInTableBody(token);
         break;
     case InsertionMode::AfterBody:
-        ASSERT(insertionMode() == InsertionMode::AfterBody);
-        if (token->name() == htmlTag) {
+        if (token.name() == htmlTag) {
             if (isParsingFragment()) {
                 parseError(token);
                 return;
             }
-            setInsertionMode(InsertionMode::AfterAfterBody);
+            m_insertionMode = InsertionMode::AfterAfterBody;
             return;
         }
         FALLTHROUGH;
     case InsertionMode::AfterAfterBody:
-        ASSERT(insertionMode() == InsertionMode::AfterBody || insertionMode() == InsertionMode::AfterAfterBody);
+        ASSERT(m_insertionMode == InsertionMode::AfterBody || m_insertionMode == InsertionMode::AfterAfterBody);
         parseError(token);
-        setInsertionMode(InsertionMode::InBody);
+        m_insertionMode = InsertionMode::InBody;
         processEndTag(token);
         break;
     case InsertionMode::InHeadNoscript:
-        ASSERT(insertionMode() == InsertionMode::InHeadNoscript);
-        if (token->name() == noscriptTag) {
+        if (token.name() == noscriptTag) {
             ASSERT(m_tree.currentStackItem()->hasTagName(noscriptTag));
             m_tree.openElements()->pop();
             ASSERT(m_tree.currentStackItem()->hasTagName(headTag));
-            setInsertionMode(InsertionMode::InHead);
+            m_insertionMode = InsertionMode::InHead;
             return;
         }
-        if (token->name() != brTag) {
+        if (token.name() != brTag) {
             parseError(token);
             return;
         }
@@ -2158,13 +2135,13 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
         processToken(token);
         break;
     case InsertionMode::Text:
-        if (token->name() == scriptTag) {
+        if (token.name() == scriptTag) {
             // Pause ourselves so that parsing stops until the script can be processed by the caller.
             ASSERT(m_tree.currentStackItem()->hasTagName(scriptTag));
             if (scriptingContentIsAllowed(m_tree.parserContentPolicy()))
                 m_scriptToProcess = m_tree.currentElement();
             m_tree.openElements()->pop();
-            setInsertionMode(m_originalInsertionMode);
+            m_insertionMode = m_originalInsertionMode;
 
             if (m_parser.tokenizer()) {
                 // This token will not have been created by the tokenizer if a
@@ -2177,11 +2154,10 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
             return;
         }
         m_tree.openElements()->pop();
-        setInsertionMode(m_originalInsertionMode);
+        m_insertionMode = m_originalInsertionMode;
         break;
     case InsertionMode::InFrameset:
-        ASSERT(insertionMode() == InsertionMode::InFrameset);
-        if (token->name() == framesetTag) {
+        if (token.name() == framesetTag) {
             bool ignoreFramesetForFragmentParsing  = m_tree.currentIsRootNode();
 #if ENABLE(TEMPLATE_ELEMENT)
             ignoreFramesetForFragmentParsing = ignoreFramesetForFragmentParsing || m_tree.openElements()->hasTemplateInHTMLScope();
@@ -2193,46 +2169,44 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
             }
             m_tree.openElements()->pop();
             if (!isParsingFragment() && !m_tree.currentStackItem()->hasTagName(framesetTag))
-                setInsertionMode(InsertionMode::AfterFrameset);
+                m_insertionMode = InsertionMode::AfterFrameset;
             return;
         }
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (token->name() == templateTag) {
+        if (token.name() == templateTag) {
             processTemplateEndTag(token);
             return;
         }
 #endif
         break;
     case InsertionMode::AfterFrameset:
-        ASSERT(insertionMode() == InsertionMode::AfterFrameset);
-        if (token->name() == htmlTag) {
-            setInsertionMode(InsertionMode::AfterAfterFrameset);
+        if (token.name() == htmlTag) {
+            m_insertionMode = InsertionMode::AfterAfterFrameset;
             return;
         }
         FALLTHROUGH;
     case InsertionMode::AfterAfterFrameset:
-        ASSERT(insertionMode() == InsertionMode::AfterFrameset || insertionMode() == InsertionMode::AfterAfterFrameset);
+        ASSERT(m_insertionMode == InsertionMode::AfterFrameset || m_insertionMode == InsertionMode::AfterAfterFrameset);
         parseError(token);
         break;
     case InsertionMode::InSelectInTable:
-        ASSERT(insertionMode() == InsertionMode::InSelectInTable);
-        if (token->name() == captionTag
-            || token->name() == tableTag
-            || isTableBodyContextTag(token->name())
-            || token->name() == trTag
-            || isTableCellContextTag(token->name())) {
+        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())) {
+            if (m_tree.openElements()->inTableScope(token.name())) {
                 AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
-                processEndTag(&endSelect);
+                processEndTag(endSelect);
                 processEndTag(token);
             }
             return;
         }
         FALLTHROUGH;
     case InsertionMode::InSelect:
-        ASSERT(insertionMode() == InsertionMode::InSelect || insertionMode() == InsertionMode::InSelectInTable);
-        if (token->name() == optgroupTag) {
+        ASSERT(m_insertionMode == InsertionMode::InSelect || m_insertionMode == InsertionMode::InSelectInTable);
+        if (token.name() == optgroupTag) {
             if (is<HTMLOptionElement>(*m_tree.currentStackItem()->node()) && m_tree.oneBelowTop() && is<HTMLOptGroupElement>(*m_tree.oneBelowTop()->node()))
                 processFakeEndTag(optionTag);
             if (is<HTMLOptGroupElement>(*m_tree.currentStackItem()->node())) {
@@ -2242,7 +2216,7 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
             parseError(token);
             return;
         }
-        if (token->name() == optionTag) {
+        if (token.name() == optionTag) {
             if (is<HTMLOptionElement>(*m_tree.currentStackItem()->node())) {
                 m_tree.openElements()->pop();
                 return;
@@ -2250,8 +2224,8 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
             parseError(token);
             return;
         }
-        if (token->name() == selectTag) {
-            if (!m_tree.openElements()->inSelectScope(token->name())) {
+        if (token.name() == selectTag) {
+            if (!m_tree.openElements()->inSelectScope(token.name())) {
                 ASSERT(isParsingFragment());
                 parseError(token);
                 return;
@@ -2261,7 +2235,7 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
             return;
         }
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (token->name() == templateTag) {
+        if (token.name() == templateTag) {
             processTemplateEndTag(token);
             return;
         }
@@ -2271,31 +2245,29 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
         defaultForInTableText();
         processEndTag(token);
         break;
-    case InsertionMode::TemplateContents:
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (token->name() == templateTag) {
+    case InsertionMode::TemplateContents:
+        if (token.name() == templateTag) {
             processTemplateEndTag(token);
             return;
         }
-#else
-        ASSERT_NOT_REACHED();
-#endif
         break;
+#endif
     }
 }
 
-void HTMLTreeBuilder::processComment(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processComment(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::Comment);
+    ASSERT(token.type() == HTMLToken::Comment);
     if (m_insertionMode == InsertionMode::Initial
         || m_insertionMode == InsertionMode::BeforeHTML
         || m_insertionMode == InsertionMode::AfterAfterBody
         || m_insertionMode == InsertionMode::AfterAfterFrameset) {
-        m_tree.insertCommentOnDocument(token);
+        m_tree.insertCommentOnDocument(&token);
         return;
     }
     if (m_insertionMode == InsertionMode::AfterBody) {
-        m_tree.insertCommentOnHTMLHtmlElement(token);
+        m_tree.insertCommentOnHTMLHtmlElement(&token);
         return;
     }
     if (m_insertionMode == InsertionMode::InTableText) {
@@ -2303,18 +2275,19 @@ void HTMLTreeBuilder::processComment(AtomicHTMLToken* token)
         processComment(token);
         return;
     }
-    m_tree.insertComment(token);
+    m_tree.insertComment(&token);
 }
 
-void HTMLTreeBuilder::processCharacter(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processCharacter(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::Character);
+    ASSERT(token.type() == HTMLToken::Character);
     ExternalCharacterTokenBuffer buffer(token);
     processCharacterBuffer(buffer);
 }
 
-// FIXME: Extract the following iOS-specific code into a separate file.
 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
+
+// FIXME: Extract the following iOS-specific code into a separate file.
 // From the string 4089961010, creates a link of the form <a href="tel:4089961010">4089961010</a> and inserts it.
 void HTMLTreeBuilder::insertPhoneNumberLink(const String& string)
 {
@@ -2325,10 +2298,10 @@ void HTMLTreeBuilder::insertPhoneNumberLink(const String& string)
     AtomicHTMLToken aStartToken(HTMLToken::StartTag, aTagLocalName, attributes);
     AtomicHTMLToken aEndToken(HTMLToken::EndTag, aTagLocalName);
 
-    processStartTag(&aStartToken);
+    processStartTag(aStartToken);
     m_tree.executeQueuedTasks();
     m_tree.insertTextNode(string);
-    processEndTag(&aEndToken);
+    processEndTag(aEndToken);
 }
 
 // Locates the phone numbers in the string and deals with it
@@ -2398,6 +2371,7 @@ static inline bool shouldParseTelephoneNumbersInNode(const ContainerNode& node)
     } while (currentNode);
     return true;
 }
+
 #endif // ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
 
 void HTMLTreeBuilder::processCharacterBuffer(ExternalCharacterTokenBuffer& buffer)
@@ -2421,77 +2395,68 @@ ReprocessBuffer:
             return;
     }
 
-    switch (insertionMode()) {
-    case InsertionMode::Initial: {
-        ASSERT(insertionMode() == InsertionMode::Initial);
+    switch (m_insertionMode) {
+    case InsertionMode::Initial:
         buffer.skipLeadingWhitespace();
         if (buffer.isEmpty())
             return;
         defaultForInitial();
+        ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
         FALLTHROUGH;
-    }
-    case InsertionMode::BeforeHTML: {
-        ASSERT(insertionMode() == InsertionMode::BeforeHTML);
+    case InsertionMode::BeforeHTML:
         buffer.skipLeadingWhitespace();
         if (buffer.isEmpty())
             return;
         defaultForBeforeHTML();
+        ASSERT(m_insertionMode == InsertionMode::BeforeHead);
         FALLTHROUGH;
-    }
-    case InsertionMode::BeforeHead: {
-        ASSERT(insertionMode() == InsertionMode::BeforeHead);
+    case InsertionMode::BeforeHead:
         buffer.skipLeadingWhitespace();
         if (buffer.isEmpty())
             return;
         defaultForBeforeHead();
+        ASSERT(m_insertionMode == InsertionMode::InHead);
         FALLTHROUGH;
-    }
     case InsertionMode::InHead: {
-        ASSERT(insertionMode() == InsertionMode::InHead);
         String leadingWhitespace = buffer.takeLeadingWhitespace();
         if (!leadingWhitespace.isEmpty())
             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
         if (buffer.isEmpty())
             return;
         defaultForInHead();
+        ASSERT(m_insertionMode == InsertionMode::AfterHead);
         FALLTHROUGH;
     }
     case InsertionMode::AfterHead: {
-        ASSERT(insertionMode() == InsertionMode::AfterHead);
         String leadingWhitespace = buffer.takeLeadingWhitespace();
         if (!leadingWhitespace.isEmpty())
             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
         if (buffer.isEmpty())
             return;
         defaultForAfterHead();
+        ASSERT(m_insertionMode == InsertionMode::InBody);
         FALLTHROUGH;
     }
     case InsertionMode::InBody:
     case InsertionMode::InCaption:
-    case InsertionMode::TemplateContents:
-    case InsertionMode::InCell: {
+    case InsertionMode::InCell:
 #if ENABLE(TEMPLATE_ELEMENT)
-        ASSERT(insertionMode() == InsertionMode::InBody || insertionMode() == InsertionMode::InCaption || insertionMode() == InsertionMode::InCell || insertionMode() == InsertionMode::TemplateContents);
-#else
-        ASSERT(insertionMode() != InsertionMode::TemplateContents);
-        ASSERT(insertionMode() == InsertionMode::InBody || insertionMode() == InsertionMode::InCaption || insertionMode() == InsertionMode::InCell);
+    case InsertionMode::TemplateContents:
 #endif
         processCharacterBufferForInBody(buffer);
         break;
-    }
     case InsertionMode::InTable:
     case InsertionMode::InTableBody:
-    case InsertionMode::InRow: {
-        ASSERT(insertionMode() == InsertionMode::InTable || insertionMode() == InsertionMode::InTableBody || insertionMode() == InsertionMode::InRow);
+    case InsertionMode::InRow:
         ASSERT(m_pendingTableCharacters.isEmpty());
         if (m_tree.currentStackItem()->isElementNode()
-            && (is<HTMLTableElement>(*m_tree.currentStackItem()->node())
+            && (is<HTMLTableElement>(*m_tree.currentStackItem()->element())
                 || m_tree.currentStackItem()->hasTagName(HTMLNames::tbodyTag)
                 || m_tree.currentStackItem()->hasTagName(HTMLNames::tfootTag)
                 || m_tree.currentStackItem()->hasTagName(HTMLNames::theadTag)
                 || m_tree.currentStackItem()->hasTagName(HTMLNames::trTag))) {
             m_originalInsertionMode = m_insertionMode;
-            setInsertionMode(InsertionMode::InTableText);
+            m_insertionMode = InsertionMode::InTableText;
             // Note that we fall through to the InsertionMode::InTableText case below.
         } else {
             HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
@@ -2499,13 +2464,10 @@ ReprocessBuffer:
             break;
         }
         FALLTHROUGH;
-    }
-    case InsertionMode::InTableText: {
+    case InsertionMode::InTableText:
         buffer.giveRemainingTo(m_pendingTableCharacters);
         break;
-    }
     case InsertionMode::InColumnGroup: {
-        ASSERT(insertionMode() == InsertionMode::InColumnGroup);
         String leadingWhitespace = buffer.takeLeadingWhitespace();
         if (!leadingWhitespace.isEmpty())
             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
@@ -2521,19 +2483,14 @@ ReprocessBuffer:
         goto ReprocessBuffer;
     }
     case InsertionMode::AfterBody:
-    case InsertionMode::AfterAfterBody: {
-        ASSERT(insertionMode() == InsertionMode::AfterBody || insertionMode() == InsertionMode::AfterAfterBody);
+    case InsertionMode::AfterAfterBody:
         // FIXME: parse error
-        setInsertionMode(InsertionMode::InBody);
+        m_insertionMode = InsertionMode::InBody;
         goto ReprocessBuffer;
-    }
-    case InsertionMode::Text: {
-        ASSERT(insertionMode() == InsertionMode::Text);
+    case InsertionMode::Text:
         m_tree.insertTextNode(buffer.takeRemaining());
         break;
-    }
     case InsertionMode::InHeadNoscript: {
-        ASSERT(insertionMode() == InsertionMode::InHeadNoscript);
         String leadingWhitespace = buffer.takeLeadingWhitespace();
         if (!leadingWhitespace.isEmpty())
             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
@@ -2544,7 +2501,6 @@ ReprocessBuffer:
     }
     case InsertionMode::InFrameset:
     case InsertionMode::AfterFrameset: {
-        ASSERT(insertionMode() == InsertionMode::InFrameset || insertionMode() == InsertionMode::AfterFrameset || insertionMode() == InsertionMode::AfterAfterFrameset);
         String leadingWhitespace = buffer.takeRemainingWhitespace();
         if (!leadingWhitespace.isEmpty())
             m_tree.insertTextNode(leadingWhitespace, AllWhitespace);
@@ -2553,11 +2509,9 @@ ReprocessBuffer:
         break;
     }
     case InsertionMode::InSelectInTable:
-    case InsertionMode::InSelect: {
-        ASSERT(insertionMode() == InsertionMode::InSelect || insertionMode() == InsertionMode::InSelectInTable);
+    case InsertionMode::InSelect:
         m_tree.insertTextNode(buffer.takeRemaining());
         break;
-    }
     case InsertionMode::AfterAfterFrameset: {
         String leadingWhitespace = buffer.takeRemainingWhitespace();
         if (!leadingWhitespace.isEmpty()) {
@@ -2583,64 +2537,55 @@ void HTMLTreeBuilder::processCharacterBufferForInBody(ExternalCharacterTokenBuff
 #else
     m_tree.insertTextNode(characters);
 #endif
-
     if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
         m_framesetOk = false;
 }
 
-void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::EndOfFile);
-    switch (insertionMode()) {
+    ASSERT(token.type() == HTMLToken::EndOfFile);
+    switch (m_insertionMode) {
     case InsertionMode::Initial:
-        ASSERT(insertionMode() == InsertionMode::Initial);
         defaultForInitial();
+        ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
         FALLTHROUGH;
     case InsertionMode::BeforeHTML:
-        ASSERT(insertionMode() == InsertionMode::BeforeHTML);
         defaultForBeforeHTML();
+        ASSERT(m_insertionMode == InsertionMode::BeforeHead);
         FALLTHROUGH;
     case InsertionMode::BeforeHead:
-        ASSERT(insertionMode() == InsertionMode::BeforeHead);
         defaultForBeforeHead();
+        ASSERT(m_insertionMode == InsertionMode::InHead);
         FALLTHROUGH;
     case InsertionMode::InHead:
-        ASSERT(insertionMode() == InsertionMode::InHead);
         defaultForInHead();
+        ASSERT(m_insertionMode == InsertionMode::AfterHead);
         FALLTHROUGH;
     case InsertionMode::AfterHead:
-        ASSERT(insertionMode() == InsertionMode::AfterHead);
         defaultForAfterHead();
+        ASSERT(m_insertionMode == InsertionMode::InBody);
         FALLTHROUGH;
     case InsertionMode::InBody:
     case InsertionMode::InCell:
     case InsertionMode::InCaption:
     case InsertionMode::InRow:
-#if ENABLE(TEMPLATE_ELEMENT)
-        ASSERT(insertionMode() == InsertionMode::InBody || insertionMode() == InsertionMode::InCell || insertionMode() == InsertionMode::InCaption || insertionMode() == InsertionMode::InRow || insertionMode() == InsertionMode::TemplateContents);
-#else
-        ASSERT(insertionMode() != InsertionMode::TemplateContents);
-        ASSERT(insertionMode() == InsertionMode::InBody || insertionMode() == InsertionMode::InCell || insertionMode() == InsertionMode::InCaption || insertionMode() == InsertionMode::InRow);
-#endif
         notImplemented(); // Emit parse error based on what elements are still open.
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (!m_templateInsertionModes.isEmpty())
+        if (!m_templateInsertionModes.isEmpty()) {
             if (processEndOfFileForInTemplateContents(token))
                 return;
+        }
 #endif
         break;
     case InsertionMode::AfterBody:
     case InsertionMode::AfterAfterBody:
-        ASSERT(insertionMode() == InsertionMode::AfterBody || insertionMode() == InsertionMode::AfterAfterBody);
         break;
     case InsertionMode::InHeadNoscript:
-        ASSERT(insertionMode() == InsertionMode::InHeadNoscript);
         defaultForInHeadNoscript();
         processEndOfFile(token);
         return;
     case InsertionMode::AfterFrameset:
     case InsertionMode::AfterAfterFrameset:
-        ASSERT(insertionMode() == InsertionMode::AfterFrameset || insertionMode() == InsertionMode::AfterAfterFrameset);
         break;
     case InsertionMode::InColumnGroup:
         if (m_tree.currentIsRootNode()) {
@@ -2659,14 +2604,14 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken* token)
     case InsertionMode::InTableBody:
     case InsertionMode::InSelectInTable:
     case InsertionMode::InSelect:
-        ASSERT(insertionMode() == InsertionMode::InSelect || insertionMode() == InsertionMode::InSelectInTable || insertionMode() == InsertionMode::InTable || insertionMode() == InsertionMode::InFrameset || insertionMode() == InsertionMode::InTableBody || insertionMode() == InsertionMode::InColumnGroup);
+        ASSERT(m_insertionMode == InsertionMode::InSelect || m_insertionMode == InsertionMode::InSelectInTable || m_insertionMode == InsertionMode::InTable || m_insertionMode == InsertionMode::InFrameset || m_insertionMode == InsertionMode::InTableBody || m_insertionMode == InsertionMode::InColumnGroup);
         if (m_tree.currentNode() != m_tree.openElements()->rootNode())
             parseError(token);
-
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (!m_templateInsertionModes.isEmpty())
+        if (!m_templateInsertionModes.isEmpty()) {
             if (processEndOfFileForInTemplateContents(token))
                 return;
+        }
 #endif
         break;
     case InsertionMode::InTableText:
@@ -2679,16 +2624,14 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken* token)
             notImplemented(); // mark the script element as "already started".
         m_tree.openElements()->pop();
         ASSERT(m_originalInsertionMode != InsertionMode::Text);
-        setInsertionMode(m_originalInsertionMode);
+        m_insertionMode = m_originalInsertionMode;
         processEndOfFile(token);
         return;
-    case InsertionMode::TemplateContents:
 #if ENABLE(TEMPLATE_ELEMENT)
+    case InsertionMode::TemplateContents:
         if (processEndOfFileForInTemplateContents(token))
             return;
         break;
-#else
-        ASSERT_NOT_REACHED();
 #endif
     }
     ASSERT(m_tree.currentNode());
@@ -2700,38 +2643,38 @@ void HTMLTreeBuilder::defaultForInitial()
     notImplemented();
     m_tree.setDefaultCompatibilityMode();
     // FIXME: parse error
-    setInsertionMode(InsertionMode::BeforeHTML);
+    m_insertionMode = InsertionMode::BeforeHTML;
 }
 
 void HTMLTreeBuilder::defaultForBeforeHTML()
 {
     AtomicHTMLToken startHTML(HTMLToken::StartTag, htmlTag.localName());
     m_tree.insertHTMLHtmlStartTagBeforeHTML(&startHTML);
-    setInsertionMode(InsertionMode::BeforeHead);
+    m_insertionMode = InsertionMode::BeforeHead;
 }
 
 void HTMLTreeBuilder::defaultForBeforeHead()
 {
     AtomicHTMLToken startHead(HTMLToken::StartTag, headTag.localName());
-    processStartTag(&startHead);
+    processStartTag(startHead);
 }
 
 void HTMLTreeBuilder::defaultForInHead()
 {
     AtomicHTMLToken endHead(HTMLToken::EndTag, headTag.localName());
-    processEndTag(&endHead);
+    processEndTag(endHead);
 }
 
 void HTMLTreeBuilder::defaultForInHeadNoscript()
 {
     AtomicHTMLToken endNoscript(HTMLToken::EndTag, noscriptTag.localName());
-    processEndTag(&endNoscript);
+    processEndTag(endNoscript);
 }
 
 void HTMLTreeBuilder::defaultForAfterHead()
 {
     AtomicHTMLToken startBody(HTMLToken::StartTag, bodyTag.localName());
-    processStartTag(&startBody);
+    processStartTag(startBody);
     m_framesetOk = true;
 }
 
@@ -2745,90 +2688,90 @@ void HTMLTreeBuilder::defaultForInTableText()
         m_tree.reconstructTheActiveFormattingElements();
         m_tree.insertTextNode(characters, NotAllWhitespace);
         m_framesetOk = false;
-        setInsertionMode(m_originalInsertionMode);
+        m_insertionMode = m_originalInsertionMode;
         return;
     }
     m_tree.insertTextNode(characters);
-    setInsertionMode(m_originalInsertionMode);
+    m_insertionMode = m_originalInsertionMode;
 }
 
-bool HTMLTreeBuilder::processStartTagForInHead(AtomicHTMLToken* token)
+bool HTMLTreeBuilder::processStartTagForInHead(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::StartTag);
-    if (token->name() == htmlTag) {
+    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.insertSelfClosingHTMLElement(token);
+    if (token.name() == baseTag
+        || token.name() == basefontTag
+        || token.name() == bgsoundTag
+        || token.name() == commandTag
+        || token.name() == linkTag
+        || token.name() == metaTag) {
+        m_tree.insertSelfClosingHTMLElement(&token);
         // Note: The custom processing for the <meta> tag is done in HTMLMetaElement::process().
         return true;
     }
-    if (token->name() == titleTag) {
+    if (token.name() == titleTag) {
         processGenericRCDATAStartTag(token);
         return true;
     }
-    if (token->name() == noscriptTag) {
+    if (token.name() == noscriptTag) {
         if (m_options.scriptEnabled) {
             processGenericRawTextStartTag(token);
             return true;
         }
-        m_tree.insertHTMLElement(token);
-        setInsertionMode(InsertionMode::InHeadNoscript);
+        m_tree.insertHTMLElement(&token);
+        m_insertionMode = InsertionMode::InHeadNoscript;
         return true;
     }
-    if (token->name() == noframesTag || token->name() == styleTag) {
+    if (token.name() == noframesTag || token.name() == styleTag) {
         processGenericRawTextStartTag(token);
         return true;
     }
-    if (token->name() == scriptTag) {
+    if (token.name() == scriptTag) {
         processScriptStartTag(token);
-        if (m_options.usePreHTML5ParserQuirks && token->selfClosing())
+        if (m_options.usePreHTML5ParserQuirks && token.selfClosing())
             processFakeEndTag(scriptTag);
         return true;
     }
 #if ENABLE(TEMPLATE_ELEMENT)
-    if (token->name() == templateTag) {
+    if (token.name() == templateTag) {
         processTemplateStartTag(token);
         return true;
     }
 #endif
-    if (token->name() == headTag) {
+    if (token.name() == headTag) {
         parseError(token);
         return true;
     }
     return false;
 }
 
-void HTMLTreeBuilder::processGenericRCDATAStartTag(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processGenericRCDATAStartTag(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::StartTag);
-    m_tree.insertHTMLElement(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(InsertionMode::Text);
+    m_insertionMode = InsertionMode::Text;
 }
 
-void HTMLTreeBuilder::processGenericRawTextStartTag(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processGenericRawTextStartTag(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::StartTag);
-    m_tree.insertHTMLElement(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(InsertionMode::Text);
+    m_insertionMode = InsertionMode::Text;
 }
 
-void HTMLTreeBuilder::processScriptStartTag(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processScriptStartTag(AtomicHTMLToken& token)
 {
-    ASSERT(token->type() == HTMLToken::StartTag);
-    m_tree.insertScriptElement(token);
+    ASSERT(token.type() == HTMLToken::StartTag);
+    m_tree.insertScriptElement(&token);
     if (m_parser.tokenizer())
         m_parser.tokenizer()->setState(HTMLTokenizer::ScriptDataState);
     m_originalInsertionMode = m_insertionMode;
@@ -2837,55 +2780,55 @@ void HTMLTreeBuilder::processScriptStartTag(AtomicHTMLToken* token)
 
     m_scriptToProcessStartPosition = position;
 
-    setInsertionMode(InsertionMode::Text);
+    m_insertionMode = InsertionMode::Text;
 }
 
 // http://www.whatwg.org/specs/web-apps/current-work/#adjusted-current-node
-HTMLStackItem* HTMLTreeBuilder::adjustedCurrentStackItem() const
+HTMLStackItem& HTMLTreeBuilder::adjustedCurrentStackItem() const
 {
     ASSERT(!m_tree.isEmpty());
     if (isParsingFragment() && m_tree.openElements()->hasOnlyOneElement())
         return m_fragmentContext.contextElementStackItem();
 
-    return m_tree.currentStackItem();
+    return *m_tree.currentStackItem();
 }
 
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#tree-construction
-bool HTMLTreeBuilder::shouldProcessTokenInForeignContent(AtomicHTMLToken* token)
+bool HTMLTreeBuilder::shouldProcessTokenInForeignContent(AtomicHTMLToken& token)
 {
     if (m_tree.isEmpty())
         return false;
-    HTMLStackItem* adjustedCurrentNode = adjustedCurrentStackItem();
-    if (adjustedCurrentNode->isInHTMLNamespace())
+    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)
+    if (HTMLElementStack::isMathMLTextIntegrationPoint(&adjustedCurrentNode)) {
+        if (token.type() == HTMLToken::StartTag
+            && token.name() != MathMLNames::mglyphTag
+            && token.name() != MathMLNames::malignmarkTag)
             return false;
-        if (token->type() == HTMLToken::Character)
+        if (token.type() == HTMLToken::Character)
             return false;
     }
-    if (adjustedCurrentNode->hasTagName(MathMLNames::annotation_xmlTag)
-        && token->type() == HTMLToken::StartTag
-        && token->name() == SVGNames::svgTag)
+    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)
+    if (HTMLElementStack::isHTMLIntegrationPoint(&adjustedCurrentNode)) {
+        if (token.type() == HTMLToken::StartTag)
             return false;
-        if (token->type() == HTMLToken::Character)
+        if (token.type() == HTMLToken::Character)
             return false;
     }
-    if (token->type() == HTMLToken::EndOfFile)
+    if (token.type() == HTMLToken::EndOfFile)
         return false;
     return true;
 }
 
-void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken& token)
 {
-    HTMLStackItem* adjustedCurrentNode = adjustedCurrentStackItem();
+    HTMLStackItem& adjustedCurrentNode = adjustedCurrentStackItem();
     
-    switch (token->type()) {
+    switch (token.type()) {
     case HTMLToken::Uninitialized:
         ASSERT_NOT_REACHED();
         break;
@@ -2893,67 +2836,67 @@ void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token)
         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)))) {
+        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();
+        const AtomicString& currentNamespace = adjustedCurrentNode.namespaceURI();
         if (currentNamespace == MathMLNames::mathmlNamespaceURI)
-            adjustMathMLAttributes(*token);
+            adjustMathMLAttributes(token);
         if (currentNamespace == SVGNames::svgNamespaceURI) {
-            adjustSVGTagNameCase(*token);
-            adjustSVGAttributes(*token);
+            adjustSVGTagNameCase(token);
+            adjustSVGAttributes(token);
         }
-        adjustForeignAttributes(*token);
-        m_tree.insertForeignElement(token, currentNamespace);
+        adjustForeignAttributes(token);
+        m_tree.insertForeignElement(&token, currentNamespace);
         break;
     }
     case HTMLToken::EndTag: {
-        if (adjustedCurrentNode->namespaceURI() == SVGNames::svgNamespaceURI)
-            adjustSVGTagNameCase(*token);
+        if (adjustedCurrentNode.namespaceURI() == SVGNames::svgNamespaceURI)
+            adjustSVGTagNameCase(token);
 
-        if (token->name() == SVGNames::scriptTag && m_tree.currentStackItem()->hasTagName(SVGNames::scriptTag)) {
+        if (token.name() == SVGNames::scriptTag && m_tree.currentStackItem()->hasTagName(SVGNames::scriptTag)) {
             if (scriptingContentIsAllowed(m_tree.parserContentPolicy()))
                 m_scriptToProcess = m_tree.currentElement();
             m_tree.openElements()->pop();
@@ -2961,11 +2904,11 @@ void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token)
         }
         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()))
+            auto* nodeRecord = m_tree.openElements()->topRecord();
+            if (!nodeRecord->stackItem()->hasLocalName(token.name()))
                 parseError(token);
             while (1) {
-                if (nodeRecord->stackItem()->hasLocalName(token->name())) {
+                if (nodeRecord->stackItem()->hasLocalName(token.name())) {
                     m_tree.openElements()->popUntilPopped(nodeRecord->element());
                     return;
                 }
@@ -2980,10 +2923,10 @@ void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token)
         break;
     }
     case HTMLToken::Comment:
-        m_tree.insertComment(token);
+        m_tree.insertComment(&token);
         return;
     case HTMLToken::Character: {
-        String characters = String(token->characters(), token->charactersLength());
+        String characters = String(token.characters(), token.charactersLength());
         m_tree.insertTextNode(characters);
         if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
             m_framesetOk = false;
@@ -2997,6 +2940,8 @@ void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token)
 
 void HTMLTreeBuilder::finished()
 {
+    ASSERT(!m_destroyed);
+
     if (isParsingFragment())
         return;
 
@@ -3004,12 +2949,11 @@ void HTMLTreeBuilder::finished()
     ASSERT(m_templateInsertionModes.isEmpty());
 #endif
 
-    ASSERT(m_isAttached);
-    // Warning, this may detach the parser. Do not do anything else after this.
     m_tree.finishedParsing();
+    // The tree builder might have been destroyed as an indirect result of finishing the parsing.
 }
 
-void HTMLTreeBuilder::parseError(AtomicHTMLToken*)
+inline void HTMLTreeBuilder::parseError(AtomicHTMLToken&)
 {
 }
 
index ad9fa8970691f0b9cedf84177b1b94aa0b14a7c2..624dfa9362fa6d1c3427e432640dae0c0d315ad3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 Google, Inc. All Rights Reserved.
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef HTMLTreeBuilder_h
 #define HTMLTreeBuilder_h
 
-#include "FragmentScriptingPermission.h"
 #include "HTMLConstructionSite.h"
-#include "HTMLElementStack.h"
-#include "HTMLFormattingElementList.h"
 #include "HTMLParserOptions.h"
-#include "HTMLStackItem.h"
-#include "HTMLTokenizer.h"
-#include <wtf/Noncopyable.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
-#include <wtf/text/StringBuilder.h>
-#include <wtf/text/TextPosition.h>
 
 namespace WebCore {
 
-class AtomicHTMLToken;
-class Document;
-class DocumentFragment;
-class Element;
-class Frame;
-class HTMLToken;
-class HTMLDocument;
-class Node;
 class HTMLDocumentParser;
 
 class HTMLTreeBuilder {
-    WTF_MAKE_NONCOPYABLE(HTMLTreeBuilder); WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_FAST_ALLOCATED;
 public:
-    HTMLTreeBuilder(HTMLDocumentParser&, HTMLDocument&, ParserContentPolicy, const HTMLParserOptions&);
-    HTMLTreeBuilder(HTMLDocumentParser&, DocumentFragment&, Element* contextElement, ParserContentPolicy, const HTMLParserOptions&);
-    ~HTMLTreeBuilder();
+    HTMLTreeBuilder(const HTMLDocumentParser&, HTMLDocument&, ParserContentPolicy, const HTMLParserOptions&);
+    HTMLTreeBuilder(const HTMLDocumentParser&, DocumentFragment&, Element& contextElement, ParserContentPolicy, const HTMLParserOptions&);
+    void setShouldSkipLeadingNewline(bool);
 
-    const HTMLElementStack* openElements() const { return m_tree.openElements(); }
+    ~HTMLTreeBuilder();
 
-    bool isParsingFragment() const { return !!m_fragmentContext.fragment(); }
-#if ENABLE(TEMPLATE_ELEMENT)
-    bool isParsingTemplateContents() const { return m_tree.openElements()->hasTemplateInHTMLScope(); }
-#else
-    bool isParsingTemplateContents() const { return false; }
-#endif
-    bool isParsingFragmentOrTemplateContents() const { return isParsingFragment() || isParsingTemplateContents(); }
+    bool isParsingFragment() const;
 
-    void detach();
+    void constructTree(AtomicHTMLToken&);
 
-    void constructTree(AtomicHTMLToken*);
+    bool hasParserBlockingScript() const;
 
-    bool hasParserBlockingScript() const { return !!m_scriptToProcess; }
     // Must be called to take the parser-blocking script before calling the parser again.
-    PassRefPtr<Element> takeScriptToProcess(TextPosition& scriptStartPosition);
+    RefPtr<Element> takeScriptToProcess(TextPosition& scriptStartPosition);
 
     // Done, close any open tags, etc.
     void finished();
 
-    void setShouldSkipLeadingNewline(bool shouldSkip) { m_shouldSkipLeadingNewline = shouldSkip; }
-
 private:
     class ExternalCharacterTokenBuffer;
+
     // Represents HTML5 "insertion mode"
     // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#insertion-mode
     enum class InsertionMode {
@@ -94,7 +67,9 @@ private:
         InHead,
         InHeadNoscript,
         AfterHead,
+#if ENABLE(TEMPLATE_ELEMENT)
         TemplateContents,
+#endif
         InBody,
         Text,
         InTable,
@@ -113,52 +88,54 @@ private:
         AfterAfterFrameset,
     };
 
-#if ENABLE(TELEPHONE_NUMBER_DETECTION)
+    bool isParsingTemplateContents() const;
+    bool isParsingFragmentOrTemplateContents() const;
+
+#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
     void insertPhoneNumberLink(const String&);
     void linkifyPhoneNumbers(const String&);
 #endif
 
-    void processToken(AtomicHTMLToken*);
-
-    void processDoctypeToken(AtomicHTMLToken*);
-    void processStartTag(AtomicHTMLToken*);
-    void processEndTag(AtomicHTMLToken*);
-    void processComment(AtomicHTMLToken*);
-    void processCharacter(AtomicHTMLToken*);
-    void processEndOfFile(AtomicHTMLToken*);
-
-    bool processStartTagForInHead(AtomicHTMLToken*);
-    void processStartTagForInBody(AtomicHTMLToken*);
-    void processStartTagForInTable(AtomicHTMLToken*);
-    void processEndTagForInBody(AtomicHTMLToken*);
-    void processEndTagForInTable(AtomicHTMLToken*);
-    void processEndTagForInTableBody(AtomicHTMLToken*);
-    void processEndTagForInRow(AtomicHTMLToken*);
-    void processEndTagForInCell(AtomicHTMLToken*);
-
-    void processIsindexStartTagForInBody(AtomicHTMLToken*);
-    void processHtmlStartTagForInBody(AtomicHTMLToken*);
-    bool processBodyEndTagForInBody(AtomicHTMLToken*);
+    void processToken(AtomicHTMLToken&);
+
+    void processDoctypeToken(AtomicHTMLToken&);
+    void processStartTag(AtomicHTMLToken&);
+    void processEndTag(AtomicHTMLToken&);
+    void processComment(AtomicHTMLToken&);
+    void processCharacter(AtomicHTMLToken&);
+    void processEndOfFile(AtomicHTMLToken&);
+
+    bool processStartTagForInHead(AtomicHTMLToken&);
+    void processStartTagForInBody(AtomicHTMLToken&);
+    void processStartTagForInTable(AtomicHTMLToken&);
+    void processEndTagForInBody(AtomicHTMLToken&);
+    void processEndTagForInTable(AtomicHTMLToken&);
+    void processEndTagForInTableBody(AtomicHTMLToken&);
+    void processEndTagForInRow(AtomicHTMLToken&);
+    void processEndTagForInCell(AtomicHTMLToken&);
+
+    void processIsindexStartTagForInBody(AtomicHTMLToken&);
+    void processHtmlStartTagForInBody(AtomicHTMLToken&);
+    bool processBodyEndTagForInBody(AtomicHTMLToken&);
     bool processTableEndTagForInTable();
     bool processCaptionEndTagForInCaption();
     bool processColgroupEndTagForInColumnGroup();
     bool processTrEndTagForInRow();
-    // FIXME: This function should be inlined into its one call site or it
-    // needs to assert which tokens it can be called with.
-    void processAnyOtherEndTagForInBody(AtomicHTMLToken*);
+
+    void processAnyOtherEndTagForInBody(AtomicHTMLToken&);
 
     void processCharacterBuffer(ExternalCharacterTokenBuffer&);
     inline void processCharacterBufferForInBody(ExternalCharacterTokenBuffer&);
 
-    void processFakeStartTag(const QualifiedName&, const Vector<Attribute>& attributes = Vector<Attribute>());
+    void processFakeStartTag(const QualifiedName&, Vector<Attribute>&& attributes = Vector<Attribute>());
     void processFakeEndTag(const QualifiedName&);
     void processFakeEndTag(const AtomicString&);
     void processFakeCharacters(const String&);
     void processFakePEndTagIfPInButtonScope();
 
-    void processGenericRCDATAStartTag(AtomicHTMLToken*);
-    void processGenericRawTextStartTag(AtomicHTMLToken*);
-    void processScriptStartTag(AtomicHTMLToken*);
+    void processGenericRCDATAStartTag(AtomicHTMLToken&);
+    void processGenericRawTextStartTag(AtomicHTMLToken&);
+    void processScriptStartTag(AtomicHTMLToken&);
 
     // Default processing for the different insertion modes.
     void defaultForInitial();
@@ -169,81 +146,104 @@ private:
     void defaultForAfterHead();
     void defaultForInTableText();
 
-    inline bool shouldProcessTokenInForeignContent(AtomicHTMLToken*);
-    void processTokenInForeignContent(AtomicHTMLToken*);
+    bool shouldProcessTokenInForeignContent(AtomicHTMLToken&);
+    void processTokenInForeignContent(AtomicHTMLToken&);
     
-    inline HTMLStackItem* adjustedCurrentStackItem() const;
+    HTMLStackItem& adjustedCurrentStackItem() const;
 
-    Vector<Attribute> attributesForIsindexInput(AtomicHTMLToken*);
+    Vector<Attribute> attributesForIsindexInput(AtomicHTMLToken&);
 
-    void callTheAdoptionAgency(AtomicHTMLToken*);
+    void callTheAdoptionAgency(AtomicHTMLToken&);
 
     void closeTheCell();
 
-    template <bool shouldClose(const HTMLStackItem*)>
-    void processCloseWhenNestedTag(AtomicHTMLToken*);
+    template <bool shouldClose(const HTMLStackItem&)> void processCloseWhenNestedTag(AtomicHTMLToken&);
 
-    void parseError(AtomicHTMLToken*);
-
-    InsertionMode insertionMode() const { return m_insertionMode; }
-    void setInsertionMode(InsertionMode mode) { m_insertionMode = mode; }
+    void parseError(AtomicHTMLToken&);
 
     void resetInsertionModeAppropriately();
 
 #if ENABLE(TEMPLATE_ELEMENT)
-    void processTemplateStartTag(AtomicHTMLToken*);
-    bool processTemplateEndTag(AtomicHTMLToken*);
-    bool processEndOfFileForInTemplateContents(AtomicHTMLToken*);
+    void processTemplateStartTag(AtomicHTMLToken&);
+    bool processTemplateEndTag(AtomicHTMLToken&);
+    bool processEndOfFileForInTemplateContents(AtomicHTMLToken&);
 #endif
 
     class FragmentParsingContext {
-        WTF_MAKE_NONCOPYABLE(FragmentParsingContext);
     public:
         FragmentParsingContext();
-        FragmentParsingContext(DocumentFragment&, Element* contextElement);
-        ~FragmentParsingContext();
+        FragmentParsingContext(DocumentFragment&, Element& contextElement);
 
-        DocumentFragment* fragment() const { return m_fragment; }
-        Element* contextElement() const { ASSERT(m_fragment); return m_contextElementStackItem->element(); }
-        HTMLStackItem* contextElementStackItem() const { ASSERT(m_fragment); return m_contextElementStackItem.get(); }
+        DocumentFragment* fragment() const;
+        Element& contextElement() const;
+        HTMLStackItem& contextElementStackItem() const;
 
     private:
-        DocumentFragment* m_fragment;
+        DocumentFragment* m_fragment { nullptr };
         RefPtr<HTMLStackItem> m_contextElementStackItem;
     };
 
-    bool m_framesetOk;
-#ifndef NDEBUG
-    bool m_isAttached;
-#endif
-    FragmentParsingContext m_fragmentContext;
-    HTMLConstructionSite m_tree;
-
-    // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#insertion-mode
-    InsertionMode m_insertionMode;
+    const HTMLDocumentParser& m_parser;
+    const HTMLParserOptions m_options;
+    const FragmentParsingContext m_fragmentContext;
 
-    // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#original-insertion-mode
-    InsertionMode m_originalInsertionMode;
+    HTMLConstructionSite m_tree;
 
+    // https://html.spec.whatwg.org/multipage/syntax.html#the-insertion-mode
+    InsertionMode m_insertionMode { InsertionMode::Initial };
+    InsertionMode m_originalInsertionMode { InsertionMode::Initial };
 #if ENABLE(TEMPLATE_ELEMENT)
-    Vector<InsertionMode> m_templateInsertionModes;
+    Vector<InsertionMode, 1> m_templateInsertionModes;
 #endif
 
-    // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#pending-table-character-tokens
+    // https://html.spec.whatwg.org/multipage/syntax.html#concept-pending-table-char-tokens
     StringBuilder m_pendingTableCharacters;
 
-    bool m_shouldSkipLeadingNewline;
-
-    // We access parser because HTML5 spec requires that we be able to change the state of the tokenizer
-    // from within parser actions. We also need it to track the current position.
-    HTMLDocumentParser& m_parser;
-
     RefPtr<Element> m_scriptToProcess; // <script> tag which needs processing before resuming the parser.
     TextPosition m_scriptToProcessStartPosition; // Starting line number of the script tag needing processing.
 
-    HTMLParserOptions m_options;
+    bool m_shouldSkipLeadingNewline { false };
+
+    bool m_framesetOk { true };
+
+#if !ASSERT_DISABLED
+    bool m_destroyed { false };
+    bool m_destructionProhibited { true };
+#endif
 };
 
+inline HTMLTreeBuilder::~HTMLTreeBuilder()
+{
+#if !ASSERT_DISABLED
+    ASSERT(!m_destroyed);
+    ASSERT(!m_destructionProhibited);
+    m_destroyed = true;
+#endif
+}
+
+inline void HTMLTreeBuilder::setShouldSkipLeadingNewline(bool shouldSkip)
+{
+    ASSERT(!m_destroyed);
+    m_shouldSkipLeadingNewline = shouldSkip;
+}
+
+inline bool HTMLTreeBuilder::isParsingFragment() const
+{
+    ASSERT(!m_destroyed);
+    return !!m_fragmentContext.fragment();
+}
+
+inline bool HTMLTreeBuilder::hasParserBlockingScript() const
+{
+    ASSERT(!m_destroyed);
+    return !!m_scriptToProcess;
+}
+
+inline DocumentFragment* HTMLTreeBuilder::FragmentParsingContext::fragment() const
+{
+    return m_fragment;
+}
+
 }
 
 #endif
index b2736f327e814d6519f34218b3a409b0a1840d5e..f6a56760c38338925be1f373a5ca6d3354706662 100644 (file)
@@ -59,7 +59,7 @@ void TextDocumentParser::insertFakePreElement()
     Vector<Attribute> attributes;
     attributes.append(Attribute(styleAttr, "word-wrap: break-word; white-space: pre-wrap;"));
     AtomicHTMLToken fakePre(HTMLToken::StartTag, preTag.localName(), attributes);
-    treeBuilder()->constructTree(&fakePre);
+    treeBuilder()->constructTree(fakePre);
 
     // Normally we would skip the first \n after a <pre> element, but we don't
     // want to skip the first \n for text documents!