DOMPromise should only restrict the resolution type
authoryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 May 2016 09:36:00 +0000 (09:36 +0000)
committeryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 May 2016 09:36:00 +0000 (09:36 +0000)
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 toJS and DeferredWrapper to accept Ref<>&& and RefPtr<>&&.
Previously Ref<>&& were not accepted and only "const RefPtr<>&" was accepted.
This in turn created an unecessary churn count when calling toJS.

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/JSDOMBinding.h:
(WebCore::toJS):
(WebCore::jsPair):
* 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:

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

19 files changed:
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/JSDOMBinding.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 b218bee..837017b 100644 (file)
@@ -1,3 +1,74 @@
+2016-05-12  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 toJS and DeferredWrapper to accept Ref<>&& and RefPtr<>&&.
+        Previously Ref<>&& were not accepted and only "const RefPtr<>&" was accepted.
+        This in turn created an unecessary churn count when calling toJS.
+
+        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/JSDOMBinding.h:
+        (WebCore::toJS):
+        (WebCore::jsPair):
+        * 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-12  Manuel Rego Casasnovas  <rego@igalia.com>
 
         [css-grid] Incorrect parsing when using just 'span" as grid-line value
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 35be243..7c9b9e6 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 73b149b..9ce4198 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 06ce474..1fe695a 100644 (file)
@@ -251,7 +251,8 @@ JSC::JSObject* toJSSequence(JSC::ExecState*, JSC::JSValue, unsigned& length);
 JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSC::ArrayBuffer*);
 JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSC::ArrayBufferView*);
 JSC::JSValue toJS(JSC::ExecState*, JSC::JSGlobalObject*, JSC::ArrayBufferView*);
-template<typename T> JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, RefPtr<T>);
+template<typename T> JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, RefPtr<T>&);
+template<typename T> JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, RefPtr<T>&&);
 template<typename T> JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, PassRefPtr<T>);
 template<typename T> JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const Vector<T>&);
 template<typename T> JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const Vector<RefPtr<T>>&);
@@ -267,7 +268,7 @@ template<typename T, size_t inlineCapacity> JSC::JSValue jsArray(JSC::ExecState*
 WEBCORE_EXPORT JSC::JSValue jsArray(JSC::ExecState*, JSDOMGlobalObject*, PassRefPtr<DOMStringList>);
 
 JSC::JSValue jsPair(JSC::ExecState&, JSDOMGlobalObject*, JSC::JSValue, JSC::JSValue);
-template<typename FirstType, typename SecondType> JSC::JSValue jsPair(JSC::ExecState&, JSDOMGlobalObject*, const FirstType&, const SecondType&);
+template<typename FirstType, typename SecondType> JSC::JSValue jsPair(JSC::ExecState&, JSDOMGlobalObject*, FirstType&, SecondType&);
 
 RefPtr<JSC::ArrayBufferView> toArrayBufferView(JSC::JSValue);
 RefPtr<JSC::Int8Array> toInt8Array(JSC::JSValue);
@@ -540,7 +541,12 @@ inline JSC::JSValue toJS(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject
     return view->wrap(exec, globalObject);
 }
 
-template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, RefPtr<T> ptr)
+template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, RefPtr<T>& ptr)
+{
+    return toJS(exec, globalObject, ptr.get());
+}
+
+template<typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, RefPtr<T>&& ptr)
 {
     return toJS(exec, globalObject, ptr.get());
 }
@@ -644,7 +650,7 @@ inline JSC::JSValue jsPair(JSC::ExecState& state, JSDOMGlobalObject* globalObjec
     return constructArray(&state, 0, globalObject, args);
 }
 
-template<typename FirstType, typename SecondType> inline JSC::JSValue jsPair(JSC::ExecState& state, JSDOMGlobalObject* globalObject, const FirstType& value1, const SecondType& value2)
+template<typename FirstType, typename SecondType> inline JSC::JSValue jsPair(JSC::ExecState& state, JSDOMGlobalObject* globalObject, FirstType& value1, SecondType& value2)
 {
     return jsPair(state, globalObject, toJS(&state, globalObject, value1), toJS(&state, globalObject, value2));
 }
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..c13ca5f 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 testIsRefOrRefPtr(int) -> decltype(std::declval<T>().leakRef(), bool()) { return true; }
+    template<typename T> static constexpr bool testIsRefOrRefPtr(...) { return false; }
+
+public:
+    static constexpr bool isRefOrRefPtr = testIsRefOrRefPtr<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 +125,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 +148,7 @@ inline JSC::JSValue callPromiseFunction(JSC::ExecState& state, JSC::EncodedJSVal
     return promiseDeferred.promise();
 }
 
-template <typename Value, typename Error>
+template <typename Value>
 class DOMPromise {
 public:
     DOMPromise(DeferredWrapper&& wrapper) : m_wrapper(WTFMove(wrapper)) { }
@@ -80,105 +157,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 d8bc155..0184be0 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;