Bug 769356: Calling transaction.abort() should leave transaction.error as null, but throwing exceptions should set transaction.error. r=sicking
authorKyle Huey <khuey@kylehuey.com>
Fri, 29 Jun 2012 09:48:34 -0700
changeset 97923 1cf5fe8cdb15fa40206d3303f15004f0756f7da6
parent 97922 5424f28013c674fe90a3cdd87459b9ff2c57adf3
child 97924 6b50a5c705c26841fd7dd665f62e6736d85e589e
push id23010
push userkhuey@mozilla.com
push dateFri, 29 Jun 2012 17:39:48 +0000
treeherdermozilla-central@027b86239bf3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs769356
milestone16.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 769356: Calling transaction.abort() should leave transaction.error as null, but throwing exceptions should set transaction.error. r=sicking
dom/indexedDB/AsyncConnectionHelper.cpp
dom/indexedDB/IDBDatabase.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IDBTransaction.cpp
dom/indexedDB/IDBTransaction.h
dom/indexedDB/ipc/IndexedDBParent.cpp
dom/indexedDB/test/exceptions_in_events_iframe.html
--- a/dom/indexedDB/AsyncConnectionHelper.cpp
+++ b/dom/indexedDB/AsyncConnectionHelper.cpp
@@ -433,17 +433,17 @@ AsyncConnectionHelper::OnSuccess()
   NS_ASSERTION(!mTransaction ||
                mTransaction->IsOpen() ||
                mTransaction->IsAborted(),
                "How else can this be closed?!");
 
   if ((internalEvent->flags & NS_EVENT_FLAG_EXCEPTION_THROWN) &&
       mTransaction &&
       mTransaction->IsOpen()) {
-    rv = mTransaction->Abort();
+    rv = mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 void
 AsyncConnectionHelper::OnError()
@@ -469,17 +469,17 @@ AsyncConnectionHelper::OnError()
                  "How else can this be closed?!");
 
     nsEvent* internalEvent = event->GetInternalNSEvent();
     NS_ASSERTION(internalEvent, "This should never be null!");
 
     if ((internalEvent->flags & NS_EVENT_FLAG_EXCEPTION_THROWN) &&
         mTransaction &&
         mTransaction->IsOpen() &&
-        NS_FAILED(mTransaction->Abort())) {
+        NS_FAILED(mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR))) {
       NS_WARNING("Failed to abort transaction!");
     }
 
     if (doDefault &&
         mTransaction &&
         mTransaction->IsOpen() &&
         NS_FAILED(mTransaction->Abort(mRequest))) {
       NS_WARNING("Failed to abort transaction!");
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -813,17 +813,17 @@ NoRequestDatabaseHelper::OnSuccess()
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   return NS_OK;
 }
 
 void
 NoRequestDatabaseHelper::OnError()
 {
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
-  mTransaction->AbortWithCode(GetResultCode());
+  mTransaction->Abort(GetResultCode());
 }
 
 nsresult
 CreateObjectStoreHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   nsCOMPtr<mozIStorageStatement> stmt =
     mTransaction->GetCachedStatement(NS_LITERAL_CSTRING(
     "INSERT INTO object_store (id, auto_increment, name, key_path) "
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -2352,17 +2352,17 @@ NoRequestObjectStoreHelper::OnSuccess()
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   return NS_OK;
 }
 
 void
 NoRequestObjectStoreHelper::OnError()
 {
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
-  mTransaction->AbortWithCode(GetResultCode());
+  mTransaction->Abort(GetResultCode());
 }
 
 nsresult
 AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(aConnection, "Passed a null connection!");
 
   nsresult rv;
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -493,33 +493,37 @@ IDBTransaction::AddFileInfo(nsIDOMBlob* 
 
 void
 IDBTransaction::ClearCreatedFileInfos()
 {
   mCreatedFileInfos.Clear();
 }
 
 nsresult
-IDBTransaction::AbortWithCode(nsresult aAbortCode)
+IDBTransaction::AbortInternal(nsresult aAbortCode,
+                              already_AddRefed<nsIDOMDOMError> aError)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
+  nsCOMPtr<nsIDOMDOMError> error = aError;
+
   if (IsFinished()) {
     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
   }
 
   if (mActorChild) {
     NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
     mActorChild->SendAbort(aAbortCode);
   }
 
   bool needToCommitOrRollback = mReadyState == IDBTransaction::INITIAL;
 
   mAbortCode = aAbortCode;
   mReadyState = IDBTransaction::DONE;
+  mError = error.forget();
 
   if (GetMode() == IDBTransaction::VERSION_CHANGE) {
     // If a version change transaction is aborted, we must revert the world
     // back to its previous state.
     mDatabase->RevertToPreviousState();
 
     DatabaseInfo* dbInfo = mDatabase->Info();
 
@@ -561,19 +565,28 @@ IDBTransaction::AbortWithCode(nsresult a
 }
 
 nsresult
 IDBTransaction::Abort(IDBRequest* aRequest)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aRequest, "This is undesirable.");
 
-  aRequest->GetError(getter_AddRefs(mError));
+  nsCOMPtr<nsIDOMDOMError> error;
+  aRequest->GetError(getter_AddRefs(error));
+
+  return AbortInternal(aRequest->GetErrorCode(), error.forget());
+}
 
-  return AbortWithCode(aRequest->GetErrorCode());
+nsresult
+IDBTransaction::Abort(nsresult aErrorCode)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+  return AbortInternal(aErrorCode, DOMError::CreateForNSResult(aErrorCode));
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBTransaction)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBTransaction,
                                                   IDBWrapperCache)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mDatabase,
                                                        nsIDOMEventTarget)
