summaryrefslogtreecommitdiff
path: root/Source/WebCore/html/parser/HTMLTreeBuilder.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/html/parser/HTMLTreeBuilder.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/html/parser/HTMLTreeBuilder.cpp')
-rw-r--r--Source/WebCore/html/parser/HTMLTreeBuilder.cpp2499
1 files changed, 1159 insertions, 1340 deletions
diff --git a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp
index 46b3baf47..4b22f4f8f 100644
--- a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp
+++ b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 Google, Inc. All Rights Reserved.
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,48 +30,42 @@
#include "DocumentFragment.h"
#include "HTMLDocument.h"
#include "HTMLDocumentParser.h"
+#include "HTMLFormControlElement.h"
#include "HTMLFormElement.h"
#include "HTMLOptGroupElement.h"
#include "HTMLOptionElement.h"
#include "HTMLParserIdioms.h"
+#include "HTMLScriptElement.h"
#include "HTMLTableElement.h"
-#include "HTMLTemplateElement.h"
+#include "JSCustomElementInterface.h"
#include "LocalizedStrings.h"
#include "NotImplemented.h"
+#include "SVGScriptElement.h"
#include "XLinkNames.h"
#include "XMLNSNames.h"
#include "XMLNames.h"
-#include <wtf/MainThread.h>
+#include <wtf/NeverDestroyed.h>
#include <wtf/unicode/CharacterNames.h>
-// FIXME: Extract the following iOS-specific code into a separate file.
-#if PLATFORM(IOS)
-#include "SoftLinking.h"
-
-#ifdef __has_include
-#if __has_include(<DataDetectorsCore/DDDFACache.h>)
-#include <DataDetectorsCore/DDDFACache.h>
-#else
-typedef void* DDDFACacheRef;
-#endif
-
-#if __has_include(<DataDetectorsCore/DDDFAScanner.h>)
-#include <DataDetectorsCore/DDDFAScanner.h>
-#else
-typedef void* DDDFAScannerRef;
-#endif
-#endif
-
-SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(DataDetectorsCore)
-SOFT_LINK(DataDetectorsCore, DDDFACacheCreateFromFramework, DDDFACacheRef, (), ())
-SOFT_LINK(DataDetectorsCore, DDDFAScannerCreateFromCache, DDDFAScannerRef, (DDDFACacheRef cache), (cache))
-SOFT_LINK(DataDetectorsCore, DDDFAScannerFirstResultInUnicharArray, Boolean, (DDDFAScannerRef scanner, const UniChar* str, unsigned length, int* startPos, int* endPos), (scanner, str, length, startPos, endPos))
+#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
+#include "TelephoneNumberDetector.h"
#endif
namespace WebCore {
using namespace HTMLNames;
+CustomElementConstructionData::CustomElementConstructionData(Ref<JSCustomElementInterface>&& customElementInterface, const AtomicString& name, Vector<Attribute>&& attributes)
+ : elementInterface(WTFMove(customElementInterface))
+ , name(name)
+ , attributes(WTFMove(attributes))
+{
+}
+
+CustomElementConstructionData::~CustomElementConstructionData()
+{
+}
+
namespace {
inline bool isHTMLSpaceOrReplacementCharacter(UChar character)
@@ -81,9 +75,9 @@ inline bool isHTMLSpaceOrReplacementCharacter(UChar character)
}
-static TextPosition uninitializedPositionValue1()
+static inline TextPosition uninitializedPositionValue1()
{
- return TextPosition(OrdinalNumber::fromOneBasedInt(-1), OrdinalNumber::first());
+ return TextPosition(OrdinalNumber::fromOneBasedInt(-1), OrdinalNumber());
}
static inline bool isAllWhitespace(const String& string)
@@ -108,9 +102,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)
@@ -120,9 +112,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)
@@ -143,31 +133,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
-static bool isFormattingTag(const AtomicString& tagName)
+// https://html.spec.whatwg.org/multipage/syntax.html#formatting
+bool HTMLConstructionSite::isFormattingTag(const AtomicString& tagName)
{
return tagName == aTag || isNonAnchorFormattingTag(tagName);
}
class HTMLTreeBuilder::ExternalCharacterTokenBuffer {
- WTF_MAKE_NONCOPYABLE(ExternalCharacterTokenBuffer);
public:
- explicit ExternalCharacterTokenBuffer(AtomicHTMLToken* token)
- : m_current(token->characters())
- , m_end(m_current + token->charactersLength())
- , m_isAll8BitData(token->isAll8BitData())
+ explicit ExternalCharacterTokenBuffer(AtomicHTMLToken& token)
+ : m_text(token.characters(), token.charactersLength())
+ , m_isAll8BitData(token.charactersIsAll8BitData())
{
ASSERT(!isEmpty());
}
explicit ExternalCharacterTokenBuffer(const String& string)
- : m_current(string.deprecatedCharacters())
- , m_end(m_current + string.length())
- , m_isAll8BitData(string.length() && string.is8Bit())
+ : m_text(string)
+ , m_isAll8BitData(m_text.is8Bit())
{
ASSERT(!isEmpty());
}
@@ -177,15 +163,15 @@ public:
ASSERT(isEmpty());
}
- bool isEmpty() const { return m_current == m_end; }
+ bool isEmpty() const { return m_text.isEmpty(); }
bool isAll8BitData() const { return m_isAll8BitData; }
void skipAtMostOneLeadingNewline()
{
ASSERT(!isEmpty());
- if (*m_current == '\n')
- ++m_current;
+ if (m_text[0] == '\n')
+ m_text = m_text.substring(1);
}
void skipLeadingWhitespace()
@@ -205,246 +191,240 @@ public:
String takeRemaining()
{
- ASSERT(!isEmpty());
- const UChar* start = m_current;
- m_current = m_end;
- size_t length = m_current - start;
-
- if (isAll8BitData())
- return String::make8BitFrom16BitSource(start, length);
-
- return String(start, length);
+ String result = makeString(m_text);
+ m_text = StringView();
+ return result;
}
void giveRemainingTo(StringBuilder& recipient)
{
- recipient.append(m_current, m_end - m_current);
- m_current = m_end;
+ recipient.append(m_text);
+ m_text = StringView();
}
String takeRemainingWhitespace()
{
ASSERT(!isEmpty());
- Vector<UChar> whitespace;
+ Vector<LChar, 8> whitespace;
do {
- UChar cc = *m_current++;
- if (isHTMLSpace(cc))
- whitespace.append(cc);
- } while (m_current < m_end);
+ UChar character = m_text[0];
+ if (isHTMLSpace(character))
+ whitespace.append(character);
+ m_text = m_text.substring(1);
+ } while (!m_text.isEmpty());
+
// Returning the null string when there aren't any whitespace
// characters is slightly cleaner semantically because we don't want
// to insert a text node (as opposed to inserting an empty text node).
if (whitespace.isEmpty())
return String();
- return String::adopt(whitespace);
+
+ return String::adopt(WTFMove(whitespace));
}
private:
- template<bool characterPredicate(UChar)>
- void skipLeading()
+ template<bool characterPredicate(UChar)> void skipLeading()
{
ASSERT(!isEmpty());
- while (characterPredicate(*m_current)) {
- if (++m_current == m_end)
+ while (characterPredicate(m_text[0])) {
+ m_text = m_text.substring(1);
+ if (m_text.isEmpty())
return;
}
}
- template<bool characterPredicate(UChar)>
- String takeLeading()
+ template<bool characterPredicate(UChar)> String takeLeading()
{
ASSERT(!isEmpty());
- const UChar* start = m_current;
+ StringView start = m_text;
skipLeading<characterPredicate>();
- if (start == m_current)
+ if (start.length() == m_text.length())
return String();
- if (isAll8BitData())
- return String::make8BitFrom16BitSource(start, m_current - start);
- return String(start, m_current - start);
+ return makeString(start.substring(0, start.length() - m_text.length()));
}
- const UChar* m_current;
- const UChar* m_end;
+ String makeString(StringView stringView) const
+ {
+ if (stringView.is8Bit() || !isAll8BitData())
+ return stringView.toString();
+ return String::make8BitFrom16BitSource(stringView.characters16(), stringView.length());
+ }
+
+ StringView m_text;
bool m_isAll8BitData;
};
+inline bool HTMLTreeBuilder::isParsingTemplateContents() const
+{
+ return m_tree.openElements().hasTemplateInHTMLScope();
+}
+
+inline bool HTMLTreeBuilder::isParsingFragmentOrTemplateContents() const
+{
+ return isParsingFragment() || isParsingTemplateContents();
+}
HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser& parser, HTMLDocument& document, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options)
- : m_framesetOk(true)
-#ifndef NDEBUG
- , m_isAttached(true)
-#endif
+ : 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(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));
-
-#if ENABLE(TEMPLATE_ELEMENT)
- if (contextElement->hasTagName(templateTag))
- m_templateInsertionModes.append(InsertionMode::TemplateContents);
-#endif
- resetInsertionModeAppropriately();
- m_tree.setForm(!contextElement || isHTMLFormElement(contextElement) ? toHTMLFormElement(contextElement) : HTMLFormElement::findClosestFormAncestor(*contextElement));
- }
-}
+ // 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));
-HTMLTreeBuilder::~HTMLTreeBuilder()
-{
-}
+ if (contextElement.hasTagName(templateTag))
+ m_templateInsertionModes.append(InsertionMode::TemplateContents);
-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;
+ resetInsertionModeAppropriately();
+
+ m_tree.setForm(is<HTMLFormElement>(contextElement) ? &downcast<HTMLFormElement>(contextElement) : HTMLFormElement::findClosestFormAncestor(contextElement));
+
+#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)
- , m_contextElement(0)
{
}
-HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment& fragment, Element* contextElement)
+HTMLTreeBuilder::FragmentParsingContext::FragmentParsingContext(DocumentFragment& fragment, Element& contextElement)
: m_fragment(&fragment)
- , m_contextElement(contextElement)
{
ASSERT(!fragment.hasChildNodes());
+ m_contextElementStackItem = HTMLStackItem::create(contextElement);
+}
+
+inline Element& HTMLTreeBuilder::FragmentParsingContext::contextElement() const
+{
+ return contextElementStackItem().element();
}
-HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext()
+inline HTMLStackItem& HTMLTreeBuilder::FragmentParsingContext::contextElementStackItem() const
{
+ ASSERT(m_fragment);
+ return *m_contextElementStackItem;
}
-PassRefPtr<Element> HTMLTreeBuilder::takeScriptToProcess(TextPosition& scriptStartPosition)
+RefPtr<ScriptElement> HTMLTreeBuilder::takeScriptToProcess(TextPosition& scriptStartPosition)
{
- ASSERT(m_scriptToProcess);
+ 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 WTFMove(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);
+ processTokenInForeignContent(WTFMove(token));
else
- processToken(token);
+ processToken(WTFMove(token));
- if (m_parser.tokenizer()) {
- bool inForeignContent = !m_tree.isEmpty()
- && !m_tree.currentStackItem()->isInHTMLNamespace()
- && !HTMLElementStack::isHTMLIntegrationPoint(m_tree.currentStackItem())
- && !HTMLElementStack::isMathMLTextIntegrationPoint(m_tree.currentStackItem());
+ bool inForeignContent = !m_tree.isEmpty()
+ && !isInHTMLNamespace(adjustedCurrentStackItem())
+ && !HTMLElementStack::isHTMLIntegrationPoint(m_tree.currentStackItem())
+ && !HTMLElementStack::isMathMLTextIntegrationPoint(m_tree.currentStackItem());
- m_parser.tokenizer()->setForceNullCharacterReplacement(m_insertionMode == InsertionMode::Text || inForeignContent);
- m_parser.tokenizer()->setShouldAllowCDATA(inForeignContent);
- }
+ m_parser.tokenizer().setForceNullCharacterReplacement(m_insertionMode == InsertionMode::Text || inForeignContent);
+ 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;
case HTMLToken::DOCTYPE:
m_shouldSkipLeadingNewline = false;
- processDoctypeToken(token);
+ processDoctypeToken(WTFMove(token));
break;
case HTMLToken::StartTag:
m_shouldSkipLeadingNewline = false;
- processStartTag(token);
+ processStartTag(WTFMove(token));
break;
case HTMLToken::EndTag:
m_shouldSkipLeadingNewline = false;
- processEndTag(token);
+ processEndTag(WTFMove(token));
break;
case HTMLToken::Comment:
m_shouldSkipLeadingNewline = false;
- processComment(token);
+ processComment(WTFMove(token));
return;
case HTMLToken::Character:
- processCharacter(token);
+ processCharacter(WTFMove(token));
break;
case HTMLToken::EndOfFile:
m_shouldSkipLeadingNewline = false;
- processEndOfFile(token);
+ processEndOfFile(WTFMove(token));
break;
}
}
-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(WTFMove(token));
+ m_insertionMode = InsertionMode::BeforeHTML;
return;
}
if (m_insertionMode == InsertionMode::InTableText) {
defaultForInTableText();
- processDoctypeToken(token);
+ processDoctypeToken(WTFMove(token));
return;
}
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(), WTFMove(attributes));
+ processStartTag(WTFMove(fakeToken));
}
void HTMLTreeBuilder::processFakeEndTag(const AtomicString& tagName)
{
AtomicHTMLToken fakeToken(HTMLToken::EndTag, tagName);
- processEndTag(&fakeToken);
+ processEndTag(WTFMove(fakeToken));
}
void HTMLTreeBuilder::processFakeEndTag(const QualifiedName& tagName)
@@ -462,428 +442,363 @@ void HTMLTreeBuilder::processFakeCharacters(const String& characters)
void HTMLTreeBuilder::processFakePEndTagIfPInButtonScope()
{
- if (!m_tree.openElements()->inButtonScope(pTag.localName()))
+ if (!m_tree.openElements().inButtonScope(pTag.localName()))
return;
AtomicHTMLToken endP(HTMLToken::EndTag, pTag.localName());
- processEndTag(&endP);
-}
-
-Vector<Attribute> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken* token)
-{
- 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))
- attributes.remove(i);
- }
-
- attributes.append(Attribute(nameAttr, isindexTag.localName()));
- return attributes;
-}
-
-void HTMLTreeBuilder::processIsindexStartTagForInBody(AtomicHTMLToken* token)
-{
- 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);
- if (actionAttribute)
- m_tree.form()->setAttribute(actionAttr, actionAttribute->value());
- processFakeStartTag(hrTag);
- processFakeStartTag(labelTag);
- Attribute* promptAttribute = token->getAttributeItem(promptAttr);
- if (promptAttribute)
- processFakeCharacters(promptAttribute->value());
- else
- processFakeCharacters(searchableIndexIntroduction());
- processFakeStartTag(inputTag, attributesForIsindexInput(token));
- notImplemented(); // This second set of characters may be needed by non-english locales.
- processFakeEndTag(labelTag);
- processFakeStartTag(hrTag);
- processFakeEndTag(formTag);
+ processEndTag(WTFMove(endP));
}
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.isElement());
+ processFakeEndTag(item.localName());
break;
}
- if (item->isSpecialNode() && !item->hasTagName(addressTag) && !item->hasTagName(divTag) && !item->hasTagName(pTag))
+ if (isSpecialNode(item) && !item.hasTagName(addressTag) && !item.hasTagName(divTag) && !item.hasTagName(pTag))
break;
- nodeRecord = nodeRecord->next();
}
processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLElement(token);
+ m_tree.insertHTMLElement(WTFMove(token));
}
-typedef HashMap<AtomicString, QualifiedName> PrefixedNameToQualifiedNameMap;
-
-static void mapLoweredLocalNameToName(PrefixedNameToQualifiedNameMap* map, const QualifiedName* const names[], size_t length)
+template <typename TableQualifiedName> static HashMap<AtomicString, QualifiedName> createCaseMap(const TableQualifiedName* const names[], unsigned length)
{
- for (size_t i = 0; i < length; ++i) {
+ HashMap<AtomicString, QualifiedName> map;
+ for (unsigned i = 0; i < length; ++i) {
const QualifiedName& name = *names[i];
const AtomicString& localName = name.localName();
- AtomicString loweredLocalName = localName.lower();
+ AtomicString loweredLocalName = localName.convertToASCIILowercase();
if (loweredLocalName != localName)
- map->add(loweredLocalName, name);
+ map.add(loweredLocalName, name);
}
+ return map;
}
-static void adjustSVGTagNameCase(AtomicHTMLToken* token)
+static void adjustSVGTagNameCase(AtomicHTMLToken& token)
{
- static PrefixedNameToQualifiedNameMap* caseMap = 0;
- if (!caseMap) {
- caseMap = new PrefixedNameToQualifiedNameMap;
- mapLoweredLocalNameToName(caseMap, SVGNames::getSVGTags(), SVGNames::SVGTagsCount);
- }
-
- const QualifiedName& casedName = caseMap->get(token->name());
+ static NeverDestroyed<HashMap<AtomicString, QualifiedName>> map = createCaseMap(SVGNames::getSVGTags(), SVGNames::SVGTagsCount);
+ const QualifiedName& casedName = map.get().get(token.name());
if (casedName.localName().isNull())
return;
- token->setName(casedName.localName());
+ token.setName(casedName.localName());
}
-template<const QualifiedName* const * getAttrs(), unsigned length>
-static void adjustAttributes(AtomicHTMLToken* token)
+static inline void adjustAttributes(HashMap<AtomicString, QualifiedName>& map, AtomicHTMLToken& token)
{
- static PrefixedNameToQualifiedNameMap* caseMap = 0;
- if (!caseMap) {
- caseMap = new PrefixedNameToQualifiedNameMap;
- mapLoweredLocalNameToName(caseMap, getAttrs(), length);
- }
-
- for (unsigned i = 0; i < token->attributes().size(); ++i) {
- Attribute& tokenAttribute = token->attributes().at(i);
- const QualifiedName& casedName = caseMap->get(tokenAttribute.localName());
+ for (auto& attribute : token.attributes()) {
+ const QualifiedName& casedName = map.get(attribute.localName());
if (!casedName.localName().isNull())
- tokenAttribute.parserSetName(casedName);
+ attribute.parserSetName(casedName);
}
}
-static void adjustSVGAttributes(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);
+}
+
+static inline void adjustSVGAttributes(AtomicHTMLToken& token)
{
adjustAttributes<SVGNames::getSVGAttrs, SVGNames::SVGAttrsCount>(token);
}
-static void adjustMathMLAttributes(AtomicHTMLToken* token)
+static inline void adjustMathMLAttributes(AtomicHTMLToken& token)
{
adjustAttributes<MathMLNames::getMathMLAttrs, MathMLNames::MathMLAttrsCount>(token);
}
-static void addNamesWithPrefix(PrefixedNameToQualifiedNameMap* map, const AtomicString& prefix, const QualifiedName* const names[], size_t length)
+static void addNamesWithPrefix(HashMap<AtomicString, QualifiedName>& map, const AtomicString& prefix, const QualifiedName* const names[], unsigned length)
{
- for (size_t i = 0; i < length; ++i) {
+ for (unsigned i = 0; i < length; ++i) {
const QualifiedName& name = *names[i];
const AtomicString& localName = name.localName();
- AtomicString prefixColonLocalName = prefix + ':' + localName;
- QualifiedName nameWithPrefix(prefix, localName, name.namespaceURI());
- map->add(prefixColonLocalName, nameWithPrefix);
+ map.add(prefix + ':' + localName, QualifiedName(prefix, localName, name.namespaceURI()));
}
}
-static void adjustForeignAttributes(AtomicHTMLToken* token)
+static HashMap<AtomicString, QualifiedName> createForeignAttributesMap()
{
- static PrefixedNameToQualifiedNameMap* map = 0;
- if (!map) {
- map = new PrefixedNameToQualifiedNameMap;
+ HashMap<AtomicString, QualifiedName> map;
- addNamesWithPrefix(map, xlinkAtom, XLinkNames::getXLinkAttrs(), XLinkNames::XLinkAttrsCount);
+ AtomicString xlinkName("xlink", AtomicString::ConstructFromLiteral);
+ addNamesWithPrefix(map, xlinkName, XLinkNames::getXLinkAttrs(), XLinkNames::XLinkAttrsCount);
+ addNamesWithPrefix(map, xmlAtom, XMLNames::getXMLAttrs(), XMLNames::XMLAttrsCount);
- addNamesWithPrefix(map, xmlAtom, XMLNames::getXMLAttrs(), XMLNames::XMLAttrsCount);
+ map.add(WTF::xmlnsAtom, XMLNSNames::xmlnsAttr);
+ map.add("xmlns:xlink", QualifiedName(xmlnsAtom, xlinkName, XMLNSNames::xmlnsNamespaceURI));
- map->add(WTF::xmlnsAtom, XMLNSNames::xmlnsAttr);
- map->add("xmlns:xlink", QualifiedName(xmlnsAtom, xlinkAtom, XMLNSNames::xmlnsNamespaceURI));
- }
+ return map;
+}
- for (unsigned i = 0; i < token->attributes().size(); ++i) {
- Attribute& tokenAttribute = token->attributes().at(i);
- const QualifiedName& name = map->get(tokenAttribute.localName());
- if (!name.localName().isNull())
- tokenAttribute.parserSetName(name);
- }
+static void adjustForeignAttributes(AtomicHTMLToken& token)
+{
+ static NeverDestroyed<HashMap<AtomicString, QualifiedName>> map = createForeignAttributesMap();
+ adjustAttributes(map, token);
}
-void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken&& token)
{
- ASSERT(token->type() == HTMLToken::StartTag);
- if (token->name() == htmlTag) {
- processHtmlStartTagForInBody(token);
+ ASSERT(token.type() == HTMLToken::StartTag);
+ if (token.name() == htmlTag) {
+ processHtmlStartTagForInBody(WTFMove(token));
return;
}
- if (token->name() == baseTag
- || token->name() == basefontTag
- || token->name() == bgsoundTag
- || token->name() == commandTag
- || token->name() == linkTag
- || token->name() == metaTag
- || token->name() == noframesTag
- || token->name() == scriptTag
- || token->name() == styleTag
- || token->name() == titleTag) {
- bool didProcess = processStartTagForInHead(token);
+ if (token.name() == baseTag
+ || token.name() == basefontTag
+ || token.name() == bgsoundTag
+ || token.name() == commandTag
+ || token.name() == linkTag
+ || token.name() == metaTag
+ || token.name() == noframesTag
+ || token.name() == scriptTag
+ || token.name() == styleTag
+ || token.name() == titleTag) {
+ bool didProcess = processStartTagForInHead(WTFMove(token));
ASSERT_UNUSED(didProcess, didProcess);
return;
}
- if (token->name() == bodyTag) {
+ if (token.name() == bodyTag) {
parseError(token);
- bool fragmentOrTemplateCase = !m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement();
-#if ENABLE(TEMPLATE_ELEMENT)
- fragmentOrTemplateCase = fragmentOrTemplateCase || m_tree.openElements()->hasTemplateInHTMLScope();
-#endif
+ bool fragmentOrTemplateCase = !m_tree.openElements().secondElementIsHTMLBodyElement() || m_tree.openElements().hasOnlyOneElement()
+ || m_tree.openElements().hasTemplateInHTMLScope();
if (fragmentOrTemplateCase) {
ASSERT(isParsingFragmentOrTemplateContents());
return;
}
m_framesetOk = false;
- m_tree.insertHTMLBodyStartTagInBody(token);
+ m_tree.insertHTMLBodyStartTagInBody(WTFMove(token));
return;
}
- if (token->name() == framesetTag) {
+ if (token.name() == framesetTag) {
parseError(token);
- if (!m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement()) {
+ if (!m_tree.openElements().secondElementIsHTMLBodyElement() || m_tree.openElements().hasOnlyOneElement()) {
ASSERT(isParsingFragmentOrTemplateContents());
return;
}
if (!m_framesetOk)
return;
- m_tree.openElements()->bodyElement()->remove(ASSERT_NO_EXCEPTION);
- m_tree.openElements()->popUntil(m_tree.openElements()->bodyElement());
- m_tree.openElements()->popHTMLBodyElement();
- 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.openElements().bodyElement().remove();
+ m_tree.openElements().popUntil(m_tree.openElements().bodyElement());
+ m_tree.openElements().popHTMLBodyElement();
+ // Note: in the fragment case the root is a DocumentFragment instead of a proper html element which is a quirk / optimization in WebKit.
+ ASSERT(!isParsingFragment() || is<DocumentFragment>(m_tree.openElements().topNode()));
+ ASSERT(isParsingFragment() || &m_tree.openElements().top() == &m_tree.openElements().htmlElement());
+ m_tree.insertHTMLElement(WTFMove(token));
+ m_insertionMode = InsertionMode::InFrameset;
+ return;
+ }
+ if (token.name() == addressTag
+ || token.name() == articleTag
+ || token.name() == asideTag
+ || token.name() == blockquoteTag
+ || token.name() == centerTag
+ || token.name() == detailsTag
+ || token.name() == dirTag
+ || token.name() == divTag
+ || token.name() == dlTag
+ || token.name() == fieldsetTag
+ || token.name() == figcaptionTag
+ || token.name() == figureTag
+ || token.name() == footerTag
+ || token.name() == headerTag
+ || token.name() == hgroupTag
+ || token.name() == mainTag
+ || token.name() == menuTag
+ || token.name() == navTag
+ || token.name() == olTag
+ || token.name() == pTag
+ || token.name() == sectionTag
+ || token.name() == summaryTag
+ || token.name() == ulTag) {
processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLElement(token);
+ m_tree.insertHTMLElement(WTFMove(token));
return;
}
- if (isNumberedHeaderTag(token->name())) {
+ if (isNumberedHeaderTag(token.name())) {
processFakePEndTagIfPInButtonScope();
- if (m_tree.currentStackItem()->isNumberedHeaderElement()) {
+ if (isNumberedHeaderElement(m_tree.currentStackItem())) {
parseError(token);
- m_tree.openElements()->pop();
+ m_tree.openElements().pop();
}
- m_tree.insertHTMLElement(token);
+ m_tree.insertHTMLElement(WTFMove(token));
return;
}
- if (token->name() == preTag || token->name() == listingTag) {
+ if (token.name() == preTag || token.name() == listingTag) {
processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLElement(token);
+ m_tree.insertHTMLElement(WTFMove(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(WTFMove(token));
return;
}
- if (token->name() == liTag) {
- processCloseWhenNestedTag<isLi>(token);
+ if (token.name() == liTag) {
+ processCloseWhenNestedTag<isLi>(WTFMove(token));
return;
}
- if (token->name() == ddTag || token->name() == dtTag) {
- processCloseWhenNestedTag<isDdOrDt>(token);
+ if (token.name() == ddTag || token.name() == dtTag) {
+ processCloseWhenNestedTag<isDdOrDt>(WTFMove(token));
return;
}
- if (token->name() == plaintextTag) {
+ if (token.name() == plaintextTag) {
processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLElement(token);
- if (m_parser.tokenizer())
- m_parser.tokenizer()->setState(HTMLTokenizer::PLAINTEXTState);
+ m_tree.insertHTMLElement(WTFMove(token));
+ m_parser.tokenizer().setPLAINTEXTState();
return;
}
- if (token->name() == buttonTag) {
- if (m_tree.openElements()->inScope(buttonTag)) {
+ if (token.name() == buttonTag) {
+ if (m_tree.openElements().inScope(buttonTag)) {
parseError(token);
processFakeEndTag(buttonTag);
- processStartTag(token); // FIXME: Could we just fall through here?
+ processStartTag(WTFMove(token)); // FIXME: Could we just fall through here?
return;
}
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(token);
+ m_tree.insertHTMLElement(WTFMove(token));
m_framesetOk = false;
return;
}
- if (token->name() == aTag) {
- Element* activeATag = m_tree.activeFormattingElements()->closestElementInScopeWithName(aTag.localName());
+ if (token.name() == aTag) {
+ Element* activeATag = m_tree.activeFormattingElements().closestElementInScopeWithName(aTag.localName());
if (activeATag) {
parseError(token);
processFakeEndTag(aTag);
- m_tree.activeFormattingElements()->remove(activeATag);
- if (m_tree.openElements()->contains(activeATag))
- m_tree.openElements()->remove(activeATag);
+ m_tree.activeFormattingElements().remove(*activeATag);
+ if (m_tree.openElements().contains(*activeATag))
+ m_tree.openElements().remove(*activeATag);
}
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertFormattingElement(token);
+ m_tree.insertFormattingElement(WTFMove(token));
return;
}
- if (isNonAnchorNonNobrFormattingTag(token->name())) {
+ if (isNonAnchorNonNobrFormattingTag(token.name())) {
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertFormattingElement(token);
+ m_tree.insertFormattingElement(WTFMove(token));
return;
}
- if (token->name() == nobrTag) {
+ if (token.name() == nobrTag) {
m_tree.reconstructTheActiveFormattingElements();
- if (m_tree.openElements()->inScope(nobrTag)) {
+ if (m_tree.openElements().inScope(nobrTag)) {
parseError(token);
processFakeEndTag(nobrTag);
m_tree.reconstructTheActiveFormattingElements();
}
- m_tree.insertFormattingElement(token);
+ m_tree.insertFormattingElement(WTFMove(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.activeFormattingElements()->appendMarker();
+ m_tree.insertHTMLElement(WTFMove(token));
+ m_tree.activeFormattingElements().appendMarker();
m_framesetOk = false;
return;
}
- if (token->name() == tableTag) {
- if (!m_tree.inQuirksMode() && m_tree.openElements()->inButtonScope(pTag))
+ if (token.name() == tableTag) {
+ if (!m_tree.inQuirksMode() && m_tree.openElements().inButtonScope(pTag))
processFakeEndTag(pTag);
- m_tree.insertHTMLElement(token);
+ m_tree.insertHTMLElement(WTFMove(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(WTFMove(token));
m_framesetOk = false;
return;
}
- if (token->name() == inputTag) {
- Attribute* typeAttribute = token->getAttributeItem(typeAttr);
+ if (token.name() == inputTag) {
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertSelfClosingHTMLElement(token);
- if (!typeAttribute || !equalIgnoringCase(typeAttribute->value(), "hidden"))
+ auto* typeAttribute = findAttribute(token.attributes(), typeAttr);
+ bool shouldClearFramesetOK = !typeAttribute || !equalLettersIgnoringASCIICase(typeAttribute->value(), "hidden");
+ m_tree.insertSelfClosingHTMLElement(WTFMove(token));
+ if (shouldClearFramesetOK)
m_framesetOk = false;
return;
}
- if (token->name() == paramTag
- || token->name() == sourceTag
- || token->name() == trackTag) {
- m_tree.insertSelfClosingHTMLElement(token);
+ if (token.name() == paramTag || token.name() == sourceTag || token.name() == trackTag) {
+ m_tree.insertSelfClosingHTMLElement(WTFMove(token));
return;
}
- if (token->name() == hrTag) {
+ if (token.name() == hrTag) {
processFakePEndTagIfPInButtonScope();
- m_tree.insertSelfClosingHTMLElement(token);
+ m_tree.insertSelfClosingHTMLElement(WTFMove(token));
m_framesetOk = false;
return;
}
- if (token->name() == isindexTag) {
- processIsindexStartTagForInBody(token);
- return;
- }
- if (token->name() == textareaTag) {
- m_tree.insertHTMLElement(token);
+ if (token.name() == textareaTag) {
+ m_tree.insertHTMLElement(WTFMove(token));
m_shouldSkipLeadingNewline = true;
- if (m_parser.tokenizer())
- m_parser.tokenizer()->setState(HTMLTokenizer::RCDATAState);
+ m_parser.tokenizer().setRCDATAState();
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);
+ processGenericRawTextStartTag(WTFMove(token));
return;
}
- if (token->name() == iframeTag) {
+ if (token.name() == iframeTag) {
m_framesetOk = false;
- processGenericRawTextStartTag(token);
+ processGenericRawTextStartTag(WTFMove(token));
return;
}
- if (token->name() == noembedTag && m_options.pluginsEnabled) {
- processGenericRawTextStartTag(token);
+ if (token.name() == noembedTag && m_options.pluginsEnabled) {
+ processGenericRawTextStartTag(WTFMove(token));
return;
}
- if (token->name() == noscriptTag && m_options.scriptEnabled) {
- processGenericRawTextStartTag(token);
+ if (token.name() == noscriptTag && m_options.scriptEnabled) {
+ processGenericRawTextStartTag(WTFMove(token));
return;
}
- if (token->name() == selectTag) {
+ if (token.name() == selectTag) {
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(token);
+ m_tree.insertHTMLElement(WTFMove(token));
m_framesetOk = false;
if (m_insertionMode == InsertionMode::InTable
|| m_insertionMode == InsertionMode::InCaption
@@ -891,576 +806,556 @@ 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 (isHTMLOptionElement(m_tree.currentStackItem()->node())) {
+ if (token.name() == optgroupTag || token.name() == optionTag) {
+ if (is<HTMLOptionElement>(m_tree.currentStackItem().node())) {
AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
- processEndTag(&endOption);
+ processEndTag(WTFMove(endOption));
}
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(token);
+ m_tree.insertHTMLElement(WTFMove(token));
return;
}
- if (token->name() == rpTag || token->name() == rtTag) {
- if (m_tree.openElements()->inScope(rubyTag.localName())) {
+ if (token.name() == rbTag || token.name() == rtcTag) {
+ if (m_tree.openElements().inScope(rubyTag.localName())) {
m_tree.generateImpliedEndTags();
- if (!m_tree.currentStackItem()->hasTagName(rubyTag))
+ if (!m_tree.currentStackItem().hasTagName(rubyTag))
parseError(token);
}
- m_tree.insertHTMLElement(token);
+ m_tree.insertHTMLElement(WTFMove(token));
return;
}
- if (token->name() == MathMLNames::mathTag.localName()) {
+ if (token.name() == rtTag || token.name() == rpTag) {
+ if (m_tree.openElements().inScope(rubyTag.localName())) {
+ m_tree.generateImpliedEndTagsWithExclusion(rtcTag.localName());
+ if (!m_tree.currentStackItem().hasTagName(rubyTag) && !m_tree.currentStackItem().hasTagName(rtcTag))
+ parseError(token);
+ }
+ m_tree.insertHTMLElement(WTFMove(token));
+ return;
+ }
+ if (token.name() == MathMLNames::mathTag.localName()) {
m_tree.reconstructTheActiveFormattingElements();
adjustMathMLAttributes(token);
adjustForeignAttributes(token);
- m_tree.insertForeignElement(token, MathMLNames::mathmlNamespaceURI);
+ m_tree.insertForeignElement(WTFMove(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);
+ m_tree.insertForeignElement(WTFMove(token), SVGNames::svgNamespaceURI);
return;
}
- if (isCaptionColOrColgroupTag(token->name())
- || token->name() == frameTag
- || token->name() == headTag
- || isTableBodyContextTag(token->name())
- || isTableCellContextTag(token->name())
- || token->name() == trTag) {
+ 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) {
- processTemplateStartTag(token);
+ if (token.name() == templateTag) {
+ m_framesetOk = false;
+ processTemplateStartTag(WTFMove(token));
return;
}
-#endif
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(token);
+ insertGenericHTMLElement(WTFMove(token));
}
-#if ENABLE(TEMPLATE_ELEMENT)
-void HTMLTreeBuilder::processTemplateStartTag(AtomicHTMLToken* token)
+inline void HTMLTreeBuilder::insertGenericHTMLElement(AtomicHTMLToken&& token)
{
- m_tree.activeFormattingElements()->appendMarker();
- m_tree.insertHTMLElement(token);
+ m_customElementToConstruct = m_tree.insertHTMLElementOrFindCustomElementInterface(WTFMove(token));
+}
+
+void HTMLTreeBuilder::didCreateCustomOrCallbackElement(Ref<Element>&& element, CustomElementConstructionData& data)
+{
+ m_tree.insertCustomElement(WTFMove(element), data.name, WTFMove(data.attributes));
+}
+
+void HTMLTreeBuilder::processTemplateStartTag(AtomicHTMLToken&& token)
+{
+ m_tree.activeFormattingElements().appendMarker();
+ m_tree.insertHTMLElement(WTFMove(token));
m_templateInsertionModes.append(InsertionMode::TemplateContents);
- setInsertionMode(InsertionMode::TemplateContents);
+ m_insertionMode = InsertionMode::TemplateContents;
}
-bool HTMLTreeBuilder::processTemplateEndTag(AtomicHTMLToken* token)
+bool HTMLTreeBuilder::processTemplateEndTag(AtomicHTMLToken&& token)
{
- ASSERT(token->name() == templateTag.localName());
- if (!m_tree.openElements()->hasTemplateInHTMLScope()) {
- ASSERT(m_templateInsertionModes.isEmpty() || (m_templateInsertionModes.size() == 1 && m_fragmentContext.contextElement()->hasTagName(templateTag)));
+ ASSERT(token.name() == templateTag.localName());
+ if (!m_tree.openElements().hasTemplateInHTMLScope()) {
+ ASSERT(m_templateInsertionModes.isEmpty() || (m_templateInsertionModes.size() == 1 && m_fragmentContext.contextElement().hasTagName(templateTag)));
parseError(token);
return false;
}
m_tree.generateImpliedEndTags();
- if (!m_tree.currentStackItem()->hasTagName(templateTag))
+ if (!m_tree.currentStackItem().hasTagName(templateTag))
parseError(token);
- m_tree.openElements()->popUntilPopped(templateTag);
- m_tree.activeFormattingElements()->clearToLastMarker();
+ m_tree.openElements().popUntilPopped(templateTag);
+ m_tree.activeFormattingElements().clearToLastMarker();
m_templateInsertionModes.removeLast();
resetInsertionModeAppropriately();
return true;
}
-bool HTMLTreeBuilder::processEndOfFileForInTemplateContents(AtomicHTMLToken* token)
+bool HTMLTreeBuilder::processEndOfFileForInTemplateContents(AtomicHTMLToken&& token)
{
AtomicHTMLToken endTemplate(HTMLToken::EndTag, templateTag.localName());
- if (!processTemplateEndTag(&endTemplate))
+ if (!processTemplateEndTag(WTFMove(endTemplate)))
return false;
- processEndOfFile(token);
+ processEndOfFile(WTFMove(token));
return true;
}
-#endif
bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup()
{
- bool ignoreFakeEndTag = m_tree.currentIsRootNode();
-#if ENABLE(TEMPLATE_ELEMENT)
- ignoreFakeEndTag = ignoreFakeEndTag || m_tree.currentNode()->hasTagName(templateTag);
-#endif
+ bool ignoreFakeEndTag = m_tree.currentIsRootNode() || m_tree.currentNode().hasTagName(templateTag);
if (ignoreFakeEndTag) {
ASSERT(isParsingFragmentOrTemplateContents());
// FIXME: parse error
return false;
}
- m_tree.openElements()->pop();
- setInsertionMode(InsertionMode::InTable);
+ m_tree.openElements().pop();
+ m_insertionMode = InsertionMode::InTable;
return true;
}
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#close-the-cell
void HTMLTreeBuilder::closeTheCell()
{
- ASSERT(insertionMode() == InsertionMode::InCell);
- if (m_tree.openElements()->inTableScope(tdTag)) {
- ASSERT(!m_tree.openElements()->inTableScope(thTag));
+ ASSERT(m_insertionMode == InsertionMode::InCell);
+ if (m_tree.openElements().inTableScope(tdTag)) {
+ ASSERT(!m_tree.openElements().inTableScope(thTag));
processFakeEndTag(tdTag);
return;
}
- ASSERT(m_tree.openElements()->inTableScope(thTag));
+ 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) {
- m_tree.openElements()->popUntilTableScopeMarker();
- m_tree.activeFormattingElements()->appendMarker();
- m_tree.insertHTMLElement(token);
- setInsertionMode(InsertionMode::InCaption);
+ ASSERT(token.type() == HTMLToken::StartTag);
+ if (token.name() == captionTag) {
+ m_tree.openElements().popUntilTableScopeMarker();
+ m_tree.activeFormattingElements().appendMarker();
+ m_tree.insertHTMLElement(WTFMove(token));
+ m_insertionMode = InsertionMode::InCaption;
return;
}
- if (token->name() == colgroupTag) {
- m_tree.openElements()->popUntilTableScopeMarker();
- m_tree.insertHTMLElement(token);
- setInsertionMode(InsertionMode::InColumnGroup);
+ if (token.name() == colgroupTag) {
+ m_tree.openElements().popUntilTableScopeMarker();
+ m_tree.insertHTMLElement(WTFMove(token));
+ m_insertionMode = InsertionMode::InColumnGroup;
return;
}
- if (token->name() == colTag) {
+ if (token.name() == colTag) {
processFakeStartTag(colgroupTag);
- ASSERT(insertionMode() == InsertionMode::InColumnGroup);
- processStartTag(token);
+ ASSERT(m_insertionMode == InsertionMode::InColumnGroup);
+ processStartTag(WTFMove(token));
return;
}
- if (isTableBodyContextTag(token->name())) {
- m_tree.openElements()->popUntilTableScopeMarker();
- m_tree.insertHTMLElement(token);
- setInsertionMode(InsertionMode::InTableBody);
+ if (isTableBodyContextTag(token.name())) {
+ m_tree.openElements().popUntilTableScopeMarker();
+ m_tree.insertHTMLElement(WTFMove(token));
+ m_insertionMode = InsertionMode::InTableBody;
return;
}
- if (isTableCellContextTag(token->name())
- || token->name() == trTag) {
+ if (isTableCellContextTag(token.name()) || token.name() == trTag) {
processFakeStartTag(tbodyTag);
- ASSERT(insertionMode() == InsertionMode::InTableBody);
- processStartTag(token);
+ ASSERT(m_insertionMode == InsertionMode::InTableBody);
+ processStartTag(WTFMove(token));
return;
}
- if (token->name() == tableTag) {
+ if (token.name() == tableTag) {
parseError(token);
if (!processTableEndTagForInTable()) {
ASSERT(isParsingFragmentOrTemplateContents());
return;
}
- processStartTag(token);
+ processStartTag(WTFMove(token));
return;
}
- if (token->name() == styleTag || token->name() == scriptTag) {
- processStartTagForInHead(token);
+ if (token.name() == styleTag || token.name() == scriptTag) {
+ processStartTagForInHead(WTFMove(token));
return;
}
- if (token->name() == inputTag) {
- Attribute* typeAttribute = token->getAttributeItem(typeAttr);
- if (typeAttribute && equalIgnoringCase(typeAttribute->value(), "hidden")) {
+ if (token.name() == inputTag) {
+ auto* typeAttribute = findAttribute(token.attributes(), typeAttr);
+ if (typeAttribute && equalLettersIgnoringASCIICase(typeAttribute->value(), "hidden")) {
parseError(token);
- m_tree.insertSelfClosingHTMLElement(token);
+ m_tree.insertSelfClosingHTMLElement(WTFMove(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.openElements()->pop();
+ m_tree.insertHTMLFormElement(WTFMove(token), true);
+ m_tree.openElements().pop();
return;
}
-#if ENABLE(TEMPLATE_ELEMENT)
- if (token->name() == templateTag) {
- processTemplateStartTag(token);
+ if (token.name() == templateTag) {
+ processTemplateStartTag(WTFMove(token));
return;
}
-#endif
parseError(token);
HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
- processStartTagForInBody(token);
+ processStartTagForInBody(WTFMove(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(WTFMove(token));
+ m_insertionMode = InsertionMode::BeforeHead;
return;
}
defaultForBeforeHTML();
+ ASSERT(m_insertionMode == InsertionMode::BeforeHead);
FALLTHROUGH;
case InsertionMode::BeforeHead:
- ASSERT(insertionMode() == InsertionMode::BeforeHead);
- if (token->name() == htmlTag) {
- processHtmlStartTagForInBody(token);
+ if (token.name() == htmlTag) {
+ processHtmlStartTagForInBody(WTFMove(token));
return;
}
- if (token->name() == headTag) {
- m_tree.insertHTMLHeadElement(token);
- setInsertionMode(InsertionMode::InHead);
+ if (token.name() == headTag) {
+ m_tree.insertHTMLHeadElement(WTFMove(token));
+ m_insertionMode = InsertionMode::InHead;
return;
}
defaultForBeforeHead();
+ ASSERT(m_insertionMode == InsertionMode::InHead);
FALLTHROUGH;
case InsertionMode::InHead:
- ASSERT(insertionMode() == InsertionMode::InHead);
- if (processStartTagForInHead(token))
+ if (processStartTagForInHead(WTFMove(token)))
return;
defaultForInHead();
+ ASSERT(m_insertionMode == InsertionMode::AfterHead);
FALLTHROUGH;
case InsertionMode::AfterHead:
- ASSERT(insertionMode() == InsertionMode::AfterHead);
- if (token->name() == htmlTag) {
- processHtmlStartTagForInBody(token);
+ if (token.name() == htmlTag) {
+ processHtmlStartTagForInBody(WTFMove(token));
return;
}
- if (token->name() == bodyTag) {
+ if (token.name() == bodyTag) {
m_framesetOk = false;
- m_tree.insertHTMLBodyElement(token);
- setInsertionMode(InsertionMode::InBody);
+ m_tree.insertHTMLBodyElement(WTFMove(token));
+ m_insertionMode = InsertionMode::InBody;
return;
}
- if (token->name() == framesetTag) {
- m_tree.insertHTMLElement(token);
- setInsertionMode(InsertionMode::InFrameset);
+ if (token.name() == framesetTag) {
+ m_tree.insertHTMLElement(WTFMove(token));
+ m_insertionMode = InsertionMode::InFrameset;
return;
}
- if (token->name() == baseTag
- || token->name() == basefontTag
- || token->name() == bgsoundTag
- || token->name() == linkTag
- || token->name() == metaTag
- || token->name() == noframesTag
- || token->name() == scriptTag
- || token->name() == styleTag
-#if ENABLE(TEMPLATE_ELEMENT)
- || token->name() == templateTag
-#endif
- || token->name() == titleTag) {
+ if (token.name() == baseTag
+ || token.name() == basefontTag
+ || token.name() == bgsoundTag
+ || token.name() == linkTag
+ || token.name() == metaTag
+ || token.name() == noframesTag
+ || token.name() == scriptTag
+ || token.name() == styleTag
+ || token.name() == templateTag
+ || token.name() == titleTag) {
parseError(token);
- ASSERT(m_tree.head());
- m_tree.openElements()->pushHTMLHeadElement(m_tree.headStackItem());
- processStartTagForInHead(token);
- m_tree.openElements()->removeHTMLHeadElement(m_tree.head());
+ ASSERT(m_tree.headStackItem());
+ m_tree.openElements().pushHTMLHeadElement(*m_tree.headStackItem());
+ processStartTagForInHead(WTFMove(token));
+ m_tree.openElements().removeHTMLHeadElement(m_tree.head());
return;
}
- if (token->name() == headTag) {
+ if (token.name() == headTag) {
parseError(token);
return;
}
defaultForAfterHead();
+ ASSERT(m_insertionMode == InsertionMode::InBody);
FALLTHROUGH;
case InsertionMode::InBody:
- ASSERT(insertionMode() == InsertionMode::InBody);
- processStartTagForInBody(token);
+ processStartTagForInBody(WTFMove(token));
break;
case InsertionMode::InTable:
- ASSERT(insertionMode() == InsertionMode::InTable);
- processStartTagForInTable(token);
+ processStartTagForInTable(WTFMove(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());
return;
}
- processStartTag(token);
+ processStartTag(WTFMove(token));
return;
}
- processStartTagForInBody(token);
+ processStartTagForInBody(WTFMove(token));
break;
case InsertionMode::InColumnGroup:
- ASSERT(insertionMode() == InsertionMode::InColumnGroup);
- if (token->name() == htmlTag) {
- processHtmlStartTagForInBody(token);
+ if (token.name() == htmlTag) {
+ processHtmlStartTagForInBody(WTFMove(token));
return;
}
- if (token->name() == colTag) {
- m_tree.insertSelfClosingHTMLElement(token);
+ if (token.name() == colTag) {
+ m_tree.insertSelfClosingHTMLElement(WTFMove(token));
return;
}
-#if ENABLE(TEMPLATE_ELEMENT)
- if (token->name() == templateTag) {
- processTemplateStartTag(token);
+ if (token.name() == templateTag) {
+ processTemplateStartTag(WTFMove(token));
return;
}
-#endif
if (!processColgroupEndTagForInColumnGroup()) {
ASSERT(isParsingFragmentOrTemplateContents());
return;
}
- processStartTag(token);
+ processStartTag(WTFMove(token));
break;
case InsertionMode::InTableBody:
- ASSERT(insertionMode() == InsertionMode::InTableBody);
- if (token->name() == trTag) {
- m_tree.openElements()->popUntilTableBodyScopeMarker(); // How is there ever anything to pop?
- m_tree.insertHTMLElement(token);
- setInsertionMode(InsertionMode::InRow);
+ if (token.name() == trTag) {
+ m_tree.openElements().popUntilTableBodyScopeMarker(); // How is there ever anything to pop?
+ m_tree.insertHTMLElement(WTFMove(token));
+ m_insertionMode = InsertionMode::InRow;
return;
}
- if (isTableCellContextTag(token->name())) {
+ if (isTableCellContextTag(token.name())) {
parseError(token);
processFakeStartTag(trTag);
- ASSERT(insertionMode() == InsertionMode::InRow);
- processStartTag(token);
+ ASSERT(m_insertionMode == InsertionMode::InRow);
+ processStartTag(WTFMove(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)) {
+ if (!m_tree.openElements().inTableScope(tbodyTag) && !m_tree.openElements().inTableScope(theadTag) && !m_tree.openElements().inTableScope(tfootTag)) {
ASSERT(isParsingFragmentOrTemplateContents());
parseError(token);
return;
}
- m_tree.openElements()->popUntilTableBodyScopeMarker();
- ASSERT(isTableBodyContextTag(m_tree.currentStackItem()->localName()));
- processFakeEndTag(m_tree.currentStackItem()->localName());
- processStartTag(token);
+ m_tree.openElements().popUntilTableBodyScopeMarker();
+ ASSERT(isTableBodyContextTag(m_tree.currentStackItem().localName()));
+ processFakeEndTag(m_tree.currentStackItem().localName());
+ processStartTag(WTFMove(token));
return;
}
- processStartTagForInTable(token);
+ processStartTagForInTable(WTFMove(token));
break;
case InsertionMode::InRow:
- ASSERT(insertionMode() == InsertionMode::InRow);
- if (isTableCellContextTag(token->name())) {
- m_tree.openElements()->popUntilTableRowScopeMarker();
- m_tree.insertHTMLElement(token);
- setInsertionMode(InsertionMode::InCell);
- m_tree.activeFormattingElements()->appendMarker();
+ if (isTableCellContextTag(token.name())) {
+ m_tree.openElements().popUntilTableRowScopeMarker();
+ m_tree.insertHTMLElement(WTFMove(token));
+ m_insertionMode = InsertionMode::InCell;
+ m_tree.activeFormattingElements().appendMarker();
return;
}
- if (token->name() == trTag
- || isCaptionColOrColgroupTag(token->name())
- || isTableBodyContextTag(token->name())) {
+ if (token.name() == trTag
+ || isCaptionColOrColgroupTag(token.name())
+ || isTableBodyContextTag(token.name())) {
if (!processTrEndTagForInRow()) {
ASSERT(isParsingFragmentOrTemplateContents());
return;
}
- ASSERT(insertionMode() == InsertionMode::InTableBody);
- processStartTag(token);
+ ASSERT(m_insertionMode == InsertionMode::InTableBody);
+ processStartTag(WTFMove(token));
return;
}
- processStartTagForInTable(token);
+ processStartTagForInTable(WTFMove(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)) {
+ if (!m_tree.openElements().inTableScope(tdTag) && !m_tree.openElements().inTableScope(thTag)) {
ASSERT(isParsingFragment());
parseError(token);
return;
}
closeTheCell();
- processStartTag(token);
+ processStartTag(WTFMove(token));
return;
}
- processStartTagForInBody(token);
+ processStartTagForInBody(WTFMove(token));
break;
case InsertionMode::AfterBody:
case InsertionMode::AfterAfterBody:
- ASSERT(insertionMode() == InsertionMode::AfterBody || insertionMode() == InsertionMode::AfterAfterBody);
- if (token->name() == htmlTag) {
- processHtmlStartTagForInBody(token);
+ if (token.name() == htmlTag) {
+ processHtmlStartTagForInBody(WTFMove(token));
return;
}
- setInsertionMode(InsertionMode::InBody);
- processStartTag(token);
+ m_insertionMode = InsertionMode::InBody;
+ processStartTag(WTFMove(token));
break;
case InsertionMode::InHeadNoscript:
- ASSERT(insertionMode() == InsertionMode::InHeadNoscript);
- if (token->name() == htmlTag) {
- processHtmlStartTagForInBody(token);
- return;
- }
- if (token->name() == basefontTag
- || token->name() == bgsoundTag
- || token->name() == linkTag
- || token->name() == metaTag
- || token->name() == noframesTag
- || token->name() == styleTag) {
- bool didProcess = processStartTagForInHead(token);
+ if (token.name() == htmlTag) {
+ processHtmlStartTagForInBody(WTFMove(token));
+ return;
+ }
+ if (token.name() == basefontTag
+ || token.name() == bgsoundTag
+ || token.name() == linkTag
+ || token.name() == metaTag
+ || token.name() == noframesTag
+ || token.name() == styleTag) {
+ bool didProcess = processStartTagForInHead(WTFMove(token));
ASSERT_UNUSED(didProcess, didProcess);
return;
}
- if (token->name() == htmlTag || token->name() == noscriptTag) {
+ if (token.name() == htmlTag || token.name() == noscriptTag) {
parseError(token);
return;
}
defaultForInHeadNoscript();
- processToken(token);
+ processToken(WTFMove(token));
break;
case InsertionMode::InFrameset:
- ASSERT(insertionMode() == InsertionMode::InFrameset);
- if (token->name() == htmlTag) {
- processHtmlStartTagForInBody(token);
- return;
- }
- if (token->name() == framesetTag) {
- m_tree.insertHTMLElement(token);
+ if (token.name() == htmlTag) {
+ processHtmlStartTagForInBody(WTFMove(token));
return;
}
- if (token->name() == frameTag) {
- m_tree.insertSelfClosingHTMLElement(token);
+ if (token.name() == framesetTag) {
+ m_tree.insertHTMLElement(WTFMove(token));
return;
}
- if (token->name() == noframesTag) {
- processStartTagForInHead(token);
+ if (token.name() == frameTag) {
+ m_tree.insertSelfClosingHTMLElement(WTFMove(token));
return;
}
-#if ENABLE(TEMPLATE_ELEMENT)
- if (token->name() == templateTag) {
- processTemplateStartTag(token);
+ if (token.name() == noframesTag) {
+ processStartTagForInHead(WTFMove(token));
return;
}
-#endif
parseError(token);
break;
case InsertionMode::AfterFrameset:
case InsertionMode::AfterAfterFrameset:
- ASSERT(insertionMode() == InsertionMode::AfterFrameset || insertionMode() == InsertionMode::AfterAfterFrameset);
- if (token->name() == htmlTag) {
- processHtmlStartTagForInBody(token);
+ if (token.name() == htmlTag) {
+ processHtmlStartTagForInBody(WTFMove(token));
return;
}
- if (token->name() == noframesTag) {
- processStartTagForInHead(token);
+ if (token.name() == noframesTag) {
+ processStartTagForInHead(WTFMove(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);
- processStartTag(token);
+ processEndTag(WTFMove(endSelect));
+ processStartTag(WTFMove(token));
return;
}
FALLTHROUGH;
case InsertionMode::InSelect:
- ASSERT(insertionMode() == InsertionMode::InSelect || insertionMode() == InsertionMode::InSelectInTable);
- if (token->name() == htmlTag) {
- processHtmlStartTagForInBody(token);
+ if (token.name() == htmlTag) {
+ processHtmlStartTagForInBody(WTFMove(token));
return;
}
- if (token->name() == optionTag) {
- if (isHTMLOptionElement(m_tree.currentStackItem()->node())) {
+ if (token.name() == optionTag) {
+ if (is<HTMLOptionElement>(m_tree.currentStackItem().node())) {
AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
- processEndTag(&endOption);
+ processEndTag(WTFMove(endOption));
}
- m_tree.insertHTMLElement(token);
+ m_tree.insertHTMLElement(WTFMove(token));
return;
}
- if (token->name() == optgroupTag) {
- if (isHTMLOptionElement(m_tree.currentStackItem()->node())) {
+ if (token.name() == optgroupTag) {
+ if (is<HTMLOptionElement>(m_tree.currentStackItem().node())) {
AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
- processEndTag(&endOption);
+ processEndTag(WTFMove(endOption));
}
- if (isHTMLOptGroupElement(m_tree.currentStackItem()->node())) {
+ if (is<HTMLOptGroupElement>(m_tree.currentStackItem().node())) {
AtomicHTMLToken endOptgroup(HTMLToken::EndTag, optgroupTag.localName());
- processEndTag(&endOptgroup);
+ processEndTag(WTFMove(endOptgroup));
}
- m_tree.insertHTMLElement(token);
+ m_tree.insertHTMLElement(WTFMove(token));
return;
}
- if (token->name() == selectTag) {
+ if (token.name() == selectTag) {
parseError(token);
AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
- processEndTag(&endSelect);
+ processEndTag(WTFMove(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)) {
+ if (!m_tree.openElements().inSelectScope(selectTag)) {
ASSERT(isParsingFragment());
return;
}
AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
- processEndTag(&endSelect);
- processStartTag(token);
+ processEndTag(WTFMove(endSelect));
+ processStartTag(WTFMove(token));
return;
}
- if (token->name() == scriptTag) {
- bool didProcess = processStartTagForInHead(token);
+ if (token.name() == scriptTag) {
+ bool didProcess = processStartTagForInHead(WTFMove(token));
ASSERT_UNUSED(didProcess, didProcess);
return;
}
-#if ENABLE(TEMPLATE_ELEMENT)
- if (token->name() == templateTag) {
- processTemplateStartTag(token);
+ if (token.name() == templateTag) {
+ processTemplateStartTag(WTFMove(token));
return;
}
-#endif
break;
case InsertionMode::InTableText:
defaultForInTableText();
- processStartTag(token);
+ processStartTag(WTFMove(token));
break;
case InsertionMode::Text:
ASSERT_NOT_REACHED();
break;
case InsertionMode::TemplateContents:
-#if ENABLE(TEMPLATE_ELEMENT)
- if (token->name() == templateTag) {
- processTemplateStartTag(token);
+ if (token.name() == templateTag) {
+ processTemplateStartTag(WTFMove(token));
return;
}
- if (token->name() == linkTag
- || token->name() == scriptTag
- || token->name() == styleTag
- || token->name() == metaTag) {
- processStartTagForInHead(token);
+ if (token.name() == linkTag
+ || token.name() == scriptTag
+ || token.name() == styleTag
+ || token.name() == metaTag) {
+ processStartTagForInHead(WTFMove(token));
return;
}
InsertionMode insertionMode = InsertionMode::TemplateContents;
- if (token->name() == frameTag)
- insertionMode = InsertionMode::InFrameset;
- else if (token->name() == colTag)
+ 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;
@@ -1468,64 +1363,57 @@ 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
+ processStartTag(WTFMove(token));
break;
}
}
-void HTMLTreeBuilder::processHtmlStartTagForInBody(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processHtmlStartTagForInBody(AtomicHTMLToken&& token)
{
parseError(token);
-#if ENABLE(TEMPLATE_ELEMENT)
- if (m_tree.openElements()->hasTemplateInHTMLScope()) {
+ if (m_tree.openElements().hasTemplateInHTMLScope()) {
ASSERT(isParsingTemplateContents());
return;
}
-#endif
- m_tree.insertHTMLHtmlStartTagInBody(token);
+ m_tree.insertHTMLHtmlStartTagInBody(WTFMove(token));
}
-bool HTMLTreeBuilder::processBodyEndTagForInBody(AtomicHTMLToken* token)
+bool HTMLTreeBuilder::processBodyEndTagForInBody(AtomicHTMLToken&& token)
{
- ASSERT(token->type() == HTMLToken::EndTag);
- ASSERT(token->name() == bodyTag);
- if (!m_tree.openElements()->inScope(bodyTag.localName())) {
+ 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 (isSpecialNode(item)) {
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
@@ -1537,43 +1425,43 @@ 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);
+ return processAnyOtherEndTagForInBody(WTFMove(token));
// 4.c
- if ((m_tree.openElements()->contains(formattingElement)) && !m_tree.openElements()->inScope(formattingElement)) {
+ if ((m_tree.openElements().contains(*formattingElement)) && !m_tree.openElements().inScope(*formattingElement)) {
parseError(token);
notImplemented(); // Check the stack of open elements for a more specific parse error.
return;
}
// 4.b
- HTMLElementStack::ElementRecord* formattingElementRecord = m_tree.openElements()->find(formattingElement);
+ auto* formattingElementRecord = m_tree.openElements().find(*formattingElement);
if (!formattingElementRecord) {
parseError(token);
- m_tree.activeFormattingElements()->remove(formattingElement);
+ m_tree.activeFormattingElements().remove(*formattingElement);
return;
}
// 4.d
- if (formattingElement != m_tree.currentElement())
+ 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);
- m_tree.activeFormattingElements()->remove(formattingElement);
+ m_tree.openElements().popUntilPopped(*formattingElement);
+ m_tree.activeFormattingElements().remove(*formattingElement);
return;
}
// 7.
- ASSERT(furthestBlock->isAbove(formattingElementRecord));
- RefPtr<HTMLStackItem> commonAncestor = formattingElementRecord->next()->stackItem();
+ ASSERT(furthestBlock->isAbove(*formattingElementRecord));
+ Ref<HTMLStackItem> commonAncestor = formattingElementRecord->next()->stackItem();
// 8.
- HTMLFormattingElementList::Bookmark bookmark = m_tree.activeFormattingElements()->bookmarkFor(formattingElement);
+ 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
@@ -1581,8 +1469,8 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token)
ASSERT(node);
nextNode = node->next(); // Save node->next() for the next iteration in case node is deleted in 9.5.
// 9.5
- if (!m_tree.activeFormattingElements()->contains(node->element())) {
- m_tree.openElements()->remove(node->element());
+ if (!m_tree.activeFormattingElements().contains(node->element())) {
+ m_tree.openElements().remove(node->element());
node = 0;
continue;
}
@@ -1590,33 +1478,31 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token)
if (node == formattingElementRecord)
break;
// 9.7
- RefPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(node->stackItem().get());
+ auto newItem = m_tree.createElementFromSavedToken(node->stackItem());
- HTMLFormattingElementList::Entry* nodeEntry = m_tree.activeFormattingElements()->find(node->element());
- nodeEntry->replaceElement(newItem);
- node->replaceElement(newItem.release());
+ HTMLFormattingElementList::Entry* nodeEntry = m_tree.activeFormattingElements().find(node->element());
+ nodeEntry->replaceElement(newItem.copyRef());
+ node->replaceElement(WTFMove(newItem));
// 9.8
if (lastNode == furthestBlock)
- bookmark.moveToAfter(nodeEntry);
+ bookmark.moveToAfter(*nodeEntry);
// 9.9
m_tree.reparent(*node, *lastNode);
// 9.10
lastNode = node;
}
// 10.
- m_tree.insertAlreadyParsedChild(*commonAncestor, *lastNode);
+ m_tree.insertAlreadyParsedChild(commonAncestor.get(), *lastNode);
// 11.
- RefPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(formattingElementRecord->stackItem().get());
- // 12.
- m_tree.takeAllChildren(*newItem, *furthestBlock);
- // 13.
- m_tree.reparent(*furthestBlock, *newItem);
+ auto newItem = m_tree.createElementFromSavedToken(formattingElementRecord->stackItem());
+ // 12. & 13.
+ m_tree.takeAllChildrenAndReparent(newItem, *furthestBlock);
// 14.
- m_tree.activeFormattingElements()->swapTo(formattingElement, newItem, bookmark);
+ m_tree.activeFormattingElements().swapTo(*formattingElement, newItem.copyRef(), bookmark);
// 15.
- m_tree.openElements()->remove(formattingElement);
- m_tree.openElements()->insertAbove(newItem, furthestBlock);
+ m_tree.openElements().remove(*formattingElement);
+ m_tree.openElements().insertAbove(WTFMove(newItem), *furthestBlock);
}
}
@@ -1624,719 +1510,691 @@ 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();
- if (item->node() == m_tree.openElements()->rootNode()) {
+ for (auto* record = &m_tree.openElements().topRecord(); ; record = record->next()) {
+ HTMLStackItem* item = &record->stackItem();
+ if (&item->node() == &m_tree.openElements().rootNode()) {
last = true;
-#if ENABLE(TEMPLATE_ELEMENT)
bool shouldCreateItem = isParsingFragment();
-#else
- ASSERT(isParsingFragment());
- bool shouldCreateItem = true;
-#endif
if (shouldCreateItem)
- item = HTMLStackItem::create(m_fragmentContext.contextElement(), HTMLStackItem::ItemForContextElement);
+ item = &m_fragmentContext.contextElementStackItem();
}
-#if ENABLE(TEMPLATE_ELEMENT)
- if (item->hasTagName(templateTag))
- return setInsertionMode(m_templateInsertionModes.last());
-#endif
+
+ if (item->hasTagName(templateTag)) {
+ m_insertionMode = m_templateInsertionModes.last();
+ return;
+ }
+
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 (isHTMLTableElement(item->node()))
- return setInsertionMode(InsertionMode::InSelectInTable);
+ while (&item->node() != &m_tree.openElements().rootNode() && !item->hasTagName(templateTag)) {
+ record = record->next();
+ item = &record->stackItem();
+ if (is<HTMLTableElement>(item->node())) {
+ m_insertionMode = InsertionMode::InSelectInTable;
+ return;
+ }
}
}
-#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 (isHTMLTableElement(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);
-#endif
- return setInsertionMode(InsertionMode::InBody);
+ if (!m_fragmentContext.fragment() || &m_fragmentContext.contextElement() != &item->node()) {
+ m_insertionMode = InsertionMode::InHead;
+ return;
+ }
+ m_insertionMode = InsertionMode::InBody;
+ return;
+ }
+ if (item->hasTagName(bodyTag)) {
+ m_insertionMode = InsertionMode::InBody;
+ return;
}
- if (item->hasTagName(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_tree.openElements().popUntilTableBodyScopeMarker();
+ m_tree.openElements().pop();
+ 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)) {
+ if (!m_tree.openElements().inTableScope(tbodyTag) && !m_tree.openElements().inTableScope(theadTag) && !m_tree.openElements().inTableScope(tfootTag)) {
ASSERT(isParsingFragmentOrTemplateContents());
parseError(token);
return;
}
- m_tree.openElements()->popUntilTableBodyScopeMarker();
- ASSERT(isTableBodyContextTag(m_tree.currentStackItem()->localName()));
- processFakeEndTag(m_tree.currentStackItem()->localName());
- processEndTag(token);
+ m_tree.openElements().popUntilTableBodyScopeMarker();
+ ASSERT(isTableBodyContextTag(m_tree.currentStackItem().localName()));
+ processFakeEndTag(m_tree.currentStackItem().localName());
+ processEndTag(WTFMove(token));
return;
}
- if (token->name() == bodyTag
- || isCaptionColOrColgroupTag(token->name())
- || token->name() == htmlTag
- || isTableCellContextTag(token->name())
- || token->name() == trTag) {
+ if (token.name() == bodyTag
+ || isCaptionColOrColgroupTag(token.name())
+ || token.name() == htmlTag
+ || isTableCellContextTag(token.name())
+ || token.name() == trTag) {
parseError(token);
return;
}
- processEndTagForInTable(token);
+ processEndTagForInTable(WTFMove(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);
- processEndTag(token);
+ ASSERT(m_insertionMode == InsertionMode::InTableBody);
+ processEndTag(WTFMove(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);
- processEndTag(token);
+ ASSERT(m_insertionMode == InsertionMode::InTableBody);
+ processEndTag(WTFMove(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);
+ processEndTagForInTable(WTFMove(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.activeFormattingElements()->clearToLastMarker();
- setInsertionMode(InsertionMode::InRow);
+ m_tree.openElements().popUntilPopped(token.name());
+ m_tree.activeFormattingElements().clearToLastMarker();
+ m_insertionMode = InsertionMode::InRow;
return;
}
- if (token->name() == bodyTag
- || isCaptionColOrColgroupTag(token->name())
- || token->name() == htmlTag) {
+ 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 ENABLE(TEMPLATE_ELEMENT)
- ASSERT(isTableBodyContextTag(token->name()) || m_tree.openElements()->inTableScope(templateTag) || isParsingFragment());
-#else
- ASSERT(isTableBodyContextTag(token->name()) || isParsingFragment());
-#endif
+ if (token.name() == tableTag
+ || token.name() == trTag
+ || isTableBodyContextTag(token.name())) {
+ if (!m_tree.openElements().inTableScope(token.name())) {
+ ASSERT(isTableBodyContextTag(token.name()) || m_tree.openElements().inTableScope(templateTag) || isParsingFragment());
parseError(token);
return;
}
closeTheCell();
- processEndTag(token);
+ processEndTag(WTFMove(token));
return;
}
- processEndTagForInBody(token);
+ processEndTagForInBody(WTFMove(token));
}
-void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
+void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken&& token)
{
- ASSERT(token->type() == HTMLToken::EndTag);
- if (token->name() == bodyTag) {
- processBodyEndTagForInBody(token);
+ ASSERT(token.type() == HTMLToken::EndTag);
+ if (token.name() == bodyTag) {
+ processBodyEndTagForInBody(WTFMove(token));
return;
}
- if (token->name() == htmlTag) {
+ if (token.name() == htmlTag) {
AtomicHTMLToken endBody(HTMLToken::EndTag, bodyTag.localName());
- if (processBodyEndTagForInBody(&endBody))
- processEndTag(token);
- return;
- }
- if (token->name() == addressTag
- || token->name() == articleTag
- || token->name() == asideTag
- || token->name() == blockquoteTag
- || token->name() == buttonTag
- || token->name() == centerTag
- || token->name() == detailsTag
- || token->name() == dirTag
- || token->name() == divTag
- || token->name() == dlTag
- || token->name() == fieldsetTag
- || token->name() == figcaptionTag
- || token->name() == figureTag
- || token->name() == footerTag
- || token->name() == headerTag
- || token->name() == hgroupTag
- || token->name() == listingTag
- || token->name() == mainTag
- || token->name() == menuTag
- || token->name() == navTag
- || token->name() == olTag
- || token->name() == preTag
- || token->name() == sectionTag
- || token->name() == summaryTag
- || token->name() == ulTag) {
- if (!m_tree.openElements()->inScope(token->name())) {
+ if (processBodyEndTagForInBody(WTFMove(endBody)))
+ processEndTag(WTFMove(token));
+ return;
+ }
+ if (token.name() == addressTag
+ || token.name() == articleTag
+ || token.name() == asideTag
+ || token.name() == blockquoteTag
+ || token.name() == buttonTag
+ || token.name() == centerTag
+ || token.name() == detailsTag
+ || token.name() == dirTag
+ || token.name() == divTag
+ || token.name() == dlTag
+ || token.name() == fieldsetTag
+ || token.name() == figcaptionTag
+ || token.name() == figureTag
+ || token.name() == footerTag
+ || token.name() == headerTag
+ || token.name() == hgroupTag
+ || token.name() == listingTag
+ || token.name() == mainTag
+ || token.name() == menuTag
+ || token.name() == navTag
+ || token.name() == olTag
+ || token.name() == preTag
+ || token.name() == sectionTag
+ || token.name() == summaryTag
+ || token.name() == ulTag) {
+ if (!m_tree.openElements().inScope(token.name())) {
parseError(token);
return;
}
m_tree.generateImpliedEndTags();
- if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
+ 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())) {
+ RefPtr<Element> formElement = m_tree.takeForm();
+ if (!formElement || !m_tree.openElements().inScope(*formElement)) {
parseError(token);
return;
}
m_tree.generateImpliedEndTags();
- if (m_tree.currentNode() != node.get())
+ if (&m_tree.currentNode() != formElement.get())
parseError(token);
- m_tree.openElements()->remove(node.get());
+ m_tree.openElements().remove(*formElement);
} 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))
+ 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()));
- processEndTag(token);
+ ASSERT(m_tree.openElements().inScope(token.name()));
+ processEndTag(WTFMove(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 (!m_tree.openElements()->hasNumberedHeaderElementInScope()) {
+ 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();
+ m_tree.openElements().popUntilNumberedHeaderElementPopped();
return;
}
- if (isFormattingTag(token->name())) {
+ if (HTMLConstructionSite::isFormattingTag(token.name())) {
callTheAdoptionAgency(token);
return;
}
- if (token->name() == appletTag
- || token->name() == marqueeTag
- || token->name() == objectTag) {
- if (!m_tree.openElements()->inScope(token->name())) {
+ 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.activeFormattingElements()->clearToLastMarker();
+ 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) {
- processTemplateEndTag(token);
+ if (token.name() == templateTag) {
+ processTemplateEndTag(WTFMove(token));
return;
}
-#endif
- processAnyOtherEndTagForInBody(token);
+ processAnyOtherEndTagForInBody(WTFMove(token));
}
bool HTMLTreeBuilder::processCaptionEndTagForInCaption()
{
- if (!m_tree.openElements()->inTableScope(captionTag.localName())) {
+ if (!m_tree.openElements().inTableScope(captionTag.localName())) {
ASSERT(isParsingFragment());
// FIXME: parse error
return false;
}
m_tree.generateImpliedEndTags();
- // FIXME: parse error if (!m_tree.currentStackItem()->hasTagName(captionTag))
- m_tree.openElements()->popUntilPopped(captionTag.localName());
- m_tree.activeFormattingElements()->clearToLastMarker();
- setInsertionMode(InsertionMode::InTable);
+ // FIXME: parse error if (!m_tree.currentStackItem().hasTagName(captionTag))
+ m_tree.openElements().popUntilPopped(captionTag.localName());
+ m_tree.activeFormattingElements().clearToLastMarker();
+ m_insertionMode = InsertionMode::InTable;
return true;
}
bool HTMLTreeBuilder::processTrEndTagForInRow()
{
- if (!m_tree.openElements()->inTableScope(trTag)) {
+ if (!m_tree.openElements().inTableScope(trTag)) {
ASSERT(isParsingFragmentOrTemplateContents());
// FIXME: parse error
return false;
}
- m_tree.openElements()->popUntilTableRowScopeMarker();
- ASSERT(m_tree.currentStackItem()->hasTagName(trTag));
- m_tree.openElements()->pop();
- setInsertionMode(InsertionMode::InTableBody);
+ m_tree.openElements().popUntilTableRowScopeMarker();
+ ASSERT(m_tree.currentStackItem().hasTagName(trTag));
+ m_tree.openElements().pop();
+ m_insertionMode = InsertionMode::InTableBody;
return true;
}
bool HTMLTreeBuilder::processTableEndTagForInTable()
{
- if (!m_tree.openElements()->inTableScope(tableTag)) {
+ if (!m_tree.openElements().inTableScope(tableTag)) {
ASSERT(isParsingFragmentOrTemplateContents());
// FIXME: parse error.
return false;
}
- m_tree.openElements()->popUntilPopped(tableTag.localName());
+ m_tree.openElements().popUntilPopped(tableTag.localName());
resetInsertionModeAppropriately();
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;
}
parseError(token);
// Is this redirection necessary here?
HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
- processEndTagForInBody(token);
+ processEndTagForInBody(WTFMove(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);
defaultForInitial();
+ ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
FALLTHROUGH;
case InsertionMode::BeforeHTML:
- ASSERT(insertionMode() == InsertionMode::BeforeHTML);
- 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;
}
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) {
- processTemplateEndTag(token);
+ if (token.name() == templateTag) {
+ processTemplateEndTag(WTFMove(token));
return;
}
-#endif
- if (token->name() == headTag) {
- m_tree.openElements()->popHTMLHeadElement();
- setInsertionMode(InsertionMode::AfterHead);
+ if (token.name() == headTag) {
+ m_tree.openElements().popHTMLHeadElement();
+ 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);
+ processEndTagForInBody(WTFMove(token));
break;
case InsertionMode::InTable:
- ASSERT(insertionMode() == InsertionMode::InTable);
- processEndTagForInTable(token);
+ processEndTagForInTable(WTFMove(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());
return;
}
- processEndTag(token);
+ processEndTag(WTFMove(token));
return;
}
- if (token->name() == bodyTag
- || token->name() == colTag
- || token->name() == colgroupTag
- || token->name() == htmlTag
- || isTableBodyContextTag(token->name())
- || isTableCellContextTag(token->name())
- || token->name() == trTag) {
+ 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);
+ processEndTagForInBody(WTFMove(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) {
- processTemplateEndTag(token);
+ if (token.name() == templateTag) {
+ processTemplateEndTag(WTFMove(token));
return;
}
-#endif
if (!processColgroupEndTagForInColumnGroup()) {
ASSERT(isParsingFragmentOrTemplateContents());
return;
}
- processEndTag(token);
+ processEndTag(WTFMove(token));
break;
case InsertionMode::InRow:
- ASSERT(insertionMode() == InsertionMode::InRow);
- processEndTagForInRow(token);
+ processEndTagForInRow(WTFMove(token));
break;
case InsertionMode::InCell:
- ASSERT(insertionMode() == InsertionMode::InCell);
- processEndTagForInCell(token);
+ processEndTagForInCell(WTFMove(token));
break;
case InsertionMode::InTableBody:
- ASSERT(insertionMode() == InsertionMode::InTableBody);
- processEndTagForInTableBody(token);
+ processEndTagForInTableBody(WTFMove(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);
- processEndTag(token);
+ m_insertionMode = InsertionMode::InBody;
+ processEndTag(WTFMove(token));
break;
case InsertionMode::InHeadNoscript:
- ASSERT(insertionMode() == InsertionMode::InHeadNoscript);
- if (token->name() == noscriptTag) {
- ASSERT(m_tree.currentStackItem()->hasTagName(noscriptTag));
- m_tree.openElements()->pop();
- ASSERT(m_tree.currentStackItem()->hasTagName(headTag));
- setInsertionMode(InsertionMode::InHead);
+ if (token.name() == noscriptTag) {
+ ASSERT(m_tree.currentStackItem().hasTagName(noscriptTag));
+ m_tree.openElements().pop();
+ ASSERT(m_tree.currentStackItem().hasTagName(headTag));
+ m_insertionMode = InsertionMode::InHead;
return;
}
- if (token->name() != brTag) {
+ if (token.name() != brTag) {
parseError(token);
return;
}
defaultForInHeadNoscript();
- processToken(token);
+ processToken(WTFMove(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));
+ ASSERT(m_tree.currentStackItem().hasTagName(scriptTag));
if (scriptingContentIsAllowed(m_tree.parserContentPolicy()))
- m_scriptToProcess = m_tree.currentElement();
- m_tree.openElements()->pop();
- setInsertionMode(m_originalInsertionMode);
-
- if (m_parser.tokenizer()) {
- // This token will not have been created by the tokenizer if a
- // self-closing script tag was encountered and pre-HTML5 parser
- // quirks are enabled. We must set the tokenizer's state to
- // DataState explicitly if the tokenizer didn't have a chance to.
- ASSERT(m_parser.tokenizer()->state() == HTMLTokenizer::DataState || m_options.usePreHTML5ParserQuirks);
- m_parser.tokenizer()->setState(HTMLTokenizer::DataState);
- }
+ m_scriptToProcess = &downcast<HTMLScriptElement>(m_tree.currentElement());
+ m_tree.openElements().pop();
+ m_insertionMode = m_originalInsertionMode;
+
+ // This token will not have been created by the tokenizer if a
+ // self-closing script tag was encountered and pre-HTML5 parser
+ // quirks are enabled. We must set the tokenizer's state to
+ // DataState explicitly if the tokenizer didn't have a chance to.
+ ASSERT(m_parser.tokenizer().isInDataState() || m_options.usePreHTML5ParserQuirks);
+ m_parser.tokenizer().setDataState();
return;
}
- m_tree.openElements()->pop();
- setInsertionMode(m_originalInsertionMode);
+ m_tree.openElements().pop();
+ m_insertionMode = m_originalInsertionMode;
break;
case InsertionMode::InFrameset:
- ASSERT(insertionMode() == InsertionMode::InFrameset);
- if (token->name() == framesetTag) {
- bool ignoreFramesetForFragmentParsing = m_tree.currentIsRootNode();
-#if ENABLE(TEMPLATE_ELEMENT)
- ignoreFramesetForFragmentParsing = ignoreFramesetForFragmentParsing || m_tree.openElements()->hasTemplateInHTMLScope();
-#endif
+ if (token.name() == framesetTag) {
+ bool ignoreFramesetForFragmentParsing = m_tree.currentIsRootNode() || m_tree.openElements().hasTemplateInHTMLScope();
if (ignoreFramesetForFragmentParsing) {
ASSERT(isParsingFragmentOrTemplateContents());
parseError(token);
return;
}
- m_tree.openElements()->pop();
- if (!isParsingFragment() && !m_tree.currentStackItem()->hasTagName(framesetTag))
- setInsertionMode(InsertionMode::AfterFrameset);
- return;
- }
-#if ENABLE(TEMPLATE_ELEMENT)
- if (token->name() == templateTag) {
- processTemplateEndTag(token);
+ m_tree.openElements().pop();
+ if (!isParsingFragment() && !m_tree.currentStackItem().hasTagName(framesetTag))
+ m_insertionMode = InsertionMode::AfterFrameset;
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(token);
+ processEndTag(WTFMove(endSelect));
+ processEndTag(WTFMove(token));
}
return;
}
FALLTHROUGH;
case InsertionMode::InSelect:
- ASSERT(insertionMode() == InsertionMode::InSelect || insertionMode() == InsertionMode::InSelectInTable);
- if (token->name() == optgroupTag) {
- if (isHTMLOptionElement(m_tree.currentStackItem()->node()) && m_tree.oneBelowTop() && isHTMLOptGroupElement(m_tree.oneBelowTop()->node()))
+ 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 (isHTMLOptGroupElement(m_tree.currentStackItem()->node())) {
- m_tree.openElements()->pop();
+ if (is<HTMLOptGroupElement>(m_tree.currentStackItem().node())) {
+ m_tree.openElements().pop();
return;
}
parseError(token);
return;
}
- if (token->name() == optionTag) {
- if (isHTMLOptionElement(m_tree.currentStackItem()->node())) {
- m_tree.openElements()->pop();
+ if (token.name() == optionTag) {
+ if (is<HTMLOptionElement>(m_tree.currentStackItem().node())) {
+ m_tree.openElements().pop();
return;
}
parseError(token);
return;
}
- if (token->name() == selectTag) {
- if (!m_tree.openElements()->inSelectScope(token->name())) {
+ if (token.name() == selectTag) {
+ if (!m_tree.openElements().inSelectScope(token.name())) {
ASSERT(isParsingFragment());
parseError(token);
return;
}
- m_tree.openElements()->popUntilPopped(selectTag.localName());
+ m_tree.openElements().popUntilPopped(selectTag.localName());
resetInsertionModeAppropriately();
return;
}
-#if ENABLE(TEMPLATE_ELEMENT)
- if (token->name() == templateTag) {
- processTemplateEndTag(token);
+ if (token.name() == templateTag) {
+ processTemplateEndTag(WTFMove(token));
return;
}
-#endif
break;
case InsertionMode::InTableText:
defaultForInTableText();
- processEndTag(token);
+ processEndTag(WTFMove(token));
break;
case InsertionMode::TemplateContents:
-#if ENABLE(TEMPLATE_ELEMENT)
- if (token->name() == templateTag) {
- processTemplateEndTag(token);
+ if (token.name() == templateTag) {
+ processTemplateEndTag(WTFMove(token));
return;
}
-
- break;
-#else
- ASSERT_NOT_REACHED();
-#endif
break;
}
}
-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(WTFMove(token));
return;
}
if (m_insertionMode == InsertionMode::AfterBody) {
- m_tree.insertCommentOnHTMLHtmlElement(token);
+ m_tree.insertCommentOnHTMLHtmlElement(WTFMove(token));
return;
}
if (m_insertionMode == InsertionMode::InTableText) {
defaultForInTableText();
- processComment(token);
+ processComment(WTFMove(token));
return;
}
- m_tree.insertComment(token);
+ m_tree.insertComment(WTFMove(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);
}
+#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
+
// FIXME: Extract the following iOS-specific code into a separate file.
-#if PLATFORM(IOS)
// 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)
{
@@ -2344,13 +2202,13 @@ void HTMLTreeBuilder::insertPhoneNumberLink(const String& string)
attributes.append(Attribute(HTMLNames::hrefAttr, ASCIILiteral("tel:") + string));
const AtomicString& aTagLocalName = aTag.localName();
- AtomicHTMLToken aStartToken(HTMLToken::StartTag, aTagLocalName, attributes);
+ AtomicHTMLToken aStartToken(HTMLToken::StartTag, aTagLocalName, WTFMove(attributes));
AtomicHTMLToken aEndToken(HTMLToken::EndTag, aTagLocalName);
- processStartTag(&aStartToken);
+ processStartTag(WTFMove(aStartToken));
m_tree.executeQueuedTasks();
m_tree.insertTextNode(string);
- processEndTag(&aEndToken);
+ processEndTag(WTFMove(aEndToken));
}
// Locates the phone numbers in the string and deals with it
@@ -2360,13 +2218,7 @@ void HTMLTreeBuilder::insertPhoneNumberLink(const String& string)
// 4. Appends the rest of the string as a text node.
void HTMLTreeBuilder::linkifyPhoneNumbers(const String& string)
{
- static DDDFACacheRef phoneNumbersCache = DDDFACacheCreateFromFramework();
- if (!phoneNumbersCache) {
- m_tree.insertTextNode(string);
- return;
- }
-
- static DDDFAScannerRef phoneNumbersScanner = DDDFAScannerCreateFromCache(phoneNumbersCache);
+ ASSERT(TelephoneNumberDetector::isSupported());
// relativeStartPosition and relativeEndPosition are the endpoints of the phone number range,
// relative to the scannerPosition
@@ -2375,8 +2227,10 @@ void HTMLTreeBuilder::linkifyPhoneNumbers(const String& string)
int relativeStartPosition = 0;
int relativeEndPosition = 0;
+ auto characters = StringView(string).upconvertedCharacters();
+
// While there's a phone number in the rest of the string...
- while ((scannerPosition < length) && DDDFAScannerFirstResultInUnicharArray(phoneNumbersScanner, &string.characters()[scannerPosition], length - scannerPosition, &relativeStartPosition, &relativeEndPosition)) {
+ while (scannerPosition < length && TelephoneNumberDetector::find(&characters[scannerPosition], length - scannerPosition, &relativeStartPosition, &relativeEndPosition)) {
// The convention in the Data Detectors framework is that the end position is the first character NOT in the phone number
// (that is, the length of the range is relativeEndPosition - relativeStartPosition). So substract 1 to get the same
// convention as the old WebCore phone number parser (so that the rest of the code is still valid if we want to go back
@@ -2402,12 +2256,11 @@ void HTMLTreeBuilder::linkifyPhoneNumbers(const String& string)
}
// Looks at the ancestors of the element to determine whether we're inside an element which disallows parsing phone numbers.
-static inline bool disallowTelephoneNumberParsing(const Node& node)
+static inline bool disallowTelephoneNumberParsing(const ContainerNode& node)
{
return node.isLink()
- || node.nodeType() == Node::COMMENT_NODE
|| node.hasTagName(scriptTag)
- || (node.isHTMLElement() && toHTMLElement(node).isFormControlElement())
+ || is<HTMLFormControlElement>(node)
|| node.hasTagName(styleTag)
|| node.hasTagName(ttTag)
|| node.hasTagName(preTag)
@@ -2416,15 +2269,14 @@ static inline bool disallowTelephoneNumberParsing(const Node& node)
static inline bool shouldParseTelephoneNumbersInNode(const ContainerNode& node)
{
- const ContainerNode* currentNode = &node;
- do {
- if (currentNode->isElementNode() && disallowTelephoneNumberParsing(*currentNode))
+ for (const ContainerNode* ancestor = &node; ancestor; ancestor = ancestor->parentNode()) {
+ if (disallowTelephoneNumberParsing(*ancestor))
return false;
- currentNode = currentNode->parentNode();
- } while (currentNode);
+ }
return true;
}
-#endif // PLATFORM(IOS)
+
+#endif // ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
void HTMLTreeBuilder::processCharacterBuffer(ExternalCharacterTokenBuffer& buffer)
{
@@ -2447,77 +2299,66 @@ 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::InCell:
case InsertionMode::TemplateContents:
- 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);
-#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()
- && (isHTMLTableElement(m_tree.currentStackItem()->node())
- || m_tree.currentStackItem()->hasTagName(HTMLNames::tbodyTag)
- || m_tree.currentStackItem()->hasTagName(HTMLNames::tfootTag)
- || m_tree.currentStackItem()->hasTagName(HTMLNames::theadTag)
- || m_tree.currentStackItem()->hasTagName(HTMLNames::trTag))) {
+ if (is<HTMLTableElement>(m_tree.currentStackItem().node())
+ || m_tree.currentStackItem().hasTagName(HTMLNames::tbodyTag)
+ || m_tree.currentStackItem().hasTagName(HTMLNames::tfootTag)
+ || m_tree.currentStackItem().hasTagName(HTMLNames::theadTag)
+ || m_tree.currentStackItem().hasTagName(HTMLNames::trTag)) {
+
m_originalInsertionMode = m_insertionMode;
- setInsertionMode(InsertionMode::InTableText);
+ m_insertionMode = InsertionMode::InTableText;
// Note that we fall through to the InsertionMode::InTableText case below.
} else {
HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
@@ -2525,13 +2366,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);
@@ -2547,20 +2385,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;
- break;
- }
- 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);
@@ -2568,11 +2400,9 @@ ReprocessBuffer:
return;
defaultForInHeadNoscript();
goto ReprocessBuffer;
- break;
}
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);
@@ -2581,11 +2411,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()) {
@@ -2603,83 +2431,68 @@ void HTMLTreeBuilder::processCharacterBufferForInBody(ExternalCharacterTokenBuff
{
m_tree.reconstructTheActiveFormattingElements();
String characters = buffer.takeRemaining();
-#if PLATFORM(IOS)
- if (!isParsingFragment() && m_tree.isTelephoneNumberParsingEnabled() && shouldParseTelephoneNumbersInNode(*m_tree.currentNode()) && DataDetectorsCoreLibrary())
+#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
+ if (!isParsingFragment() && m_tree.isTelephoneNumberParsingEnabled() && shouldParseTelephoneNumbersInNode(m_tree.currentNode()) && TelephoneNumberDetector::isSupported())
linkifyPhoneNumbers(characters);
else
m_tree.insertTextNode(characters);
#else
m_tree.insertTextNode(characters);
#endif
-
if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
m_framesetOk = false;
}
-void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken* token)
+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 (processEndOfFileForInTemplateContents(token))
+ if (!m_templateInsertionModes.isEmpty()) {
+ if (processEndOfFileForInTemplateContents(WTFMove(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);
+ processEndOfFile(WTFMove(token));
return;
case InsertionMode::AfterFrameset:
case InsertionMode::AfterAfterFrameset:
- ASSERT(insertionMode() == InsertionMode::AfterFrameset || insertionMode() == InsertionMode::AfterAfterFrameset);
break;
case InsertionMode::InColumnGroup:
if (m_tree.currentIsRootNode()) {
ASSERT(isParsingFragment());
return; // FIXME: Should we break here instead of returning?
}
-#if ENABLE(TEMPLATE_ELEMENT)
- ASSERT(m_tree.currentNode()->hasTagName(colgroupTag) || m_tree.currentNode()->hasTagName(templateTag));
-#else
- ASSERT(m_tree.currentNode()->hasTagName(colgroupTag));
-#endif
+ ASSERT(m_tree.currentNode().hasTagName(colgroupTag) || m_tree.currentNode().hasTagName(templateTag));
processColgroupEndTagForInColumnGroup();
FALLTHROUGH;
case InsertionMode::InFrameset:
@@ -2687,40 +2500,33 @@ 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);
- if (m_tree.currentNode() != m_tree.openElements()->rootNode())
+ 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 (processEndOfFileForInTemplateContents(token))
+ if (!m_templateInsertionModes.isEmpty()) {
+ if (processEndOfFileForInTemplateContents(WTFMove(token)))
return;
-#endif
+ }
break;
case InsertionMode::InTableText:
defaultForInTableText();
- processEndOfFile(token);
+ processEndOfFile(WTFMove(token));
return;
case InsertionMode::Text:
parseError(token);
- if (m_tree.currentStackItem()->hasTagName(scriptTag))
+ if (m_tree.currentStackItem().hasTagName(scriptTag))
notImplemented(); // mark the script element as "already started".
- m_tree.openElements()->pop();
+ m_tree.openElements().pop();
ASSERT(m_originalInsertionMode != InsertionMode::Text);
- setInsertionMode(m_originalInsertionMode);
- processEndOfFile(token);
+ m_insertionMode = m_originalInsertionMode;
+ processEndOfFile(WTFMove(token));
return;
case InsertionMode::TemplateContents:
-#if ENABLE(TEMPLATE_ELEMENT)
- if (processEndOfFileForInTemplateContents(token))
+ if (processEndOfFileForInTemplateContents(WTFMove(token)))
return;
break;
-#else
- ASSERT_NOT_REACHED();
-#endif
}
- ASSERT(m_tree.currentNode());
- m_tree.openElements()->popAll();
+ m_tree.openElements().popAll();
}
void HTMLTreeBuilder::defaultForInitial()
@@ -2728,38 +2534,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_tree.insertHTMLHtmlStartTagBeforeHTML(WTFMove(startHTML));
+ m_insertionMode = InsertionMode::BeforeHead;
}
void HTMLTreeBuilder::defaultForBeforeHead()
{
AtomicHTMLToken startHead(HTMLToken::StartTag, headTag.localName());
- processStartTag(&startHead);
+ processStartTag(WTFMove(startHead));
}
void HTMLTreeBuilder::defaultForInHead()
{
AtomicHTMLToken endHead(HTMLToken::EndTag, headTag.localName());
- processEndTag(&endHead);
+ processEndTag(WTFMove(endHead));
}
void HTMLTreeBuilder::defaultForInHeadNoscript()
{
AtomicHTMLToken endNoscript(HTMLToken::EndTag, noscriptTag.localName());
- processEndTag(&endNoscript);
+ processEndTag(WTFMove(endNoscript));
}
void HTMLTreeBuilder::defaultForAfterHead()
{
AtomicHTMLToken startBody(HTMLToken::StartTag, bodyTag.localName());
- processStartTag(&startBody);
+ processStartTag(WTFMove(startBody));
m_framesetOk = true;
}
@@ -2773,135 +2579,149 @@ 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) {
- processHtmlStartTagForInBody(token);
+ ASSERT(token.type() == HTMLToken::StartTag);
+ if (token.name() == htmlTag) {
+ processHtmlStartTagForInBody(WTFMove(token));
return true;
}
- if (token->name() == baseTag
- || token->name() == basefontTag
- || token->name() == bgsoundTag
- || token->name() == commandTag
- || token->name() == linkTag
- || token->name() == metaTag) {
- m_tree.insertSelfClosingHTMLElement(token);
+ if (token.name() == baseTag
+ || token.name() == basefontTag
+ || token.name() == bgsoundTag
+ || token.name() == commandTag
+ || token.name() == linkTag
+ || token.name() == metaTag) {
+ m_tree.insertSelfClosingHTMLElement(WTFMove(token));
// Note: The custom processing for the <meta> tag is done in HTMLMetaElement::process().
return true;
}
- if (token->name() == titleTag) {
- processGenericRCDATAStartTag(token);
+ if (token.name() == titleTag) {
+ processGenericRCDATAStartTag(WTFMove(token));
return true;
}
- if (token->name() == noscriptTag) {
+ if (token.name() == noscriptTag) {
if (m_options.scriptEnabled) {
- processGenericRawTextStartTag(token);
+ processGenericRawTextStartTag(WTFMove(token));
return true;
}
- m_tree.insertHTMLElement(token);
- setInsertionMode(InsertionMode::InHeadNoscript);
+ m_tree.insertHTMLElement(WTFMove(token));
+ m_insertionMode = InsertionMode::InHeadNoscript;
return true;
}
- if (token->name() == noframesTag || token->name() == styleTag) {
- processGenericRawTextStartTag(token);
+ if (token.name() == noframesTag || token.name() == styleTag) {
+ processGenericRawTextStartTag(WTFMove(token));
return true;
}
- if (token->name() == scriptTag) {
- processScriptStartTag(token);
- if (m_options.usePreHTML5ParserQuirks && token->selfClosing())
+ if (token.name() == scriptTag) {
+ bool isSelfClosing = token.selfClosing();
+ processScriptStartTag(WTFMove(token));
+ if (m_options.usePreHTML5ParserQuirks && isSelfClosing)
processFakeEndTag(scriptTag);
return true;
}
-#if ENABLE(TEMPLATE_ELEMENT)
- if (token->name() == templateTag) {
- processTemplateStartTag(token);
+ if (token.name() == templateTag) {
+ m_framesetOk = false;
+ processTemplateStartTag(WTFMove(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);
- if (m_parser.tokenizer())
- m_parser.tokenizer()->setState(HTMLTokenizer::RCDATAState);
+ ASSERT(token.type() == HTMLToken::StartTag);
+ m_tree.insertHTMLElement(WTFMove(token));
+ m_parser.tokenizer().setRCDATAState();
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);
- if (m_parser.tokenizer())
- m_parser.tokenizer()->setState(HTMLTokenizer::RAWTEXTState);
+ ASSERT(token.type() == HTMLToken::StartTag);
+ m_tree.insertHTMLElement(WTFMove(token));
+ m_parser.tokenizer().setRAWTEXTState();
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);
- if (m_parser.tokenizer())
- m_parser.tokenizer()->setState(HTMLTokenizer::ScriptDataState);
+ ASSERT(token.type() == HTMLToken::StartTag);
+ m_tree.insertScriptElement(WTFMove(token));
+ m_parser.tokenizer().setScriptDataState();
m_originalInsertionMode = m_insertionMode;
TextPosition position = m_parser.textPosition();
m_scriptToProcessStartPosition = position;
- setInsertionMode(InsertionMode::Text);
+ m_insertionMode = InsertionMode::Text;
+}
+
+// http://www.whatwg.org/specs/web-apps/current-work/#adjusted-current-node
+HTMLStackItem& HTMLTreeBuilder::adjustedCurrentStackItem() const
+{
+ ASSERT(!m_tree.isEmpty());
+ if (isParsingFragment() && m_tree.openElements().hasOnlyOneElement())
+ return m_fragmentContext.contextElementStackItem();
+
+ return m_tree.currentStackItem();
}
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#tree-construction
-bool HTMLTreeBuilder::shouldProcessTokenInForeignContent(AtomicHTMLToken* token)
+bool HTMLTreeBuilder::shouldProcessTokenInForeignContent(const AtomicHTMLToken& token)
{
if (m_tree.isEmpty())
return false;
- HTMLStackItem* item = m_tree.currentStackItem();
- if (item->isInHTMLNamespace())
+ HTMLStackItem& adjustedCurrentNode = adjustedCurrentStackItem();
+ if (isInHTMLNamespace(adjustedCurrentNode))
return false;
- if (HTMLElementStack::isMathMLTextIntegrationPoint(item)) {
- 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 (item->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(item)) {
- 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)
+static bool hasAttribute(const AtomicHTMLToken& token, const QualifiedName& name)
+{
+ return findAttribute(token.attributes(), name);
+}
+
+void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken&& token)
{
- switch (token->type()) {
+ HTMLStackItem& adjustedCurrentNode = adjustedCurrentStackItem();
+
+ switch (token.type()) {
case HTMLToken::Uninitialized:
ASSERT_NOT_REACHED();
break;
@@ -2909,52 +2729,52 @@ 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 && (hasAttribute(token, colorAttr) || hasAttribute(token, faceAttr) || hasAttribute(token, sizeAttr)))) {
parseError(token);
- m_tree.openElements()->popUntilForeignContentScopeMarker();
- processStartTag(token);
+ m_tree.openElements().popUntilForeignContentScopeMarker();
+ processStartTag(WTFMove(token));
return;
}
- const AtomicString& currentNamespace = m_tree.currentStackItem()->namespaceURI();
+ const AtomicString& currentNamespace = adjustedCurrentNode.namespaceURI();
if (currentNamespace == MathMLNames::mathmlNamespaceURI)
adjustMathMLAttributes(token);
if (currentNamespace == SVGNames::svgNamespaceURI) {
@@ -2962,44 +2782,44 @@ void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token)
adjustSVGAttributes(token);
}
adjustForeignAttributes(token);
- m_tree.insertForeignElement(token, currentNamespace);
+ m_tree.insertForeignElement(WTFMove(token), currentNamespace);
break;
}
case HTMLToken::EndTag: {
- if (m_tree.currentStackItem()->namespaceURI() == SVGNames::svgNamespaceURI)
+ 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();
+ m_scriptToProcess = &downcast<SVGScriptElement>(m_tree.currentElement());
+ m_tree.openElements().pop();
return;
}
- if (!m_tree.currentStackItem()->isInHTMLNamespace()) {
+ if (!isInHTMLNamespace(m_tree.currentStackItem())) {
// 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().localName() != token.name())
parseError(token);
while (1) {
- if (nodeRecord->stackItem()->hasLocalName(token->name())) {
- m_tree.openElements()->popUntilPopped(nodeRecord->element());
+ if (nodeRecord->stackItem().localName() == token.name()) {
+ m_tree.openElements().popUntilPopped(nodeRecord->element());
return;
}
nodeRecord = nodeRecord->next();
- if (nodeRecord->stackItem()->isInHTMLNamespace())
+ if (isInHTMLNamespace(nodeRecord->stackItem()))
break;
}
}
// Otherwise, process the token according to the rules given in the section corresponding to the current insertion mode in HTML content.
- processEndTag(token);
+ processEndTag(WTFMove(token));
break;
}
case HTMLToken::Comment:
- m_tree.insertComment(token);
+ m_tree.insertComment(WTFMove(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;
@@ -3013,19 +2833,18 @@ void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token)
void HTMLTreeBuilder::finished()
{
+ ASSERT(!m_destroyed);
+
if (isParsingFragment())
return;
-#if ENABLE(TEMPLATE_ELEMENT)
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(const AtomicHTMLToken&)
{
}