2010-09-13 Adam Barth <abarth@webkit.org>
authorabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Sep 2010 09:19:27 +0000 (09:19 +0000)
committerabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Sep 2010 09:19:27 +0000 (09:19 +0000)
        Reviewed by Eric Seidel.

        Apply spec changes to InForeignContentMode
        https://bugs.webkit.org/show_bug.cgi?id=45636

        Add some tests of breaking out of foreign content.

        * html5lib/resources/webkit01.dat:
2010-09-13  Adam Barth  <abarth@webkit.org>

        Reviewed by Eric Seidel.

        Apply spec changes to InForeignContentMode
        https://bugs.webkit.org/show_bug.cgi?id=45636

        Now breaking out of foreign content doesn't always bring you back to
        HTML.  If you have a foreign content element that can contain HTML, you
        just get brought back to that element.

        * html/parser/HTMLElementStack.cpp:
        (WebCore::HTMLNames::isForeignContentScopeMarker):
        (WebCore::HTMLElementStack::popUntilForeignContentScopeMarker):
        * html/parser/HTMLElementStack.h:
        * html/parser/HTMLTreeBuilder.cpp:
        (WebCore::HTMLTreeBuilder::processStartTag):
        (WebCore::HTMLTreeBuilder::processEndOfFile):

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

LayoutTests/ChangeLog
LayoutTests/html5lib/resources/webkit01.dat
WebCore/ChangeLog
WebCore/html/parser/HTMLElementStack.cpp
WebCore/html/parser/HTMLElementStack.h
WebCore/html/parser/HTMLTreeBuilder.cpp

index f917e1f..b1115c0 100644 (file)
@@ -1,3 +1,14 @@
+2010-09-13  Adam Barth  <abarth@webkit.org>
+
+        Reviewed by Eric Seidel.
+
+        Apply spec changes to InForeignContentMode
+        https://bugs.webkit.org/show_bug.cgi?id=45636
+
+        Add some tests of breaking out of foreign content.
+
+        * html5lib/resources/webkit01.dat:
+
 2010-09-12  Adam Barth  <abarth@webkit.org>
 
         Reviewed by Eric Seidel.
index a4cbde0..4297b69 100644 (file)
@@ -472,3 +472,38 @@ console.log("FOO<span>BAR</span>BAZ");
 |       <a>
 |         <title>
 |       <a>
+
+#data
+<svg><title><div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <svg svg>
+|       <svg title>
+|         <div>
+
+#data
+<svg><title><rect><div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <svg svg>
+|       <svg title>
+|         <rect>
+|           <div>
+
+#data
+<svg><title><svg><div>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <svg svg>
+|       <svg title>
+|         <svg svg>
+|         <div>
index acbee97..cb848db 100644 (file)
@@ -2,6 +2,25 @@
 
         Reviewed by Eric Seidel.
 
+        Apply spec changes to InForeignContentMode
+        https://bugs.webkit.org/show_bug.cgi?id=45636
+
+        Now breaking out of foreign content doesn't always bring you back to
+        HTML.  If you have a foreign content element that can contain HTML, you
+        just get brought back to that element.
+
+        * html/parser/HTMLElementStack.cpp:
+        (WebCore::HTMLNames::isForeignContentScopeMarker):
+        (WebCore::HTMLElementStack::popUntilForeignContentScopeMarker):
+        * html/parser/HTMLElementStack.h:
+        * html/parser/HTMLTreeBuilder.cpp:
+        (WebCore::HTMLTreeBuilder::processStartTag):
+        (WebCore::HTMLTreeBuilder::processEndOfFile):
+
+2010-09-13  Adam Barth  <abarth@webkit.org>
+
+        Reviewed by Eric Seidel.
+
         Convert notImplemented() to ASSERT_NOT_REACHED
         https://bugs.webkit.org/show_bug.cgi?id=45639
 
index b6f4111..2439897 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "Element.h"
 #include "HTMLNames.h"
+#include "MathMLNames.h"
 #include <wtf/PassOwnPtr.h>
 
 #if ENABLE(SVG)
@@ -92,6 +93,19 @@ inline bool isTableRowScopeMarker(Element* element)
         || element->hasTagName(htmlTag);
 }
 
