Bug 654106 - Avoid registering a script observer in the fragment parsing case. r=bzbarsky.
authorHenri Sivonen <hsivonen@iki.fi>
Wed, 04 May 2011 09:35:14 +0300
changeset 68933 c3c4c902e9cd9ccf3d0cd2bb470da53630a3066f
parent 68932 eb15fab87e7e7b2bdfcbf19a8648543be3f892ab
child 68934 3bae6630c5aff7f0e4c5449845b084e41a9bcfcf
push idunknown
push userunknown
push dateunknown
reviewersbzbarsky
bugs654106
milestone6.0a1
first release with
nightly linux32
c3c4c902e9cd / 6.0a1 / 20110504030604 / files
nightly linux64
c3c4c902e9cd / 6.0a1 / 20110504030604 / files
nightly mac
c3c4c902e9cd / 6.0a1 / 20110504030604 / files
nightly win32
c3c4c902e9cd / 6.0a1 / 20110504030604 / files
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
Bug 654106 - Avoid registering a script observer in the fragment parsing case. r=bzbarsky.
content/base/src/nsContentSink.cpp
content/base/src/nsContentSink.h
parser/html/nsHtml5Parser.cpp
parser/html/nsHtml5TreeOpExecutor.h
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -282,48 +282,52 @@ nsContentSink::Init(nsIDocument* aDoc,
   if (!aDoc || !aURI) {
     return NS_ERROR_NULL_POINTER;
   }
 
   mDocument = aDoc;
 
   mDocumentURI = aURI;
   mDocShell = do_QueryInterface(aContainer);
-  if (mDocShell) {
-    PRUint32 loadType = 0;
-    mDocShell->GetLoadType(&loadType);
-    mDocument->SetChangeScrollPosWhenScrollingToRef(
-      (loadType & nsIDocShell::LOAD_CMD_HISTORY) == 0);
+  mScriptLoader = mDocument->ScriptLoader();
+
+  if (!mFragmentMode) {
+    if (mDocShell) {
+      PRUint32 loadType = 0;
+      mDocShell->GetLoadType(&loadType);
+      mDocument->SetChangeScrollPosWhenScrollingToRef(
+        (loadType & nsIDocShell::LOAD_CMD_HISTORY) == 0);
+    }
+
+    // use this to avoid a circular reference sink->document->scriptloader->sink
+    nsCOMPtr<nsIScriptLoaderObserver> proxy =
+      new nsScriptLoaderObserverProxy(this);
+    NS_ENSURE_TRUE(proxy, NS_ERROR_OUT_OF_MEMORY);
+
+    mScriptLoader->AddObserver(proxy);
+
+    ProcessHTTPHeaders(aChannel);
   }
 
-  // use this to avoid a circular reference sink->document->scriptloader->sink
-  nsCOMPtr<nsIScriptLoaderObserver> proxy =
-      new nsScriptLoaderObserverProxy(this);
-  NS_ENSURE_TRUE(proxy, NS_ERROR_OUT_OF_MEMORY);
-
-  mScriptLoader = mDocument->ScriptLoader();
-  mScriptLoader->AddObserver(proxy);
-
   mCSSLoader = aDoc->CSSLoader();
 
-  ProcessHTTPHeaders(aChannel);
-
   mNodeInfoManager = aDoc->NodeInfoManager();
 
   mBackoffCount = sBackoffCount;
 
   if (sEnablePerfMode != 0) {
     mDynamicLowerValue = sEnablePerfMode == 1;
     FavorPerformanceHint(!mDynamicLowerValue, 0);
   }
 
-  mCanInterruptParser = sCanInterruptParser;
+  // prevent DropParserAndPerfHint from unblocking onload in the fragment
+  // case
+  mCanInterruptParser = !mFragmentMode && sCanInterruptParser;
 
   return NS_OK;
-
 }
 
 NS_IMETHODIMP
 nsContentSink::StyleSheetLoaded(nsCSSStyleSheet* aSheet,
                                 PRBool aWasAlternate,
                                 nsresult aStatus)
 {
   if (!aWasAlternate) {
--- a/content/base/src/nsContentSink.h
+++ b/content/base/src/nsContentSink.h
@@ -338,16 +338,18 @@ protected:
   // If true, we deferred starting layout until sheets load
   PRUint8 mDeferredLayoutStart : 1;
   // If true, we deferred notifications until sheets load
   PRUint8 mDeferredFlushTags : 1;
   // If false, we're not ourselves a document observer; that means we
   // shouldn't be performing any more content model notifications,
   // since we're not longer updating our child counts.
   PRUint8 mIsDocumentObserver : 1;
+  // True if this is a fragment parser
+  PRUint8 mFragmentMode : 1;
   
   //
   // -- Can interrupt parsing members --
   //
 
   // The number of tokens that have been processed since we measured
   // if it's time to return to the main event loop.
   PRUint32 mDeflectedCount;
--- a/parser/html/nsHtml5Parser.cpp
+++ b/parser/html/nsHtml5Parser.cpp
@@ -492,16 +492,18 @@ nsHtml5Parser::ParseHtml5Fragment(const 
                                   PRBool aPreventScriptExecution)
 {
   nsIDocument* doc = aTargetNode->GetOwnerDoc();
   NS_ENSURE_TRUE(doc, NS_ERROR_NOT_AVAILABLE);
   
   nsIURI* uri = doc->GetDocumentURI();
   NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);
 
+  mExecutor->EnableFragmentMode(aPreventScriptExecution);
+
   Initialize(doc, uri, nsnull, nsnull);
 
   mExecutor->SetParser(this);
   mExecutor->SetNodeInfoManager(doc->NodeInfoManager());
 
   nsIContent* target = aTargetNode;
   mTreeBuilder->setFragmentContext(aContextLocalName,
                                    aContextNamespace,
@@ -511,18 +513,16 @@ nsHtml5Parser::ParseHtml5Fragment(const 
 #ifdef DEBUG
   if (!aPreventScriptExecution) {
     nsCOMPtr<nsIDOMDocumentFragment> domFrag = do_QueryInterface(aTargetNode);
     NS_ASSERTION(domFrag,
         "If script execution isn't prevented, must parse to DOM fragment.");
   }
 #endif
 
-  mExecutor->EnableFragmentMode(aPreventScriptExecution);
-  
   NS_PRECONDITION(!mExecutor->HasStarted(),
                   "Tried to start parse without initializing the parser.");
   mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled());
   mTokenizer->start();
   mExecutor->Start(); // Don't call WillBuildModel in fragment case
   if (!aSourceBuffer.IsEmpty()) {
     PRBool lastWasCR = PR_FALSE;
     nsHtml5UTF16Buffer buffer(aSourceBuffer.Length());
--- a/parser/html/nsHtml5TreeOpExecutor.h
+++ b/parser/html/nsHtml5TreeOpExecutor.h
@@ -119,18 +119,16 @@ class nsHtml5TreeOpExecutor : public nsC
     nsHtml5TreeOpStage            mStage;
 
     eHtml5FlushState              mFlushState;
 
     PRBool                        mRunFlushLoopOnStack;
 
     PRBool                        mCallContinueInterruptedParsingIfEnabled;
 
-    PRBool                        mFragmentMode;
-
     PRBool                        mPreventScriptExecution;
 
   public:
   
     nsHtml5TreeOpExecutor();
     virtual ~nsHtml5TreeOpExecutor();
   
     // nsIContentSink
@@ -236,18 +234,16 @@ class nsHtml5TreeOpExecutor : public nsC
      * Enables the fragment mode.
      *
      * @param aPreventScriptExecution if true, scripts are prevented from
      * executing; don't set to false when parsing a fragment directly into
      * a document--only when parsing to an actual DOM fragment
      */
     void EnableFragmentMode(PRBool aPreventScriptExecution) {
       mFragmentMode = PR_TRUE;
-      mCanInterruptParser = PR_FALSE; // prevent DropParserAndPerfHint
-                                      // from unblocking onload
       mPreventScriptExecution = aPreventScriptExecution;
     }
     
     PRBool IsFragmentMode() {
       return mFragmentMode;
     }
 
     inline void BeginDocUpdate() {