@@ -713,13 +713,11 @@ class val::awaiter {
713
713
// - initially created with promise
714
714
// - waiting with a given coroutine handle
715
715
// - 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;
718
717
719
718
constexpr static std::size_t STATE_PROMISE = 0 ;
720
719
constexpr static std::size_t STATE_CORO = 1 ;
721
720
constexpr static std::size_t STATE_RESULT = 2 ;
722
- constexpr static std::size_t STATE_ERROR = 3 ;
723
721
724
722
public:
725
723
awaiter (const val& promise)
@@ -732,7 +730,8 @@ class val::awaiter {
732
730
bool await_ready () { return false ; }
733
731
734
732
// 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))`.
736
735
void await_suspend (std::coroutine_handle<val::promise_type> handle) {
737
736
internal::_emval_coro_suspend (std::get<STATE_PROMISE>(state).as_handle (), this );
738
737
state.emplace <STATE_CORO>(handle);
@@ -746,18 +745,14 @@ class val::awaiter {
746
745
coro.resume ();
747
746
}
748
747
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);
754
752
755
753
// `await_resume` finalizes the awaiter and should return the result
756
754
// of the `co_await ...` expression - in our case, the stored value.
757
755
val await_resume () {
758
- if (state.index () == STATE_ERROR) {
759
- throw std::get<STATE_ERROR>(state);
760
- }
761
756
return std::move (std::get<STATE_RESULT>(state));
762
757
}
763
758
};
@@ -803,12 +798,25 @@ class val::promise_type {
803
798
}
804
799
}
805
800
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
+
806
806
// Resolve the stored promise on `co_return value`.
807
807
template <typename T>
808
808
void return_value (T&& value) {
809
809
resolve (std::forward<T>(value));
810
810
}
811
811
};
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
+
812
820
#endif
813
821
814
822
// Declare a custom type that can be used in conjunction with
0 commit comments