@@ -713,13 +713,11 @@ class val::awaiter {
713713 // - initially created with promise
714714 // - waiting with a given coroutine handle
715715 // - completed with a result
716- // - rejected with an error
717- std::variant<val, std::coroutine_handle<val::promise_type>, val, val> state;
716+ std::variant<val, std::coroutine_handle<val::promise_type>, val> state;
718717
719718 constexpr static std::size_t STATE_PROMISE = 0 ;
720719 constexpr static std::size_t STATE_CORO = 1 ;
721720 constexpr static std::size_t STATE_RESULT = 2 ;
722- constexpr static std::size_t STATE_ERROR = 3 ;
723721
724722public:
725723 awaiter (const val& promise)
@@ -732,7 +730,8 @@ class val::awaiter {
732730 bool await_ready () { return false ; }
733731
734732 // On suspend, store the coroutine handle and invoke a helper that will do
735- // a rough equivalent of `promise.then(value => this.resume_with(value))`.
733+ // a rough equivalent of
734+ // `promise.then(value => this.resume_with(value)).catch(error => this.reject_with(error))`.
736735 void await_suspend (std::coroutine_handle<val::promise_type> handle) {
737736 internal::_emval_coro_suspend (std::get<STATE_PROMISE>(state).as_handle (), this );
738737 state.emplace <STATE_CORO>(handle);
@@ -746,18 +745,14 @@ class val::awaiter {
746745 coro.resume ();
747746 }
748747
749- void reject_with (val&& error) {
750- auto coro = std::move (std::get<STATE_CORO>(state));
751- state.emplace <STATE_ERROR>(std::move (error));
752- coro.resume ();
753- }
748+ // When JS invokes `reject_with` with some error value, reject currently suspended
749+ // coroutine's promise with the error value and destroy coroutine frame, because
750+ // in this scenario coroutine never reaches final_suspend point to be destroyed automatically.
751+ void reject_with (val&& error);
754752
755753 // `await_resume` finalizes the awaiter and should return the result
756754 // of the `co_await ...` expression - in our case, the stored value.
757755 val await_resume () {
758- if (state.index () == STATE_ERROR) {
759- throw std::get<STATE_ERROR>(state);
760- }
761756 return std::move (std::get<STATE_RESULT>(state));
762757 }
763758};
@@ -803,12 +798,25 @@ class val::promise_type {
803798 }
804799 }
805800
801+ // Reject the stored promise due to rejection deeper in the call chain
802+ void reject_with (val&& error) {
803+ reject (std::move (error));
804+ }
805+
806806 // Resolve the stored promise on `co_return value`.
807807 template <typename T>
808808 void return_value (T&& value) {
809809 resolve (std::forward<T>(value));
810810 }
811811};
812+
813+ inline void val::awaiter::reject_with (val&& error) {
814+ auto coro = std::move (std::get<STATE_CORO>(state));
815+ auto & promise = coro.promise ();
816+ promise.reject_with (std::move (error));
817+ coro.destroy ();
818+ }
819+
812820#endif
813821
814822// Declare a custom type that can be used in conjunction with
0 commit comments