2010-07-06 Eric Seidel <eric@webkit.org>
authorabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Jul 2010 17:28:39 +0000 (17:28 +0000)
committerabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Jul 2010 17:28:39 +0000 (17:28 +0000)
        Reviewed by Adam Barth.

        Add processing for "in cell" mode and end tag processing for "in row"
        https://bugs.webkit.org/show_bug.cgi?id=41688

        I added several new table tests, not all of which pass yet.
        Remaining failures exist due to lack of full "in table body" mode
        support, which Adam has an outstanding patch for.
        I believe all of the various branches added by this change are
        covered now by our tests.

        * html/HTMLElementStack.cpp:
         - Added QualifiedName versions of inScope functions.
           Using tagName.localName() is wrong for non-HTML elements,
           in preparation for supporting foreign content we should centralize
           our handling of QualifiedName in these functions instead of
           sprinkling more .localName() calls around the code.
        (WebCore::HTMLElementStack::inScope):
        (WebCore::HTMLElementStack::inListItemScope):
        (WebCore::HTMLElementStack::inTableScope):
        * html/HTMLElementStack.h:
        * html/HTMLFormattingElementList.cpp:
        (WebCore::HTMLFormattingElementList::Entry::operator==):
        (WebCore::HTMLFormattingElementList::Entry::operator!=):
         - Calling element() on markers will assert, so use m_element.
        * html/HTMLTreeBuilder.cpp:
        (WebCore::HTMLTreeBuilder::closeTheCell):
         - Implemented per the spec.
        (WebCore::HTMLTreeBuilder::processStartTag):
         - Use isTableBodyContextTag where possible.
         - Add InCellMode.
        (WebCore::HTMLTreeBuilder::resetInsertionModeAppropriately):
         - Use isTableBodyContextTag where possible.
        (WebCore::HTMLTreeBuilder::processTrEndTagForInRow):
         - This code is needed from at least two callsites.
        (WebCore::HTMLTreeBuilder::processEndTag):
         - Add InCellMode and InRowMode
        (WebCore::HTMLTreeBuilder::processCharacter):
        (WebCore::HTMLTreeBuilder::processEndOfFile):
        * html/HTMLTreeBuilder.h:
2010-07-06  Eric Seidel  <eric@webkit.org>

        Reviewed by Adam Barth.

        Add processing for "in cell" mode and end tag processing for "in row"
        https://bugs.webkit.org/show_bug.cgi?id=41688

        * html5lib/resources/tables01.dat:
        * html5lib/runner-expected-html5.txt:
        * html5lib/runner-expected.txt:

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

LayoutTests/ChangeLog
LayoutTests/html5lib/resources/tables01.dat
LayoutTests/html5lib/runner-expected-html5.txt
LayoutTests/html5lib/runner-expected.txt
WebCore/ChangeLog
WebCore/html/HTMLElementStack.cpp
WebCore/html/HTMLElementStack.h
WebCore/html/HTMLFormattingElementList.cpp
WebCore/html/HTMLTreeBuilder.cpp
WebCore/html/HTMLTreeBuilder.h

index 6cfacb7..7e2eb62 100644 (file)
@@ -2,6 +2,17 @@
 
         Reviewed by Adam Barth.
 
+        Add processing for "in cell" mode and end tag processing for "in row"
+        https://bugs.webkit.org/show_bug.cgi?id=41688
+
+        * html5lib/resources/tables01.dat:
+        * html5lib/runner-expected-html5.txt:
+        * html5lib/runner-expected.txt:
+
+2010-07-06  Eric Seidel  <eric@webkit.org>
+
+        Reviewed by Adam Barth.
+
         Make <a> auto-close any parent <a> tag
         https://bugs.webkit.org/show_bug.cgi?id=41684
 
index 5f830f1..9275ad3 100644 (file)
 |         <tr>
 |           <td>
 |             "B"
