dom/promise/Promise.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
     2 /* vim: set ts=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 file,
     5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef mozilla_dom_Promise_h
     8 #define mozilla_dom_Promise_h
    10 #include "mozilla/Attributes.h"
    11 #include "mozilla/ErrorResult.h"
    12 #include "mozilla/TypeTraits.h"
    13 #include "mozilla/dom/BindingDeclarations.h"
    14 #include "nsCycleCollectionParticipant.h"
    15 #include "mozilla/dom/PromiseBinding.h"
    16 #include "mozilla/dom/ToJSValue.h"
    17 #include "nsWrapperCache.h"
    18 #include "nsAutoPtr.h"
    19 #include "js/TypeDecls.h"
    21 #include "mozilla/dom/workers/bindings/WorkerFeature.h"
    23 class nsIGlobalObject;
    25 namespace mozilla {
    26 namespace dom {
    28 class AnyCallback;
    29 class PromiseCallback;
    30 class PromiseInit;
    31 class PromiseNativeHandler;
    33 class Promise;
    34 class PromiseReportRejectFeature : public workers::WorkerFeature
    35 {
    36   // The Promise that owns this feature.
    37   Promise* mPromise;
    39 public:
    40   PromiseReportRejectFeature(Promise* aPromise)
    41     : mPromise(aPromise)
    42   {
    43     MOZ_ASSERT(mPromise);
    44   }
    46   virtual bool
    47   Notify(JSContext* aCx, workers::Status aStatus) MOZ_OVERRIDE;
    48 };
    50 class Promise MOZ_FINAL : public nsISupports,
    51                           public nsWrapperCache
    52 {
    53   friend class NativePromiseCallback;
    54   friend class PromiseResolverMixin;
    55   friend class PromiseResolverTask;
    56   friend class PromiseTask;
    57   friend class PromiseReportRejectFeature;
    58   friend class RejectPromiseCallback;
    59   friend class ResolvePromiseCallback;
    60   friend class WorkerPromiseResolverTask;
    61   friend class WorkerPromiseTask;
    62   friend class WrapperPromiseCallback;
    64   ~Promise();
    66 public:
    67   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    68   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
    70   Promise(nsIGlobalObject* aGlobal);
    72   typedef void (Promise::*MaybeFunc)(JSContext* aCx,
    73                                      JS::Handle<JS::Value> aValue);
    75   void MaybeResolve(JSContext* aCx,
    76                     JS::Handle<JS::Value> aValue);
    77   void MaybeReject(JSContext* aCx,
    78                    JS::Handle<JS::Value> aValue);
    80   // Helpers for using Promise from C++.
    81   // Most DOM objects are handled already.  To add a new type T, add a
    82   // ToJSValue overload in ToJSValue.h.
    83   // aArg is a const reference so we can pass rvalues like integer constants
    84   template <typename T>
    85   void MaybeResolve(const T& aArg) {
    86     MaybeSomething(aArg, &Promise::MaybeResolve);
    87   }
    89   // aArg is a const reference so we can pass rvalues like NS_ERROR_*
    90   template <typename T>
    91   void MaybeReject(const T& aArg) {
    92     MaybeSomething(aArg, &Promise::MaybeReject);
    93   }
    95   // WebIDL
    97   nsIGlobalObject* GetParentObject() const
    98   {
    99     return mGlobal;
   100   }
   102   virtual JSObject*
   103   WrapObject(JSContext* aCx) MOZ_OVERRIDE;
   105   static already_AddRefed<Promise>
   106   Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
   107               ErrorResult& aRv);
   109   static already_AddRefed<Promise>
   110   Resolve(const GlobalObject& aGlobal, JSContext* aCx,
   111           JS::Handle<JS::Value> aValue, ErrorResult& aRv);
   113   static already_AddRefed<Promise>
   114   Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
   115           JS::Handle<JS::Value> aValue, ErrorResult& aRv);
   117   static already_AddRefed<Promise>
   118   Reject(const GlobalObject& aGlobal, JSContext* aCx,
   119          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
   121   static already_AddRefed<Promise>
   122   Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
   123          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
   125   already_AddRefed<Promise>
   126   Then(JSContext* aCx, AnyCallback* aResolveCallback,
   127        AnyCallback* aRejectCallback);
   129   already_AddRefed<Promise>
   130   Catch(JSContext* aCx, AnyCallback* aRejectCallback);
   132   static already_AddRefed<Promise>
   133   All(const GlobalObject& aGlobal, JSContext* aCx,
   134       const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
   136   static already_AddRefed<Promise>
   137   Race(const GlobalObject& aGlobal, JSContext* aCx,
   138        const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
   140   void AppendNativeHandler(PromiseNativeHandler* aRunnable);
   142 private:
   143   enum PromiseState {
   144     Pending,
   145     Resolved,
   146     Rejected
   147   };
   149   enum PromiseTaskSync {
   150     SyncTask,
   151     AsyncTask
   152   };
   154   void SetState(PromiseState aState)
   155   {
   156     MOZ_ASSERT(mState == Pending);
   157     MOZ_ASSERT(aState != Pending);
   158     mState = aState;
   159   }
   161   void SetResult(JS::Handle<JS::Value> aValue)
   162   {
   163     mResult = aValue;
   164   }
   166   // This method processes promise's resolve/reject callbacks with promise's
   167   // result. It's executed when the resolver.resolve() or resolver.reject() is
   168   // called or when the promise already has a result and new callbacks are
   169   // appended by then(), catch() or done().
   170   void RunTask();
   172   void RunResolveTask(JS::Handle<JS::Value> aValue,
   173                       Promise::PromiseState aState,
   174                       PromiseTaskSync aAsynchronous);
   176   void AppendCallbacks(PromiseCallback* aResolveCallback,
   177                        PromiseCallback* aRejectCallback);
   179   // If we have been rejected and our mResult is a JS exception,
   180   // report it to the error console.
   181   // Use MaybeReportRejectedOnce() for actual calls.
   182   void MaybeReportRejected();
   184   void MaybeReportRejectedOnce() {
   185     MaybeReportRejected();
   186     RemoveFeature();
   187     mResult = JS::UndefinedValue();
   188   }
   190   void MaybeResolveInternal(JSContext* aCx,
   191                             JS::Handle<JS::Value> aValue,
   192                             PromiseTaskSync aSync = AsyncTask);
   193   void MaybeRejectInternal(JSContext* aCx,
   194                            JS::Handle<JS::Value> aValue,
   195                            PromiseTaskSync aSync = AsyncTask);
   197   void ResolveInternal(JSContext* aCx,
   198                        JS::Handle<JS::Value> aValue,
   199                        PromiseTaskSync aSync = AsyncTask);
   201   void RejectInternal(JSContext* aCx,
   202                       JS::Handle<JS::Value> aValue,
   203                       PromiseTaskSync aSync = AsyncTask);
   205   // Helper methods for using Promises from C++
   206   JSObject* GetOrCreateWrapper(JSContext* aCx);
   208   template <typename T>
   209   void MaybeSomething(T& aArgument, MaybeFunc aFunc) {
   210     ThreadsafeAutoJSContext cx;
   212     JSObject* wrapper = GetOrCreateWrapper(cx);
   213     if (!wrapper) {
   214       HandleException(cx);
   215       return;
   216     }
   218     JSAutoCompartment ac(cx, wrapper);
   219     JS::Rooted<JS::Value> val(cx);
   220     if (!ToJSValue(cx, aArgument, &val)) {
   221       HandleException(cx);
   222       return;
   223     }
   225     (this->*aFunc)(cx, val);
   226   }
   228   // Static methods for the PromiseInit functions.
   229   static bool
   230   JSCallback(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
   232   static bool
   233   ThenableResolverCommon(JSContext* aCx, uint32_t /* PromiseCallback::Task */ aTask,
   234                          unsigned aArgc, JS::Value* aVp);
   235   static bool
   236   JSCallbackThenableResolver(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
   237   static bool
   238   JSCallbackThenableRejecter(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
   240   static JSObject*
   241   CreateFunction(JSContext* aCx, JSObject* aParent, Promise* aPromise,
   242                 int32_t aTask);
   244   static JSObject*
   245   CreateThenableFunction(JSContext* aCx, Promise* aPromise, uint32_t aTask);
   247   void HandleException(JSContext* aCx);
   249   void RemoveFeature();
   251   nsRefPtr<nsIGlobalObject> mGlobal;
   253   nsTArray<nsRefPtr<PromiseCallback> > mResolveCallbacks;
   254   nsTArray<nsRefPtr<PromiseCallback> > mRejectCallbacks;
   256   JS::Heap<JS::Value> mResult;
   257   PromiseState mState;
   258   bool mTaskPending;
   259   bool mHadRejectCallback;
   261   bool mResolvePending;
   263   // If a rejected promise on a worker has no reject callbacks attached, it
   264   // needs to know when the worker is shutting down, to report the error on the
   265   // console before the worker's context is deleted. This feature is used for
   266   // that purpose.
   267   nsAutoPtr<PromiseReportRejectFeature> mFeature;
   268 };
   270 } // namespace dom
   271 } // namespace mozilla
   273 #endif // mozilla_dom_Promise_h

mercurial