Back out changeset ddda87bd4a4a (bug 765936) because of crashes. a=backout FIREFOX_BETA_15_BASE
authorMatt Brubeck <mbrubeck@mozilla.com>
Mon, 16 Jul 2012 09:45:06 -0700
changeset 98472 626ac9c0bf97bb1fb75d97286f10ec71b97e2fd1
parent 98471 ddda87bd4a4aa7110683caaee2b463dfa1a6163a
child 98473 d6c338ecc273c7c0c72e0496ccc09f07219d47ef
push idunknown
push userunknown
push dateunknown
reviewersbackout
bugs765936
milestone15.0a2
backs outddda87bd4a4aa7110683caaee2b463dfa1a6163a
Back out changeset ddda87bd4a4a (bug 765936) because of crashes. a=backout
dom/indexedDB/IDBFactory.cpp
dom/indexedDB/IDBRequest.cpp
dom/indexedDB/IDBRequest.h
dom/indexedDB/IDBWrapperCache.cpp
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -13,17 +13,16 @@
 #include "nsIScriptContext.h"
 
 #include "mozilla/storage.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfoID.h"
-#include "nsGlobalWindow.h"
 #include "nsHashKeys.h"
 #include "nsPIDOMWindow.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOMCID.h"
 
 #include "AsyncConnectionHelper.h"
 #include "CheckPermissionsHelper.h"
@@ -435,18 +434,16 @@ IDBFactory::OpenCommon(const nsAString& 
   NS_ASSERTION(mWindow || mOwningObject, "Must have one of these!");
 
   nsCOMPtr<nsPIDOMWindow> window;
   nsCOMPtr<nsIScriptGlobalObject> sgo;
   JSObject* scriptOwner = nsnull;
 
   if (mWindow) {
     window = mWindow;
-    scriptOwner =
-      static_cast<nsGlobalWindow*>(window.get())->FastGetGlobalJSObject();
   }
   else {
     scriptOwner = mOwningObject;
   }
 
   nsRefPtr<IDBOpenDBRequest> request =
     IDBOpenDBRequest::Create(window, scriptOwner);
   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -25,24 +25,27 @@
 #include "DOMError.h"
 
 USING_INDEXEDDB_NAMESPACE
 
 IDBRequest::IDBRequest()
 : mResultVal(JSVAL_VOID),
   mActorParent(nsnull),
   mErrorCode(NS_OK),
-  mHaveResultOrErrorCode(false)
+  mHaveResultOrErrorCode(false),
+  mRooted(false)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 }
 
 IDBRequest::~IDBRequest()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+  UnrootResultVal();
 }
 
 // static
 already_AddRefed<IDBRequest>
 IDBRequest::Create(nsISupports* aSource,
                    IDBWrapperCache* aOwnerCache,
                    IDBTransaction* aTransaction)
 {
@@ -61,23 +64,25 @@ IDBRequest::Create(nsISupports* aSource,
 
 void
 IDBRequest::Reset()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   mResultVal = JSVAL_VOID;
   mHaveResultOrErrorCode = false;
   mError = nsnull;
+  UnrootResultVal();
 }
 
 nsresult
 IDBRequest::NotifyHelperCompleted(HelperBase* aHelper)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!mHaveResultOrErrorCode, "Already called!");
+  NS_ASSERTION(!PreservingWrapper(), "Already rooted?!");
   NS_ASSERTION(JSVAL_IS_VOID(mResultVal), "Should be undefined!");
 
   // See if our window is still valid. If not then we're going to pretend that
   // we never completed.
   if (NS_FAILED(CheckInnerWindowCorrectness())) {
     return NS_OK;
   }
 
@@ -101,16 +106,18 @@ IDBRequest::NotifyHelperCompleted(Helper
   }
 
   JSObject* global = GetParentObject();
   NS_ASSERTION(global, "This should never be null!");
 
   JSAutoRequest ar(cx);
   JSAutoEnterCompartment ac;
   if (ac.enter(cx, global)) {
+    RootResultVal();
+
     rv = aHelper->GetSuccessResult(cx, &mResultVal);
     if (NS_FAILED(rv)) {
       NS_WARNING("GetSuccessResult failed!");
     }
   }
   else {
     NS_WARNING("Failed to enter correct compartment!");
     rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@@ -127,16 +134,17 @@ IDBRequest::NotifyHelperCompleted(Helper
   return rv;
 }
 
 void
 IDBRequest::NotifyHelperSentResultsToChildProcess(nsresult aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!mHaveResultOrErrorCode, "Already called!");
+  NS_ASSERTION(!PreservingWrapper(), "Already rooted?!");
   NS_ASSERTION(JSVAL_IS_VOID(mResultVal), "Should be undefined!");
 
   // See if our window is still valid. If not then we're going to pretend that
   // we never completed.
   if (NS_FAILED(CheckInnerWindowCorrectness())) {
     return;
   }
 
@@ -153,16 +161,17 @@ IDBRequest::SetError(nsresult aRv)
   NS_ASSERTION(NS_FAILED(aRv), "Er, what?");
   NS_ASSERTION(!mError, "Already have an error?");
 
   mHaveResultOrErrorCode = true;
   mError = DOMError::CreateForNSResult(aRv);
   mErrorCode = aRv;
 
   mResultVal = JSVAL_VOID;
+  UnrootResultVal();
 }
 
 #ifdef DEBUG
 nsresult
 IDBRequest::GetErrorCode() const
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(mHaveResultOrErrorCode, "Don't call me yet!");
@@ -193,16 +202,28 @@ IDBRequest::GetJSContext()
   NS_ENSURE_TRUE(sc, nsnull);
 
   cx = sc->GetNativeContext();
   NS_ASSERTION(cx, "Failed to get a context!");
 
   return cx;
 }
 