@@ -742,17 +755,17 @@ IDBTransaction::ObjectStoreInternal(cons
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 IDBTransaction::Abort()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-  return AbortWithCode(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
+  return AbortInternal(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR, nsnull);
 }
 
 nsresult
 IDBTransaction::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   aVisitor.mCanHandle = true;
   aVisitor.mParentTarget = mDatabase;
   return NS_OK;
--- a/dom/indexedDB/IDBTransaction.h
+++ b/dom/indexedDB/IDBTransaction.h
@@ -188,28 +188,31 @@ public:
     return mActorChild;
   }
 
   nsresult
   ObjectStoreInternal(const nsAString& aName,
                       IDBObjectStore** _retval);
 
   nsresult
-  AbortWithCode(nsresult aAbortCode);
+  Abort(IDBRequest* aRequest);
 
   nsresult
-  Abort(IDBRequest* aRequest);
+  Abort(nsresult aAbortCode);
 
   nsresult
   GetAbortCode() const
   {
     return mAbortCode;
   }
 
 private:
+  nsresult
+  AbortInternal(nsresult aAbortCode, already_AddRefed<nsIDOMDOMError> aError);
+
   // Should only be called directly through IndexedDBDatabaseChild.
   static already_AddRefed<IDBTransaction>
   CreateInternal(IDBDatabase* aDatabase,
                  nsTArray<nsString>& aObjectStoreNames,
                  Mode aMode,
                  bool aDispatchDelayed,
                  bool aIsVersionChangeTransactionChild);
 
--- a/dom/indexedDB/ipc/IndexedDBParent.cpp
+++ b/dom/indexedDB/ipc/IndexedDBParent.cpp
@@ -573,17 +573,17 @@ IndexedDBTransactionParent::ActorDestroy
     mTransaction->SetActor(static_cast<IndexedDBTransactionParent*>(NULL));
   }
 }
 
 bool
 IndexedDBTransactionParent::RecvAbort(const nsresult& aAbortCode)
 {
   MOZ_ASSERT(mTransaction);
-  mTransaction->AbortWithCode(aAbortCode);
+  mTransaction->Abort(aAbortCode);
   return true;
 }
 
 bool
 IndexedDBTransactionParent::RecvAllRequestsFinished()
 {
   MOZ_ASSERT(mTransaction);
   MOZ_ASSERT(mArtificialRequestCount);
--- a/dom/indexedDB/test/exceptions_in_events_iframe.html
+++ b/dom/indexedDB/test/exceptions_in_events_iframe.html
@@ -63,17 +63,17 @@
         transaction.oncomplete = unexpectedSuccessHandler;
         transaction.onabort = grabEventAndContinueHandler
         throw "STOP";
       };
 
       let event = yield;
       is(event.type, "abort",
          "Throwing during an upgradeneeded event should abort the transaction.");
-      is(event.target.error, null, "Got null error object");
+      is(event.target.error.name, "AbortError", "Got AbortError object");
 
       request.onerror = grabEventAndContinueHandler;
       event = yield;
 
       is(event.type, "error",
          "Throwing during an upgradeneeded event should fire an error.");
 
       // Test 2: Throwing during a request's success handler should abort the
@@ -107,17 +107,17 @@
       request = objectStore.add({}, 1);
       request.onsuccess = function(event) {
         throw "foo";
       };
 
       event = yield;
 
       is(event.type, "abort", "Got transaction abort event");
-      is(event.target.error, null, "Got null error object");
+      is(event.target.error.name, "AbortError", "Got AbortError object");
       openrequest.onerror = grabEventAndContinueHandler;
 
       event = yield;
 
       is(event.type, "error", "Got IDBOpenDBRequest error event");
       is(event.target, openrequest, "Right event target");
       is(event.target.error.name, "AbortError", "Right error name");
 
@@ -156,17 +156,17 @@
       request.onerror = function (event) {
         event.preventDefault();
         throw "STOP";
       };
 
       event = yield;
 
       is(event.type, "abort", "Got transaction abort event");
-      is(event.target.error, null, "Got null error object");
+      is(event.target.error.name, "AbortError", "Got AbortError object");
       openrequest.onerror = grabEventAndContinueHandler;
 
       event = yield;
 
       is(event.type, "error", "Got IDBOpenDBRequest error event");
       is(event.target, openrequest, "Right event target");
       is(event.target.error.name, "AbortError", "Right error name");