+
+#data
+<table><td></body></caption></col></colgroup></html>foo
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <tr>
+|           <td>
+|             "foo"
+
+#data
+<table><td>A</table>B
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <tr>
+|           <td>
+|             "A"
+|     "B"
+
+#data
+<table><tr><caption>
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <tr>
+|       <caption>
+
+#data
+<table><tr></body></caption></col></colgroup></html></td></th><td>foo
+#errors
+#document
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <tr>
+|           <td>
+|             "foo"
index d352367..4ce30de 100644 (file)
@@ -3,7 +3,6 @@ CONSOLE MESSAGE: line 2: PASS
 CONSOLE MESSAGE: line 2: FOO<span>BAR</span>BAZ
 Content-Type: text/plain
 resources/tests1.dat:
-20
 21
 30
 32
@@ -15,8 +14,6 @@ resources/tests1.dat:
 80
 86
 90
-93
-94
 103
 104
 107
@@ -24,28 +21,6 @@ resources/tests1.dat:
 110
 112
 
-Test 20 of 113 in resources/tests1.dat failed. Input:
-<b><table><td><i></table>
-Got:
-| <html>
-|   <head>
-|   <body>
-|     <b>
-|       <table>
-|         <tbody>
-|           <tr>
-|             <td>
-Expected:
-| <html>
-|   <head>
-|   <body>
-|     <b>
-|       <table>
-|         <tbody>
-|           <tr>
-|             <td>
-|               <i>
-
 Test 21 of 113 in resources/tests1.dat failed. Input:
 <b><table><td></b><i></table>X
 Got:
@@ -57,6 +32,7 @@ Got:
 |         <tbody>
 |           <tr>
 |             <td>
+|               <i>
 Expected:
 | <html>
 |   <head>
@@ -80,6 +56,9 @@ Got:
 |         <tbody>
 |           <tr>
 |             <td>
+|               <a>
+|                 <table>
+|               <a>
 Expected:
 | <html>
 |   <head>
@@ -117,7 +96,9 @@ Got:
 |           <tbody>
 |             <tr>
 |               <th>
-|                 <!-- X -->
+|                 <i>
+|                   "please!"
+|             <!-- X -->
 Expected:
 | <!-- - -->
 | <html>
@@ -265,6 +246,9 @@ Got:
 |         <tbody>
 |           <tr>
 |             <td>
+|               <a>
+|                 href="foo"
+|                 "br"
 Expected:
 | <html>
 |   <head>
@@ -294,6 +278,9 @@ Got:
 |       <tbody>
 |         <tr>
 |           <td>
+|             <a>
+|               href="foo"
+|               "br"
 Expected:
 | <html>
 |   <head>
@@ -325,6 +312,9 @@ Got:
 |       <tbody>
 |         <tr>
 |           <td>
+|             <span>
+|               <span>
+|                 "X"
 Expected:
 | <html>
 |   <head>
@@ -365,50 +355,6 @@ Expected:
 |     <div>
 |       <a>
 
-Test 93 of 113 in resources/tests1.dat failed. Input:
-<b><table><td><i></table>
-Got:
-| <html>
-|   <head>
-|   <body>
-|     <b>
-|       <table>
-|         <tbody>
-|           <tr>
-|             <td>
-Expected:
-| <html>
-|   <head>
-|   <body>
-|     <b>
-|       <table>
-|         <tbody>
-|           <tr>
-|             <td>
-|               <i>
-
-Test 94 of 113 in resources/tests1.dat failed. Input:
-<b><table><td></b><i></table>
-Got:
-| <html>
-|   <head>
-|   <body>
-|     <b>
-|       <table>
-|         <tbody>
-|           <tr>
-|             <td>
-Expected:
-| <html>
-|   <head>
-|   <body>
-|     <b>
-|       <table>
-|         <tbody>
-|           <tr>
-|             <td>
-|               <i>
-
 Test 103 of 113 in resources/tests1.dat failed. Input:
 <a><table><td><a><table></table><a></tr><a></table><a>
 Got:
@@ -420,6 +366,9 @@ Got:
 |         <tbody>
 |           <tr>
 |             <td>
+|               <a>
+|                 <table>
+|               <a>
 Expected:
 | <html>
 |   <head>
@@ -483,6 +432,7 @@ Got:
 |         <tbody>
 |           <tr>
 |             <td>
+|               <h3>
 Expected:
 | <html>
 |   <head>
@@ -506,6 +456,7 @@ Got:
 |         <col>
 |       <tbody>
 |         <tr>
