Bug 744366 - Assert about old readyState before readyState transitions. r=bzbarsky.
authorHenri Sivonen <hsivonen@iki.fi>
Tue, 17 Apr 2012 09:41:49 +0300
changeset 91823 5ed1eb2bb418416f36a715642b30a76eb52857ba
parent 91822 e78c08c87860fc30afacccfd658f2ca53f7c4e27
child 91824 eb4d4fc1f84f8f44f581f1628c5d4c85e07755c1
child 91843 40455cbb1ad3732a85a20da3f5de9e542e0e4de6
push id8407
push userhsivonen@iki.fi
push dateTue, 17 Apr 2012 06:43:06 +0000
treeherdermozilla-inbound@5ed1eb2bb418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs744366
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 744366 - Assert about old readyState before readyState transitions. r=bzbarsky.
content/base/src/nsContentSink.cpp
content/base/src/nsContentUtils.cpp
content/base/src/nsDocument.cpp
content/html/document/src/nsHTMLDocument.cpp
content/xml/document/src/nsXMLDocument.cpp
content/xslt/src/xslt/txMozillaXMLOutput.cpp
content/xslt/src/xslt/txMozillaXSLTProcessor.cpp
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -1434,16 +1434,18 @@ nsContentSink::EndUpdate(nsIDocument *aD
     UpdateChildCounts();
   }
 }
 
 void
 nsContentSink::DidBuildModelImpl(bool aTerminated)
 {
   if (mDocument && !aTerminated) {
+    MOZ_ASSERT(mDocument->GetReadyStateEnum() ==
+               nsIDocument::READYSTATE_LOADING, "Bad readyState");
     mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE);
   }
 
   if (mScriptLoader) {
     mScriptLoader->ParsingComplete(aTerminated);
   }
 
   if (!mDocument->HaveFiredDOMTitleChange()) {
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -4104,26 +4104,19 @@ nsContentUtils::CreateDocument(const nsA
                                const nsAString& aQualifiedName, 
                                nsIDOMDocumentType* aDoctype,
                                nsIURI* aDocumentURI, nsIURI* aBaseURI,
                                nsIPrincipal* aPrincipal,
                                nsIScriptGlobalObject* aEventObject,
                                DocumentFlavor aFlavor,
                                nsIDOMDocument** aResult)
 {
-  nsresult rv = NS_NewDOMDocument(aResult, aNamespaceURI, aQualifiedName,
-                                  aDoctype, aDocumentURI, aBaseURI, aPrincipal,
-                                  true, aEventObject, aFlavor);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIDocument> document = do_QueryInterface(*aResult);
-  
-  // created documents are immediately "complete" (ready to use)
-  document->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
-  return NS_OK;
+  return NS_NewDOMDocument(aResult, aNamespaceURI, aQualifiedName,
+                           aDoctype, aDocumentURI, aBaseURI, aPrincipal,
+                           true, aEventObject, aFlavor);
 }
 
 /* static */
 nsresult
 nsContentUtils::SetNodeTextContent(nsIContent* aContent,
                                    const nsAString& aValue,
                                    bool aTryReuse)
 {
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1437,22 +1437,31 @@ nsDOMImplementation::CreateDocument(cons
     return NS_ERROR_DOM_NAMESPACE_ERR;
   }
 
   nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject =
     do_QueryReferent(mScriptObject);
   
   NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject);
 
-  return nsContentUtils::CreateDocument(aNamespaceURI, aQualifiedName, aDoctype,
-                                        mDocumentURI, mBaseURI,
-                                        mOwner->NodePrincipal(),
-                                        scriptHandlingObject,
+  nsCOMPtr<nsIDOMDocument> document;
+
+  rv = nsContentUtils::CreateDocument(aNamespaceURI, aQualifiedName, aDoctype,
+                                      mDocumentURI, mBaseURI, 
+                                      mOwner->NodePrincipal(),
+                                      scriptHandlingObject,
                                         DocumentFlavorLegacyGuess,
-                                        aReturn);
+                                      getter_AddRefs(document));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
+  doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
+
+  document.forget(aReturn);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
                                         nsIDOMDocument** aReturn)
 {
   *aReturn = nsnull;
   NS_ENSURE_STATE(mOwner);
@@ -1514,16 +1523,18 @@ nsDOMImplementation::CreateHTMLDocument(
 
   nsCOMPtr<nsIContent> body;
   rv = doc->CreateElem(NS_LITERAL_STRING("body"), NULL, kNameSpaceID_XHTML,
                        getter_AddRefs(body));
   NS_ENSURE_SUCCESS(rv, rv);
   rv = root->AppendChildTo(body, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
+
   document.forget(aReturn);
 
   return NS_OK;
 }
 
 // ==================================================================
 // =
 // ==================================================================
@@ -2361,16 +2372,18 @@ nsDocument::StartDocumentLoad(const char
     aChannel->GetURI(getter_AddRefs(uri));
     nsCAutoString spec;
     if (uri)
       uri->GetSpec(spec);
     PR_LogPrint("DOCUMENT %p StartDocumentLoad %s", this, spec.get());
   }
 #endif
 
+  MOZ_ASSERT(GetReadyStateEnum() == nsIDocument::READYSTATE_UNINITIALIZED,
+             "Bad readyState");
   SetReadyStateInternal(READYSTATE_LOADING);
 
   if (nsCRT::strcmp(kLoadAsData, aCommand) == 0) {
     mLoadedAsData = true;
     // We need to disable script & style loading in this case.
     // We leave them disabled even in EndLoad(), and let anyone
     // who puts the document on display to worry about enabling.
 
@@ -7641,16 +7654,22 @@ nsDocument::CloneDocHelper(nsDocument* c
   clone->mBaseTarget = mBaseTarget;
   return NS_OK;
 }
 
 void
 nsDocument::SetReadyStateInternal(ReadyState rs)
 {
   mReadyState = rs;
+  if (rs == READYSTATE_UNINITIALIZED) {
+    // Transition back to uninitialized happens only to keep assertions happy
+    // right before readyState transitions to something else. Make this
+    // transition undetectable by Web content.
+    return;
+  }
   if (mTiming) {
     switch (rs) {
       case READYSTATE_LOADING:
         mTiming->NotifyDOMLoading(nsIDocument::GetDocumentURI());
         break;
       case READYSTATE_INTERACTIVE:
         mTiming->NotifyDOMInteractive(nsIDocument::GetDocumentURI());
         break;
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -1573,16 +1573,18 @@ nsHTMLDocument::Open(const nsAString& aC
   // knows that document.open/write/close() is being called on this
   // document.
   ++mWriteLevel;
 
   CreateAndAddWyciwygChannel();
 
   --mWriteLevel;
 
+  SetReadyStateInternal(nsIDocument::READYSTATE_LOADING);
+
   NS_ENSURE_SUCCESS(rv, rv);
   return CallQueryInterface(this, aReturn);
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::Clear()
 {
   // This method has been deprecated
--- a/content/xml/document/src/nsXMLDocument.cpp
+++ b/content/xml/document/src/nsXMLDocument.cpp
@@ -452,16 +452,24 @@ nsXMLDocument::Load(const nsAString& aUr
   // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active,
   // which in turn keeps STOP button from becoming active  
   rv = NS_NewChannel(getter_AddRefs(channel), uri, nsnull, loadGroup, req, 
                      nsIRequest::LOAD_BACKGROUND);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
+  // StartDocumentLoad asserts that readyState is uninitialized, so
+  // uninitialize it. SetReadyStateInternal make this transition invisible to
+  // Web content. But before doing that, assert that the current readyState
+  // is complete as it should be after the call to ResetToURI() above.
+  MOZ_ASSERT(GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE,
+             "Bad readyState");
+  SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED);
+
   // Prepare for loading the XML document "into oneself"
   nsCOMPtr<nsIStreamListener> listener;
   if (NS_FAILED(rv = StartDocumentLoad(kLoadAsData, channel, 
                                        loadGroup, nsnull, 
                                        getter_AddRefs(listener),
                                        false))) {
     NS_ERROR("nsXMLDocument::Load: Failed to start the document load.");
     return rv;
--- a/content/xslt/src/xslt/txMozillaXMLOutput.cpp
+++ b/content/xslt/src/xslt/txMozillaXMLOutput.cpp
@@ -253,16 +253,18 @@ txMozillaXMLOutput::endDocument(nsresult
             mNotifier->OnTransformEnd(rv);
         }
         
         return rv;
     }
 
     if (mCreatingNewDocument) {
         // This should really be handled by nsIDocument::EndLoad
+        MOZ_ASSERT(mDocument->GetReadyStateEnum() ==
+                   nsIDocument::READYSTATE_LOADING, "Bad readyState");
         mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE);
         nsScriptLoader* loader = mDocument->ScriptLoader();
         if (loader) {
             loader->ParsingComplete(false);
         }
     }
 
     if (!mRefreshString.IsEmpty()) {
@@ -832,16 +834,18 @@ txMozillaXMLOutput::createResultDocument
     }
     else {
         // We should check the root name/namespace here and create the
         // appropriate document
         rv = NS_NewXMLDocument(getter_AddRefs(mDocument));
         NS_ENSURE_SUCCESS(rv, rv);
     }
     // This should really be handled by nsIDocument::BeginLoad
+    MOZ_ASSERT(mDocument->GetReadyStateEnum() ==
+               nsIDocument::READYSTATE_UNINITIALIZED, "Bad readyState");
     mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_LOADING);
     nsCOMPtr<nsIDocument> source = do_QueryInterface(aSourceDocument);
     NS_ENSURE_STATE(source);
     bool hasHadScriptObject = false;
     nsIScriptGlobalObject* sgo =
       source->GetScriptHandlingObject(hasHadScriptObject);
     NS_ENSURE_STATE(sgo || !hasHadScriptObject);
     mDocument->SetScriptHandlingObject(sgo);
--- a/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp
+++ b/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp
@@ -682,16 +682,18 @@ txMozillaXSLTProcessor::TransformToDoc(n
     }
     
     if (NS_SUCCEEDED(rv)) {
         if (aResult) {
             txAOutputXMLEventHandler* handler =
                 static_cast<txAOutputXMLEventHandler*>(es.mOutputHandler);
             handler->getOutputDocument(aResult);
             nsCOMPtr<nsIDocument> doc = do_QueryInterface(*aResult);
+            MOZ_ASSERT(doc->GetReadyStateEnum() ==
+                       nsIDocument::READYSTATE_INTERACTIVE, "Bad readyState");
             doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
         }
     }
     else if (mObserver) {
         // XXX set up context information, bug 204655
         reportError(rv, nsnull, nsnull);
     }