@ugo-studio/jspp 0.2.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/codegen/class-handlers.js +6 -6
- package/dist/core/codegen/statement-handlers.js +1 -1
- package/package.json +1 -1
- package/src/prelude/any_value.hpp +362 -362
- package/src/prelude/any_value_access.hpp +170 -170
- package/src/prelude/any_value_defines.hpp +189 -189
- package/src/prelude/any_value_helpers.hpp +374 -374
- package/src/prelude/library/array.hpp +185 -185
- package/src/prelude/library/console.hpp +111 -111
- package/src/prelude/library/error.hpp +112 -112
- package/src/prelude/library/function.hpp +10 -10
- package/src/prelude/library/math.hpp +307 -307
- package/src/prelude/library/object.hpp +275 -275
- package/src/prelude/library/process.hpp +39 -39
- package/src/prelude/library/promise.hpp +123 -123
- package/src/prelude/library/symbol.hpp +52 -52
- package/src/prelude/library/timer.hpp +91 -91
- package/src/prelude/types.hpp +178 -178
- package/src/prelude/utils/access.hpp +411 -411
- package/src/prelude/utils/operators.hpp +336 -336
- package/src/prelude/values/array.hpp +0 -1
- package/src/prelude/values/async_iterator.hpp +83 -83
- package/src/prelude/values/function.hpp +82 -82
- package/src/prelude/values/helpers/array.hpp +198 -208
- package/src/prelude/values/helpers/async_iterator.hpp +275 -275
- package/src/prelude/values/helpers/function.hpp +108 -108
- package/src/prelude/values/helpers/iterator.hpp +144 -144
- package/src/prelude/values/helpers/promise.hpp +253 -253
- package/src/prelude/values/helpers/string.hpp +37 -61
- package/src/prelude/values/promise.hpp +72 -72
- package/src/prelude/values/prototypes/array.hpp +14 -2
- package/src/prelude/values/prototypes/iterator.hpp +201 -201
- package/src/prelude/values/prototypes/promise.hpp +196 -196
- package/src/prelude/values/prototypes/string.hpp +564 -542
- package/src/prelude/values/string.hpp +25 -26
|
@@ -1,275 +1,275 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include "types.hpp"
|
|
4
|
-
#include "values/async_iterator.hpp"
|
|
5
|
-
#include "any_value.hpp"
|
|
6
|
-
#include "values/prototypes/async_iterator.hpp"
|
|
7
|
-
|
|
8
|
-
// --- JsAsyncIterator methods ---
|
|
9
|
-
|
|
10
|
-
template <typename T>
|
|
11
|
-
std::string jspp::JsAsyncIterator<T>::to_std_string() const
|
|
12
|
-
{
|
|
13
|
-
return "[object AsyncGenerator]";
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
template <typename T>
|
|
17
|
-
jspp::AnyValue jspp::JsAsyncIterator<T>::get_property(const std::string &key, AnyValue thisVal)
|
|
18
|
-
{
|
|
19
|
-
auto it = props.find(key);
|
|
20
|
-
if (it == props.end())
|
|
21
|
-
{
|
|
22
|
-
if constexpr (std::is_same_v<T, AnyValue>)
|
|
23
|
-
{
|
|
24
|
-
auto proto_it = AsyncIteratorPrototypes::get(key);
|
|
25
|
-
if (proto_it.has_value())
|
|
26
|
-
{
|
|
27
|
-
return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return Constants::UNDEFINED;
|
|
31
|
-
}
|
|
32
|
-
return AnyValue::resolve_property_for_read(it->second, thisVal, key);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
template <typename T>
|
|
36
|
-
jspp::AnyValue jspp::JsAsyncIterator<T>::set_property(const std::string &key, AnyValue value, AnyValue thisVal)
|
|
37
|
-
{
|
|
38
|
-
if constexpr (std::is_same_v<T, AnyValue>)
|
|
39
|
-
{
|
|
40
|
-
auto proto_it = AsyncIteratorPrototypes::get(key);
|
|
41
|
-
if (proto_it.has_value())
|
|
42
|
-
{
|
|
43
|
-
auto proto_value = proto_it.value();
|
|
44
|
-
if (proto_value.is_accessor_descriptor())
|
|
45
|
-
{
|
|
46
|
-
return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
|
|
47
|
-
}
|
|
48
|
-
if (proto_value.is_data_descriptor() && !proto_value.as_data_descriptor()->writable)
|
|
49
|
-
{
|
|
50
|
-
return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
auto it = props.find(key);
|
|
56
|
-
if (it != props.end())
|
|
57
|
-
{
|
|
58
|
-
return jspp::AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
|
|
59
|
-
}
|
|
60
|
-
else
|
|
61
|
-
{
|
|
62
|
-
props[key] = value;
|
|
63
|
-
return value;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
template <typename T>
|
|
68
|
-
void jspp::JsAsyncIterator<T>::resume_next()
|
|
69
|
-
{
|
|
70
|
-
if (!handle || handle.done())
|
|
71
|
-
return;
|
|
72
|
-
auto &p = handle.promise();
|
|
73
|
-
if (p.is_awaiting || p.is_running)
|
|
74
|
-
return;
|
|
75
|
-
if (p.pending_calls.empty())
|
|
76
|
-
return;
|
|
77
|
-
|
|
78
|
-
p.is_running = true;
|
|
79
|
-
|
|
80
|
-
auto &next_call = p.pending_calls.front();
|
|
81
|
-
p.current_input = next_call.second;
|
|
82
|
-
|
|
83
|
-
handle.resume();
|
|
84
|
-
|
|
85
|
-
p.is_running = false;
|
|
86
|
-
|
|
87
|
-
// After yield/return, if more calls are pending, handle them.
|
|
88
|
-
if (!p.pending_calls.empty() && !p.is_awaiting && !handle.done())
|
|
89
|
-
{
|
|
90
|
-
this->ref();
|
|
91
|
-
Scheduler::instance().enqueue([this]()
|
|
92
|
-
{
|
|
93
|
-
this->resume_next();
|
|
94
|
-
this->deref();
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
template <typename T>
|
|
100
|
-
jspp::JsPromise jspp::JsAsyncIterator<T>::next(const T &val)
|
|
101
|
-
{
|
|
102
|
-
// JsPromise is now a HeapObject.
|
|
103
|
-
// We should return it by value (which AnyValue will then wrap).
|
|
104
|
-
// Wait, coroutines return JsPromise by value.
|
|
105
|
-
JsPromise p;
|
|
106
|
-
if (handle)
|
|
107
|
-
{
|
|
108
|
-
if (handle.done())
|
|
109
|
-
{
|
|
110
|
-
p.resolve(AnyValue::make_object({{"value", Constants::UNDEFINED}, {"done", Constants::TRUE}}));
|
|
111
|
-
}
|
|
112
|
-
else
|
|
113
|
-
{
|
|
114
|
-
handle.promise().pending_calls.push({p, val});
|
|
115
|
-
resume_next();
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
else
|
|
119
|
-
{
|
|
120
|
-
p.resolve(AnyValue::make_object({{"value", Constants::UNDEFINED}, {"done", Constants::TRUE}}));
|
|
121
|
-
}
|
|
122
|
-
return p;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// --- JsAsyncIterator::promise_type methods ---
|
|
126
|
-
|
|
127
|
-
template <typename T>
|
|
128
|
-
template <typename From>
|
|
129
|
-
auto jspp::JsAsyncIterator<T>::promise_type::yield_value(From &&from)
|
|
130
|
-
{
|
|
131
|
-
if (!pending_calls.empty())
|
|
132
|
-
{
|
|
133
|
-
auto call = pending_calls.front();
|
|
134
|
-
pending_calls.pop();
|
|
135
|
-
AnyValue result = AnyValue::make_object({{"value", std::forward<From>(from)}, {"done", Constants::FALSE}});
|
|
136
|
-
call.first.resolve(result);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
struct YieldAwaiter
|
|
140
|
-
{
|
|
141
|
-
promise_type &p;
|
|
142
|
-
bool await_ready() { return false; }
|
|
143
|
-
void await_suspend(std::coroutine_handle<promise_type> h)
|
|
144
|
-
{
|
|
145
|
-
// Suspended at yield.
|
|
146
|
-
}
|
|
147
|
-
T await_resume() { return p.current_input; }
|
|
148
|
-
};
|
|
149
|
-
return YieldAwaiter{*this};
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
template <typename T>
|
|
153
|
-
template <typename From>
|
|
154
|
-
void jspp::JsAsyncIterator<T>::promise_type::return_value(From &&from)
|
|
155
|
-
{
|
|
156
|
-
if (!pending_calls.empty())
|
|
157
|
-
{
|
|
158
|
-
auto call = pending_calls.front();
|
|
159
|
-
pending_calls.pop();
|
|
160
|
-
AnyValue result = AnyValue::make_object({{"value", std::forward<From>(from)}, {"done", Constants::TRUE}});
|
|
161
|
-
call.first.resolve(result);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
while (!pending_calls.empty())
|
|
165
|
-
{
|
|
166
|
-
auto call = pending_calls.front();
|
|
167
|
-
pending_calls.pop();
|
|
168
|
-
AnyValue result = AnyValue::make_object({{"value", Constants::UNDEFINED}, {"done", Constants::TRUE}});
|
|
169
|
-
call.first.resolve(result);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
template <typename T>
|
|
174
|
-
void jspp::JsAsyncIterator<T>::promise_type::fail_all(const AnyValue &reason)
|
|
175
|
-
{
|
|
176
|
-
while (!pending_calls.empty())
|
|
177
|
-
{
|
|
178
|
-
auto call = pending_calls.front();
|
|
179
|
-
pending_calls.pop();
|
|
180
|
-
call.first.reject(reason);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
template <typename T>
|
|
185
|
-
void jspp::JsAsyncIterator<T>::promise_type::unhandled_exception()
|
|
186
|
-
{
|
|
187
|
-
try
|
|
188
|
-
{
|
|
189
|
-
std::rethrow_exception(std::current_exception());
|
|
190
|
-
}
|
|
191
|
-
catch (const Exception &e)
|
|
192
|
-
{
|
|
193
|
-
fail_all(e.data);
|
|
194
|
-
}
|
|
195
|
-
catch (const std::exception &e)
|
|
196
|
-
{
|
|
197
|
-
fail_all(AnyValue::make_string(e.what()));
|
|
198
|
-
}
|
|
199
|
-
catch (...)
|
|
200
|
-
{
|
|
201
|
-
fail_all(AnyValue::make_string("Unknown error in async generator"));
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
template <typename T>
|
|
206
|
-
auto jspp::JsAsyncIterator<T>::promise_type::await_transform(AnyValue value)
|
|
207
|
-
{
|
|
208
|
-
is_awaiting = true;
|
|
209
|
-
struct AsyncIterAwaiter
|
|
210
|
-
{
|
|
211
|
-
AnyValueAwaiter base_awaiter;
|
|
212
|
-
promise_type &p_ref;
|
|
213
|
-
|
|
214
|
-
bool await_ready() { return base_awaiter.await_ready(); }
|
|
215
|
-
void await_suspend(std::coroutine_handle<promise_type> h)
|
|
216
|
-
{
|
|
217
|
-
if (!base_awaiter.value.is_promise())
|
|
218
|
-
{
|
|
219
|
-
jspp::Scheduler::instance().enqueue([h]() mutable
|
|
220
|
-
{
|
|
221
|
-
auto &pr = h.promise();
|
|
222
|
-
pr.is_awaiting = false;
|
|
223
|
-
pr.is_running = true;
|
|
224
|
-
h.resume();
|
|
225
|
-
pr.is_running = false;
|
|
226
|
-
|
|
227
|
-
if (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
|
|
228
|
-
{
|
|
229
|
-
while (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
|
|
230
|
-
{
|
|
231
|
-
pr.is_running = true;
|
|
232
|
-
pr.current_input = pr.pending_calls.front().second;
|
|
233
|
-
h.resume();
|
|
234
|
-
pr.is_running = false;
|
|
235
|
-
}
|
|
236
|
-
} });
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
auto p = base_awaiter.value.as_promise();
|
|
240
|
-
p->then(
|
|
241
|
-
[h](AnyValue v) mutable
|
|
242
|
-
{
|
|
243
|
-
auto &pr = h.promise();
|
|
244
|
-
pr.is_awaiting = false;
|
|
245
|
-
pr.is_running = true;
|
|
246
|
-
h.resume();
|
|
247
|
-
pr.is_running = false;
|
|
248
|
-
|
|
249
|
-
if (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
|
|
250
|
-
{
|
|
251
|
-
while (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
|
|
252
|
-
{
|
|
253
|
-
pr.is_running = true;
|
|
254
|
-
pr.current_input = pr.pending_calls.front().second;
|
|
255
|
-
h.resume();
|
|
256
|
-
pr.is_running = false;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
},
|
|
260
|
-
[h](AnyValue e) mutable
|
|
261
|
-
{
|
|
262
|
-
auto &pr = h.promise();
|
|
263
|
-
pr.is_awaiting = false;
|
|
264
|
-
pr.is_running = true;
|
|
265
|
-
h.resume();
|
|
266
|
-
pr.is_running = false;
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
AnyValue await_resume()
|
|
270
|
-
{
|
|
271
|
-
return base_awaiter.await_resume();
|
|
272
|
-
}
|
|
273
|
-
};
|
|
274
|
-
return AsyncIterAwaiter{AnyValueAwaiter{std::move(value)}, *this};
|
|
275
|
-
}
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include "values/async_iterator.hpp"
|
|
5
|
+
#include "any_value.hpp"
|
|
6
|
+
#include "values/prototypes/async_iterator.hpp"
|
|
7
|
+
|
|
8
|
+
// --- JsAsyncIterator methods ---
|
|
9
|
+
|
|
10
|
+
template <typename T>
|
|
11
|
+
std::string jspp::JsAsyncIterator<T>::to_std_string() const
|
|
12
|
+
{
|
|
13
|
+
return "[object AsyncGenerator]";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
template <typename T>
|
|
17
|
+
jspp::AnyValue jspp::JsAsyncIterator<T>::get_property(const std::string &key, AnyValue thisVal)
|
|
18
|
+
{
|
|
19
|
+
auto it = props.find(key);
|
|
20
|
+
if (it == props.end())
|
|
21
|
+
{
|
|
22
|
+
if constexpr (std::is_same_v<T, AnyValue>)
|
|
23
|
+
{
|
|
24
|
+
auto proto_it = AsyncIteratorPrototypes::get(key);
|
|
25
|
+
if (proto_it.has_value())
|
|
26
|
+
{
|
|
27
|
+
return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return Constants::UNDEFINED;
|
|
31
|
+
}
|
|
32
|
+
return AnyValue::resolve_property_for_read(it->second, thisVal, key);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
template <typename T>
|
|
36
|
+
jspp::AnyValue jspp::JsAsyncIterator<T>::set_property(const std::string &key, AnyValue value, AnyValue thisVal)
|
|
37
|
+
{
|
|
38
|
+
if constexpr (std::is_same_v<T, AnyValue>)
|
|
39
|
+
{
|
|
40
|
+
auto proto_it = AsyncIteratorPrototypes::get(key);
|
|
41
|
+
if (proto_it.has_value())
|
|
42
|
+
{
|
|
43
|
+
auto proto_value = proto_it.value();
|
|
44
|
+
if (proto_value.is_accessor_descriptor())
|
|
45
|
+
{
|
|
46
|
+
return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
|
|
47
|
+
}
|
|
48
|
+
if (proto_value.is_data_descriptor() && !proto_value.as_data_descriptor()->writable)
|
|
49
|
+
{
|
|
50
|
+
return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
auto it = props.find(key);
|
|
56
|
+
if (it != props.end())
|
|
57
|
+
{
|
|
58
|
+
return jspp::AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
|
|
59
|
+
}
|
|
60
|
+
else
|
|
61
|
+
{
|
|
62
|
+
props[key] = value;
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
template <typename T>
|
|
68
|
+
void jspp::JsAsyncIterator<T>::resume_next()
|
|
69
|
+
{
|
|
70
|
+
if (!handle || handle.done())
|
|
71
|
+
return;
|
|
72
|
+
auto &p = handle.promise();
|
|
73
|
+
if (p.is_awaiting || p.is_running)
|
|
74
|
+
return;
|
|
75
|
+
if (p.pending_calls.empty())
|
|
76
|
+
return;
|
|
77
|
+
|
|
78
|
+
p.is_running = true;
|
|
79
|
+
|
|
80
|
+
auto &next_call = p.pending_calls.front();
|
|
81
|
+
p.current_input = next_call.second;
|
|
82
|
+
|
|
83
|
+
handle.resume();
|
|
84
|
+
|
|
85
|
+
p.is_running = false;
|
|
86
|
+
|
|
87
|
+
// After yield/return, if more calls are pending, handle them.
|
|
88
|
+
if (!p.pending_calls.empty() && !p.is_awaiting && !handle.done())
|
|
89
|
+
{
|
|
90
|
+
this->ref();
|
|
91
|
+
Scheduler::instance().enqueue([this]()
|
|
92
|
+
{
|
|
93
|
+
this->resume_next();
|
|
94
|
+
this->deref();
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
template <typename T>
|
|
100
|
+
jspp::JsPromise jspp::JsAsyncIterator<T>::next(const T &val)
|
|
101
|
+
{
|
|
102
|
+
// JsPromise is now a HeapObject.
|
|
103
|
+
// We should return it by value (which AnyValue will then wrap).
|
|
104
|
+
// Wait, coroutines return JsPromise by value.
|
|
105
|
+
JsPromise p;
|
|
106
|
+
if (handle)
|
|
107
|
+
{
|
|
108
|
+
if (handle.done())
|
|
109
|
+
{
|
|
110
|
+
p.resolve(AnyValue::make_object({{"value", Constants::UNDEFINED}, {"done", Constants::TRUE}}));
|
|
111
|
+
}
|
|
112
|
+
else
|
|
113
|
+
{
|
|
114
|
+
handle.promise().pending_calls.push({p, val});
|
|
115
|
+
resume_next();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else
|
|
119
|
+
{
|
|
120
|
+
p.resolve(AnyValue::make_object({{"value", Constants::UNDEFINED}, {"done", Constants::TRUE}}));
|
|
121
|
+
}
|
|
122
|
+
return p;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// --- JsAsyncIterator::promise_type methods ---
|
|
126
|
+
|
|
127
|
+
template <typename T>
|
|
128
|
+
template <typename From>
|
|
129
|
+
auto jspp::JsAsyncIterator<T>::promise_type::yield_value(From &&from)
|
|
130
|
+
{
|
|
131
|
+
if (!pending_calls.empty())
|
|
132
|
+
{
|
|
133
|
+
auto call = pending_calls.front();
|
|
134
|
+
pending_calls.pop();
|
|
135
|
+
AnyValue result = AnyValue::make_object({{"value", std::forward<From>(from)}, {"done", Constants::FALSE}});
|
|
136
|
+
call.first.resolve(result);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
struct YieldAwaiter
|
|
140
|
+
{
|
|
141
|
+
promise_type &p;
|
|
142
|
+
bool await_ready() { return false; }
|
|
143
|
+
void await_suspend(std::coroutine_handle<promise_type> h)
|
|
144
|
+
{
|
|
145
|
+
// Suspended at yield.
|
|
146
|
+
}
|
|
147
|
+
T await_resume() { return p.current_input; }
|
|
148
|
+
};
|
|
149
|
+
return YieldAwaiter{*this};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
template <typename T>
|
|
153
|
+
template <typename From>
|
|
154
|
+
void jspp::JsAsyncIterator<T>::promise_type::return_value(From &&from)
|
|
155
|
+
{
|
|
156
|
+
if (!pending_calls.empty())
|
|
157
|
+
{
|
|
158
|
+
auto call = pending_calls.front();
|
|
159
|
+
pending_calls.pop();
|
|
160
|
+
AnyValue result = AnyValue::make_object({{"value", std::forward<From>(from)}, {"done", Constants::TRUE}});
|
|
161
|
+
call.first.resolve(result);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
while (!pending_calls.empty())
|
|
165
|
+
{
|
|
166
|
+
auto call = pending_calls.front();
|
|
167
|
+
pending_calls.pop();
|
|
168
|
+
AnyValue result = AnyValue::make_object({{"value", Constants::UNDEFINED}, {"done", Constants::TRUE}});
|
|
169
|
+
call.first.resolve(result);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
template <typename T>
|
|
174
|
+
void jspp::JsAsyncIterator<T>::promise_type::fail_all(const AnyValue &reason)
|
|
175
|
+
{
|
|
176
|
+
while (!pending_calls.empty())
|
|
177
|
+
{
|
|
178
|
+
auto call = pending_calls.front();
|
|
179
|
+
pending_calls.pop();
|
|
180
|
+
call.first.reject(reason);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
template <typename T>
|
|
185
|
+
void jspp::JsAsyncIterator<T>::promise_type::unhandled_exception()
|
|
186
|
+
{
|
|
187
|
+
try
|
|
188
|
+
{
|
|
189
|
+
std::rethrow_exception(std::current_exception());
|
|
190
|
+
}
|
|
191
|
+
catch (const Exception &e)
|
|
192
|
+
{
|
|
193
|
+
fail_all(e.data);
|
|
194
|
+
}
|
|
195
|
+
catch (const std::exception &e)
|
|
196
|
+
{
|
|
197
|
+
fail_all(AnyValue::make_string(e.what()));
|
|
198
|
+
}
|
|
199
|
+
catch (...)
|
|
200
|
+
{
|
|
201
|
+
fail_all(AnyValue::make_string("Unknown error in async generator"));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
template <typename T>
|
|
206
|
+
auto jspp::JsAsyncIterator<T>::promise_type::await_transform(AnyValue value)
|
|
207
|
+
{
|
|
208
|
+
is_awaiting = true;
|
|
209
|
+
struct AsyncIterAwaiter
|
|
210
|
+
{
|
|
211
|
+
AnyValueAwaiter base_awaiter;
|
|
212
|
+
promise_type &p_ref;
|
|
213
|
+
|
|
214
|
+
bool await_ready() { return base_awaiter.await_ready(); }
|
|
215
|
+
void await_suspend(std::coroutine_handle<promise_type> h)
|
|
216
|
+
{
|
|
217
|
+
if (!base_awaiter.value.is_promise())
|
|
218
|
+
{
|
|
219
|
+
jspp::Scheduler::instance().enqueue([h]() mutable
|
|
220
|
+
{
|
|
221
|
+
auto &pr = h.promise();
|
|
222
|
+
pr.is_awaiting = false;
|
|
223
|
+
pr.is_running = true;
|
|
224
|
+
h.resume();
|
|
225
|
+
pr.is_running = false;
|
|
226
|
+
|
|
227
|
+
if (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
|
|
228
|
+
{
|
|
229
|
+
while (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
|
|
230
|
+
{
|
|
231
|
+
pr.is_running = true;
|
|
232
|
+
pr.current_input = pr.pending_calls.front().second;
|
|
233
|
+
h.resume();
|
|
234
|
+
pr.is_running = false;
|
|
235
|
+
}
|
|
236
|
+
} });
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
auto p = base_awaiter.value.as_promise();
|
|
240
|
+
p->then(
|
|
241
|
+
[h](AnyValue v) mutable
|
|
242
|
+
{
|
|
243
|
+
auto &pr = h.promise();
|
|
244
|
+
pr.is_awaiting = false;
|
|
245
|
+
pr.is_running = true;
|
|
246
|
+
h.resume();
|
|
247
|
+
pr.is_running = false;
|
|
248
|
+
|
|
249
|
+
if (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
|
|
250
|
+
{
|
|
251
|
+
while (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
|
|
252
|
+
{
|
|
253
|
+
pr.is_running = true;
|
|
254
|
+
pr.current_input = pr.pending_calls.front().second;
|
|
255
|
+
h.resume();
|
|
256
|
+
pr.is_running = false;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
[h](AnyValue e) mutable
|
|
261
|
+
{
|
|
262
|
+
auto &pr = h.promise();
|
|
263
|
+
pr.is_awaiting = false;
|
|
264
|
+
pr.is_running = true;
|
|
265
|
+
h.resume();
|
|
266
|
+
pr.is_running = false;
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
AnyValue await_resume()
|
|
270
|
+
{
|
|
271
|
+
return base_awaiter.await_resume();
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
return AsyncIterAwaiter{AnyValueAwaiter{std::move(value)}, *this};
|
|
275
|
+
}
|