Bug 945766 - DOM Promise should pass Promise/A+ tests. r=bz
[gecko.git] / dom / promise / Promise.h
blob157702f4a021441e4a8b667645b8d137d9cfd1bc
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/dom/BindingDeclarations.h"
13 #include "nsCycleCollectionParticipant.h"
14 #include "mozilla/dom/PromiseBinding.h"
15 #include "nsWrapperCache.h"
16 #include "nsAutoPtr.h"
17 #include "nsPIDOMWindow.h"
18 #include "js/TypeDecls.h"
20 namespace mozilla {
21 namespace dom {
23 class AnyCallback;
24 class PromiseCallback;
25 class PromiseInit;
26 class PromiseNativeHandler;
28 class Promise MOZ_FINAL : public nsISupports,
29 public nsWrapperCache
31 friend class NativePromiseCallback;
32 friend class PromiseResolverMixin;
33 friend class PromiseResolverTask;
34 friend class PromiseTask;
35 friend class RejectPromiseCallback;
36 friend class ResolvePromiseCallback;
37 friend class WorkerPromiseResolverTask;
38 friend class WorkerPromiseTask;
39 friend class WrapperPromiseCallback;
41 public:
42 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
43 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
45 Promise(nsPIDOMWindow* aWindow);
46 ~Promise();
48 static bool EnabledForScope(JSContext* aCx, JSObject* /* unused */);
50 void MaybeResolve(JSContext* aCx,
51 JS::Handle<JS::Value> aValue);
52 void MaybeReject(JSContext* aCx,
53 JS::Handle<JS::Value> aValue);
55 // WebIDL
57 nsPIDOMWindow* GetParentObject() const
59 return mWindow;
62 virtual JSObject*
63 WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
65 static already_AddRefed<Promise>
66 Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
67 ErrorResult& aRv);
69 static already_AddRefed<Promise>
70 Resolve(const GlobalObject& aGlobal, JSContext* aCx,
71 const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv);
73 static already_AddRefed<Promise>
74 Resolve(nsPIDOMWindow* aWindow, JSContext* aCx,
75 JS::Handle<JS::Value> aValue, ErrorResult& aRv);
77 static already_AddRefed<Promise>
78 Reject(const GlobalObject& aGlobal, JSContext* aCx,
79 const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv);
81 static already_AddRefed<Promise>
82 Reject(nsPIDOMWindow* aWindow, JSContext* aCx,
83 JS::Handle<JS::Value> aValue, ErrorResult& aRv);
85 already_AddRefed<Promise>
86 Then(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback);
88 already_AddRefed<Promise>
89 Catch(AnyCallback* aRejectCallback);
91 // FIXME(nsm): Bug 956197
92 static already_AddRefed<Promise>
93 All(const GlobalObject& aGlobal, JSContext* aCx,
94 const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
96 static already_AddRefed<Promise>
97 Cast(const GlobalObject& aGlobal, JSContext* aCx,
98 const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv);
100 // FIXME(nsm): Bug 956197
101 static already_AddRefed<Promise>
102 Race(const GlobalObject& aGlobal, JSContext* aCx,
103 const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
105 void AppendNativeHandler(PromiseNativeHandler* aRunnable);
107 private:
108 enum PromiseState {
109 Pending,
110 Resolved,
111 Rejected
114 enum PromiseTaskSync {
115 SyncTask,
116 AsyncTask
119 void SetState(PromiseState aState)
121 MOZ_ASSERT(mState == Pending);
122 MOZ_ASSERT(aState != Pending);
123 mState = aState;
126 void SetResult(JS::Handle<JS::Value> aValue)
128 mResult = aValue;
131 // This method processes promise's resolve/reject callbacks with promise's
132 // result. It's executed when the resolver.resolve() or resolver.reject() is
133 // called or when the promise already has a result and new callbacks are
134 // appended by then(), catch() or done().
135 void RunTask();
137 void RunResolveTask(JS::Handle<JS::Value> aValue,
138 Promise::PromiseState aState,
139 PromiseTaskSync aAsynchronous);
141 void AppendCallbacks(PromiseCallback* aResolveCallback,
142 PromiseCallback* aRejectCallback);
144 // If we have been rejected and our mResult is a JS exception,
145 // report it to the error console.
146 void MaybeReportRejected();
148 void MaybeResolveInternal(JSContext* aCx,
149 JS::Handle<JS::Value> aValue,
150 PromiseTaskSync aSync = AsyncTask);
151 void MaybeRejectInternal(JSContext* aCx,
152 JS::Handle<JS::Value> aValue,
153 PromiseTaskSync aSync = AsyncTask);
155 void ResolveInternal(JSContext* aCx,
156 JS::Handle<JS::Value> aValue,
157 PromiseTaskSync aSync = AsyncTask);
159 void RejectInternal(JSContext* aCx,
160 JS::Handle<JS::Value> aValue,
161 PromiseTaskSync aSync = AsyncTask);
163 // Static methods for the PromiseInit functions.
164 static bool
165 JSCallback(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
167 static bool
168 ThenableResolverCommon(JSContext* aCx, uint32_t /* PromiseCallback::Task */ aTask,
169 unsigned aArgc, JS::Value* aVp);
170 static bool
171 JSCallbackThenableResolver(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
172 static bool
173 JSCallbackThenableRejecter(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
175 static JSObject*
176 CreateFunction(JSContext* aCx, JSObject* aParent, Promise* aPromise,
177 int32_t aTask);
179 static JSObject*
180 CreateThenableFunction(JSContext* aCx, Promise* aPromise, uint32_t aTask);
182 void HandleException(JSContext* aCx);
184 nsRefPtr<nsPIDOMWindow> mWindow;
186 nsTArray<nsRefPtr<PromiseCallback> > mResolveCallbacks;
187 nsTArray<nsRefPtr<PromiseCallback> > mRejectCallbacks;
189 JS::Heap<JS::Value> mResult;
190 PromiseState mState;
191 bool mTaskPending;
192 bool mHadRejectCallback;
194 bool mResolvePending;
197 } // namespace dom
198 } // namespace mozilla
200 #endif // mozilla_dom_Promise_h