summaryrefslogtreecommitdiff
path: root/Source/WebCore/html/parser/HTMLTreeBuilder.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
commit32761a6cee1d0dee366b885b7b9c777e67885688 (patch)
treed6bec92bebfb216f4126356e55518842c2f476a1 /Source/WebCore/html/parser/HTMLTreeBuilder.cpp
parenta4e969f4965059196ca948db781e52f7cfebf19e (diff)
downloadWebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/WebCore/html/parser/HTMLTreeBuilder.cpp')
-rw-r--r--Source/WebCore/html/parser/HTMLTreeBuilder.cpp2153
1 files changed, 1120 insertions, 1033 deletions
diff --git a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp
index dda0de851..46b3baf47 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, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 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,20 +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 "HTMLTableElement.h"
+#include "HTMLTemplateElement.h"
#include "LocalizedStrings.h"
#include "NotImplemented.h"
#include "XLinkNames.h"
#include "XMLNSNames.h"
#include "XMLNames.h"
-#include <wtf/NeverDestroyed.h>
+#include <wtf/MainThread.h>
#include <wtf/unicode/CharacterNames.h>
-#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
-#include "TelephoneNumberDetector.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))
#endif
namespace WebCore {
@@ -59,7 +81,7 @@ inline bool isHTMLSpaceOrReplacementCharacter(UChar character)
}
-static inline TextPosition uninitializedPositionValue1()
+static TextPosition uninitializedPositionValue1()
{
return TextPosition(OrdinalNumber::fromOneBasedInt(-1), OrdinalNumber::first());
}
@@ -86,7 +108,9 @@ 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)
@@ -96,7 +120,9 @@ 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)
@@ -117,27 +143,31 @@ static bool isNonAnchorNonNobrFormattingTag(const AtomicString& tagName)
static bool isNonAnchorFormattingTag(const AtomicString& tagName)
{
- return tagName == nobrTag || isNonAnchorNonNobrFormattingTag(tagName);
+ return tagName == nobrTag
+ || isNonAnchorNonNobrFormattingTag(tagName);
}
-// https://html.spec.whatwg.org/multipage/syntax.html#formatting
-bool HTMLConstructionSite::isFormattingTag(const AtomicString& tagName)
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#formatting
+static bool isFormattingTag(const AtomicString& tagName)
{
return tagName == aTag || isNonAnchorFormattingTag(tagName);
}
class HTMLTreeBuilder::ExternalCharacterTokenBuffer {
+ WTF_MAKE_NONCOPYABLE(ExternalCharacterTokenBuffer);
public:
- explicit ExternalCharacterTokenBuffer(AtomicHTMLToken& token)
- : m_text(token.characters(), token.charactersLength())
- , m_isAll8BitData(token.charactersIsAll8BitData())
+ explicit ExternalCharacterTokenBuffer(AtomicHTMLToken* token)
+ : m_current(token->characters())
+ , m_end(m_current + token->charactersLength())
+ , m_isAll8BitData(token->isAll8BitData())
{
ASSERT(!isEmpty());
}
explicit ExternalCharacterTokenBuffer(const String& string)
- : m_text(string)
- , m_isAll8BitData(m_text.is8Bit())
+ : m_current(string.deprecatedCharacters())
+ , m_end(m_current + string.length())
+ , m_isAll8BitData(string.length() && string.is8Bit())
{
ASSERT(!isEmpty());
}
@@ -147,15 +177,15 @@ public:
ASSERT(isEmpty());
}
- bool isEmpty() const { return m_text.isEmpty(); }
+ bool isEmpty() const { return m_current == m_end; }
bool isAll8BitData() const { return m_isAll8BitData; }
void skipAtMostOneLeadingNewline()
{
ASSERT(!isEmpty());
- if (m_text[0] == '\n')
- m_text = m_text.substring(1);
+ if (*m_current == '\n')
+ ++m_current;
}
void skipLeadingWhitespace()
@@ -175,190 +205,190 @@ public:
String takeRemaining()
{
- String result = makeString(m_text);
- m_text = StringView();
- return result;
+ 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);
}
void giveRemainingTo(StringBuilder& recipient)
{
- recipient.append(m_text);
- m_text = StringView();
+ recipient.append(m_current, m_end - m_current);
+ m_current = m_end;
}
String takeRemainingWhitespace()
{
ASSERT(!isEmpty());
- Vector<LChar, 8> whitespace;
+ Vector<UChar> whitespace;
do {
- UChar character = m_text[0];
- if (isHTMLSpace(character))
- whitespace.append(character);
- m_text = m_text.substring(1);
- } while (!m_text.isEmpty());
-
+ UChar cc = *m_current++;
+ if (isHTMLSpace(cc))
+ whitespace.append(cc);
+ } while (m_current < m_end);
// 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);
}
private:
- template<bool characterPredicate(UChar)> void skipLeading()
+ template<bool characterPredicate(UChar)>
+ void skipLeading()
{
ASSERT(!isEmpty());
- while (characterPredicate(m_text[0])) {
- m_text = m_text.substring(1);
- if (m_text.isEmpty())
+ while (characterPredicate(*m_current)) {
+ if (++m_current == m_end)
return;
}
}
- template<bool characterPredicate(UChar)> String takeLeading()
+ template<bool characterPredicate(UChar)>
+ String takeLeading()
{
ASSERT(!isEmpty());
- StringView start = m_text;
+ const UChar* start = m_current;
skipLeading<characterPredicate>();
- if (start.length() == m_text.length())
+ if (start == m_current)
return String();
- return makeString(start.substring(0, start.length() - m_text.length()));
- }
-
- String makeString(StringView stringView) const
- {
- if (stringView.is8Bit() || !isAll8BitData())
- return stringView.toString();
- return String::make8BitFrom16BitSource(stringView.characters16(), stringView.length());
+ if (isAll8BitData())
+ return String::make8BitFrom16BitSource(start, m_current - start);
+ return String(start, m_current - start);
}
- StringView m_text;
+ const UChar* m_current;
+ const UChar* m_end;
bool m_isAll8BitData;
};
-inline bool HTMLTreeBuilder::isParsingTemplateContents() const
-{
-#if ENABLE(TEMPLATE_ELEMENT)
- return m_tree.openElements().hasTemplateInHTMLScope();
-#else
- return false;
-#endif
-}
-
-inline bool HTMLTreeBuilder::isParsingFragmentOrTemplateContents() const
-{
- return isParsingFragment() || isParsingTemplateContents();
-}
HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser& parser, HTMLDocument& document, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options)
- : m_parser(parser)
- , m_options(options)
+ : m_framesetOk(true)
+#ifndef NDEBUG
+ , m_isAttached(true)
+#endif
, 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
}
-HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser& parser, DocumentFragment& fragment, Element& contextElement, ParserContentPolicy parserContentPolicy, const HTMLParserOptions& options)
- : m_parser(parser)
- , m_options(options)
+// 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
, 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());
-
- // 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));
+ // 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);
+ if (contextElement->hasTagName(templateTag))
+ m_templateInsertionModes.append(InsertionMode::TemplateContents);
#endif
- resetInsertionModeAppropriately();
+ resetInsertionModeAppropriately();
+ m_tree.setForm(!contextElement || isHTMLFormElement(contextElement) ? toHTMLFormElement(contextElement) : HTMLFormElement::findClosestFormAncestor(*contextElement));
+ }
+}
- m_tree.setForm(is<HTMLFormElement>(contextElement) ? &downcast<HTMLFormElement>(contextElement) : HTMLFormElement::findClosestFormAncestor(contextElement));
+HTMLTreeBuilder::~HTMLTreeBuilder()
+{
+}
-#if !ASSERT_DISABLED
- m_destructionProhibited = false;
+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;
#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
+HTMLTreeBuilder::FragmentParsingContext::~FragmentParsingContext()
{
- return contextElementStackItem().element();
}
-inline HTMLStackItem& HTMLTreeBuilder::FragmentParsingContext::contextElementStackItem() const
+PassRefPtr<Element> HTMLTreeBuilder::takeScriptToProcess(TextPosition& scriptStartPosition)
{
- ASSERT(m_fragment);
- return *m_contextElementStackItem;
-}
-
-RefPtr<Element> HTMLTreeBuilder::takeScriptToProcess(TextPosition& scriptStartPosition)
-{
- ASSERT(!m_destroyed);
-
- if (!m_scriptToProcess)
- return nullptr;
-
+ ASSERT(m_scriptToProcess);
// 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 WTFMove(m_scriptToProcess);
+ return m_scriptToProcess.release();
}
-void HTMLTreeBuilder::constructTree(AtomicHTMLToken& token)
+void HTMLTreeBuilder::constructTree(AtomicHTMLToken* token)
{
-#if !ASSERT_DISABLED
- ASSERT(!m_destroyed);
- ASSERT(!m_destructionProhibited);
- m_destructionProhibited = true;
-#endif
-
if (shouldProcessTokenInForeignContent(token))
processTokenInForeignContent(token);
else
processToken(token);
- bool inForeignContent = !m_tree.isEmpty()
- && !isInHTMLNamespace(adjustedCurrentStackItem())
- && !HTMLElementStack::isHTMLIntegrationPoint(m_tree.currentStackItem())
- && !HTMLElementStack::isMathMLTextIntegrationPoint(m_tree.currentStackItem());
-
- m_parser.tokenizer().setForceNullCharacterReplacement(m_insertionMode == InsertionMode::Text || inForeignContent);
- m_parser.tokenizer().setShouldAllowCDATA(inForeignContent);
+ if (m_parser.tokenizer()) {
+ bool inForeignContent = !m_tree.isEmpty()
+ && !m_tree.currentStackItem()->isInHTMLNamespace()
+ && !HTMLElementStack::isHTMLIntegrationPoint(m_tree.currentStackItem())
+ && !HTMLElementStack::isMathMLTextIntegrationPoint(m_tree.currentStackItem());
-#if !ASSERT_DISABLED
- m_destructionProhibited = false;
-#endif
+ m_parser.tokenizer()->setForceNullCharacterReplacement(m_insertionMode == InsertionMode::Text || inForeignContent);
+ m_parser.tokenizer()->setShouldAllowCDATA(inForeignContent);
+ }
m_tree.executeQueuedTasks();
- // The tree builder might have been destroyed as an indirect result of executing the queued tasks.
+ // We might be detached now.
}
-void HTMLTreeBuilder::processToken(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processToken(AtomicHTMLToken* token)
{
- switch (token.type()) {
+ switch (token->type()) {
case HTMLToken::Uninitialized:
ASSERT_NOT_REACHED();
break;
@@ -388,12 +418,12 @@ void HTMLTreeBuilder::processToken(AtomicHTMLToken& token)
}
}
-void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::DOCTYPE);
+ ASSERT(token->type() == HTMLToken::DOCTYPE);
if (m_insertionMode == InsertionMode::Initial) {
- m_tree.insertDoctype(&token);
- m_insertionMode = InsertionMode::BeforeHTML;
+ m_tree.insertDoctype(token);
+ setInsertionMode(InsertionMode::BeforeHTML);
return;
}
if (m_insertionMode == InsertionMode::InTableText) {
@@ -404,17 +434,17 @@ void HTMLTreeBuilder::processDoctypeToken(AtomicHTMLToken& token)
parseError(token);
}
-void HTMLTreeBuilder::processFakeStartTag(const QualifiedName& tagName, Vector<Attribute>&& attributes)
+void HTMLTreeBuilder::processFakeStartTag(const QualifiedName& tagName, const Vector<Attribute>& attributes)
{
// FIXME: We'll need a fancier conversion than just "localName" for SVG/MathML tags.
- AtomicHTMLToken fakeToken(HTMLToken::StartTag, tagName.localName(), WTFMove(attributes));
- processStartTag(fakeToken);
+ AtomicHTMLToken fakeToken(HTMLToken::StartTag, tagName.localName(), attributes);
+ processStartTag(&fakeToken);
}
void HTMLTreeBuilder::processFakeEndTag(const AtomicString& tagName)
{
AtomicHTMLToken fakeToken(HTMLToken::EndTag, tagName);
- processEndTag(fakeToken);
+ processEndTag(&fakeToken);
}
void HTMLTreeBuilder::processFakeEndTag(const QualifiedName& tagName)
@@ -432,38 +462,41 @@ 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);
+ processEndTag(&endP);
}
-Vector<Attribute> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken& token)
+Vector<Attribute> HTMLTreeBuilder::attributesForIsindexInput(AtomicHTMLToken* token)
{
- Vector<Attribute> attributes = token.attributes();
- attributes.removeAllMatching([] (const Attribute& attribute) {
- const QualifiedName& name = attribute.name();
- return name.matches(nameAttr) || name.matches(actionAttr) || name.matches(promptAttr);
- });
+ 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)
+void HTMLTreeBuilder::processIsindexStartTagForInBody(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::StartTag);
- ASSERT(token.name() == isindexTag);
+ ASSERT(token->type() == HTMLToken::StartTag);
+ ASSERT(token->name() == isindexTag);
parseError(token);
if (m_tree.form() && !isParsingTemplateContents())
return;
notImplemented(); // Acknowledge self-closing flag
processFakeStartTag(formTag);
- if (Attribute* actionAttribute = findAttribute(token.attributes(), actionAttr))
+ Attribute* actionAttribute = token->getAttributeItem(actionAttr);
+ if (actionAttribute)
m_tree.form()->setAttribute(actionAttr, actionAttribute->value());
processFakeStartTag(hrTag);
processFakeStartTag(labelTag);
- if (Attribute* promptAttribute = findAttribute(token.attributes(), promptAttr))
+ Attribute* promptAttribute = token->getAttributeItem(promptAttr);
+ if (promptAttribute)
processFakeCharacters(promptAttribute->value());
else
processFakeCharacters(searchableIndexIntroduction());
@@ -476,357 +509,381 @@ void HTMLTreeBuilder::processIsindexStartTagForInBody(AtomicHTMLToken& token)
namespace {
-bool isLi(const HTMLStackItem& item)
+bool isLi(const HTMLStackItem* item)
{
- return item.hasTagName(liTag);
+ return item->hasTagName(liTag);
}
-bool isDdOrDt(const HTMLStackItem& item)
+bool isDdOrDt(const HTMLStackItem* item)
{
- return item.hasTagName(ddTag) || item.hasTagName(dtTag);
+ return item->hasTagName(ddTag)
+ || item->hasTagName(dtTag);
}
}
-template <bool shouldClose(const HTMLStackItem&)> void HTMLTreeBuilder::processCloseWhenNestedTag(AtomicHTMLToken& token)
+template <bool shouldClose(const HTMLStackItem*)>
+void HTMLTreeBuilder::processCloseWhenNestedTag(AtomicHTMLToken* token)
{
m_framesetOk = false;
- for (auto* nodeRecord = &m_tree.openElements().topRecord(); ; nodeRecord = nodeRecord->next()) {
- HTMLStackItem& item = nodeRecord->stackItem();
- if (shouldClose(item)) {
- ASSERT(item.isElement());
- processFakeEndTag(item.localName());
+ HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord();
+ while (1) {
+ RefPtr<HTMLStackItem> item = nodeRecord->stackItem();
+ if (shouldClose(item.get())) {
+ ASSERT(item->isElementNode());
+ processFakeEndTag(item->localName());
break;
}
- if (isSpecialNode(item) && !item.hasTagName(addressTag) && !item.hasTagName(divTag) && !item.hasTagName(pTag))
+ if (item->isSpecialNode() && !item->hasTagName(addressTag) && !item->hasTagName(divTag) && !item->hasTagName(pTag))
break;
+ nodeRecord = nodeRecord->next();
}
processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLElement(&token);
+ m_tree.insertHTMLElement(token);
}
-template <typename TableQualifiedName> static HashMap<AtomicString, QualifiedName> createCaseMap(const TableQualifiedName* const names[], unsigned length)
+typedef HashMap<AtomicString, QualifiedName> PrefixedNameToQualifiedNameMap;
+
+static void mapLoweredLocalNameToName(PrefixedNameToQualifiedNameMap* map, const QualifiedName* const names[], size_t length)
{
- HashMap<AtomicString, QualifiedName> map;
- for (unsigned i = 0; i < length; ++i) {
+ for (size_t i = 0; i < length; ++i) {
const QualifiedName& name = *names[i];
const AtomicString& localName = name.localName();
- AtomicString loweredLocalName = localName.convertToASCIILowercase();
+ AtomicString loweredLocalName = localName.lower();
if (loweredLocalName != localName)
- map.add(loweredLocalName, name);
+ map->add(loweredLocalName, name);
}
- return map;
}
-static void adjustSVGTagNameCase(AtomicHTMLToken& token)
+static void adjustSVGTagNameCase(AtomicHTMLToken* token)
{
- static NeverDestroyed<HashMap<AtomicString, QualifiedName>> map = createCaseMap(SVGNames::getSVGTags(), SVGNames::SVGTagsCount);
- const QualifiedName& casedName = map.get().get(token.name());
+ static PrefixedNameToQualifiedNameMap* caseMap = 0;
+ if (!caseMap) {
+ caseMap = new PrefixedNameToQualifiedNameMap;
+ mapLoweredLocalNameToName(caseMap, SVGNames::getSVGTags(), SVGNames::SVGTagsCount);
+ }
+
+ const QualifiedName& casedName = caseMap->get(token->name());
if (casedName.localName().isNull())
return;
- token.setName(casedName.localName());
+ token->setName(casedName.localName());
}
-static inline void adjustAttributes(HashMap<AtomicString, QualifiedName>& map, AtomicHTMLToken& token)
+template<const QualifiedName* const * getAttrs(), unsigned length>
+static void adjustAttributes(AtomicHTMLToken* token)
{
- for (auto& attribute : token.attributes()) {
- const QualifiedName& casedName = map.get(attribute.localName());
- if (!casedName.localName().isNull())
- attribute.parserSetName(casedName);
+ static PrefixedNameToQualifiedNameMap* caseMap = 0;
+ if (!caseMap) {
+ caseMap = new PrefixedNameToQualifiedNameMap;
+ mapLoweredLocalNameToName(caseMap, getAttrs(), length);
}
-}
-template<const QualifiedName* const* attributesTable(), unsigned attributesTableLength> static void adjustAttributes(AtomicHTMLToken& token)
-{
- static NeverDestroyed<HashMap<AtomicString, QualifiedName>> map = createCaseMap(attributesTable(), attributesTableLength);
- adjustAttributes(map, token);
+ for (unsigned i = 0; i < token->attributes().size(); ++i) {
+ Attribute& tokenAttribute = token->attributes().at(i);
+ const QualifiedName& casedName = caseMap->get(tokenAttribute.localName());
+ if (!casedName.localName().isNull())
+ tokenAttribute.parserSetName(casedName);
+ }
}
-static inline void adjustSVGAttributes(AtomicHTMLToken& token)
+static void adjustSVGAttributes(AtomicHTMLToken* token)
{
adjustAttributes<SVGNames::getSVGAttrs, SVGNames::SVGAttrsCount>(token);
}
-static inline void adjustMathMLAttributes(AtomicHTMLToken& token)
+static void adjustMathMLAttributes(AtomicHTMLToken* token)
{
adjustAttributes<MathMLNames::getMathMLAttrs, MathMLNames::MathMLAttrsCount>(token);
}
-static void addNamesWithPrefix(HashMap<AtomicString, QualifiedName>& map, const AtomicString& prefix, const QualifiedName* const names[], unsigned length)
+static void addNamesWithPrefix(PrefixedNameToQualifiedNameMap* map, const AtomicString& prefix, const QualifiedName* const names[], size_t length)
{
- for (unsigned i = 0; i < length; ++i) {
+ for (size_t i = 0; i < length; ++i) {
const QualifiedName& name = *names[i];
const AtomicString& localName = name.localName();
- map.add(prefix + ':' + localName, QualifiedName(prefix, localName, name.namespaceURI()));
+ AtomicString prefixColonLocalName = prefix + ':' + localName;
+ QualifiedName nameWithPrefix(prefix, localName, name.namespaceURI());
+ map->add(prefixColonLocalName, nameWithPrefix);
}
}
-static HashMap<AtomicString, QualifiedName> createForeignAttributesMap()
+static void adjustForeignAttributes(AtomicHTMLToken* token)
{
- HashMap<AtomicString, QualifiedName> map;
+ static PrefixedNameToQualifiedNameMap* map = 0;
+ if (!map) {
+ map = new PrefixedNameToQualifiedNameMap;
- addNamesWithPrefix(map, xlinkAtom, XLinkNames::getXLinkAttrs(), XLinkNames::XLinkAttrsCount);
- addNamesWithPrefix(map, xmlAtom, XMLNames::getXMLAttrs(), XMLNames::XMLAttrsCount);
+ addNamesWithPrefix(map, xlinkAtom, XLinkNames::getXLinkAttrs(), XLinkNames::XLinkAttrsCount);
- map.add(WTF::xmlnsAtom, XMLNSNames::xmlnsAttr);
- map.add("xmlns:xlink", QualifiedName(xmlnsAtom, xlinkAtom, XMLNSNames::xmlnsNamespaceURI));
+ addNamesWithPrefix(map, xmlAtom, XMLNames::getXMLAttrs(), XMLNames::XMLAttrsCount);
- return map;
-}
+ map->add(WTF::xmlnsAtom, XMLNSNames::xmlnsAttr);
+ map->add("xmlns:xlink", QualifiedName(xmlnsAtom, xlinkAtom, XMLNSNames::xmlnsNamespaceURI));
+ }
-static void adjustForeignAttributes(AtomicHTMLToken& token)
-{
- static NeverDestroyed<HashMap<AtomicString, QualifiedName>> map = createForeignAttributesMap();
- adjustAttributes(map, token);
+ for (unsigned i = 0; i < token->attributes().size(); ++i) {
+ Attribute& tokenAttribute = token->attributes().at(i);
+ const QualifiedName& name = map->get(tokenAttribute.localName());
+ if (!name.localName().isNull())
+ tokenAttribute.parserSetName(name);
+ }
}
-void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::StartTag);
- if (token.name() == htmlTag) {
+ ASSERT(token->type() == HTMLToken::StartTag);
+ if (token->name() == htmlTag) {
processHtmlStartTagForInBody(token);
return;
}
- if (token.name() == baseTag
- || token.name() == basefontTag
- || token.name() == bgsoundTag
- || token.name() == commandTag
- || token.name() == linkTag
- || token.name() == metaTag
- || token.name() == noframesTag
- || token.name() == scriptTag
- || token.name() == styleTag
- || token.name() == titleTag) {
+ if (token->name() == baseTag
+ || token->name() == basefontTag
+ || token->name() == bgsoundTag
+ || token->name() == commandTag
+ || token->name() == linkTag
+ || token->name() == metaTag
+ || token->name() == noframesTag
+ || token->name() == scriptTag
+ || token->name() == styleTag
+ || token->name() == titleTag) {
bool didProcess = processStartTagForInHead(token);
ASSERT_UNUSED(didProcess, didProcess);
return;
}
- if (token.name() == bodyTag) {
+ if (token->name() == bodyTag) {
parseError(token);
- bool fragmentOrTemplateCase = !m_tree.openElements().secondElementIsHTMLBodyElement() || m_tree.openElements().hasOnlyOneElement();
+ bool fragmentOrTemplateCase = !m_tree.openElements()->secondElementIsHTMLBodyElement() || m_tree.openElements()->hasOnlyOneElement();
#if ENABLE(TEMPLATE_ELEMENT)
- fragmentOrTemplateCase = fragmentOrTemplateCase || m_tree.openElements().hasTemplateInHTMLScope();
+ fragmentOrTemplateCase = fragmentOrTemplateCase || m_tree.openElements()->hasTemplateInHTMLScope();
#endif
if (fragmentOrTemplateCase) {
ASSERT(isParsingFragmentOrTemplateContents());
return;
}
m_framesetOk = false;
- m_tree.insertHTMLBodyStartTagInBody(&token);
+ m_tree.insertHTMLBodyStartTagInBody(token);
return;
}
- if (token.name() == framesetTag) {
+ if (token->name() == framesetTag) {
parseError(token);
- if (!m_tree.openElements().secondElementIsHTMLBodyElement() || m_tree.openElements().hasOnlyOneElement()) {
+ 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);
- 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) {
+ 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) {
processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLElement(&token);
+ m_tree.insertHTMLElement(token);
return;
}
- if (isNumberedHeaderTag(token.name())) {
+ if (isNumberedHeaderTag(token->name())) {
processFakePEndTagIfPInButtonScope();
- if (isNumberedHeaderElement(m_tree.currentStackItem())) {
+ if (m_tree.currentStackItem()->isNumberedHeaderElement()) {
parseError(token);
- m_tree.openElements().pop();
+ m_tree.openElements()->pop();
}
- m_tree.insertHTMLElement(&token);
+ m_tree.insertHTMLElement(token);
return;
}
- if (token.name() == preTag || token.name() == listingTag) {
+ if (token->name() == preTag || token->name() == listingTag) {
processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLElement(&token);
+ m_tree.insertHTMLElement(token);
m_shouldSkipLeadingNewline = true;
m_framesetOk = false;
return;
}
- if (token.name() == formTag) {
+ if (token->name() == formTag) {
if (m_tree.form() && !isParsingTemplateContents()) {
parseError(token);
return;
}
processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLFormElement(&token);
+ m_tree.insertHTMLFormElement(token);
return;
}
- if (token.name() == liTag) {
+ if (token->name() == liTag) {
processCloseWhenNestedTag<isLi>(token);
return;
}
- if (token.name() == ddTag || token.name() == dtTag) {
+ if (token->name() == ddTag || token->name() == dtTag) {
processCloseWhenNestedTag<isDdOrDt>(token);
return;
}
- if (token.name() == plaintextTag) {
+ if (token->name() == plaintextTag) {
processFakePEndTagIfPInButtonScope();
- m_tree.insertHTMLElement(&token);
- m_parser.tokenizer().setPLAINTEXTState();
+ m_tree.insertHTMLElement(token);
+ if (m_parser.tokenizer())
+ m_parser.tokenizer()->setState(HTMLTokenizer::PLAINTEXTState);
return;
}
- if (token.name() == buttonTag) {
- if (m_tree.openElements().inScope(buttonTag)) {
+ if (token->name() == buttonTag) {
+ if (m_tree.openElements()->inScope(buttonTag)) {
parseError(token);
processFakeEndTag(buttonTag);
processStartTag(token); // FIXME: Could we just fall through here?
return;
}
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(&token);
+ m_tree.insertHTMLElement(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(token);
return;
}
- if (isNonAnchorNonNobrFormattingTag(token.name())) {
+ if (isNonAnchorNonNobrFormattingTag(token->name())) {
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertFormattingElement(&token);
+ m_tree.insertFormattingElement(token);
return;
}
- if (token.name() == nobrTag) {
+ if (token->name() == nobrTag) {
m_tree.reconstructTheActiveFormattingElements();
- if (m_tree.openElements().inScope(nobrTag)) {
+ if (m_tree.openElements()->inScope(nobrTag)) {
parseError(token);
processFakeEndTag(nobrTag);
m_tree.reconstructTheActiveFormattingElements();
}
- m_tree.insertFormattingElement(&token);
+ m_tree.insertFormattingElement(token);
return;
}
- if (token.name() == appletTag || token.name() == embedTag || token.name() == objectTag) {
+ if (token->name() == appletTag
+ || token->name() == embedTag
+ || token->name() == objectTag) {
if (!pluginContentIsAllowed(m_tree.parserContentPolicy()))
return;
}
- if (token.name() == appletTag || token.name() == marqueeTag || token.name() == objectTag) {
+ if (token->name() == appletTag
+ || token->name() == marqueeTag
+ || token->name() == objectTag) {
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(&token);
- m_tree.activeFormattingElements().appendMarker();
+ m_tree.insertHTMLElement(token);
+ m_tree.activeFormattingElements()->appendMarker();
m_framesetOk = false;
return;
}
- if (token.name() == tableTag) {
- if (!m_tree.inQuirksMode() && m_tree.openElements().inButtonScope(pTag))
+ if (token->name() == tableTag) {
+ if (!m_tree.inQuirksMode() && m_tree.openElements()->inButtonScope(pTag))
processFakeEndTag(pTag);
- m_tree.insertHTMLElement(&token);
+ m_tree.insertHTMLElement(token);
m_framesetOk = false;
- m_insertionMode = InsertionMode::InTable;
+ setInsertionMode(InsertionMode::InTable);
return;
}
- if (token.name() == imageTag) {
+ if (token->name() == imageTag) {
parseError(token);
// Apparently we're not supposed to ask.
- token.setName(imgTag.localName());
+ token->setName(imgTag.localName());
// Note the fall through to the imgTag handling below!
}
- if (token.name() == areaTag
- || token.name() == brTag
- || token.name() == embedTag
- || token.name() == imgTag
- || token.name() == keygenTag
- || token.name() == wbrTag) {
+ if (token->name() == areaTag
+ || token->name() == brTag
+ || token->name() == embedTag
+ || token->name() == imgTag
+ || token->name() == keygenTag
+ || token->name() == wbrTag) {
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertSelfClosingHTMLElement(&token);
+ m_tree.insertSelfClosingHTMLElement(token);
m_framesetOk = false;
return;
}
- if (token.name() == inputTag) {
+ if (token->name() == inputTag) {
+ Attribute* typeAttribute = token->getAttributeItem(typeAttr);
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertSelfClosingHTMLElement(&token);
- Attribute* typeAttribute = findAttribute(token.attributes(), typeAttr);
- if (!typeAttribute || !equalLettersIgnoringASCIICase(typeAttribute->value(), "hidden"))
+ m_tree.insertSelfClosingHTMLElement(token);
+ if (!typeAttribute || !equalIgnoringCase(typeAttribute->value(), "hidden"))
m_framesetOk = false;
return;
}
- if (token.name() == paramTag || token.name() == sourceTag || token.name() == trackTag) {
- m_tree.insertSelfClosingHTMLElement(&token);
+ if (token->name() == paramTag
+ || token->name() == sourceTag
+ || token->name() == trackTag) {
+ m_tree.insertSelfClosingHTMLElement(token);
return;
}
- if (token.name() == hrTag) {
+ if (token->name() == hrTag) {
processFakePEndTagIfPInButtonScope();
- m_tree.insertSelfClosingHTMLElement(&token);
+ m_tree.insertSelfClosingHTMLElement(token);
m_framesetOk = false;
return;
}
- if (token.name() == isindexTag) {
+ if (token->name() == isindexTag) {
processIsindexStartTagForInBody(token);
return;
}
- if (token.name() == textareaTag) {
- m_tree.insertHTMLElement(&token);
+ if (token->name() == textareaTag) {
+ m_tree.insertHTMLElement(token);
m_shouldSkipLeadingNewline = true;
- m_parser.tokenizer().setRCDATAState();
+ if (m_parser.tokenizer())
+ m_parser.tokenizer()->setState(HTMLTokenizer::RCDATAState);
m_originalInsertionMode = m_insertionMode;
m_framesetOk = false;
- m_insertionMode = InsertionMode::Text;
+ setInsertionMode(InsertionMode::Text);
return;
}
- if (token.name() == xmpTag) {
+ if (token->name() == xmpTag) {
processFakePEndTagIfPInButtonScope();
m_tree.reconstructTheActiveFormattingElements();
m_framesetOk = false;
processGenericRawTextStartTag(token);
return;
}
- if (token.name() == iframeTag) {
+ if (token->name() == iframeTag) {
m_framesetOk = false;
processGenericRawTextStartTag(token);
return;
}
- if (token.name() == noembedTag && m_options.pluginsEnabled) {
+ if (token->name() == noembedTag && m_options.pluginsEnabled) {
processGenericRawTextStartTag(token);
return;
}
- if (token.name() == noscriptTag && m_options.scriptEnabled) {
+ if (token->name() == noscriptTag && m_options.scriptEnabled) {
processGenericRawTextStartTag(token);
return;
}
- if (token.name() == selectTag) {
+ if (token->name() == selectTag) {
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(&token);
+ m_tree.insertHTMLElement(token);
m_framesetOk = false;
if (m_insertionMode == InsertionMode::InTable
|| m_insertionMode == InsertionMode::InCaption
@@ -834,116 +891,105 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken& token)
|| m_insertionMode == InsertionMode::InTableBody
|| m_insertionMode == InsertionMode::InRow
|| m_insertionMode == InsertionMode::InCell)
- m_insertionMode = InsertionMode::InSelectInTable;
+ setInsertionMode(InsertionMode::InSelectInTable);
else
- m_insertionMode = InsertionMode::InSelect;
+ setInsertionMode(InsertionMode::InSelect);
return;
}
- if (token.name() == optgroupTag || token.name() == optionTag) {
- if (is<HTMLOptionElement>(m_tree.currentStackItem().node())) {
+ if (token->name() == optgroupTag || token->name() == optionTag) {
+ if (isHTMLOptionElement(m_tree.currentStackItem()->node())) {
AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
- processEndTag(endOption);
+ processEndTag(&endOption);
}
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(&token);
+ m_tree.insertHTMLElement(token);
return;
}
- if (token.name() == rbTag || token.name() == rtcTag) {
- if (m_tree.openElements().inScope(rubyTag.localName())) {
+ if (token->name() == rpTag || token->name() == rtTag) {
+ if (m_tree.openElements()->inScope(rubyTag.localName())) {
m_tree.generateImpliedEndTags();
- if (!m_tree.currentStackItem().hasTagName(rubyTag))
- parseError(token);
- }
- m_tree.insertHTMLElement(&token);
- return;
- }
- if (token.name() == rtTag || token.name() == rpTag) {
- if (m_tree.openElements().inScope(rubyTag.localName())) {
- m_tree.generateImpliedEndTagsWithExclusion(rtcTag.localName());
- if (!m_tree.currentStackItem().hasTagName(rubyTag) && !m_tree.currentStackItem().hasTagName(rtcTag))
+ if (!m_tree.currentStackItem()->hasTagName(rubyTag))
parseError(token);
}
- m_tree.insertHTMLElement(&token);
+ m_tree.insertHTMLElement(token);
return;
}
- if (token.name() == MathMLNames::mathTag.localName()) {
+ if (token->name() == MathMLNames::mathTag.localName()) {
m_tree.reconstructTheActiveFormattingElements();
adjustMathMLAttributes(token);
adjustForeignAttributes(token);
- m_tree.insertForeignElement(&token, MathMLNames::mathmlNamespaceURI);
+ m_tree.insertForeignElement(token, MathMLNames::mathmlNamespaceURI);
return;
}
- if (token.name() == SVGNames::svgTag.localName()) {
+ if (token->name() == SVGNames::svgTag.localName()) {
m_tree.reconstructTheActiveFormattingElements();
adjustSVGAttributes(token);
adjustForeignAttributes(token);
- m_tree.insertForeignElement(&token, SVGNames::svgNamespaceURI);
+ m_tree.insertForeignElement(token, SVGNames::svgNamespaceURI);
return;
}
- if (isCaptionColOrColgroupTag(token.name())
- || token.name() == frameTag
- || token.name() == headTag
- || isTableBodyContextTag(token.name())
- || isTableCellContextTag(token.name())
- || token.name() == trTag) {
+ if (isCaptionColOrColgroupTag(token->name())
+ || token->name() == frameTag
+ || token->name() == headTag
+ || isTableBodyContextTag(token->name())
+ || isTableCellContextTag(token->name())
+ || token->name() == trTag) {
parseError(token);
return;
}
#if ENABLE(TEMPLATE_ELEMENT)
- if (token.name() == templateTag) {
+ if (token->name() == templateTag) {
processTemplateStartTag(token);
return;
}
#endif
m_tree.reconstructTheActiveFormattingElements();
- m_tree.insertHTMLElement(&token);
+ m_tree.insertHTMLElement(token);
}
#if ENABLE(TEMPLATE_ELEMENT)
-
-void HTMLTreeBuilder::processTemplateStartTag(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processTemplateStartTag(AtomicHTMLToken* token)
{
- m_tree.activeFormattingElements().appendMarker();
- m_tree.insertHTMLElement(&token);
+ m_tree.activeFormattingElements()->appendMarker();
+ m_tree.insertHTMLElement(token);
m_templateInsertionModes.append(InsertionMode::TemplateContents);
- m_insertionMode = InsertionMode::TemplateContents;
+ setInsertionMode(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(&endTemplate))
return false;
processEndOfFile(token);
return true;
}
-
#endif
bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup()
{
bool ignoreFakeEndTag = m_tree.currentIsRootNode();
#if ENABLE(TEMPLATE_ELEMENT)
- ignoreFakeEndTag = ignoreFakeEndTag || m_tree.currentNode().hasTagName(templateTag);
+ ignoreFakeEndTag = ignoreFakeEndTag || m_tree.currentNode()->hasTagName(templateTag);
#endif
if (ignoreFakeEndTag) {
@@ -951,60 +997,61 @@ bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup()
// FIXME: parse error
return false;
}
- m_tree.openElements().pop();
- m_insertionMode = InsertionMode::InTable;
+ m_tree.openElements()->pop();
+ setInsertionMode(InsertionMode::InTable);
return true;
}
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#close-the-cell
void HTMLTreeBuilder::closeTheCell()
{
- ASSERT(m_insertionMode == InsertionMode::InCell);
- if (m_tree.openElements().inTableScope(tdTag)) {
- ASSERT(!m_tree.openElements().inTableScope(thTag));
+ ASSERT(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(m_insertionMode == InsertionMode::InRow);
+ ASSERT(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);
- m_insertionMode = InsertionMode::InCaption;
+ ASSERT(token->type() == HTMLToken::StartTag);
+ if (token->name() == captionTag) {
+ m_tree.openElements()->popUntilTableScopeMarker();
+ m_tree.activeFormattingElements()->appendMarker();
+ m_tree.insertHTMLElement(token);
+ setInsertionMode(InsertionMode::InCaption);
return;
}
- if (token.name() == colgroupTag) {
- m_tree.openElements().popUntilTableScopeMarker();
- m_tree.insertHTMLElement(&token);
- m_insertionMode = InsertionMode::InColumnGroup;
+ if (token->name() == colgroupTag) {
+ m_tree.openElements()->popUntilTableScopeMarker();
+ m_tree.insertHTMLElement(token);
+ setInsertionMode(InsertionMode::InColumnGroup);
return;
}
- if (token.name() == colTag) {
+ if (token->name() == colTag) {
processFakeStartTag(colgroupTag);
- ASSERT(m_insertionMode == InsertionMode::InColumnGroup);
+ ASSERT(insertionMode() == InsertionMode::InColumnGroup);
processStartTag(token);
return;
}
- if (isTableBodyContextTag(token.name())) {
- m_tree.openElements().popUntilTableScopeMarker();
- m_tree.insertHTMLElement(&token);
- m_insertionMode = InsertionMode::InTableBody;
+ if (isTableBodyContextTag(token->name())) {
+ m_tree.openElements()->popUntilTableScopeMarker();
+ m_tree.insertHTMLElement(token);
+ setInsertionMode(InsertionMode::InTableBody);
return;
}
- if (isTableCellContextTag(token.name()) || token.name() == trTag) {
+ if (isTableCellContextTag(token->name())
+ || token->name() == trTag) {
processFakeStartTag(tbodyTag);
- ASSERT(m_insertionMode == InsertionMode::InTableBody);
+ ASSERT(insertionMode() == InsertionMode::InTableBody);
processStartTag(token);
return;
}
- if (token.name() == tableTag) {
+ if (token->name() == tableTag) {
parseError(token);
if (!processTableEndTagForInTable()) {
ASSERT(isParsingFragmentOrTemplateContents());
@@ -1013,29 +1060,29 @@ void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken& token)
processStartTag(token);
return;
}
- if (token.name() == styleTag || token.name() == scriptTag) {
+ if (token->name() == styleTag || token->name() == scriptTag) {
processStartTagForInHead(token);
return;
}
- if (token.name() == inputTag) {
- Attribute* typeAttribute = findAttribute(token.attributes(), typeAttr);
- if (typeAttribute && equalLettersIgnoringASCIICase(typeAttribute->value(), "hidden")) {
+ if (token->name() == inputTag) {
+ Attribute* typeAttribute = token->getAttributeItem(typeAttr);
+ if (typeAttribute && equalIgnoringCase(typeAttribute->value(), "hidden")) {
parseError(token);
- m_tree.insertSelfClosingHTMLElement(&token);
+ m_tree.insertSelfClosingHTMLElement(token);
return;
}
// Fall through to "anything else" case.
}
- if (token.name() == formTag) {
+ if (token->name() == formTag) {
parseError(token);
if (m_tree.form() && !isParsingTemplateContents())
return;
- m_tree.insertHTMLFormElement(&token, true);
- m_tree.openElements().pop();
+ m_tree.insertHTMLFormElement(token, true);
+ m_tree.openElements()->pop();
return;
}
#if ENABLE(TEMPLATE_ELEMENT)
- if (token.name() == templateTag) {
+ if (token->name() == templateTag) {
processTemplateStartTag(token);
return;
}
@@ -1045,94 +1092,98 @@ void HTMLTreeBuilder::processStartTagForInTable(AtomicHTMLToken& token)
processStartTagForInBody(token);
}
-void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::StartTag);
- switch (m_insertionMode) {
+ ASSERT(token->type() == HTMLToken::StartTag);
+ switch (insertionMode()) {
case InsertionMode::Initial:
+ ASSERT(insertionMode() == InsertionMode::Initial);
defaultForInitial();
- ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
FALLTHROUGH;
case InsertionMode::BeforeHTML:
- if (token.name() == htmlTag) {
- m_tree.insertHTMLHtmlStartTagBeforeHTML(&token);
- m_insertionMode = InsertionMode::BeforeHead;
+ ASSERT(insertionMode() == InsertionMode::BeforeHTML);
+ if (token->name() == htmlTag) {
+ m_tree.insertHTMLHtmlStartTagBeforeHTML(token);
+ setInsertionMode(InsertionMode::BeforeHead);
return;
}
defaultForBeforeHTML();
- ASSERT(m_insertionMode == InsertionMode::BeforeHead);
FALLTHROUGH;
case InsertionMode::BeforeHead:
- if (token.name() == htmlTag) {
+ ASSERT(insertionMode() == InsertionMode::BeforeHead);
+ if (token->name() == htmlTag) {
processHtmlStartTagForInBody(token);
return;
}
- if (token.name() == headTag) {
- m_tree.insertHTMLHeadElement(&token);
- m_insertionMode = InsertionMode::InHead;
+ if (token->name() == headTag) {
+ m_tree.insertHTMLHeadElement(token);
+ setInsertionMode(InsertionMode::InHead);
return;
}
defaultForBeforeHead();
- ASSERT(m_insertionMode == InsertionMode::InHead);
FALLTHROUGH;
case InsertionMode::InHead:
+ ASSERT(insertionMode() == InsertionMode::InHead);
if (processStartTagForInHead(token))
return;
defaultForInHead();
- ASSERT(m_insertionMode == InsertionMode::AfterHead);
FALLTHROUGH;
case InsertionMode::AfterHead:
- if (token.name() == htmlTag) {
+ ASSERT(insertionMode() == InsertionMode::AfterHead);
+ if (token->name() == htmlTag) {
processHtmlStartTagForInBody(token);
return;
}
- if (token.name() == bodyTag) {
+ if (token->name() == bodyTag) {
m_framesetOk = false;
- m_tree.insertHTMLBodyElement(&token);
- m_insertionMode = InsertionMode::InBody;
+ m_tree.insertHTMLBodyElement(token);
+ setInsertionMode(InsertionMode::InBody);
return;
}
- if (token.name() == framesetTag) {
- m_tree.insertHTMLElement(&token);
- m_insertionMode = InsertionMode::InFrameset;
+ if (token->name() == framesetTag) {
+ m_tree.insertHTMLElement(token);
+ setInsertionMode(InsertionMode::InFrameset);
return;
}
- if (token.name() == baseTag
- || token.name() == basefontTag
- || token.name() == bgsoundTag
- || token.name() == linkTag
- || token.name() == metaTag
- || token.name() == noframesTag
- || token.name() == scriptTag
- || token.name() == styleTag
+ if (token->name() == baseTag
+ || token->name() == basefontTag
+ || token->name() == bgsoundTag
+ || token->name() == linkTag
+ || token->name() == metaTag
+ || token->name() == noframesTag
+ || token->name() == scriptTag
+ || token->name() == styleTag
#if ENABLE(TEMPLATE_ELEMENT)
- || token.name() == templateTag
+ || token->name() == templateTag
#endif
- || token.name() == titleTag) {
+ || token->name() == titleTag) {
parseError(token);
- m_tree.openElements().pushHTMLHeadElement(m_tree.headStackItem());
+ ASSERT(m_tree.head());
+ m_tree.openElements()->pushHTMLHeadElement(m_tree.headStackItem());
processStartTagForInHead(token);
- m_tree.openElements().removeHTMLHeadElement(&m_tree.head());
+ m_tree.openElements()->removeHTMLHeadElement(m_tree.head());
return;
}
- if (token.name() == headTag) {
+ if (token->name() == headTag) {
parseError(token);
return;
}
defaultForAfterHead();
- ASSERT(m_insertionMode == InsertionMode::InBody);
FALLTHROUGH;
case InsertionMode::InBody:
+ ASSERT(insertionMode() == InsertionMode::InBody);
processStartTagForInBody(token);
break;
case InsertionMode::InTable:
+ ASSERT(insertionMode() == InsertionMode::InTable);
processStartTagForInTable(token);
break;
case InsertionMode::InCaption:
- if (isCaptionColOrColgroupTag(token.name())
- || isTableBodyContextTag(token.name())
- || isTableCellContextTag(token.name())
- || token.name() == trTag) {
+ ASSERT(insertionMode() == InsertionMode::InCaption);
+ if (isCaptionColOrColgroupTag(token->name())
+ || isTableBodyContextTag(token->name())
+ || isTableCellContextTag(token->name())
+ || token->name() == trTag) {
parseError(token);
if (!processCaptionEndTagForInCaption()) {
ASSERT(isParsingFragment());
@@ -1144,16 +1195,17 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
processStartTagForInBody(token);
break;
case InsertionMode::InColumnGroup:
- if (token.name() == htmlTag) {
+ ASSERT(insertionMode() == InsertionMode::InColumnGroup);
+ if (token->name() == htmlTag) {
processHtmlStartTagForInBody(token);
return;
}
- if (token.name() == colTag) {
- m_tree.insertSelfClosingHTMLElement(&token);
+ if (token->name() == colTag) {
+ m_tree.insertSelfClosingHTMLElement(token);
return;
}
#if ENABLE(TEMPLATE_ELEMENT)
- if (token.name() == templateTag) {
+ if (token->name() == templateTag) {
processTemplateStartTag(token);
return;
}
@@ -1165,62 +1217,65 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
processStartTag(token);
break;
case InsertionMode::InTableBody:
- if (token.name() == trTag) {
- m_tree.openElements().popUntilTableBodyScopeMarker(); // How is there ever anything to pop?
- m_tree.insertHTMLElement(&token);
- m_insertionMode = InsertionMode::InRow;
+ 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);
return;
}
- if (isTableCellContextTag(token.name())) {
+ if (isTableCellContextTag(token->name())) {
parseError(token);
processFakeStartTag(trTag);
- ASSERT(m_insertionMode == InsertionMode::InRow);
+ ASSERT(insertionMode() == InsertionMode::InRow);
processStartTag(token);
return;
}
- if (isCaptionColOrColgroupTag(token.name()) || isTableBodyContextTag(token.name())) {
+ if (isCaptionColOrColgroupTag(token->name()) || isTableBodyContextTag(token->name())) {
// FIXME: This is slow.
- if (!m_tree.openElements().inTableScope(tbodyTag) && !m_tree.openElements().inTableScope(theadTag) && !m_tree.openElements().inTableScope(tfootTag)) {
+ 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());
+ m_tree.openElements()->popUntilTableBodyScopeMarker();
+ ASSERT(isTableBodyContextTag(m_tree.currentStackItem()->localName()));
+ processFakeEndTag(m_tree.currentStackItem()->localName());
processStartTag(token);
return;
}
processStartTagForInTable(token);
break;
case InsertionMode::InRow:
- if (isTableCellContextTag(token.name())) {
- m_tree.openElements().popUntilTableRowScopeMarker();
- m_tree.insertHTMLElement(&token);
- m_insertionMode = InsertionMode::InCell;
- m_tree.activeFormattingElements().appendMarker();
+ ASSERT(insertionMode() == InsertionMode::InRow);
+ if (isTableCellContextTag(token->name())) {
+ m_tree.openElements()->popUntilTableRowScopeMarker();
+ m_tree.insertHTMLElement(token);
+ setInsertionMode(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(m_insertionMode == InsertionMode::InTableBody);
+ ASSERT(insertionMode() == InsertionMode::InTableBody);
processStartTag(token);
return;
}
processStartTagForInTable(token);
break;
case InsertionMode::InCell:
- if (isCaptionColOrColgroupTag(token.name())
- || isTableCellContextTag(token.name())
- || token.name() == trTag
- || isTableBodyContextTag(token.name())) {
+ ASSERT(insertionMode() == InsertionMode::InCell);
+ if (isCaptionColOrColgroupTag(token->name())
+ || isTableCellContextTag(token->name())
+ || token->name() == trTag
+ || isTableBodyContextTag(token->name())) {
// FIXME: This could be more efficient.
- if (!m_tree.openElements().inTableScope(tdTag) && !m_tree.openElements().inTableScope(thTag)) {
+ if (!m_tree.openElements()->inTableScope(tdTag) && !m_tree.openElements()->inTableScope(thTag)) {
ASSERT(isParsingFragment());
parseError(token);
return;
@@ -1233,29 +1288,31 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
break;
case InsertionMode::AfterBody:
case InsertionMode::AfterAfterBody:
- if (token.name() == htmlTag) {
+ ASSERT(insertionMode() == InsertionMode::AfterBody || insertionMode() == InsertionMode::AfterAfterBody);
+ if (token->name() == htmlTag) {
processHtmlStartTagForInBody(token);
return;
}
- m_insertionMode = InsertionMode::InBody;
+ setInsertionMode(InsertionMode::InBody);
processStartTag(token);
break;
case InsertionMode::InHeadNoscript:
- if (token.name() == htmlTag) {
+ 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) {
+ if (token->name() == basefontTag
+ || token->name() == bgsoundTag
+ || token->name() == linkTag
+ || token->name() == metaTag
+ || token->name() == noframesTag
+ || token->name() == styleTag) {
bool didProcess = processStartTagForInHead(token);
ASSERT_UNUSED(didProcess, didProcess);
return;
}
- if (token.name() == htmlTag || token.name() == noscriptTag) {
+ if (token->name() == htmlTag || token->name() == noscriptTag) {
parseError(token);
return;
}
@@ -1263,24 +1320,25 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
processToken(token);
break;
case InsertionMode::InFrameset:
- if (token.name() == htmlTag) {
+ ASSERT(insertionMode() == InsertionMode::InFrameset);
+ if (token->name() == htmlTag) {
processHtmlStartTagForInBody(token);
return;
}
- if (token.name() == framesetTag) {
- m_tree.insertHTMLElement(&token);
+ if (token->name() == framesetTag) {
+ m_tree.insertHTMLElement(token);
return;
}
- if (token.name() == frameTag) {
- m_tree.insertSelfClosingHTMLElement(&token);
+ if (token->name() == frameTag) {
+ m_tree.insertSelfClosingHTMLElement(token);
return;
}
- if (token.name() == noframesTag) {
+ if (token->name() == noframesTag) {
processStartTagForInHead(token);
return;
}
#if ENABLE(TEMPLATE_ELEMENT)
- if (token.name() == templateTag) {
+ if (token->name() == templateTag) {
processTemplateStartTag(token);
return;
}
@@ -1289,78 +1347,83 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
break;
case InsertionMode::AfterFrameset:
case InsertionMode::AfterAfterFrameset:
- if (token.name() == htmlTag) {
+ ASSERT(insertionMode() == InsertionMode::AfterFrameset || insertionMode() == InsertionMode::AfterAfterFrameset);
+ if (token->name() == htmlTag) {
processHtmlStartTagForInBody(token);
return;
}
- if (token.name() == noframesTag) {
+ if (token->name() == noframesTag) {
processStartTagForInHead(token);
return;
}
parseError(token);
break;
case InsertionMode::InSelectInTable:
- if (token.name() == captionTag
- || token.name() == tableTag
- || isTableBodyContextTag(token.name())
- || token.name() == trTag
- || isTableCellContextTag(token.name())) {
+ ASSERT(insertionMode() == InsertionMode::InSelectInTable);
+ if (token->name() == captionTag
+ || token->name() == tableTag
+ || isTableBodyContextTag(token->name())
+ || token->name() == trTag
+ || isTableCellContextTag(token->name())) {
parseError(token);
AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
- processEndTag(endSelect);
+ processEndTag(&endSelect);
processStartTag(token);
return;
}
FALLTHROUGH;
case InsertionMode::InSelect:
- if (token.name() == htmlTag) {
+ ASSERT(insertionMode() == InsertionMode::InSelect || insertionMode() == InsertionMode::InSelectInTable);
+ if (token->name() == htmlTag) {
processHtmlStartTagForInBody(token);
return;
}
- if (token.name() == optionTag) {
- if (is<HTMLOptionElement>(m_tree.currentStackItem().node())) {
+ if (token->name() == optionTag) {
+ if (isHTMLOptionElement(m_tree.currentStackItem()->node())) {
AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
- processEndTag(endOption);
+ processEndTag(&endOption);
}
- m_tree.insertHTMLElement(&token);
+ m_tree.insertHTMLElement(token);
return;
}
- if (token.name() == optgroupTag) {
- if (is<HTMLOptionElement>(m_tree.currentStackItem().node())) {
+ if (token->name() == optgroupTag) {
+ if (isHTMLOptionElement(m_tree.currentStackItem()->node())) {
AtomicHTMLToken endOption(HTMLToken::EndTag, optionTag.localName());
- processEndTag(endOption);
+ processEndTag(&endOption);
}
- if (is<HTMLOptGroupElement>(m_tree.currentStackItem().node())) {
+ if (isHTMLOptGroupElement(m_tree.currentStackItem()->node())) {
AtomicHTMLToken endOptgroup(HTMLToken::EndTag, optgroupTag.localName());
- processEndTag(endOptgroup);
+ processEndTag(&endOptgroup);
}
- m_tree.insertHTMLElement(&token);
+ m_tree.insertHTMLElement(token);
return;
}
- if (token.name() == selectTag) {
+ if (token->name() == selectTag) {
parseError(token);
AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
- processEndTag(endSelect);
+ processEndTag(&endSelect);
return;
}
- if (token.name() == inputTag || token.name() == keygenTag || token.name() == textareaTag) {
+ if (token->name() == inputTag
+ || token->name() == keygenTag
+ || token->name() == textareaTag) {
parseError(token);
- if (!m_tree.openElements().inSelectScope(selectTag)) {
+ if (!m_tree.openElements()->inSelectScope(selectTag)) {
ASSERT(isParsingFragment());
return;
}
AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
- processEndTag(endSelect);
+ processEndTag(&endSelect);
processStartTag(token);
return;
}
- if (token.name() == scriptTag) {
+ if (token->name() == scriptTag) {
bool didProcess = processStartTagForInHead(token);
ASSERT_UNUSED(didProcess, didProcess);
return;
}
#if ENABLE(TEMPLATE_ELEMENT)
- if (token.name() == templateTag) {
+ if (token->name() == templateTag) {
processTemplateStartTag(token);
return;
}
@@ -1373,31 +1436,31 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
case InsertionMode::Text:
ASSERT_NOT_REACHED();
break;
-#if ENABLE(TEMPLATE_ELEMENT)
case InsertionMode::TemplateContents:
- if (token.name() == templateTag) {
+#if ENABLE(TEMPLATE_ELEMENT)
+ if (token->name() == templateTag) {
processTemplateStartTag(token);
return;
}
- if (token.name() == linkTag
- || token.name() == scriptTag
- || token.name() == styleTag
- || token.name() == metaTag) {
+ if (token->name() == linkTag
+ || token->name() == scriptTag
+ || token->name() == styleTag
+ || token->name() == metaTag) {
processStartTagForInHead(token);
return;
}
InsertionMode insertionMode = InsertionMode::TemplateContents;
- if (token.name() == frameTag)
+ if (token->name() == frameTag)
insertionMode = InsertionMode::InFrameset;
- else if (token.name() == colTag)
+ else if (token->name() == colTag)
insertionMode = InsertionMode::InColumnGroup;
- else if (isCaptionColOrColgroupTag(token.name()) || isTableBodyContextTag(token.name()))
+ else if (isCaptionColOrColgroupTag(token->name()) || isTableBodyContextTag(token->name()))
insertionMode = InsertionMode::InTable;
- else if (token.name() == trTag)
+ else if (token->name() == trTag)
insertionMode = InsertionMode::InTableBody;
- else if (isTableCellContextTag(token.name()))
+ else if (isTableCellContextTag(token->name()))
insertionMode = InsertionMode::InRow;
else
insertionMode = InsertionMode::InBody;
@@ -1405,60 +1468,64 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
ASSERT(insertionMode != InsertionMode::TemplateContents);
ASSERT(m_templateInsertionModes.last() == InsertionMode::TemplateContents);
m_templateInsertionModes.last() = insertionMode;
- m_insertionMode = insertionMode;
+ setInsertionMode(insertionMode);
processStartTag(token);
- break;
+#else
+ ASSERT_NOT_REACHED();
#endif
+ 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(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.
- m_insertionMode = InsertionMode::AfterBody;
+ setInsertionMode(InsertionMode::AfterBody);
return true;
}
-void HTMLTreeBuilder::processAnyOtherEndTagForInBody(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processAnyOtherEndTagForInBody(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::EndTag);
- for (auto* record = &m_tree.openElements().topRecord(); ; record = record->next()) {
- HTMLStackItem& item = record->stackItem();
- if (item.matchesHTMLTag(token.name())) {
- m_tree.generateImpliedEndTagsWithExclusion(token.name());
- if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
+ 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()))
parseError(token);
- m_tree.openElements().popUntilPopped(&item.element());
+ m_tree.openElements()->popUntilPopped(item->element());
return;
}
- if (isSpecialNode(item)) {
+ if (item->isSpecialNode()) {
parseError(token);
return;
}
+ record = record->next();
}
}
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#parsing-main-inbody
-void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken& token)
+void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token)
{
// The adoption agency algorithm is N^2. We limit the number of iterations
// to stop from hanging the whole browser. This limit is specified in the
@@ -1470,43 +1537,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);
// 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
- auto* formattingElementRecord = m_tree.openElements().find(formattingElement);
+ HTMLElementStack::ElementRecord* 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.
- auto* furthestBlock = m_tree.openElements().furthestBlockForFormattingElement(formattingElement);
+ HTMLElementStack::ElementRecord* 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));
- Ref<HTMLStackItem> commonAncestor = formattingElementRecord->next()->stackItem();
+ RefPtr<HTMLStackItem> commonAncestor = formattingElementRecord->next()->stackItem();
// 8.
- HTMLFormattingElementList::Bookmark bookmark = m_tree.activeFormattingElements().bookmarkFor(formattingElement);
+ HTMLFormattingElementList::Bookmark bookmark = m_tree.activeFormattingElements()->bookmarkFor(formattingElement);
// 9.
- auto* node = furthestBlock;
- auto* nextNode = node->next();
- auto* lastNode = furthestBlock;
+ HTMLElementStack::ElementRecord* node = furthestBlock;
+ HTMLElementStack::ElementRecord* nextNode = node->next();
+ HTMLElementStack::ElementRecord* lastNode = furthestBlock;
// 9.1, 9.2, 9.3 and 9.11 are covered by the for() loop.
for (int i = 0; i < innerIterationLimit; ++i) {
// 9.4
@@ -1514,8 +1581,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;
}
@@ -1523,10 +1590,10 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken& token)
if (node == formattingElementRecord)
break;
// 9.7
- RefPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(&node->stackItem());
+ RefPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(node->stackItem().get());
- HTMLFormattingElementList::Entry* nodeEntry = m_tree.activeFormattingElements().find(&node->element());
- nodeEntry->replaceElement(newItem.copyRef());
+ HTMLFormattingElementList::Entry* nodeEntry = m_tree.activeFormattingElements()->find(node->element());
+ nodeEntry->replaceElement(newItem);
node->replaceElement(newItem.release());
// 9.8
@@ -1538,18 +1605,18 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken& token)
lastNode = node;
}
// 10.
- m_tree.insertAlreadyParsedChild(commonAncestor.get(), *lastNode);
+ m_tree.insertAlreadyParsedChild(*commonAncestor, *lastNode);
// 11.
- RefPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(&formattingElementRecord->stackItem());
+ RefPtr<HTMLStackItem> newItem = m_tree.createElementFromSavedToken(formattingElementRecord->stackItem().get());
// 12.
m_tree.takeAllChildren(*newItem, *furthestBlock);
// 13.
m_tree.reparent(*furthestBlock, *newItem);
// 14.
- m_tree.activeFormattingElements().swapTo(formattingElement, newItem, bookmark);
+ m_tree.activeFormattingElements()->swapTo(formattingElement, newItem, bookmark);
// 15.
- m_tree.openElements().remove(formattingElement);
- m_tree.openElements().insertAbove(newItem, furthestBlock);
+ m_tree.openElements()->remove(formattingElement);
+ m_tree.openElements()->insertAbove(newItem, furthestBlock);
}
}
@@ -1557,9 +1624,10 @@ void HTMLTreeBuilder::resetInsertionModeAppropriately()
{
// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#reset-the-insertion-mode-appropriately
bool last = false;
- for (auto* record = &m_tree.openElements().topRecord(); ; record = record->next()) {
- HTMLStackItem* item = &record->stackItem();
- if (&item->node() == &m_tree.openElements().rootNode()) {
+ HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord();
+ while (1) {
+ RefPtr<HTMLStackItem> item = nodeRecord->stackItem();
+ if (item->node() == m_tree.openElements()->rootNode()) {
last = true;
#if ENABLE(TEMPLATE_ELEMENT)
bool shouldCreateItem = isParsingFragment();
@@ -1568,193 +1636,167 @@ void HTMLTreeBuilder::resetInsertionModeAppropriately()
bool shouldCreateItem = true;
#endif
if (shouldCreateItem)
- item = &m_fragmentContext.contextElementStackItem();
+ item = HTMLStackItem::create(m_fragmentContext.contextElement(), HTMLStackItem::ItemForContextElement);
}
-
#if ENABLE(TEMPLATE_ELEMENT)
- if (item->hasTagName(templateTag)) {
- m_insertionMode = m_templateInsertionModes.last();
- return;
- }
+ if (item->hasTagName(templateTag))
+ return setInsertionMode(m_templateInsertionModes.last());
#endif
if (item->hasTagName(selectTag)) {
#if ENABLE(TEMPLATE_ELEMENT)
if (!last) {
- while (&item->node() != &m_tree.openElements().rootNode() && !item->hasTagName(templateTag)) {
- record = record->next();
- item = &record->stackItem();
- if (is<HTMLTableElement>(item->node())) {
- m_insertionMode = InsertionMode::InSelectInTable;
- return;
- }
+ while (item->node() != m_tree.openElements()->rootNode() && !item->hasTagName(templateTag)) {
+ nodeRecord = nodeRecord->next();
+ item = nodeRecord->stackItem();
+ if (isHTMLTableElement(item->node()))
+ return setInsertionMode(InsertionMode::InSelectInTable);
}
}
#endif
- 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;
- }
+ 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);
if (item->hasTagName(colgroupTag)) {
- m_insertionMode = InsertionMode::InColumnGroup;
- return;
- }
- if (is<HTMLTableElement>(item->node())) {
- m_insertionMode = InsertionMode::InTable;
- return;
+ return setInsertionMode(InsertionMode::InColumnGroup);
}
+ 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()) {
- m_insertionMode = InsertionMode::InHead;
- return;
- }
+ if (!m_fragmentContext.fragment() || m_fragmentContext.contextElement() != item->node())
+ return setInsertionMode(InsertionMode::InHead);
#endif
- m_insertionMode = InsertionMode::InBody;
- return;
- }
- if (item->hasTagName(bodyTag)) {
- m_insertionMode = InsertionMode::InBody;
- return;
+ return setInsertionMode(InsertionMode::InBody);
}
+ if (item->hasTagName(bodyTag))
+ return setInsertionMode(InsertionMode::InBody);
if (item->hasTagName(framesetTag)) {
- m_insertionMode = InsertionMode::InFrameset;
- return;
+ return setInsertionMode(InsertionMode::InFrameset);
}
if (item->hasTagName(htmlTag)) {
- if (m_tree.headStackItem()) {
- m_insertionMode = InsertionMode::AfterHead;
- return;
- }
+ if (m_tree.headStackItem())
+ return setInsertionMode(InsertionMode::AfterHead);
ASSERT(isParsingFragment());
- m_insertionMode = InsertionMode::BeforeHead;
- return;
+ return setInsertionMode(InsertionMode::BeforeHead);
}
if (last) {
ASSERT(isParsingFragment());
- m_insertionMode = InsertionMode::InBody;
- return;
+ return setInsertionMode(InsertionMode::InBody);
}
+ 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();
- m_insertionMode = InsertionMode::InTable;
+ m_tree.openElements()->popUntilTableBodyScopeMarker();
+ m_tree.openElements()->pop();
+ setInsertionMode(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());
+ m_tree.openElements()->popUntilTableBodyScopeMarker();
+ ASSERT(isTableBodyContextTag(m_tree.currentStackItem()->localName()));
+ processFakeEndTag(m_tree.currentStackItem()->localName());
processEndTag(token);
return;
}
- if (token.name() == bodyTag
- || isCaptionColOrColgroupTag(token.name())
- || token.name() == htmlTag
- || isTableCellContextTag(token.name())
- || token.name() == trTag) {
+ if (token->name() == bodyTag
+ || isCaptionColOrColgroupTag(token->name())
+ || token->name() == htmlTag
+ || isTableCellContextTag(token->name())
+ || token->name() == trTag) {
parseError(token);
return;
}
processEndTagForInTable(token);
}
-void HTMLTreeBuilder::processEndTagForInRow(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processEndTagForInRow(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::EndTag);
- if (token.name() == trTag) {
+ ASSERT(token->type() == HTMLToken::EndTag);
+ if (token->name() == trTag) {
processTrEndTagForInRow();
return;
}
- if (token.name() == tableTag) {
+ if (token->name() == tableTag) {
if (!processTrEndTagForInRow()) {
ASSERT(isParsingFragmentOrTemplateContents());
return;
}
- ASSERT(m_insertionMode == InsertionMode::InTableBody);
+ ASSERT(insertionMode() == InsertionMode::InTableBody);
processEndTag(token);
return;
}
- if (isTableBodyContextTag(token.name())) {
- if (!m_tree.openElements().inTableScope(token.name())) {
+ if (isTableBodyContextTag(token->name())) {
+ if (!m_tree.openElements()->inTableScope(token->name())) {
parseError(token);
return;
}
processFakeEndTag(trTag);
- ASSERT(m_insertionMode == InsertionMode::InTableBody);
+ ASSERT(insertionMode() == InsertionMode::InTableBody);
processEndTag(token);
return;
}
- if (token.name() == bodyTag
- || isCaptionColOrColgroupTag(token.name())
- || token.name() == htmlTag
- || isTableCellContextTag(token.name())) {
+ if (token->name() == bodyTag
+ || isCaptionColOrColgroupTag(token->name())
+ || token->name() == htmlTag
+ || isTableCellContextTag(token->name())) {
parseError(token);
return;
}
processEndTagForInTable(token);
}
-void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::EndTag);
- if (isTableCellContextTag(token.name())) {
- if (!m_tree.openElements().inTableScope(token.name())) {
+ ASSERT(token->type() == HTMLToken::EndTag);
+ if (isTableCellContextTag(token->name())) {
+ if (!m_tree.openElements()->inTableScope(token->name())) {
parseError(token);
return;
}
m_tree.generateImpliedEndTags();
- if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
+ if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
parseError(token);
- m_tree.openElements().popUntilPopped(token.name());
- m_tree.activeFormattingElements().clearToLastMarker();
- m_insertionMode = InsertionMode::InRow;
+ m_tree.openElements()->popUntilPopped(token->name());
+ m_tree.activeFormattingElements()->clearToLastMarker();
+ setInsertionMode(InsertionMode::InRow);
return;
}
- if (token.name() == bodyTag
- || isCaptionColOrColgroupTag(token.name())
- || token.name() == htmlTag) {
+ if (token->name() == bodyTag
+ || isCaptionColOrColgroupTag(token->name())
+ || token->name() == htmlTag) {
parseError(token);
return;
}
- if (token.name() == tableTag
- || token.name() == trTag
- || isTableBodyContextTag(token.name())) {
- if (!m_tree.openElements().inTableScope(token.name())) {
+ if (token->name() == tableTag
+ || token->name() == trTag
+ || isTableBodyContextTag(token->name())) {
+ if (!m_tree.openElements()->inTableScope(token->name())) {
#if ENABLE(TEMPLATE_ELEMENT)
- ASSERT(isTableBodyContextTag(token.name()) || m_tree.openElements().inTableScope(templateTag) || isParsingFragment());
+ ASSERT(isTableBodyContextTag(token->name()) || m_tree.openElements()->inTableScope(templateTag) || isParsingFragment());
#else
- ASSERT(isTableBodyContextTag(token.name()) || isParsingFragment());
+ ASSERT(isTableBodyContextTag(token->name()) || isParsingFragment());
#endif
parseError(token);
return;
@@ -1766,146 +1808,149 @@ void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken& token)
processEndTagForInBody(token);
}
-void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::EndTag);
- if (token.name() == bodyTag) {
+ ASSERT(token->type() == HTMLToken::EndTag);
+ if (token->name() == bodyTag) {
processBodyEndTagForInBody(token);
return;
}
- if (token.name() == htmlTag) {
+ if (token->name() == htmlTag) {
AtomicHTMLToken endBody(HTMLToken::EndTag, bodyTag.localName());
- if (processBodyEndTagForInBody(endBody))
+ if (processBodyEndTagForInBody(&endBody))
processEndTag(token);
return;
}
- if (token.name() == addressTag
- || token.name() == articleTag
- || token.name() == asideTag
- || token.name() == blockquoteTag
- || token.name() == buttonTag
- || token.name() == centerTag
- || token.name() == detailsTag
- || token.name() == dirTag
- || token.name() == divTag
- || token.name() == dlTag
- || token.name() == fieldsetTag
- || token.name() == figcaptionTag
- || token.name() == figureTag
- || token.name() == footerTag
- || token.name() == headerTag
- || token.name() == hgroupTag
- || token.name() == listingTag
- || token.name() == mainTag
- || token.name() == menuTag
- || token.name() == navTag
- || token.name() == olTag
- || token.name() == preTag
- || token.name() == sectionTag
- || token.name() == summaryTag
- || token.name() == ulTag) {
- if (!m_tree.openElements().inScope(token.name())) {
+ if (token->name() == addressTag
+ || token->name() == articleTag
+ || token->name() == asideTag
+ || token->name() == blockquoteTag
+ || token->name() == buttonTag
+ || token->name() == centerTag
+ || token->name() == detailsTag
+ || token->name() == dirTag
+ || token->name() == divTag
+ || token->name() == dlTag
+ || token->name() == fieldsetTag
+ || token->name() == figcaptionTag
+ || token->name() == figureTag
+ || token->name() == footerTag
+ || token->name() == headerTag
+ || token->name() == hgroupTag
+ || token->name() == listingTag
+ || token->name() == mainTag
+ || token->name() == menuTag
+ || token->name() == navTag
+ || token->name() == olTag
+ || token->name() == preTag
+ || token->name() == sectionTag
+ || token->name() == summaryTag
+ || token->name() == ulTag) {
+ if (!m_tree.openElements()->inScope(token->name())) {
parseError(token);
return;
}
m_tree.generateImpliedEndTags();
- if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
+ if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
parseError(token);
- m_tree.openElements().popUntilPopped(token.name());
+ m_tree.openElements()->popUntilPopped(token->name());
return;
}
- if (token.name() == formTag) {
+ if (token->name() == formTag) {
if (!isParsingTemplateContents()) {
RefPtr<Element> node = m_tree.takeForm();
- if (!node || !m_tree.openElements().inScope(node.get())) {
+ if (!node || !m_tree.openElements()->inScope(node.get())) {
parseError(token);
return;
}
m_tree.generateImpliedEndTags();
- if (&m_tree.currentNode() != node.get())
+ if (m_tree.currentNode() != node.get())
parseError(token);
- m_tree.openElements().remove(node.get());
+ m_tree.openElements()->remove(node.get());
} else {
- if (!m_tree.openElements().inScope(token.name())) {
+ if (!m_tree.openElements()->inScope(token->name())) {
parseError(token);
return;
}
m_tree.generateImpliedEndTags();
- if (!m_tree.currentNode().hasTagName(formTag))
+ if (!m_tree.currentNode()->hasTagName(formTag))
parseError(token);
- m_tree.openElements().popUntilPopped(token.name());
+ m_tree.openElements()->popUntilPopped(token->name());
}
}
- if (token.name() == pTag) {
- if (!m_tree.openElements().inButtonScope(token.name())) {
+ if (token->name() == pTag) {
+ if (!m_tree.openElements()->inButtonScope(token->name())) {
parseError(token);
processFakeStartTag(pTag);
- ASSERT(m_tree.openElements().inScope(token.name()));
+ ASSERT(m_tree.openElements()->inScope(token->name()));
processEndTag(token);
return;
}
- m_tree.generateImpliedEndTagsWithExclusion(token.name());
- if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
+ m_tree.generateImpliedEndTagsWithExclusion(token->name());
+ if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
parseError(token);
- m_tree.openElements().popUntilPopped(token.name());
+ m_tree.openElements()->popUntilPopped(token->name());
return;
}
- if (token.name() == liTag) {
- if (!m_tree.openElements().inListItemScope(token.name())) {
+ if (token->name() == liTag) {
+ if (!m_tree.openElements()->inListItemScope(token->name())) {
parseError(token);
return;
}
- m_tree.generateImpliedEndTagsWithExclusion(token.name());
- if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
+ m_tree.generateImpliedEndTagsWithExclusion(token->name());
+ if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
parseError(token);
- m_tree.openElements().popUntilPopped(token.name());
+ m_tree.openElements()->popUntilPopped(token->name());
return;
}
- if (token.name() == ddTag || token.name() == dtTag) {
- if (!m_tree.openElements().inScope(token.name())) {
+ if (token->name() == ddTag
+ || token->name() == dtTag) {
+ if (!m_tree.openElements()->inScope(token->name())) {
parseError(token);
return;
}
- m_tree.generateImpliedEndTagsWithExclusion(token.name());
- if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
+ m_tree.generateImpliedEndTagsWithExclusion(token->name());
+ if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
parseError(token);
- m_tree.openElements().popUntilPopped(token.name());
+ m_tree.openElements()->popUntilPopped(token->name());
return;
}
- if (isNumberedHeaderTag(token.name())) {
- if (!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 (HTMLConstructionSite::isFormattingTag(token.name())) {
+ if (isFormattingTag(token->name())) {
callTheAdoptionAgency(token);
return;
}
- if (token.name() == appletTag || token.name() == marqueeTag || token.name() == objectTag) {
- if (!m_tree.openElements().inScope(token.name())) {
+ if (token->name() == appletTag
+ || token->name() == marqueeTag
+ || token->name() == objectTag) {
+ if (!m_tree.openElements()->inScope(token->name())) {
parseError(token);
return;
}
m_tree.generateImpliedEndTags();
- if (!m_tree.currentStackItem().matchesHTMLTag(token.name()))
+ if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
parseError(token);
- m_tree.openElements().popUntilPopped(token.name());
- m_tree.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) {
+ if (token->name() == templateTag) {
processTemplateEndTag(token);
return;
}
@@ -1915,58 +1960,58 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken& 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();
- m_insertionMode = InsertionMode::InTable;
+ // FIXME: parse error if (!m_tree.currentStackItem()->hasTagName(captionTag))
+ m_tree.openElements()->popUntilPopped(captionTag.localName());
+ m_tree.activeFormattingElements()->clearToLastMarker();
+ setInsertionMode(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();
- m_insertionMode = InsertionMode::InTableBody;
+ m_tree.openElements()->popUntilTableRowScopeMarker();
+ ASSERT(m_tree.currentStackItem()->hasTagName(trTag));
+ m_tree.openElements()->pop();
+ setInsertionMode(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;
}
@@ -1976,72 +2021,75 @@ void HTMLTreeBuilder::processEndTagForInTable(AtomicHTMLToken& token)
processEndTagForInBody(token);
}
-void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::EndTag);
- switch (m_insertionMode) {
+ ASSERT(token->type() == HTMLToken::EndTag);
+ switch (insertionMode()) {
case InsertionMode::Initial:
+ ASSERT(insertionMode() == InsertionMode::Initial);
defaultForInitial();
- ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
FALLTHROUGH;
case InsertionMode::BeforeHTML:
- if (token.name() != headTag && token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
+ ASSERT(insertionMode() == InsertionMode::BeforeHTML);
+ if (token->name() != headTag && token->name() != bodyTag && token->name() != htmlTag && token->name() != brTag) {
parseError(token);
return;
}
defaultForBeforeHTML();
- ASSERT(m_insertionMode == InsertionMode::BeforeHead);
FALLTHROUGH;
case InsertionMode::BeforeHead:
- if (token.name() != headTag && token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
+ ASSERT(insertionMode() == InsertionMode::BeforeHead);
+ if (token->name() != headTag && token->name() != bodyTag && token->name() != htmlTag && token->name() != brTag) {
parseError(token);
return;
}
defaultForBeforeHead();
- ASSERT(m_insertionMode == InsertionMode::InHead);
FALLTHROUGH;
case InsertionMode::InHead:
+ ASSERT(insertionMode() == InsertionMode::InHead);
// FIXME: This case should be broken out into processEndTagForInHead,
// because other end tag cases now refer to it ("process the token for using the rules of the "in head" insertion mode").
// but because the logic falls through to InsertionMode::AfterHead, that gets a little messy.
#if ENABLE(TEMPLATE_ELEMENT)
- if (token.name() == templateTag) {
+ if (token->name() == templateTag) {
processTemplateEndTag(token);
return;
}
#endif
- if (token.name() == headTag) {
- m_tree.openElements().popHTMLHeadElement();
- m_insertionMode = InsertionMode::AfterHead;
+ if (token->name() == headTag) {
+ m_tree.openElements()->popHTMLHeadElement();
+ setInsertionMode(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:
- if (token.name() != bodyTag && token.name() != htmlTag && token.name() != brTag) {
+ ASSERT(insertionMode() == InsertionMode::AfterHead);
+ if (token->name() != bodyTag && token->name() != htmlTag && token->name() != brTag) {
parseError(token);
return;
}
defaultForAfterHead();
- ASSERT(m_insertionMode == InsertionMode::InBody);
FALLTHROUGH;
case InsertionMode::InBody:
+ ASSERT(insertionMode() == InsertionMode::InBody);
processEndTagForInBody(token);
break;
case InsertionMode::InTable:
+ ASSERT(insertionMode() == InsertionMode::InTable);
processEndTagForInTable(token);
break;
case InsertionMode::InCaption:
- if (token.name() == captionTag) {
+ ASSERT(insertionMode() == InsertionMode::InCaption);
+ if (token->name() == captionTag) {
processCaptionEndTagForInCaption();
return;
}
- if (token.name() == tableTag) {
+ if (token->name() == tableTag) {
parseError(token);
if (!processCaptionEndTagForInCaption()) {
ASSERT(isParsingFragment());
@@ -2050,29 +2098,30 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
processEndTag(token);
return;
}
- if (token.name() == bodyTag
- || token.name() == colTag
- || token.name() == colgroupTag
- || token.name() == htmlTag
- || isTableBodyContextTag(token.name())
- || isTableCellContextTag(token.name())
- || token.name() == trTag) {
+ if (token->name() == bodyTag
+ || token->name() == colTag
+ || token->name() == colgroupTag
+ || token->name() == htmlTag
+ || isTableBodyContextTag(token->name())
+ || isTableCellContextTag(token->name())
+ || token->name() == trTag) {
parseError(token);
return;
}
processEndTagForInBody(token);
break;
case InsertionMode::InColumnGroup:
- if (token.name() == colgroupTag) {
+ ASSERT(insertionMode() == InsertionMode::InColumnGroup);
+ if (token->name() == colgroupTag) {
processColgroupEndTagForInColumnGroup();
return;
}
- if (token.name() == colTag) {
+ if (token->name() == colTag) {
parseError(token);
return;
}
#if ENABLE(TEMPLATE_ELEMENT)
- if (token.name() == templateTag) {
+ if (token->name() == templateTag) {
processTemplateEndTag(token);
return;
}
@@ -2084,39 +2133,44 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
processEndTag(token);
break;
case InsertionMode::InRow:
+ ASSERT(insertionMode() == InsertionMode::InRow);
processEndTagForInRow(token);
break;
case InsertionMode::InCell:
+ ASSERT(insertionMode() == InsertionMode::InCell);
processEndTagForInCell(token);
break;
case InsertionMode::InTableBody:
+ ASSERT(insertionMode() == InsertionMode::InTableBody);
processEndTagForInTableBody(token);
break;
case InsertionMode::AfterBody:
- if (token.name() == htmlTag) {
+ ASSERT(insertionMode() == InsertionMode::AfterBody);
+ if (token->name() == htmlTag) {
if (isParsingFragment()) {
parseError(token);
return;
}
- m_insertionMode = InsertionMode::AfterAfterBody;
+ setInsertionMode(InsertionMode::AfterAfterBody);
return;
}
FALLTHROUGH;
case InsertionMode::AfterAfterBody:
- ASSERT(m_insertionMode == InsertionMode::AfterBody || m_insertionMode == InsertionMode::AfterAfterBody);
+ ASSERT(insertionMode() == InsertionMode::AfterBody || insertionMode() == InsertionMode::AfterAfterBody);
parseError(token);
- m_insertionMode = InsertionMode::InBody;
+ setInsertionMode(InsertionMode::InBody);
processEndTag(token);
break;
case InsertionMode::InHeadNoscript:
- if (token.name() == noscriptTag) {
- ASSERT(m_tree.currentStackItem().hasTagName(noscriptTag));
- m_tree.openElements().pop();
- ASSERT(m_tree.currentStackItem().hasTagName(headTag));
- m_insertionMode = InsertionMode::InHead;
+ 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);
return;
}
- if (token.name() != brTag) {
+ if (token->name() != brTag) {
parseError(token);
return;
}
@@ -2124,105 +2178,110 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
processToken(token);
break;
case InsertionMode::Text:
- if (token.name() == scriptTag) {
+ if (token->name() == scriptTag) {
// Pause ourselves so that parsing stops until the script can be processed by the caller.
- ASSERT(m_tree.currentStackItem().hasTagName(scriptTag));
+ ASSERT(m_tree.currentStackItem()->hasTagName(scriptTag));
if (scriptingContentIsAllowed(m_tree.parserContentPolicy()))
- m_scriptToProcess = &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();
+ 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);
+ }
return;
}
- m_tree.openElements().pop();
- m_insertionMode = m_originalInsertionMode;
+ m_tree.openElements()->pop();
+ setInsertionMode(m_originalInsertionMode);
break;
case InsertionMode::InFrameset:
- if (token.name() == framesetTag) {
+ ASSERT(insertionMode() == InsertionMode::InFrameset);
+ if (token->name() == framesetTag) {
bool ignoreFramesetForFragmentParsing = m_tree.currentIsRootNode();
#if ENABLE(TEMPLATE_ELEMENT)
- ignoreFramesetForFragmentParsing = ignoreFramesetForFragmentParsing || m_tree.openElements().hasTemplateInHTMLScope();
+ ignoreFramesetForFragmentParsing = ignoreFramesetForFragmentParsing || m_tree.openElements()->hasTemplateInHTMLScope();
#endif
if (ignoreFramesetForFragmentParsing) {
ASSERT(isParsingFragmentOrTemplateContents());
parseError(token);
return;
}
- m_tree.openElements().pop();
- if (!isParsingFragment() && !m_tree.currentStackItem().hasTagName(framesetTag))
- m_insertionMode = InsertionMode::AfterFrameset;
+ m_tree.openElements()->pop();
+ if (!isParsingFragment() && !m_tree.currentStackItem()->hasTagName(framesetTag))
+ setInsertionMode(InsertionMode::AfterFrameset);
return;
}
#if ENABLE(TEMPLATE_ELEMENT)
- if (token.name() == templateTag) {
+ if (token->name() == templateTag) {
processTemplateEndTag(token);
return;
}
#endif
break;
case InsertionMode::AfterFrameset:
- if (token.name() == htmlTag) {
- m_insertionMode = InsertionMode::AfterAfterFrameset;
+ ASSERT(insertionMode() == InsertionMode::AfterFrameset);
+ if (token->name() == htmlTag) {
+ setInsertionMode(InsertionMode::AfterAfterFrameset);
return;
}
FALLTHROUGH;
case InsertionMode::AfterAfterFrameset:
- ASSERT(m_insertionMode == InsertionMode::AfterFrameset || m_insertionMode == InsertionMode::AfterAfterFrameset);
+ ASSERT(insertionMode() == InsertionMode::AfterFrameset || insertionMode() == InsertionMode::AfterAfterFrameset);
parseError(token);
break;
case InsertionMode::InSelectInTable:
- if (token.name() == captionTag
- || token.name() == tableTag
- || isTableBodyContextTag(token.name())
- || token.name() == trTag
- || isTableCellContextTag(token.name())) {
+ ASSERT(insertionMode() == InsertionMode::InSelectInTable);
+ if (token->name() == captionTag
+ || token->name() == tableTag
+ || isTableBodyContextTag(token->name())
+ || token->name() == trTag
+ || isTableCellContextTag(token->name())) {
parseError(token);
- if (m_tree.openElements().inTableScope(token.name())) {
+ if (m_tree.openElements()->inTableScope(token->name())) {
AtomicHTMLToken endSelect(HTMLToken::EndTag, selectTag.localName());
- processEndTag(endSelect);
+ processEndTag(&endSelect);
processEndTag(token);
}
return;
}
FALLTHROUGH;
case InsertionMode::InSelect:
- ASSERT(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()))
+ 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()))
processFakeEndTag(optionTag);
- if (is<HTMLOptGroupElement>(m_tree.currentStackItem().node())) {
- m_tree.openElements().pop();
+ if (isHTMLOptGroupElement(m_tree.currentStackItem()->node())) {
+ m_tree.openElements()->pop();
return;
}
parseError(token);
return;
}
- if (token.name() == optionTag) {
- if (is<HTMLOptionElement>(m_tree.currentStackItem().node())) {
- m_tree.openElements().pop();
+ if (token->name() == optionTag) {
+ if (isHTMLOptionElement(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) {
+ if (token->name() == templateTag) {
processTemplateEndTag(token);
return;
}
@@ -2232,29 +2291,33 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
defaultForInTableText();
processEndTag(token);
break;
-#if ENABLE(TEMPLATE_ELEMENT)
case InsertionMode::TemplateContents:
- if (token.name() == templateTag) {
+#if ENABLE(TEMPLATE_ELEMENT)
+ if (token->name() == templateTag) {
processTemplateEndTag(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(token);
return;
}
if (m_insertionMode == InsertionMode::AfterBody) {
- m_tree.insertCommentOnHTMLHtmlElement(&token);
+ m_tree.insertCommentOnHTMLHtmlElement(token);
return;
}
if (m_insertionMode == InsertionMode::InTableText) {
@@ -2262,19 +2325,18 @@ void HTMLTreeBuilder::processComment(AtomicHTMLToken& token)
processComment(token);
return;
}
- m_tree.insertComment(&token);
+ m_tree.insertComment(token);
}
-void HTMLTreeBuilder::processCharacter(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processCharacter(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::Character);
+ ASSERT(token->type() == HTMLToken::Character);
ExternalCharacterTokenBuffer buffer(token);
processCharacterBuffer(buffer);
}
-#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)
{
@@ -2282,13 +2344,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, WTFMove(attributes));
+ AtomicHTMLToken aStartToken(HTMLToken::StartTag, aTagLocalName, attributes);
AtomicHTMLToken aEndToken(HTMLToken::EndTag, aTagLocalName);
- processStartTag(aStartToken);
+ processStartTag(&aStartToken);
m_tree.executeQueuedTasks();
m_tree.insertTextNode(string);
- processEndTag(aEndToken);
+ processEndTag(&aEndToken);
}
// Locates the phone numbers in the string and deals with it
@@ -2298,7 +2360,13 @@ void HTMLTreeBuilder::insertPhoneNumberLink(const String& string)
// 4. Appends the rest of the string as a text node.
void HTMLTreeBuilder::linkifyPhoneNumbers(const String& string)
{
- ASSERT(TelephoneNumberDetector::isSupported());
+ static DDDFACacheRef phoneNumbersCache = DDDFACacheCreateFromFramework();
+ if (!phoneNumbersCache) {
+ m_tree.insertTextNode(string);
+ return;
+ }
+
+ static DDDFAScannerRef phoneNumbersScanner = DDDFAScannerCreateFromCache(phoneNumbersCache);
// relativeStartPosition and relativeEndPosition are the endpoints of the phone number range,
// relative to the scannerPosition
@@ -2307,10 +2375,8 @@ 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 && TelephoneNumberDetector::find(&characters[scannerPosition], length - scannerPosition, &relativeStartPosition, &relativeEndPosition)) {
+ while ((scannerPosition < length) && DDDFAScannerFirstResultInUnicharArray(phoneNumbersScanner, &string.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
@@ -2336,11 +2402,12 @@ 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 ContainerNode& node)
+static inline bool disallowTelephoneNumberParsing(const Node& node)
{
return node.isLink()
+ || node.nodeType() == Node::COMMENT_NODE
|| node.hasTagName(scriptTag)
- || is<HTMLFormControlElement>(node)
+ || (node.isHTMLElement() && toHTMLElement(node).isFormControlElement())
|| node.hasTagName(styleTag)
|| node.hasTagName(ttTag)
|| node.hasTagName(preTag)
@@ -2349,14 +2416,15 @@ static inline bool disallowTelephoneNumberParsing(const ContainerNode& node)
static inline bool shouldParseTelephoneNumbersInNode(const ContainerNode& node)
{
- for (const ContainerNode* ancestor = &node; ancestor; ancestor = ancestor->parentNode()) {
- if (disallowTelephoneNumberParsing(*ancestor))
+ const ContainerNode* currentNode = &node;
+ do {
+ if (currentNode->isElementNode() && disallowTelephoneNumberParsing(*currentNode))
return false;
- }
+ currentNode = currentNode->parentNode();
+ } while (currentNode);
return true;
}
-
-#endif // ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
+#endif // PLATFORM(IOS)
void HTMLTreeBuilder::processCharacterBuffer(ExternalCharacterTokenBuffer& buffer)
{
@@ -2379,68 +2447,77 @@ ReprocessBuffer:
return;
}
- switch (m_insertionMode) {
- case InsertionMode::Initial:
+ switch (insertionMode()) {
+ case InsertionMode::Initial: {
+ ASSERT(insertionMode() == InsertionMode::Initial);
buffer.skipLeadingWhitespace();
if (buffer.isEmpty())
return;
defaultForInitial();
- ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
FALLTHROUGH;
- case InsertionMode::BeforeHTML:
+ }
+ case InsertionMode::BeforeHTML: {
+ ASSERT(insertionMode() == InsertionMode::BeforeHTML);
buffer.skipLeadingWhitespace();
if (buffer.isEmpty())
return;
defaultForBeforeHTML();
- ASSERT(m_insertionMode == InsertionMode::BeforeHead);
FALLTHROUGH;
- case InsertionMode::BeforeHead:
+ }
+ case InsertionMode::BeforeHead: {
+ ASSERT(insertionMode() == 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:
-#if ENABLE(TEMPLATE_ELEMENT)
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:
+ case InsertionMode::InRow: {
+ ASSERT(insertionMode() == InsertionMode::InTable || insertionMode() == InsertionMode::InTableBody || insertionMode() == InsertionMode::InRow);
ASSERT(m_pendingTableCharacters.isEmpty());
- if (is<HTMLTableElement>(m_tree.currentStackItem().node())
- || m_tree.currentStackItem().hasTagName(HTMLNames::tbodyTag)
- || m_tree.currentStackItem().hasTagName(HTMLNames::tfootTag)
- || m_tree.currentStackItem().hasTagName(HTMLNames::theadTag)
- || m_tree.currentStackItem().hasTagName(HTMLNames::trTag)) {
-
+ 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))) {
m_originalInsertionMode = m_insertionMode;
- m_insertionMode = InsertionMode::InTableText;
+ setInsertionMode(InsertionMode::InTableText);
// Note that we fall through to the InsertionMode::InTableText case below.
} else {
HTMLConstructionSite::RedirectToFosterParentGuard redirecter(m_tree);
@@ -2448,10 +2525,13 @@ 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);
@@ -2467,14 +2547,20 @@ ReprocessBuffer:
goto ReprocessBuffer;
}
case InsertionMode::AfterBody:
- case InsertionMode::AfterAfterBody:
+ case InsertionMode::AfterAfterBody: {
+ ASSERT(insertionMode() == InsertionMode::AfterBody || insertionMode() == InsertionMode::AfterAfterBody);
// FIXME: parse error
- m_insertionMode = InsertionMode::InBody;
+ setInsertionMode(InsertionMode::InBody);
goto ReprocessBuffer;
- case InsertionMode::Text:
+ break;
+ }
+ case InsertionMode::Text: {
+ ASSERT(insertionMode() == 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);
@@ -2482,9 +2568,11 @@ 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);
@@ -2493,9 +2581,11 @@ ReprocessBuffer:
break;
}
case InsertionMode::InSelectInTable:
- case InsertionMode::InSelect:
+ case InsertionMode::InSelect: {
+ ASSERT(insertionMode() == InsertionMode::InSelect || insertionMode() == InsertionMode::InSelectInTable);
m_tree.insertTextNode(buffer.takeRemaining());
break;
+ }
case InsertionMode::AfterAfterFrameset: {
String leadingWhitespace = buffer.takeRemainingWhitespace();
if (!leadingWhitespace.isEmpty()) {
@@ -2513,63 +2603,72 @@ void HTMLTreeBuilder::processCharacterBufferForInBody(ExternalCharacterTokenBuff
{
m_tree.reconstructTheActiveFormattingElements();
String characters = buffer.takeRemaining();
-#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(IOS)
- if (!isParsingFragment() && m_tree.isTelephoneNumberParsingEnabled() && shouldParseTelephoneNumbersInNode(m_tree.currentNode()) && TelephoneNumberDetector::isSupported())
+#if PLATFORM(IOS)
+ if (!isParsingFragment() && m_tree.isTelephoneNumberParsingEnabled() && shouldParseTelephoneNumbersInNode(*m_tree.currentNode()) && DataDetectorsCoreLibrary())
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 (m_insertionMode) {
+ ASSERT(token->type() == HTMLToken::EndOfFile);
+ switch (insertionMode()) {
case InsertionMode::Initial:
+ ASSERT(insertionMode() == InsertionMode::Initial);
defaultForInitial();
- ASSERT(m_insertionMode == InsertionMode::BeforeHTML);
FALLTHROUGH;
case InsertionMode::BeforeHTML:
+ ASSERT(insertionMode() == InsertionMode::BeforeHTML);
defaultForBeforeHTML();
- ASSERT(m_insertionMode == InsertionMode::BeforeHead);
FALLTHROUGH;
case InsertionMode::BeforeHead:
+ ASSERT(insertionMode() == InsertionMode::BeforeHead);
defaultForBeforeHead();
- ASSERT(m_insertionMode == InsertionMode::InHead);
FALLTHROUGH;
case InsertionMode::InHead:
+ ASSERT(insertionMode() == InsertionMode::InHead);
defaultForInHead();
- ASSERT(m_insertionMode == InsertionMode::AfterHead);
FALLTHROUGH;
case InsertionMode::AfterHead:
+ ASSERT(insertionMode() == InsertionMode::AfterHead);
defaultForAfterHead();
- ASSERT(m_insertionMode == InsertionMode::InBody);
FALLTHROUGH;
case InsertionMode::InBody:
case InsertionMode::InCell:
case InsertionMode::InCaption:
case InsertionMode::InRow:
+#if ENABLE(TEMPLATE_ELEMENT)
+ ASSERT(insertionMode() == InsertionMode::InBody || insertionMode() == InsertionMode::InCell || insertionMode() == InsertionMode::InCaption || insertionMode() == InsertionMode::InRow || insertionMode() == InsertionMode::TemplateContents);
+#else
+ ASSERT(insertionMode() != InsertionMode::TemplateContents);
+ ASSERT(insertionMode() == InsertionMode::InBody || insertionMode() == InsertionMode::InCell || insertionMode() == InsertionMode::InCaption || insertionMode() == InsertionMode::InRow);
+#endif
notImplemented(); // Emit parse error based on what elements are still open.
#if ENABLE(TEMPLATE_ELEMENT)
- if (!m_templateInsertionModes.isEmpty()) {
+ if (!m_templateInsertionModes.isEmpty())
if (processEndOfFileForInTemplateContents(token))
return;
- }
#endif
break;
case InsertionMode::AfterBody:
case InsertionMode::AfterAfterBody:
+ ASSERT(insertionMode() == InsertionMode::AfterBody || insertionMode() == InsertionMode::AfterAfterBody);
break;
case InsertionMode::InHeadNoscript:
+ ASSERT(insertionMode() == InsertionMode::InHeadNoscript);
defaultForInHeadNoscript();
processEndOfFile(token);
return;
case InsertionMode::AfterFrameset:
case InsertionMode::AfterAfterFrameset:
+ ASSERT(insertionMode() == InsertionMode::AfterFrameset || insertionMode() == InsertionMode::AfterAfterFrameset);
break;
case InsertionMode::InColumnGroup:
if (m_tree.currentIsRootNode()) {
@@ -2577,9 +2676,9 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken& token)
return; // FIXME: Should we break here instead of returning?
}
#if ENABLE(TEMPLATE_ELEMENT)
- ASSERT(m_tree.currentNode().hasTagName(colgroupTag) || m_tree.currentNode().hasTagName(templateTag));
+ ASSERT(m_tree.currentNode()->hasTagName(colgroupTag) || m_tree.currentNode()->hasTagName(templateTag));
#else
- ASSERT(m_tree.currentNode().hasTagName(colgroupTag));
+ ASSERT(m_tree.currentNode()->hasTagName(colgroupTag));
#endif
processColgroupEndTagForInColumnGroup();
FALLTHROUGH;
@@ -2588,14 +2687,14 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken& token)
case InsertionMode::InTableBody:
case InsertionMode::InSelectInTable:
case InsertionMode::InSelect:
- ASSERT(m_insertionMode == InsertionMode::InSelect || m_insertionMode == InsertionMode::InSelectInTable || m_insertionMode == InsertionMode::InTable || m_insertionMode == InsertionMode::InFrameset || m_insertionMode == InsertionMode::InTableBody || m_insertionMode == InsertionMode::InColumnGroup);
- if (&m_tree.currentNode() != &m_tree.openElements().rootNode())
+ 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())
parseError(token);
+
#if ENABLE(TEMPLATE_ELEMENT)
- if (!m_templateInsertionModes.isEmpty()) {
+ if (!m_templateInsertionModes.isEmpty())
if (processEndOfFileForInTemplateContents(token))
return;
- }
#endif
break;
case InsertionMode::InTableText:
@@ -2604,21 +2703,24 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken& 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);
- m_insertionMode = m_originalInsertionMode;
+ setInsertionMode(m_originalInsertionMode);
processEndOfFile(token);
return;
-#if ENABLE(TEMPLATE_ELEMENT)
case InsertionMode::TemplateContents:
+#if ENABLE(TEMPLATE_ELEMENT)
if (processEndOfFileForInTemplateContents(token))
return;
break;
+#else
+ ASSERT_NOT_REACHED();
#endif
}
- m_tree.openElements().popAll();
+ ASSERT(m_tree.currentNode());
+ m_tree.openElements()->popAll();
}
void HTMLTreeBuilder::defaultForInitial()
@@ -2626,38 +2728,38 @@ void HTMLTreeBuilder::defaultForInitial()
notImplemented();
m_tree.setDefaultCompatibilityMode();
// FIXME: parse error
- m_insertionMode = InsertionMode::BeforeHTML;
+ setInsertionMode(InsertionMode::BeforeHTML);
}
void HTMLTreeBuilder::defaultForBeforeHTML()
{
AtomicHTMLToken startHTML(HTMLToken::StartTag, htmlTag.localName());
m_tree.insertHTMLHtmlStartTagBeforeHTML(&startHTML);
- m_insertionMode = InsertionMode::BeforeHead;
+ setInsertionMode(InsertionMode::BeforeHead);
}
void HTMLTreeBuilder::defaultForBeforeHead()
{
AtomicHTMLToken startHead(HTMLToken::StartTag, headTag.localName());
- processStartTag(startHead);
+ processStartTag(&startHead);
}
void HTMLTreeBuilder::defaultForInHead()
{
AtomicHTMLToken endHead(HTMLToken::EndTag, headTag.localName());
- processEndTag(endHead);
+ processEndTag(&endHead);
}
void HTMLTreeBuilder::defaultForInHeadNoscript()
{
AtomicHTMLToken endNoscript(HTMLToken::EndTag, noscriptTag.localName());
- processEndTag(endNoscript);
+ processEndTag(&endNoscript);
}
void HTMLTreeBuilder::defaultForAfterHead()
{
AtomicHTMLToken startBody(HTMLToken::StartTag, bodyTag.localName());
- processStartTag(startBody);
+ processStartTag(&startBody);
m_framesetOk = true;
}
@@ -2671,149 +2773,135 @@ void HTMLTreeBuilder::defaultForInTableText()
m_tree.reconstructTheActiveFormattingElements();
m_tree.insertTextNode(characters, NotAllWhitespace);
m_framesetOk = false;
- m_insertionMode = m_originalInsertionMode;
+ setInsertionMode(m_originalInsertionMode);
return;
}
m_tree.insertTextNode(characters);
- m_insertionMode = m_originalInsertionMode;
+ setInsertionMode(m_originalInsertionMode);
}
-bool HTMLTreeBuilder::processStartTagForInHead(AtomicHTMLToken& token)
+bool HTMLTreeBuilder::processStartTagForInHead(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::StartTag);
- if (token.name() == htmlTag) {
+ ASSERT(token->type() == HTMLToken::StartTag);
+ if (token->name() == htmlTag) {
processHtmlStartTagForInBody(token);
return true;
}
- if (token.name() == baseTag
- || token.name() == basefontTag
- || token.name() == bgsoundTag
- || token.name() == commandTag
- || token.name() == linkTag
- || token.name() == metaTag) {
- m_tree.insertSelfClosingHTMLElement(&token);
+ if (token->name() == baseTag
+ || token->name() == basefontTag
+ || token->name() == bgsoundTag
+ || token->name() == commandTag
+ || token->name() == linkTag
+ || token->name() == metaTag) {
+ m_tree.insertSelfClosingHTMLElement(token);
// Note: The custom processing for the <meta> tag is done in HTMLMetaElement::process().
return true;
}
- if (token.name() == titleTag) {
+ if (token->name() == titleTag) {
processGenericRCDATAStartTag(token);
return true;
}
- if (token.name() == noscriptTag) {
+ if (token->name() == noscriptTag) {
if (m_options.scriptEnabled) {
processGenericRawTextStartTag(token);
return true;
}
- m_tree.insertHTMLElement(&token);
- m_insertionMode = InsertionMode::InHeadNoscript;
+ m_tree.insertHTMLElement(token);
+ setInsertionMode(InsertionMode::InHeadNoscript);
return true;
}
- if (token.name() == noframesTag || token.name() == styleTag) {
+ if (token->name() == noframesTag || token->name() == styleTag) {
processGenericRawTextStartTag(token);
return true;
}
- if (token.name() == scriptTag) {
+ if (token->name() == scriptTag) {
processScriptStartTag(token);
- if (m_options.usePreHTML5ParserQuirks && token.selfClosing())
+ if (m_options.usePreHTML5ParserQuirks && token->selfClosing())
processFakeEndTag(scriptTag);
return true;
}
#if ENABLE(TEMPLATE_ELEMENT)
- if (token.name() == templateTag) {
+ if (token->name() == templateTag) {
processTemplateStartTag(token);
return true;
}
#endif
- if (token.name() == headTag) {
+ if (token->name() == headTag) {
parseError(token);
return true;
}
return false;
}
-void HTMLTreeBuilder::processGenericRCDATAStartTag(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processGenericRCDATAStartTag(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::StartTag);
- m_tree.insertHTMLElement(&token);
- m_parser.tokenizer().setRCDATAState();
+ ASSERT(token->type() == HTMLToken::StartTag);
+ m_tree.insertHTMLElement(token);
+ if (m_parser.tokenizer())
+ m_parser.tokenizer()->setState(HTMLTokenizer::RCDATAState);
m_originalInsertionMode = m_insertionMode;
- m_insertionMode = InsertionMode::Text;
+ setInsertionMode(InsertionMode::Text);
}
-void HTMLTreeBuilder::processGenericRawTextStartTag(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processGenericRawTextStartTag(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::StartTag);
- m_tree.insertHTMLElement(&token);
- m_parser.tokenizer().setRAWTEXTState();
+ ASSERT(token->type() == HTMLToken::StartTag);
+ m_tree.insertHTMLElement(token);
+ if (m_parser.tokenizer())
+ m_parser.tokenizer()->setState(HTMLTokenizer::RAWTEXTState);
m_originalInsertionMode = m_insertionMode;
- m_insertionMode = InsertionMode::Text;
+ setInsertionMode(InsertionMode::Text);
}
-void HTMLTreeBuilder::processScriptStartTag(AtomicHTMLToken& token)
+void HTMLTreeBuilder::processScriptStartTag(AtomicHTMLToken* token)
{
- ASSERT(token.type() == HTMLToken::StartTag);
- m_tree.insertScriptElement(&token);
- m_parser.tokenizer().setScriptDataState();
+ ASSERT(token->type() == HTMLToken::StartTag);
+ m_tree.insertScriptElement(token);
+ if (m_parser.tokenizer())
+ m_parser.tokenizer()->setState(HTMLTokenizer::ScriptDataState);
m_originalInsertionMode = m_insertionMode;
TextPosition position = m_parser.textPosition();
m_scriptToProcessStartPosition = position;
- 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();
+ setInsertionMode(InsertionMode::Text);
}
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#tree-construction
-bool HTMLTreeBuilder::shouldProcessTokenInForeignContent(AtomicHTMLToken& token)
+bool HTMLTreeBuilder::shouldProcessTokenInForeignContent(AtomicHTMLToken* token)
{
if (m_tree.isEmpty())
return false;
- HTMLStackItem& adjustedCurrentNode = adjustedCurrentStackItem();
- if (isInHTMLNamespace(adjustedCurrentNode))
+ HTMLStackItem* item = m_tree.currentStackItem();
+ if (item->isInHTMLNamespace())
return false;
- if (HTMLElementStack::isMathMLTextIntegrationPoint(adjustedCurrentNode)) {
- if (token.type() == HTMLToken::StartTag
- && token.name() != MathMLNames::mglyphTag
- && token.name() != MathMLNames::malignmarkTag)
+ if (HTMLElementStack::isMathMLTextIntegrationPoint(item)) {
+ if (token->type() == HTMLToken::StartTag
+ && token->name() != MathMLNames::mglyphTag
+ && token->name() != MathMLNames::malignmarkTag)
return false;
- if (token.type() == HTMLToken::Character)
+ if (token->type() == HTMLToken::Character)
return false;
}
- if (adjustedCurrentNode.hasTagName(MathMLNames::annotation_xmlTag)
- && token.type() == HTMLToken::StartTag
- && token.name() == SVGNames::svgTag)
+ if (item->hasTagName(MathMLNames::annotation_xmlTag)
+ && token->type() == HTMLToken::StartTag
+ && token->name() == SVGNames::svgTag)
return false;
- if (HTMLElementStack::isHTMLIntegrationPoint(adjustedCurrentNode)) {
- if (token.type() == HTMLToken::StartTag)
+ if (HTMLElementStack::isHTMLIntegrationPoint(item)) {
+ 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;
}
-static bool hasAttribute(AtomicHTMLToken& token, const QualifiedName& name)
+void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token)
{
- return findAttribute(token.attributes(), name);
-}
-
-void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken& token)
-{
- HTMLStackItem& adjustedCurrentNode = adjustedCurrentStackItem();
-
- switch (token.type()) {
+ switch (token->type()) {
case HTMLToken::Uninitialized:
ASSERT_NOT_REACHED();
break;
@@ -2821,52 +2909,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 && (hasAttribute(token, colorAttr) || hasAttribute(token, faceAttr) || hasAttribute(token, sizeAttr)))) {
+ if (token->name() == bTag
+ || token->name() == bigTag
+ || token->name() == blockquoteTag
+ || token->name() == bodyTag
+ || token->name() == brTag
+ || token->name() == centerTag
+ || token->name() == codeTag
+ || token->name() == ddTag
+ || token->name() == divTag
+ || token->name() == dlTag
+ || token->name() == dtTag
+ || token->name() == emTag
+ || token->name() == embedTag
+ || isNumberedHeaderTag(token->name())
+ || token->name() == headTag
+ || token->name() == hrTag
+ || token->name() == iTag
+ || token->name() == imgTag
+ || token->name() == liTag
+ || token->name() == listingTag
+ || token->name() == menuTag
+ || token->name() == metaTag
+ || token->name() == nobrTag
+ || token->name() == olTag
+ || token->name() == pTag
+ || token->name() == preTag
+ || token->name() == rubyTag
+ || token->name() == sTag
+ || token->name() == smallTag
+ || token->name() == spanTag
+ || token->name() == strongTag
+ || token->name() == strikeTag
+ || token->name() == subTag
+ || token->name() == supTag
+ || token->name() == tableTag
+ || token->name() == ttTag
+ || token->name() == uTag
+ || token->name() == ulTag
+ || token->name() == varTag
+ || (token->name() == fontTag && (token->getAttributeItem(colorAttr) || token->getAttributeItem(faceAttr) || token->getAttributeItem(sizeAttr)))) {
parseError(token);
- m_tree.openElements().popUntilForeignContentScopeMarker();
+ m_tree.openElements()->popUntilForeignContentScopeMarker();
processStartTag(token);
return;
}
- const AtomicString& currentNamespace = adjustedCurrentNode.namespaceURI();
+ const AtomicString& currentNamespace = m_tree.currentStackItem()->namespaceURI();
if (currentNamespace == MathMLNames::mathmlNamespaceURI)
adjustMathMLAttributes(token);
if (currentNamespace == SVGNames::svgNamespaceURI) {
@@ -2874,32 +2962,32 @@ void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken& token)
adjustSVGAttributes(token);
}
adjustForeignAttributes(token);
- m_tree.insertForeignElement(&token, currentNamespace);
+ m_tree.insertForeignElement(token, currentNamespace);
break;
}
case HTMLToken::EndTag: {
- if (adjustedCurrentNode.namespaceURI() == SVGNames::svgNamespaceURI)
+ if (m_tree.currentStackItem()->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 = m_tree.currentElement();
+ m_tree.openElements()->pop();
return;
}
- if (!isInHTMLNamespace(m_tree.currentStackItem())) {
+ if (!m_tree.currentStackItem()->isInHTMLNamespace()) {
// FIXME: This code just wants an Element* iterator, instead of an ElementRecord*
- auto* nodeRecord = &m_tree.openElements().topRecord();
- if (nodeRecord->stackItem().localName() != token.name())
+ HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord();
+ if (!nodeRecord->stackItem()->hasLocalName(token->name()))
parseError(token);
while (1) {
- if (nodeRecord->stackItem().localName() == token.name()) {
- m_tree.openElements().popUntilPopped(&nodeRecord->element());
+ if (nodeRecord->stackItem()->hasLocalName(token->name())) {
+ m_tree.openElements()->popUntilPopped(nodeRecord->element());
return;
}
nodeRecord = nodeRecord->next();
- if (isInHTMLNamespace(nodeRecord->stackItem()))
+ if (nodeRecord->stackItem()->isInHTMLNamespace())
break;
}
}
@@ -2908,10 +2996,10 @@ void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken& token)
break;
}
case HTMLToken::Comment:
- m_tree.insertComment(&token);
+ m_tree.insertComment(token);
return;
case HTMLToken::Character: {
- String characters = String(token.characters(), token.charactersLength());
+ String characters = String(token->characters(), token->charactersLength());
m_tree.insertTextNode(characters);
if (m_framesetOk && !isAllWhitespaceOrReplacementCharacters(characters))
m_framesetOk = false;
@@ -2925,8 +3013,6 @@ void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken& token)
void HTMLTreeBuilder::finished()
{
- ASSERT(!m_destroyed);
-
if (isParsingFragment())
return;
@@ -2934,11 +3020,12 @@ void HTMLTreeBuilder::finished()
ASSERT(m_templateInsertionModes.isEmpty());
#endif
+ ASSERT(m_isAttached);
+ // Warning, this may detach the parser. Do not do anything else after this.
m_tree.finishedParsing();
- // The tree builder might have been destroyed as an indirect result of finishing the parsing.
}
-inline void HTMLTreeBuilder::parseError(AtomicHTMLToken&)
+void HTMLTreeBuilder::parseError(AtomicHTMLToken*)
{
}