DOMPromise should only restrict the resolution type
authoryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 17 May 2016 10:20:11 +0000 (10:20 +0000)
committeryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 17 May 2016 10:20:11 +0000 (10:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=157307

Reviewed by Darin Adler.

Source/WebCore:

Removing from DOMPromise the rejection template parameter.
Supported rejection types are integers (Exception codes) and DOM objects (DOMError typically).

Updated DeferredWrapper to accept Ref<>&& and RefPtr<>&&.
Relanding without touching JSDOMBinding.h as this seemed to be impacting performances.

Changes also allow in most cases to remove the need for explictly declaring the
rejection/resolution type.

Minor refactoring of FontFaceSet promise handling to use DOMPromise in lieu of DeferredWrapper.

Covered by existing tests.
Changes should not be visible from user scripts.

* Modules/fetch/FetchBody.cpp:
(WebCore::FetchBody::consume):
(WebCore::FetchBody::consumeText):
(WebCore::blobFromArrayBuffer):
(WebCore::FetchBody::loadingFailed):
* Modules/fetch/FetchBody.h:
(WebCore::FetchBody::formData):
* Modules/fetch/FetchBodyOwner.cpp:
(WebCore::FetchBodyOwner::arrayBuffer):
(WebCore::FetchBodyOwner::blob):
(WebCore::FetchBodyOwner::formData):
(WebCore::FetchBodyOwner::json):
(WebCore::FetchBodyOwner::text):
* Modules/fetch/FetchResponse.cpp:
(WebCore::FetchResponse::BodyLoader::didReceiveResponse):
* Modules/fetch/FetchResponse.h:
* Modules/mediastream/MediaDevices.h:
* Modules/mediastream/PeerConnectionBackend.h:
* Modules/mediastream/UserMediaRequest.cpp:
(WebCore::UserMediaRequest::didCreateStream):
* Modules/streams/ReadableStreamSource.h:
* Modules/webaudio/AudioContext.h:
* bindings/js/JSDOMPromise.cpp:
(WebCore::fulfillPromiseWithJSON):
* bindings/js/JSDOMPromise.h:
(WebCore::TypeInspector::decltype):
(WebCore::TypeInspector::testIsVector):
(WebCore::TypeInspector::testIsRefOrRefPtr):
(WebCore::DeferredWrapper::resolve):
(WebCore::DeferredWrapper::reject):
(WebCore::DOMPromise::resolve):
(WebCore::DOMPromise::reject):
(WebCore::DeferredWrapper::resolveWithValue):
(WebCore::DeferredWrapper::rejectWithValue):
(WebCore::callPromiseFunction):
* bindings/js/JSSubtleCryptoCustom.cpp:
(WebCore::JSSubtleCrypto::importKey):
(WebCore::JSSubtleCrypto::unwrapKey):
* css/FontFace.h:
* css/FontFaceSet.cpp:
(WebCore::FontFaceSet::PendingPromise::PendingPromise):
(WebCore::FontFaceSet::load):
(WebCore::FontFaceSet::registerReady):
* css/FontFaceSet.h:
* html/HTMLMediaElement.h:

Source/WTF:

* wtf/Ref.h: Adding static constexpr to ease detection of Ref for templates.
* wtf/RefPtr.h: Ditto.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@201013 268f45cc-cd09-0410-ab3c-d52691b4dbfc

21 files changed:
Source/WTF/ChangeLog
Source/WTF/wtf/Ref.h
Source/WTF/wtf/RefPtr.h
Source/WebCore/ChangeLog
Source/WebCore/Modules/fetch/FetchBody.cpp
Source/WebCore/Modules/fetch/FetchBody.h
Source/WebCore/Modules/fetch/FetchBodyOwner.cpp
Source/WebCore/Modules/fetch/FetchResponse.cpp
Source/WebCore/Modules/fetch/FetchResponse.h
Source/WebCore/Modules/mediastream/MediaDevices.h
Source/WebCore/Modules/mediastream/PeerConnectionBackend.h
Source/WebCore/Modules/mediastream/UserMediaRequest.cpp
Source/WebCore/Modules/streams/ReadableStreamSource.h
Source/WebCore/Modules/webaudio/AudioContext.h
Source/WebCore/bindings/js/JSDOMPromise.cpp
Source/WebCore/bindings/js/JSDOMPromise.h
Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp
Source/WebCore/css/FontFace.h
Source/WebCore/css/FontFaceSet.cpp
Source/WebCore/css/FontFaceSet.h
Source/WebCore/html/HTMLMediaElement.h

index cfee5dc..52f69d7 100644 (file)
@@ -1,3 +1,13 @@
+2016-05-17  Youenn Fablet  <youenn.fablet@crf.canon.fr>
+
+        DOMPromise should only restrict the resolution type
+        https://bugs.webkit.org/show_bug.cgi?id=157307
+
+        Reviewed by Darin Adler.
+
+        * wtf/Ref.h: Adding static constexpr to ease detection of Ref for templates.
+        * wtf/RefPtr.h: Ditto.
+
 2016-05-16  Michael Saboff  <msaboff@apple.com>
 
         ARMV7K: Crash at JavaScriptCore: WTF::ScopedLambdaFunctor<bool
index 7b4a48b..3ba9dd7 100644 (file)
@@ -46,6 +46,8 @@ template<typename T> Ref<T> adoptRef(T&);
 
 template<typename T> class Ref {
 public:
+    static constexpr bool isRef = true;
+
     ~Ref()
     {
 #if ASAN_ENABLED
index ca446f4..ed51ee6 100644 (file)
@@ -39,6 +39,8 @@ public:
     typedef T ValueType;
     typedef ValueType* PtrType;
 
+    static constexpr bool isRefPtr = true;
+
     ALWAYS_INLINE RefPtr() : m_ptr(nullptr) { }
     ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
     ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); }
index 3d50678..7568cee 100644 (file)
@@ -1,3 +1,70 @@
+2016-05-17  Youenn Fablet  <youenn.fablet@crf.canon.fr>
+
+        DOMPromise should only restrict the resolution type
+        https://bugs.webkit.org/show_bug.cgi?id=157307
+
+        Reviewed by Darin Adler.
+
+        Removing from DOMPromise the rejection template parameter.
+        Supported rejection types are integers (Exception codes) and DOM objects (DOMError typically).
+
+        Updated DeferredWrapper to accept Ref<>&& and RefPtr<>&&.
+        Relanding without touching JSDOMBinding.h as this seemed to be impacting performances.
+
+        Changes also allow in most cases to remove the need for explictly declaring the
+        rejection/resolution type.
+
+        Minor refactoring of FontFaceSet promise handling to use DOMPromise in lieu of DeferredWrapper.
+
+        Covered by existing tests.
+        Changes should not be visible from user scripts.
+
+        * Modules/fetch/FetchBody.cpp:
+        (WebCore::FetchBody::consume):
+        (WebCore::FetchBody::consumeText):
+        (WebCore::blobFromArrayBuffer):
+        (WebCore::FetchBody::loadingFailed):
+        * Modules/fetch/FetchBody.h:
+        (WebCore::FetchBody::formData):
+        * Modules/fetch/FetchBodyOwner.cpp:
+        (WebCore::FetchBodyOwner::arrayBuffer):
+        (WebCore::FetchBodyOwner::blob):
+        (WebCore::FetchBodyOwner::formData):
+        (WebCore::FetchBodyOwner::json):
+        (WebCore::FetchBodyOwner::text):
+        * Modules/fetch/FetchResponse.cpp:
+        (WebCore::FetchResponse::BodyLoader::didReceiveResponse):
+        * Modules/fetch/FetchResponse.h:
+        * Modules/mediastream/MediaDevices.h:
+        * Modules/mediastream/PeerConnectionBackend.h:
+        * Modules/mediastream/UserMediaRequest.cpp:
+        (WebCore::UserMediaRequest::didCreateStream):
+        * Modules/streams/ReadableStreamSource.h:
+        * Modules/webaudio/AudioContext.h:
+        * bindings/js/JSDOMPromise.cpp:
+        (WebCore::fulfillPromiseWithJSON):
+        * bindings/js/JSDOMPromise.h:
+        (WebCore::TypeInspector::decltype):
+        (WebCore::TypeInspector::testIsVector):
+        (WebCore::TypeInspector::testIsRefOrRefPtr):
+        (WebCore::DeferredWrapper::resolve):
+        (WebCore::DeferredWrapper::reject):
+        (WebCore::DOMPromise::resolve):
+        (WebCore::DOMPromise::reject):
+        (WebCore::DeferredWrapper::resolveWithValue):
+        (WebCore::DeferredWrapper::rejectWithValue):
+        (WebCore::callPromiseFunction):
+        * bindings/js/JSSubtleCryptoCustom.cpp:
+        (WebCore::JSSubtleCrypto::importKey):
+        (WebCore::JSSubtleCrypto::unwrapKey):
+        * css/FontFace.h:
+        * css/FontFaceSet.cpp:
+        (WebCore::FontFaceSet::PendingPromise::PendingPromise):
+        (WebCore::FontFaceSet::load):
+        (WebCore::FontFaceSet::registerReady):
+        * css/FontFaceSet.h:
+        * html/HTMLMediaElement.h:
+
 2016-05-16  Alex Christensen  <achristensen@webkit.org>
 
         Modernize CSS Parser
index 10a11f1..46ac45d 100644 (file)
@@ -43,7 +43,7 @@
 
 namespace WebCore {
 
-static RefPtr<Blob> blobFromArrayBuffer(ArrayBuffer*, const String&);
+static Ref<Blob> blobFromArrayBuffer(ArrayBuffer*, const String&);
 
 FetchBody::FetchBody(Ref<Blob>&& blob)
     : m_type(Type::Blob)
@@ -141,7 +141,7 @@ void FetchBody::consume(FetchBodyOwner& owner, Consumer::Type type, DeferredWrap
     }
 
     // FIXME: Support other types.
-    promise.reject<ExceptionCode>(0);
+    promise.reject(0);
 }
 
 #if ENABLE(STREAMS_API)
@@ -200,7 +200,7 @@ void FetchBody::consumeText(Consumer::Type type, DeferredWrapper& promise)
         return;
     }
     String contentType = Blob::normalizedContentType(extractMIMETypeFromMediaType(m_mimeType));
