Make sure to notify on the root if a flush happens before we've done so.
Bug 397856, r=peterv, sr=sicking
--- a/content/html/document/src/nsHTMLContentSink.cpp
+++ b/content/html/document/src/nsHTMLContentSink.cpp
@@ -309,16 +309,18 @@ protected:
virtual void PreEvaluateScript();
virtual void PostEvaluateScript(nsIScriptElement *aElement);
void UpdateChildCounts();
void NotifyInsert(nsIContent* aContent,
nsIContent* aChildContent,
PRInt32 aIndexInContainer);
+ void NotifyRootInsertion();
+
PRBool IsMonolithicContainer(nsHTMLTag aTag);
#ifdef NS_DEBUG
void ForceReflow();
#endif
};
class SinkContext
@@ -2338,34 +2340,17 @@ HTMLContentSink::OpenContainer(const nsI
rv = OpenBody(aNode);
break;
case eHTMLTag_html:
if (mRoot) {
// If we've already hit this code once, need to check for
// already-present attributes on the root.
AddAttributes(aNode, mRoot, PR_TRUE, mNotifiedRootInsertion);
if (!mNotifiedRootInsertion) {
- NS_ASSERTION(!mLayoutStarted,
- "How did we start layout without notifying on root?");
- // Now make sure to notify that we have now inserted our root. If
- // there has been no initial reflow yet it'll be a no-op, but if
- // there has been one we need this to get its frames constructed.
- // Note that if mNotifiedRootInsertion is true we don't notify here,
- // since that just means there are multiple <html> tags in the
- // document; in those cases we just want to put all the attrs on one
- // tag.
- mNotifiedRootInsertion = PR_TRUE;
- PRInt32 index = mDocument->IndexOf(mRoot);
- NS_ASSERTION(index != -1, "mRoot not child of document?");
- NotifyInsert(nsnull, mRoot, index);
-
- // Now update the notification information in all our
- // contexts, since we just inserted the root and notified on
- // our whole tree
- UpdateChildCounts();
+ NotifyRootInsertion();
}
}
break;
case eHTMLTag_form:
rv = OpenForm(aNode);
break;
default:
rv = mCurrentContext->OpenContainer(aNode);
@@ -3056,16 +3041,40 @@ HTMLContentSink::NotifyInsert(nsIContent
}
MOZ_TIMER_DEBUGLOG(("Restore: nsHTMLContentSink::NotifyInsert()\n"));
MOZ_TIMER_RESTORE(mWatch);
mInNotification--;
}
+void
+HTMLContentSink::NotifyRootInsertion()
+{
+ NS_PRECONDITION(!mNotifiedRootInsertion, "Double-notifying on root?");
+ NS_ASSERTION(!mLayoutStarted,
+ "How did we start layout without notifying on root?");
+ // Now make sure to notify that we have now inserted our root. If
+ // there has been no initial reflow yet it'll be a no-op, but if
+ // there has been one we need this to get its frames constructed.
+ // Note that if mNotifiedRootInsertion is true we don't notify here,
+ // since that just means there are multiple <html> tags in the
+ // document; in those cases we just want to put all the attrs on one
+ // tag.
+ mNotifiedRootInsertion = PR_TRUE;
+ PRInt32 index = mDocument->IndexOf(mRoot);
+ NS_ASSERTION(index != -1, "mRoot not child of document?");
+ NotifyInsert(nsnull, mRoot, index);
+
+ // Now update the notification information in all our
+ // contexts, since we just inserted the root and notified on
+ // our whole tree
+ UpdateChildCounts();
+}
+
PRBool
HTMLContentSink::IsMonolithicContainer(nsHTMLTag aTag)
{
if (aTag == eHTMLTag_tr ||
aTag == eHTMLTag_select ||
aTag == eHTMLTag_applet ||
aTag == eHTMLTag_object) {
return PR_TRUE;
@@ -3193,34 +3202,39 @@ HTMLContentSink::ProcessSTYLEEndTag(nsGe
return rv;
}
void
HTMLContentSink::FlushPendingNotifications(mozFlushType aType)
{
// Only flush tags if we're not doing the notification ourselves
// (since we aren't reentrant)
- if (mCurrentContext && !mInNotification) {
+ if (!mInNotification) {
if (aType >= Flush_ContentAndNotify) {
- mCurrentContext->FlushTags();
+ FlushTags();
}
- else {
+ else if (mCurrentContext) {
mCurrentContext->FlushText();
}
if (aType >= Flush_Layout) {
// Make sure that layout has started so that the reflow flush
// will actually happen.
StartLayout(PR_TRUE);
}
}
}
nsresult
HTMLContentSink::FlushTags()
{
+ if (!mNotifiedRootInsertion) {
+ NotifyRootInsertion();
+ return NS_OK;
+ }
+
return mCurrentContext ? mCurrentContext->FlushTags() : NS_OK;
}
NS_IMETHODIMP
HTMLContentSink::SetDocumentCharset(nsACString& aCharset)
{
if (mDocShell) {
// the following logic to get muCV is copied from