mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
bug 296677: Fix nsParser::ParseFragment to not screw up setting <textarea>'s innerHTML. r=jst sr=peterv a=asa
This commit is contained in:
parent
13e87d6df0
commit
6664814803
@ -1,4 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=2 et tw=80: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -125,6 +126,7 @@ public:
|
||||
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument);
|
||||
NS_IMETHOD WillBuildContent();
|
||||
NS_IMETHOD DidBuildContent();
|
||||
NS_IMETHOD IgnoreFirstContainer();
|
||||
|
||||
nsIContent* GetCurrentContent();
|
||||
PRInt32 PushContent(nsIContent *aContent);
|
||||
@ -146,6 +148,7 @@ public:
|
||||
PRPackedBool mAllContent;
|
||||
PRPackedBool mProcessing;
|
||||
PRPackedBool mSeenBody;
|
||||
PRPackedBool mIgnoreContainer;
|
||||
|
||||
nsCOMPtr<nsIContent> mRoot;
|
||||
nsCOMPtr<nsIParser> mParser;
|
||||
@ -197,6 +200,7 @@ nsHTMLFragmentContentSink::nsHTMLFragmentContentSink(PRBool aAllContent)
|
||||
: mAllContent(aAllContent),
|
||||
mProcessing(aAllContent),
|
||||
mSeenBody(!aAllContent),
|
||||
mIgnoreContainer(PR_FALSE),
|
||||
mContentStack(nsnull),
|
||||
mText(nsnull),
|
||||
mTextLength(0),
|
||||
@ -443,7 +447,7 @@ nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode)
|
||||
|
||||
nsresult result = NS_OK;
|
||||
|
||||
if (mProcessing) {
|
||||
if (mProcessing && !mIgnoreContainer) {
|
||||
FlushText();
|
||||
|
||||
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
|
||||
@ -497,6 +501,9 @@ nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode)
|
||||
// XXX if navigator_quirks_mode (only body in html supports background)
|
||||
AddBaseTagInfo(content);
|
||||
}
|
||||
else if (mProcessing && mIgnoreContainer) {
|
||||
mIgnoreContainer = PR_FALSE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -723,6 +730,13 @@ nsHTMLFragmentContentSink::DidBuildContent()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFragmentContentSink::IgnoreFirstContainer()
|
||||
{
|
||||
mIgnoreContainer = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
nsHTMLFragmentContentSink::GetCurrentContent()
|
||||
{
|
||||
|
@ -90,6 +90,7 @@ public:
|
||||
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument);
|
||||
NS_IMETHOD WillBuildContent();
|
||||
NS_IMETHOD DidBuildContent();
|
||||
NS_IMETHOD IgnoreFirstContainer();
|
||||
|
||||
protected:
|
||||
virtual PRBool SetDocElement(PRInt32 aNameSpaceID,
|
||||
@ -423,3 +424,11 @@ nsXMLFragmentContentSink::DidBuildContent()
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXMLFragmentContentSink::IgnoreFirstContainer()
|
||||
{
|
||||
NS_NOTREACHED("XML isn't as broken as HTML");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user