DOMMozPromiseRequestHolder.h (3771B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_DOMMozPromiseRequestHolder_h 8 #define mozilla_dom_DOMMozPromiseRequestHolder_h 9 10 #include "mozilla/DOMEventTargetHelper.h" 11 #include "mozilla/MozPromise.h" 12 13 namespace mozilla::dom { 14 15 /** 16 * This is a helper class that can be used when MozPromises are 17 * being consumed by binding layer code. It effectively creates 18 * a MozPromiseRequestHolder that auto-disconnects when the binding's 19 * global is disconnected. 20 * 21 * It can be used like this: 22 * 23 * RefPtr<Promise> 24 * SomeAsyncAPI(Args& aArgs, ErrorResult& aRv) 25 * { 26 * nsIGlobalObject* global = GetParentObject(); 27 * if (!global) { 28 * aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); 29 * return nullptr; 30 * } 31 * 32 * RefPtr<Promise> outer = Promise::Create(global, aRv); 33 * if (aRv.Failed()) { 34 * return nullptr; 35 * } 36 * 37 * RefPtr<DOMMozPromiseRequestHolder> holder = 38 * new DOMMozPromiseRequestHolder(global); 39 * 40 * DoAsyncStuff()->Then( 41 * global->EventTargetFor(TaskCategory::Other), __func__, 42 * [holder, outer] (const Result& aResult) { 43 * holder->Complete(); 44 * 45 * // Note, you can access the holder's bound global in 46 * // your reaction handler. Its mostly likely set if 47 * // the handler fires, but you still must check for 48 * // its existence since something could disconnect 49 * // the global between when the MozPromise reaction 50 * // runnable is queued and when it actually runs. 51 * nsIGlobalObject* global = holder->GetParentObject(); 52 * NS_ENSURE_TRUE_VOID(global); 53 * 54 * outer->MaybeResolve(aResult); 55 * }, [holder, outer] (nsresult aRv) { 56 * holder->Complete(); 57 * outer->MaybeReject(aRv); 58 * })->Track(*holder); 59 * 60 * return outer.forget(); 61 * } 62 * 63 * NOTE: Currently this helper class extends DETH. This is only 64 * so that it can bind to the global and receive the 65 * DisconnectFromOwner() method call. In this future the 66 * binding code should be factored out so DETH is not 67 * needed here. See bug 1456893. 68 */ 69 template <typename PromiseType> 70 class DOMMozPromiseRequestHolder final : public DOMEventTargetHelper { 71 MozPromiseRequestHolder<PromiseType> mHolder; 72 73 ~DOMMozPromiseRequestHolder() = default; 74 75 void DisconnectFromOwner() override { 76 mHolder.DisconnectIfExists(); 77 DOMEventTargetHelper::DisconnectFromOwner(); 78 } 79 80 JSObject* WrapObject(JSContext* aCx, 81 JS::Handle<JSObject*> aGivenProto) override { 82 // We are extending DETH to get notified when the global goes 83 // away, but this object should never actually be exposed to 84 // script. 85 MOZ_CRASH("illegal method"); 86 } 87 88 public: 89 explicit DOMMozPromiseRequestHolder(nsIGlobalObject* aGlobal) 90 : DOMEventTargetHelper(aGlobal) { 91 MOZ_DIAGNOSTIC_ASSERT(aGlobal); 92 } 93 94 operator MozPromiseRequestHolder<PromiseType>&() { return mHolder; } 95 96 operator const MozPromiseRequestHolder<PromiseType>&() const { 97 return mHolder; 98 } 99 100 void Complete() { mHolder.Complete(); } 101 102 void DisconnectIfExists() { mHolder.DisconnectIfExists(); } 103 104 bool Exists() const { return mHolder.Exists(); } 105 106 NS_INLINE_DECL_REFCOUNTING_INHERITED(DOMMozPromiseRequestHolder, 107 DOMEventTargetHelper) 108 }; 109 110 } // namespace mozilla::dom 111 112 #endif // mozilla_dom_DOMMozPromiseRequestHolder_h