diff --git a/mozilla/content/html/content/test/test_bug353415-2.html b/mozilla/content/html/content/test/test_bug353415-2.html
index f41342afe63..78817cf52be 100644
--- a/mozilla/content/html/content/test/test_bug353415-2.html
+++ b/mozilla/content/html/content/test/test_bug353415-2.html
@@ -57,7 +57,7 @@
SimpleTest.waitForExplicitFinish();
function doCheck(){
- is(frames['submit_frame'].location.href, "http://localhost:8888/blah?field1-2=teststring&field2-2=0&field4-2=1&field6-2=3&field7-2=2&field8-2=8&field9-2=9&field12-2=&field14-2=14&field1=teststring&field2=0&field4=1&field6=3&field7=2&field8=8&field9=9&field12=&field14=14", "Submit string was correct.");
+ is(frames['submit_frame'].location.href, "http://localhost:8888/blah?field1-2=teststring&field2-2=0&field4-2=1&field6-2=3&field7-2=2&field8-2=8&field9-2=9&field12-2=&field1=teststring&field2=0&field4=1&field6=3&field7=2&field8=8&field9=9&field12=&field14=14&field14-2=14", "Submit string was correct.");
SimpleTest.finish();
}
diff --git a/mozilla/parser/htmlparser/src/CNavDTD.cpp b/mozilla/parser/htmlparser/src/CNavDTD.cpp
index 9aa35c5bd0e..ecda0ae4178 100644
--- a/mozilla/parser/htmlparser/src/CNavDTD.cpp
+++ b/mozilla/parser/htmlparser/src/CNavDTD.cpp
@@ -474,47 +474,52 @@ CNavDTD::GetType()
return NS_IPARSER_FLAG_HTML;
}
-/**
- * Text and some tags require a body when they're added, this function returns
- * true for those tags.
- *
- * @param aToken The current token that we care about.
- * @param aTokenizer A tokenizer that we can get the tags attributes off of.
- * @return PR_TRUE if aToken does indeed force the body to open.
- */
static PRBool
-DoesRequireBody(CToken* aToken, nsITokenizer* aTokenizer)
+ValueIsHidden(const nsAString& aValue)
{
- PRBool result = PR_FALSE;
+ // Having to deal with whitespace here sucks, but we have to match
+ // what the content sink does.
+ nsAutoString str(aValue);
+ str.Trim("\n\r\t\b");
+ return str.LowerCaseEqualsLiteral("hidden");
+}
- if (aToken) {
- eHTMLTags theTag = (eHTMLTags)aToken->GetTypeID();
- if (gHTMLElements[theTag].HasSpecialProperty(kRequiresBody)) {
- if (theTag == eHTMLTag_input) {
- // IE & Nav4x opens up a body for type=text - Bug 66985
- PRInt32 ac = aToken->GetAttributeCount();
- for(PRInt32 i = 0; i < ac; ++i) {
- CAttributeToken* attr = static_cast
- (aTokenizer->GetTokenAt(i));
- const nsSubstring& name = attr->GetKey();
- const nsAString& value = attr->GetValue();
-
- if ((name.EqualsLiteral("type") ||
- name.EqualsLiteral("TYPE"))
- &&
- !(value.EqualsLiteral("hidden") ||
- value.EqualsLiteral("HIDDEN"))) {
- result = PR_TRUE;
- break;
- }
- }
- } else {
- result = PR_TRUE;
- }
+// Check whether aToken corresponds to a tag. The token
+// must be a start tag token for an . This must be called at a point
+// when all the attributes for the input are still in the tokenizer.
+static PRBool
+IsHiddenInput(CToken* aToken, nsITokenizer* aTokenizer)
+{
+ NS_PRECONDITION(eHTMLTokenTypes(aToken->GetTokenType()) == eToken_start,
+ "Must be start token");
+ NS_PRECONDITION(eHTMLTags(aToken->GetTypeID()) == eHTMLTag_input,
+ "Must be tag");
+
+ PRInt32 ac = aToken->GetAttributeCount();
+ NS_ASSERTION(ac <= aTokenizer->GetCount(),
+ "Not enough tokens in the tokenizer");
+ // But we don't really trust ourselves to get that right
+ ac = PR_MIN(ac, aTokenizer->GetCount());
+
+ for (PRInt32 i = 0; i < ac; ++i) {
+ NS_ASSERTION(eHTMLTokenTypes(aTokenizer->GetTokenAt(i)->GetTokenType()) ==
+ eToken_attribute, "Unexpected token type");
+ // Again, we're not sure we actually manage to guarantee that
+ if (eHTMLTokenTypes(aTokenizer->GetTokenAt(i)->GetTokenType()) !=
+ eToken_attribute) {
+ break;
}
+
+ CAttributeToken* attrToken =
+ static_cast(aTokenizer->GetTokenAt(i));
+ if (!attrToken->GetKey().LowerCaseEqualsLiteral("type")) {
+ continue;
+ }
+
+ return ValueIsHidden(attrToken->GetValue());
}
-
- return result;
+
+ return PR_FALSE;
}
/**
@@ -566,7 +571,6 @@ CNavDTD::HandleToken(CToken* aToken, nsIParser* aParser)
}
eHTMLTags theParentTag = mBodyContext->Last();
- theTag = (eHTMLTags)theToken->GetTypeID();
if (FindTagInSet(theTag, gLegalElements,
NS_ARRAY_LENGTH(gLegalElements)) ||
(gHTMLElements[theParentTag].CanContain(theTag, mDTDMode) &&
@@ -581,7 +585,11 @@ CNavDTD::HandleToken(CToken* aToken, nsIParser* aParser)
// noscript, etc). Script is special, though. Shipping it out
// breaks document.write stuff. See bug 243064.
(!gHTMLElements[theTag].HasSpecialProperty(kLegalOpen) ||
- theTag == eHTMLTag_script))) {
+ theTag == eHTMLTag_script)) ||
+ (theTag == eHTMLTag_input && theType == eToken_start &&
+ FindTagInSet(theParentTag, gLegalElements,
+ NS_ARRAY_LENGTH(gLegalElements)) &&
+ IsHiddenInput(theToken, mTokenizer))) {
// Reset the state since all the misplaced tokens are about to get
// handled.
mFlags &= ~NS_DTD_FLAG_MISPLACED_CONTENT;
@@ -677,7 +685,9 @@ CNavDTD::HandleToken(CToken* aToken, nsIParser* aParser)
// end tag.
}
- if (DoesRequireBody(aToken, mTokenizer)) {
+ if (gHTMLElements[theTag].HasSpecialProperty(kRequiresBody) &&
+ ((theTag != eHTMLTag_input) ||
+ !IsHiddenInput(aToken, mTokenizer))) {
CToken* theBodyToken =
mTokenAllocator->CreateTokenOfType(eToken_start,
eHTMLTag_body,
@@ -875,9 +885,33 @@ CNavDTD::HandleDefaultStartToken(CToken* aToken, eHTMLTags aChildTag,
do {
eHTMLTags theParentTag = mBodyContext->TagAt(--theIndex);
+ // Figure out whether this is a hidden input inside a
+ // table/tbody/thead/tfoot/tr
+ static eHTMLTags sTableElements[] = {
+ eHTMLTag_table, eHTMLTag_thead, eHTMLTag_tbody,
+ eHTMLTag_tr, eHTMLTag_tfoot
+ };
+
+ PRBool isHiddenInputInsideTableElement = PR_FALSE;
+ if (aChildTag == eHTMLTag_input &&
+ FindTagInSet(theParentTag, sTableElements,
+ NS_ARRAY_LENGTH(sTableElements))) {
+ PRInt32 attrCount = aNode->GetAttributeCount();
+ for (PRInt32 attrIndex = 0; attrIndex < attrCount; ++attrIndex) {
+ const nsAString& key = aNode->GetKeyAt(attrIndex);
+ if (key.LowerCaseEqualsLiteral("type")) {
+ isHiddenInputInsideTableElement =
+ ValueIsHidden(aNode->GetValueAt(attrIndex));
+ break;
+ }
+ }
+ }
+
// Precompute containment, and pass it to CanOmit()...
- theParentContains = CanContain(theParentTag, aChildTag);
- if (CanOmit(theParentTag, aChildTag, theParentContains)) {
+ theParentContains =
+ isHiddenInputInsideTableElement || CanContain(theParentTag, aChildTag);
+ if (!isHiddenInputInsideTableElement &&
+ CanOmit(theParentTag, aChildTag, theParentContains)) {
HandleOmittedTag(aToken, aChildTag, theParentTag, aNode);
return NS_OK;
}
diff --git a/mozilla/parser/htmlparser/src/nsHTMLTokenizer.cpp b/mozilla/parser/htmlparser/src/nsHTMLTokenizer.cpp
index 3147c149ddc..e458d88f141 100644
--- a/mozilla/parser/htmlparser/src/nsHTMLTokenizer.cpp
+++ b/mozilla/parser/htmlparser/src/nsHTMLTokenizer.cpp
@@ -873,7 +873,7 @@ nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,
// If you're here, it's because we were in the midst of consuming a start
// tag but ran out of data (not in the stream, but in this *part* of the
// stream. For simplicity, we have to unwind our input. Therefore, we pop
- // and discard any new tokens we've cued this round. Later we can get
+ // and discard any new tokens we've queued this round. Later we can get
// smarter about this.
if (NS_FAILED(result)) {
while (mTokenDeque.GetSize()>theDequeSize) {
diff --git a/mozilla/parser/htmlparser/tests/mochitest/regressions.txt b/mozilla/parser/htmlparser/tests/mochitest/regressions.txt
index 93ce44f7f36..bc1ff381a35 100644
--- a/mozilla/parser/htmlparser/tests/mochitest/regressions.txt
+++ b/mozilla/parser/htmlparser/tests/mochitest/regressions.txt
@@ -74,3 +74,310 @@ Expected closing tag after
| "
x { content:"