diff --git a/content/html/document/src/nsHTMLFragmentContentSink.cpp b/content/html/document/src/nsHTMLFragmentContentSink.cpp
index 61c5669d6a5e..aa9e59ff3493 100644
--- a/content/html/document/src/nsHTMLFragmentContentSink.cpp
+++ b/content/html/document/src/nsHTMLFragmentContentSink.cpp
@@ -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 mRoot;
nsCOMPtr 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()
{
diff --git a/content/xml/document/src/nsXMLFragmentContentSink.cpp b/content/xml/document/src/nsXMLFragmentContentSink.cpp
index cb7727a551ae..940824129f36 100644
--- a/content/xml/document/src/nsXMLFragmentContentSink.cpp
+++ b/content/xml/document/src/nsXMLFragmentContentSink.cpp
@@ -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;
+}
+
diff --git a/parser/htmlparser/public/nsIFragmentContentSink.h b/parser/htmlparser/public/nsIFragmentContentSink.h
index 91f4e35fc9bf..8b959900fb0a 100644
--- a/parser/htmlparser/public/nsIFragmentContentSink.h
+++ b/parser/htmlparser/public/nsIFragmentContentSink.h
@@ -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;
};
/**
diff --git a/parser/htmlparser/src/nsParser.cpp b/parser/htmlparser/src/nsParser.cpp
index 4c5fcda3c352..99a835409368 100644
--- a/parser/htmlparser/src/nsParser.cpp
+++ b/parser/htmlparser/src/nsParser.cpp
@@ -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("");
- }
-
// 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 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 in the context.
+ // XXX This is extremely ugly. Maybe CNavDTD should have FlushMisplaced()?
+ NS_ASSERTION(mParserContext, "Parsing didn't create a parser context?");
+ nsCOMPtr 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