bug 296677: Fix nsParser::ParseFragment to not screw up setting <textarea>'s innerHTML. r=jst sr=peterv a=asa

git-svn-id: svn://10.0.0.236/trunk@174716 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
mrbkap%gmail.com
2005-06-16 18:59:59 +00:00
parent 72275d6be3
commit f2a332e8d4
4 changed files with 70 additions and 12 deletions

View File

@@ -43,8 +43,8 @@ class nsIDOMDocumentFragment;
class nsIDocument;
#define NS_I_FRAGMENT_CONTENT_SINK_IID \
{ 0xe9ea6afb, 0x92f3, 0x4270, \
{ 0xb2, 0x67, 0xd2, 0xe3, 0x8d, 0x0e, 0x95, 0x45 } }
{ 0x2cec7263, 0x9dd0, 0x4413, \
{ 0xb6, 0x68, 0x6f, 0xf0, 0xa1, 0x40, 0xc1, 0xbe } }
/**
* The fragment sink allows a client to parse a fragment of sink, possibly
@@ -85,6 +85,14 @@ public:
* (such as an end context).
*/
NS_IMETHOD DidBuildContent() = 0;
/**
* This method is a total hack to help with parsing fragments. It is called to
* tell the fragment sink that a container from the context will be delivered
* after the call to WillBuildContent(). This is only relevent for HTML
* fragments that use nsHTMLTokenizer/CNavDTD.
*/
NS_IMETHOD IgnoreFirstContainer() = 0;
};
/**

View File

@@ -1839,15 +1839,6 @@ nsParser::ParseFragment(const nsAString& aSourceBuffer,
theContext.AppendLiteral(">");
}
if (!aXMLMode) {
// Make sure we flush the context out if there wasn't a body tag. This is
// safe, since the fragment sink doesn't make a distinction between the
// head and body context. This is needed because if there wasn't a body
// tag, the DTD will store tags that belong in the body until it sees
// text or a body tag. This flushes all context tags out of the DTD.
theContext.AppendLiteral("<BODY>");
}
// First, parse the context to build up the DTD's tag stack. Note that we
// pass PR_FALSE for the aLastCall parameter.
result = Parse(theContext, (void*)&theContext, aMimeType,
@@ -1860,6 +1851,42 @@ nsParser::ParseFragment(const nsAString& aSourceBuffer,
nsCOMPtr<nsIFragmentContentSink> fragSink = do_QueryInterface(mSink);
NS_ASSERTION(fragSink, "ParseFragment requires a fragment content sink");
if (!aXMLMode) {
// First, we have to flush any tags that don't belong in the head if there
// was no <body> in the context.
// XXX This is extremely ugly. Maybe CNavDTD should have FlushMisplaced()?
NS_ASSERTION(mParserContext, "Parsing didn't create a parser context?");
nsCOMPtr<CNavDTD> dtd = do_QueryInterface(mParserContext->mDTD);
if (dtd) {
CStartToken bodyToken(NS_LITERAL_STRING("BODY"), eHTMLTag_body);
nsCParserNode bodyNode(&bodyToken, 0);
dtd->OpenBody(&bodyNode);
// Now parse the flushed out tags.
result = BuildModel();
if (NS_FAILED(result)) {
mFlags |= NS_PARSER_FLAG_OBSERVERS_ENABLED;
return result;
}
}
// Now that we've flushed all of the tags out of the body, we have to make
// sure that there aren't any context tags left in the scanner.
NS_ASSERTION(mParserContext->mScanner, "Where'd the scanner go?");
PRUnichar next;
if (NS_SUCCEEDED(mParserContext->mScanner->Peek(next))) {
// Uh, oh. This must mean that the context stack has a special tag on
// it, such as <textarea> or <title> that requires its end tag before it
// will be consumed. Tell the content sink that it will be coming.
// Note: For now, we can assume that there is only one such tag.
NS_ASSERTION(next == '<', "The tokenizer failed to consume a token");
fragSink->IgnoreFirstContainer();
}
}
fragSink->WillBuildContent();
// Now, parse the actual content. Note that this is the last call for HTML
// content, but for XML, we will want to build and parse the end tags.