dom/promise/Promise.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/promise/Promise.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,273 @@
     1.4 +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
     1.5 +/* vim: set ts=2 et sw=2 tw=80: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef mozilla_dom_Promise_h
    1.11 +#define mozilla_dom_Promise_h
    1.12 +
    1.13 +#include "mozilla/Attributes.h"
    1.14 +#include "mozilla/ErrorResult.h"
    1.15 +#include "mozilla/TypeTraits.h"
    1.16 +#include "mozilla/dom/BindingDeclarations.h"
    1.17 +#include "nsCycleCollectionParticipant.h"
    1.18 +#include "mozilla/dom/PromiseBinding.h"
    1.19 +#include "mozilla/dom/ToJSValue.h"
    1.20 +#include "nsWrapperCache.h"
    1.21 +#include "nsAutoPtr.h"
    1.22 +#include "js/TypeDecls.h"
    1.23 +
    1.24 +#include "mozilla/dom/workers/bindings/WorkerFeature.h"
    1.25 +
    1.26 +class nsIGlobalObject;
    1.27 +
    1.28 +namespace mozilla {
    1.29 +namespace dom {
    1.30 +
    1.31 +class AnyCallback;
    1.32 +class PromiseCallback;
    1.33 +class PromiseInit;
    1.34 +class PromiseNativeHandler;
    1.35 +
    1.36 +class Promise;
    1.37 +class PromiseReportRejectFeature : public workers::WorkerFeature
    1.38 +{
    1.39 +  // The Promise that owns this feature.
    1.40 +  Promise* mPromise;
    1.41 +
    1.42 +public:
    1.43 +  PromiseReportRejectFeature(Promise* aPromise)
    1.44 +    : mPromise(aPromise)
    1.45 +  {
    1.46 +    MOZ_ASSERT(mPromise);
    1.47 +  }
    1.48 +
    1.49 +  virtual bool
    1.50 +  Notify(JSContext* aCx, workers::Status aStatus) MOZ_OVERRIDE;
    1.51 +};
    1.52 +
    1.53 +class Promise MOZ_FINAL : public nsISupports,
    1.54 +                          public nsWrapperCache
    1.55 +{
    1.56 +  friend class NativePromiseCallback;
    1.57 +  friend class PromiseResolverMixin;
    1.58 +  friend class PromiseResolverTask;
    1.59 +  friend class PromiseTask;
    1.60 +  friend class PromiseReportRejectFeature;
    1.61 +  friend class RejectPromiseCallback;
    1.62 +  friend class ResolvePromiseCallback;
    1.63 +  friend class WorkerPromiseResolverTask;
    1.64 +  friend class WorkerPromiseTask;
    1.65 +  friend class WrapperPromiseCallback;
    1.66 +
    1.67 +  ~Promise();
    1.68 +
    1.69 +public:
    1.70 +  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    1.71 +  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
    1.72 +
    1.73 +  Promise(nsIGlobalObject* aGlobal);
    1.74 +
    1.75 +  typedef void (Promise::*MaybeFunc)(JSContext* aCx,
    1.76 +                                     JS::Handle<JS::Value> aValue);
    1.77 +
    1.78 +  void MaybeResolve(JSContext* aCx,
    1.79 +                    JS::Handle<JS::Value> aValue);
    1.80 +  void MaybeReject(JSContext* aCx,
    1.81 +                   JS::Handle<JS::Value> aValue);
    1.82 +
    1.83 +  // Helpers for using Promise from C++.
    1.84 +  // Most DOM objects are handled already.  To add a new type T, add a
    1.85 +  // ToJSValue overload in ToJSValue.h.
    1.86 +  // aArg is a const reference so we can pass rvalues like integer constants
    1.87 +  template <typename T>
    1.88 +  void MaybeResolve(const T& aArg) {
    1.89 +    MaybeSomething(aArg, &Promise::MaybeResolve);
    1.90 +  }
    1.91 +
    1.92 +  // aArg is a const reference so we can pass rvalues like NS_ERROR_*
    1.93 +  template <typename T>
    1.94 +  void MaybeReject(const T& aArg) {
    1.95 +    MaybeSomething(aArg, &Promise::MaybeReject);
    1.96 +  }
    1.97 +
    1.98 +  // WebIDL
    1.99 +
   1.100 +  nsIGlobalObject* GetParentObject() const
   1.101 +  {
   1.102 +    return mGlobal;
   1.103 +  }
   1.104 +
   1.105 +  virtual JSObject*
   1.106 +  WrapObject(JSContext* aCx) MOZ_OVERRIDE;
   1.107 +
   1.108 +  static already_AddRefed<Promise>
   1.109 +  Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
   1.110 +              ErrorResult& aRv);
   1.111 +
   1.112 +  static already_AddRefed<Promise>
   1.113 +  Resolve(const GlobalObject& aGlobal, JSContext* aCx,
   1.114 +          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
   1.115 +
   1.116 +  static already_AddRefed<Promise>
   1.117 +  Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
   1.118 +          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
   1.119 +
   1.120 +  static already_AddRefed<Promise>
   1.121 +  Reject(const GlobalObject& aGlobal, JSContext* aCx,
   1.122 +         JS::Handle<JS::Value> aValue, ErrorResult& aRv);
   1.123 +
   1.124 +  static already_AddRefed<Promise>
   1.125 +  Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
   1.126 +         JS::Handle<JS::Value> aValue, ErrorResult& aRv);
   1.127 +
   1.128 +  already_AddRefed<Promise>
   1.129 +  Then(JSContext* aCx, AnyCallback* aResolveCallback,
   1.130 +       AnyCallback* aRejectCallback);
   1.131 +
   1.132 +  already_AddRefed<Promise>
   1.133 +  Catch(JSContext* aCx, AnyCallback* aRejectCallback);
   1.134 +
   1.135 +  static already_AddRefed<Promise>
   1.136 +  All(const GlobalObject& aGlobal, JSContext* aCx,
   1.137 +      const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
   1.138 +
   1.139 +  static already_AddRefed<Promise>
   1.140 +  Race(const GlobalObject& aGlobal, JSContext* aCx,
   1.141 +       const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
   1.142 +
   1.143 +  void AppendNativeHandler(PromiseNativeHandler* aRunnable);
   1.144 +
   1.145 +private:
   1.146 +  enum PromiseState {
   1.147 +    Pending,
   1.148 +    Resolved,
   1.149 +    Rejected
   1.150 +  };
   1.151 +
   1.152 +  enum PromiseTaskSync {
   1.153 +    SyncTask,
   1.154 +    AsyncTask
   1.155 +  };
   1.156 +
   1.157 +  void SetState(PromiseState aState)
   1.158 +  {
   1.159 +    MOZ_ASSERT(mState == Pending);
   1.160 +    MOZ_ASSERT(aState != Pending);
   1.161 +    mState = aState;
   1.162 +  }
   1.163 +
   1.164 +  void SetResult(JS::Handle<JS::Value> aValue)
   1.165 +  {
   1.166 +    mResult = aValue;
   1.167 +  }
   1.168 +
   1.169 +  // This method processes promise's resolve/reject callbacks with promise's
   1.170 +  // result. It's executed when the resolver.resolve() or resolver.reject() is
   1.171 +  // called or when the promise already has a result and new callbacks are
   1.172 +  // appended by then(), catch() or done().
   1.173 +  void RunTask();
   1.174 +
   1.175 +  void RunResolveTask(JS::Handle<JS::Value> aValue,
   1.176 +                      Promise::PromiseState aState,
   1.177 +                      PromiseTaskSync aAsynchronous);
   1.178 +
   1.179 +  void AppendCallbacks(PromiseCallback* aResolveCallback,
   1.180 +                       PromiseCallback* aRejectCallback);
   1.181 +
   1.182 +  // If we have been rejected and our mResult is a JS exception,
   1.183 +  // report it to the error console.
   1.184 +  // Use MaybeReportRejectedOnce() for actual calls.
   1.185 +  void MaybeReportRejected();
   1.186 +
   1.187 +  void MaybeReportRejectedOnce() {
   1.188 +    MaybeReportRejected();
   1.189 +    RemoveFeature();
   1.190 +    mResult = JS::UndefinedValue();
   1.191 +  }
   1.192 +
   1.193 +  void MaybeResolveInternal(JSContext* aCx,
   1.194 +                            JS::Handle<JS::Value> aValue,
   1.195 +                            PromiseTaskSync aSync = AsyncTask);
   1.196 +  void MaybeRejectInternal(JSContext* aCx,
   1.197 +                           JS::Handle<JS::Value> aValue,
   1.198 +                           PromiseTaskSync aSync = AsyncTask);
   1.199 +
   1.200 +  void ResolveInternal(JSContext* aCx,
   1.201 +                       JS::Handle<JS::Value> aValue,
   1.202 +                       PromiseTaskSync aSync = AsyncTask);
   1.203 +
   1.204 +  void RejectInternal(JSContext* aCx,
   1.205 +                      JS::Handle<JS::Value> aValue,
   1.206 +                      PromiseTaskSync aSync = AsyncTask);
   1.207 +
   1.208 +  // Helper methods for using Promises from C++
   1.209 +  JSObject* GetOrCreateWrapper(JSContext* aCx);
   1.210 +
   1.211 +  template <typename T>
   1.212 +  void MaybeSomething(T& aArgument, MaybeFunc aFunc) {
   1.213 +    ThreadsafeAutoJSContext cx;
   1.214 +
   1.215 +    JSObject* wrapper = GetOrCreateWrapper(cx);
   1.216 +    if (!wrapper) {
   1.217 +      HandleException(cx);
   1.218 +      return;
   1.219 +    }
   1.220 +
   1.221 +    JSAutoCompartment ac(cx, wrapper);
   1.222 +    JS::Rooted<JS::Value> val(cx);
   1.223 +    if (!ToJSValue(cx, aArgument, &val)) {
   1.224 +      HandleException(cx);
   1.225 +      return;
   1.226 +    }
   1.227 +
   1.228 +    (this->*aFunc)(cx, val);
   1.229 +  }
   1.230 +
   1.231 +  // Static methods for the PromiseInit functions.
   1.232 +  static bool
   1.233 +  JSCallback(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
   1.234 +
   1.235 +  static bool
   1.236 +  ThenableResolverCommon(JSContext* aCx, uint32_t /* PromiseCallback::Task */ aTask,
   1.237 +                         unsigned aArgc, JS::Value* aVp);
   1.238 +  static bool
   1.239 +  JSCallbackThenableResolver(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
   1.240 +  static bool
   1.241 +  JSCallbackThenableRejecter(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
   1.242 +
   1.243 +  static JSObject*
   1.244 +  CreateFunction(JSContext* aCx, JSObject* aParent, Promise* aPromise,
   1.245 +                int32_t aTask);
   1.246 +
   1.247 +  static JSObject*
   1.248 +  CreateThenableFunction(JSContext* aCx, Promise* aPromise, uint32_t aTask);
   1.249 +
   1.250 +  void HandleException(JSContext* aCx);
   1.251 +
   1.252 +  void RemoveFeature();
   1.253 +
   1.254 +  nsRefPtr<nsIGlobalObject> mGlobal;
   1.255 +
   1.256 +  nsTArray<nsRefPtr<PromiseCallback> > mResolveCallbacks;
   1.257 +  nsTArray<nsRefPtr<PromiseCallback> > mRejectCallbacks;
   1.258 +
   1.259 +  JS::Heap<JS::Value> mResult;
   1.260 +  PromiseState mState;
   1.261 +  bool mTaskPending;
   1.262 +  bool mHadRejectCallback;
   1.263 +
   1.264 +  bool mResolvePending;
   1.265 +
   1.266 +  // If a rejected promise on a worker has no reject callbacks attached, it
   1.267 +  // needs to know when the worker is shutting down, to report the error on the
   1.268 +  // console before the worker's context is deleted. This feature is used for
   1.269 +  // that purpose.
   1.270 +  nsAutoPtr<PromiseReportRejectFeature> mFeature;
   1.271 +};
   1.272 +
   1.273 +} // namespace dom
   1.274 +} // namespace mozilla
   1.275 +
   1.276 +#endif // mozilla_dom_Promise_h

mercurial