+void
+IDBRequest::RootResultValInternal()
+{
+  NS_HOLD_JS_OBJECTS(this, IDBRequest);
+}
+
+void
+IDBRequest::UnrootResultValInternal()
+{
+  NS_DROP_JS_OBJECTS(this, IDBRequest);
+}
+
 NS_IMETHODIMP
 IDBRequest::GetReadyState(nsAString& aReadyState)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (mHaveResultOrErrorCode) {
     aReadyState.AssignLiteral("done");
   }
@@ -270,16 +291,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(error)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSource)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mTransaction,
                                                        nsPIDOMEventTarget)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
   tmp->mResultVal = JSVAL_VOID;
+  tmp->UnrootResultVal();
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(success)
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(error)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSource)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTransaction)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(IDBRequest, IDBWrapperCache)
   // Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because
@@ -311,16 +333,18 @@ IDBRequest::PreHandleEvent(nsEventChainP
   aVisitor.mCanHandle = true;
   aVisitor.mParentTarget = mTransaction;
   return NS_OK;
 }
 
 IDBOpenDBRequest::~IDBOpenDBRequest()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+  UnrootResultVal();
 }
 
 // static
 already_AddRefed<IDBOpenDBRequest>
 IDBOpenDBRequest::Create(nsPIDOMWindow* aOwner,
                          JSObject* aScriptOwner)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@@ -340,16 +364,28 @@ IDBOpenDBRequest::SetTransaction(IDBTran
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   NS_ASSERTION(!aTransaction || !mTransaction,
                "Shouldn't have a transaction here!");
 
   mTransaction = aTransaction;
 }
 
+void
+IDBOpenDBRequest::RootResultValInternal()
+{
+  NS_HOLD_JS_OBJECTS(this, IDBOpenDBRequest);
+}
+
+void
+IDBOpenDBRequest::UnrootResultValInternal()
+{
+  NS_DROP_JS_OBJECTS(this, IDBOpenDBRequest);
+}
+
 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBOpenDBRequest)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBOpenDBRequest,
                                                   IDBRequest)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(upgradeneeded)
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(blocked)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
--- a/dom/indexedDB/IDBRequest.h
+++ b/dom/indexedDB/IDBRequest.h
@@ -77,30 +77,50 @@ public:
   {
     return mActorParent;
   }
 
 protected:
   IDBRequest();
   ~IDBRequest();
 
+  virtual void RootResultValInternal();
+  virtual void UnrootResultValInternal();
+
+  void RootResultVal()
+  {
+    if (!mRooted) {
+      RootResultValInternal();
+      mRooted = true;
+    }
+  }
+
+  void UnrootResultVal()
+  {
+    if (mRooted) {
+      UnrootResultValInternal();
+      mRooted = false;
+    }
+  }
+
   nsCOMPtr<nsISupports> mSource;
   nsRefPtr<IDBTransaction> mTransaction;
 
   NS_DECL_EVENT_HANDLER(success)
   NS_DECL_EVENT_HANDLER(error)
 
   jsval mResultVal;
 
   nsCOMPtr<nsIDOMDOMError> mError;
 
   IndexedDBRequestParentBase* mActorParent;
 
   nsresult mErrorCode;
   bool mHaveResultOrErrorCode;
+  bool mRooted;
 };
 
 class IDBOpenDBRequest : public IDBRequest,
                          public nsIIDBOpenDBRequest
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_FORWARD_NSIIDBREQUEST(IDBRequest::)
@@ -123,16 +143,19 @@ public:
   void SetTransaction(IDBTransaction* aTransaction);
 
   // nsIDOMEventTarget
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
 
 protected:
   ~IDBOpenDBRequest();
 
+  virtual void RootResultValInternal();
+  virtual void UnrootResultValInternal();
+
   // Only touched on the main thread.
   NS_DECL_EVENT_HANDLER(blocked)
   NS_DECL_EVENT_HANDLER(upgradeneeded)
 };
 
 END_INDEXEDDB_NAMESPACE
 
 #endif // mozilla_dom_indexeddb_idbrequest_h__
--- a/dom/indexedDB/IDBWrapperCache.cpp
+++ b/dom/indexedDB/IDBWrapperCache.cpp
@@ -46,17 +46,23 @@ IDBWrapperCache::~IDBWrapperCache()
   if (mScriptOwner) {
     NS_DROP_JS_OBJECTS(this, IDBWrapperCache);
   }
 }
 
 bool
 IDBWrapperCache::SetScriptOwner(JSObject* aScriptOwner)
 {
-  NS_ASSERTION(!aScriptOwner, "This should never be null!");
+  if (!aScriptOwner) {
+    NS_ASSERTION(!mScriptOwner,
+                 "Don't null out existing owner, we need to call "
+                 "DropJSObjects!");
+
+    return true;
+  }
 
   mScriptOwner = aScriptOwner;
 
   nsISupports* thisSupports = NS_CYCLE_COLLECTION_UPCAST(this, IDBWrapperCache);
   nsXPCOMCycleCollectionParticipant* participant;
   CallQueryInterface(this, &participant);
   nsresult rv = nsContentUtils::HoldJSObjects(thisSupports, participant);
   if (NS_FAILED(rv)) {