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