+|         <tr>
 |           <td>
 Expected:
 | <html>
@@ -537,6 +488,7 @@ Got:
 |       <colgroup>
 |       <tbody>
 |         <tr>
+|         <tr>
 |           <td>
 Expected:
 | <html>
@@ -573,36 +525,13 @@ Expected:
 |         <tr>
 |     <p>
 resources/tests2.dat:
-4
 9
 11
 13
-34
 36
 47
 48
 49
-58
-
-Test 4 of 59 in resources/tests2.dat failed. Input:
-<table><td>test</tbody></table>
-Got:
-| <html>
-|   <head>
-|   <body>
-|     <table>
-|       <tbody>
-|         <tr>
-|           <td>
-Expected:
-| <html>
-|   <head>
-|   <body>
-|     <table>
-|       <tbody>
-|         <tr>
-|           <td>
-|             "test"
 
 Test 9 of 59 in resources/tests2.dat failed. Input:
 <!DOCTYPE html><dt><div><dd>
@@ -650,6 +579,7 @@ Got:
 |     <table>
 |       <tbody>
 |         <tr>
+|           "TEST"
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -660,32 +590,6 @@ Expected:
 |       <tbody>
 |         <tr>
 
-Test 34 of 59 in resources/tests2.dat failed. Input:
-<!DOCTYPE html><table><caption>test TEST</caption><td>test
-Got:
-| <!DOCTYPE html>
-| <html>
-|   <head>
-|   <body>
-|     <table>
-|       <caption>
-|         "test TEST"
-|       <tbody>
-|         <tr>
-|           <td>
-Expected:
-| <!DOCTYPE html>
-| <html>
-|   <head>
-|   <body>
-|     <table>
-|       <caption>
-|         "test TEST"
-|       <tbody>
-|         <tr>
-|           <td>
-|             "test"
-
 Test 36 of 59 in resources/tests2.dat failed. Input:
 <!DOCTYPE html><select><optgroup><option></optgroup><option><select><option>
 Got:
@@ -764,28 +668,6 @@ Expected:
 |       "x"
 |     "  "
 |   <body>
-
-Test 58 of 59 in resources/tests2.dat failed. Input:
-<!DOCTYPE html><table><tr><td></p></table>
-Got:
-| <!DOCTYPE html>
-| <html>
-|   <head>
-|   <body>
-|     <table>
-|       <tbody>
-|         <tr>
-|           <td>
-Expected:
-| <!DOCTYPE html>
-| <html>
-|   <head>
-|   <body>
-|     <table>
-|       <tbody>
-|         <tr>
-|           <td>
-|             <p>
 resources/tests3.dat:
 16
 17
@@ -1315,7 +1197,6 @@ resources/tests7.dat:
 19
 20
 24
-26
 27
 28
 29
@@ -1369,6 +1250,9 @@ Got:
 |       <tbody>
 |         <tr>
 |           <td>
+|             <table>
+|               " "
+|               <meta>
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -1421,6 +1305,7 @@ Got:
 |     <table>
 |       <tbody>
 |         <tr>
+|           "x  "
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -1557,27 +1442,6 @@ Expected:
 | <body>
 |   "X"
 
-Test 26 of 30 in resources/tests7.dat failed. Input:
-<table><tr><td><code></code> </table>
-Got:
-| <html>
-|   <head>
-|   <body>
-|     <table>
-|       <tbody>
-|         <tr>
-|           <td>
-Expected:
-| <html>
-|   <head>
-|   <body>
-|     <table>
-|       <tbody>
-|         <tr>
-|           <td>
-|             <code>
-|             " "
-
 Test 27 of 30 in resources/tests7.dat failed. Input:
 <table><b><tr><td>aaa</td></tr>bbb</table>ccc
 Got:
@@ -1589,6 +1453,7 @@ Got:
 |       <tbody>
 |         <tr>
 |           <td>
+|             "aaa"
 Expected:
 | <html>
 |   <head>
@@ -1614,6 +1479,7 @@ Got:
 |     <table>
 |       <tbody>
 |         <tr>
+|           " B"
 Expected:
 | <html>
 |   <head>
