Bug 185236 part 3. Add a way to differentiate SheetComplete calls for actual loads and for the fake SheetLoadData we use to trigger observer notifications for already-complete sheets. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 26 Sep 2011 17:26:54 -0400
changeset 78926 2c05e937de5d8eb6002eb74e8b4a6f30cc303887
parent 78925 465554cdfbcc1785afd3804b7ba711add1ecdd32
child 78927 231da6eb82249cfc7fdccb858adcede1adc47ea7
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs185236
milestone9.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 185236 part 3. Add a way to differentiate SheetComplete calls for actual loads and for the fake SheetLoadData we use to trigger observer notifications for already-complete sheets. r=peterv
layout/style/Loader.cpp
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -235,16 +235,20 @@ public:
   // in the loaded sheet.
   PRPackedBool               mAllowUnsafeRules : 1;
 
   // mUseSystemPrincipal is true if the system principal should be used for
   // this sheet, no matter what the channel principal is.  Only true for sync
   // loads.
   PRPackedBool               mUseSystemPrincipal : 1;
 
+  // If true, this SheetLoadData is being used as a way to handle
+  // async observer notification for an already-complete sheet.
+  PRPackedBool               mSheetAlreadyComplete : 1;
+
   // This is the element that imported the sheet.  Needed to get the
   // charset set on it.
   nsCOMPtr<nsIStyleSheetLinkingElement> mOwningElement;
 
   // The observer that wishes to be notified of load completion
   nsCOMPtr<nsICSSLoaderObserver>        mObserver;
 
   // The principal that identifies who started loading us.
