@ugo-studio/jspp 0.1.5 → 0.1.7

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.
@@ -3,149 +3,188 @@
3
3
  #include "types.hpp"
4
4
  #include "any_value.hpp"
5
5
 
6
- jspp::AnyValue jspp::AnyValue::get_own_property(const std::string &key) const
6
+ namespace jspp
7
7
  {
8
- return get_property_with_receiver(key, *this);
9
- }
10
- bool jspp::AnyValue::has_property(const std::string &key) const
11
- {
12
- switch (get_type())
8
+ AnyValue AnyValue::get_own_property(const std::string &key) const
9
+ {
10
+ return get_property_with_receiver(key, *this);
11
+ }
12
+ bool AnyValue::has_property(const std::string &key) const
13
13
  {
14
- case JsType::Object:
15
- return std::get<std::shared_ptr<JsObject>>(storage)->has_property(key);
16
- case JsType::Array:
17
- return std::get<std::shared_ptr<JsArray>>(storage)->has_property(key);
18
- case JsType::Function:
19
- return std::get<std::shared_ptr<JsFunction>>(storage)->has_property(key);
20
- case JsType::Promise:
21
- // Promises don't have their own props usually, but could.
22
- return false;
23
- case JsType::Iterator:
24
- return false;
25
- case JsType::Symbol:
26
- return false;
27
- case JsType::String:
28
- if (key == "length")
29
- return true;
30
- if (JsArray::is_array_index(key))
14
+ switch (get_type())
31
15
  {
32
- uint32_t idx = static_cast<uint32_t>(std::stoull(key));
33
- return idx < std::get<std::shared_ptr<JsString>>(storage)->value.length();
16
+ case JsType::Object:
17
+ return std::get<std::shared_ptr<JsObject>>(storage)->has_property(key);
18
+ case JsType::Array:
19
+ return std::get<std::shared_ptr<JsArray>>(storage)->has_property(key);
20
+ case JsType::Function:
21
+ return std::get<std::shared_ptr<JsFunction>>(storage)->has_property(key);
22
+ case JsType::Promise:
23
+ // Promises don't have their own props usually, but could.
24
+ return false;
25
+ case JsType::Iterator:
26
+ return false;
27
+ case JsType::AsyncIterator:
28
+ return false;
29
+ case JsType::Symbol:
30
+ return false;
31
+ case JsType::String:
32
+ if (key == "length")
33
+ return true;
34
+ if (JsArray::is_array_index(key))
35
+ {
36
+ uint32_t idx = static_cast<uint32_t>(std::stoull(key));
37
+ return idx < std::get<std::shared_ptr<JsString>>(storage)->value.length();
38
+ }
39
+ return false;
40
+ case JsType::Number:
41
+ return false;
42
+ case JsType::Uninitialized:
43
+ Exception::throw_uninitialized_reference("#<Object>");
44
+ return false;
45
+ default:
46
+ return false;
34
47
  }
35
- return false;
36
- case JsType::Number:
37
- return false;
38
- case JsType::Uninitialized:
39
- Exception::throw_uninitialized_reference("#<Object>");
40
- return false;
41
- default:
42
- return false;
43
48
  }
44
- }
45
- jspp::AnyValue jspp::AnyValue::get_own_property(uint32_t idx) const
46
- {
47
- switch (storage.index())
49
+ AnyValue AnyValue::get_own_property(uint32_t idx) const
48
50
  {
49
- case 7: // Array
50
- return std::get<std::shared_ptr<JsArray>>(storage)->get_property(idx);
51
- case 5: // String
52
- return std::get<std::shared_ptr<JsString>>(storage)->get_property(idx);
53
- case 4: // Number
54
- return get_own_property(std::to_string(idx));
55
- default:
56
- return get_own_property(std::to_string(idx));
51
+ switch (storage.index())
52
+ {
53
+ case 7: // Array
54
+ return std::get<std::shared_ptr<JsArray>>(storage)->get_property(idx);
55
+ case 5: // String
56
+ return std::get<std::shared_ptr<JsString>>(storage)->get_property(idx);
57
+ case 4: // Number
58
+ return get_own_property(std::to_string(idx));
59
+ default:
60
+ return get_own_property(std::to_string(idx));
61
+ }
57
62
  }
58
- }
59
- jspp::AnyValue jspp::AnyValue::get_own_property(const AnyValue &key) const
60
- {
61
- if (key.is_number() && is_array())
62
- return std::get<std::shared_ptr<JsArray>>(storage)->get_property(key.as_double());
63
- if (key.is_number() && is_string())
64
- return std::get<std::shared_ptr<JsString>>(storage)->get_property(key.as_double());
63
+ AnyValue AnyValue::get_own_property(const AnyValue &key) const
64
+ {
65
+ if (key.is_number() && is_array())
66
+ return std::get<std::shared_ptr<JsArray>>(storage)->get_property(key.as_double());
67
+ if (key.is_number() && is_string())
68
+ return std::get<std::shared_ptr<JsString>>(storage)->get_property(key.as_double());
65
69
 
66
- // If the key is a Symbol, use its internal key string
67
- if (key.is_symbol())
68
- return get_own_property(key.as_symbol()->key);
70
+ // If the key is a Symbol, use its internal key string
71
+ if (key.is_symbol())
72
+ return get_own_property(key.as_symbol()->key);
69
73
 
70
- return get_own_property(key.to_std_string());
71
- }
74
+ return get_own_property(key.to_std_string());
75
+ }
72
76
 
