Changeset 21472 in webkit
- Timestamp:
- May 14, 2007, 6:41:53 PM (18 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r21470 r21472 1 2007-05-14 Mitz Pettel <mitz@webkit.org> 2 3 Reviewed by Dave Hyatt. 4 5 - test for http://bugs.webkit.org/show_bug.cgi?id=13603 6 style leaks in washingtonpost.com 7 8 * fast/parser/residual-style-close-across-n-blocks-expected.txt: Added. 9 * fast/parser/residual-style-close-across-n-blocks.html: Added. 10 1 11 2007-05-14 Sam Weinig <sam@webkit.org> 2 12 -
trunk/WebCore/ChangeLog
r21471 r21472 1 2007-05-14 Mitz Pettel <mitz@webkit.org> 2 3 Reviewed by Dave Hyatt. 4 5 - fix http://bugs.webkit.org/show_bug.cgi?id=13603 6 style leaks in washingtonpost.com 7 also known as http://bugs.webkit.org/show_bug.cgi?id=8750 8 w3c.org: incorrect recovery from unclosed <a> elements 9 also known as http://bugs.webkit.org/show_bug.cgi?id=12808 10 Handling of misnested tags results in entire page appearing as link 11 also known as http://bugs.webkit.org/show_bug.cgi?id=12861 12 Post text renders as link 13 14 Test: fast/parser/residual-style-close-across-n-blocks.html 15 16 * html/HTMLParser.cpp: 17 (WebCore::HTMLParser::handleResidualStyleCloseTagAcrossBlocks): Changed to 18 deal with multiple block crossings instead of bailing out, by doing multiple 19 reparenting passes, starting from the outermost block. 20 1 21 2007-05-14 Mitz Pettel <mitz@webkit.org> 2 22 -
trunk/WebCore/html/HTMLParser.cpp
r21439 r21472 978 978 void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem) 979 979 { 980 // Find the element that crosses over to a higher level. For now, if there is more than 981 // one, we will just give up and not attempt any sort of correction. It's highly unlikely that 982 // there will be more than one, since <p> tags aren't allowed to be nested. 983 ExceptionCode ec = 0; 984 HTMLStackElem* curr = blockStack; 985 HTMLStackElem* maxElem = 0; 986 HTMLStackElem* prev = 0; 987 HTMLStackElem* prevMaxElem = 0; 988 while (curr && curr != elem) { 989 if (curr->level > elem->level) { 990 if (maxElem) 991 return; 992 maxElem = curr; 993 prevMaxElem = prev; 980 HTMLStackElem* maxElem; 981 bool finished = false; 982 while (!finished) { 983 // Find the outermost element that crosses over to a higher level. If there exists another higher-level 984 // element, we will do another pass, until we have corrected the innermost one. 985 ExceptionCode ec = 0; 986 HTMLStackElem* curr = blockStack; 987 HTMLStackElem* prev = 0; 988 HTMLStackElem* prevMaxElem = 0; 989 maxElem = 0; 990 finished = true; 991 while (curr && curr != elem) { 992 if (curr->level > elem->level) { 993 if (!isAffectedByResidualStyle(curr->tagName)) 994 return; 995 if (maxElem) 996 // We will need another pass. 997 finished = false; 998 maxElem = curr; 999 prevMaxElem = prev; 1000 } 1001 1002 prev = curr; 1003 curr = curr->next; 994 1004 } 995 1005 996 prev = curr; 997 curr = curr->next; 998 } 999 1000 if (!curr || !maxElem || !isAffectedByResidualStyle(maxElem->tagName)) return; 1001 1002 Node* residualElem = prev->node; 1003 Node* blockElem = prevMaxElem ? prevMaxElem->node : current; 1004 Node* parentElem = elem->node; 1005 1006 // Check to see if the reparenting that is going to occur is allowed according to the DOM. 1007 // FIXME: We should either always allow it or perform an additional fixup instead of 1008 // just bailing here. 1009 // Example: <p><font><center>blah</font></center></p> isn't doing a fixup right now. 1010 if (!parentElem->childAllowed(blockElem)) 1011 return; 1012 1013 if (maxElem->node->parentNode() != elem->node) { 1014 // Walk the stack and remove any elements that aren't residual style tags. These 1015 // are basically just being closed up. Example: 1016 // <font><span>Moo<p>Goo</font></p>. 1017 // In the above example, the <span> doesn't need to be reopened. It can just close. 1018 HTMLStackElem* currElem = maxElem->next; 1019 HTMLStackElem* prevElem = maxElem; 1006 if (!curr || !maxElem) 1007 return; 1008 1009 Node* residualElem = prev->node; 1010 Node* blockElem = prevMaxElem ? prevMaxElem->node : current; 1011 Node* parentElem = elem->node; 1012 1013 // Check to see if the reparenting that is going to occur is allowed according to the DOM. 1014 // FIXME: We should either always allow it or perform an additional fixup instead of 1015 // just bailing here. 1016 // Example: <p><font><center>blah</font></center></p> isn't doing a fixup right now. 1017 if (!parentElem->childAllowed(blockElem)) 1018 return; 1019 1020 if (maxElem->node->parentNode() != elem->node) { 1021 // Walk the stack and remove any elements that aren't residual style tags. These 1022 // are basically just being closed up. Example: 1023 // <font><span>Moo<p>Goo</font></p>. 1024 // In the above example, the <span> doesn't need to be reopened. It can just close. 1025 HTMLStackElem* currElem = maxElem->next; 1026 HTMLStackElem* prevElem = maxElem; 1027 while (currElem != elem) { 1028 HTMLStackElem* nextElem = currElem->next; 1029 if (!isResidualStyleTag(currElem->tagName)) { 1030 prevElem->next = nextElem; 1031 prevElem->derefNode(); 1032 prevElem->node = currElem->node; 1033 prevElem->didRefNode = currElem->didRefNode; 1034 delete currElem; 1035 } 1036 else 1037 prevElem = currElem; 1038 currElem = nextElem; 1039 } 1040 1041 // We have to reopen residual tags in between maxElem and elem. An example of this case is: 1042 // <font><i>Moo<p>Foo</font>. 1043 // In this case, we need to transform the part before the <p> into: 1044 // <font><i>Moo</i></font><i> 1045 // so that the <i> will remain open. This involves the modification of elements 1046 // in the block stack. 1047 // This will also affect how we ultimately reparent the block, since we want it to end up 1048 // under the reopened residual tags (e.g., the <i> in the above example.) 1049 RefPtr<Node> prevNode = 0; 1050 currElem = maxElem; 1051 while (currElem->node != residualElem) { 1052 if (isResidualStyleTag(currElem->node->localName())) { 1053 // Create a clone of this element. 1054 // We call releaseRef to get a raw pointer since we plan to hand over ownership to currElem. 1055 Node* currNode = currElem->node->cloneNode(false).releaseRef(); 1056 1057 // Change the stack element's node to point to the clone. 1058 // The stack element adopts the reference we obtained above by calling release(). 1059 currElem->derefNode(); 1060 currElem->node = currNode; 1061 currElem->didRefNode = true; 1062 1063 // Attach the previous node as a child of this new node. 1064 if (prevNode) 1065 currNode->appendChild(prevNode, ec); 1066 else // The new parent for the block element is going to be the innermost clone. 1067 parentElem = currNode; 1068 1069 prevNode = currNode; 1070 } 1071 1072 currElem = currElem->next; 1073 } 1074 1075 // Now append the chain of new residual style elements if one exists. 1076 if (prevNode) 1077 elem->node->appendChild(prevNode, ec); 1078 } 1079 1080 // Check if the block is still in the tree. If it isn't, then we don't 1081 // want to remove it from its parent (that would crash) or insert it into 1082 // a new parent later. See http://bugs.webkit.org/show_bug.cgi?id=6778 1083 bool isBlockStillInTree = blockElem->parentNode(); 1084 1085 // We need to make a clone of |residualElem| and place it just inside |blockElem|. 1086 // All content of |blockElem| is reparented to be under this clone. We then 1087 // reparent |blockElem| using real DOM calls so that attachment/detachment will 1088 // be performed to fix up the rendering tree. 1089 // So for this example: <b>...<p>Foo</b>Goo</p> 1090 // The end result will be: <b>...</b><p><b>Foo</b>Goo</p> 1091 // 1092 // Step 1: Remove |blockElem| from its parent, doing a batch detach of all the kids. 1093 if (m_currentFormElement) 1094 m_currentFormElement->setPreserveAcrossRemove(true); 1095 if (isBlockStillInTree) 1096 blockElem->parentNode()->removeChild(blockElem, ec); 1097 1098 // Step 2: Clone |residualElem|. 1099 RefPtr<Node> newNode = residualElem->cloneNode(false); // Shallow clone. We don't pick up the same kids. 1100 Node* newNodePtr = newNode.get(); 1101 1102 // Step 3: Place |blockElem|'s children under |newNode|. Remove all of the children of |blockElem| 1103 // before we've put |newElem| into the document. That way we'll only do one attachment of all 1104 // the new content (instead of a bunch of individual attachments). 1105 Node* currNode = blockElem->firstChild(); 1106 while (currNode) { 1107 Node* nextNode = currNode->nextSibling(); 1108 newNode->appendChild(currNode, ec); 1109 currNode = nextNode; 1110 } 1111 1112 // Step 4: Place |newNode| under |blockElem|. |blockElem| is still out of the document, so no 1113 // attachment can occur yet. 1114 blockElem->appendChild(newNode.release(), ec); 1115 1116 // Step 5: Reparent |blockElem|. Now the full attachment of the fixed up tree takes place. 1117 if (isBlockStillInTree) 1118 parentElem->appendChild(blockElem, ec); 1119 1120 // Step 6: Pull |elem| out of the stack, since it is no longer enclosing us. Also update 1121 // the node associated with the previous stack element so that when it gets popped, 1122 // it doesn't make the residual element the next current node. 1123 HTMLStackElem* currElem = maxElem; 1124 HTMLStackElem* prevElem = 0; 1020 1125 while (currElem != elem) { 1021 HTMLStackElem* nextElem = currElem->next; 1022 if (!isResidualStyleTag(currElem->tagName)) { 1023 prevElem->next = nextElem; 1024 prevElem->derefNode(); 1025 prevElem->node = currElem->node; 1026 prevElem->didRefNode = currElem->didRefNode; 1027 delete currElem; 1028 } 1029 else 1030 prevElem = currElem; 1031 currElem = nextElem; 1032 } 1033 1034 // We have to reopen residual tags in between maxElem and elem. An example of this case is: 1035 // <font><i>Moo<p>Foo</font>. 1036 // In this case, we need to transform the part before the <p> into: 1037 // <font><i>Moo</i></font><i> 1038 // so that the <i> will remain open. This involves the modification of elements 1039 // in the block stack. 1040 // This will also affect how we ultimately reparent the block, since we want it to end up 1041 // under the reopened residual tags (e.g., the <i> in the above example.) 1042 RefPtr<Node> prevNode = 0; 1043 currElem = maxElem; 1044 while (currElem->node != residualElem) { 1045 if (isResidualStyleTag(currElem->node->localName())) { 1046 // Create a clone of this element. 1047 // We call releaseRef to get a raw pointer since we plan to hand over ownership to currElem. 1048 Node* currNode = currElem->node->cloneNode(false).releaseRef(); 1049 1050 // Change the stack element's node to point to the clone. 1051 // The stack element adopts the reference we obtained above by calling release(). 1052 currElem->derefNode(); 1053 currElem->node = currNode; 1054 currElem->didRefNode = true; 1055 1056 // Attach the previous node as a child of this new node. 1057 if (prevNode) 1058 currNode->appendChild(prevNode, ec); 1059 else // The new parent for the block element is going to be the innermost clone. 1060 parentElem = currNode; 1061 1062 prevNode = currNode; 1063 } 1064 1126 prevElem = currElem; 1065 1127 currElem = currElem->next; 1066 1128 } 1067 1068 // Now append the chain of new residual style elements if one exists. 1069 if (prevNode) 1070 elem->node->appendChild(prevNode, ec); 1071 } 1072 1073 // Check if the block is still in the tree. If it isn't, then we don't 1074 // want to remove it from its parent (that would crash) or insert it into 1075 // a new parent later. See http://bugs.webkit.org/show_bug.cgi?id=6778 1076 bool isBlockStillInTree = blockElem->parentNode(); 1077 1078 // We need to make a clone of |residualElem| and place it just inside |blockElem|. 1079 // All content of |blockElem| is reparented to be under this clone. We then 1080 // reparent |blockElem| using real DOM calls so that attachment/detachment will 1081 // be performed to fix up the rendering tree. 1082 // So for this example: <b>...<p>Foo</b>Goo</p> 1083 // The end result will be: <b>...</b><p><b>Foo</b>Goo</p> 1084 // 1085 // Step 1: Remove |blockElem| from its parent, doing a batch detach of all the kids. 1086 if (m_currentFormElement) 1087 m_currentFormElement->setPreserveAcrossRemove(true); 1088 if (isBlockStillInTree) 1089 blockElem->parentNode()->removeChild(blockElem, ec); 1090 1091 // Step 2: Clone |residualElem|. 1092 RefPtr<Node> newNode = residualElem->cloneNode(false); // Shallow clone. We don't pick up the same kids. 1093 1094 // Step 3: Place |blockElem|'s children under |newNode|. Remove all of the children of |blockElem| 1095 // before we've put |newElem| into the document. That way we'll only do one attachment of all 1096 // the new content (instead of a bunch of individual attachments). 1097 Node* currNode = blockElem->firstChild(); 1098 while (currNode) { 1099 Node* nextNode = currNode->nextSibling(); 1100 newNode->appendChild(currNode, ec); 1101 currNode = nextNode; 1102 } 1103 1104 // Step 4: Place |newNode| under |blockElem|. |blockElem| is still out of the document, so no 1105 // attachment can occur yet. 1106 blockElem->appendChild(newNode.release(), ec); 1107 1108 // Step 5: Reparent |blockElem|. Now the full attachment of the fixed up tree takes place. 1109 if (isBlockStillInTree) 1110 parentElem->appendChild(blockElem, ec); 1111 1112 // Step 6: Elide |elem|, since it is effectively no longer open. Also update 1113 // the node associated with the previous stack element so that when it gets popped, 1114 // it doesn't make the residual element the next current node. 1115 HTMLStackElem* currElem = maxElem; 1116 HTMLStackElem* prevElem = 0; 1117 while (currElem != elem) { 1118 prevElem = currElem; 1119 currElem = currElem->next; 1120 } 1121 prevElem->next = elem->next; 1122 prevElem->derefNode(); 1123 prevElem->node = elem->node; 1124 prevElem->didRefNode = elem->didRefNode; 1125 delete elem; 1126 1129 prevElem->next = elem->next; 1130 prevElem->derefNode(); 1131 prevElem->node = elem->node; 1132 prevElem->didRefNode = elem->didRefNode; 1133 if (!finished) { 1134 // Repurpose |elem| to represent |newNode| and insert it at the appropriate position 1135 // in the stack. We do not do this for the innermost block, because in that case the new 1136 // node is effectively no longer open. 1137 elem->next = maxElem; 1138 elem->node = prevMaxElem->node; 1139 elem->didRefNode = prevMaxElem->didRefNode; 1140 prevMaxElem->next = elem; 1141 prevMaxElem->node = newNodePtr; 1142 prevMaxElem->didRefNode = false; 1143 } else 1144 delete elem; 1145 } 1146 1127 1147 // Step 7: Reopen intermediate inlines, e.g., <b><p><i>Foo</b>Goo</p>. 1128 1148 // In the above example, Goo should stay italic. 1129 1149 // We cap the number of tags we're willing to reopen based off cResidualStyleMaxDepth. 1130 curr = blockStack;1150 HTMLStackElem* curr = blockStack; 1131 1151 HTMLStackElem* residualStyleStack = 0; 1132 1152 unsigned stackDepth = 1; … … 1152 1172 reopenResidualStyleTags(residualStyleStack, 0); // FIXME: Deal with stray table content some day 1153 1173 // if it becomes necessary to do so. 1154 1174 1155 1175 if (m_currentFormElement) 1156 1176 m_currentFormElement->setPreserveAcrossRemove(false);
Note:
See TracChangeset
for help on using the changeset viewer.