Read tag names and attributes from the saved tokens where possible.
authorkseo@webkit.org <kseo@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Jul 2012 05:47:29 +0000 (05:47 +0000)
committerkseo@webkit.org <kseo@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Jul 2012 05:47:29 +0000 (05:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=92079

Reviewed by Adam Barth.

Read tag names and attributes from the saved tokens, not from the DOM.
Also added convenient methods such as hasLocalName, hasTagName, localName,
isElementNode and isDocumentFragmentNode to HTMLStackItem class.

No new tests, covered by existing tests.

* html/parser/HTMLConstructionSite.cpp:
(WebCore::HTMLNames::hasImpliedEndTag):
(WebCore::HTMLNames::causesFosterParenting):
(WebCore::HTMLConstructionSite::generateImpliedEndTagsWithExclusion):
(WebCore::HTMLConstructionSite::generateImpliedEndTags):
(WebCore::HTMLConstructionSite::shouldFosterParent):
* html/parser/HTMLConstructionSite.h:
(WebCore::HTMLConstructionSite::currentStackItem):
* html/parser/HTMLElementStack.cpp:
(WebCore::HTMLNames::isNumberedHeaderElement):
(WebCore::HTMLNames::isRootNode):
(WebCore::HTMLNames::isScopeMarker):
(WebCore::HTMLNames::isListItemScopeMarker):
(WebCore::HTMLNames::isTableScopeMarker):
(WebCore::HTMLNames::isTableBodyScopeMarker):
(WebCore::HTMLNames::isTableRowScopeMarker):
(WebCore::HTMLNames::isForeignContentScopeMarker):
(WebCore::HTMLNames::isButtonScopeMarker):
(WebCore::HTMLNames::isSelectScopeMarker):
(WebCore::HTMLElementStack::ElementRecord::replaceElement):
(WebCore::HTMLElementStack::popUntilNumberedHeaderElementPopped):
(WebCore::HTMLElementStack::popUntilTableScopeMarker):
(WebCore::HTMLElementStack::popUntilTableBodyScopeMarker):
(WebCore::HTMLElementStack::popUntilTableRowScopeMarker):
(WebCore::HTMLElementStack::isMathMLTextIntegrationPoint):
(WebCore::HTMLElementStack::isHTMLIntegrationPoint):
(WebCore::HTMLElementStack::popUntilForeignContentScopeMarker):
(WebCore::HTMLElementStack::pushRootNode):
(WebCore::HTMLElementStack::oneBelowTop):
(WebCore::HTMLElementStack::topmost):
(WebCore):
(WebCore::inScopeCommon):
(WebCore::HTMLElementStack::hasNumberedHeaderElementInScope):
(WebCore::HTMLElementStack::inScope):
* html/parser/HTMLElementStack.h:
(WebCore::HTMLElementStack::topStackItem):
(HTMLElementStack):
(WebCore::isInHTMLNamespace):
* html/parser/HTMLStackItem.h:
(WebCore::HTMLStackItem::isDocumentFragmentNode):
(WebCore::HTMLStackItem::isElementNode):
(HTMLStackItem):
(WebCore::HTMLStackItem::hasLocalName):
(WebCore::HTMLStackItem::hasTagName):
(WebCore::HTMLStackItem::HTMLStackItem):
* html/parser/HTMLTreeBuilder.cpp:
(WebCore):
(WebCore::HTMLTreeBuilder::constructTreeFromAtomicToken):
(WebCore::HTMLTreeBuilder::processFakeEndTag):
(WebCore::HTMLTreeBuilder::processCloseWhenNestedTag):
(WebCore::HTMLTreeBuilder::processStartTagForInBody):
(WebCore::HTMLTreeBuilder::processStartTag):
(WebCore::HTMLTreeBuilder::processAnyOtherEndTagForInBody):
(WebCore::HTMLTreeBuilder::furthestBlockForFormattingElement):
(WebCore::HTMLTreeBuilder::callTheAdoptionAgency):
(WebCore::HTMLTreeBuilder::processEndTagForInTableBody):
(WebCore::HTMLTreeBuilder::processEndTagForInCell):
(WebCore::HTMLTreeBuilder::processEndTagForInBody):
(WebCore::HTMLTreeBuilder::processCaptionEndTagForInCaption):
(WebCore::HTMLTreeBuilder::processTrEndTagForInRow):
(WebCore::HTMLTreeBuilder::processEndTag):
(WebCore::HTMLTreeBuilder::processCharacterBuffer):
(WebCore::HTMLTreeBuilder::processEndOfFile):
(WebCore::HTMLTreeBuilder::shouldProcessTokenInForeignContent):
(WebCore::HTMLTreeBuilder::processTokenInForeignContent):
* html/parser/HTMLTreeBuilder.h:

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

Source/WebCore/ChangeLog
Source/WebCore/html/parser/HTMLConstructionSite.cpp
Source/WebCore/html/parser/HTMLConstructionSite.h
Source/WebCore/html/parser/HTMLElementStack.cpp
Source/WebCore/html/parser/HTMLElementStack.h
Source/WebCore/html/parser/HTMLStackItem.h
Source/WebCore/html/parser/HTMLTreeBuilder.cpp
Source/WebCore/html/parser/HTMLTreeBuilder.h

index 743fb09..a102bd2 100644 (file)
@@ -1,3 +1,83 @@
+2012-07-24  Kwang Yul Seo  <skyul@company100.net>
+
+        Read tag names and attributes from the saved tokens where possible.
+        https://bugs.webkit.org/show_bug.cgi?id=92079
+
+        Reviewed by Adam Barth.
+
+        Read tag names and attributes from the saved tokens, not from the DOM.
+        Also added convenient methods such as hasLocalName, hasTagName, localName,
+        isElementNode and isDocumentFragmentNode to HTMLStackItem class.
+
+        No new tests, covered by existing tests.
+
+        * html/parser/HTMLConstructionSite.cpp:
+        (WebCore::HTMLNames::hasImpliedEndTag):
+        (WebCore::HTMLNames::causesFosterParenting):
+        (WebCore::HTMLConstructionSite::generateImpliedEndTagsWithExclusion):
+        (WebCore::HTMLConstructionSite::generateImpliedEndTags):
+        (WebCore::HTMLConstructionSite::shouldFosterParent):
+        * html/parser/HTMLConstructionSite.h:
+        (WebCore::HTMLConstructionSite::currentStackItem):
+        * html/parser/HTMLElementStack.cpp:
+        (WebCore::HTMLNames::isNumberedHeaderElement):
+        (WebCore::HTMLNames::isRootNode):
+        (WebCore::HTMLNames::isScopeMarker):
+        (WebCore::HTMLNames::isListItemScopeMarker):
+        (WebCore::HTMLNames::isTableScopeMarker):
+        (WebCore::HTMLNames::isTableBodyScopeMarker):
+        (WebCore::HTMLNames::isTableRowScopeMarker):
+        (WebCore::HTMLNames::isForeignContentScopeMarker):
+        (WebCore::HTMLNames::isButtonScopeMarker):
+        (WebCore::HTMLNames::isSelectScopeMarker):
+        (WebCore::HTMLElementStack::ElementRecord::replaceElement):
+        (WebCore::HTMLElementStack::popUntilNumberedHeaderElementPopped):
+        (WebCore::HTMLElementStack::popUntilTableScopeMarker):
+        (WebCore::HTMLElementStack::popUntilTableBodyScopeMarker):
+        (WebCore::HTMLElementStack::popUntilTableRowScopeMarker):
+        (WebCore::HTMLElementStack::isMathMLTextIntegrationPoint):
+        (WebCore::HTMLElementStack::isHTMLIntegrationPoint):
+        (WebCore::HTMLElementStack::popUntilForeignContentScopeMarker):
+        (WebCore::HTMLElementStack::pushRootNode):
+        (WebCore::HTMLElementStack::oneBelowTop):
+        (WebCore::HTMLElementStack::topmost):
+        (WebCore):
+        (WebCore::inScopeCommon):
+        (WebCore::HTMLElementStack::hasNumberedHeaderElementInScope):
+        (WebCore::HTMLElementStack::inScope):
+        * html/parser/HTMLElementStack.h:
+        (WebCore::HTMLElementStack::topStackItem):
+        (HTMLElementStack):
+        (WebCore::isInHTMLNamespace):
+        * html/parser/HTMLStackItem.h:
+        (WebCore::HTMLStackItem::isDocumentFragmentNode):
+        (WebCore::HTMLStackItem::isElementNode):
+        (HTMLStackItem):
+        (WebCore::HTMLStackItem::hasLocalName):
+        (WebCore::HTMLStackItem::hasTagName):
+        (WebCore::HTMLStackItem::HTMLStackItem):
+        * html/parser/HTMLTreeBuilder.cpp:
+        (WebCore):
+        (WebCore::HTMLTreeBuilder::constructTreeFromAtomicToken):
+        (WebCore::HTMLTreeBuilder::processFakeEndTag):
+        (WebCore::HTMLTreeBuilder::processCloseWhenNestedTag):
+        (WebCore::HTMLTreeBuilder::processStartTagForInBody):
+        (WebCore::HTMLTreeBuilder::processStartTag):
+        (WebCore::HTMLTreeBuilder::processAnyOtherEndTagForInBody):
+        (WebCore::HTMLTreeBuilder::furthestBlockForFormattingElement):
+        (WebCore::HTMLTreeBuilder::callTheAdoptionAgency):
+        (WebCore::HTMLTreeBuilder::processEndTagForInTableBody):
+        (WebCore::HTMLTreeBuilder::processEndTagForInCell):
+        (WebCore::HTMLTreeBuilder::processEndTagForInBody):
+        (WebCore::HTMLTreeBuilder::processCaptionEndTagForInCaption):
+        (WebCore::HTMLTreeBuilder::processTrEndTagForInRow):
+        (WebCore::HTMLTreeBuilder::processEndTag):
+        (WebCore::HTMLTreeBuilder::processCharacterBuffer):
+        (WebCore::HTMLTreeBuilder::processEndOfFile):
+        (WebCore::HTMLTreeBuilder::shouldProcessTokenInForeignContent):
+        (WebCore::HTMLTreeBuilder::processTokenInForeignContent):
+        * html/parser/HTMLTreeBuilder.h:
+
 2012-07-24  Hironori Bono  <hbono@chromium.org>
 
         Avoid moving child objects multiple times when vertical scrollbar are shown at the left side.
index cc8bc29..9183c0f 100644 (file)
@@ -60,25 +60,25 @@ using namespace HTMLNames;
 
 namespace {
 
-bool hasImpliedEndTag(ContainerNode* node)
+bool hasImpliedEndTag(const HTMLStackItem* item)
 {
-    return node->hasTagName(ddTag)
-        || node->hasTagName(dtTag)
-        || node->hasTagName(liTag)
-        || node->hasTagName(optionTag)
-        || node->hasTagName(optgroupTag)
-        || node->hasTagName(pTag)
-        || node->hasTagName(rpTag)
-        || node->hasTagName(rtTag);
+    return item->hasTagName(ddTag)
+        || item->hasTagName(dtTag)
+        || item->hasTagName(liTag)
+        || item->hasTagName(optionTag)
+        || item->hasTagName(optgroupTag)
+        || item->hasTagName(pTag)
+        || item->hasTagName(rpTag)
+        || item->hasTagName(rtTag);
 }
 
-bool causesFosterParenting(const QualifiedName& tagName)
+bool causesFosterParenting(const HTMLStackItem* item)
 {
-    return tagName == tableTag
-        || tagName == tbodyTag
-        || tagName == tfootTag
-        || tagName == theadTag
-        || tagName == trTag;
+    return item->hasTagName(tableTag)
+        || item->hasTagName(tbodyTag)
+        || item->hasTagName(tfootTag)
+        || item->hasTagName(theadTag)
+        || item->hasTagName(trTag);
 }
 
 inline bool isAllWhitespace(const String& string)
@@ -465,13 +465,13 @@ void HTMLConstructionSite::reconstructTheActiveFormattingElements()
 
 void HTMLConstructionSite::generateImpliedEndTagsWithExclusion(const AtomicString& tagName)
 {
-    while (hasImpliedEndTag(currentNode()) && !currentNode()->hasLocalName(tagName))
+    while (hasImpliedEndTag(currentStackItem()) && !currentStackItem()->hasLocalName(tagName))
         m_openElements.pop();
 }
 
 void HTMLConstructionSite::generateImpliedEndTags()
 {
-    while (hasImpliedEndTag(currentNode()))
+    while (hasImpliedEndTag(currentStackItem()))
         m_openElements.pop();
 }
 
@@ -495,8 +495,8 @@ void HTMLConstructionSite::findFosterSite(HTMLConstructionSiteTask& task)
 bool HTMLConstructionSite::shouldFosterParent() const
 {
     return m_redirectAttachToFosterParent
-        && currentNode()->isElementNode()
-        && causesFosterParenting(currentElement()->tagQName());
+        && currentStackItem()->isElementNode()
+        && causesFosterParenting(currentStackItem());
 }
 
 void HTMLConstructionSite::fosterParent(PassRefPtr<Node> node)
index a43668b..337ff79 100644 (file)
@@ -121,6 +121,7 @@ public:
     HTMLElementStack::ElementRecord* currentElementRecord() const { return m_openElements.topRecord(); }
     Element* currentElement() const { return m_openElements.top(); }
     ContainerNode* currentNode() const { return m_openElements.topNode(); }
+    HTMLStackItem* currentStackItem() const { return m_openElements.topStackItem(); }
     Element* oneBelowTop() const { return m_openElements.oneBelowTop(); }
 
     HTMLElementStack* openElements() const { return &m_openElements; }
index 7acab9a..6642cd5 100644 (file)
@@ -40,87 +40,87 @@ using namespace HTMLNames;
 
 namespace {
 
-inline bool isNumberedHeaderElement(ContainerNode* node)
+inline bool isNumberedHeaderElement(HTMLStackItem* item)
 {
-    return node->hasTagName(h1Tag)
-        || node->hasTagName(h2Tag)
-        || node->hasTagName(h3Tag)
-        || node->hasTagName(h4Tag)
-        || node->hasTagName(h5Tag)
-        || node->hasTagName(h6Tag);
+    return item->hasTagName(h1Tag)
+        || item->hasTagName(h2Tag)
+        || item->hasTagName(h3Tag)
+        || item->hasTagName(h4Tag)
+        || item->hasTagName(h5Tag)
+        || item->hasTagName(h6Tag);
 }
     
-inline bool isRootNode(ContainerNode* node)
+inline bool isRootNode(HTMLStackItem* item)
 {
-    return node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE
-        || node->hasTagName(htmlTag);
+    return item->isDocumentFragmentNode()
+        || item->hasTagName(htmlTag);
 }
 
-inline bool isScopeMarker(ContainerNode* node)
+inline bool isScopeMarker(HTMLStackItem* item)
 {
-    return node->hasTagName(appletTag)
-        || node->hasTagName(captionTag)
-        || node->hasTagName(marqueeTag)
-        || node->hasTagName(objectTag)
-        || node->hasTagName(tableTag)
-        || node->hasTagName(tdTag)
-        || node->hasTagName(thTag)
-        || node->hasTagName(MathMLNames::miTag)
-        || node->hasTagName(MathMLNames::moTag)
-        || node->hasTagName(MathMLNames::mnTag)
-        || node->hasTagName(MathMLNames::msTag)
-        || node->hasTagName(MathMLNames::mtextTag)
-        || node->hasTagName(MathMLNames::annotation_xmlTag)
-        || node->hasTagName(SVGNames::foreignObjectTag)
-        || node->hasTagName(SVGNames::descTag)
-        || node->hasTagName(SVGNames::titleTag)
-        || isRootNode(node);
+    return item->hasTagName(appletTag)
+        || item->hasTagName(captionTag)
+        || item->hasTagName(marqueeTag)
+        || item->hasTagName(objectTag)
+        || item->hasTagName(tableTag)
+        || item->hasTagName(tdTag)
+        || item->hasTagName(thTag)
+        || item->hasTagName(MathMLNames::miTag)
+        || item->hasTagName(MathMLNames::moTag)
+        || item->hasTagName(MathMLNames::mnTag)
+        || item->hasTagName(MathMLNames::msTag)
+        || item->hasTagName(MathMLNames::mtextTag)
+        || item->hasTagName(MathMLNames::annotation_xmlTag)
+        || item->hasTagName(SVGNames::foreignObjectTag)
+        || item->hasTagName(SVGNames::descTag)
+        || item->hasTagName(SVGNames::titleTag)
+        || isRootNode(item);
 }
 
-inline bool isListItemScopeMarker(ContainerNode* node)
+inline bool isListItemScopeMarker(HTMLStackItem* item)
 {
-    return isScopeMarker(node)
-        || node->hasTagName(olTag)
-        || node->hasTagName(ulTag);
+    return isScopeMarker(item)
+        || item->hasTagName(olTag)
+        || item->hasTagName(ulTag);
 }
 
-inline bool isTableScopeMarker(ContainerNode* node)
+inline bool isTableScopeMarker(HTMLStackItem* item)
 {
-    return node->hasTagName(tableTag)
-        || isRootNode(node);
+    return item->hasTagName(tableTag)
+        || isRootNode(item);
 }
 
-inline bool isTableBodyScopeMarker(ContainerNode* node)
+inline bool isTableBodyScopeMarker(HTMLStackItem* item)
 {
-    return node->hasTagName(tbodyTag)
-        || node->hasTagName(tfootTag)
-        || node->hasTagName(theadTag)
-        || isRootNode(node);
+    return item->hasTagName(tbodyTag)
+        || item->hasTagName(tfootTag)
+        || item->hasTagName(theadTag)
+        || isRootNode(item);
 }
 
-inline bool isTableRowScopeMarker(ContainerNode* node)
+inline bool isTableRowScopeMarker(HTMLStackItem* item)
 {
-    return node->hasTagName(trTag)
-        || isRootNode(node);
+    return item->hasTagName(trTag)
+        || isRootNode(item);
 }
 
-inline bool isForeignContentScopeMarker(ContainerNode* node)
+inline bool isForeignContentScopeMarker(HTMLStackItem* item)
 {
-    return HTMLElementStack::isMathMLTextIntegrationPoint(node)
-        || HTMLElementStack::isHTMLIntegrationPoint(node)
-        || isInHTMLNamespace(node);
+    return HTMLElementStack::isMathMLTextIntegrationPoint(item)
+        || HTMLElementStack::isHTMLIntegrationPoint(item)
+        || isInHTMLNamespace(item);
 }
 
-inline bool isButtonScopeMarker(ContainerNode* node)
+inline bool isButtonScopeMarker(HTMLStackItem* item)
 {
-    return isScopeMarker(node)
-        || node->hasTagName(buttonTag);
+    return isScopeMarker(item)
+        || item->hasTagName(buttonTag);
 }
 
-inline bool isSelectScopeMarker(ContainerNode* node)
+inline bool isSelectScopeMarker(HTMLStackItem* item)
 {
-    return !node->hasTagName(optgroupTag)
-        && !node->hasTagName(optionTag);
+    return !item->hasTagName(optgroupTag)
+        && !item->hasTagName(optionTag);
 }
 
 }
@@ -139,7 +139,7 @@ HTMLElementStack::ElementRecord::~ElementRecord()
 void HTMLElementStack::ElementRecord::replaceElement(PassRefPtr<HTMLStackItem> item)
 {
     ASSERT(item);
-    ASSERT(!m_item || m_item->node()->isElementNode());
+    ASSERT(!m_item || m_item->isElementNode());
     // FIXME: Should this call finishParsingChildren?
     m_item = item;
 }
@@ -231,7 +231,7 @@ void HTMLElementStack::popUntilPopped(const AtomicString& tagName)
 
 void HTMLElementStack::popUntilNumberedHeaderElementPopped()
 {
-    while (!isNumberedHeaderElement(topNode()))
+    while (!isNumberedHeaderElement(topStackItem()))
         pop();
     pop();
 }
@@ -251,65 +251,64 @@ void HTMLElementStack::popUntilPopped(Element* element)
 void HTMLElementStack::popUntilTableScopeMarker()
 {
     // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#clear-the-stack-back-to-a-table-context
-    while (!isTableScopeMarker(topNode()))
+    while (!isTableScopeMarker(topStackItem()))
         pop();
 }
 
 void HTMLElementStack::popUntilTableBodyScopeMarker()
 {
     // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#clear-the-stack-back-to-a-table-body-context
-    while (!isTableBodyScopeMarker(topNode()))
+    while (!isTableBodyScopeMarker(topStackItem()))
         pop();
 }
 
 void HTMLElementStack::popUntilTableRowScopeMarker()
 {
     // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#clear-the-stack-back-to-a-table-row-context
-    while (!isTableRowScopeMarker(topNode()))
+    while (!isTableRowScopeMarker(topStackItem()))
         pop();
 }
 
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#mathml-text-integration-point
-bool HTMLElementStack::isMathMLTextIntegrationPoint(ContainerNode* node)
+bool HTMLElementStack::isMathMLTextIntegrationPoint(HTMLStackItem* item)
 {
-    if (!node->isElementNode())
+    if (!item->isElementNode())
         return false;
-    Element* element = static_cast<Element*>(node);
-    return element->hasTagName(MathMLNames::miTag)
-        || element->hasTagName(MathMLNames::moTag)
-        || element->hasTagName(MathMLNames::mnTag)
-        || element->hasTagName(MathMLNames::msTag)
-        || element->hasTagName(MathMLNames::mtextTag);
+    return item->hasTagName(MathMLNames::miTag)
+        || item->hasTagName(MathMLNames::moTag)
+        || item->hasTagName(MathMLNames::mnTag)
+        || item->hasTagName(MathMLNames::msTag)
+        || item->hasTagName(MathMLNames::mtextTag);
 }
 
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#html-integration-point
-bool HTMLElementStack::isHTMLIntegrationPoint(ContainerNode* node)
+bool HTMLElementStack::isHTMLIntegrationPoint(HTMLStackItem* item)
 {
-    if (!node->isElementNode())
+    if (!item->isElementNode())
+        return false;
+    if (item->hasTagName(MathMLNames::annotation_xmlTag)) {
+        Attribute* encodingAttr = item->token()->getAttributeItem(MathMLNames::encodingAttr);
+        if (encodingAttr) {
+            const String& encoding = encodingAttr->value();
+            return equalIgnoringCase(encoding, "text/html")
+                || equalIgnoringCase(encoding, "application/xhtml+xml");
+        }
         return false;
-    Element* element = static_cast<Element*>(node);
-    if (element->hasTagName(MathMLNames::annotation_xmlTag)) {
-        // FIXME: Technically we shouldn't read back from the DOM here.
-        // Instead, we're supposed to track this information in the element
-        // stack, which lets the parser run on its own thread.
-        String encoding = element->fastGetAttribute(MathMLNames::encodingAttr);
-        return equalIgnoringCase(encoding, "text/html")
-            || equalIgnoringCase(encoding, "application/xhtml+xml");
     }
-    return element->hasTagName(SVGNames::foreignObjectTag)
-        || element->hasTagName(SVGNames::descTag)
-        || element->hasTagName(SVGNames::titleTag);
+    return item->hasTagName(SVGNames::foreignObjectTag)
+        || item->hasTagName(SVGNames::descTag)
+        || item->hasTagName(SVGNames::titleTag);
 }
 
 void HTMLElementStack::popUntilForeignContentScopeMarker()
 {
-    while (!isForeignContentScopeMarker(topNode()))
+    while (!isForeignContentScopeMarker(topStackItem()))
         pop();
 }
     
 void HTMLElementStack::pushRootNode(PassRefPtr<HTMLStackItem> rootItem)
 {
-    ASSERT(rootItem->node()->nodeType() == Node::DOCUMENT_FRAGMENT_NODE);
+    ASSERT(rootItem->isDocumentFragmentNode());
     pushRootNodeCommon(rootItem);
 }
 
@@ -389,7 +388,7 @@ Element* HTMLElementStack::oneBelowTop() const
     // We should never call this if there are fewer than 2 elements on the stack.
     ASSERT(m_top);
     ASSERT(m_top->next());
-    if (m_top->next()->node()->isElementNode())
+    if (m_top->next()->stackItem()->isElementNode())
         return m_top->next()->element();
     return 0;
 }
@@ -432,7 +431,7 @@ HTMLElementStack::ElementRecord* HTMLElementStack::find(Element* element) const
 HTMLElementStack::ElementRecord* HTMLElementStack::topmost(const AtomicString& tagName) const
 {
     for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) {
-        if (pos->node()->hasLocalName(tagName))
+        if (pos->stackItem()->hasLocalName(tagName))
             return pos;
     }
     return 0;
@@ -448,14 +447,14 @@ bool HTMLElementStack::contains(const AtomicString& tagName) const
     return !!topmost(tagName);
 }
 
-template <bool isMarker(ContainerNode*)>
+template <bool isMarker(HTMLStackItem*)>
 bool inScopeCommon(HTMLElementStack::ElementRecord* top, const AtomicString& targetTag)
 {
     for (HTMLElementStack::ElementRecord* pos = top; pos; pos = pos->next()) {
-        ContainerNode* node = pos->node();
-        if (node->hasLocalName(targetTag))
+        HTMLStackItem* item = pos->stackItem().get();
+        if (item->hasLocalName(targetTag))
             return true;
-        if (isMarker(node))
+        if (isMarker(item))
             return false;
     }
     ASSERT_NOT_REACHED(); // <html> is always on the stack and is a scope marker.
@@ -465,10 +464,10 @@ bool inScopeCommon(HTMLElementStack::ElementRecord* top, const AtomicString& tar
 bool HTMLElementStack::hasNumberedHeaderElementInScope() const
 {
     for (ElementRecord* record = m_top.get(); record; record = record->next()) {
-        ContainerNode* node = record->node();
-        if (isNumberedHeaderElement(node))
+        HTMLStackItem* item = record->stackItem().get();
+        if (isNumberedHeaderElement(item))
             return true;
-        if (isScopeMarker(node))
+        if (isScopeMarker(item))
             return false;
     }
     ASSERT_NOT_REACHED(); // <html> is always on the stack and is a scope marker.
@@ -478,10 +477,10 @@ bool HTMLElementStack::hasNumberedHeaderElementInScope() const
 bool HTMLElementStack::inScope(Element* targetElement) const
 {
     for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) {
-        ContainerNode* node = pos->node();
-        if (node == targetElement)
+        HTMLStackItem* item = pos->stackItem().get();
+        if (item->node() == targetElement)
             return true;
-        if (isScopeMarker(node))
+        if (isScopeMarker(item))
             return false;
     }
     ASSERT_NOT_REACHED(); // <html> is always on the stack and is a scope marker.
index 6e31251..f19bc30 100644 (file)
@@ -92,6 +92,12 @@ public:
         return m_top->node();
     }
 
+    HTMLStackItem* topStackItem() const
+    {
+        ASSERT(m_top->stackItem());
+        return m_top->stackItem().get();
+    }
+
     Element* oneBelowTop() const;
     ElementRecord* topRecord() const;
     Element* bottom() const;
@@ -120,8 +126,8 @@ public:
     void popHTMLBodyElement();
     void popAll();
 
-    static bool isMathMLTextIntegrationPoint(ContainerNode*);
-    static bool isHTMLIntegrationPoint(ContainerNode*);
+    static bool isMathMLTextIntegrationPoint(HTMLStackItem*);
+    static bool isHTMLIntegrationPoint(HTMLStackItem*);
 
     void remove(Element*);
     void removeHTMLHeadElement(Element*);
@@ -175,12 +181,12 @@ private:
     unsigned m_stackDepth;
 };
     
-inline bool isInHTMLNamespace(Node* node)
+inline bool isInHTMLNamespace(const HTMLStackItem* item)
 {
     // A DocumentFragment takes the place of the document element when parsing
     // fragments and should be considered in the HTML namespace.
-    return node->namespaceURI() == HTMLNames::xhtmlNamespaceURI
-        || node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE; // FIXME: Does this also apply to ShadowRoot?
+    return item->namespaceURI() == HTMLNames::xhtmlNamespaceURI
+        || item->isDocumentFragmentNode(); // FIXME: Does this also apply to ShadowRoot?
 }
 
 
index 9fcc31d..1b1c1bf 100644 (file)
@@ -55,15 +55,25 @@ public:
     Element* element() const { return toElement(m_node.get()); }
     ContainerNode* node() const { return m_node.get(); }
 
+    bool isDocumentFragmentNode() const { return m_isDocumentFragmentNode; }
+    bool isElementNode() const { return !m_isDocumentFragmentNode; }
+
     AtomicHTMLToken* token() { return m_token.get(); }
     const AtomicString& namespaceURI() const { return m_namespaceURI; }
     const AtomicString& localName() const { return m_token->name(); }
 
+    bool hasLocalName(const AtomicString& name) const { return m_token->name() == name; }
+    bool hasTagName(const QualifiedName& name) const { return m_token->name() == name.localName() && m_namespaceURI == name.namespaceURI(); }
+
 private:
     HTMLStackItem(PassRefPtr<ContainerNode> node)
         : m_node(node)
         , m_isDocumentFragmentNode(true)
     {
+        // Create a fake token for a document fragment node. This looks ugly but required for performance
+        // because we want to use m_token->name() in localName(), hasLocalName() and hasTagName() without
+        // checking m_isDocumentFragmentNode flag.
+        m_token = AtomicHTMLToken::create(HTMLTokenTypes::StartTag, nullAtom);
     }
 
     HTMLStackItem(PassRefPtr<ContainerNode> node, PassRefPtr<AtomicHTMLToken> token, const AtomicString& namespaceURI = HTMLNames::xhtmlNamespaceURI)
index 180a50c..b3ab6ba 100644 (file)
@@ -109,23 +109,23 @@ bool isTableBodyContextTag(const AtomicString& tagName)
 }
 
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#special
-bool isSpecialNode(Node* node)
-{
-    if (node->hasTagName(MathMLNames::miTag)
-        || node->hasTagName(MathMLNames::moTag)
-        || node->hasTagName(MathMLNames::mnTag)
-        || node->hasTagName(MathMLNames::msTag)
-        || node->hasTagName(MathMLNames::mtextTag)
-        || node->hasTagName(MathMLNames::annotation_xmlTag)
-        || node->hasTagName(SVGNames::foreignObjectTag)
-        || node->hasTagName(SVGNames::descTag)
-        || node->hasTagName(SVGNames::titleTag))
+bool isSpecialNode(const HTMLStackItem* item)
+{
+    if (item->hasTagName(MathMLNames::miTag)
+        || item->hasTagName(MathMLNames::moTag)
+        || item->hasTagName(MathMLNames::mnTag)
+        || item->hasTagName(MathMLNames::msTag)
+        || item->hasTagName(MathMLNames::mtextTag)
+        || item->hasTagName(MathMLNames::annotation_xmlTag)
+        || item->hasTagName(SVGNames::foreignObjectTag)
+        || item->hasTagName(SVGNames::descTag)
+        || item->hasTagName(SVGNames::titleTag))
         return true;
-    if (node->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)
+    if (item->isDocumentFragmentNode())
         return true;
-    if (!isInHTMLNamespace(node))
+    if (!isInHTMLNamespace(item))
         return false;
-    const AtomicString& tagName = node->localName();
+    const AtomicString& tagName = item->localName();
     return tagName == addressTag
         || tagName == appletTag
         || tagName == areaTag
@@ -471,9 +471,9 @@ void HTMLTreeBuilder::constructTreeFromAtomicToken(AtomicHTMLToken* token)
         processToken(token);
 
     bool inForeignContent = !m_tree.isEmpty()
-        && !isInHTMLNamespace(m_tree.currentNode())
-        && !HTMLElementStack::isHTMLIntegrationPoint(m_tree.currentNode())
-        && !HTMLElementStack::isMathMLTextIntegrationPoint(m_tree.currentNode());
+        && !isInHTMLNamespace(m_tree.currentStackItem())
+        && !HTMLElementStack::isHTMLIntegrationPoint(m_tree.currentStackItem())
+        && !HTMLElementStack::isMathMLTextIntegrationPoint(m_tree.currentStackItem());
 
     m_parser->tokenizer()->setForceNullCharacterReplacement(m_insertionMode == TextMode || inForeignContent);
     m_parser->tokenizer()->setShouldAllowCDATA(inForeignContent);
@@ -537,11 +537,16 @@ void HTMLTreeBuilder::processFakeStartTag(const QualifiedName& tagName, const Ve
     processStartTag(fakeToken.get());
 }
 
+void HTMLTreeBuilder::processFakeEndTag(const AtomicString& tagName)
+{
+    RefPtr<AtomicHTMLToken> fakeToken = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, tagName);
+    processEndTag(fakeToken.get());
+}
+
 void HTMLTreeBuilder::processFakeEndTag(const QualifiedName& tagName)
 {
     // FIXME: We'll need a fancier conversion than just "localName" for SVG/MathML tags.
-    RefPtr<AtomicHTMLToken> fakeToken = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, tagName.localName());
-    processEndTag(fakeToken.get());
+    processFakeEndTag(tagName.localName());
 }
 
 void HTMLTreeBuilder::processFakeCharacters(const String& characters)
@@ -600,32 +605,32 @@ void HTMLTreeBuilder::processIsindexStartTagForInBody(AtomicHTMLToken* token)
 
 namespace {
 
-bool isLi(const ContainerNode* element)
+bool isLi(const HTMLStackItem* item)
 {
-    return element->hasTagName(liTag);
+    return item->hasTagName(liTag);
 }
 
-bool isDdOrDt(const ContainerNode* element)
+bool isDdOrDt(const HTMLStackItem* item)
 {
-    return element->hasTagName(ddTag)
-        || element->hasTagName(dtTag);
+    return item->hasTagName(ddTag)
+        || item->hasTagName(dtTag);
 }
 
 }
 
-template <bool shouldClose(const ContainerNode*)>
+template <bool shouldClose(const HTMLStackItem*)>
 void HTMLTreeBuilder::processCloseWhenNestedTag(AtomicHTMLToken* token)
 {
     m_framesetOk = false;
     HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord();
     while (1) {
-        RefPtr<ContainerNode> node = nodeRecord->node();
-        if (shouldClose(node.get())) {
-            ASSERT(node->isElementNode());
-            processFakeEndTag(toElement(node.get())->tagQName());
+        RefPtr<HTMLStackItem> item = nodeRecord->stackItem();
+        if (shouldClose(item.get())) {
+            ASSERT(item->isElementNode());
+            processFakeEndTag(item->localName());
             break;
         }
-        if (isSpecialNode(node.get()) && !node->hasTagName(addressTag) && !node->hasTagName(divTag) && !node->hasTagName(pTag))
+        if (isSpecialNode(item.get()) && !item->hasTagName(addressTag) && !item->hasTagName(divTag) && !item->hasTagName(pTag))
             break;
         nodeRecord = nodeRecord->next();
     }
@@ -807,7 +812,7 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
     }
     if (isNumberedHeaderTag(token->name())) {
         processFakePEndTagIfPInButtonScope();
-        if (isNumberedHeaderTag(m_tree.currentNode()->localName())) {
+        if (isNumberedHeaderTag(m_tree.currentStackItem()->localName())) {
             parseError(token);
             m_tree.openElements()->pop();
         }
@@ -987,7 +992,7 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
         return;
     }
     if (token->name() == optgroupTag || token->name() == optionTag) {
-        if (m_tree.currentNode()->hasTagName(optionTag)) {
+        if (m_tree.currentStackItem()->hasTagName(optionTag)) {
             RefPtr<AtomicHTMLToken> endOption = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, optionTag.localName());
             processEndTag(endOption.get());
         }
@@ -998,7 +1003,7 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken* token)
     if (token->name() == rpTag || token->name() == rtTag) {
         if (m_tree.openElements()->inScope(rubyTag.localName())) {
             m_tree.generateImpliedEndTags();
-            if (!m_tree.currentNode()->hasTagName(rubyTag))
+            if (!m_tree.currentStackItem()->hasTagName(rubyTag))
                 parseError(token);
         }
         m_tree.insertHTMLElement(token);
@@ -1265,8 +1270,8 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
                 return;
             }
             m_tree.openElements()->popUntilTableBodyScopeMarker();
-            ASSERT(isTableBodyContextTag(m_tree.currentElement()->localName()));
-            processFakeEndTag(m_tree.currentElement()->tagQName());
+            ASSERT(isTableBodyContextTag(m_tree.currentStackItem()->localName()));
+            processFakeEndTag(m_tree.currentStackItem()->localName());
             processStartTag(token);
             return;
         }
@@ -1399,7 +1404,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
             return;
         }
         if (token->name() == optionTag) {
-            if (m_tree.currentNode()->hasTagName(optionTag)) {
+            if (m_tree.currentStackItem()->hasTagName(optionTag)) {
                 RefPtr<AtomicHTMLToken> endOption = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, optionTag.localName());
                 processEndTag(endOption.get());
             }
@@ -1407,11 +1412,11 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
             return;
         }
         if (token->name() == optgroupTag) {
-            if (m_tree.currentNode()->hasTagName(optionTag)) {
+            if (m_tree.currentStackItem()->hasTagName(optionTag)) {
                 RefPtr<AtomicHTMLToken> endOption = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, optionTag.localName());
                 processEndTag(endOption.get());
             }
-            if (m_tree.currentNode()->hasTagName(optgroupTag)) {
+            if (m_tree.currentStackItem()->hasTagName(optgroupTag)) {
                 RefPtr<AtomicHTMLToken> endOptgroup = AtomicHTMLToken::create(HTMLTokenTypes::EndTag, optgroupTag.localName());
                 processEndTag(endOptgroup.get());
             }
@@ -1477,15 +1482,15 @@ void HTMLTreeBuilder::processAnyOtherEndTagForInBody(AtomicHTMLToken* token)
     ASSERT(token->type() == HTMLTokenTypes::EndTag);
     HTMLElementStack::ElementRecord* record = m_tree.openElements()->topRecord();
     while (1) {
-        RefPtr<ContainerNode> node = record->node();
-        if (node->hasLocalName(token->name())) {
+        RefPtr<HTMLStackItem> item = record->stackItem();
+        if (item->hasLocalName(token->name())) {
             m_tree.generateImpliedEndTagsWithExclusion(token->name());
-            if (!m_tree.currentNode()->hasLocalName(token->name()))
+            if (!m_tree.currentStackItem()->hasLocalName(token->name()))
                 parseError(token);
-            m_tree.openElements()->popUntilPopped(toElement(node.get()));
+            m_tree.openElements()->popUntilPopped(item->element());
             return;
         }
-        if (isSpecialNode(node.get())) {
+        if (isSpecialNode(item.get())) {
             parseError(token);
             return;
         }
@@ -1501,7 +1506,7 @@ HTMLElementStack::ElementRecord* HTMLTreeBuilder::furthestBlockForFormattingElem
     for (; record; record = record->next()) {
         if (record->element() == formattingElement)
             return furthestBlock;
-        if (isSpecialNode(record->element()))
+        if (isSpecialNode(record->stackItem().get()))
             furthestBlock = record;
     }
     ASSERT_NOT_REACHED();
@@ -1597,7 +1602,7 @@ void HTMLTreeBuilder::callTheAdoptionAgency(AtomicHTMLToken* token)
             m_tree.fosterParent(lastNode->element());
         else {
             commonAncestor->parserAddChild(lastNode->element());
-            ASSERT(lastNode->node()->isElementNode());
+            ASSERT(lastNode->stackItem()->isElementNode());
             ASSERT(lastNode->element()->parentNode());
             if (lastNode->element()->parentNode()->attached() && !lastNode->element()->attached())
                 lastNode->element()->lazyAttach();
@@ -1698,8 +1703,8 @@ void HTMLTreeBuilder::processEndTagForInTableBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.openElements()->popUntilTableBodyScopeMarker();
-        ASSERT(isTableBodyContextTag(m_tree.currentElement()->localName()));
-        processFakeEndTag(m_tree.currentElement()->tagQName());
+        ASSERT(isTableBodyContextTag(m_tree.currentStackItem()->localName()));
+        processFakeEndTag(m_tree.currentStackItem()->localName());
         processEndTag(token);
         return;
     }
@@ -1759,7 +1764,7 @@ void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTags();
-        if (!m_tree.currentNode()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilPopped(token->name());
         m_tree.activeFormattingElements()->clearToLastMarker();
@@ -1829,7 +1834,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTags();
-        if (!m_tree.currentNode()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilPopped(token->name());
         return;
@@ -1854,7 +1859,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTagsWithExclusion(token->name());
-        if (!m_tree.currentNode()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilPopped(token->name());
         return;
@@ -1865,7 +1870,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTagsWithExclusion(token->name());
-        if (!m_tree.currentNode()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilPopped(token->name());
         return;
@@ -1877,7 +1882,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTagsWithExclusion(token->name());
-        if (!m_tree.currentNode()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilPopped(token->name());
         return;
@@ -1888,7 +1893,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTags();
-        if (!m_tree.currentNode()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilNumberedHeaderElementPopped();
         return;
@@ -1905,7 +1910,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTags();
-        if (!m_tree.currentNode()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilPopped(token->name());
         m_tree.activeFormattingElements()->clearToLastMarker();
@@ -1927,7 +1932,7 @@ bool HTMLTreeBuilder::processCaptionEndTagForInCaption()
         return false;
     }
     m_tree.generateImpliedEndTags();
-    // FIXME: parse error if (!m_tree.currentElement()->hasTagName(captionTag))
+    // FIXME: parse error if (!m_tree.currentStackItem()->hasTagName(captionTag))
     m_tree.openElements()->popUntilPopped(captionTag.localName());
     m_tree.activeFormattingElements()->clearToLastMarker();
     setInsertionMode(InTableMode);
@@ -1942,7 +1947,7 @@ bool HTMLTreeBuilder::processTrEndTagForInRow()
         return false;
     }
     m_tree.openElements()->popUntilTableRowScopeMarker();
-    ASSERT(m_tree.currentElement()->hasTagName(trTag));
+    ASSERT(m_tree.currentStackItem()->hasTagName(trTag));
     m_tree.openElements()->pop();
     setInsertionMode(InTableBodyMode);
     return true;
@@ -2110,9 +2115,9 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
     case InHeadNoscriptMode:
         ASSERT(insertionMode() == InHeadNoscriptMode);
         if (token->name() == noscriptTag) {
-            ASSERT(m_tree.currentElement()->hasTagName(noscriptTag));
+            ASSERT(m_tree.currentStackItem()->hasTagName(noscriptTag));
             m_tree.openElements()->pop();
-            ASSERT(m_tree.currentElement()->hasTagName(headTag));
+            ASSERT(m_tree.currentStackItem()->hasTagName(headTag));
             setInsertionMode(InHeadMode);
             return;
         }
@@ -2126,7 +2131,7 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
     case TextMode:
         if (token->name() == scriptTag) {
             // Pause ourselves so that parsing stops until the script can be processed by the caller.
-            ASSERT(m_tree.currentElement()->hasTagName(scriptTag));
+            ASSERT(m_tree.currentStackItem()->hasTagName(scriptTag));
             m_scriptToProcess = m_tree.currentElement();
             m_tree.openElements()->pop();
             if (isParsingFragment() && m_fragmentContext.scriptingPermission() == DisallowScriptingContent)
@@ -2152,7 +2157,7 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
                 return;
             }
             m_tree.openElements()->pop();
-            if (!isParsingFragment() && !m_tree.currentElement()->hasTagName(framesetTag))
+            if (!isParsingFragment() && !m_tree.currentStackItem()->hasTagName(framesetTag))
                 setInsertionMode(AfterFramesetMode);
             return;
         }
@@ -2187,9 +2192,9 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
     case InSelectMode:
         ASSERT(insertionMode() == InSelectMode || insertionMode() == InSelectInTableMode);
         if (token->name() == optgroupTag) {
-            if (m_tree.currentNode()->hasTagName(optionTag) && m_tree.oneBelowTop() && m_tree.oneBelowTop()->hasTagName(optgroupTag))
+            if (m_tree.currentStackItem()->hasTagName(optionTag) && m_tree.oneBelowTop() && m_tree.oneBelowTop()->hasTagName(optgroupTag))
                 processFakeEndTag(optionTag);
-            if (m_tree.currentNode()->hasTagName(optgroupTag)) {
+            if (m_tree.currentStackItem()->hasTagName(optgroupTag)) {
                 m_tree.openElements()->pop();
                 return;
             }
@@ -2197,7 +2202,7 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken* token)
             return;
         }
         if (token->name() == optionTag) {
-            if (m_tree.currentNode()->hasTagName(optionTag)) {
+            if (m_tree.currentStackItem()->hasTagName(optionTag)) {
                 m_tree.openElements()->pop();
                 return;
             }
@@ -2329,12 +2334,12 @@ ReprocessBuffer:
     case InRowMode: {
         ASSERT(insertionMode() == InTableMode || insertionMode() == InTableBodyMode || insertionMode() == InRowMode);
         ASSERT(m_pendingTableCharacters.isEmpty());
-        if (m_tree.currentNode()->isElementNode()
-            && (m_tree.currentElement()->hasTagName(HTMLNames::tableTag)
-                || m_tree.currentElement()->hasTagName(HTMLNames::tbodyTag)
-                || m_tree.currentElement()->hasTagName(HTMLNames::tfootTag)
-                || m_tree.currentElement()->hasTagName(HTMLNames::theadTag)
-                || m_tree.currentElement()->hasTagName(HTMLNames::trTag))) {
+        if (m_tree.currentStackItem()->isElementNode()
+            && (m_tree.currentStackItem()->hasTagName(HTMLNames::tableTag)
+                || m_tree.currentStackItem()->hasTagName(HTMLNames::tbodyTag)
+                || m_tree.currentStackItem()->hasTagName(HTMLNames::tfootTag)
+                || m_tree.currentStackItem()->hasTagName(HTMLNames::theadTag)
+                || m_tree.currentStackItem()->hasTagName(HTMLNames::trTag))) {
             m_originalInsertionMode = m_insertionMode;
             setInsertionMode(InTableTextMode);
             // Note that we fall through to the InTableTextMode case below.
@@ -2497,7 +2502,7 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken* token)
         return;
     case TextMode:
         parseError(token);
-        if (m_tree.currentNode()->hasTagName(scriptTag))
+        if (m_tree.currentStackItem()->hasTagName(scriptTag))
             notImplemented(); // mark the script element as "already started".
         m_tree.openElements()->pop();
         ASSERT(m_originalInsertionMode != TextMode);
@@ -2651,10 +2656,10 @@ bool HTMLTreeBuilder::shouldProcessTokenInForeignContent(AtomicHTMLToken* token)
 {
     if (m_tree.isEmpty())
         return false;
-    ContainerNode* node = m_tree.currentNode();
-    if (isInHTMLNamespace(node))
+    HTMLStackItem* item = m_tree.currentStackItem();
+    if (isInHTMLNamespace(item))
         return false;
-    if (HTMLElementStack::isMathMLTextIntegrationPoint(node)) {
+    if (HTMLElementStack::isMathMLTextIntegrationPoint(item)) {
         if (token->type() == HTMLTokenTypes::StartTag
             && token->name() != MathMLNames::mglyphTag
             && token->name() != MathMLNames::malignmarkTag)
@@ -2662,11 +2667,11 @@ bool HTMLTreeBuilder::shouldProcessTokenInForeignContent(AtomicHTMLToken* token)
         if (token->type() == HTMLTokenTypes::Character)
             return false;
     }
-    if (node->hasTagName(MathMLNames::annotation_xmlTag)
+    if (item->hasTagName(MathMLNames::annotation_xmlTag)
         && token->type() == HTMLTokenTypes::StartTag
         && token->name() == SVGNames::svgTag)
         return false;
-    if (HTMLElementStack::isHTMLIntegrationPoint(node)) {
+    if (HTMLElementStack::isHTMLIntegrationPoint(item)) {
         if (token->type() == HTMLTokenTypes::StartTag)
             return false;
         if (token->type() == HTMLTokenTypes::Character)
@@ -2732,7 +2737,7 @@ void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token)
             processStartTag(token);
             return;
         }
-        const AtomicString& currentNamespace = m_tree.currentElement()->namespaceURI();
+        const AtomicString& currentNamespace = m_tree.currentStackItem()->namespaceURI();
         if (currentNamespace == MathMLNames::mathmlNamespaceURI)
             adjustMathMLAttributes(token);
         if (currentNamespace == SVGNames::svgNamespaceURI) {
@@ -2744,27 +2749,27 @@ void HTMLTreeBuilder::processTokenInForeignContent(AtomicHTMLToken* token)
         break;
     }
     case HTMLTokenTypes::EndTag: {
-        if (m_tree.currentNode()->namespaceURI() == SVGNames::svgNamespaceURI)
+        if (m_tree.currentStackItem()->namespaceURI() == SVGNames::svgNamespaceURI)
             adjustSVGTagNameCase(token);
 
-        if (token->name() == SVGNames::scriptTag && m_tree.currentNode()->hasTagName(SVGNames::scriptTag)) {
+        if (token->name() == SVGNames::scriptTag && m_tree.currentStackItem()->hasTagName(SVGNames::scriptTag)) {
             m_scriptToProcess = m_tree.currentElement();
             m_tree.openElements()->pop();
             return;
         }
-        if (!isInHTMLNamespace(m_tree.currentNode())) {
+        if (!isInHTMLNamespace(m_tree.currentStackItem())) {
             // FIXME: This code just wants an Element* iterator, instead of an ElementRecord*
             HTMLElementStack::ElementRecord* nodeRecord = m_tree.openElements()->topRecord();
-            if (!nodeRecord->node()->hasLocalName(token->name()))
+            if (!nodeRecord->stackItem()->hasLocalName(token->name()))
                 parseError(token);
             while (1) {
-                if (nodeRecord->node()->hasLocalName(token->name())) {
+                if (nodeRecord->stackItem()->hasLocalName(token->name())) {
                     m_tree.openElements()->popUntilPopped(nodeRecord->element());
                     return;
                 }
                 nodeRecord = nodeRecord->next();
 
-                if (isInHTMLNamespace(nodeRecord->node()))
+                if (isInHTMLNamespace(nodeRecord->stackItem().get()))
                     break;
             }
         }
index 3f2114c..86d229d 100644 (file)
@@ -152,6 +152,7 @@ private:
 
     void processFakeStartTag(const QualifiedName&, const Vector<Attribute>& attributes = Vector<Attribute>());
     void processFakeEndTag(const QualifiedName&);
+    void processFakeEndTag(const AtomicString&);
     void processFakeCharacters(const String&);
     void processFakePEndTagIfPInButtonScope();
 
@@ -178,7 +179,7 @@ private:
 
     void closeTheCell();
 
-    template <bool shouldClose(const ContainerNode*)>
+    template <bool shouldClose(const HTMLStackItem*)>
     void processCloseWhenNestedTag(AtomicHTMLToken*);
 
     bool m_framesetOk;