#ifndef __PROMISEHANDLER_H__ #define __PROMISEHANDLER_H__ #include "../FunctionTraits.h" #include "PromiseData.h" #include #include template class Promise; template struct PromiseDeduce { using Type = Promise; }; template struct PromiseDeduce : public PromiseDeduce {}; template struct PromiseDeduce : public PromiseDeduce {}; template struct PromiseDeduce : public PromiseDeduce {}; template struct PromiseDeduce> : public PromiseDeduce {}; template struct PromiseFunctor { using ResultType = typename std::invoke_result_t; using PromiseType = typename PromiseDeduce::Type; }; template struct PromiseFulfill { template static void call(V &&value, const TResolve &resolve, const TReject &) { resolve(std::forward(value)); } }; template struct PromiseFulfill> { template static void call(const Promise &promise, const TResolve &resolve, const TReject &reject) { if (promise.isFulfilled()) { resolve(promise.m_d->value()); } else if (promise.isRejected()) { reject(promise.m_d->error()); } else { promise.then([=]() { resolve(promise.m_d->value()); }, [=]() { // catch all reject(promise.m_d->error()); }); } } }; template <> struct PromiseFulfill> { template static void call(const TPromise &promise, const TResolve &resolve, const TReject &reject) { if (promise.isFulfilled()) { resolve(); } else if (promise.isRejected()) { reject(promise.m_d->error()); } else { promise.then([=]() { resolve(); }, [=]() { // catch all reject(promise.m_d->error()); }); } } }; template struct PromiseDispatch { template static void call(const Resolve &resolve, const Reject &reject, Functor fn, Args &&...args) { try { PromiseFulfill>::call(fn(std::forward(args)...), resolve, reject); } catch (...) { reject(std::current_exception()); } } }; template <> struct PromiseDispatch { template static void call(const Resolve &resolve, const Reject &reject, Functor fn, Args &&...args) { try { fn(std::forward(args)...); resolve(); } catch (...) { reject(std::current_exception()); } } }; template ::first> struct PromiseHandler { using ResType = std::invoke_result_t; using PromiseType = typename PromiseDeduce::Type; template static std::function create(const THandler &handler, const TResolve &resolve, const TReject &reject) { return [=](const T &value) { PromiseDispatch::call(resolve, reject, handler, value); }; } }; template struct PromiseHandler { using ResType = std::invoke_result_t; using PromiseType = typename PromiseDeduce::Type; template static std::function create(const THandler &handler, const TResolve &resolve, const TReject &reject) { return [=](const T &) { PromiseDispatch::call(resolve, reject, handler); }; } }; template struct PromiseHandler { using ResType = std::invoke_result_t; using PromiseType = typename PromiseDeduce::Type; template static std::function create(const THandler &handler, const TResolve &resolve, const TReject &reject) { return [=]() { PromiseDispatch::call(resolve, reject, handler); }; } }; template struct PromiseHandler { using PromiseType = Promise; template static std::function create(std::nullptr_t, const TResolve &resolve, const TReject &reject) { return [=](const T &value) { // 2.2.7.3. If onFulfilled is not a function and promise1 is fulfilled, // promise2 must be fulfilled with the same value as promise1. PromiseFulfill::call(std::move(T(value)), resolve, reject); }; } }; template <> struct PromiseHandler { using PromiseType = Promise; template static std::function create(std::nullptr_t, const TResolve &resolve, const TReject &) { return [=]() { // 2.2.7.3. If onFulfilled is not a function and promise1 is fulfilled, // promise2 must be fulfilled with the same value as promise1. resolve(); }; } }; template ::first> struct PromiseCatcher { using ResType = std::invoke_result_t; template static std::function create(const THandler &handler, const TResolve &resolve, const TReject &reject) { return [=](const PromiseError &error) { try { error.rethrow(); } catch (const TArg &argError) { PromiseDispatch::call(resolve, reject, handler, argError); } catch (...) { reject(std::current_exception()); } }; } }; template struct PromiseCatcher { using ResType = typename std::invoke_result_t; template static std::function create(const THandler &handler, const TResolve &resolve, const TReject &reject) { return [=](const PromiseError &error) { try { error.rethrow(); } catch (...) { PromiseDispatch::call(resolve, reject, handler); } }; } }; template struct PromiseCatcher { template static std::function create(std::nullptr_t, const TResolve &, const TReject &reject) { return [=](const PromiseError &error) { // 2.2.7.4. If onRejected is not a function and promise1 is rejected, // promise2 must be rejected with the same reason as promise1 reject(error); }; } }; #endif // __PROMISEHANDLER_H__