@@ -714,12 +714,11 @@ class val::awaiter {
714714 // - waiting with a given coroutine handle
715715 // - completed with a result
716716 // - rejected with an error
717- std::variant<val, std::coroutine_handle<val::promise_type>, val, val > state;
717+ std::variant<val, std::coroutine_handle<val::promise_type>, val> state;
718718
719719 constexpr static std::size_t STATE_PROMISE = 0 ;
720720 constexpr static std::size_t STATE_CORO = 1 ;
721721 constexpr static std::size_t STATE_RESULT = 2 ;
722- constexpr static std::size_t STATE_ERROR = 3 ;
723722
724723public:
725724 awaiter (const val& promise)
@@ -732,7 +731,8 @@ class val::awaiter {
732731 bool await_ready () { return false ; }
733732
734733 // 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))`.
734+ // a rough equivalent of
735+ // `promise.then(value => this.resume_with(value)).catch(error => this.reject_with(error))`.
736736 void await_suspend (std::coroutine_handle<val::promise_type> handle) {
737737 internal::_emval_coro_suspend (std::get<STATE_PROMISE>(state).as_handle (), this );
738738 state.emplace <STATE_CORO>(handle);
@@ -746,18 +746,14 @@ class val::awaiter {
746746 coro.resume ();
747747 }
748748
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- }
749+ // When JS invokes `reject_with` with some error value, reject currently suspended
750+ // coroutine's promise with that error value and destroy coroutine frame, because
751+ // in this case coroutine never reaches final_suspend point to be destroyed automatically.
752+ void reject_with (val&& error);
754753
755754 // `await_resume` finalizes the awaiter and should return the result
756755 // of the `co_await ...` expression - in our case, the stored value.
757756 val await_resume () {
758- if (state.index () == STATE_ERROR) {
759- throw std::get<STATE_ERROR>(state);
760- }
761757 return std::move (std::get<STATE_RESULT>(state));
762758 }
763759};
@@ -803,12 +799,25 @@ class val::promise_type {
803799 }
804800 }
805801
802+ // Reject the stored promise due to rejection deeper in the call chain
803+ void reject_with (val&& error) {
804+ reject (std::move (error));
805+ }
806+
806807 // Resolve the stored promise on `co_return value`.
807808 template <typename T>
808809 void return_value (T&& value) {
809810 resolve (std::forward<T>(value));
810811 }
811812};
813+
814+ inline void val::awaiter::reject_with (val&& error) {
815+ auto coro = std::move (std::get<STATE_CORO>(state));
816+ auto & promise = coro.promise ();
817+ promise.reject_with (std::move (error));
818+ coro.destroy ();
819+ }
820+
812821#endif
813822
814823// Declare a custom type that can be used in conjunction with
0 commit comments