Make sure to notify on the root if a flush happens before we've done so. Bug 397856, r=peterv, sr=sicking
authorbzbarsky@mit.edu
Wed, 03 Oct 2007 22:16:35 -0700
changeset 6642 086fdeddcd208de9e9d83367c01c60f13d42610a
parent 6641 8b5fca4d69d7c13a93922ed556d276cc06e79af2
child 6643 3744aa02417d7e6a171605940af7e7c0f2d66668
push idunknown
push userunknown
push dateunknown
reviewerspeterv, sicking
bugs397856
milestone1.9a9pre
Make sure to notify on the root if a flush happens before we've done so. Bug 397856, r=peterv, sr=sicking
content/html/document/src/nsHTMLContentSink.cpp
--- 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