diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/bindings/js/JSDOMPromise.h | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/bindings/js/JSDOMPromise.h')
-rw-r--r-- | Source/WebCore/bindings/js/JSDOMPromise.h | 270 |
1 files changed, 214 insertions, 56 deletions
diff --git a/Source/WebCore/bindings/js/JSDOMPromise.h b/Source/WebCore/bindings/js/JSDOMPromise.h index d431c4e5d..39530cc6e 100644 --- a/Source/WebCore/bindings/js/JSDOMPromise.h +++ b/Source/WebCore/bindings/js/JSDOMPromise.h @@ -23,87 +23,245 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSDOMPromise_h -#define JSDOMPromise_h +#pragma once -#include "JSCryptoKey.h" -#include "JSCryptoKeyPair.h" -#include "JSDOMBinding.h" +#include "ActiveDOMCallback.h" +#include "JSDOMConvert.h" #include <heap/StrongInlines.h> #include <runtime/JSPromiseDeferred.h> namespace WebCore { -class DeferredWrapper { +class DeferredPromise : public RefCounted<DeferredPromise>, public ActiveDOMCallback { public: - DeferredWrapper(JSC::ExecState*, JSDOMGlobalObject*); + static Ref<DeferredPromise> create(JSDOMGlobalObject& globalObject, JSC::JSPromiseDeferred& deferred) + { + return adoptRef(*new DeferredPromise(globalObject, deferred)); + } - template<class ResolveResultType> - void resolve(const ResolveResultType&); + ~DeferredPromise(); - template<class RejectResultType> - void reject(const RejectResultType&); + template<class IDLType> + void resolve(typename IDLType::ParameterType value) + { + if (isSuspended()) + return; + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* exec = m_globalObject->globalExec(); + JSC::JSLockHolder locker(exec); + resolve(*exec, toJS<IDLType>(*exec, *m_globalObject.get(), std::forward<typename IDLType::ParameterType>(value))); + } - JSC::JSObject* promise() const; + void resolve() + { + if (isSuspended()) + return; + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* exec = m_globalObject->globalExec(); + JSC::JSLockHolder locker(exec); + resolve(*exec, JSC::jsUndefined()); + } + + template<class IDLType> + void resolveWithNewlyCreated(typename IDLType::ParameterType value) + { + if (isSuspended()) + return; + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* exec = m_globalObject->globalExec(); + JSC::JSLockHolder locker(exec); + resolve(*exec, toJSNewlyCreated<IDLType>(*exec, *m_globalObject.get(), std::forward<typename IDLType::ParameterType>(value))); + } + + template<class IDLType> + void reject(typename IDLType::ParameterType value) + { + if (isSuspended()) + return; + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* exec = m_globalObject->globalExec(); + JSC::JSLockHolder locker(exec); + reject(*exec, toJS<IDLType>(*exec, *m_globalObject.get(), std::forward<typename IDLType::ParameterType>(value))); + } + + void reject(); + void reject(std::nullptr_t); + void reject(Exception&&); + void reject(ExceptionCode, const String& = { }); + void reject(const JSC::PrivateName&); + + template<typename Callback> + void resolveWithCallback(Callback callback) + { + if (isSuspended()) + return; + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* exec = m_globalObject->globalExec(); + JSC::JSLockHolder locker(exec); + resolve(*exec, callback(*exec, *m_globalObject.get())); + } + + template<typename Callback> + void rejectWithCallback(Callback callback) + { + if (isSuspended()) + return; + ASSERT(m_deferred); + ASSERT(m_globalObject); + JSC::ExecState* exec = m_globalObject->globalExec(); + JSC::JSLockHolder locker(exec); + reject(*exec, callback(*exec, *m_globalObject.get())); + } + + JSC::JSValue promise() const; + + bool isSuspended() { return !m_deferred || !canInvokeCallback(); } // The wrapper world has gone away or active DOM objects have been suspended. + JSDOMGlobalObject* globalObject() { return m_globalObject.get(); } + + void visitAggregate(JSC::SlotVisitor& visitor) { visitor.append(m_deferred); } private: - void resolve(JSC::ExecState*, JSC::JSValue); - void reject(JSC::ExecState*, JSC::JSValue); + DeferredPromise(JSDOMGlobalObject&, JSC::JSPromiseDeferred&); + + void clear(); + void contextDestroyed() override; - JSC::Strong<JSDOMGlobalObject> m_globalObject; - JSC::Strong<JSC::JSPromiseDeferred> m_deferred; + void callFunction(JSC::ExecState&, JSC::JSValue function, JSC::JSValue resolution); + 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); } + + JSC::Weak<JSC::JSPromiseDeferred> m_deferred; + JSC::Weak<JSDOMGlobalObject> m_globalObject; }; -template<class ResolveResultType> -inline void DeferredWrapper::resolve(const ResolveResultType& result) -{ - JSC::ExecState* exec = m_globalObject->globalExec(); - resolve(exec, toJS(exec, m_globalObject.get(), result)); -} +class DOMPromiseBase { +public: + DOMPromiseBase(Ref<DeferredPromise>&& genericPromise) + : m_promiseDeferred(WTFMove(genericPromise)) + { + } -template<class RejectResultType> -inline void DeferredWrapper::reject(const RejectResultType& result) -{ - JSC::ExecState* exec = m_globalObject->globalExec(); - reject(exec, toJS(exec, m_globalObject.get(), result)); -} + DOMPromiseBase(DOMPromiseBase&& promise) + : m_promiseDeferred(WTFMove(promise.m_promiseDeferred)) + { + } -template<> -inline void DeferredWrapper::reject(const std::nullptr_t&) -{ - JSC::ExecState* exec = m_globalObject->globalExec(); - reject(exec, JSC::jsNull()); -} + DOMPromiseBase(const DOMPromiseBase& other) + : m_promiseDeferred(other.m_promiseDeferred.copyRef()) + { + } -template<> -inline void DeferredWrapper::resolve<String>(const String& result) -{ - JSC::ExecState* exec = m_globalObject->globalExec(); - resolve(exec, jsString(exec, result)); -} + DOMPromiseBase& operator=(const DOMPromiseBase& other) + { + m_promiseDeferred = other.m_promiseDeferred.copyRef(); + return *this; + } -template<> -inline void DeferredWrapper::resolve<bool>(const bool& result) -{ - JSC::ExecState* exec = m_globalObject->globalExec(); - resolve(exec, JSC::jsBoolean(result)); -} + DOMPromiseBase& operator=(DOMPromiseBase&& other) + { + m_promiseDeferred = WTFMove(other.m_promiseDeferred); + return *this; + } + + void reject() + { + m_promiseDeferred->reject(); + } + + template<typename... ErrorType> + void reject(ErrorType&&... error) + { + m_promiseDeferred->reject(std::forward<ErrorType>(error)...); + } -template<> -inline void DeferredWrapper::resolve<Vector<unsigned char>>(const Vector<unsigned char>& result) + template<typename IDLType> + void rejectType(typename IDLType::ParameterType value) + { + m_promiseDeferred->reject<IDLType>(std::forward<typename IDLType::ParameterType>(value)); + } + + JSC::JSValue promise() const { return m_promiseDeferred->promise(); }; + +protected: + Ref<DeferredPromise> m_promiseDeferred; +}; + +template<typename IDLType> +class DOMPromise : public DOMPromiseBase { +public: + using DOMPromiseBase::DOMPromiseBase; + using DOMPromiseBase::operator=; + using DOMPromiseBase::promise; + using DOMPromiseBase::reject; + + void resolve(typename IDLType::ParameterType value) + { + m_promiseDeferred->resolve<IDLType>(std::forward<typename IDLType::ParameterType>(value)); + } +}; + +template<> class DOMPromise<void> : public DOMPromiseBase { +public: + using DOMPromiseBase::DOMPromiseBase; + using DOMPromiseBase::operator=; + using DOMPromiseBase::promise; + using DOMPromiseBase::reject; + + void resolve() + { + m_promiseDeferred->resolve(); + } +}; + + +Ref<DeferredPromise> createDeferredPromise(JSC::ExecState&, JSDOMWindow&); + +void fulfillPromiseWithJSON(Ref<DeferredPromise>&&, const String&); +void fulfillPromiseWithArrayBuffer(Ref<DeferredPromise>&&, ArrayBuffer*); +void fulfillPromiseWithArrayBuffer(Ref<DeferredPromise>&&, const void*, size_t); +void rejectPromiseWithExceptionIfAny(JSC::ExecState&, JSDOMGlobalObject&, JSC::JSPromiseDeferred&); +JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::ExecState&, const String&); + +using PromiseFunction = void(JSC::ExecState&, Ref<DeferredPromise>&&); + +enum class PromiseExecutionScope { WindowOnly, WindowOrWorker }; + +template<PromiseFunction promiseFunction, PromiseExecutionScope executionScope> +inline JSC::JSValue callPromiseFunction(JSC::ExecState& state) { - JSC::ExecState* exec = m_globalObject->globalExec(); - RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(result.data(), result.size()); - resolve(exec, toJS(exec, m_globalObject.get(), buffer.get())); + JSC::VM& vm = state.vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + + JSDOMGlobalObject& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()); + JSC::JSPromiseDeferred* promiseDeferred = JSC::JSPromiseDeferred::create(&state, &globalObject); + + // promiseDeferred can be null when terminating a Worker abruptly. + if (executionScope == PromiseExecutionScope::WindowOrWorker && !promiseDeferred) + return JSC::jsUndefined(); + + promiseFunction(state, DeferredPromise::create(globalObject, *promiseDeferred)); + + rejectPromiseWithExceptionIfAny(state, globalObject, *promiseDeferred); + ASSERT_UNUSED(scope, !scope.exception()); + return promiseDeferred->promise(); } -template<> -inline void DeferredWrapper::reject<String>(const String& result) +using BindingPromiseFunction = JSC::EncodedJSValue(JSC::ExecState*, Ref<DeferredPromise>&&); +template<BindingPromiseFunction bindingFunction> +inline void bindingPromiseFunctionAdapter(JSC::ExecState& state, Ref<DeferredPromise>&& promise) { - JSC::ExecState* exec = m_globalObject->globalExec(); - reject(exec, jsString(exec, result)); + bindingFunction(&state, WTFMove(promise)); } +template<BindingPromiseFunction bindingPromiseFunction, PromiseExecutionScope executionScope> +inline JSC::JSValue callPromiseFunction(JSC::ExecState& state) +{ + return callPromiseFunction<bindingPromiseFunctionAdapter<bindingPromiseFunction>, executionScope>(state); } -#endif // JSDOMPromise_h +} // namespace WebCore |