@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.
- package/LICENSE +25 -21
- package/README.md +2 -16
- package/dist/ast/symbols.js +3 -0
- package/dist/cli.js +7 -4
- package/dist/core/codegen/control-flow-handlers.js +28 -9
- package/dist/core/codegen/expression-handlers.js +7 -4
- package/dist/core/codegen/function-handlers.js +45 -27
- package/dist/core/codegen/helpers.js +24 -17
- package/dist/core/codegen/index.js +16 -9
- package/dist/core/codegen/statement-handlers.js +242 -58
- package/package.json +2 -1
- package/src/prelude/any_value.hpp +27 -1
- package/src/prelude/any_value_access.hpp +161 -122
- package/src/prelude/any_value_helpers.hpp +2 -0
- package/src/prelude/index.hpp +3 -0
- package/src/prelude/library/promise.hpp +6 -14
- package/src/prelude/types.hpp +6 -0
- package/src/prelude/utils/access.hpp +35 -2
- package/src/prelude/values/array.hpp +2 -2
- package/src/prelude/values/async_iterator.hpp +79 -0
- package/src/prelude/values/function.hpp +2 -1
- package/src/prelude/values/helpers/array.hpp +3 -0
- package/src/prelude/values/helpers/async_iterator.hpp +275 -0
- package/src/prelude/values/helpers/function.hpp +4 -0
- package/src/prelude/values/helpers/promise.hpp +10 -3
- package/src/prelude/values/promise.hpp +4 -8
- package/src/prelude/values/prototypes/async_iterator.hpp +50 -0
|
@@ -3,149 +3,188 @@
|
|
|
3
3
|
#include "types.hpp"
|
|
4
4
|
#include "any_value.hpp"
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
namespace jspp
|
|
7
7
|
{
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
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
|
-
|
|
33
|
-
return
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
71
|
-
}
|
|
74
|
+
return get_own_property(key.to_std_string());
|
|
75
|
+
}
|
|
72
76
|
|
|
73
|
-
|
|
74
|
-
{
|
|
75
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
94
|
-
if (proto_it.has_value())
|
|
139
|
+
if (is_array())
|
|
95
140
|
{
|
|
96
|
-
return
|
|
141
|
+
return std::get<std::shared_ptr<JsArray>>(storage)->set_property(idx, value);
|
|
97
142
|
}
|
|
98
|
-
return
|
|
143
|
+
return set_own_property(std::to_string(idx), value);
|
|
99
144
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
112
|
-
{
|
|
113
|
-
switch (get_type())
|
|
159
|
+
AnyValue AnyValue::call_own_property(const std::string &key, std::span<const AnyValue> args) const
|
|
114
160
|
{
|
|
115
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
|
|
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:
|
package/src/prelude/index.hpp
CHANGED
|
@@ -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::
|
|
24
|
-
return jspp::
|
|
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::
|
|
31
|
-
return jspp::
|
|
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::
|
|
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::
|
|
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"));
|
package/src/prelude/types.hpp
CHANGED
|
@@ -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)
|
|
21
|
-
explicit JsArray(std::vector<AnyValue> &&items)
|
|
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>)
|
|
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)
|