73
- jspp::AnyValue jspp::AnyValue::get_property_with_receiver(const std::string &key, const AnyValue &receiver) const
74
- {
75
- switch (get_type())
77
+ AnyValue AnyValue::get_property_with_receiver(const std::string &key, const AnyValue &receiver) const
78
+ {
79
+ switch (get_type())
80
+ {
81
+ case JsType::Object:
82
+ return std::get<std::shared_ptr<JsObject>>(storage)->get_property(key, receiver);
83
+ case JsType::Array:
84
+ return std::get<std::shared_ptr<JsArray>>(storage)->get_property(key, receiver);
85
+ case JsType::Function:
86
+ return std::get<std::shared_ptr<JsFunction>>(storage)->get_property(key, receiver);
87
+ case JsType::Promise:
88
+ return std::get<std::shared_ptr<JsPromise>>(storage)->get_property(key, receiver);
89
+ case JsType::Iterator:
90
+ return std::get<std::shared_ptr<JsIterator<AnyValue>>>(storage)->get_property(key, receiver);
91
+ case JsType::AsyncIterator:
92
+ return std::get<std::shared_ptr<JsAsyncIterator<AnyValue>>>(storage)->get_property(key, receiver);
93
+ case JsType::Symbol:
94
+ return std::get<std::shared_ptr<JsSymbol>>(storage)->get_property(key, receiver);
95
+ case JsType::String:
96
+ return std::get<std::shared_ptr<JsString>>(storage)->get_property(key, receiver);
97
+ case JsType::Number:
98
+ {
99
+ auto proto_it = NumberPrototypes::get(key, std::get<double>(storage));
100
+ if (proto_it.has_value())
101
+ {
102
+ return AnyValue::resolve_property_for_read(proto_it.value(), receiver, key);
103
+ }
104
+ return AnyValue::make_undefined();
105
+ }
106
+ case JsType::Undefined:
107
+ throw Exception::make_exception("Cannot read properties of undefined (reading '" + key + "')", "TypeError");
108
+ case JsType::Null:
109
+ throw Exception::make_exception("Cannot read properties of null (reading '" + key + "')", "TypeError");
110
+ case JsType::Uninitialized:
111
+ Exception::throw_uninitialized_reference("#<Object>");
112
+ default:
113
+ return AnyValue::make_undefined();
114
+ }
115
+ }
116
+
117
+ AnyValue AnyValue::set_own_property(const std::string &key, const AnyValue &value) const
76
118
  {
77
- case JsType::Object:
78
- return std::get<std::shared_ptr<JsObject>>(storage)->get_property(key, receiver);
79
- case JsType::Array:
80
- return std::get<std::shared_ptr<JsArray>>(storage)->get_property(key, receiver);
81
- case JsType::Function:
82
- return std::get<std::shared_ptr<JsFunction>>(storage)->get_property(key, receiver);
83
- case JsType::Promise:
84
- return std::get<std::shared_ptr<JsPromise>>(storage)->get_property(key, receiver);
85
- case JsType::Iterator:
86
- return std::get<std::shared_ptr<JsIterator<AnyValue>>>(storage)->get_property(key, receiver);
87
- case JsType::Symbol:
88
- return std::get<std::shared_ptr<JsSymbol>>(storage)->get_property(key, receiver);
89
- case JsType::String:
90
- return std::get<std::shared_ptr<JsString>>(storage)->get_property(key, receiver);
91
- case JsType::Number:
119
+ switch (get_type())
120
+ {
121
+ case JsType::Object:
122
+ return std::get<std::shared_ptr<JsObject>>(storage)->set_property(key, value, *this);
123
+ case JsType::Array:
124
+ return std::get<std::shared_ptr<JsArray>>(storage)->set_property(key, value, *this);
125
+ case JsType::Function:
126
+ return std::get<std::shared_ptr<JsFunction>>(storage)->set_property(key, value, *this);
127
+ case JsType::Promise:
128
+ return std::get<std::shared_ptr<JsPromise>>(storage)->set_property(key, value, *this);
129
+ case JsType::Undefined:
130
+ throw Exception::make_exception("Cannot set properties of undefined (setting '" + key + "')", "TypeError");
131
+ case JsType::Null:
132
+ throw Exception::make_exception("Cannot set properties of null (setting '" + key + "')", "TypeError");
133
+ default:
134
+ return value;
135
+ }
136
+ }
137
+ AnyValue AnyValue::set_own_property(uint32_t idx, const AnyValue &value) const
92
138
  {
93
- auto proto_it = NumberPrototypes::get(key, std::get<double>(storage));
94
- if (proto_it.has_value())
139
+ if (is_array())
95
140
  {
96
- return AnyValue::resolve_property_for_read(proto_it.value(), receiver, key);
141
+ return std::get<std::shared_ptr<JsArray>>(storage)->set_property(idx, value);
97
142
  }
98
- return AnyValue::make_undefined();
143
+ return set_own_property(std::to_string(idx), value);
99
144
  }
100
- case JsType::Undefined:
101
- throw Exception::make_exception("Cannot read properties of undefined (reading '" + key + "')", "TypeError");
102
- case JsType::Null:
103
- throw Exception::make_exception("Cannot read properties of null (reading '" + key + "')", "TypeError");
104
- case JsType::Uninitialized:
105
- Exception::throw_uninitialized_reference("#<Object>");
106
- default:
107
- return AnyValue::make_undefined();
145
+ AnyValue AnyValue::set_own_property(const AnyValue &key, const AnyValue &value) const
146
+ {
147
+ if (key.is_number() && is_array())
148
+ {
149
+ return std::get<std::shared_ptr<JsArray>>(storage)->set_property(key.as_double(), value);
150
+ }
151
+
152
+ // If the key is a Symbol, use its internal key string
153
+ if (key.is_symbol())
154
+ return set_own_property(key.as_symbol()->key, value);
155
+
156
+ return set_own_property(key.to_std_string(), value);
108
157
  }
109
- }
110
158
 
