Bug 1598164 - Align ReadyState with states defined in the spec. r=dom-workers-and-storage-reviewers,edenchuang
authorSimon Giesecke <sgiesecke@mozilla.com>
Thu, 28 Nov 2019 16:00:29 +0000
changeset 504262 97a03c24e865c8826fac62e76cd552c7c1e5d443
parent 504261 6992a67bab45d5fe2bed849b0f07814ece54b2d4
child 504263 fb6184becfbd6b9e8f648ca836acbf5e00812bad
push id101838
push usersgiesecke@mozilla.com
push dateThu, 28 Nov 2019 16:38:05 +0000
treeherderautoland@fb6184becfbd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdom-workers-and-storage-reviewers, edenchuang
bugs1598164
milestone72.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 1598164 - Align ReadyState with states defined in the spec. r=dom-workers-and-storage-reviewers,edenchuang Differential Revision: https://phabricator.services.mozilla.com/D54322
dom/indexedDB/ActorsChild.cpp
dom/indexedDB/IDBCursor.cpp
dom/indexedDB/IDBDatabase.cpp
dom/indexedDB/IDBIndex.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IDBTransaction.cpp
dom/indexedDB/IDBTransaction.h
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -684,23 +684,24 @@ void DispatchErrorEvent(IDBRequest* aReq
 
   IgnoredErrorResult rv;
   const bool doDefault =
       request->DispatchEvent(*aEvent, CallerType::System, rv);
   if (NS_WARN_IF(rv.Failed())) {
     return;
   }
 
-  MOZ_ASSERT(!transaction || transaction->IsOpen() || transaction->IsAborted());
+  MOZ_ASSERT(!transaction || transaction->CanAcceptRequests() ||
+             transaction->IsAborted());
 
   // Do not abort the transaction here if this request is failed due to the
   // abortion of its transaction to ensure that the correct error cause of
   // the abort event be set in IDBTransaction::FireCompleteOrAbortEvents()
   // later.
-  if (transaction && transaction->IsOpen() &&
+  if (transaction && transaction->CanAcceptRequests() &&
       aErrorCode != NS_ERROR_DOM_INDEXEDDB_ABORT_ERR) {
     WidgetEvent* const internalEvent = aEvent->WidgetEventPtr();
     MOZ_ASSERT(internalEvent);
 
     if (internalEvent->mFlags.mExceptionWasRaised) {
       transaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
     } else if (doDefault) {
       transaction->Abort(request);
@@ -733,42 +734,42 @@ void DispatchSuccessEvent(ResultHelper* 
     MOZ_ASSERT(successEvent);
 
     aEvent = successEvent;
   }
 
   request->SetResultCallback(aResultHelper);
 
   MOZ_ASSERT(aEvent);
-  MOZ_ASSERT_IF(transaction, transaction->IsOpen());
+  MOZ_ASSERT_IF(transaction, transaction->CanAcceptRequests());
 
   if (transaction) {
     IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
         "Firing %s event", "%s", transaction->LoggingSerialNumber(),
         request->LoggingSerialNumber(),
         IDB_LOG_STRINGIFY(aEvent, kSuccessEventType));
   } else {
     IDB_LOG_MARK_CHILD_REQUEST("Firing %s event", "%s",
                                request->LoggingSerialNumber(),
                                IDB_LOG_STRINGIFY(aEvent, kSuccessEventType));
   }
 
   MOZ_ASSERT_IF(transaction,
-                transaction->IsOpen() && !transaction->IsAborted());
+                transaction->CanAcceptRequests() && !transaction->IsAborted());
 
   IgnoredErrorResult rv;
   request->DispatchEvent(*aEvent, rv);
   if (NS_WARN_IF(rv.Failed())) {
     return;
   }
 
   WidgetEvent* const internalEvent = aEvent->WidgetEventPtr();
   MOZ_ASSERT(internalEvent);
 
-  if (transaction && transaction->IsOpen()) {
+  if (transaction && transaction->CanAcceptRequests()) {
     if (internalEvent->mFlags.mExceptionWasRaised) {
       transaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
     } else {
       // To handle upgrade transaction.
       transaction->Run();
     }
   }
 }
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -190,17 +190,17 @@ void IDBCursor::DropJSObjects() {
   mRooted = false;
 
   mozilla::DropJSObjects(this);
 }
 
 bool IDBCursor::IsSourceDeleted() const {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mTransaction);
-  MOZ_ASSERT(mTransaction->IsOpen());
+  MOZ_ASSERT(mTransaction->CanAcceptRequests());
 
   IDBObjectStore* sourceObjectStore;
   if (mType == Type_Index || mType == Type_IndexKey) {
     MOZ_ASSERT(mSourceIndex);
 
     if (mSourceIndex->IsDeleted()) {
       return true;
     }
@@ -371,17 +371,17 @@ void IDBCursor::GetValue(JSContext* aCx,
 
   aResult.set(mCachedValue);
 }
 
 void IDBCursor::Continue(JSContext* aCx, JS::Handle<JS::Value> aKey,
                          ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return;
   }
 
   if (IsSourceDeleted() || !mHaveValue || mContinueCalled) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return;
   }
@@ -461,17 +461,17 @@ void IDBCursor::Continue(JSContext* aCx,
   mContinueCalled = true;
 }
 
 void IDBCursor::ContinuePrimaryKey(JSContext* aCx, JS::Handle<JS::Value> aKey,
                                    JS::Handle<JS::Value> aPrimaryKey,
                                    ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return;
   }
 
   if (IsSourceDeleted()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return;
   }
@@ -570,17 +570,17 @@ void IDBCursor::ContinuePrimaryKey(JSCon
 void IDBCursor::Advance(uint32_t aCount, ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
   if (!aCount) {
     aRv.ThrowTypeError(u"0 (Zero) is not a valid advance count.");
     return;
   }
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return;
   }
 
   if (IsSourceDeleted() || !mHaveValue || mContinueCalled) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return;
   }
@@ -613,17 +613,17 @@ void IDBCursor::Advance(uint32_t aCount,
   mContinueCalled = true;
 }
 
 already_AddRefed<IDBRequest> IDBCursor::Update(JSContext* aCx,
                                                JS::Handle<JS::Value> aValue,
                                                ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   if (!mTransaction->IsWriteAllowed()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
     return nullptr;
   }
@@ -724,17 +724,17 @@ already_AddRefed<IDBRequest> IDBCursor::
 
   return request.forget();
 }
 
 already_AddRefed<IDBRequest> IDBCursor::Delete(JSContext* aCx,
                                                ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   if (!mTransaction->IsWriteAllowed()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
     return nullptr;
   }
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -369,17 +369,17 @@ already_AddRefed<IDBObjectStore> IDBData
 
   IDBTransaction* transaction = IDBTransaction::GetCurrent();
   if (!transaction || transaction->Database() != this ||
       transaction->GetMode() != IDBTransaction::Mode::VersionChange) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
-  if (!transaction->IsOpen()) {
+  if (!transaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   KeyPath keyPath(0);
   if (NS_FAILED(KeyPath::Parse(aOptionalParameters.mKeyPath, &keyPath))) {
     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
     return nullptr;
@@ -442,17 +442,17 @@ void IDBDatabase::DeleteObjectStore(cons
 
   IDBTransaction* transaction = IDBTransaction::GetCurrent();
   if (!transaction || transaction->Database() != this ||
       transaction->GetMode() != IDBTransaction::Mode::VersionChange) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return;
   }
 
-  if (!transaction->IsOpen()) {
+  if (!transaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return;
   }
 
   auto& specArray = mSpec->objectStores();
   const auto end = specArray.end();
   const auto foundIt =
       std::find_if(specArray.begin(), end, [&aName](const auto& objectStore) {
@@ -735,17 +735,17 @@ void IDBDatabase::AbortTransactions(bool
         IDBTransaction* transaction = iter.Get()->GetKey();
         MOZ_ASSERT(transaction);
 
         transaction->AssertIsOnOwningThread();
 
         // Transactions that are already done can simply be ignored. Otherwise
         // there is a race here and it's possible that the transaction has not
         // been successfully committed yet so we will warn the user.
-        if (!transaction->IsDone()) {
+        if (!transaction->IsFinished()) {
           transactionsToAbort.AppendElement(transaction);
         }
       }
       MOZ_ASSERT(transactionsToAbort.Length() <= transactionTable.Count());
 
       if (transactionsToAbort.IsEmpty()) {
         // Return early as an optimization, the remainder is a no-op in this
         // case.
@@ -756,17 +756,17 @@ void IDBDatabase::AbortTransactions(bool
       // transactions once and abort them all first, collecting the transactions
       // that need to have a warning issued along the way. Those that need a
       // warning will be a subset of those that are aborted, so we don't need
       // additional strong references here.
       WeakTransactionArray transactionsThatNeedWarning;
 
       for (RefPtr<IDBTransaction>& transaction : transactionsToAbort) {
         MOZ_ASSERT(transaction);
-        MOZ_ASSERT(!transaction->IsDone());
+        MOZ_ASSERT(!transaction->IsFinished());
 
         // We warn for any transactions that could have written data, but
         // ignore read-only transactions.
         if (aShouldWarn && transaction->IsWriteAllowed()) {
           transactionsThatNeedWarning.AppendElement(transaction);
         }
 
         transaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -133,17 +133,17 @@ void IDBIndex::SetName(const nsAString& 
   IDBTransaction* const transaction = mObjectStore->Transaction();
 
   if (transaction->GetMode() != IDBTransaction::Mode::VersionChange ||
       mDeletedMetadata) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
-  if (!transaction->IsOpen()) {
+  if (!transaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return;
   }
 
   if (aName == mMetadata->name()) {
     return;
   }
 
@@ -266,17 +266,17 @@ already_AddRefed<IDBRequest> IDBIndex::G
   AssertIsOnOwningThread();
 
   if (mDeletedMetadata) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
   IDBTransaction* transaction = mObjectStore->Transaction();
-  if (!transaction->IsOpen()) {
+  if (!transaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   RefPtr<IDBKeyRange> keyRange;
   IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange), aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
@@ -341,17 +341,17 @@ already_AddRefed<IDBRequest> IDBIndex::G
   AssertIsOnOwningThread();
 
   if (mDeletedMetadata) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
   IDBTransaction* transaction = mObjectStore->Transaction();
-  if (!transaction->IsOpen()) {
+  if (!transaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   RefPtr<IDBKeyRange> keyRange;
   IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange), aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
@@ -416,17 +416,17 @@ already_AddRefed<IDBRequest> IDBIndex::O
   AssertIsOnOwningThread();
 
   if (mDeletedMetadata) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
   IDBTransaction* transaction = mObjectStore->Transaction();
-  if (!transaction->IsOpen()) {
+  if (!transaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   RefPtr<IDBKeyRange> keyRange;
   IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange), aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
@@ -498,17 +498,17 @@ already_AddRefed<IDBRequest> IDBIndex::C
   AssertIsOnOwningThread();
 
   if (mDeletedMetadata) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
   IDBTransaction* const transaction = mObjectStore->Transaction();
-  if (!transaction->IsOpen()) {
+  if (!transaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   RefPtr<IDBKeyRange> keyRange;
   IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange), aRv);
   if (aRv.Failed()) {
     return nullptr;
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -1495,17 +1495,17 @@ already_AddRefed<IDBRequest> IDBObjectSt
   MOZ_ASSERT_IF(aFromCursor, aOverwrite);
 
   if (mTransaction->GetMode() == IDBTransaction::Mode::Cleanup ||
       mDeletedSpec) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   if (!mTransaction->IsWriteAllowed()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
     return nullptr;
   }
@@ -1518,17 +1518,17 @@ already_AddRefed<IDBRequest> IDBObjectSt
     const auto autoStateRestore = mTransaction->TemporarilyProceedToInactive();
     GetAddInfo(aCx, aValueWrapper, aKey, cloneWriteInfo, key, updateInfo, aRv);
   }
 
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   // Check the size limit of the serialized message which mainly consists of
   // a StructuredCloneBuffer, an encoded object key, and the encoded index keys.
   // kMaxIDBMsgOverhead covers the minor stuff not included in this calculation
   // because the precise calculation would slow down this AddOrPut operation.
@@ -1688,17 +1688,17 @@ already_AddRefed<IDBRequest> IDBObjectSt
     const Optional<uint32_t>& aLimit, ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
   if (mDeletedSpec) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   RefPtr<IDBKeyRange> keyRange;
   IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange), aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
@@ -1759,17 +1759,17 @@ already_AddRefed<IDBRequest> IDBObjectSt
                                                    ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
   if (mDeletedSpec) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   if (!mTransaction->IsWriteAllowed()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
     return nullptr;
   }
@@ -1792,17 +1792,17 @@ already_AddRefed<IDBRequest> IDBObjectSt
 
   return request.forget();
 }
 
 already_AddRefed<IDBIndex> IDBObjectStore::Index(const nsAString& aName,
                                                  ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
-  if (mTransaction->IsCommittingOrDone() || mDeletedSpec) {
+  if (mTransaction->IsCommittingOrFinished() || mDeletedSpec) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
 
   const nsTArray<IndexMetadata>& indexMetadatas = mSpec->indexes();
 
   const auto endIndexMetadatas = indexMetadatas.cend();
   const auto foundMetadata =
@@ -1930,17 +1930,17 @@ already_AddRefed<IDBRequest> IDBObjectSt
     ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
   if (mDeletedSpec) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   RefPtr<IDBKeyRange> keyRange;
   IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange), aRv);
   if (aRv.Failed()) {
     return nullptr;
@@ -1987,17 +1987,17 @@ already_AddRefed<IDBRequest> IDBObjectSt
     ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
   if (mDeletedSpec) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   if (!mTransaction->IsWriteAllowed()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
     return nullptr;
   }
@@ -2045,17 +2045,18 @@ already_AddRefed<IDBIndex> IDBObjectStor
 
   if (mTransaction->GetMode() != IDBTransaction::Mode::VersionChange ||
       mDeletedSpec) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
   IDBTransaction* const transaction = IDBTransaction::GetCurrent();
-  if (!transaction || transaction != mTransaction || !transaction->IsOpen()) {
+  if (!transaction || transaction != mTransaction ||
+      !transaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   auto& indexes = const_cast<nsTArray<IndexMetadata>&>(mSpec->indexes());
   for (uint32_t count = indexes.Length(), index = 0; index < count; index++) {
     if (aName == indexes[index].name()) {
       aRv.ThrowDOMException(
@@ -2145,17 +2146,18 @@ void IDBObjectStore::DeleteIndex(const n
 
   if (mTransaction->GetMode() != IDBTransaction::Mode::VersionChange ||
       mDeletedSpec) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return;
   }
 
   IDBTransaction* transaction = IDBTransaction::GetCurrent();
-  if (!transaction || transaction != mTransaction || !transaction->IsOpen()) {
+  if (!transaction || transaction != mTransaction ||
+      !transaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return;
   }
 
   auto& metadataArray = const_cast<nsTArray<IndexMetadata>&>(mSpec->indexes());
 
   int64_t foundId = 0;
 
@@ -2215,17 +2217,17 @@ already_AddRefed<IDBRequest> IDBObjectSt
                                                    ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
   if (mDeletedSpec) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   RefPtr<IDBKeyRange> keyRange;
   IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange), aRv);
   if (aRv.Failed()) {
     return nullptr;
@@ -2267,17 +2269,17 @@ already_AddRefed<IDBRequest> IDBObjectSt
   AssertIsOnOwningThread();
   MOZ_ASSERT(aCx);
 
   if (mDeletedSpec) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     return nullptr;
   }
 
-  if (!mTransaction->IsOpen()) {
+  if (!mTransaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   RefPtr<IDBKeyRange> keyRange;
   IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange), aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
@@ -2421,17 +2423,18 @@ void IDBObjectStore::SetName(const nsASt
 
   if (mTransaction->GetMode() != IDBTransaction::Mode::VersionChange ||
       mDeletedSpec) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   IDBTransaction* transaction = IDBTransaction::GetCurrent();
-  if (!transaction || transaction != mTransaction || !transaction->IsOpen()) {
+  if (!transaction || transaction != mTransaction ||
+      !transaction->CanAcceptRequests()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return;
   }
 
   if (aName == mSpec->metadata().name()) {
     return;
   }
 
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -98,17 +98,16 @@ IDBTransaction::IDBTransaction(IDBDataba
       mLoggingSerialNumber(GetIndexedDBThreadLocal()->NextTransactionSN(aMode)),
       mNextObjectStoreId(0),
       mNextIndexId(0),
       mAbortCode(NS_OK),
       mPendingRequestCount(0),
       mFilename(std::move(aFilename)),
       mLineNo(aLineNo),
       mColumn(aColumn),
-      mReadyState(IDBTransaction::ReadyState::Initial),
       mMode(aMode),
       mCreating(false),
       mRegistered(false),
       mAbortedByScript(false),
       mNotedActiveTransaction(false)
 #ifdef DEBUG
       ,
       mSentCommitOrAbort(false),
@@ -222,17 +221,17 @@ already_AddRefed<IDBTransaction> IDBTran
     WorkerPrivate* const workerPrivate = GetCurrentThreadWorkerPrivate();
     MOZ_ASSERT(workerPrivate);
 
     workerPrivate->AssertIsOnWorkerThread();
 
     RefPtr<StrongWorkerRef> workerRef = StrongWorkerRef::Create(
         workerPrivate, "IDBTransaction", [transaction]() {
           transaction->AssertIsOnOwningThread();
-          if (!transaction->IsCommittingOrDone()) {
+          if (!transaction->IsCommittingOrFinished()) {
             IDB_REPORT_INTERNAL_ERR();
             transaction->AbortInternal(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR,
                                        nullptr);
           }
         });
     if (NS_WARN_IF(!workerRef)) {
       // Silence the destructor assertion if we never made this object live.
 #ifdef DEBUG
@@ -335,32 +334,38 @@ void IDBTransaction::RefreshSpec(const b
     objectStore->RefreshSpec(false);
   }
 }
 
 void IDBTransaction::OnNewRequest() {
   AssertIsOnOwningThread();
 
   if (!mPendingRequestCount) {
-    MOZ_ASSERT(ReadyState::Initial == mReadyState);
-    mReadyState = ReadyState::Loading;
+    MOZ_ASSERT(ReadyState::Active == mReadyState);
+    MOZ_ASSERT(!mStarted);
+    mStarted = true;
   }
 
   ++mPendingRequestCount;
 }
 
 void IDBTransaction::OnRequestFinished(
     const bool aRequestCompletedSuccessfully) {
   AssertIsOnOwningThread();
+  MOZ_ASSERT(mReadyState == ReadyState::Active ||
+             mReadyState == ReadyState::Finished);
+  MOZ_ASSERT_IF(mReadyState == ReadyState::Finished, !NS_SUCCEEDED(mAbortCode));
   MOZ_ASSERT(mPendingRequestCount);
 
   --mPendingRequestCount;
 
   if (!mPendingRequestCount) {
-    mReadyState = ReadyState::Committing;
+    if (mReadyState == ReadyState::Active) {
+      mReadyState = ReadyState::Committing;
+    }
 
     if (aRequestCompletedSuccessfully) {
       if (NS_SUCCEEDED(mAbortCode)) {
         SendCommit();
       } else {
         SendAbort(mAbortCode);
       }
     } else {
@@ -375,17 +380,17 @@ void IDBTransaction::OnRequestFinished(
           "IDBTransaction abort", LoggingSerialNumber());
     }
   }
 }
 
 void IDBTransaction::SendCommit() {
   AssertIsOnOwningThread();
   MOZ_ASSERT(NS_SUCCEEDED(mAbortCode));
-  MOZ_ASSERT(IsCommittingOrDone());
+  MOZ_ASSERT(IsCommittingOrFinished());
   MOZ_ASSERT(!mSentCommitOrAbort);
   MOZ_ASSERT(!mPendingRequestCount);
 
   // Don't do this in the macro because we always need to increment the serial
   // number to keep in sync with the parent.
   const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
 
   IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
@@ -397,17 +402,17 @@ void IDBTransaction::SendCommit() {
 #ifdef DEBUG
   mSentCommitOrAbort = true;
 #endif
 }
 
 void IDBTransaction::SendAbort(const nsresult aResultCode) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(NS_FAILED(aResultCode));
-  MOZ_ASSERT(IsCommittingOrDone());
+  MOZ_ASSERT(IsCommittingOrFinished());
   MOZ_ASSERT(!mSentCommitOrAbort);
 
   // Don't do this in the macro because we always need to increment the serial
   // number to keep in sync with the parent.
   const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
 
   IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
       "Aborting transaction with result 0x%x", "IDBTransaction abort (0x%x)",
@@ -433,35 +438,27 @@ void IDBTransaction::MaybeNoteInactiveTr
   AssertIsOnOwningThread();
 
   if (mNotedActiveTransaction) {
     mDatabase->NoteInactiveTransaction();
     mNotedActiveTransaction = false;
   }
 }
 
-bool IDBTransaction::IsOpen() const {
+bool IDBTransaction::CanAcceptRequests() const {
   AssertIsOnOwningThread();
 
-  // If we haven't started anything then we're open.
-  if (mReadyState == IDBTransaction::ReadyState::Initial) {
-    return true;
-  }
-
+  // If we haven't started anything then we can accept requests.
   // If we've already started then we need to check to see if we still have the
   // mCreating flag set. If we do (i.e. we haven't returned to the event loop
-  // from the time we were created) then we are open. Otherwise check the
-  // currently running transaction to see if it's the same. We only allow other
-  // requests to be made if this transaction is currently running.
-  if (mReadyState == IDBTransaction::ReadyState::Loading &&
-      (mCreating || GetCurrent() == this)) {
-    return true;
-  }
-
-  return false;
+  // from the time we were created) then we can accept requests. Otherwise check
+  // the currently running transaction to see if it's the same. We only allow
+  // other requests to be made if this transaction is currently running.
+  return mReadyState == ReadyState::Active &&
+         (!mStarted || mCreating || GetCurrent() == this);
 }
 
 void IDBTransaction::GetCallerLocation(nsAString& aFilename,
                                        uint32_t* const aLineNo,
                                        uint32_t* const aColumn) const {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aLineNo);
   MOZ_ASSERT(aColumn);
@@ -472,17 +469,17 @@ void IDBTransaction::GetCallerLocation(n
 }
 
 already_AddRefed<IDBObjectStore> IDBTransaction::CreateObjectStore(
     const ObjectStoreSpec& aSpec) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aSpec.metadata().id());
   MOZ_ASSERT(Mode::VersionChange == mMode);
   MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
-  MOZ_ASSERT(IsOpen());
+  MOZ_ASSERT(CanAcceptRequests());
 
 #ifdef DEBUG
   {
     // TODO: Bind name outside of lambda capture as a workaround for GCC 7 bug
     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66735.
     const auto& name = aSpec.metadata().name();
     // TODO: Use #ifdef and local variable as a workaround for Bug 1583449.
     const bool objectStoreNameDoesNotYetExist =
@@ -506,17 +503,17 @@ already_AddRefed<IDBObjectStore> IDBTran
   return objectStore.forget();
 }
 
 void IDBTransaction::DeleteObjectStore(const int64_t aObjectStoreId) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aObjectStoreId);
   MOZ_ASSERT(Mode::VersionChange == mMode);
   MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
-  MOZ_ASSERT(IsOpen());
+  MOZ_ASSERT(CanAcceptRequests());
 
   MOZ_ALWAYS_TRUE(
       mBackgroundActor.mVersionChangeBackgroundActor->SendDeleteObjectStore(
           aObjectStoreId));
 
   const auto foundIt =
       std::find_if(mObjectStores.begin(), mObjectStores.end(),
                    [aObjectStoreId](const auto& objectStore) {
@@ -535,94 +532,95 @@ void IDBTransaction::DeleteObjectStore(c
 }
 
 void IDBTransaction::RenameObjectStore(const int64_t aObjectStoreId,
                                        const nsAString& aName) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aObjectStoreId);
   MOZ_ASSERT(Mode::VersionChange == mMode);
   MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
-  MOZ_ASSERT(IsOpen());
+  MOZ_ASSERT(CanAcceptRequests());
 
   MOZ_ALWAYS_TRUE(
       mBackgroundActor.mVersionChangeBackgroundActor->SendRenameObjectStore(
           aObjectStoreId, nsString(aName)));
 }
 
 void IDBTransaction::CreateIndex(IDBObjectStore* const aObjectStore,
                                  const indexedDB::IndexMetadata& aMetadata) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aObjectStore);
   MOZ_ASSERT(aMetadata.id());
   MOZ_ASSERT(Mode::VersionChange == mMode);
   MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
-  MOZ_ASSERT(IsOpen());
+  MOZ_ASSERT(CanAcceptRequests());
 
   MOZ_ALWAYS_TRUE(
       mBackgroundActor.mVersionChangeBackgroundActor->SendCreateIndex(
           aObjectStore->Id(), aMetadata));
 }
 
 void IDBTransaction::DeleteIndex(IDBObjectStore* const aObjectStore,
                                  const int64_t aIndexId) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aObjectStore);
   MOZ_ASSERT(aIndexId);
   MOZ_ASSERT(Mode::VersionChange == mMode);
   MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
-  MOZ_ASSERT(IsOpen());
+  MOZ_ASSERT(CanAcceptRequests());
 
   MOZ_ALWAYS_TRUE(
       mBackgroundActor.mVersionChangeBackgroundActor->SendDeleteIndex(
           aObjectStore->Id(), aIndexId));
 }
 
 void IDBTransaction::RenameIndex(IDBObjectStore* const aObjectStore,
                                  const int64_t aIndexId,
                                  const nsAString& aName) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aObjectStore);
   MOZ_ASSERT(aIndexId);
   MOZ_ASSERT(Mode::VersionChange == mMode);
   MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
-  MOZ_ASSERT(IsOpen());
+  MOZ_ASSERT(CanAcceptRequests());
 
   MOZ_ALWAYS_TRUE(
       mBackgroundActor.mVersionChangeBackgroundActor->SendRenameIndex(
           aObjectStore->Id(), aIndexId, nsString(aName)));
 }
 
 void IDBTransaction::AbortInternal(const nsresult aAbortCode,
                                    already_AddRefed<DOMException> aError) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(NS_FAILED(aAbortCode));
-  MOZ_ASSERT(!IsCommittingOrDone());
+  MOZ_ASSERT(!IsCommittingOrFinished());
 
   RefPtr<DOMException> error = aError;
 
   const bool isVersionChange = mMode == Mode::VersionChange;
-  const bool needToSendAbort = mReadyState == ReadyState::Initial;
+  const bool needToSendAbort = mReadyState == ReadyState::Active && !mStarted;
 
   mAbortCode = aAbortCode;
-  mReadyState = ReadyState::Done;
+  mReadyState = ReadyState::Finished;
   mError = error.forget();
 
   if (isVersionChange) {
     // If a version change transaction is aborted, we must revert the world
     // back to its previous state unless we're being invalidated after the
     // transaction already completed.
     if (!mDatabase->IsInvalidated()) {
       mDatabase->RevertToPreviousState();
     }
 
     // We do the reversion only for the mObjectStores/mDeletedObjectStores but
     // not for the mIndexes/mDeletedIndexes of each IDBObjectStore because it's
     // time-consuming(O(m*n)) and mIndexes/mDeletedIndexes won't be used anymore
     // in IDBObjectStore::(Create|Delete)Index() and IDBObjectStore::Index() in
-    // which all the executions are returned earlier by !transaction->IsOpen().
+    // which all the executions are returned earlier by
+    // !transaction->CanAcceptRequests().
 
     const nsTArray<ObjectStoreSpec>& specArray =
         mDatabase->Spec()->objectStores();
 
     if (specArray.IsEmpty()) {
       // This case is specially handled as a performance optimization, it is
       // equivalent to the else block.
       mObjectStores.Clear();
@@ -664,60 +662,60 @@ void IDBTransaction::AbortInternal(const
     mDatabase->Close();
   }
 }
 
 void IDBTransaction::Abort(IDBRequest* const aRequest) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aRequest);
 
-  if (IsCommittingOrDone()) {
+  if (IsCommittingOrFinished()) {
     // Already started (and maybe finished) the commit or abort so there is
     // nothing to do here.
     return;
   }
 
   ErrorResult rv;
   RefPtr<DOMException> error = aRequest->GetError(rv);
 
   AbortInternal(aRequest->GetErrorCode(), error.forget());
 }
 
 void IDBTransaction::Abort(const nsresult aErrorCode) {
   AssertIsOnOwningThread();
 
-  if (IsCommittingOrDone()) {
+  if (IsCommittingOrFinished()) {
     // Already started (and maybe finished) the commit or abort so there is
     // nothing to do here.
     return;
   }
 
   RefPtr<DOMException> error = DOMException::Create(aErrorCode);
   AbortInternal(aErrorCode, error.forget());
 }
 
 void IDBTransaction::Abort(ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
-  if (IsCommittingOrDone()) {
+  if (IsCommittingOrFinished()) {
     aRv = NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
     return;
   }
 
   AbortInternal(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR, nullptr);
 
   MOZ_ASSERT(!mAbortedByScript);
   mAbortedByScript = true;
 }
 
 void IDBTransaction::FireCompleteOrAbortEvents(const nsresult aResult) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(!mFiredCompleteOrAbort);
 
-  mReadyState = ReadyState::Done;
+  mReadyState = ReadyState::Finished;
 
 #ifdef DEBUG
   mFiredCompleteOrAbort = true;
 #endif
 
   // Make sure we drop the WorkerRef when this function completes.
   const auto scopeExit = MakeScopeExit([&] { mWorkerRef = nullptr; });
 
@@ -858,17 +856,17 @@ already_AddRefed<DOMStringList> IDBTrans
   list->StringArray() = mObjectStoreNames;
   return list.forget();
 }
 
 already_AddRefed<IDBObjectStore> IDBTransaction::ObjectStore(
     const nsAString& aName, ErrorResult& aRv) {
   AssertIsOnOwningThread();
 
-  if (IsCommittingOrDone()) {
+  if (IsCommittingOrFinished()) {
     aRv.ThrowDOMException(
         NS_ERROR_DOM_INVALID_STATE_ERR,
         NS_LITERAL_CSTRING("Transaction is already committing or done."));
     return nullptr;
   }
 
   const ObjectStoreSpec* spec = nullptr;
 
@@ -953,18 +951,18 @@ void IDBTransaction::GetEventTargetParen
 NS_IMETHODIMP
 IDBTransaction::Run() {
   AssertIsOnOwningThread();
 
   // We're back at the event loop, no longer newborn.
   mCreating = false;
 
   // Maybe commit if there were no requests generated.
-  if (mReadyState == IDBTransaction::ReadyState::Initial) {
-    mReadyState = ReadyState::Done;
+  if (mReadyState == ReadyState::Active && !mStarted) {
+    mReadyState = ReadyState::Finished;
 
     SendCommit();
   }
 
   return NS_OK;
 }
 
 }  // namespace dom
--- a/dom/indexedDB/IDBTransaction.h
+++ b/dom/indexedDB/IDBTransaction.h
@@ -54,17 +54,17 @@ class IDBTransaction final : public DOME
     ReadWriteFlush,
     Cleanup,
     VersionChange,
 
     // Only needed for IPC serialization helper, should never be used in code.
     Invalid
   };
 
-  enum struct ReadyState { Initial = 0, Loading, Inactive, Committing, Done };
+  enum struct ReadyState { Active, Inactive, Committing, Finished };
 
  private:
   // TODO: Only non-const because of Bug 1575173.
   RefPtr<IDBDatabase> mDatabase;
   RefPtr<DOMException> mError;
   const nsTArray<nsString> mObjectStoreNames;
   nsTArray<RefPtr<IDBObjectStore>> mObjectStores;
   nsTArray<RefPtr<IDBObjectStore>> mDeletedObjectStores;
@@ -96,17 +96,18 @@ class IDBTransaction final : public DOME
                                   ///< OnRequestFinished, so that the
                                   ///< transaction can auto-commit when the last
                                   ///< pending request finished.
 
   const nsString mFilename;
   const uint32_t mLineNo;
   const uint32_t mColumn;
 
-  ReadyState mReadyState;
+  ReadyState mReadyState = ReadyState::Active;
+  bool mStarted = false;
   const Mode mMode;
 
   bool mCreating;    ///< Set between successful creation until the transaction
                      ///< has run on the event-loop.
   bool mRegistered;  ///< Whether mDatabase->RegisterTransaction() has been
                      ///< called (which may not be the case if construction was
                      ///< incomplete).
   bool mAbortedByScript;
@@ -158,66 +159,63 @@ class IDBTransaction final : public DOME
   indexedDB::BackgroundRequestChild* StartRequest(
       IDBRequest* aRequest, const indexedDB::RequestParams& aParams);
 
   void OpenCursor(indexedDB::BackgroundCursorChild* aBackgroundActor,
                   const indexedDB::OpenCursorParams& aParams);
 
   void RefreshSpec(bool aMayDelete);
 
-  bool IsOpen() const;
+  bool CanAcceptRequests() const;
 
-  bool IsCommittingOrDone() const {
+  bool IsCommittingOrFinished() const {
     AssertIsOnOwningThread();
 
     return mReadyState == ReadyState::Committing ||
-           mReadyState == ReadyState::Done;
+           mReadyState == ReadyState::Finished;
   }
 
-  bool IsDone() const {
+  bool IsFinished() const {
     AssertIsOnOwningThread();
 
-    return mReadyState == ReadyState::Done;
+    return mReadyState == ReadyState::Finished;
   }
 
   bool IsWriteAllowed() const {
     AssertIsOnOwningThread();
     return mMode == Mode::ReadWrite || mMode == Mode::ReadWriteFlush ||
            mMode == Mode::Cleanup || mMode == Mode::VersionChange;
   }
 
   bool IsAborted() const {
     AssertIsOnOwningThread();
     return NS_FAILED(mAbortCode);
   }
 
   auto TemporarilyProceedToInactive() {
     AssertIsOnOwningThread();
-    MOZ_ASSERT(mReadyState == ReadyState::Initial ||
-               mReadyState == ReadyState::Loading);
-    const auto savedReadyState = mReadyState;
+    MOZ_ASSERT(mReadyState == ReadyState::Active);
     mReadyState = ReadyState::Inactive;
 
     struct AutoRestoreState {
       IDBTransaction& mOwner;
-      ReadyState mSavedReadyState;
 #ifdef DEBUG
       uint32_t mSavedPendingRequestCount;
 #endif
 
       ~AutoRestoreState() {
         mOwner.AssertIsOnOwningThread();
         MOZ_ASSERT(mOwner.mReadyState == ReadyState::Inactive);
         MOZ_ASSERT(mOwner.mPendingRequestCount == mSavedPendingRequestCount);
 
-        mOwner.mReadyState = mSavedReadyState;
+        mOwner.mReadyState = ReadyState::Active;
       }
     };
 
-    return AutoRestoreState{*this, savedReadyState
+    return AutoRestoreState{*this
 #ifdef DEBUG
                             ,
                             mPendingRequestCount
 #endif
     };
   }
 
   nsresult AbortCode() const {