Bug 1550519 - Show a translucent parent highlight when a subgrid is highlighted....
[gecko.git] / dom / promise / Promise-inl.h
blob560a5f9c8921423ec04586960dd6618ec44b65db
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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_Promise_inl_h
8 #define mozilla_dom_Promise_inl_h
10 #include "mozilla/TupleCycleCollection.h"
11 #include "mozilla/TypeTraits.h"
12 #include "mozilla/ResultExtensions.h"
13 #include "mozilla/dom/PromiseNativeHandler.h"
15 namespace mozilla {
16 namespace dom {
18 class PromiseNativeThenHandlerBase : public PromiseNativeHandler {
19 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
20 NS_DECL_CYCLE_COLLECTION_CLASS(PromiseNativeThenHandlerBase)
22 PromiseNativeThenHandlerBase(Promise& aPromise) : mPromise(&aPromise) {}
24 void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
26 void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
28 protected:
29 virtual ~PromiseNativeThenHandlerBase() = default;
31 virtual already_AddRefed<Promise> CallResolveCallback(
32 JSContext* aCx, JS::Handle<JS::Value> aValue) = 0;
34 virtual void Traverse(nsCycleCollectionTraversalCallback&) = 0;
35 virtual void Unlink() = 0;
37 RefPtr<Promise> mPromise;
40 namespace {
42 template <typename T,
43 bool = IsRefcounted<typename RemovePointer<T>::Type>::value,
44 bool = (IsConvertible<T, nsISupports*>::value ||
45 IsConvertible<T*, nsISupports*>::value)>
46 struct StorageTypeHelper {
47 using Type = T;
50 template <typename T>
51 struct StorageTypeHelper<T, true, true> {
52 using Type = nsCOMPtr<T>;
55 template <typename T>
56 struct StorageTypeHelper<nsCOMPtr<T>, true, true> {
57 using Type = nsCOMPtr<T>;
60 template <typename T>
61 struct StorageTypeHelper<T*, true, false> {
62 using Type = RefPtr<T>;
65 template <template <typename> class SmartPtr, typename T>
66 struct StorageTypeHelper<SmartPtr<T>, true, false>
67 : EnableIf<IsConvertible<SmartPtr<T>, T*>::value, RefPtr<T>> {};
69 template <typename T>
70 using StorageType = typename StorageTypeHelper<typename Decay<T>::Type>::Type;
72 // Helpers to choose the correct argument type based on the storage type. Smart
73 // pointers are converted to the corresponding raw pointer type. Everything else
74 // is passed by move reference.
76 // Note: We can't just use std::forward for this because the input type may be a
77 // raw pointer which does not match the argument type, and while the
78 // spec-compliant behavior there should still give us the expected results, MSVC
79 // considers it an illegal use of std::forward.
80 template <template <typename> class SmartPtr, typename T>
81 decltype(DeclVal<SmartPtr<T>>().get()) ArgType(SmartPtr<T>& aVal) {
82 return aVal.get();
85 template <typename T>
86 T&& ArgType(T& aVal) {
87 return std::move(aVal);
90 using ::ImplCycleCollectionUnlink;
92 template <typename Callback, typename... Args>
93 class NativeThenHandler final : public PromiseNativeThenHandlerBase {
94 public:
95 NativeThenHandler(Promise& aPromise, Callback&& aOnResolve, Args&&... aArgs)
96 : PromiseNativeThenHandlerBase(aPromise),
97 mOnResolve(std::forward<Callback>(aOnResolve)),
98 mArgs(std::forward<Args>(aArgs)...) {}
100 protected:
101 void Traverse(nsCycleCollectionTraversalCallback& cb) override {
102 auto* tmp = this;
103 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArgs)
106 void Unlink() override {
107 auto* tmp = this;
108 NS_IMPL_CYCLE_COLLECTION_UNLINK(mArgs)
111 already_AddRefed<Promise> CallResolveCallback(
112 JSContext* aCx, JS::Handle<JS::Value> aValue) override {
113 return CallCallback(aCx, mOnResolve, aValue);
116 template <size_t... Indices>
117 already_AddRefed<Promise> CallCallback(JSContext* aCx,
118 const Callback& aHandler,
119 JS::Handle<JS::Value> aValue,
120 std::index_sequence<Indices...>) {
121 return mOnResolve(aCx, aValue, ArgType(Get<Indices>(mArgs))...);
124 already_AddRefed<Promise> CallCallback(JSContext* aCx,
125 const Callback& aHandler,
126 JS::Handle<JS::Value> aValue) {
127 return CallCallback(aCx, aHandler, aValue,
128 std::index_sequence_for<Args...>{});
131 Callback mOnResolve;
133 Tuple<StorageType<Args>...> mArgs;
136 } // anonymous namespace
138 template <typename Callback, typename... Args>
139 Promise::ThenResult<Callback, Args...> Promise::ThenWithCycleCollectedArgs(
140 Callback&& aOnResolve, Args&&... aArgs) {
141 using HandlerType = NativeThenHandler<Callback, Args...>;
143 ErrorResult rv;
144 RefPtr<Promise> promise = Promise::Create(GetParentObject(), rv);
145 if (rv.Failed()) {
146 return Err(rv.StealNSResult());
149 auto* handler =
150 new (fallible) HandlerType(*promise, std::forward<Callback>(aOnResolve),
151 std::forward<Args>(aArgs)...);
153 if (!handler) {
154 return Err(NS_ERROR_OUT_OF_MEMORY);
157 AppendNativeHandler(handler);
158 return std::move(promise);
161 } // namespace dom
162 } // namespace mozilla
164 #endif // mozilla_dom_Promise_inl_h