111
- jspp::AnyValue jspp::AnyValue::set_own_property(const std::string &key, const AnyValue &value) const
112
- {
113
- switch (get_type())
159
+ AnyValue AnyValue::call_own_property(const std::string &key, std::span<const AnyValue> args) const
114
160
  {
115
- case JsType::Object:
116
- return std::get<std::shared_ptr<JsObject>>(storage)->set_property(key, value, *this);
117
- case JsType::Array:
118
- return std::get<std::shared_ptr<JsArray>>(storage)->set_property(key, value, *this);
119
- case JsType::Function:
120
- return std::get<std::shared_ptr<JsFunction>>(storage)->set_property(key, value, *this);
121
- case JsType::Promise:
122
- return std::get<std::shared_ptr<JsPromise>>(storage)->set_property(key, value, *this);
123
- case JsType::Undefined:
124
- throw Exception::make_exception("Cannot set properties of undefined (setting '" + key + "')", "TypeError");
125
- case JsType::Null:
126
- throw Exception::make_exception("Cannot set properties of null (setting '" + key + "')", "TypeError");
127
- default:
128
- return value;
161
+ return get_own_property(key).call((*this), args, key);
129
162
  }
130
- }
131
- jspp::AnyValue jspp::AnyValue::set_own_property(uint32_t idx, const AnyValue &value) const
132
- {
133
- if (is_array())
163
+ AnyValue AnyValue::call_own_property(uint32_t idx, std::span<const AnyValue> args) const
134
164
  {
135
- return std::get<std::shared_ptr<JsArray>>(storage)->set_property(idx, value);
165
+ switch (storage.index())
166
+ {
167
+ case 7: // Array
168
+ return std::get<std::shared_ptr<JsArray>>(storage)->get_property(idx).call((*this), args, "[" + std::to_string(idx) + "]");
169
+ case 5: // String
170
+ return std::get<std::shared_ptr<JsString>>(storage)->get_property(idx).call((*this), args, "[" + std::to_string(idx) + "]");
171
+ case 4: // Number
172
+ return call_own_property(std::to_string(idx), args);
173
+ default:
174
+ return call_own_property(std::to_string(idx), args);
175
+ }
136
176
  }
137
- return set_own_property(std::to_string(idx), value);
138
- }
139
- jspp::AnyValue jspp::AnyValue::set_own_property(const AnyValue &key, const AnyValue &value) const
140
- {
141
- if (key.is_number() && is_array())
177
+ AnyValue AnyValue::call_own_property(const AnyValue &key, std::span<const AnyValue> args) const
142
178
  {
143
- return std::get<std::shared_ptr<JsArray>>(storage)->set_property(key.as_double(), value);
144
- }
179
+ if (key.is_number() && is_array())
180
+ return std::get<std::shared_ptr<JsArray>>(storage)->get_property(key.as_double()).call((*this), args, "[" + key.to_std_string() + "]");
181
+ if (key.is_number() && is_string())
182
+ return std::get<std::shared_ptr<JsString>>(storage)->get_property(key.as_double()).call((*this), args, "[" + key.to_std_string() + "]");
145
183
 
146
- // If the key is a Symbol, use its internal key string
147
- if (key.is_symbol())
148
- return set_own_property(key.as_symbol()->key, value);
184
+ // If the key is a Symbol, use its internal key string
185
+ if (key.is_symbol())
186
+ return call_own_property(key.as_symbol()->key, args);
149
187
 
150
- return set_own_property(key.to_std_string(), value);
151
- }
188
+ return call_own_property(key.to_std_string(), args);
189
+ }
190
+ }
@@ -27,6 +27,8 @@ namespace jspp
27
27
  return std::get<std::shared_ptr<JsFunction>>(storage)->to_std_string();