@@ -325,16 +329,17 @@ SheetLoadData::SheetLoadData(Loader* aLo
     mSyncLoad(PR_FALSE),
     mIsNonDocumentSheet(PR_FALSE),
     mIsLoading(PR_FALSE),
     mIsCancelled(PR_FALSE),
     mMustNotify(PR_FALSE),
     mWasAlternate(aIsAlternate),
     mAllowUnsafeRules(PR_FALSE),
     mUseSystemPrincipal(PR_FALSE),
+    mSheetAlreadyComplete(PR_FALSE),
     mOwningElement(aOwningElement),
     mObserver(aObserver),
     mLoaderPrincipal(aLoaderPrincipal)
 {
   NS_PRECONDITION(mLoader, "Must have a loader!");
   NS_ADDREF(mLoader);
 }
 
@@ -354,16 +359,17 @@ SheetLoadData::SheetLoadData(Loader* aLo
     mSyncLoad(PR_FALSE),
     mIsNonDocumentSheet(PR_FALSE),
     mIsLoading(PR_FALSE),
     mIsCancelled(PR_FALSE),
     mMustNotify(PR_FALSE),
     mWasAlternate(PR_FALSE),
     mAllowUnsafeRules(PR_FALSE),
     mUseSystemPrincipal(PR_FALSE),
+    mSheetAlreadyComplete(PR_FALSE),
     mOwningElement(nsnull),
     mObserver(aObserver),
     mLoaderPrincipal(aLoaderPrincipal)
 {
   NS_PRECONDITION(mLoader, "Must have a loader!");
   NS_ADDREF(mLoader);
   if (mParentData) {
     NS_ADDREF(mParentData);
@@ -397,16 +403,17 @@ SheetLoadData::SheetLoadData(Loader* aLo
     mSyncLoad(aSyncLoad),
     mIsNonDocumentSheet(PR_TRUE),
     mIsLoading(PR_FALSE),
     mIsCancelled(PR_FALSE),
     mMustNotify(PR_FALSE),
     mWasAlternate(PR_FALSE),
     mAllowUnsafeRules(aAllowUnsafeRules),
     mUseSystemPrincipal(aUseSystemPrincipal),
+    mSheetAlreadyComplete(PR_FALSE),
     mOwningElement(nsnull),
     mObserver(aObserver),
     mLoaderPrincipal(aLoaderPrincipal),
     mCharsetHint(aCharset)
 {
   NS_PRECONDITION(mLoader, "Must have a loader!");
   NS_ADDREF(mLoader);
 
@@ -1645,17 +1652,19 @@ Loader::DoSheetComplete(SheetLoadData* a
     }
   }
 
   // Go through and deal with the whole linked list.
   SheetLoadData* data = aLoadData;
   while (data) {
     NS_ABORT_IF_FALSE(!data->mSheet->IsModified(),
                       "should not get marked modified during parsing");
-    data->mSheet->SetComplete();
+    if (!data->mSheetAlreadyComplete) {
+      data->mSheet->SetComplete();
+    }
     if (data->mMustNotify && (data->mObserver || !mObservers.IsEmpty())) {
       // Don't notify here so we don't trigger script.  Remember the
       // info we need to notify, then do it later when it's safe.
       aDatasToNotify.AppendElement(data);
 
       // On append failure, just press on.  We'll fail to notify the observer,
       // but not much we can do about that....
     }
@@ -1746,21 +1755,16 @@ Loader::LoadInlineStyle(nsIContent* aEle
 
   rv = InsertSheetInDoc(sheet, aElement, mDocument);
   NS_ENSURE_SUCCESS(rv, rv);
 
   SheetLoadData* data = new SheetLoadData(this, aTitle, nsnull, sheet,
                                           owningElement, *aIsAlternate,
                                           aObserver, nsnull);
 
-  if (!data) {
-    sheet->SetComplete();
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
   // We never actually load this, so just set its principal directly
   sheet->SetPrincipal(aElement->NodePrincipal());
 
   NS_ADDREF(data);
   data->mLineNumber = aLineNumber;
   // Parse completion releases the load data
   rv = ParseSheet(aBuffer, data, *aCompleted);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1822,35 +1826,30 @@ Loader::LoadStyleLink(nsIContent* aEleme
   LOG(("  Sheet is alternate: %d", *aIsAlternate));
 
   rv = InsertSheetInDoc(sheet, aElement, mDocument);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (state == eSheetComplete) {
     LOG(("  Sheet already complete: 0x%p",
          static_cast<void*>(sheet.get())));
-    if (aObserver) {
+    if (aObserver || !mObservers.IsEmpty()) {
       rv = PostLoadEvent(aURL, sheet, aObserver, *aIsAlternate);
       return rv;
     }
 
     return NS_OK;
   }
 
   nsCOMPtr<nsIStyleSheetLinkingElement> owningElement(do_QueryInterface(aElement));
 
   // Now we need to actually load it
   SheetLoadData* data = new SheetLoadData(this, aTitle, aURL, sheet,
                                           owningElement, *aIsAlternate,
                                           aObserver, principal);
-  if (!data) {
-    sheet->SetComplete();
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
   NS_ADDREF(data);
 
   // If we have to parse and it's an alternate non-inline, defer it
   if (aURL && state == eSheetNeedsParser && mLoadingDatas.Count() != 0 &&
       *aIsAlternate) {
     LOG(("  Deferring alternate sheet load"));
     URIAndPrincipalHashKey key(data->mURI, data->mLoaderPrincipal);
     if (!mPendingDatas.Put(&key, data)) {
@@ -1991,21 +1990,16 @@ Loader::LoadChildSheet(nsCSSStyleSheet* 
     // @import rule addition/modification will trigger the right style
     // changes automatically.
     return NS_OK;
   }
 
   SheetLoadData* data = new SheetLoadData(this, aURL, sheet, parentData,
                                           observer, principal);
 
-  if (!data) {
-    sheet->SetComplete();
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
   NS_ADDREF(data);
   PRBool syncLoad = data->mSyncLoad;
 
   // Load completion will release the data
   rv = LoadSheet(data, state);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If syncLoad is true, |data| will be deleted by now.
@@ -2092,35 +2086,30 @@ Loader::InternalLoadNonDocumentSheet(nsI
   NS_ENSURE_SUCCESS(rv, rv);
 
   const nsSubstring& empty = EmptyString();
   rv = PrepareSheet(sheet, empty, empty, nsnull);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (state == eSheetComplete) {
     LOG(("  Sheet already complete"));
-    if (aObserver) {
+    if (aObserver || !mObservers.IsEmpty()) {
       rv = PostLoadEvent(aURL, sheet, aObserver, PR_FALSE);
     }
     if (aSheet) {
       sheet.swap(*aSheet);
     }
     return rv;
   }
 
   SheetLoadData* data =
     new SheetLoadData(this, aURL, sheet, syncLoad, aAllowUnsafeRules,
                       aUseSystemPrincipal, aCharset, aObserver,
                       aOriginPrincipal);
 
-  if (!data) {
-    sheet->SetComplete();
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
   NS_ADDREF(data);
   rv = LoadSheet(data, state);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aSheet) {
     sheet.swap(*aSheet);
   }
   if (aObserver) {
@@ -2133,17 +2122,17 @@ Loader::InternalLoadNonDocumentSheet(nsI
 nsresult
 Loader::PostLoadEvent(nsIURI* aURI,
                       nsCSSStyleSheet* aSheet,
                       nsICSSLoaderObserver* aObserver,
                       PRBool aWasAlternate)
 {
   LOG(("css::Loader::PostLoadEvent"));
   NS_PRECONDITION(aSheet, "Must have sheet");
-  NS_PRECONDITION(aObserver, "Must have observer");
+  NS_PRECONDITION(aObserver || !mObservers.IsEmpty(), "Must have observer");
 
   nsRefPtr<SheetLoadData> evt =
     new SheetLoadData(this, EmptyString(), // title doesn't matter here
                       aURI,
                       aSheet,
                       nsnull,  // owning element doesn't matter here
                       aWasAlternate,
                       aObserver,
@@ -2161,16 +2150,17 @@ Loader::PostLoadEvent(nsIURI* aURI,
   } else {
     // We'll unblock onload when we handle the event.
     if (mDocument) {
       mDocument->BlockOnload();
     }
 
     // We want to notify the observer for this data.
     evt->mMustNotify = PR_TRUE;
+    evt->mSheetAlreadyComplete = PR_TRUE;
   }
 
   return rv;
 }
 
 void
 Loader::HandleLoadEvent(SheetLoadData* aEvent)
 {