+inline bool isForeignContentScopeMarker(Element* element)
+{
+    return element->hasTagName(MathMLNames::miTag)
+        || element->hasTagName(MathMLNames::moTag)
+        || element->hasTagName(MathMLNames::mnTag)
+        || element->hasTagName(MathMLNames::msTag)
+        || element->hasTagName(MathMLNames::mtextTag)
+        || element->hasTagName(SVGNames::foreignObjectTag)
+        || element->hasTagName(SVGNames::descTag)
+        || element->hasTagName(SVGNames::titleTag)
+        || element->namespaceURI() == HTMLNames::xhtmlNamespaceURI;
+}
+
 inline bool isButtonScopeMarker(Element* element)
 {
     return isScopeMarker(element)
@@ -186,12 +200,6 @@ void HTMLElementStack::pop()
     popCommon();
 }
 
-void HTMLElementStack::popUntilElementWithNamespace(const AtomicString& namespaceURI)
-{
-    while (top()->namespaceURI() != namespaceURI)
-        pop();
-}
-
 void HTMLElementStack::popUntil(const AtomicString& tagName)
 {
     while (!top()->hasLocalName(tagName)) {
@@ -247,6 +255,12 @@ void HTMLElementStack::popUntilTableRowScopeMarker()
         pop();
 }
 
+void HTMLElementStack::popUntilForeignContentScopeMarker()
+{
+    while (!isForeignContentScopeMarker(top()))
+        pop();
+}
+
 void HTMLElementStack::pushHTMLHtmlElement(PassRefPtr<Element> element)
 {
     ASSERT(!m_top); // <html> should always be the bottom of the stack.
index 73cfcb1..47fa603 100644 (file)
@@ -90,7 +90,6 @@ public:
 
     void pop();
     void popUntil(const AtomicString& tagName);
-    void popUntilElementWithNamespace(const AtomicString& namespaceURI);
     void popUntil(Element*);
     void popUntilPopped(const AtomicString& tagName);
     void popUntilPopped(Element*);
@@ -98,6 +97,7 @@ public:
     void popUntilTableScopeMarker(); // "clear the stack back to a table context" in the spec.
     void popUntilTableBodyScopeMarker(); // "clear the stack back to a table body context" in the spec.
     void popUntilTableRowScopeMarker(); // "clear the stack back to a table row context" in the spec.
+    void popUntilForeignContentScopeMarker();
     void popHTMLHeadElement();
     void popHTMLBodyElement();
     void popAll();
index 74535d3..47bd30a 100644 (file)
@@ -1486,7 +1486,6 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
         processStartTag(token);
         break;
     case InForeignContentMode: {
-        // FIXME: We're missing a bunch of if branches here.
         if (shouldProcessUsingSecondaryInsertionMode(token, m_tree.currentElement())) {
             processUsingSecondaryInsertionModeAndAdjustInsertionMode(token);
             return;
@@ -1531,8 +1530,10 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
             || token.name() == ulTag
             || token.name() == varTag
             || (token.name() == fontTag && (token.getAttributeItem(colorAttr) || token.getAttributeItem(faceAttr) || token.getAttributeItem(sizeAttr)))) {
-            m_tree.openElements()->popUntilElementWithNamespace(xhtmlNamespaceURI);
-            setInsertionMode(m_secondaryInsertionMode);
+            parseError(token);
+            m_tree.openElements()->popUntilForeignContentScopeMarker();
+            if (insertionMode() == InForeignContentMode && m_tree.openElements()->hasOnlyHTMLElementsInScope())
+                setInsertionMode(m_secondaryInsertionMode);
             processStartTag(token);
             return;
         }
@@ -2636,9 +2637,11 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken& token)
         return;
     case InForeignContentMode:
         parseError(token);
-        // FIXME: Following the spec would infinitely recurse on <svg><svg>
-        // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10115
-        m_tree.openElements()->popUntilElementWithNamespace(xhtmlNamespaceURI);
+        m_tree.openElements()->popUntilForeignContentScopeMarker();
+        // FIXME: The spec adds the following condition before setting the
+        //        insertion mode.  However, this condition causes an infinite loop.
+        //        See http://www.w3.org/Bugs/Public/show_bug.cgi?id=10621
+        //        if (insertionMode() == InForeignContentMode && m_tree.openElements()->hasOnlyHTMLElementsInScope())
         setInsertionMode(m_secondaryInsertionMode);
         processEndOfFile(token);
         return;