@@ -1633,6 +1499,7 @@ Got:
 |     <table>
 |       <tbody>
 |         <tr>
+|           " B"
 Expected:
 | <html>
 |   <head>
@@ -1959,6 +1826,7 @@ Got:
 |     <table>
 |       <tbody>
 |         <tr>
+|           "foobar"
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -1984,6 +1852,11 @@ Got:
 |       <tbody>
 |         <tr>
 |           <td>
+|             <math>
+|               <mi>
+|                 "foo"
+|               <mi>
+|                 "bar"
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -2010,6 +1883,13 @@ Got:
 |       <tbody>
 |         <tr>
 |           <td>
+|             <math>
+|               <mi>
+|                 "foo"
+|               <mi>
+|                 "bar"
+|             <p>
+|               "baz"
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -2172,6 +2052,8 @@ Got:
 |       <tbody>
 |         <tr>
 |           <td>
+|             <select>
+|               "foobarbaz"
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -2506,6 +2388,7 @@ Got:
 |     <table>
 |       <tbody>
 |         <tr>
+|           "foobar"
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -2531,6 +2414,11 @@ Got:
 |       <tbody>
 |         <tr>
 |           <td>
+|             <svg>
+|               <g>
+|                 "foo"
+|               <g>
+|                 "bar"
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -2557,6 +2445,13 @@ Got:
 |       <tbody>
 |         <tr>
 |           <td>
+|             <svg>
+|               <g>
+|                 "foo"
+|               <g>
+|                 "bar"
+|             <p>
+|               "baz"
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -2719,6 +2614,8 @@ Got:
 |       <tbody>
 |         <tr>
 |           <td>
+|             <select>
+|               "foobarbaz"
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -3866,6 +3763,7 @@ Got:
 |         <tbody>
 |           <tr>
 |             <td>
+|               <img>
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -3920,6 +3818,7 @@ Got:
 |                   <tbody>
 |                     <tr>
 |                       <td>
+|                         <img>
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -4097,6 +3996,7 @@ Got:
 |     <table>
 |       <tbody>
 |         <tr>
+|           " x"
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -4145,6 +4045,8 @@ Got:
 |         <tbody>
 |           <tr>
 |             <td>
+|               "bar"
+|             " "
 Expected:
 | <!DOCTYPE html>
 | <html>
@@ -4160,33 +4062,8 @@ Expected:
 |             <td>
 |               "bar"
 |             " "
-resources/tests16.dat:
-188
+resources/tests16.dat: PASS
 
-Test 188 of 189 in resources/tests16.dat failed. Input:
-<!doctype html><table><td><span><font></span><span>
-Got:
-| <!DOCTYPE html>
-| <html>
-|   <head>
-|   <body>
-|     <table>
-|       <tbody>
-|         <tr>
-|           <td>
-Expected:
-| <!DOCTYPE html>
-| <html>
-|   <head>
-|   <body>
-|     <table>
-|       <tbody>
-|         <tr>
-|           <td>
-|             <span>
-|               <font>
-|             <font>
-|               <span>
 resources/webkit01.dat: PASS
 
 resources/doctype01.dat: PASS
@@ -4339,8 +4216,10 @@ resources/tables01.dat:
 8
 9
 10
+12
+13
 
-Test 4 of 10 in resources/tables01.dat failed. Input:
+Test 4 of 14 in resources/tables01.dat failed. Input:
 <table><colgroup></html>foo
 Got:
 | <html>
@@ -4357,7 +4236,7 @@ Expected:
 |     <table>
 |       <colgroup>
 
-Test 7 of 10 in resources/tables01.dat failed. Input:
+Test 7 of 14 in resources/tables01.dat failed. Input:
 <table><select><option>3</select></table>
 Got:
 | <html>
@@ -4376,7 +4255,7 @@ Expected:
 |         "3"
 |     <table>
 
-Test 8 of 10 in resources/tables01.dat failed. Input:
+Test 8 of 14 in resources/tables01.dat failed. Input:
 <table><select><table></table></select></table>
 Got:
 | <html>
@@ -4392,7 +4271,7 @@ Expected:
 |     <table>
 |     <table>
 