-    promise.resolve<RefPtr<Blob>>(Blob::create(extractFromText(), contentType));
+    promise.resolve(Blob::create(extractFromText(), contentType));
 }
 
 FetchLoader::Type FetchBody::loadingType(Consumer::Type type)
@@ -236,7 +236,7 @@ Vector<uint8_t> FetchBody::extractFromText() const
     return value;
 }
 
-static inline RefPtr<Blob> blobFromArrayBuffer(ArrayBuffer* buffer, const String& contentType)
+static inline Ref<Blob> blobFromArrayBuffer(ArrayBuffer* buffer, const String& contentType)
 {
     if (!buffer)
         return Blob::create(Vector<uint8_t>(), contentType);
@@ -259,7 +259,7 @@ void FetchBody::fulfillTextPromise(FetchBody::Consumer::Type type, const String&
 void FetchBody::loadingFailed()
 {
     ASSERT(m_consumer);
-    m_consumer->promise.reject<ExceptionCode>(0);
+    m_consumer->promise.reject(0);
     m_consumer = Nullopt;
 }
 
index 046010a..56f3dfd 100644 (file)
@@ -53,7 +53,7 @@ public:
     void blob(FetchBodyOwner&, DeferredWrapper&&);
     void json(FetchBodyOwner&, DeferredWrapper&&);
     void text(FetchBodyOwner&, DeferredWrapper&&);
-    void formData(FetchBodyOwner&, DeferredWrapper&& promise) { promise.reject<ExceptionCode>(0); }
+    void formData(FetchBodyOwner&, DeferredWrapper&& promise) { promise.reject(0); }
 
 #if ENABLE(STREAMS_API)
     void consumeAsStream(FetchBodyOwner&, FetchResponseSource&);
index caf4ac8..96c04c3 100644 (file)
@@ -75,7 +75,7 @@ void FetchBodyOwner::arrayBuffer(DeferredWrapper&& promise)
         return;
     }
     if (isDisturbed()) {
-        promise.reject<ExceptionCode>(TypeError);
+        promise.reject(TypeError);
         return;
     }
     m_isDisturbed = true;
@@ -85,11 +85,11 @@ void FetchBodyOwner::arrayBuffer(DeferredWrapper&& promise)
 void FetchBodyOwner::blob(DeferredWrapper&& promise)
 {
     if (m_body.isEmpty()) {
-        promise.resolve<RefPtr<Blob>>(Blob::create());
+        promise.resolve(Blob::create());
         return;
     }
     if (isDisturbed()) {
-        promise.reject<ExceptionCode>(TypeError);
+        promise.reject(TypeError);
         return;
     }
     m_isDisturbed = true;
@@ -99,11 +99,11 @@ void FetchBodyOwner::blob(DeferredWrapper&& promise)
 void FetchBodyOwner::formData(DeferredWrapper&& promise)
 {
     if (m_body.isEmpty()) {
-        promise.reject<ExceptionCode>(0);
+        promise.reject(0);
         return;
     }
     if (isDisturbed()) {
-        promise.reject<ExceptionCode>(TypeError);
+        promise.reject(TypeError);
         return;
     }
     m_isDisturbed = true;
@@ -113,11 +113,11 @@ void FetchBodyOwner::formData(DeferredWrapper&& promise)
 void FetchBodyOwner::json(DeferredWrapper&& promise)
 {
     if (m_body.isEmpty()) {
-        promise.reject<ExceptionCode>(SYNTAX_ERR);
+        promise.reject(SYNTAX_ERR);
         return;
     }
     if (isDisturbed()) {
-        promise.reject<ExceptionCode>(TypeError);
+        promise.reject(TypeError);
         return;
     }
     m_isDisturbed = true;
@@ -131,7 +131,7 @@ void FetchBodyOwner::text(DeferredWrapper&& promise)
         return;
     }
     if (isDisturbed()) {
-        promise.reject<ExceptionCode>(TypeError);
+        promise.reject(TypeError);
         return;
     }
     m_isDisturbed = true;
index c5faafc..6f38902 100644 (file)
@@ -213,7 +213,7 @@ void FetchResponse::BodyLoader::didReceiveResponse(const ResourceResponse& resou
     m_response.m_response = resourceResponse;
     m_response.m_headers->filterAndFill(resourceResponse.httpHeaderFields(), FetchHeaders::Guard::Response);
 
-    std::exchange(m_promise, Nullopt)->resolve(&m_response);
+    std::exchange(m_promise, Nullopt)->resolve(m_response);
 }
 
 void FetchResponse::BodyLoader::didReceiveData(const char* data, size_t size)
index 7e48b03..ed24711 100644 (file)
@@ -54,7 +54,7 @@ public:
     static Ref<FetchResponse> error(ScriptExecutionContext&);
     static RefPtr<FetchResponse> redirect(ScriptExecutionContext&, const String&, int, ExceptionCode&);
 
-    using FetchPromise = DOMPromise<RefPtr<FetchResponse>, ExceptionCode>;
+    using FetchPromise = DOMPromise<FetchResponse>;
     static void fetch(ScriptExecutionContext&, FetchRequest&, const Dictionary&, FetchPromise&&);
     static void fetch(ScriptExecutionContext&, const String&, const Dictionary&, FetchPromise&&);
 
index 702272d..c48d860 100644 (file)
@@ -58,8 +58,8 @@ public:
 
     Document* document() const;
 
-    typedef DOMPromise<RefPtr<MediaStream>, RefPtr<NavigatorUserMediaError>> Promise;
-    typedef DOMPromise<MediaDeviceInfoVector, ExceptionCode> EnumerateDevicesPromise;
+    typedef DOMPromise<MediaStream> Promise;
+    typedef DOMPromise<MediaDeviceInfoVector> EnumerateDevicesPromise;
 
     void getUserMedia(const Dictionary&, Promise&&, ExceptionCode&) const;
     void enumerateDevices(EnumerateDevicesPromise&&, ExceptionCode&) const;
index 50de930..bfff44e 100644 (file)
@@ -53,9 +53,9 @@ class RTCStatsResponse;
 class ScriptExecutionContext;
 
 namespace PeerConnection {
-typedef DOMPromise<RefPtr<RTCSessionDescription>, RefPtr<DOMError>> SessionDescriptionPromise;
-typedef DOMPromise<std::nullptr_t, RefPtr<DOMError>> VoidPromise;
-typedef DOMPromise<RefPtr<RTCStatsResponse>, RefPtr<DOMError>> StatsPromise;
+typedef DOMPromise<RTCSessionDescription> SessionDescriptionPromise;
+typedef DOMPromise<std::nullptr_t> VoidPromise;
+typedef DOMPromise<RTCStatsResponse> StatsPromise;
 }
 
 class PeerConnectionBackendClient {
index bb08375..e252a55 100644 (file)
@@ -172,7 +172,7 @@ void UserMediaRequest::didCreateStream(PassRefPtr<MediaStreamPrivate> privateStr
         return;
 
     // 4 - Create the MediaStream and pass it to the success callback.
-    RefPtr<MediaStream> stream = MediaStream::create(*m_scriptExecutionContext, privateStream);
+    Ref<MediaStream> stream = MediaStream::create(*m_scriptExecutionContext, privateStream);
     if (m_audioConstraints) {
         for (auto& track : stream->getAudioTracks()) {
             track->applyConstraints(*m_audioConstraints);
index 0fd16f3..087b45c 100644 (file)
@@ -44,7 +44,7 @@ class ReadableStreamSource : public RefCounted<ReadableStreamSource> {
 public:
     virtual ~ReadableStreamSource() { }
 
-    typedef DOMPromise<std::nullptr_t, ExceptionCode> Promise;
+    typedef DOMPromise<std::nullptr_t> Promise;
 
     void start(ReadableStreamController&&, Promise&&);
     void cancel(JSC::JSValue);
index 858f647..16b2b3c 100644 (file)
@@ -109,7 +109,7 @@ public:
     using ActiveDOMObject::suspend;
     using ActiveDOMObject::resume;
 
-    typedef DOMPromise<std::nullptr_t, ExceptionCode> Promise;
+    typedef DOMPromise<std::nullptr_t> Promise;
 
     void suspend(Promise&&);
     void resume(Promise&&);
index 896f849..a214b87 100644 (file)
@@ -88,7 +88,7 @@ void fulfillPromiseWithJSON(DeferredWrapper& promise, const String& data)
 {
     JSC::JSValue value = parseAsJSON(promise.globalObject().globalExec(), data);
     if (!value)
-        promise.reject<ExceptionCode>(SYNTAX_ERR);
+        promise.reject(SYNTAX_ERR);
     else
         promise.resolve(value);
 }
index fb51b72..b907773 100644 (file)
 
 namespace WebCore {
 
+template<typename DOMClass>
+struct TypeInspector {
+private:
+    template<typename T> static constexpr auto testIsVector(int) -> decltype(std::declval<T>().shrinkToFit(), bool()) { return true; }
+    template<typename T> static constexpr bool testIsVector(...) { return false; }
+
+    template<typename T> static constexpr auto testIsRef(int) -> decltype(T::isRef) { return true; }
+    template<typename T> static constexpr bool testIsRef(...) { return false; }
+
+    template<typename T> static constexpr auto testIsRefPtr(int) -> decltype(T::isRefPtr) { return true; }
+    template<typename T> static constexpr bool testIsRefPtr(...) { return false; }
+
+public:
+    static constexpr bool isRefOrRefPtr = testIsRef<DOMClass>(0) || testIsRefPtr<DOMClass>(0);
+    static constexpr bool isPassByValueType = std::is_pointer<DOMClass>::value
+        || std::is_same<DOMClass, std::nullptr_t>::value
+        || std::is_same<DOMClass, JSC::JSValue>::value
+        || std::is_same<DOMClass, bool>::value;
+    static constexpr bool isPassByConstRefType = testIsVector<DOMClass>(0)
+        || std::is_same<DOMClass, String>::value;
+};
+
+template<typename DOMClass, typename Enable = void>
+struct PromiseResultInspector {
+public:
+    static constexpr bool passByValue = false;
+    static constexpr bool passByRef = true;
+    static constexpr bool passByURef = false;
+    static constexpr bool passByConstRef = false;
+
+    typedef DOMClass& Type;
+};
+
+template<typename DOMClass>
+struct PromiseResultInspector<DOMClass, typename std::enable_if<TypeInspector<DOMClass>::isPassByValueType>::type> {
+public:
+    static constexpr bool passByValue = true;
+    static constexpr bool passByRef = false;
+    static constexpr bool passByURef = false;
+    static constexpr bool passByConstRef = false;
+
+    typedef DOMClass Type;
+};
+
+template<typename DOMClass>
+struct PromiseResultInspector<DOMClass, typename std::enable_if<TypeInspector<DOMClass>::isPassByConstRefType>::type> {
+public:
+    static constexpr bool passByValue = false;
+    static constexpr bool passByRef = false;
+    static constexpr bool passByURef = false;
+    static constexpr bool passByConstRef = true;
+
+    typedef const DOMClass& Type;
+};
+
+template<typename DOMClass>
+struct PromiseResultInspector<DOMClass, typename std::enable_if<TypeInspector<DOMClass>::isRefOrRefPtr>::type> {
+    static constexpr bool passByValue = false;
+    static constexpr bool passByRef = false;
+    static constexpr bool passByURef = true;
+    static constexpr bool passByConstRef = false;
+};
+
 class DeferredWrapper {
 public:
     DeferredWrapper(JSC::ExecState*, JSDOMGlobalObject*, JSC::JSPromiseDeferred*);
 
-    template<class ResolveResultType>
-    void resolve(const ResolveResultType&);
+    template<class ResolveResultType> typename std::enable_if<PromiseResultInspector<ResolveResultType>::passByValue, void>::type
+    resolve(ResolveResultType result) { resolveWithValue(result); }
+    template<class ResolveResultType> typename std::enable_if<PromiseResultInspector<ResolveResultType>::passByRef, void>::type
+    resolve(ResolveResultType& result) { resolveWithValue(result); }
+    template<class ResolveResultType> typename std::enable_if<PromiseResultInspector<ResolveResultType>::passByURef, void>::type
+    resolve(ResolveResultType&& result) { resolveWithValue(std::forward<ResolveResultType>(result)); }
+    template<class ResolveResultType> typename std::enable_if<PromiseResultInspector<ResolveResultType>::passByConstRef, void>::type
+    resolve(const ResolveResultType& result) { resolveWithValue(result); }
+
+    template<class RejectResultType> typename std::enable_if<PromiseResultInspector<RejectResultType>::passByValue, void>::type
+    reject(RejectResultType result) { rejectWithValue(result); }
+    template<class RejectResultType> typename std::enable_if<PromiseResultInspector<RejectResultType>::passByRef, void>::type
+    reject(RejectResultType& result) { rejectWithValue(result); }
+    template<class RejectResultType> typename std::enable_if<PromiseResultInspector<RejectResultType>::passByURef, void>::type
+    reject(RejectResultType&& result) { rejectWithValue(std::forward<RejectResultType>(result)); }
+    template<class RejectResultType> typename std::enable_if<PromiseResultInspector<RejectResultType>::passByConstRef, void>::type
+    reject(const RejectResultType& result) { rejectWithValue(result); }
 
-    template<class RejectResultType>
-    void reject(const RejectResultType&);
+    void reject(ExceptionCode);
 
     JSDOMGlobalObject& globalObject() const;
     JSC::JSValue promise() const;
@@ -51,6 +128,9 @@ private:
     void resolve(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, m_deferred->resolve(), resolution); }
     void reject(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, m_deferred->reject(), resolution); }
 
+    template<class RejectResultType> void rejectWithValue(RejectResultType&&);
+    template<class ResolveResultType> void resolveWithValue(ResolveResultType&&);
+
     JSC::Strong<JSDOMGlobalObject> m_globalObject;
     JSC::Strong<JSC::JSPromiseDeferred> m_deferred;
 };
@@ -71,7 +151,8 @@ inline JSC::JSValue callPromiseFunction(JSC::ExecState& state, JSC::EncodedJSVal
     return promiseDeferred.promise();
 }
 
-template <typename Value, typename Error>
+// At the moment, Value cannot be a Ref<T> or RefPtr<T>, it should be a DOM class.
+template <typename Value>
 class DOMPromise {
 public:
     DOMPromise(DeferredWrapper&& wrapper) : m_wrapper(WTFMove(wrapper)) { }
@@ -80,105 +161,105 @@ public:
     DOMPromise(const DOMPromise&) = default;
     DOMPromise& operator=(DOMPromise const&) = default;
 
-    void resolve(const Value& value) { m_wrapper.resolve<Value>(value); }
-    void reject(const Error& error) { m_wrapper.reject<Error>(error); }
+    void resolve(typename PromiseResultInspector<Value>::Type value) { m_wrapper.resolve(value); }
+
+    template<typename ErrorType> void reject(ErrorType&& error) { m_wrapper.reject(std::forward<ErrorType>(error)); }
 
 private:
     DeferredWrapper m_wrapper;
 };
 
-template<class ResolveResultType>
-inline void DeferredWrapper::resolve(const ResolveResultType& result)
+inline void DeferredWrapper::reject(ExceptionCode ec)
 {
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
     JSC::JSLockHolder locker(exec);
-    resolve(*exec, toJS(exec, m_globalObject.get(), result));
+    reject(*exec, createDOMException(exec, ec));
 }
 
-template<class RejectResultType>
-inline void DeferredWrapper::reject(const RejectResultType& result)
+template<class ResolveResultType>
+inline void DeferredWrapper::resolveWithValue(ResolveResultType&& result)
 {
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
     JSC::JSLockHolder locker(exec);
-    reject(*exec, toJS(exec, m_globalObject.get(), result));
+    resolve(*exec, toJS(exec, m_globalObject.get(), std::forward<ResolveResultType>(result)));
 }
 
-template<>
-inline void DeferredWrapper::reject(const std::nullptr_t&)
+template<class RejectResultType>
+inline void DeferredWrapper::rejectWithValue(RejectResultType&& result)
 {
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
     JSC::JSLockHolder locker(exec);
-    reject(*exec, JSC::jsNull());
+    reject(*exec, toJS(exec, m_globalObject.get(), std::forward<RejectResultType>(result)));
 }
 
 template<>
-inline void DeferredWrapper::reject(const JSC::JSValue& value)
+inline void DeferredWrapper::resolve(bool result)
 {
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
     JSC::JSLockHolder locker(exec);
-    reject(*exec, value);
+    resolve(*exec, JSC::jsBoolean(result));
 }
 
 template<>
-inline void DeferredWrapper::reject<ExceptionCode>(const ExceptionCode& ec)
+inline void DeferredWrapper::resolve(JSC::JSValue value)
 {
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
     JSC::JSLockHolder locker(exec);
-    reject(*exec, createDOMException(exec, ec));
+    resolve(*exec, value);
 }
 
 template<>
-inline void DeferredWrapper::resolve<String>(const String& result)
+inline void DeferredWrapper::reject(JSC::JSValue value)
 {
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
     JSC::JSLockHolder locker(exec);
-    resolve(*exec, jsString(exec, result));
+    reject(*exec, value);
 }
 
 template<>
-inline void DeferredWrapper::resolve<bool>(const bool& result)
+inline void DeferredWrapper::resolve(std::nullptr_t)
 {
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
     JSC::JSLockHolder locker(exec);
-    resolve(*exec, JSC::jsBoolean(result));
+    resolve(*exec, JSC::jsUndefined());
 }
 
 template<>
-inline void DeferredWrapper::resolve<JSC::JSValue>(const JSC::JSValue& value)
+inline void DeferredWrapper::reject(std::nullptr_t)
 {
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
     JSC::JSLockHolder locker(exec);
-    resolve(*exec, value);
+    reject(*exec, JSC::jsNull());
 }
 
 template<>
-inline void DeferredWrapper::resolve(const std::nullptr_t&)
+inline void DeferredWrapper::resolve(const String& result)
 {
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
     JSC::ExecState* exec = m_globalObject->globalExec();
     JSC::JSLockHolder locker(exec);
-    resolve(*exec, JSC::jsUndefined());
+    resolve(*exec, jsString(exec, result));
 }
 
 template<>
-inline void DeferredWrapper::reject<String>(const String& result)
+inline void DeferredWrapper::reject(const String& result)
 {
     ASSERT(m_deferred);
     ASSERT(m_globalObject);
index 4fa6782..8c6d88a 100644 (file)
@@ -550,7 +550,7 @@ JSValue JSSubtleCrypto::importKey(ExecState& state)
     JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
     DeferredWrapper wrapper(&state, globalObject(), promiseDeferred);
     auto successCallback = [wrapper](CryptoKey& result) mutable {
-        wrapper.resolve(&result);
+        wrapper.resolve(result);
     };
     auto failureCallback = [wrapper]() mutable {
         wrapper.reject(nullptr);
@@ -785,7 +785,7 @@ JSValue JSSubtleCrypto::unwrapKey(ExecState& state)
 
     auto decryptSuccessCallback = [domGlobalObject, keyFormat, unwrappedKeyAlgorithmPtr, unwrappedKeyAlgorithmParametersPtr, extractable, keyUsages, wrapper](const Vector<uint8_t>& result) mutable {
         auto importSuccessCallback = [wrapper](CryptoKey& key) mutable {
-            wrapper.resolve(&key);
+            wrapper.resolve(key);
         };
         auto importFailureCallback = [wrapper]() mutable {
             wrapper.reject(nullptr);
index 8971ef1..e24934d 100644 (file)
@@ -65,7 +65,7 @@ public:
     enum class LoadStatus { Unloaded, Loading, Loaded, Error };
     LoadStatus status() const;
 
-    typedef DOMPromise<FontFace&, ExceptionCode> Promise;
+    typedef DOMPromise<FontFace&> Promise;
     void registerLoaded(Promise&&);
 
     void load();
index 7e74498..189e5bd 100644 (file)
@@ -83,7 +83,7 @@ RefPtr<FontFace> FontFaceSet::Iterator::next()
     return m_target->backing()[m_index++].wrapper();
 }
 
-FontFaceSet::PendingPromise::PendingPromise(Promise&& promise)
+FontFaceSet::PendingPromise::PendingPromise(LoadPromise&& promise)
     : promise(WTFMove(promise))
 {
 }
@@ -123,7 +123,7 @@ void FontFaceSet::clear()
         m_backing->remove(m_backing.get()[0]);
 }
 
-void FontFaceSet::load(const String& font, const String& text, DeferredWrapper&& promise)
+void FontFaceSet::load(const String& font, const String& text, LoadPromise&& promise)
 {
     ExceptionCode ec = 0;
     auto matchingFaces = m_backing->matchingFaces(font, text, ec);
@@ -142,7 +142,7 @@ void FontFaceSet::load(const String& font, const String& text, DeferredWrapper&&
 
     for (auto& face : matchingFaces) {
         if (face.get().status() == CSSFontFace::Status::Failure) {
-            promise.reject(DOMCoreException::create(ExceptionCodeDescription(NETWORK_ERR)).ptr());
+            promise.reject(DOMCoreException::create(ExceptionCodeDescription(NETWORK_ERR)));
             return;
         }
     }
@@ -167,7 +167,7 @@ bool FontFaceSet::check(const String& family, const String& text, ExceptionCode&
     return m_backing->check(family, text, ec);
 }
 
-void FontFaceSet::registerReady(Promise&& promise)
+void FontFaceSet::registerReady(ReadyPromise&& promise)
 {
     ASSERT(!m_promise);
     if (m_isReady) {
index f0470e9..89ad08d 100644 (file)
@@ -47,14 +47,15 @@ public:
     bool remove(FontFace&);
     void clear();
 
-    void load(const String& font, const String& text, DeferredWrapper&& promise);
+    typedef DOMPromise<Vector<RefPtr<FontFace>>> LoadPromise;
+    void load(const String& font, const String& text, LoadPromise&&);
     bool check(const String& font, const String& text, ExceptionCode&);
 
     enum class LoadStatus { Loading, Loaded };
     LoadStatus status() const;
 
-    typedef DOMPromise<FontFaceSet&, DOMCoreException&> Promise;
-    void registerReady(Promise&&);
+    typedef DOMPromise<FontFaceSet&> ReadyPromise;
+    void registerReady(ReadyPromise&&);
 
     CSSFontFaceSet& backing() { return m_backing; }
 
@@ -74,19 +75,18 @@ public:
 
 private:
     struct PendingPromise : RefCounted<PendingPromise> {
-        typedef DOMPromise<Vector<RefPtr<FontFace>>&, DOMCoreException&> Promise;
-        static Ref<PendingPromise> create(Promise&& promise)
+        static Ref<PendingPromise> create(LoadPromise&& promise)
         {
             return adoptRef(*new PendingPromise(WTFMove(promise)));
         }
         ~PendingPromise();
 
     private:
-        PendingPromise(Promise&&);
+        PendingPromise(LoadPromise&&);
 
     public:
         Vector<RefPtr<FontFace>> faces;
-        Promise promise;
+        LoadPromise promise;
         bool hasReachedTerminalState { false };
     };
 
@@ -110,7 +110,7 @@ private:
 
     Ref<CSSFontFaceSet> m_backing;
     HashMap<RefPtr<CSSFontFace>, Vector<Ref<PendingPromise>>> m_pendingPromises;
-    Optional<Promise> m_promise;
+    Optional<ReadyPromise> m_promise;
     bool m_isReady { false };
 };
 
index e52e879..b389398 100644 (file)
@@ -212,7 +212,7 @@ public:
     bool loop() const;
     void setLoop(bool b);
 
-    typedef DOMPromise<std::nullptr_t, DOMError&> PlayPromise;
+    typedef DOMPromise<std::nullptr_t> PlayPromise;
     void play(PlayPromise&&);
 
     WEBCORE_EXPORT void play() override;