Bug 1367679. P3 - pass mCompletionPromise to InvokeCallbackMethod(). draft
authorJW Wang <jwwang@mozilla.com>
Wed, 31 May 2017 17:28:09 +0800
changeset 588114 d4fc95136513ef4d0d427d0d72a20f5eaa90cf4b
parent 588113 cde4ba9d0dd75c0e0cf924b29b643cbbb6ffe104
child 588115 99ef0109a439d88645181d4a3c5ce09f37a49191
push id61915
push userjwwang@mozilla.com
push dateFri, 02 Jun 2017 06:48:13 +0000
bugs1367679
milestone55.0a1
Bug 1367679. P3 - pass mCompletionPromise to InvokeCallbackMethod(). This reduces duplicate code by handling promise chaining in one place. MozReview-Commit-ID: 474T5hvf9oM
xpcom/threads/MozPromise.h
--- a/xpcom/threads/MozPromise.h
+++ b/xpcom/threads/MozPromise.h
@@ -521,36 +521,43 @@ protected:
     return (aThisVal->*aMethod)();
   }
 
   // Called when promise chaining is supported.
   template<bool SupportChaining,
            typename ThisType,
            typename MethodType,
            typename ValueType>
-  static typename EnableIf<SupportChaining, already_AddRefed<MozPromise>>::Type
-  InvokeCallbackMethod(ThisType* aThisVal,
-                       MethodType aMethod,
-                       ValueType&& aValue)
+  static typename EnableIf<SupportChaining, void>::Type InvokeCallbackMethod(
+    ThisType* aThisVal,
+    MethodType aMethod,
+    ValueType&& aValue,
+    RefPtr<Private>&& aCompletionPromise)
   {
-    return InvokeMethod(aThisVal, aMethod, Forward<ValueType>(aValue)).forget();
+    auto p = InvokeMethod(aThisVal, aMethod, Forward<ValueType>(aValue));
+    if (aCompletionPromise) {
+      p->ChainTo(aCompletionPromise.forget(), "<chained completion promise>");
+    }
   }
 
   // Called when promise chaining is not supported.
   template<bool SupportChaining,
            typename ThisType,
            typename MethodType,
            typename ValueType>
-  static typename EnableIf<!SupportChaining, already_AddRefed<MozPromise>>::Type
-  InvokeCallbackMethod(ThisType* aThisVal,
-                       MethodType aMethod,
-                       ValueType&& aValue)
+  static typename EnableIf<!SupportChaining, void>::Type InvokeCallbackMethod(
+    ThisType* aThisVal,
+    MethodType aMethod,
+    ValueType&& aValue,
+    RefPtr<Private>&& aCompletionPromise)
   {
+    MOZ_DIAGNOSTIC_ASSERT(
+      !aCompletionPromise,
+      "Can't do promise chaining for a non-promise-returning method.");
     InvokeMethod(aThisVal, aMethod, Forward<ValueType>(aValue));
-    return nullptr;
   }
 
   template<typename>
   class ThenCommand;
 
   template<typename...>
   class ThenValue;
 
@@ -592,39 +599,35 @@ protected:
   protected:
     MozPromiseBase* CompletionPromise() const override
     {
       return mCompletionPromise;
     }
 
     void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override
     {
-      RefPtr<MozPromise> result;
       if (aValue.IsResolve()) {
-        result = InvokeCallbackMethod<SupportChaining::value>(
-          mThisVal.get(), mResolveMethod, MaybeMove(aValue.ResolveValue()));
+        InvokeCallbackMethod<SupportChaining::value>(
+          mThisVal.get(),
+          mResolveMethod,
+          MaybeMove(aValue.ResolveValue()),
+          Move(mCompletionPromise));
       } else {
-        result = InvokeCallbackMethod<SupportChaining::value>(
-          mThisVal.get(), mRejectMethod, MaybeMove(aValue.RejectValue()));
+        InvokeCallbackMethod<SupportChaining::value>(
+          mThisVal.get(),
+          mRejectMethod,
+          MaybeMove(aValue.RejectValue()),
+          Move(mCompletionPromise));
       }
 
       // Null out mThisVal after invoking the callback so that any references are
       // released predictably on the dispatch thread. Otherwise, it would be
       // released on whatever thread last drops its reference to the ThenValue,
       // which may or may not be ok.
       mThisVal = nullptr;
-
-      MOZ_DIAGNOSTIC_ASSERT(
-        !mCompletionPromise || result,
-        "Can't do promise chaining for a non-promise-returning method.");
-
-      if (mCompletionPromise && result) {
-        result->ChainTo(mCompletionPromise.forget(),
-                        "<chained completion promise>");
-      }
     }
 
   private:
     RefPtr<ThisType> mThisVal; // Only accessed and refcounted on dispatch thread.
     ResolveMethodType mResolveMethod;
     RejectMethodType mRejectMethod;
     RefPtr<Private> mCompletionPromise;
   };