-Test 9 of 10 in resources/tables01.dat failed. Input:
+Test 9 of 14 in resources/tables01.dat failed. Input:
 <table><select></table>
 Got:
 | <html>
@@ -4407,7 +4286,7 @@ Expected:
 |     <select>
 |     <table>
 
-Test 10 of 10 in resources/tables01.dat failed. Input:
+Test 10 of 14 in resources/tables01.dat failed. Input:
 <table><select><option>A<tr><td>B</td></tr></table>
 Got:
 | <html>
@@ -4420,6 +4299,7 @@ Got:
 |       <tbody>
 |         <tr>
 |           <td>
+|             "B"
 Expected:
 | <html>
 |   <head>
@@ -4432,4 +4312,44 @@ Expected:
 |         <tr>
 |           <td>
 |             "B"
+
+Test 12 of 14 in resources/tables01.dat failed. Input:
+<table><td>A</table>B
+Got:
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <tr>
+|           <td>
+|             "A"
+Expected:
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <tr>
+|           <td>
+|             "A"
+|     "B"
+
+Test 13 of 14 in resources/tables01.dat failed. Input:
+<table><tr><caption>
+Got:
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <tr>
+Expected:
+| <html>
+|   <head>
+|   <body>
+|     <table>
+|       <tbody>
+|         <tr>
+|       <caption>
 #EOF
index f59931e..2780927 100644 (file)
@@ -5135,7 +5135,7 @@ resources/tables01.dat:
 8
 9
 
-Test 3 of 10 in resources/tables01.dat failed. Input:
+Test 3 of 14 in resources/tables01.dat failed. Input:
 <table><col foo='bar'>
 Got:
 | <html>
@@ -5153,7 +5153,7 @@ Expected:
 |         <col>
 |           foo="bar"
 
-Test 7 of 10 in resources/tables01.dat failed. Input:
+Test 7 of 14 in resources/tables01.dat failed. Input:
 <table><select><option>3</select></table>
 Got:
 | <html>
@@ -5173,7 +5173,7 @@ Expected:
 |         "3"
 |     <table>
 
-Test 8 of 10 in resources/tables01.dat failed. Input:
+Test 8 of 14 in resources/tables01.dat failed. Input:
 <table><select><table></table></select></table>
 Got:
 | <html>
@@ -5191,7 +5191,7 @@ Expected:
 |     <table>
 |     <table>
 
-Test 9 of 10 in resources/tables01.dat failed. Input:
+Test 9 of 14 in resources/tables01.dat failed. Input:
 <table><select></table>
 Got:
 | <html>
index 97e2589..f5fab4a 100644 (file)
@@ -2,6 +2,49 @@
 
         Reviewed by Adam Barth.
 
+        Add processing for "in cell" mode and end tag processing for "in row"
+        https://bugs.webkit.org/show_bug.cgi?id=41688
+
+        I added several new table tests, not all of which pass yet.
+        Remaining failures exist due to lack of full "in table body" mode
+        support, which Adam has an outstanding patch for.
+        I believe all of the various branches added by this change are
+        covered now by our tests.
+
+        * html/HTMLElementStack.cpp:
+         - Added QualifiedName versions of inScope functions.
+           Using tagName.localName() is wrong for non-HTML elements,
+           in preparation for supporting foreign content we should centralize
+           our handling of QualifiedName in these functions instead of
+           sprinkling more .localName() calls around the code.
+        (WebCore::HTMLElementStack::inScope):
+        (WebCore::HTMLElementStack::inListItemScope):
+        (WebCore::HTMLElementStack::inTableScope):
+        * html/HTMLElementStack.h:
+        * html/HTMLFormattingElementList.cpp:
+        (WebCore::HTMLFormattingElementList::Entry::operator==):
+        (WebCore::HTMLFormattingElementList::Entry::operator!=):
+         - Calling element() on markers will assert, so use m_element.
+        * html/HTMLTreeBuilder.cpp:
+        (WebCore::HTMLTreeBuilder::closeTheCell):
+         - Implemented per the spec.
+        (WebCore::HTMLTreeBuilder::processStartTag):
+         - Use isTableBodyContextTag where possible.
+         - Add InCellMode.
+        (WebCore::HTMLTreeBuilder::resetInsertionModeAppropriately):
+         - Use isTableBodyContextTag where possible.
+        (WebCore::HTMLTreeBuilder::processTrEndTagForInRow):
+         - This code is needed from at least two callsites.
+        (WebCore::HTMLTreeBuilder::processEndTag):
+         - Add InCellMode and InRowMode
+        (WebCore::HTMLTreeBuilder::processCharacter):
+        (WebCore::HTMLTreeBuilder::processEndOfFile):
+        * html/HTMLTreeBuilder.h:
+
+2010-07-06  Eric Seidel  <eric@webkit.org>
+
+        Reviewed by Adam Barth.
+
         Make <a> auto-close any parent <a> tag
         https://bugs.webkit.org/show_bug.cgi?id=41684
 