28
28
  case JsType::Iterator:
29
29
  return std::get<std::shared_ptr<JsIterator<AnyValue>>>(storage)->to_std_string();
30
+ case JsType::AsyncIterator:
31
+ return std::get<std::shared_ptr<JsAsyncIterator<AnyValue>>>(storage)->to_std_string();
30
32
  case JsType::Promise:
31
33
  return std::get<std::shared_ptr<JsPromise>>(storage)->to_std_string();
32
34
  case JsType::Symbol:
@@ -11,6 +11,7 @@
11
11
  #include "values/array.hpp"
12
12
  #include "values/function.hpp"
13
13
  #include "values/iterator.hpp"
14
+ #include "values/async_iterator.hpp"
14
15
  #include "values/promise.hpp"
15
16
  #include "values/string.hpp"
16
17
 
@@ -28,6 +29,7 @@
28
29
  #include "values/prototypes/array.hpp"
29
30
  #include "values/prototypes/function.hpp"
30
31
  #include "values/prototypes/iterator.hpp"
32
+ #include "values/prototypes/async_iterator.hpp"
31
33
  #include "values/prototypes/promise.hpp"
32
34
  #include "values/prototypes/string.hpp"
33
35
  #include "values/prototypes/number.hpp"
@@ -37,6 +39,7 @@
37
39
  #include "values/helpers/array.hpp"
