HTML parser should consistently inspect the namespace of elements on the stack of...
authoradamk@chromium.org <adamk@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 Apr 2013 16:14:40 +0000 (16:14 +0000)
committeradamk@chromium.org <adamk@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 Apr 2013 16:14:40 +0000 (16:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=113723

Reviewed by Adam Barth.

Source/WebCore:

Added HTMLStackItem::matchesHTMLTag method and use that nearly
everywhere instead of HTMLStackItem::hasLocalName. The most important
of these changes is in HTMLElementStack's inScopeCommon() function,
where the use of matchesHTMLTag means that any of the inXXXScope()
calls now only match HTML tags.

Tests: html5lib/generated/run-namespace-sensitivity-data.html
       html5lib/generated/run-namespace-sensitivity-write.html

* html/parser/HTMLConstructionSite.cpp:
(WebCore::HTMLConstructionSite::generateImpliedEndTagsWithExclusion):
* html/parser/HTMLElementStack.cpp:
(WebCore::HTMLElementStack::popUntil):
(WebCore::HTMLElementStack::topmost):
(WebCore::inScopeCommon):
(WebCore::HTMLElementStack::inScope):
(WebCore::HTMLElementStack::inListItemScope):
(WebCore::HTMLElementStack::inTableScope):
(WebCore::HTMLElementStack::inButtonScope):
(WebCore::HTMLElementStack::inSelectScope):
* html/parser/HTMLElementStack.h:
(WebCore::HTMLElementStack::popUntilPopped):
* html/parser/HTMLFormattingElementList.cpp:
(WebCore::HTMLFormattingElementList::closestElementInScopeWithName):
* html/parser/HTMLStackItem.h:
(WebCore::HTMLStackItem::matchesHTMLTag):
(HTMLStackItem):
* html/parser/HTMLTreeBuilder.cpp:
(WebCore::HTMLTreeBuilder::HTMLTreeBuilder):
(WebCore::HTMLTreeBuilder::processAnyOtherEndTagForInBody):
(WebCore::HTMLTreeBuilder::processEndTagForInCell):
(WebCore::HTMLTreeBuilder::processEndTagForInBody):

LayoutTests:

* html5lib/generated/run-namespace-sensitivity-data-expected.txt: Added.
* html5lib/generated/run-namespace-sensitivity-data.html: Added.
* html5lib/generated/run-namespace-sensitivity-write-expected.txt: Added.
* html5lib/generated/run-namespace-sensitivity-write.html: Added.
* html5lib/resources/namespace-sensitivity.dat: Added.

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

13 files changed:
LayoutTests/ChangeLog
LayoutTests/html5lib/generated/run-namespace-sensitivity-data-expected.txt [new file with mode: 0644]
LayoutTests/html5lib/generated/run-namespace-sensitivity-data.html [new file with mode: 0644]
LayoutTests/html5lib/generated/run-namespace-sensitivity-write-expected.txt [new file with mode: 0644]
LayoutTests/html5lib/generated/run-namespace-sensitivity-write.html [new file with mode: 0644]
LayoutTests/html5lib/resources/namespace-sensitivity.dat [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/parser/HTMLConstructionSite.cpp
Source/WebCore/html/parser/HTMLElementStack.cpp
Source/WebCore/html/parser/HTMLElementStack.h
Source/WebCore/html/parser/HTMLFormattingElementList.cpp
Source/WebCore/html/parser/HTMLStackItem.h
Source/WebCore/html/parser/HTMLTreeBuilder.cpp

index 00ebbd1..816ab68 100644 (file)
@@ -1,3 +1,16 @@
+2013-04-02  Adam Klein  <adamk@chromium.org>
+
+        HTML parser should consistently inspect the namespace of elements on the stack of open elements
+        https://bugs.webkit.org/show_bug.cgi?id=113723
+
+        Reviewed by Adam Barth.
+
+        * html5lib/generated/run-namespace-sensitivity-data-expected.txt: Added.
+        * html5lib/generated/run-namespace-sensitivity-data.html: Added.
+        * html5lib/generated/run-namespace-sensitivity-write-expected.txt: Added.
+        * html5lib/generated/run-namespace-sensitivity-write.html: Added.
+        * html5lib/resources/namespace-sensitivity.dat: Added.
+
 2013-04-02  Andrei Bucur  <abucur@adobe.com>
 
         [Chromium] Unreviewed.
diff --git a/LayoutTests/html5lib/generated/run-namespace-sensitivity-data-expected.txt b/LayoutTests/html5lib/generated/run-namespace-sensitivity-data-expected.txt
new file mode 100644 (file)
index 0000000..c2d3845
--- /dev/null
@@ -0,0 +1 @@
+../resources/namespace-sensitivity.dat: PASS
diff --git a/LayoutTests/html5lib/generated/run-namespace-sensitivity-data.html b/LayoutTests/html5lib/generated/run-namespace-sensitivity-data.html
new file mode 100644 (file)
index 0000000..aea5c5f
--- /dev/null
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<script>
+var test_files = [ '../resources/namespace-sensitivity.dat' ]
+</script>
+<script src="../../resources/dump-as-markup.js"></script>
+<script>window.forceDataURLs = true;</script>
+<script src="../resources/runner.js"></script>
diff --git a/LayoutTests/html5lib/generated/run-namespace-sensitivity-write-expected.txt b/LayoutTests/html5lib/generated/run-namespace-sensitivity-write-expected.txt
new file mode 100644 (file)
index 0000000..c2d3845
--- /dev/null
@@ -0,0 +1 @@
+../resources/namespace-sensitivity.dat: PASS
diff --git a/LayoutTests/html5lib/generated/run-namespace-sensitivity-write.html b/LayoutTests/html5lib/generated/run-namespace-sensitivity-write.html
new file mode 100644 (file)
index 0000000..667d171
--- /dev/null
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<script>
+var test_files = [ '../resources/namespace-sensitivity.dat' ]
+</script>
+<script src="../../resources/dump-as-markup.js"></script>
+
+<script src="../resources/runner.js"></script>
diff --git a/LayoutTests/html5lib/resources/namespace-sensitivity.dat b/LayoutTests/html5lib/resources/namespace-sensitivity.dat
new file mode 100644 (file)
index 0000000..ca35c0e
--- /dev/null
@@ -0,0 +1,16 @@
+#data
+<body><table><tr><td><svg><td><foreignObject><span></td>Foo
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     "Foo"
+|     <table>
+|       <tbody>
+|         <tr>
+|           <td>
+|             <svg svg>
+|               <svg td>
+|                 <svg foreignObject>
+|                   <span>
index 3aa6f37..4fcb6bd 100644 (file)
@@ -1,3 +1,43 @@
+2013-04-02  Adam Klein  <adamk@chromium.org>
+
+        HTML parser should consistently inspect the namespace of elements on the stack of open elements
+        https://bugs.webkit.org/show_bug.cgi?id=113723
+
+        Reviewed by Adam Barth.
+
+        Added HTMLStackItem::matchesHTMLTag method and use that nearly
+        everywhere instead of HTMLStackItem::hasLocalName. The most important
+        of these changes is in HTMLElementStack's inScopeCommon() function,
+        where the use of matchesHTMLTag means that any of the inXXXScope()
+        calls now only match HTML tags.
+
+        Tests: html5lib/generated/run-namespace-sensitivity-data.html
+               html5lib/generated/run-namespace-sensitivity-write.html
+
+        * html/parser/HTMLConstructionSite.cpp:
+        (WebCore::HTMLConstructionSite::generateImpliedEndTagsWithExclusion):
+        * html/parser/HTMLElementStack.cpp:
+        (WebCore::HTMLElementStack::popUntil):
+        (WebCore::HTMLElementStack::topmost):
+        (WebCore::inScopeCommon):
+        (WebCore::HTMLElementStack::inScope):
+        (WebCore::HTMLElementStack::inListItemScope):
+        (WebCore::HTMLElementStack::inTableScope):
+        (WebCore::HTMLElementStack::inButtonScope):
+        (WebCore::HTMLElementStack::inSelectScope):
+        * html/parser/HTMLElementStack.h:
+        (WebCore::HTMLElementStack::popUntilPopped):
+        * html/parser/HTMLFormattingElementList.cpp:
+        (WebCore::HTMLFormattingElementList::closestElementInScopeWithName):
+        * html/parser/HTMLStackItem.h:
+        (WebCore::HTMLStackItem::matchesHTMLTag):
+        (HTMLStackItem):
+        * html/parser/HTMLTreeBuilder.cpp:
+        (WebCore::HTMLTreeBuilder::HTMLTreeBuilder):
+        (WebCore::HTMLTreeBuilder::processAnyOtherEndTagForInBody):
+        (WebCore::HTMLTreeBuilder::processEndTagForInCell):
+        (WebCore::HTMLTreeBuilder::processEndTagForInBody):
+
 2013-04-02  Hayato Ito  <hayato@chromium.org>
 
         Report memory usage for ShadowDistributedRules.
index 0684d01..d15b405 100644 (file)
@@ -596,7 +596,7 @@ void HTMLConstructionSite::reconstructTheActiveFormattingElements()
 
 void HTMLConstructionSite::generateImpliedEndTagsWithExclusion(const AtomicString& tagName)
 {
-    while (hasImpliedEndTag(currentStackItem()) && !currentStackItem()->hasLocalName(tagName))
+    while (hasImpliedEndTag(currentStackItem()) && !currentStackItem()->matchesHTMLTag(tagName))
         m_openElements.pop();
 }
 
index 6bb5fb2..0623d57 100644 (file)
@@ -219,15 +219,7 @@ void HTMLElementStack::pop()
 
 void HTMLElementStack::popUntil(const AtomicString& tagName)
 {
-    while (!topStackItem()->hasLocalName(tagName)) {
-        // pop() will ASSERT if a <body>, <head> or <html> will be popped.
-        pop();
-    }
-}
-
-void HTMLElementStack::popUntil(const QualifiedName& tagName)
-{
-    while (!topStackItem()->hasTagName(tagName)) {
+    while (!topStackItem()->matchesHTMLTag(tagName)) {
         // pop() will ASSERT if a <body>, <head> or <html> will be popped.
         pop();
     }
@@ -239,12 +231,6 @@ void HTMLElementStack::popUntilPopped(const AtomicString& tagName)
     pop();
 }
 
-void HTMLElementStack::popUntilPopped(const QualifiedName& tagName)
-{
-    popUntil(tagName);
-    pop();
-}
-
 void HTMLElementStack::popUntilNumberedHeaderElementPopped()
 {
     while (!topStackItem()->isNumberedHeaderElement())
@@ -442,7 +428,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->stackItem()->hasLocalName(tagName))
+        if (pos->stackItem()->matchesHTMLTag(tagName))
             return pos;
     }
     return 0;
@@ -463,21 +449,7 @@ bool inScopeCommon(HTMLElementStack::ElementRecord* top, const AtomicString& tar
 {
     for (HTMLElementStack::ElementRecord* pos = top; pos; pos = pos->next()) {
         HTMLStackItem* item = pos->stackItem().get();
-        if (item->hasLocalName(targetTag))
-            return true;
-        if (isMarker(item))
-            return false;
-    }
-    ASSERT_NOT_REACHED(); // <html> is always on the stack and is a scope marker.
-    return false;
-}
-
-template <bool isMarker(HTMLStackItem*)>
-bool inScopeCommon(HTMLElementStack::ElementRecord* top, const QualifiedName& targetTag)
-{
-    for (HTMLElementStack::ElementRecord* pos = top; pos; pos = pos->next()) {
-        HTMLStackItem* item = pos->stackItem().get();
-        if (item->hasTagName(targetTag))
+        if (item->matchesHTMLTag(targetTag))
             return true;
         if (isMarker(item))
             return false;
@@ -519,7 +491,6 @@ bool HTMLElementStack::inScope(const AtomicString& targetTag) const
 
 bool HTMLElementStack::inScope(const QualifiedName& tagName) const
 {
-    // FIXME: Is localName() right for non-html elements?
     return inScope(tagName.localName());
 }
 
@@ -530,7 +501,6 @@ bool HTMLElementStack::inListItemScope(const AtomicString& targetTag) const
 
 bool HTMLElementStack::inListItemScope(const QualifiedName& tagName) const
 {
-    // FIXME: Is localName() right for non-html elements?
     return inListItemScope(tagName.localName());
 }
 
@@ -541,7 +511,7 @@ bool HTMLElementStack::inTableScope(const AtomicString& targetTag) const
 
 bool HTMLElementStack::inTableScope(const QualifiedName& tagName) const
 {
-    return inScopeCommon<isTableScopeMarker>(m_top.get(), tagName);
+    return inTableScope(tagName.localName());
 }
 
 bool HTMLElementStack::inButtonScope(const AtomicString& targetTag) const
@@ -551,7 +521,6 @@ bool HTMLElementStack::inButtonScope(const AtomicString& targetTag) const
 
 bool HTMLElementStack::inButtonScope(const QualifiedName& tagName) const
 {
-    // FIXME: Is localName() right for non-html elements?
     return inButtonScope(tagName.localName());
 }
 
@@ -562,7 +531,6 @@ bool HTMLElementStack::inSelectScope(const AtomicString& targetTag) const
 
 bool HTMLElementStack::inSelectScope(const QualifiedName& tagName) const
 {
-    // FIXME: Is localName() right for non-html elements?
     return inSelectScope(tagName.localName());
 }
 
index 5be211a..e6aa6b7 100644 (file)
@@ -116,10 +116,7 @@ public:
     void popUntil(const AtomicString& tagName);
     void popUntil(Element*);
     void popUntilPopped(const AtomicString& tagName);
-
-    // FIXME: These are fixes for https://www.w3.org/Bugs/Public/show_bug.cgi?id=21292
-    void popUntil(const QualifiedName&);
-    void popUntilPopped(const QualifiedName&);
+    void popUntilPopped(const QualifiedName& tagName) { popUntilPopped(tagName.localName()); }
 
     void popUntilPopped(Element*);
     void popUntilNumberedHeaderElementPopped();
index 4283f6e..f6f9a28 100644 (file)
@@ -54,7 +54,7 @@ Element* HTMLFormattingElementList::closestElementInScopeWithName(const AtomicSt
         const Entry& entry = m_entries[m_entries.size() - i];
         if (entry.isMarker())
             return 0;
-        if (entry.stackItem()->hasLocalName(targetName))
+        if (entry.stackItem()->matchesHTMLTag(targetName))
             return entry.element();
     }
     return 0;
index d9354bb..953a679 100644 (file)
@@ -78,6 +78,9 @@ public:
     bool hasLocalName(const AtomicString& name) const { return m_tokenLocalName == name; }
     bool hasTagName(const QualifiedName& name) const { return m_tokenLocalName == name.localName() && m_namespaceURI == name.namespaceURI(); }
 
+    bool matchesHTMLTag(const AtomicString& name) const { return m_tokenLocalName == name && m_namespaceURI == HTMLNames::xhtmlNamespaceURI; }
+    bool matchesHTMLTag(const QualifiedName& name) const { return m_tokenLocalName == name && m_namespaceURI == HTMLNames::xhtmlNamespaceURI; }
+
     bool causesFosterParenting()
     {
         return hasTagName(HTMLNames::tableTag)
index 10f0071..6a245b3 100644 (file)
@@ -305,7 +305,7 @@ HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, DocumentFragment* f
         m_tree.openElements()->pushRootNode(HTMLStackItem::create(fragment, HTMLStackItem::ItemForDocumentFragmentNode));
 
 #if ENABLE(TEMPLATE_ELEMENT)
-        if (contextElement->hasLocalName(templateTag))
+        if (contextElement->hasTagName(templateTag))
             m_templateInsertionModes.append(TemplateContentsMode);
 #endif
 
@@ -1504,9 +1504,9 @@ void HTMLTreeBuilder::processAnyOtherEndTagForInBody(AtomicHTMLToken* token)
     HTMLElementStack::ElementRecord* record = m_tree.openElements()->topRecord();
     while (1) {
         RefPtr<HTMLStackItem> item = record->stackItem();
-        if (item->hasLocalName(token->name())) {
+        if (item->matchesHTMLTag(token->name())) {
             m_tree.generateImpliedEndTagsWithExclusion(token->name());
-            if (!m_tree.currentStackItem()->hasLocalName(token->name()))
+            if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
                 parseError(token);
             m_tree.openElements()->popUntilPopped(item->element());
             return;
@@ -1784,7 +1784,7 @@ void HTMLTreeBuilder::processEndTagForInCell(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTags();
-        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilPopped(token->name());
         m_tree.activeFormattingElements()->clearToLastMarker();
@@ -1859,7 +1859,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTags();
-        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilPopped(token->name());
         return;
@@ -1884,7 +1884,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTagsWithExclusion(token->name());
-        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilPopped(token->name());
         return;
@@ -1895,7 +1895,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTagsWithExclusion(token->name());
-        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilPopped(token->name());
         return;
@@ -1907,7 +1907,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTagsWithExclusion(token->name());
-        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilPopped(token->name());
         return;
@@ -1918,7 +1918,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTags();
-        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilNumberedHeaderElementPopped();
         return;
@@ -1935,7 +1935,7 @@ void HTMLTreeBuilder::processEndTagForInBody(AtomicHTMLToken* token)
             return;
         }
         m_tree.generateImpliedEndTags();
-        if (!m_tree.currentStackItem()->hasLocalName(token->name()))
+        if (!m_tree.currentStackItem()->matchesHTMLTag(token->name()))
             parseError(token);
         m_tree.openElements()->popUntilPopped(token->name());
         m_tree.activeFormattingElements()->clearToLastMarker();