@@ -659,33 +662,26 @@ protected:
   protected:
     MozPromiseBase* CompletionPromise() const override
     {
       return mCompletionPromise;
     }
 
     void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override
     {
-      RefPtr<MozPromise> result = InvokeCallbackMethod<SupportChaining::value>(
-        mThisVal.get(), mResolveRejectMethod, MaybeMove(aValue));
+      InvokeCallbackMethod<SupportChaining::value>(mThisVal.get(),
+                                                   mResolveRejectMethod,
+                                                   MaybeMove(aValue),
+                                                   Move(mCompletionPromise));
 
       // Null out mThisVal after invoking the callback so that any references are
       // released predictably on the dispatch thread. Otherwise, it would be
       // released on whatever thread last drops its reference to the ThenValue,
       // which may or may not be ok.
       mThisVal = nullptr;
-
-      MOZ_DIAGNOSTIC_ASSERT(
-        !mCompletionPromise || result,
-        "Can't do promise chaining for a non-promise-returning method.");
-
-      if (mCompletionPromise && result) {
-        result->ChainTo(mCompletionPromise.forget(),
-                        "<chained completion promise>");
-      }
     }
 
   private:
     RefPtr<ThisType> mThisVal; // Only accessed and refcounted on dispatch thread.
     ResolveRejectMethodType mResolveRejectMethod;
     RefPtr<Private> mCompletionPromise;
   };
 
@@ -730,44 +726,36 @@ protected:
 
     void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override
     {
       // Note: The usage of InvokeCallbackMethod here requires that
       // ResolveFunction/RejectFunction are capture-lambdas (i.e. anonymous
       // classes with ::operator()), since it allows us to share code more easily.
       // We could fix this if need be, though it's quite easy to work around by
       // just capturing something.
-      RefPtr<MozPromise> result;
       if (aValue.IsResolve()) {
-        result = InvokeCallbackMethod<SupportChaining::value>(
+        InvokeCallbackMethod<SupportChaining::value>(
           mResolveFunction.ptr(),
           &ResolveFunction::operator(),
-          MaybeMove(aValue.ResolveValue()));
+          MaybeMove(aValue.ResolveValue()),
+          Move(mCompletionPromise));
       } else {
-        result = InvokeCallbackMethod<SupportChaining::value>(
+        InvokeCallbackMethod<SupportChaining::value>(
           mRejectFunction.ptr(),
           &RejectFunction::operator(),
-          MaybeMove(aValue.RejectValue()));
+          MaybeMove(aValue.RejectValue()),
+          Move(mCompletionPromise));
       }
 
       // Destroy callbacks after invocation so that any references in closures are
       // released predictably on the dispatch thread. Otherwise, they would be
       // released on whatever thread last drops its reference to the ThenValue,
       // which may or may not be ok.
       mResolveFunction.reset();
       mRejectFunction.reset();
-
-      MOZ_DIAGNOSTIC_ASSERT(
-        !mCompletionPromise || result,
-        "Can't do promise chaining for a non-promise-returning method.");
-
-      if (mCompletionPromise && result) {
-        result->ChainTo(mCompletionPromise.forget(),
-                        "<chained completion promise>");
-      }
     }
 
   private:
     Maybe<ResolveFunction> mResolveFunction; // Only accessed and deleted on dispatch thread.
     Maybe<RejectFunction> mRejectFunction; // Only accessed and deleted on dispatch thread.
     RefPtr<Private> mCompletionPromise;
   };
 
@@ -806,35 +794,27 @@ protected:
 
     void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override
     {
       // Note: The usage of InvokeCallbackMethod here requires that
       // ResolveRejectFunction is capture-lambdas (i.e. anonymous
       // classes with ::operator()), since it allows us to share code more easily.
       // We could fix this if need be, though it's quite easy to work around by
       // just capturing something.
-      RefPtr<MozPromise> result = InvokeCallbackMethod<SupportChaining::value>(
+      InvokeCallbackMethod<SupportChaining::value>(
         mResolveRejectFunction.ptr(),
         &ResolveRejectFunction::operator(),
-        MaybeMove(aValue));
+        MaybeMove(aValue),
+        Move(mCompletionPromise));
 
       // Destroy callbacks after invocation so that any references in closures are
       // released predictably on the dispatch thread. Otherwise, they would be
       // released on whatever thread last drops its reference to the ThenValue,
       // which may or may not be ok.
       mResolveRejectFunction.reset();
-
-      MOZ_DIAGNOSTIC_ASSERT(
-        !mCompletionPromise || result,
-        "Can't do promise chaining for a non-promise-returning method.");
-
-      if (mCompletionPromise && result) {
-        result->ChainTo(mCompletionPromise.forget(),
-                        "<chained completion promise>");
-      }
     }
 
   private:
     Maybe<ResolveRejectFunction> mResolveRejectFunction; // Only accessed and deleted on dispatch thread.
     RefPtr<Private> mCompletionPromise;
   };
 
 public: