Bug 1632128 - Dissolve ResultHelper class into a function. r=dom-workers-and-storage-reviewers,janv
authorSimon Giesecke <sgiesecke@mozilla.com>
Thu, 14 May 2020 09:42:23 +0000
changeset 593598 1e9b275f2afa33c9db1b643839157bba31dab7c1
parent 593597 4c55bf108c9b69828419e969612bfe2356c34830
child 593599 7c0d5a5a3f2a466981091cbe4f8acb50a9617be0
push id13186
push userffxbld-merge
push dateMon, 01 Jun 2020 09:52:46 +0000
treeherdermozilla-beta@3e7c70a1e4a1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdom-workers-and-storage-reviewers, janv
bugs1632128
milestone78.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 1632128 - Dissolve ResultHelper class into a function. r=dom-workers-and-storage-reviewers,janv Differential Revision: https://phabricator.services.mozilla.com/D74890
dom/indexedDB/ActorsChild.cpp
dom/indexedDB/IDBResult.h
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -189,190 +189,163 @@ class MOZ_STACK_CLASS AutoSetCurrentTran
 
     if (mThreadLocal) {
       // Reset old value.
       mThreadLocal->SetCurrentTransaction(mPreviousTransaction);
     }
   }
 };
 
-class MOZ_STACK_CLASS ResultHelper final {
-  const RefPtr<IDBRequest> mRequest;
-  const AutoSetCurrentTransaction mAutoTransaction;
-  const SafeRefPtr<IDBTransaction> mTransaction;
-
-  mozilla::Variant<
-      IDBDatabase*, IDBCursor*, IDBMutableFile*, StructuredCloneReadInfoChild*,
-      nsTArray<StructuredCloneReadInfoChild>*, const Key*, const nsTArray<Key>*,
-      const uint64_t*, const JS::Handle<JS::Value>*>
-      mResult;
-
- public:
-  template <typename T>
-  ResultHelper(IDBRequest* aRequest, SafeRefPtr<IDBTransaction> aTransaction,
-               T* aResult)
-      : mRequest(aRequest),
-        mAutoTransaction(aTransaction ? SomeRef(*aTransaction) : Nothing()),
-        mTransaction(std::move(aTransaction)),
-        mResult(aResult) {
-    MOZ_ASSERT(aRequest);
-    MOZ_ASSERT(aResult);
+template <typename T>
+void SetResultAndDispatchSuccessEvent(
+    const RefPtr<IDBRequest>& aRequest,
+    const SafeRefPtr<IDBTransaction>& aTransaction, T* aPtr,
+    RefPtr<Event> aEvent = nullptr);
+
+namespace detail {
+void DispatchSuccessEvent(const RefPtr<IDBRequest>& aRequest,
+                          const SafeRefPtr<IDBTransaction>& aTransaction,
+                          const RefPtr<Event>& aEvent);
+
+template <class T>
+std::enable_if_t<std::is_same_v<T, IDBDatabase> ||
+                     std::is_same_v<T, IDBCursor> ||
+                     std::is_same_v<T, IDBMutableFile>,
+                 nsresult>
+GetResult(JSContext* aCx, T* aDOMObject, JS::MutableHandle<JS::Value> aResult) {
+  if (!aDOMObject) {
+    aResult.setNull();
+    return NS_OK;
+  }
+
+  const bool ok = GetOrCreateDOMReflector(aCx, aDOMObject, aResult);
+  if (NS_WARN_IF(!ok)) {
+    IDB_REPORT_INTERNAL_ERR();
+    return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
-  nsresult operator()(JSContext* aCx,
-                      JS::MutableHandle<JS::Value> aResult) const {
-    MOZ_ASSERT(aCx);
-    MOZ_ASSERT(mRequest);
-
-    return mResult.match(
-        [aCx, aResult](auto* aPtr) { return GetResult(aCx, aPtr, aResult); });
+  return NS_OK;
+}
+
+nsresult GetResult(JSContext* aCx, const JS::Handle<JS::Value>* aValue,
+                   JS::MutableHandle<JS::Value> aResult) {
+  aResult.set(*aValue);
+  return NS_OK;
+}
+
+nsresult GetResult(JSContext* aCx, const uint64_t* aValue,
+                   JS::MutableHandle<JS::Value> aResult) {
+  aResult.set(JS::NumberValue(*aValue));
+  return NS_OK;
+}
+
+nsresult GetResult(JSContext* aCx, StructuredCloneReadInfoChild&& aCloneInfo,
+                   JS::MutableHandle<JS::Value> aResult) {
+  const bool ok =
+      IDBObjectStore::DeserializeValue(aCx, std::move(aCloneInfo), aResult);
+
+  if (NS_WARN_IF(!ok)) {
+    return NS_ERROR_DOM_DATA_CLONE_ERR;
   }
 
-  void DispatchSuccessEvent(RefPtr<Event> aEvent = nullptr);
-
- private:
-  template <class T>
-  static std::enable_if_t<std::is_same_v<T, IDBDatabase> ||
-                              std::is_same_v<T, IDBCursor> ||
-                              std::is_same_v<T, IDBMutableFile>,
-                          nsresult>
-  GetResult(JSContext* aCx, T* aDOMObject,
-            JS::MutableHandle<JS::Value> aResult) {
-    if (!aDOMObject) {
-      aResult.setNull();
-      return NS_OK;
-    }
-
-    const bool ok = GetOrCreateDOMReflector(aCx, aDOMObject, aResult);
-    if (NS_WARN_IF(!ok)) {
+  return NS_OK;
+}
+
+nsresult GetResult(JSContext* aCx, StructuredCloneReadInfoChild* aCloneInfo,
+                   JS::MutableHandle<JS::Value> aResult) {
+  return GetResult(aCx, std::move(*aCloneInfo), aResult);
+}
+
+nsresult GetResult(JSContext* aCx,
+                   nsTArray<StructuredCloneReadInfoChild>* aCloneInfos,
+                   JS::MutableHandle<JS::Value> aResult) {
+  JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, 0));
+  if (NS_WARN_IF(!array)) {
+    IDB_REPORT_INTERNAL_ERR();
+    return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
+  }
+
+  if (!aCloneInfos->IsEmpty()) {
+    const uint32_t count = aCloneInfos->Length();
+
+    if (NS_WARN_IF(!JS::SetArrayLength(aCx, array, count))) {
       IDB_REPORT_INTERNAL_ERR();
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
-    return NS_OK;
-  }
-
-  static nsresult GetResult(JSContext* aCx, const JS::Handle<JS::Value>* aValue,
-                            JS::MutableHandle<JS::Value> aResult) {
-    aResult.set(*aValue);
-    return NS_OK;
-  }
-
-  static nsresult GetResult(JSContext* aCx, const uint64_t* aValue,
-                            JS::MutableHandle<JS::Value> aResult) {
-    aResult.set(JS::NumberValue(*aValue));
-    return NS_OK;
-  }
-
-  static nsresult GetResult(JSContext* aCx,
-                            StructuredCloneReadInfoChild* aCloneInfo,
-                            JS::MutableHandle<JS::Value> aResult) {
-    return GetResult(aCx, std::move(*aCloneInfo), aResult);
-  }
-
-  static nsresult GetResult(JSContext* aCx,
-                            StructuredCloneReadInfoChild&& aCloneInfo,
-                            JS::MutableHandle<JS::Value> aResult) {
-    const bool ok =
-        IDBObjectStore::DeserializeValue(aCx, std::move(aCloneInfo), aResult);
-
-    if (NS_WARN_IF(!ok)) {
-      return NS_ERROR_DOM_DATA_CLONE_ERR;
-    }
-
-    return NS_OK;
-  }
-
-  static nsresult GetResult(JSContext* aCx,
-                            nsTArray<StructuredCloneReadInfoChild>* aCloneInfos,
-                            JS::MutableHandle<JS::Value> aResult) {
-    JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, 0));
-    if (NS_WARN_IF(!array)) {
-      IDB_REPORT_INTERNAL_ERR();
-      return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
-    }
-
-    if (!aCloneInfos->IsEmpty()) {
-      const uint32_t count = aCloneInfos->Length();
-
-      if (NS_WARN_IF(!JS::SetArrayLength(aCx, array, count))) {
+    for (uint32_t index = 0; index < count; index++) {
+      auto& cloneInfo = aCloneInfos->ElementAt(index);
+
+      JS::Rooted<JS::Value> value(aCx);
+
+      const nsresult rv = GetResult(aCx, std::move(cloneInfo), &value);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+
+      if (NS_WARN_IF(
+              !JS_DefineElement(aCx, array, index, value, JSPROP_ENUMERATE))) {
         IDB_REPORT_INTERNAL_ERR();
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
-
-      for (uint32_t index = 0; index < count; index++) {
-        auto& cloneInfo = aCloneInfos->ElementAt(index);
-
-        JS::Rooted<JS::Value> value(aCx);
-
-        const nsresult rv = GetResult(aCx, std::move(cloneInfo), &value);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return rv;
-        }
-
-        if (NS_WARN_IF(!JS_DefineElement(aCx, array, index, value,
-                                         JSPROP_ENUMERATE))) {
-          IDB_REPORT_INTERNAL_ERR();
-          return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
-        }
-      }
     }
-
-    aResult.setObject(*array);
-    return NS_OK;
+  }
+
+  aResult.setObject(*array);
+  return NS_OK;
+}
+
+nsresult GetResult(JSContext* aCx, const Key* aKey,
+                   JS::MutableHandle<JS::Value> aResult) {
+  const nsresult rv = aKey->ToJSVal(aCx, aResult);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
   }
-
-  static nsresult GetResult(JSContext* aCx, const Key* aKey,
-                            JS::MutableHandle<JS::Value> aResult) {
-    const nsresult rv = aKey->ToJSVal(aCx, aResult);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    return NS_OK;
+  return NS_OK;
+}
+
+nsresult GetResult(JSContext* aCx, const nsTArray<Key>* aKeys,
+                   JS::MutableHandle<JS::Value> aResult) {
+  JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, 0));
+  if (NS_WARN_IF(!array)) {
+    IDB_REPORT_INTERNAL_ERR();
+    return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
-  static nsresult GetResult(JSContext* aCx, const nsTArray<Key>* aKeys,
-                            JS::MutableHandle<JS::Value> aResult) {
-    JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, 0));
-    if (NS_WARN_IF(!array)) {
+  if (!aKeys->IsEmpty()) {
+    const uint32_t count = aKeys->Length();
+
+    if (NS_WARN_IF(!JS::SetArrayLength(aCx, array, count))) {
       IDB_REPORT_INTERNAL_ERR();
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
-    if (!aKeys->IsEmpty()) {
-      const uint32_t count = aKeys->Length();
-
-      if (NS_WARN_IF(!JS::SetArrayLength(aCx, array, count))) {
+    for (uint32_t index = 0; index < count; index++) {
+      const Key& key = aKeys->ElementAt(index);
+      MOZ_ASSERT(!key.IsUnset());
+
+      JS::Rooted<JS::Value> value(aCx);
+
+      const nsresult rv = GetResult(aCx, &key, &value);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+
+      if (NS_WARN_IF(
+              !JS_DefineElement(aCx, array, index, value, JSPROP_ENUMERATE))) {
         IDB_REPORT_INTERNAL_ERR();
         return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
-
-      for (uint32_t index = 0; index < count; index++) {
-        const Key& key = aKeys->ElementAt(index);
-        MOZ_ASSERT(!key.IsUnset());
-
-        JS::Rooted<JS::Value> value(aCx);
-
-        const nsresult rv = GetResult(aCx, &key, &value);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return rv;
-        }
-
-        if (NS_WARN_IF(!JS_DefineElement(aCx, array, index, value,
-                                         JSPROP_ENUMERATE))) {
-          IDB_REPORT_INTERNAL_ERR();
-          return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
-        }
-      }
     }
-
-    aResult.setObject(*array);
-    return NS_OK;
   }
-};
+
+  aResult.setObject(*array);
+  return NS_OK;
+}
+}  // namespace detail
 
 class PermissionRequestMainProcessHelper final : public PermissionRequestBase {
   BackgroundFactoryRequestChild* mActor;
   SafeRefPtr<IDBFactory> mFactory;
 
  public:
   PermissionRequestMainProcessHelper(BackgroundFactoryRequestChild* aActor,
                                      SafeRefPtr<IDBFactory> aFactory,
@@ -540,17 +513,17 @@ void DispatchErrorEvent(
   if (!aEvent) {
     // Make an error event and fire it at the target.
     aEvent = CreateGenericEvent(request, nsDependentString(kErrorEventType),
                                 eDoesBubble, eCancelable);
   }
   MOZ_ASSERT(aEvent);
 
   // XXX This is redundant if we are called from
-  // ResultHelper::DispatchSuccessEvent.
+  // DispatchSuccessEvent.
   Maybe<AutoSetCurrentTransaction> asct;
   if (aTransaction) {
     asct.emplace(SomeRef(*aTransaction));
   }
 
   if (aTransaction && aTransaction->IsInactive()) {
     aTransaction->TransitionToActive();
   }
@@ -593,73 +566,94 @@ void DispatchErrorEvent(
         aTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
       } else if (doDefault) {
         aTransaction->Abort(request);
       }
     }
   }
 }
 
-void ResultHelper::DispatchSuccessEvent(RefPtr<Event> aEvent) {
-  AUTO_PROFILER_LABEL("IndexedDB:DispatchSuccessEvent", DOM);
-
-  MOZ_ASSERT(mRequest);
-  mRequest->AssertIsOnOwningThread();
-
-  if (mTransaction && mTransaction->IsAborted()) {
-    DispatchErrorEvent(mRequest, mTransaction->AbortCode(), mTransaction);
+template <typename T>
+void SetResultAndDispatchSuccessEvent(
+    const RefPtr<IDBRequest>& aRequest,
+    const SafeRefPtr<IDBTransaction>& aTransaction, T* aPtr,
+    RefPtr<Event> aEvent) {
+  MOZ_ASSERT(aRequest);
+  MOZ_ASSERT(aPtr);
+
+  const auto autoTransaction = AutoSetCurrentTransaction{
+      aTransaction ? SomeRef(*aTransaction) : Nothing()};
+
+  AUTO_PROFILER_LABEL("IndexedDB:SetResultAndDispatchSuccessEvent", DOM);
+
+  aRequest->AssertIsOnOwningThread();
+
+  if (aTransaction && aTransaction->IsAborted()) {
+    DispatchErrorEvent(aRequest, aTransaction->AbortCode(), aTransaction);
     return;
   }
 
   if (!aEvent) {
-    aEvent = CreateGenericEvent(mRequest, nsDependentString(kSuccessEventType),
+    aEvent = CreateGenericEvent(aRequest, nsDependentString(kSuccessEventType),
                                 eDoesNotBubble, eNotCancelable);
   }
   MOZ_ASSERT(aEvent);
 
-  mRequest->SetResult(*this);
-
-  if (mTransaction && mTransaction->IsInactive()) {
-    mTransaction->TransitionToActive();
+  aRequest->SetResult(
+      [aPtr](JSContext* aCx, JS::MutableHandle<JS::Value> aResult) {
+        MOZ_ASSERT(aCx);
+        return detail::GetResult(aCx, aPtr, aResult);
+      });
+
+  detail::DispatchSuccessEvent(aRequest, aTransaction, aEvent);
+}
+
+namespace detail {
+void DispatchSuccessEvent(const RefPtr<IDBRequest>& aRequest,
+                          const SafeRefPtr<IDBTransaction>& aTransaction,
+                          const RefPtr<Event>& aEvent) {
+  if (aTransaction && aTransaction->IsInactive()) {
+    aTransaction->TransitionToActive();
   }
 
-  if (mTransaction) {
+  if (aTransaction) {
     IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
-        "Firing %s event", "%s", mTransaction->LoggingSerialNumber(),
-        mRequest->LoggingSerialNumber(),
+        "Firing %s event", "%s", aTransaction->LoggingSerialNumber(),
+        aRequest->LoggingSerialNumber(),
         IDB_LOG_STRINGIFY(aEvent, kSuccessEventType));
   } else {
     IDB_LOG_MARK_CHILD_REQUEST("Firing %s event", "%s",
-                               mRequest->LoggingSerialNumber(),
+                               aRequest->LoggingSerialNumber(),
                                IDB_LOG_STRINGIFY(aEvent, kSuccessEventType));
   }
 
-  MOZ_ASSERT_IF(mTransaction && !mTransaction->WasExplicitlyCommitted(),
-                mTransaction->IsActive() && !mTransaction->IsAborted());
+  MOZ_ASSERT_IF(aTransaction && !aTransaction->WasExplicitlyCommitted(),
+                aTransaction->IsActive() && !aTransaction->IsAborted());
 
   IgnoredErrorResult rv;
-  mRequest->DispatchEvent(*aEvent, rv);
+  aRequest->DispatchEvent(*aEvent, rv);
   if (NS_WARN_IF(rv.Failed())) {
     return;
   }
 
   WidgetEvent* const internalEvent = aEvent->WidgetEventPtr();
   MOZ_ASSERT(internalEvent);
 
-  if (mTransaction && mTransaction->IsActive()) {
-    mTransaction->TransitionToInactive();
+  if (aTransaction && aTransaction->IsActive()) {
+    aTransaction->TransitionToInactive();
 
     if (internalEvent->mFlags.mExceptionWasRaised) {
-      mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
+      aTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
     } else {
       // To handle upgrade transaction.
-      mTransaction->CommitIfNotStarted();
+      aTransaction->CommitIfNotStarted();
     }
   }
 }
+}  // namespace detail
 
 PRFileDesc* GetFileDescriptorFromStream(nsIInputStream* aStream) {
   MOZ_ASSERT(aStream);
 
   const nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(aStream);
   if (NS_WARN_IF(!fileMetadata)) {
     return nullptr;
   }
@@ -1413,39 +1407,36 @@ bool BackgroundFactoryRequestChild::Hand
   MOZ_ASSERT(mDatabaseActor == databaseActor);
 
   if (database->IsClosed()) {
     // If the database was closed already, which is only possible if we fired an
     // "upgradeneeded" event, then we shouldn't fire a "success" event here.
     // Instead we fire an error event with AbortErr.
     DispatchErrorEvent(mRequest, NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
   } else {
-    ResultHelper helper(mRequest, nullptr, database);
-
-    helper.DispatchSuccessEvent();
+    SetResultAndDispatchSuccessEvent(mRequest, nullptr, database);
   }
 
   databaseActor->ReleaseDOMObject();
   MOZ_ASSERT(!mDatabaseActor);
 
   return true;
 }
 
 bool BackgroundFactoryRequestChild::HandleResponse(
     const DeleteDatabaseRequestResponse& aResponse) {
   AssertIsOnOwningThread();
 
-  ResultHelper helper(mRequest, nullptr, &JS::UndefinedHandleValue);
-
   RefPtr<Event> successEvent = IDBVersionChangeEvent::Create(
       mRequest, nsDependentString(kSuccessEventType),
       aResponse.previousVersion());
   MOZ_ASSERT(successEvent);
 
-  helper.DispatchSuccessEvent(std::move(successEvent));
+  SetResultAndDispatchSuccessEvent(mRequest, nullptr, &JS::UndefinedHandleValue,
+                                   std::move(successEvent));
 
   MOZ_ASSERT(!mDatabaseActor);
 
   return true;
 }
 
 void BackgroundFactoryRequestChild::ActorDestroy(ActorDestroyReason aWhy) {
   AssertIsOnOwningThread();
@@ -1784,19 +1775,18 @@ BackgroundDatabaseChild::RecvPBackground
 
   request->SetTransaction(transaction.clonePtr());
 
   RefPtr<Event> upgradeNeededEvent = IDBVersionChangeEvent::Create(
       request, nsDependentString(kUpgradeNeededEventType), aCurrentVersion,
       aRequestedVersion);
   MOZ_ASSERT(upgradeNeededEvent);
 
-  ResultHelper helper(request, std::move(transaction), mDatabase);
-
-  helper.DispatchSuccessEvent(std::move(upgradeNeededEvent));
+  SetResultAndDispatchSuccessEvent(request, transaction, mDatabase,
+                                   std::move(upgradeNeededEvent));
 
   return IPC_OK();
 }
 
 PBackgroundMutableFileChild*
 BackgroundDatabaseChild::AllocPBackgroundMutableFileChild(
     const nsString& aName, const nsString& aType) {
   AssertIsOnOwningThread();
@@ -1945,19 +1935,17 @@ bool BackgroundDatabaseRequestChild::Han
   MOZ_ASSERT(mutableFileActor);
 
   mutableFileActor->EnsureDOMObject();
 
   auto mutableFile =
       static_cast<IDBMutableFile*>(mutableFileActor->GetDOMObject());
   MOZ_ASSERT(mutableFile);
 
-  ResultHelper helper(mRequest, nullptr, mutableFile);
-
-  helper.DispatchSuccessEvent();
+  SetResultAndDispatchSuccessEvent(mRequest, nullptr, mutableFile);
 
   mutableFileActor->ReleaseDOMObject();
 
   return true;
 }
 
 mozilla::ipc::IPCResult BackgroundDatabaseRequestChild::Recv__delete__(
     const DatabaseRequestResponse& aResponse) {
@@ -2432,40 +2420,35 @@ void BackgroundRequestChild::HandleRespo
   MOZ_ASSERT(mTransaction);
 
   DispatchErrorEvent(mRequest, aResponse, mTransaction.clonePtr());
 }
 
 void BackgroundRequestChild::HandleResponse(const Key& aResponse) {
   AssertIsOnOwningThread();
 
-  ResultHelper helper(mRequest, AcquireTransaction(), &aResponse);
-
-  helper.DispatchSuccessEvent();
+  SetResultAndDispatchSuccessEvent(mRequest, AcquireTransaction(), &aResponse);
 }
 
 void BackgroundRequestChild::HandleResponse(const nsTArray<Key>& aResponse) {
   AssertIsOnOwningThread();
 
-  ResultHelper helper(mRequest, AcquireTransaction(), &aResponse);
-
-  helper.DispatchSuccessEvent();
+  SetResultAndDispatchSuccessEvent(mRequest, AcquireTransaction(), &aResponse);
 }
 
 void BackgroundRequestChild::HandleResponse(
     SerializedStructuredCloneReadInfo&& aResponse) {
   AssertIsOnOwningThread();
 
   auto cloneReadInfo = DeserializeStructuredCloneReadInfo(
       std::move(aResponse), mTransaction->Database(),
       [this] { return std::move(*GetNextCloneData()); });
 
-  ResultHelper helper(mRequest, AcquireTransaction(), &cloneReadInfo);
-
-  helper.DispatchSuccessEvent();
+  SetResultAndDispatchSuccessEvent(mRequest, AcquireTransaction(),
+                                   &cloneReadInfo);
 }
 
 void BackgroundRequestChild::HandleResponse(
     nsTArray<SerializedStructuredCloneReadInfo>&& aResponse) {
   AssertIsOnOwningThread();
 
   nsTArray<StructuredCloneReadInfoChild> cloneReadInfos;
 
@@ -2481,36 +2464,32 @@ void BackgroundRequestChild::HandleRespo
         [database = mTransaction->Database(),
          this](SerializedStructuredCloneReadInfo&& serializedCloneInfo) {
           return DeserializeStructuredCloneReadInfo(
               std::move(serializedCloneInfo), database,
               [this] { return std::move(*GetNextCloneData()); });
         });
   }
 
-  ResultHelper helper(mRequest, AcquireTransaction(), &cloneReadInfos);
-
-  helper.DispatchSuccessEvent();
+  SetResultAndDispatchSuccessEvent(mRequest, AcquireTransaction(),
+                                   &cloneReadInfos);
 }
 
 void BackgroundRequestChild::HandleResponse(JS::Handle<JS::Value> aResponse) {
   AssertIsOnOwningThread();
 
-  ResultHelper helper(mRequest, AcquireTransaction(),
-                      const_cast<const JS::Handle<JS::Value>*>(&aResponse));
-
-  helper.DispatchSuccessEvent();
+  SetResultAndDispatchSuccessEvent(
+      mRequest, AcquireTransaction(),
+      const_cast<const JS::Handle<JS::Value>*>(&aResponse));
 }
 
 void BackgroundRequestChild::HandleResponse(const uint64_t aResponse) {
   AssertIsOnOwningThread();
 
-  ResultHelper helper(mRequest, AcquireTransaction(), &aResponse);
-
-  helper.DispatchSuccessEvent();
+  SetResultAndDispatchSuccessEvent(mRequest, AcquireTransaction(), &aResponse);
 }
 
 nsresult BackgroundRequestChild::HandlePreprocess(
     const PreprocessInfo& aPreprocessInfo) {
   return HandlePreprocessInternal(
       AutoTArray<PreprocessInfo, 1>{aPreprocessInfo});
 }
 
@@ -3179,22 +3158,22 @@ void BackgroundCursorChild<CursorType>::
   mDelayedResponses.pop_front();
 
   IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
       "PRELOAD: Consumed 1 cached response, %zu cached responses remaining",
       "Consumed cached response", mTransaction->LoggingSerialNumber(),
       GetRequest()->LoggingSerialNumber(),
       mDelayedResponses.size() + mCachedResponses.size());
 
-  ResultHelper helper(GetRequest(),
-                      mTransaction ? SafeRefPtr{&mTransaction.ref(),
-                                                AcquireStrongRefFromRawPtr{}}
-                                   : nullptr,
-                      cursor.get());
-  helper.DispatchSuccessEvent();
+  SetResultAndDispatchSuccessEvent(
+      GetRequest(),
+      mTransaction
+          ? SafeRefPtr{&mTransaction.ref(), AcquireStrongRefFromRawPtr{}}
+          : nullptr,
+      cursor.get());
 
   mTransaction->OnRequestFinished(/* aRequestCompletedSuccessfully */ true);
 }
 
 template <IDBCursorType CursorType>
 void BackgroundCursorChild<CursorType>::SendDeleteMeInternal() {
   AssertIsOnOwningThread();
   MOZ_ASSERT(!mStrongRequest);
@@ -3287,22 +3266,22 @@ void BackgroundCursorChild<CursorType>::
   MOZ_ASSERT(mTransaction);
   MOZ_ASSERT(!mStrongRequest);
   MOZ_ASSERT(!mStrongCursor);
 
   if (mCursor) {
     mCursor->Reset();
   }
 
-  ResultHelper helper(GetRequest(),
-                      mTransaction ? SafeRefPtr{&mTransaction.ref(),
-                                                AcquireStrongRefFromRawPtr{}}
-                                   : nullptr,
-                      &JS::NullHandleValue);
-  helper.DispatchSuccessEvent();
+  SetResultAndDispatchSuccessEvent(
+      GetRequest(),
+      mTransaction
+          ? SafeRefPtr{&mTransaction.ref(), AcquireStrongRefFromRawPtr{}}
+          : nullptr,
+      &JS::NullHandleValue);
 
   if (!mCursor) {
     MOZ_ALWAYS_SUCCEEDS(this->GetActorEventTarget()->Dispatch(
         MakeAndAddRef<DelayedActionRunnable<BackgroundCursorChild<CursorType>>>(
             this, &BackgroundCursorChild::SendDeleteMeInternal),
         NS_DISPATCH_NORMAL));
   }
 }
@@ -3343,17 +3322,17 @@ void BackgroundCursorChild<CursorType>::
 
   IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
       "PRELOAD: Received %zu cursor responses", "Received",
       mTransaction->LoggingSerialNumber(), GetRequest()->LoggingSerialNumber(),
       aResponses.Length());
   MOZ_ASSERT_IF(aResponses.Length() > 1, mCachedResponses.empty());
 
   // If a new cursor is created, we need to keep a reference to it until the
-  // ResultHelper creates a DOM Binding.
+  // SetResultAndDispatchSuccessEvent creates a DOM Binding.
   RefPtr<IDBCursor> strongNewCursor;
 
   bool isFirst = true;
   for (auto& response : aResponses) {
     IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
         "PRELOAD: Processing response for key %s", "Processing",
         mTransaction->LoggingSerialNumber(),
         GetRequest()->LoggingSerialNumber(), response.key().GetBuffer().get());
@@ -3378,22 +3357,22 @@ void BackgroundCursorChild<CursorType>::
           "Discarding responses", mTransaction->LoggingSerialNumber(),
           GetRequest()->LoggingSerialNumber());
 
       mInFlightResponseInvalidationNeeded = false;
       break;
     }
   }
 
-  ResultHelper helper(GetRequest(),
-                      mTransaction ? SafeRefPtr{&mTransaction.ref(),
-                                                AcquireStrongRefFromRawPtr{}}
-                                   : nullptr,
-                      static_cast<IDBCursor*>(mCursor));
-  helper.DispatchSuccessEvent();
+  SetResultAndDispatchSuccessEvent(
+      GetRequest(),
+      mTransaction
+          ? SafeRefPtr{&mTransaction.ref(), AcquireStrongRefFromRawPtr{}}
+          : nullptr,
+      static_cast<IDBCursor*>(mCursor));
 }
 
 template <IDBCursorType CursorType>
 void BackgroundCursorChild<CursorType>::HandleResponse(
     nsTArray<ResponseType>&& aResponses) {
   AssertIsOnOwningThread();
 
   if constexpr (CursorType == IDBCursorType::ObjectStore) {
--- a/dom/indexedDB/IDBResult.h
+++ b/dom/indexedDB/IDBResult.h
@@ -28,18 +28,18 @@ struct OkType final {
   T mValue;
 };
 
 template <>
 struct OkType<void> final {};
 
 template <IDBSpecialValue Value>
 using SpecialConstant = std::integral_constant<IDBSpecialValue, Value>;
-using FailureType = detail::SpecialConstant<IDBSpecialValue::Failure>;
-using InvalidType = detail::SpecialConstant<IDBSpecialValue::Invalid>;
+using FailureType = SpecialConstant<IDBSpecialValue::Failure>;
+using InvalidType = SpecialConstant<IDBSpecialValue::Invalid>;
 struct ExceptionType final {};
 struct VoidType final {};
 }  // namespace detail
 
 namespace {
 template <typename T>
 constexpr inline detail::OkType<std::remove_reference_t<T>> Ok(T&& aValue) {
   return {std::forward<T>(aValue)};
@@ -73,70 +73,68 @@ template <>
 struct IsSortedSet<> : std::true_type {};
 
 // IDBResultBase contains the bulk of the implementation of IDBResult, namely
 // functionality that's applicable to all values of T.
 template <typename T, IDBSpecialValue... S>
 class IDBResultBase {
   // This assertion ensures that permutations of the set of possible special
   // values don't create distinct types.
-  static_assert(detail::IsSortedSet<S...>::value,
+  static_assert(IsSortedSet<S...>::value,
                 "special value list must be sorted and unique");
 
   template <typename R, IDBSpecialValue... U>
   friend class IDBResultBase;
 
  protected:
-  using ValueType = detail::OkType<T>;
+  using ValueType = OkType<T>;
 
  public:
   // Construct a normal result. Use the Ok function to create an object of type
   // ValueType.
   MOZ_IMPLICIT IDBResultBase(const ValueType& aValue) : mVariant(aValue) {}
 
-  MOZ_IMPLICIT IDBResultBase(detail::ExceptionType)
-      : mVariant(detail::ExceptionType{}) {}
+  MOZ_IMPLICIT IDBResultBase(ExceptionType) : mVariant(ExceptionType{}) {}
 
   template <IDBSpecialValue Special>
-  MOZ_IMPLICIT IDBResultBase(detail::SpecialConstant<Special>)
-      : mVariant(detail::SpecialConstant<Special>{}) {}
+  MOZ_IMPLICIT IDBResultBase(SpecialConstant<Special>)
+      : mVariant(SpecialConstant<Special>{}) {}
 
   // Construct an IDBResult from another IDBResult whose set of possible special
   // values is a subset of this one's.
   template <IDBSpecialValue... U>
   MOZ_IMPLICIT IDBResultBase(const IDBResultBase<T, U...>& aOther)
       : mVariant(aOther.mVariant.match(
             [](auto& aVariant) { return VariantType{aVariant}; })) {}
 
   // Test whether the result is a normal return value. The choice of the first
   // parameter's type makes it possible to write `result.Is(Ok, rv)`, promoting
   // readability and uniformity with other functions in the overload set.
-  bool Is(detail::OkType<void> (*)(), const ErrorResult& aRv) const {
+  bool Is(OkType<void> (*)(), const ErrorResult& aRv) const {
     AssertConsistency(aRv);
     return mVariant.template is<ValueType>();
   }
 
-  bool Is(detail::ExceptionType, const ErrorResult& aRv) const {
+  bool Is(ExceptionType, const ErrorResult& aRv) const {
     AssertConsistency(aRv);
-    return mVariant.template is<detail::ExceptionType>();
+    return mVariant.template is<ExceptionType>();
   }
 
   template <IDBSpecialValue Special>
-  bool Is(detail::SpecialConstant<Special>, const ErrorResult& aRv) const {
+  bool Is(SpecialConstant<Special>, const ErrorResult& aRv) const {
     AssertConsistency(aRv);
-    return mVariant.template is<detail::SpecialConstant<Special>>();
+    return mVariant.template is<SpecialConstant<Special>>();
   }
 
  protected:
   void AssertConsistency(const ErrorResult& aRv) const {
-    MOZ_ASSERT(aRv.Failed() == mVariant.template is<detail::ExceptionType>());
+    MOZ_ASSERT(aRv.Failed() == mVariant.template is<ExceptionType>());
   }
 
-  using VariantType =
-      Variant<ValueType, detail::ExceptionType, detail::SpecialConstant<S>...>;
+  using VariantType = Variant<ValueType, ExceptionType, SpecialConstant<S>...>;
 
   VariantType mVariant;
 };
 }  // namespace detail
 
 // Represents a return value of an IndexedDB algorithm. T is the type of the
 // regular return value, while S is a list of special values that can be
 // returned by the particular algorithm.