@ugo-studio/jspp 0.3.0 → 0.3.2
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 -25
- package/README.md +20 -12
- package/dist/cli/args.js +22 -0
- package/dist/cli/compiler.js +53 -0
- package/dist/cli/index.js +43 -107
- package/dist/cli/pch.js +71 -0
- package/dist/cli/runner.js +23 -0
- package/dist/cli/spinner.js +27 -11
- package/dist/cli/transpiler.js +20 -0
- package/dist/cli/utils.js +59 -0
- package/dist/cli/wasm.js +70 -0
- package/dist/index.js +17 -6
- package/dist/{analysis → interpreter/analysis}/scope.js +38 -3
- package/dist/{analysis → interpreter/analysis}/typeAnalyzer.js +563 -28
- package/dist/{core → interpreter/core}/codegen/class-handlers.js +1 -1
- package/dist/{core → interpreter/core}/codegen/control-flow-handlers.js +12 -11
- package/dist/{core → interpreter/core}/codegen/declaration-handlers.js +28 -9
- package/dist/{core → interpreter/core}/codegen/destructuring-handlers.js +9 -4
- package/dist/{core → interpreter/core}/codegen/expression-handlers.js +82 -88
- package/dist/{core → interpreter/core}/codegen/function-handlers.js +159 -46
- package/dist/{core → interpreter/core}/codegen/helpers.js +170 -25
- package/dist/interpreter/core/codegen/index.js +156 -0
- package/dist/{core → interpreter/core}/codegen/literal-handlers.js +9 -0
- package/dist/{core → interpreter/core}/codegen/statement-handlers.js +47 -7
- package/package.json +6 -4
- package/scripts/precompile-headers.ts +293 -50
- package/scripts/setup-compiler.ts +63 -63
- package/scripts/setup-emsdk.ts +114 -0
- package/src/prelude/any_value.cpp +888 -0
- package/src/prelude/any_value.hpp +29 -24
- package/src/prelude/{exception_helpers.hpp → exception.cpp} +53 -53
- package/src/prelude/exception.hpp +27 -27
- package/src/prelude/iterator_instantiations.hpp +10 -0
- package/src/prelude/{index.hpp → jspp.hpp} +13 -17
- package/src/prelude/library/array.cpp +191 -0
- package/src/prelude/library/array.hpp +5 -178
- package/src/prelude/library/boolean.cpp +30 -0
- package/src/prelude/library/boolean.hpp +14 -0
- package/src/prelude/library/console.cpp +125 -0
- package/src/prelude/library/console.hpp +9 -97
- package/src/prelude/library/error.cpp +100 -0
- package/src/prelude/library/error.hpp +8 -108
- package/src/prelude/library/function.cpp +69 -0
- package/src/prelude/library/function.hpp +6 -5
- package/src/prelude/library/global.cpp +98 -0
- package/src/prelude/library/global.hpp +12 -28
- package/src/prelude/library/global_usings.hpp +15 -0
- package/src/prelude/library/math.cpp +261 -0
- package/src/prelude/library/math.hpp +8 -288
- package/src/prelude/library/object.cpp +379 -0
- package/src/prelude/library/object.hpp +5 -267
- package/src/prelude/library/performance.cpp +21 -0
- package/src/prelude/library/performance.hpp +5 -20
- package/src/prelude/library/process.cpp +38 -0
- package/src/prelude/library/process.hpp +3 -31
- package/src/prelude/library/promise.cpp +131 -0
- package/src/prelude/library/promise.hpp +5 -116
- package/src/prelude/library/symbol.cpp +56 -0
- package/src/prelude/library/symbol.hpp +5 -46
- package/src/prelude/library/timer.cpp +88 -0
- package/src/prelude/library/timer.hpp +11 -87
- package/src/prelude/runtime.cpp +19 -0
- package/src/prelude/types.hpp +26 -20
- package/src/prelude/utils/access.hpp +123 -32
- package/src/prelude/utils/assignment_operators.hpp +119 -99
- package/src/prelude/utils/log_any_value/array.hpp +61 -40
- package/src/prelude/utils/log_any_value/function.hpp +39 -39
- package/src/prelude/utils/log_any_value/log_any_value.hpp +1 -1
- package/src/prelude/utils/log_any_value/object.hpp +60 -3
- package/src/prelude/utils/log_any_value/primitives.hpp +1 -1
- package/src/prelude/utils/operators.hpp +109 -94
- package/src/prelude/utils/operators_native.hpp +349 -0
- package/src/prelude/utils/well_known_symbols.hpp +24 -24
- package/src/prelude/values/array.cpp +1399 -0
- package/src/prelude/values/array.hpp +4 -0
- package/src/prelude/values/async_iterator.cpp +251 -0
- package/src/prelude/values/async_iterator.hpp +60 -32
- package/src/prelude/values/boolean.cpp +64 -0
- package/src/prelude/values/function.cpp +262 -0
- package/src/prelude/values/function.hpp +10 -30
- package/src/prelude/values/iterator.cpp +309 -0
- package/src/prelude/values/iterator.hpp +33 -64
- package/src/prelude/values/number.cpp +221 -0
- package/src/prelude/values/object.cpp +200 -0
- package/src/prelude/values/object.hpp +4 -0
- package/src/prelude/values/promise.cpp +479 -0
- package/src/prelude/values/promise.hpp +9 -2
- package/src/prelude/values/prototypes/array.hpp +46 -1348
- package/src/prelude/values/prototypes/async_iterator.hpp +19 -61
- package/src/prelude/values/prototypes/boolean.hpp +24 -0
- package/src/prelude/values/prototypes/function.hpp +7 -46
- package/src/prelude/values/prototypes/iterator.hpp +15 -191
- package/src/prelude/values/prototypes/number.hpp +30 -210
- package/src/prelude/values/prototypes/object.hpp +7 -23
- package/src/prelude/values/prototypes/promise.hpp +8 -186
- package/src/prelude/values/prototypes/string.hpp +28 -553
- package/src/prelude/values/prototypes/symbol.hpp +9 -70
- package/src/prelude/values/shape.hpp +52 -52
- package/src/prelude/values/string.cpp +485 -0
- package/src/prelude/values/symbol.cpp +89 -0
- package/src/prelude/values/symbol.hpp +101 -101
- package/dist/cli/file-utils.js +0 -20
- package/dist/cli-utils/args.js +0 -59
- package/dist/cli-utils/colors.js +0 -9
- package/dist/cli-utils/file-utils.js +0 -20
- package/dist/cli-utils/spinner.js +0 -55
- package/dist/cli.js +0 -153
- package/dist/core/codegen/index.js +0 -86
- package/src/prelude/any_value_access.hpp +0 -170
- package/src/prelude/any_value_defines.hpp +0 -190
- package/src/prelude/any_value_helpers.hpp +0 -374
- package/src/prelude/utils/operators_primitive.hpp +0 -337
- package/src/prelude/values/helpers/array.hpp +0 -199
- package/src/prelude/values/helpers/async_iterator.hpp +0 -275
- package/src/prelude/values/helpers/function.hpp +0 -109
- package/src/prelude/values/helpers/iterator.hpp +0 -145
- package/src/prelude/values/helpers/object.hpp +0 -104
- package/src/prelude/values/helpers/promise.hpp +0 -254
- package/src/prelude/values/helpers/string.hpp +0 -37
- package/src/prelude/values/helpers/symbol.hpp +0 -21
- /package/dist/{ast → interpreter/ast}/symbols.js +0 -0
- /package/dist/{ast → interpreter/ast}/types.js +0 -0
- /package/dist/{core → interpreter/core}/codegen/visitor.js +0 -0
- /package/dist/{core → interpreter/core}/constants.js +0 -0
- /package/dist/{core → interpreter/core}/error.js +0 -0
- /package/dist/{core → interpreter/core}/parser.js +0 -0
- /package/dist/{core → interpreter/core}/traverser.js +0 -0
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
#include "jspp.hpp"
|
|
2
|
+
#include "values/promise.hpp"
|
|
3
|
+
#include "values/prototypes/promise.hpp"
|
|
4
|
+
|
|
5
|
+
namespace jspp {
|
|
6
|
+
|
|
7
|
+
// --- PromiseState Implementation ---
|
|
8
|
+
|
|
9
|
+
PromiseState::PromiseState() : result(Constants::UNDEFINED), handled(false) {}
|
|
10
|
+
|
|
11
|
+
PromiseState::~PromiseState()
|
|
12
|
+
{
|
|
13
|
+
if (status == PromiseStatus::Rejected && !handled)
|
|
14
|
+
{
|
|
15
|
+
std::string msg;
|
|
16
|
+
try
|
|
17
|
+
{
|
|
18
|
+
if (result.is_object() || result.is_function())
|
|
19
|
+
{
|
|
20
|
+
msg = result.call_own_property("toString", {}).to_std_string();
|
|
21
|
+
}
|
|
22
|
+
else
|
|
23
|
+
{
|
|
24
|
+
msg = result.to_std_string();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (...)
|
|
28
|
+
{
|
|
29
|
+
msg = result.to_std_string();
|
|
30
|
+
}
|
|
31
|
+
std::cerr << "UnhandledPromiseRejection: " << msg << "\n";
|
|
32
|
+
std::exit(1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// --- JsPromise Implementation ---
|
|
37
|
+
|
|
38
|
+
JsPromise::JsPromise() : state(std::make_shared<PromiseState>()) {}
|
|
39
|
+
|
|
40
|
+
void JsPromise::resolve(AnyValue value)
|
|
41
|
+
{
|
|
42
|
+
if (state->status != PromiseStatus::Pending)
|
|
43
|
+
return;
|
|
44
|
+
|
|
45
|
+
if (value.is_promise())
|
|
46
|
+
{
|
|
47
|
+
auto p = value.as_promise();
|
|
48
|
+
if (p->state == state)
|
|
49
|
+
{
|
|
50
|
+
reject(AnyValue::make_string("TypeError: Chaining cycle detected for promise"));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
auto weak_state = std::weak_ptr<PromiseState>(state);
|
|
55
|
+
|
|
56
|
+
p->then(
|
|
57
|
+
[weak_state](AnyValue v)
|
|
58
|
+
{
|
|
59
|
+
if (auto s = weak_state.lock())
|
|
60
|
+
{
|
|
61
|
+
s->status = PromiseStatus::Fulfilled;
|
|
62
|
+
s->result = v;
|
|
63
|
+
auto callbacks = s->onFulfilled;
|
|
64
|
+
s->onFulfilled.clear();
|
|
65
|
+
s->onRejected.clear();
|
|
66
|
+
for (auto &cb : callbacks)
|
|
67
|
+
jspp::Scheduler::instance().enqueue([cb, v]()
|
|
68
|
+
{ cb(v); });
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
[weak_state](AnyValue r)
|
|
72
|
+
{
|
|
73
|
+
if (auto s = weak_state.lock())
|
|
74
|
+
{
|
|
75
|
+
s->status = PromiseStatus::Rejected;
|
|
76
|
+
s->result = r;
|
|
77
|
+
auto callbacks = s->onRejected;
|
|
78
|
+
s->onFulfilled.clear();
|
|
79
|
+
s->onRejected.clear();
|
|
80
|
+
for (auto &cb : callbacks)
|
|
81
|
+
jspp::Scheduler::instance().enqueue([cb, r]()
|
|
82
|
+
{ cb(r); });
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
state->status = PromiseStatus::Fulfilled;
|
|
89
|
+
state->result = value;
|
|
90
|
+
|
|
91
|
+
auto callbacks = state->onFulfilled;
|
|
92
|
+
state->onFulfilled.clear();
|
|
93
|
+
state->onRejected.clear();
|
|
94
|
+
|
|
95
|
+
for (auto &cb : callbacks)
|
|
96
|
+
{
|
|
97
|
+
jspp::Scheduler::instance().enqueue([cb, value]()
|
|
98
|
+
{ cb(value); });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
void JsPromise::reject(AnyValue reason)
|
|
103
|
+
{
|
|
104
|
+
if (state->status != PromiseStatus::Pending)
|
|
105
|
+
return;
|
|
106
|
+
state->status = PromiseStatus::Rejected;
|
|
107
|
+
state->result = reason;
|
|
108
|
+
|
|
109
|
+
auto callbacks = state->onRejected;
|
|
110
|
+
state->onFulfilled.clear();
|
|
111
|
+
state->onRejected.clear();
|
|
112
|
+
|
|
113
|
+
for (auto &cb : callbacks)
|
|
114
|
+
{
|
|
115
|
+
jspp::Scheduler::instance().enqueue([cb, reason]()
|
|
116
|
+
{ cb(reason); });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
void JsPromise::then(std::function<void(AnyValue)> onFulfilled, std::function<void(AnyValue)> onRejected)
|
|
121
|
+
{
|
|
122
|
+
state->handled = true;
|
|
123
|
+
if (state->status == PromiseStatus::Fulfilled)
|
|
124
|
+
{
|
|
125
|
+
if (onFulfilled)
|
|
126
|
+
{
|
|
127
|
+
AnyValue val = state->result;
|
|
128
|
+
jspp::Scheduler::instance().enqueue([onFulfilled, val]()
|
|
129
|
+
{ onFulfilled(val); });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else if (state->status == PromiseStatus::Rejected)
|
|
133
|
+
{
|
|
134
|
+
if (onRejected)
|
|
135
|
+
{
|
|
136
|
+
AnyValue val = state->result;
|
|
137
|
+
jspp::Scheduler::instance().enqueue([onRejected, val]()
|
|
138
|
+
{ onRejected(val); });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else
|
|
142
|
+
{
|
|
143
|
+
if (onFulfilled)
|
|
144
|
+
state->onFulfilled.push_back(onFulfilled);
|
|
145
|
+
if (onRejected)
|
|
146
|
+
state->onRejected.push_back(onRejected);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
std::string JsPromise::to_std_string() const
|
|
151
|
+
{
|
|
152
|
+
return "[object Promise]";
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
bool JsPromise::has_symbol_property(const AnyValue &key) const
|
|
156
|
+
{
|
|
157
|
+
if (symbol_props.count(key) > 0)
|
|
158
|
+
return true;
|
|
159
|
+
if (PromisePrototypes::get(key).has_value())
|
|
160
|
+
return true;
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
AnyValue JsPromise::get_property(const std::string &key, AnyValue thisVal)
|
|
165
|
+
{
|
|
166
|
+
auto proto_it = PromisePrototypes::get(key);
|
|
167
|
+
if (proto_it.has_value())
|
|
168
|
+
{
|
|
169
|
+
return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
auto it = props.find(key);
|
|
173
|
+
if (it != props.end())
|
|
174
|
+
{
|
|
175
|
+
return AnyValue::resolve_property_for_read(it->second, thisVal, key);
|
|
176
|
+
}
|
|
177
|
+
return Constants::UNDEFINED;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
AnyValue JsPromise::get_symbol_property(const AnyValue &key, AnyValue thisVal)
|
|
181
|
+
{
|
|
182
|
+
auto it = symbol_props.find(key);
|
|
183
|
+
if (it == symbol_props.end())
|
|
184
|
+
{
|
|
185
|
+
auto proto_it = PromisePrototypes::get(key);
|
|
186
|
+
if (proto_it.has_value())
|
|
187
|
+
{
|
|
188
|
+
return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key.to_std_string());
|
|
189
|
+
}
|
|
190
|
+
return Constants::UNDEFINED;
|
|
191
|
+
}
|
|
192
|
+
return AnyValue::resolve_property_for_read(it->second, thisVal, key.to_std_string());
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
AnyValue JsPromise::set_property(const std::string &key, AnyValue value, AnyValue thisVal)
|
|
196
|
+
{
|
|
197
|
+
auto it = props.find(key);
|
|
198
|
+
if (it != props.end())
|
|
199
|
+
{
|
|
200
|
+
return AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
|
|
201
|
+
}
|
|
202
|
+
else
|
|
203
|
+
{
|
|
204
|
+
props[key] = value;
|
|
205
|
+
return value;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
AnyValue JsPromise::set_symbol_property(const AnyValue &key, AnyValue value, AnyValue thisVal)
|
|
210
|
+
{
|
|
211
|
+
auto it = symbol_props.find(key);
|
|
212
|
+
if (it != symbol_props.end())
|
|
213
|
+
{
|
|
214
|
+
return AnyValue::resolve_property_for_write(it->second, thisVal, value, key.to_std_string());
|
|
215
|
+
}
|
|
216
|
+
else
|
|
217
|
+
{
|
|
218
|
+
symbol_props[key] = value;
|
|
219
|
+
return value;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// --- JsPromisePromiseType Implementation ---
|
|
224
|
+
|
|
225
|
+
void JsPromisePromiseType::return_value(AnyValue val)
|
|
226
|
+
{
|
|
227
|
+
promise.resolve(val);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
void JsPromisePromiseType::unhandled_exception()
|
|
231
|
+
{
|
|
232
|
+
try
|
|
233
|
+
{
|
|
234
|
+
throw;
|
|
235
|
+
}
|
|
236
|
+
catch (const Exception &e)
|
|
237
|
+
{
|
|
238
|
+
promise.reject(e.data);
|
|
239
|
+
}
|
|
240
|
+
catch (const std::exception &e)
|
|
241
|
+
{
|
|
242
|
+
promise.reject(AnyValue::make_string(e.what()));
|
|
243
|
+
}
|
|
244
|
+
catch (...)
|
|
245
|
+
{
|
|
246
|
+
promise.reject(AnyValue::make_string("Unknown exception"));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
AnyValueAwaiter JsPromisePromiseType::await_transform(AnyValue value)
|
|
251
|
+
{
|
|
252
|
+
return AnyValueAwaiter{value};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
AnyValueAwaiter JsPromisePromiseType::await_transform(const JsPromise &value)
|
|
256
|
+
{
|
|
257
|
+
return AnyValueAwaiter{AnyValue::make_promise(value)};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// --- AnyValueAwaiter Implementation ---
|
|
261
|
+
|
|
262
|
+
bool AnyValueAwaiter::await_ready()
|
|
263
|
+
{
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
void AnyValueAwaiter::await_suspend(std::coroutine_handle<> h)
|
|
268
|
+
{
|
|
269
|
+
if (!value.is_promise())
|
|
270
|
+
{
|
|
271
|
+
jspp::Scheduler::instance().enqueue([h]() mutable
|
|
272
|
+
{ h.resume(); });
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
auto p = value.as_promise();
|
|
276
|
+
|
|
277
|
+
p->then(
|
|
278
|
+
[h](AnyValue v) mutable
|
|
279
|
+
{ h.resume(); },
|
|
280
|
+
[h](AnyValue e) mutable
|
|
281
|
+
{ h.resume(); });
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
AnyValue AnyValueAwaiter::await_resume()
|
|
285
|
+
{
|
|
286
|
+
if (!value.is_promise())
|
|
287
|
+
return value;
|
|
288
|
+
auto p = value.as_promise();
|
|
289
|
+
if (p->state->status == PromiseStatus::Fulfilled)
|
|
290
|
+
{
|
|
291
|
+
return p->state->result;
|
|
292
|
+
}
|
|
293
|
+
else
|
|
294
|
+
{
|
|
295
|
+
throw Exception(p->state->result);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// --- PromisePrototypes Implementation ---
|
|
300
|
+
|
|
301
|
+
namespace PromisePrototypes {
|
|
302
|
+
|
|
303
|
+
AnyValue &get_then_fn()
|
|
304
|
+
{
|
|
305
|
+
static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
|
|
306
|
+
{
|
|
307
|
+
auto self = thisVal.as_promise();
|
|
308
|
+
AnyValue onFulfilled = (args.size() > 0 && args[0].is_function()) ? args[0] : Constants::UNDEFINED;
|
|
309
|
+
AnyValue onRejected = (args.size() > 1 && args[1].is_function()) ? args[1] : Constants::UNDEFINED;
|
|
310
|
+
|
|
311
|
+
JsPromise newPromise;
|
|
312
|
+
AnyValue newPromiseVal = AnyValue::make_promise(newPromise);
|
|
313
|
+
|
|
314
|
+
auto newPromiseState = newPromise.state;
|
|
315
|
+
auto resolveNew = [newPromiseState](const AnyValue &v)
|
|
316
|
+
{
|
|
317
|
+
if (newPromiseState->status != PromiseStatus::Pending)
|
|
318
|
+
return;
|
|
319
|
+
newPromiseState->status = PromiseStatus::Fulfilled;
|
|
320
|
+
newPromiseState->result = v;
|
|
321
|
+
auto callbacks = newPromiseState->onFulfilled;
|
|
322
|
+
newPromiseState->onFulfilled.clear();
|
|
323
|
+
newPromiseState->onRejected.clear();
|
|
324
|
+
for (auto &cb : callbacks)
|
|
325
|
+
jspp::Scheduler::instance().enqueue([cb, v]()
|
|
326
|
+
{ cb(v); });
|
|
327
|
+
};
|
|
328
|
+
auto rejectNew = [newPromiseState](const AnyValue &r)
|
|
329
|
+
{
|
|
330
|
+
if (newPromiseState->status != PromiseStatus::Pending)
|
|
331
|
+
return;
|
|
332
|
+
newPromiseState->status = PromiseStatus::Rejected;
|
|
333
|
+
newPromiseState->result = r;
|
|
334
|
+
auto callbacks = newPromiseState->onRejected;
|
|
335
|
+
newPromiseState->onFulfilled.clear();
|
|
336
|
+
newPromiseState->onRejected.clear();
|
|
337
|
+
for (auto &cb : callbacks)
|
|
338
|
+
jspp::Scheduler::instance().enqueue([cb, r]()
|
|
339
|
+
{ cb(r); });
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
auto resolveHandler = [resolveNew, rejectNew, onFulfilled](const AnyValue &val) mutable
|
|
343
|
+
{
|
|
344
|
+
if (onFulfilled.is_function())
|
|
345
|
+
{
|
|
346
|
+
try
|
|
347
|
+
{
|
|
348
|
+
const AnyValue cbArgs[] = {val};
|
|
349
|
+
auto res = onFulfilled.call(Constants::UNDEFINED, cbArgs, "onFulfilled");
|
|
350
|
+
if (res.is_promise())
|
|
351
|
+
{
|
|
352
|
+
auto chained = res.as_promise();
|
|
353
|
+
chained->then(
|
|
354
|
+
[resolveNew](const AnyValue &v)
|
|
355
|
+
{ resolveNew(v); },
|
|
356
|
+
[rejectNew](const AnyValue &e)
|
|
357
|
+
{ rejectNew(e); });
|
|
358
|
+
}
|
|
359
|
+
else
|
|
360
|
+
{
|
|
361
|
+
resolveNew(res);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
catch (const Exception &e)
|
|
365
|
+
{
|
|
366
|
+
rejectNew(e.data);
|
|
367
|
+
}
|
|
368
|
+
catch (...)
|
|
369
|
+
{
|
|
370
|
+
rejectNew(AnyValue::make_string("Unknown error"));
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
else
|
|
374
|
+
{
|
|
375
|
+
resolveNew(val);
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
auto rejectHandler = [resolveNew, rejectNew, onRejected](const AnyValue &reason) mutable
|
|
380
|
+
{
|
|
381
|
+
if (onRejected.is_function())
|
|
382
|
+
{
|
|
383
|
+
try
|
|
384
|
+
{
|
|
385
|
+
const AnyValue cbArgs[] = {reason};
|
|
386
|
+
auto res = onRejected.call(Constants::UNDEFINED, cbArgs, "onRejected");
|
|
387
|
+
if (res.is_promise())
|
|
388
|
+
{
|
|
389
|
+
auto chained = res.as_promise();
|
|
390
|
+
chained->then(
|
|
391
|
+
[resolveNew](const AnyValue &v)
|
|
392
|
+
{ resolveNew(v); },
|
|
393
|
+
[rejectNew](const AnyValue &e)
|
|
394
|
+
{ rejectNew(e); });
|
|
395
|
+
}
|
|
396
|
+
else
|
|
397
|
+
{
|
|
398
|
+
resolveNew(res);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
catch (const Exception &e)
|
|
402
|
+
{
|
|
403
|
+
rejectNew(e.data);
|
|
404
|
+
}
|
|
405
|
+
catch (...)
|
|
406
|
+
{
|
|
407
|
+
rejectNew(AnyValue::make_string("Unknown error"));
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
else
|
|
411
|
+
{
|
|
412
|
+
rejectNew(reason);
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
self->then(resolveHandler, rejectHandler);
|
|
417
|
+
return newPromiseVal; },
|
|
418
|
+
"then");
|
|
419
|
+
return fn;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
AnyValue &get_catch_fn()
|
|
423
|
+
{
|
|
424
|
+
static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
|
|
425
|
+
{
|
|
426
|
+
AnyValue onRejected = (args.size() > 0 && args[0].is_function()) ? args[0] : Constants::UNDEFINED;
|
|
427
|
+
const AnyValue thenArgs[] = {Constants::UNDEFINED, onRejected};
|
|
428
|
+
return thisVal.get_own_property("then").call(thisVal, thenArgs, "then"); },
|
|
429
|
+
"catch");
|
|
430
|
+
return fn;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
AnyValue &get_finally_fn()
|
|
434
|
+
{
|
|
435
|
+
static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
|
|
436
|
+
{
|
|
437
|
+
AnyValue onFinally = (args.size() > 0 && args[0].is_function()) ? args[0] : Constants::UNDEFINED;
|
|
438
|
+
|
|
439
|
+
const AnyValue thenArgs[] = {
|
|
440
|
+
AnyValue::make_function([onFinally](const AnyValue &, std::span<const AnyValue> args) -> AnyValue
|
|
441
|
+
{
|
|
442
|
+
AnyValue val = args.empty() ? Constants::UNDEFINED : args[0];
|
|
443
|
+
if (onFinally.is_function())
|
|
444
|
+
{
|
|
445
|
+
onFinally.call(Constants::UNDEFINED, {}, "onFinally");
|
|
446
|
+
}
|
|
447
|
+
return val; },
|
|
448
|
+
""),
|
|
449
|
+
AnyValue::make_function([onFinally](const AnyValue &, std::span<const AnyValue> args) -> AnyValue
|
|
450
|
+
{
|
|
451
|
+
AnyValue reason = args.empty() ? Constants::UNDEFINED : args[0];
|
|
452
|
+
if (onFinally.is_function())
|
|
453
|
+
{
|
|
454
|
+
onFinally.call(Constants::UNDEFINED, {}, "onFinally");
|
|
455
|
+
}
|
|
456
|
+
throw Exception(reason); },
|
|
457
|
+
"")};
|
|
458
|
+
return thisVal.get_own_property("then").call(thisVal, thenArgs, "then"); },
|
|
459
|
+
"finally");
|
|
460
|
+
return fn;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
std::optional<AnyValue> get(const std::string &key)
|
|
464
|
+
{
|
|
465
|
+
if (key == "then") return get_then_fn();
|
|
466
|
+
if (key == "catch") return get_catch_fn();
|
|
467
|
+
if (key == "finally") return get_finally_fn();
|
|
468
|
+
return std::nullopt;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
std::optional<AnyValue> get(const AnyValue &key)
|
|
472
|
+
{
|
|
473
|
+
// Well-known symbols could be added here if needed
|
|
474
|
+
return std::nullopt;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
} // namespace PromisePrototypes
|
|
478
|
+
|
|
479
|
+
} // namespace jspp
|
|
@@ -24,7 +24,10 @@ namespace jspp
|
|
|
24
24
|
std::vector<std::function<void(const AnyValue&)>> onFulfilled;
|
|
25
25
|
std::vector<std::function<void(const AnyValue&)>> onRejected;
|
|
26
26
|
|
|
27
|
+
bool handled = false;
|
|
28
|
+
|
|
27
29
|
PromiseState(); // Defined in helpers
|
|
30
|
+
~PromiseState(); // Defined in helpers
|
|
28
31
|
};
|
|
29
32
|
|
|
30
33
|
struct JsPromisePromiseType; // Forward declaration
|
|
@@ -35,6 +38,7 @@ namespace jspp
|
|
|
35
38
|
|
|
36
39
|
std::shared_ptr<PromiseState> state;
|
|
37
40
|
std::unordered_map<std::string, AnyValue> props;
|
|
41
|
+
std::map<AnyValue, AnyValue> symbol_props;
|
|
38
42
|
|
|
39
43
|
JsPromise();
|
|
40
44
|
|
|
@@ -47,8 +51,11 @@ namespace jspp
|
|
|
47
51
|
|
|
48
52
|
// --- Methods ---
|
|
49
53
|
std::string to_std_string() const;
|
|
54
|
+
bool has_symbol_property(const AnyValue& key) const;
|
|
50
55
|
AnyValue get_property(const std::string& key, AnyValue thisVal);
|
|
56
|
+
AnyValue get_symbol_property(const AnyValue& key, AnyValue thisVal);
|
|
51
57
|
AnyValue set_property(const std::string& key, AnyValue value, AnyValue thisVal);
|
|
58
|
+
AnyValue set_symbol_property(const AnyValue& key, AnyValue value, AnyValue thisVal);
|
|
52
59
|
|
|
53
60
|
auto operator co_await() const;
|
|
54
61
|
};
|
|
@@ -65,8 +72,8 @@ namespace jspp
|
|
|
65
72
|
void unhandled_exception();
|
|
66
73
|
|
|
67
74
|
// await_transform for AnyValue
|
|
68
|
-
|
|
75
|
+
AnyValueAwaiter await_transform(AnyValue value);
|
|
69
76
|
// await_transform for JsPromise
|
|
70
|
-
|
|
77
|
+
AnyValueAwaiter await_transform(const JsPromise& value);
|
|
71
78
|
};
|
|
72
79
|
}
|