dom/promise/Promise.h

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

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

mercurial