38
40
  #include "values/helpers/function.hpp"
39
41
  #include "values/helpers/iterator.hpp"
42
+ #include "values/helpers/async_iterator.hpp"
40
43
  #include "values/helpers/promise.hpp"
41
44
  #include "values/helpers/string.hpp"
42
45
 
@@ -20,15 +20,15 @@ inline auto Promise = jspp::AnyValue::make_function([](const jspp::AnyValue &thi
20
20
  auto resolveFn = jspp::AnyValue::make_function([state](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
21
21
  {
22
22
  jspp::JsPromise p; p.state = state;
23
- p.resolve(args.empty() ? jspp::AnyValue::make_undefined() : args[0]);
24
- return jspp::AnyValue::make_undefined(); }, "resolve");
23
+ p.resolve(args.empty() ? jspp::Constants::UNDEFINED : args[0]);
24
+ return jspp::Constants::UNDEFINED; }, "resolve");
25
25
 
26
26
  // reject function
27
27
  auto rejectFn = jspp::AnyValue::make_function([state](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
28
28
  {
29
29
  jspp::JsPromise p; p.state = state;
30
- p.reject(args.empty() ? jspp::AnyValue::make_undefined() : args[0]);
31
- return jspp::AnyValue::make_undefined(); }, "reject");
30
+ p.reject(args.empty() ? jspp::Constants::UNDEFINED : args[0]);
31
+ return jspp::Constants::UNDEFINED; }, "reject");
32
32
 
33
33
  try
34
34
  {
@@ -55,27 +55,19 @@ struct PromiseInit
55
55
  Promise.define_data_property("resolve", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
56
56
  {
57
57
  jspp::JsPromise p;
58
- p.resolve(args.empty() ? jspp::AnyValue::make_undefined() : args[0]);
58
+ p.resolve(args.empty() ? jspp::Constants::UNDEFINED : args[0]);
59
59
  return jspp::AnyValue::make_promise(p); }, "resolve"));
60
60
 
61
61
  // Promise.reject(reason)
62
62
  Promise.define_data_property("reject", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
63
63
  {
64
64
  jspp::JsPromise p;
65
- p.reject(args.empty() ? jspp::AnyValue::make_undefined() : args[0]);
65
+ p.reject(args.empty() ? jspp::Constants::UNDEFINED : args[0]);
66
66
  return jspp::AnyValue::make_promise(p); }, "reject"));
67
67
 
68
68
  // Promise.all(iterable)