index 31a2364..2e9282f 100644 (file)
@@ -328,16 +328,34 @@ bool HTMLElementStack::inScope(const AtomicString& targetTag) const
     return inScopeCommon<isScopeMarker>(m_top.get(), targetTag);
 }
 
+bool HTMLElementStack::inScope(const QualifiedName& tagName) const
+{
+    // FIXME: Is localName() right for non-html elements?
+    return inScope(tagName.localName());
+}
+
 bool HTMLElementStack::inListItemScope(const AtomicString& targetTag) const
 {
     return inScopeCommon<isListItemScopeMarker>(m_top.get(), targetTag);
 }
 
+bool HTMLElementStack::inListItemScope(const QualifiedName& tagName) const
+{
+    // FIXME: Is localName() right for non-html elements?
+    return inListItemScope(tagName.localName());
+}
+
 bool HTMLElementStack::inTableScope(const AtomicString& targetTag) const
 {
     return inScopeCommon<isTableScopeMarker>(m_top.get(), targetTag);
 }
 
+bool HTMLElementStack::inTableScope(const QualifiedName& tagName) const
+{
+    // FIXME: Is localName() right for non-html elements?
+    return inTableScope(tagName.localName());
+}
+
 Element* HTMLElementStack::htmlElement() const
 {
     ASSERT(m_htmlElement);
index 1db4c20..6903590 100644 (file)
@@ -35,6 +35,7 @@ namespace WebCore {
 
 class AtomicString;
 class Element;
+class QualifiedName;
 
 // NOTE: The HTML5 spec uses a backwards (grows downward) stack.  We're using
 // more standard (grows upwards) stack terminology here.
@@ -95,8 +96,11 @@ public:
 
     bool inScope(Element*) const;
     bool inScope(const AtomicString& tagName) const;
+    bool inScope(const QualifiedName&) const;
     bool inListItemScope(const AtomicString& tagName) const;
+    bool inListItemScope(const QualifiedName&) const;
     bool inTableScope(const AtomicString& tagName) const;
+    bool inTableScope(const QualifiedName&) const;
 
     Element* htmlElement() const;
     Element* headElement() const;
index 068f73b..818bfb3 100644 (file)
@@ -66,12 +66,12 @@ void HTMLFormattingElementList::Entry::replaceElement(PassRefPtr<Element> elemen
 
 bool HTMLFormattingElementList::Entry::operator==(const Entry& other) const
 {
-    return element() == other.element();
+    return m_element == other.m_element;
 }
 
 bool HTMLFormattingElementList::Entry::operator!=(const Entry& other) const
 {
-    return element() != other.element();
+    return m_element != other.m_element;
 }
 
 HTMLFormattingElementList::HTMLFormattingElementList()
index c28a8b9..b50843d 100644 (file)
@@ -756,6 +756,20 @@ bool HTMLTreeBuilder::processColgroupEndTagForInColumnGroup()
     return true;
 }
 
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#close-the-cell
+void HTMLTreeBuilder::closeTheCell()
+{
+    ASSERT(insertionMode() == InCellMode);
+    if (m_openElements.inScope(tdTag)) {
+        ASSERT(!m_openElements.inScope(thTag));
+        processFakeEndTag(tdTag);
+        return;
+    }
+    ASSERT(m_openElements.inScope(thTag));
+    processFakeEndTag(thTag);
+    ASSERT(insertionMode() == InRowMode);
+}
+
 void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
 {
     ASSERT(token.type() == HTMLToken::StartTag);
@@ -880,7 +894,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
             return;
         }
         parseError(token);
-        if (currentElement()->hasTagName(tableTag) || currentElement()->hasTagName(tbodyTag) || currentElement()->hasTagName(tfootTag) || currentElement()->hasTagName(theadTag) || currentElement()->hasTagName(trTag))
+        if (currentElement()->hasTagName(tableTag) || isTableBodyContextTag(currentElement()->localName()) || currentElement()->hasTagName(trTag))
             notImplemented(); // "whenever a node would be inserted into the current node, it must instead be foster parented."
         processStartTagForInBody(token);
         break;
@@ -935,6 +949,7 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
         notImplemented(); // process using "in table" rules
         break;
     case InRowMode:
+        ASSERT(insertionMode() == InRowMode);
         if (token.name() == thTag || token.name() == tdTag) {
             m_openElements.popUntilTableRowScopeMarker();
             insertElement(token);
@@ -942,11 +957,29 @@ void HTMLTreeBuilder::processStartTag(AtomicHTMLToken& token)
             m_activeFormattingElements.appendMarker();
         }
         if (token.name() == captionTag || token.name() == colTag || token.name() == colgroupTag || isTableBodyContextTag(token.name())) {
-            notImplemented();
+            if (!processTrEndTagForInRow()) {
+                ASSERT(m_isParsingFragment);
+                return;
+            }
+            ASSERT(insertionMode() == InTableBodyMode);
+            processStartTag(token);
             return;
         }
         notImplemented();
         break;
+    case InCellMode:
+        ASSERT(insertionMode() == InCellMode);
+        if (token.name() == captionTag || token.name() == colTag || token.name() == colgroupTag || token.name() == thTag || token.name() == tdTag || isTableBodyContextTag(token.name())) {
+            // FIXME: This could be more efficient.
+            if (!m_openElements.inTableScope(tdTag) || !m_openElements.inTableScope(thTag)) {
+                parseError(token);
+                return;
+            }
+            closeTheCell();
+            return;
+        }
+        processStartTagForInBody(token);
+        break;
     case AfterBodyMode:
     case AfterAfterBodyMode:
         ASSERT(insertionMode() == AfterBodyMode || insertionMode() == AfterAfterBodyMode);
@@ -1298,7 +1331,7 @@ void HTMLTreeBuilder::resetInsertionModeAppropriately()
             return setInsertionModeAndEnd(InCellMode, foreign);
         if (node->hasTagName(trTag))
             return setInsertionModeAndEnd(InRowMode, foreign);
-        if (node->hasTagName(tbodyTag) || node->hasTagName(theadTag) || node->hasTagName(tfootTag))
+        if (isTableBodyContextTag(node->localName()))
             return setInsertionModeAndEnd(InTableBodyMode, foreign);
         if (node->hasTagName(captionTag))
             return setInsertionModeAndEnd(InCaptionMode, foreign);
@@ -1474,6 +1507,20 @@ bool HTMLTreeBuilder::processCaptionEndTagForInCaption()
     return true;
 }
 
+bool HTMLTreeBuilder::processTrEndTagForInRow()
+{
+    if (!m_openElements.inTableScope(trTag.localName())) {
+        ASSERT(m_isParsingFragment);
+        // FIXME: parse error
+        return false;
+    }
+    m_openElements.popUntilTableRowScopeMarker();
+    ASSERT(currentElement()->hasTagName(trTag));
+    m_openElements.pop();
+    m_insertionMode = InTableBodyMode;
+    return true;
+}
+
 void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
 {
     ASSERT(token.type() == HTMLToken::EndTag);
@@ -1580,6 +1627,72 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
         }
         processEndTag(token);
         break;
+    case InRowMode:
+        ASSERT(insertionMode() == InRowMode);
+        if (token.name() == trTag) {
+            processTrEndTagForInRow();
+            return;
+        }
+        if (token.name() == tableTag) {
+            if (!processTrEndTagForInRow()) {
+                ASSERT(m_isParsingFragment);
+                return;
+            }
+            ASSERT(insertionMode() == InTableBodyMode);
+            processEndTag(token);
+            return;
+        }
+        if (isTableBodyContextTag(token.name())) {
+            if (!m_openElements.inTableScope(token.name())) {
+                parseError(token);
+                return;
+            }
+            processFakeEndTag(trTag);
+            ASSERT(insertionMode() == InTableBodyMode);
+            processEndTag(token);
+            return;
+        }
+        if (token.name() == bodyTag || token.name() == captionTag || token.name() == colTag || token.name() == colgroupTag || token.name() == htmlTag || token.name() == tdTag || token.name() == thTag) {
+            parseError(token);
+            return;
+        }
+        notImplemented();
+        break;
+    case InCellMode:
+        ASSERT(insertionMode() == InCellMode);
+        if (token.name() == thTag || token.name() == tdTag) {
+            if (!m_openElements.inTableScope(token.name())) {
+                parseError(token);
+                return;
+            }
+            generateImpliedEndTags();
+            if (!currentElement()->hasLocalName(token.name()))
+                parseError(token);
+            m_openElements.popUntil(token.name());
+            m_openElements.pop();
+            m_activeFormattingElements.clearToLastMarker();
+            m_insertionMode = InRowMode;
+            ASSERT(currentElement()->hasTagName(trTag));
+            return;
+        }
+        if (token.name() == bodyTag || token.name() == captionTag || token.name() == colTag || token.name() == colgroupTag || token.name() == htmlTag) {
+            parseError(token);
+            return;
+        }
+        if (token.name() == tableTag || token.name() == trTag || isTableBodyContextTag(token.name())) {
+            if (!m_openElements.inTableScope(token.name())) {
+                ASSERT(m_isParsingFragment);
+                // FIXME: It is unclear what the exact ASSERT should be.
+                // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10098
+                parseError(token);
+                return;
+            }
+            closeTheCell();
+            processEndTag(token);
+            return;
+        }
+        processEndTagForInBody(token);
+        break;
     case AfterBodyMode:
         ASSERT(insertionMode() == AfterBodyMode);
         if (token.name() == htmlTag) {
@@ -1741,12 +1854,14 @@ void HTMLTreeBuilder::processCharacter(AtomicHTMLToken& token)
         // Fall through
     case InBodyMode:
     case InCaptionMode:
-        ASSERT(insertionMode() == InBodyMode || insertionMode() == InCaptionMode);
+    case InCellMode:
+        ASSERT(insertionMode() == InBodyMode || insertionMode() == InCaptionMode || insertionMode() == InCellMode);
         notImplemented();
         insertTextNode(token);
         break;
     case InTableMode:
-        ASSERT(insertionMode() == InTableMode);
+    case InRowMode:
+        ASSERT(insertionMode() == InTableMode || insertionMode() == InRowMode);
         notImplemented(); // Crazy pending characters.
         insertTextNode(token);
         break;
@@ -1811,7 +1926,8 @@ void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken& token)
         processDefaultForAfterHeadMode(token);
         // Fall through
     case InBodyMode:
-        ASSERT(insertionMode() == InBodyMode);
+    case InCellMode:
+        ASSERT(insertionMode() == InBodyMode || insertionMode() == InCellMode);
         notImplemented();
         break;
     case AfterBodyMode:
index 61b11d2..293b9a8 100644 (file)
@@ -129,6 +129,7 @@ private:
     bool processBodyEndTagForInBody(AtomicHTMLToken&);
     bool processCaptionEndTagForInCaption();
     bool processColgroupEndTagForInColumnGroup();
+    bool processTrEndTagForInRow();
     void processAnyOtherEndTagForInBody(AtomicHTMLToken&);
 
     void processFakeStartTag(const QualifiedName&, PassRefPtr<NamedNodeMap> attributes = 0);
@@ -141,6 +142,8 @@ private:
     void reparentChildren(Element* oldParent, Element* newParent);
     void callTheAdoptionAgency(AtomicHTMLToken&);
 
+    void closeTheCell();
+
     template<typename ChildType>
     PassRefPtr<ChildType> attach(Node* parent, PassRefPtr<ChildType> prpChild)
     {