Chromium Code Reviews| Index: Source/bindings/core/v8/CallbackPromiseAdapter.h |
| diff --git a/Source/bindings/core/v8/CallbackPromiseAdapter.h b/Source/bindings/core/v8/CallbackPromiseAdapter.h |
| index 3f37736c6237b6608748e1e3548b2519712220f0..07d8a962d5c4049ec00843ff73c3f49047d34a61 100644 |
| --- a/Source/bindings/core/v8/CallbackPromiseAdapter.h |
| +++ b/Source/bindings/core/v8/CallbackPromiseAdapter.h |
| @@ -36,11 +36,57 @@ |
| #include "public/platform/WebPassOwnPtr.h" |
| #include "wtf/OwnPtr.h" |
| #include "wtf/PassOwnPtr.h" |
| +#include "wtf/TypeTraits.h" |
| namespace blink { |
| -class CallbackPromiseAdapterBase { |
| -public: |
| +// CallbackPromiseAdapter is a WebCallbacks subclass and resolves / rejects the |
| +// stored resolver when onSuccess / onError is called, respectively. |
| +// |
| +// Basically CallbackPromiseAdapter<S, T> is a subclass of |
| +// WebCallbacks<S::WebType, T::WebType>. There are some exceptions: |
| +// - If S or T don't have WebType (e.g. S = bool), the trivial WebType holder |
|
kinuko
2015/07/27 05:59:00
nit: 'the trivial WebType holder' -> 'a default We
yhirano
2015/07/27 06:10:27
Done.
|
| +// is used. For example, CallbackPromiseAdapter<bool, void> is a subclass of |
|
kinuko
2015/07/27 05:59:00
'is a' -> 'can be a' ?
yhirano
2015/07/27 06:10:27
Why? There is no way to have bool and void have th
kinuko
2015/07/27 07:43:54
Ok, this was impossible before so my mental model
|
| +// WebCallbacks<bool, void>. |
| +// - If a WebType is OwnPtr<T>, its corresponding type parameter on |
| +// WebCallbacks is WebPassOwnPtr<T>, because WebCallbacks is exposed to |
|
kinuko
2015/07/27 05:59:00
'is' -> 'must be' ?
yhirano
2015/07/27 06:10:27
Done.
|
| +// Chromium. |
| +// |
| +// When onSuccess is called with a S::WebType value, the value is passed to |
| +// S::take and the resolver is resolved with its return value. Ditto for |
| +// onError. |
| +// |
| +// ScriptPromiseResolver::resolve / reject will not be called when the execution |
| +// context is stopped. |
| +// |
| +// In order to implemented the above exceptions, we have template classes below. |
| +// OnSuccess and OnError provide onSuccess and onError implementation, and there |
| +// are utility templates that provide |
| +// - OwnPtr - WebPassOwnPtr translation ([Web]PassType[Impl], adopt, pass), |
| +// - trivial WebType holder (TrivialWebTypeHolder). |
| + |
| +namespace internal { |
| + |
| +// This template is placed outside of CallbackPromiseAdapterInternal because |
| +// explicit specialization is forbidden in a class scope. |
| +template <typename T> |
| +struct CallbackPromiseAdapterTrivialWebTypeHolder { |
| + using WebType = T; |
| + static T take(ScriptPromiseResolver*, const T& x) { return x; } |
| +}; |
| +template <> |
| +struct CallbackPromiseAdapterTrivialWebTypeHolder<void> { |
| + using WebType = void; |
| +}; |
| + |
| +class CallbackPromiseAdapterInternal { |
| +private: |
| + template <typename T> static T webTypeHolderMatcher(typename WTF::RemoveReference<typename T::WebType>::Type*); |
| + template <typename T> static CallbackPromiseAdapterTrivialWebTypeHolder<T> webTypeHolderMatcher(...); |
| + template <typename T> using WebTypeHolder = decltype(webTypeHolderMatcher<T>(nullptr)); |
| + |
| + // The following templates should be gone when the repositories are merged |
| + // and we can use C++11 libraries. |
| template <typename T> |
| struct PassTypeImpl { |
| using Type = T; |
| @@ -49,7 +95,6 @@ public: |
| struct PassTypeImpl<OwnPtr<T>> { |
| using Type = PassOwnPtr<T>; |
| }; |
| - |
| template <typename T> |
| struct WebPassTypeImpl { |
| using Type = T; |
| @@ -58,206 +103,87 @@ public: |
| struct WebPassTypeImpl<OwnPtr<T>> { |
| using Type = WebPassOwnPtr<T>; |
| }; |
| + template <typename T> using PassType = typename PassTypeImpl<T>::Type; |
| + template <typename T> using WebPassType = typename WebPassTypeImpl<T>::Type; |
| + template <typename T> static T& adopt(T& x) { return x; } |
| + template <typename T> static PassOwnPtr<T> adopt(WebPassOwnPtr<T>& x) { return x.release(); } |
| + template <typename T> static PassType<T> pass(T& x) { return x; } |
| + template <typename T> static PassOwnPtr<T> pass(OwnPtr<T>& x) { return x.release(); } |
| + |
| + template <typename S, typename T> |
| + class Base : public WebCallbacks<WebPassType<typename S::WebType>, WebPassType<typename T::WebType>> { |
| + public: |
| + explicit Base(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) : m_resolver(resolver) {} |
| + ScriptPromiseResolver* resolver() { return m_resolver.get(); } |
| + |
| + private: |
| + RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver; |
| + }; |
| + template <typename S, typename T> |
| + class OnSuccess : public Base<S, T> { |
| + public: |
| + explicit OnSuccess(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) : Base<S, T>(resolver) {} |
| + void onSuccess(WebPassType<typename S::WebType> r) override |
| + { |
| + typename S::WebType result(adopt(r)); |
| + ScriptPromiseResolver* resolver = this->resolver(); |
| + if (!resolver->executionContext() || resolver->executionContext()->activeDOMObjectsAreStopped()) |
| + return; |
| + resolver->resolve(S::take(resolver, pass(result))); |
| + } |
| + }; |
| template <typename T> |
| - using PassType = typename PassTypeImpl<T>::Type; |
| - template <typename T> |
| - using WebPassType = typename WebPassTypeImpl<T>::Type; |
| - template <typename T> |
| - static T& adopt(T& x) { return x; } |
| - template <typename T> |
| - static PassOwnPtr<T> adopt(WebPassOwnPtr<T>& x) { return x.release(); } |
| - template <typename T> |
| - static PassType<T> pass(T& x) { return x; } |
| - template <typename T> |
| - static PassOwnPtr<T> pass(OwnPtr<T>& x) { return x.release(); } |
| -}; |
| - |
| - |
| -// TODO(yhirano): Add comments. |
| -template<typename S, typename T> |
| -class CallbackPromiseAdapter final |
| - : public WebCallbacks<typename CallbackPromiseAdapterBase::WebPassType<typename S::WebType>, typename CallbackPromiseAdapterBase::WebPassType<typename T::WebType>>, public CallbackPromiseAdapterBase { |
| - WTF_MAKE_NONCOPYABLE(CallbackPromiseAdapter); |
| -public: |
| - explicit CallbackPromiseAdapter(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) |
| - : m_resolver(resolver) |
| - { |
| - ASSERT(m_resolver); |
| - } |
| - ~CallbackPromiseAdapter() override { } |
| - |
| - void onSuccess(WebPassType<typename S::WebType> r) override |
| - { |
| - typename S::WebType result(adopt(r)); |
| - if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) |
| - return; |
| - m_resolver->resolve(S::take(m_resolver.get(), pass(result))); |
| - } |
| - |
| - void onError(WebPassType<typename T::WebType> e) override |
| - { |
| - typename T::WebType error(adopt(e)); |
| - if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) |
| - return; |
| - m_resolver->reject(T::take(m_resolver.get(), pass(error))); |
| - } |
| - |
| -private: |
| - RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver; |
| -}; |
| - |
| -template<typename T> |
| -class CallbackPromiseAdapter<void, T> final : public WebCallbacks<void, typename CallbackPromiseAdapterBase::WebPassType<typename T::WebType>>, public CallbackPromiseAdapterBase { |
| - WTF_MAKE_NONCOPYABLE(CallbackPromiseAdapter); |
| -public: |
| - explicit CallbackPromiseAdapter(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) |
| - : m_resolver(resolver) |
| - { |
| - ASSERT(m_resolver); |
| - } |
| - ~CallbackPromiseAdapter() override { } |
| - |
| - void onSuccess() override |
| - { |
| - if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) |
| - return; |
| - m_resolver->resolve(); |
| - } |
| - |
| - void onError(WebPassType<typename T::WebType> e) override |
| - { |
| - typename T::WebType error(adopt(e)); |
| - if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) |
| - return; |
| - m_resolver->reject(T::take(m_resolver.get(), pass(error))); |
| - } |
| - |
| -private: |
| - RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver; |
| -}; |
| - |
| -template<typename S> |
| -class CallbackPromiseAdapter<S, void> final : public WebCallbacks<typename CallbackPromiseAdapterBase::WebPassType<typename S::WebType>, void>, public CallbackPromiseAdapterBase { |
| - WTF_MAKE_NONCOPYABLE(CallbackPromiseAdapter); |
| -public: |
| - explicit CallbackPromiseAdapter(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) |
| - : m_resolver(resolver) |
| - { |
| - ASSERT(m_resolver); |
| - } |
| - ~CallbackPromiseAdapter() override { } |
| - |
| - void onSuccess(WebPassType<typename S::WebType> r) override |
| - { |
| - typename S::WebType result(adopt(r)); |
| - if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) |
| - return; |
| - m_resolver->resolve(S::take(m_resolver.get(), pass(result))); |
| - } |
| - |
| - void onError() override |
| - { |
| - if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) |
| - return; |
| - m_resolver->reject(); |
| - } |
| - |
| -private: |
| - RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver; |
| -}; |
| - |
| -template<typename T> |
| -class CallbackPromiseAdapter<bool, T> final : public WebCallbacks<bool*, typename CallbackPromiseAdapterBase::WebPassType<typename T::WebType>>, public CallbackPromiseAdapterBase { |
| - WTF_MAKE_NONCOPYABLE(CallbackPromiseAdapter); |
| -public: |
| - explicit CallbackPromiseAdapter(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) |
| - : m_resolver(resolver) |
| - { |
| - ASSERT(m_resolver); |
| - } |
| - ~CallbackPromiseAdapter() override { } |
| - |
| - // TODO(nhiroki): onSuccess should take ownership of a bool object for |
| - // consistency. (http://crbug.com/493531) |
| - void onSuccess(bool* result) override |
| - { |
| - if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) |
| - return; |
| - m_resolver->resolve(*result); |
| - } |
| - |
| - void onError(WebPassType<typename T::WebType> e) override |
| - { |
| - typename T::WebType error(adopt(e)); |
| - if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) |
| - return; |
| - m_resolver->reject(T::take(m_resolver.get(), pass(error))); |
| - } |
| - |
| -private: |
| - RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver; |
| -}; |
| + class OnSuccess<WebTypeHolder<void>, T> : public Base<WebTypeHolder<void>, T> { |
| + public: |
| + explicit OnSuccess(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) : Base<WebTypeHolder<void>, T>(resolver) {} |
| + void onSuccess() override |
| + { |
| + ScriptPromiseResolver* resolver = this->resolver(); |
| + if (!resolver->executionContext() || resolver->executionContext()->activeDOMObjectsAreStopped()) |
| + return; |
| + resolver->resolve(); |
| + } |
| + }; |
| + template <typename S, typename T> |
| + class OnError : public OnSuccess<S, T> { |
| + public: |
| + explicit OnError(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) : OnSuccess<S, T>(resolver) {} |
| + void onError(WebPassType<typename T::WebType> e) override |
| + { |
| + typename T::WebType result(adopt(e)); |
| + ScriptPromiseResolver* resolver = this->resolver(); |
| + if (!resolver->executionContext() || resolver->executionContext()->activeDOMObjectsAreStopped()) |
| + return; |
| + resolver->reject(T::take(resolver, pass(result))); |
| + } |
| + }; |
| + template <typename S> |
| + class OnError<S, WebTypeHolder<void>> : public OnSuccess<S, WebTypeHolder<void>> { |
| + public: |
| + explicit OnError(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) : OnSuccess<S, WebTypeHolder<void>>(resolver) {} |
| + void onError() override |
| + { |
| + ScriptPromiseResolver* resolver = this->resolver(); |
| + if (!resolver->executionContext() || resolver->executionContext()->activeDOMObjectsAreStopped()) |
| + return; |
| + resolver->reject(); |
| + } |
| + }; |
| -template<> |
| -class CallbackPromiseAdapter<void, void> final : public WebCallbacks<void, void>, public CallbackPromiseAdapterBase { |
| - WTF_MAKE_NONCOPYABLE(CallbackPromiseAdapter); |
| public: |
| - explicit CallbackPromiseAdapter(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) |
| - : m_resolver(resolver) |
| - { |
| - ASSERT(m_resolver); |
| - } |
| - ~CallbackPromiseAdapter() override { } |
| - |
| - void onSuccess() override |
| - { |
| - if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) |
| - return; |
| - m_resolver->resolve(); |
| - } |
| - |
| - void onError() override |
| - { |
| - if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) |
| - return; |
| - m_resolver->reject(); |
| - } |
| - |
| -private: |
| - RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver; |
| + template <typename S, typename T> |
| + class CallbackPromiseAdapter final : public OnError<WebTypeHolder<S>, WebTypeHolder<T>> { |
| + WTF_MAKE_NONCOPYABLE(CallbackPromiseAdapter); |
| + public: |
| + explicit CallbackPromiseAdapter(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) : OnError<WebTypeHolder<S>, WebTypeHolder<T>>(resolver) {} |
| + }; |
| }; |
| -template<> |
| -class CallbackPromiseAdapter<bool, void> final : public WebCallbacks<bool*, void>, public CallbackPromiseAdapterBase { |
| - WTF_MAKE_NONCOPYABLE(CallbackPromiseAdapter); |
| -public: |
| - explicit CallbackPromiseAdapter(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) |
| - : m_resolver(resolver) |
| - { |
| - ASSERT(m_resolver); |
| - } |
| - ~CallbackPromiseAdapter() override { } |
| - |
| - // TODO(nhiroki): onSuccess should take ownership of a bool object for |
| - // consistency. (http://crbug.com/493531) |
| - void onSuccess(bool* result) override |
| - { |
| - if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) |
| - return; |
| - m_resolver->resolve(*result); |
| - } |
| +} // namespace internal |
| - void onError() override |
| - { |
| - if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) |
| - return; |
| - m_resolver->reject(); |
| - } |
| - |
| -private: |
| - RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver; |
| -}; |
| +template <typename S, typename T> |
| +using CallbackPromiseAdapter = internal::CallbackPromiseAdapterInternal::CallbackPromiseAdapter<S, T>; |
| } // namespace blink |