69
69
  Promise.define_data_property("all", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
70
70
  {
71
- // Basic implementation for arrays
72
- if (args.empty() || !args[0].is_array()) {
73
- // If not array, reject? Or treat as non-iterable?
74
- // Should throw TypeError if not iterable. For now assume array.
75
- // If empty array, return resolved empty array.
76
- // TODO: Strict iterable check
77
- }
78
-
79
71
  // Handle non-array iterable or empty args
80
72
  if (args.empty() || !args[0].is_array()) {
81
73
  jspp::JsPromise p; p.reject(jspp::AnyValue::make_string("Promise.all argument must be an array"));
@@ -33,6 +33,9 @@ namespace jspp
33
33
  template <typename T>
34
34
  class JsIterator; // can set property
35
35
 
36
+ template <typename T>
37
+ class JsAsyncIterator; // can set property
38
+
36
39
  // Object property configuration forward declarations
37
40
  struct DataDescriptor;
38
41
  struct AccessorDescriptor;
@@ -43,6 +46,9 @@ namespace jspp
43
46
  // Dynamic AnyValue
44
47
  class AnyValue;
45
48
 
49
+ // Awaiter for AnyValue
50
+ struct AnyValueAwaiter;
51
+
46
52
  // Truthiness checker
47
53
  const bool is_truthy(const double &val) noexcept;
48
54
  const bool is_truthy(const std::string &val) noexcept;
@@ -91,6 +91,8 @@ namespace jspp
91
91
  return AnyValue::make_string("object");
92
92
  case JsType::Iterator:
93
93
  return AnyValue::make_string("object");
94
+ case JsType::AsyncIterator:
95
+ return AnyValue::make_string("object");
94
96
  default:
95
97
  return AnyValue::make_string("undefined");
96
98
  }
@@ -169,6 +171,7 @@ namespace jspp
169
171
 
170
172
  return keys;
171
173
  }
174
+
172
175
  inline AnyValue get_object_value_iterator(const AnyValue &obj, const std::string &name)
173
176
  {
174
177
  if (obj.is_iterator())
@@ -197,6 +200,32 @@ namespace jspp
197
200
  throw jspp::Exception::make_exception(name + " is not iterable", "TypeError");
198
201
  }
199
202
 
203
+ inline AnyValue get_async_object_value_iterator(const AnyValue &obj, const std::string &name)
204
+ {
205
+ if (obj.is_async_iterator())
206
+ return obj;
207
+
208
+ // 1. Try Symbol.asyncIterator
209
+ auto method = obj.get_own_property(WellKnownSymbols::asyncIterator->key);
210
+ if (method.is_function())
211
+ {
212
+ auto iter = method.call(obj, {}, WellKnownSymbols::asyncIterator->key);
213
+ if (iter.is_object() || iter.is_async_iterator() || iter.is_iterator())
214
+ return iter;
215
+ }
216
+
217
+ // 2. Try Symbol.iterator (sync fallback)
218
+ auto syncMethod = obj.get_own_property(WellKnownSymbols::iterator->key);
219
+ if (syncMethod.is_function())
220
+ {
221
+ auto iter = syncMethod.call(obj, {}, WellKnownSymbols::iterator->key);
222
+ if (iter.is_object() || iter.is_iterator())
223
+ return iter;
224
+ }
225
+
226
+ throw jspp::Exception::make_exception(name + " is not async iterable", "TypeError");
227
+ }
228
+
200
229
  inline AnyValue in(const AnyValue &lhs, const AnyValue &rhs)
201
230
  {
202
231
  if (!rhs.is_object() && !rhs.is_array() && !rhs.is_function() && !rhs.is_promise() && !rhs.is_iterator())
@@ -212,7 +241,7 @@ namespace jspp
212
241
  {
213
242
  throw jspp::Exception::make_exception("Right-hand side of 'instanceof' is not callable", "TypeError");
214
243
  }
215
- if (!lhs.is_object() && !lhs.is_array() && !lhs.is_function() && !lhs.is_promise() && !lhs.is_iterator())
244
+ if (!lhs.is_object() && !lhs.is_array() && !lhs.is_function() && !lhs.is_promise() && !lhs.is_iterator() && !lhs.is_async_iterator())
216
245
  {
217
246
  return Constants::FALSE;
218
247
  }
@@ -256,6 +285,11 @@ namespace jspp
256
285
  // Promises don't store explicit proto yet in our impl
257
286
  break;
258
287
  }
288
+ else if (current.is_async_iterator())
289
+ {
290
+ // AsyncIterators don't store explicit proto yet in our impl
291
+ break;
292
+ }
259
293
  else
260
294
  {
261
295
  break;
@@ -341,5 +375,4 @@ namespace jspp
341
375
  }
342
376
 
343
377
  }
344
-
345
378
  }
@@ -17,8 +17,8 @@ namespace jspp
17
17
  uint64_t length = 0;
18
18
 
19
19
  JsArray() : proto(nullptr) {}
20
- explicit JsArray(const std::vector<AnyValue> &items) : dense(items), proto(nullptr), length(items.size()) {}
21
- explicit JsArray(std::vector<AnyValue> &&items) : dense(std::move(items)), proto(nullptr), length(dense.size()) {}
20
+ explicit JsArray(const std::vector<AnyValue> &items);
21
+ explicit JsArray(std::vector<AnyValue> &&items);
22
22
 
23
23
  std::string to_std_string() const;
24
24
  JsIterator<AnyValue> get_iterator();
@@ -0,0 +1,79 @@
1
+ #pragma once
2
+
3
+ #include "types.hpp"
4
+ #include <coroutine>
5
+ #include <optional>
6
+ #include <queue>
7
+ #include <iostream>
8
+ #include <utility>
9
+ #include <exception>
10
+ #include "values/promise.hpp"
11
+ #include "scheduler.hpp"
12
+
13
+ namespace jspp
14
+ {
15
+ // Forward declaration of AnyValue
16
+ class AnyValue;
17
+
18
+ template <typename T>
19
+ class JsAsyncIterator
20
+ {
21
+ public:
22
+ struct promise_type
23
+ {
24
+ std::queue<std::pair<JsPromise, T>> pending_calls;
25
+ bool is_awaiting = false;
26
+ bool is_running = false;
27
+ T current_input;
28
+
29
+ JsAsyncIterator get_return_object()
30
+ {
31
+ return JsAsyncIterator{
32
+ std::coroutine_handle<promise_type>::from_promise(*this)};
33
+ }
34
+
35
+ std::suspend_always initial_suspend() noexcept { return {}; }
36
+
37
+ std::suspend_always final_suspend() noexcept { return {}; }
38
+
39
+ // Declarations
40
+ template <typename From>
41
+ auto yield_value(From &&from);
42
+
43
+ template <typename From>
44
+ void return_value(From &&from);
45
+
46
+ void unhandled_exception();
47
+
48
+ void fail_all(const AnyValue &reason);
49
+
50
+ auto await_transform(AnyValue value);
51
+ };
52
+
53
+ using handle_type = std::coroutine_handle<promise_type>;
54
+ handle_type handle;
55
+
56
+ explicit JsAsyncIterator(handle_type h) : handle(h) {}
57
+ JsAsyncIterator(JsAsyncIterator &&other) noexcept : handle(std::exchange(other.handle, nullptr)) {}
58
+
59
+ JsAsyncIterator(const JsAsyncIterator &) = delete;
60
+ JsAsyncIterator &operator=(const JsAsyncIterator &) = delete;
61
+
62
+ ~JsAsyncIterator()
63
+ {
64
+ if (handle)
65
+ handle.destroy();
66
+ }
67
+
68
+ std::unordered_map<std::string, AnyValue> props;
69
+
70
+ std::string to_std_string() const;
71
+
72
+ JsPromise next(const T &val = T());
73
+
74
+ AnyValue get_property(const std::string &key, const AnyValue &thisVal);
75
+ AnyValue set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal);
76
+
77
+ void resume_next();
78
+ };
79
+ }
@@ -11,7 +11,8 @@ namespace jspp
11
11
 
12
12
  using JsFunctionCallable = std::variant<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>, // 0: Normal
13
13
  std::function<jspp::JsIterator<jspp::AnyValue>(const AnyValue &, std::span<const AnyValue>)>, // 1: Generator
14
- std::function<jspp::JsPromise(const AnyValue &, std::span<const AnyValue>)>>; // 2: Async
14
+ std::function<jspp::JsPromise(const AnyValue &, std::span<const AnyValue>)>, // 2: Async
15
+ std::function<jspp::JsAsyncIterator<jspp::AnyValue>(const AnyValue &, std::span<const AnyValue>)>>; // 3: Async Generator
15
16
 
16
17
  struct JsFunction
17
18
  {
@@ -6,6 +6,9 @@
6
6
  #include "any_value.hpp"
7
7
  #include "values/prototypes/array.hpp"
8
8
 
9
+ jspp::JsArray::JsArray(const std::vector<jspp::AnyValue> &items) : dense(items), proto(nullptr), length(items.size()) {}
10
+ jspp::JsArray::JsArray(std::vector<jspp::AnyValue> &&items) : dense(std::move(items)), proto(nullptr), length(dense.size()) {}
11
+
9
12
  std::string jspp::JsArray::to_std_string() const
10
13
  {
11
14
  if (length == 0)