@ugo-studio/jspp 0.2.8 → 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.
Files changed (46) hide show
  1. package/dist/analysis/typeAnalyzer.js +42 -27
  2. package/dist/core/codegen/class-handlers.js +6 -6
  3. package/dist/core/codegen/control-flow-handlers.js +4 -4
  4. package/dist/core/codegen/declaration-handlers.js +21 -3
  5. package/dist/core/codegen/destructuring-handlers.js +187 -0
  6. package/dist/core/codegen/expression-handlers.js +7 -0
  7. package/dist/core/codegen/function-handlers.js +58 -36
  8. package/dist/core/codegen/helpers.js +288 -52
  9. package/dist/core/codegen/index.js +7 -4
  10. package/dist/core/codegen/statement-handlers.js +43 -23
  11. package/package.json +1 -1
  12. package/scripts/precompile-headers.ts +13 -5
  13. package/src/prelude/any_value.hpp +362 -361
  14. package/src/prelude/any_value_access.hpp +170 -170
  15. package/src/prelude/any_value_defines.hpp +189 -189
  16. package/src/prelude/any_value_helpers.hpp +374 -365
  17. package/src/prelude/library/array.hpp +185 -185
  18. package/src/prelude/library/console.hpp +111 -111
  19. package/src/prelude/library/error.hpp +112 -112
  20. package/src/prelude/library/function.hpp +10 -10
  21. package/src/prelude/library/math.hpp +307 -307
  22. package/src/prelude/library/object.hpp +275 -275
  23. package/src/prelude/library/performance.hpp +1 -1
  24. package/src/prelude/library/process.hpp +39 -39
  25. package/src/prelude/library/promise.hpp +123 -123
  26. package/src/prelude/library/symbol.hpp +52 -52
  27. package/src/prelude/library/timer.hpp +91 -91
  28. package/src/prelude/types.hpp +178 -178
  29. package/src/prelude/utils/access.hpp +411 -393
  30. package/src/prelude/utils/operators.hpp +336 -329
  31. package/src/prelude/values/array.hpp +0 -1
  32. package/src/prelude/values/async_iterator.hpp +83 -81
  33. package/src/prelude/values/function.hpp +82 -82
  34. package/src/prelude/values/helpers/array.hpp +198 -208
  35. package/src/prelude/values/helpers/async_iterator.hpp +275 -271
  36. package/src/prelude/values/helpers/function.hpp +108 -108
  37. package/src/prelude/values/helpers/iterator.hpp +144 -107
  38. package/src/prelude/values/helpers/promise.hpp +253 -253
  39. package/src/prelude/values/helpers/string.hpp +37 -47
  40. package/src/prelude/values/iterator.hpp +32 -5
  41. package/src/prelude/values/promise.hpp +72 -72
  42. package/src/prelude/values/prototypes/array.hpp +54 -42
  43. package/src/prelude/values/prototypes/iterator.hpp +201 -74
  44. package/src/prelude/values/prototypes/promise.hpp +196 -196
  45. package/src/prelude/values/prototypes/string.hpp +564 -542
  46. package/src/prelude/values/string.hpp +25 -26
@@ -1,365 +1,374 @@
1
- #pragma once
2
-
3
- #include "types.hpp"
4
- #include "any_value.hpp"
5
- #include "values/string.hpp"
6
- #include "values/object.hpp"
7
- #include "values/array.hpp"
8
- #include "values/function.hpp"
9
- #include "values/iterator.hpp"
10
- #include "values/async_iterator.hpp"
11
- #include "values/promise.hpp"
12
- #include "values/symbol.hpp"
13
- #include "values/descriptors.hpp"
14
- #include "exception.hpp"
15
-
16
- namespace jspp
17
- {
18
- // --- AnyValue GETTERS ---
19
- inline JsString *AnyValue::as_string() const noexcept { return static_cast<JsString *>(get_ptr()); }
20
- inline JsObject *AnyValue::as_object() const noexcept { return static_cast<JsObject *>(get_ptr()); }
21
- inline JsArray *AnyValue::as_array() const noexcept { return static_cast<JsArray *>(get_ptr()); }
22
- inline JsFunction *AnyValue::as_function() const noexcept { return static_cast<JsFunction *>(get_ptr()); }
23
- inline JsSymbol *AnyValue::as_symbol() const noexcept { return static_cast<JsSymbol *>(get_ptr()); }
24
- inline JsPromise *AnyValue::as_promise() const noexcept { return static_cast<JsPromise *>(get_ptr()); }
25
- inline JsIterator<AnyValue> *AnyValue::as_iterator() const noexcept { return static_cast<JsIterator<AnyValue> *>(get_ptr()); }
26
- inline JsAsyncIterator<AnyValue> *AnyValue::as_async_iterator() const noexcept { return static_cast<JsAsyncIterator<AnyValue> *>(get_ptr()); }
27
- inline DataDescriptor *AnyValue::as_data_descriptor() const noexcept { return static_cast<DataDescriptor *>(get_ptr()); }
28
- inline AccessorDescriptor *AnyValue::as_accessor_descriptor() const noexcept { return static_cast<AccessorDescriptor *>(get_ptr()); }
29
-
30
- inline bool AnyValue::is_generator() const noexcept { return is_function() && as_function()->is_generator; }
31
-
32
- // --- AnyValue FACTORIES ---
33
- inline AnyValue AnyValue::make_string(const std::string &raw_s) noexcept
34
- {
35
- return from_ptr(new JsString(raw_s));
36
- }
37
- inline AnyValue AnyValue::make_object(std::initializer_list<std::pair<std::string, AnyValue>> props) noexcept
38
- {
39
- return from_ptr(new JsObject(props, make_null()));
40
- }
41
- inline AnyValue AnyValue::make_object(const std::map<std::string, AnyValue> &props) noexcept
42
- {
43
- return from_ptr(new JsObject(props, make_null()));
44
- }
45
- inline AnyValue AnyValue::make_object_with_proto(std::initializer_list<std::pair<std::string, AnyValue>> props, AnyValue proto) noexcept
46
- {
47
- return from_ptr(new JsObject(props, proto));
48
- }
49
- inline AnyValue AnyValue::make_object_with_proto(const std::map<std::string, AnyValue> &props, AnyValue proto) noexcept
50
- {
51
- return from_ptr(new JsObject(props, proto));
52
- }
53
- inline AnyValue AnyValue::make_array(std::span<const AnyValue> dense) noexcept
54
- {
55
- std::vector<AnyValue> vec;
56
- vec.reserve(dense.size());
57
- for (const auto &item : dense)
58
- vec.push_back(item);
59
- return from_ptr(new JsArray(std::move(vec)));
60
- }
61
- inline AnyValue AnyValue::make_array(const std::vector<AnyValue> &dense) noexcept
62
- {
63
- return from_ptr(new JsArray(dense));
64
- }
65
- inline AnyValue AnyValue::make_array(std::vector<AnyValue> &&dense) noexcept
66
- {
67
- return from_ptr(new JsArray(std::move(dense)));
68
- }
69
- inline AnyValue AnyValue::make_array_with_proto(std::span<const AnyValue> dense, AnyValue proto) noexcept
70
- {
71
- auto arr = new JsArray();
72
- arr->dense.reserve(dense.size());
73
- for (const auto &item : dense)
74
- arr->dense.push_back(item);
75
- arr->length = dense.size();
76
- arr->proto = proto;
77
- return from_ptr(arr);
78
- }
79
- inline AnyValue AnyValue::make_array_with_proto(const std::vector<AnyValue> &dense, AnyValue proto) noexcept
80
- {
81
- auto arr = new JsArray(dense);
82
- arr->proto = proto;
83
- return from_ptr(arr);
84
- }
85
- inline AnyValue AnyValue::make_array_with_proto(std::vector<AnyValue> &&dense, AnyValue proto) noexcept
86
- {
87
- auto arr = new JsArray(std::move(dense));
88
- arr->proto = proto;
89
- return from_ptr(arr);
90
- }
91
- inline AnyValue AnyValue::make_function(const JsFunctionCallable &call, const std::optional<std::string> &name, bool is_constructor) noexcept
92
- {
93
- auto v = from_ptr(new JsFunction(call, name, {}, false, is_constructor));
94
- auto proto = make_object({});
95
- proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
96
- v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
97
- return v;
98
- }
99
- inline AnyValue AnyValue::make_class(const JsFunctionCallable &call, const std::optional<std::string> &name) noexcept
100
- {
101
- auto v = from_ptr(new JsFunction(call, name, {}, true));
102
- auto proto = make_object({});
103
- proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
104
- v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
105
- return v;
106
- }
107
- inline AnyValue AnyValue::make_generator(const JsFunctionCallable &call, const std::optional<std::string> &name) noexcept
108
- {
109
- auto v = from_ptr(new JsFunction(call, true, name));
110
- auto proto = make_object({});
111
- proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
112
- v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
113
- return v;
114
- }
115
- inline AnyValue AnyValue::make_async_function(const JsFunctionCallable &call, const std::optional<std::string> &name) noexcept
116
- {
117
- auto v = from_ptr(new JsFunction(call, false, true, name));
118
- auto proto = make_object({});
119
- proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
120
- v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
121
- return v;
122
- }
123
- inline AnyValue AnyValue::make_async_generator(const JsFunctionCallable &call, const std::optional<std::string> &name) noexcept
124
- {
125
- auto v = from_ptr(new JsFunction(call, true, true, name));
126
- auto proto = make_object({});
127
- proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
128
- v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
129
- return v;
130
- }
131
- inline AnyValue AnyValue::make_symbol(const std::string &description) noexcept
132
- {
133
- return from_ptr(new JsSymbol(description));
134
- }
135
- inline AnyValue AnyValue::make_promise(const JsPromise &promise) noexcept
136
- {
137
- auto p = new JsPromise();
138
- *p = promise;
139
- return from_ptr(p);
140
- }
141
- inline AnyValue AnyValue::make_data_descriptor(AnyValue value, bool writable, bool enumerable, bool configurable) noexcept
142
- {
143
- return from_ptr(new DataDescriptor(value, writable, enumerable, configurable));
144
- }
145
- inline AnyValue AnyValue::make_accessor_descriptor(const std::optional<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>> &get,
146
- const std::optional<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>> &set,
147
- bool enumerable,
148
- bool configurable) noexcept
149
- {
150
- return from_ptr(new AccessorDescriptor(get, set, enumerable, configurable));
151
- }
152
-
153
- inline AnyValue AnyValue::from_symbol(JsSymbol *sym) noexcept
154
- {
155
- return from_ptr(sym);
156
- }
157
- inline AnyValue AnyValue::from_string(JsString *str) noexcept
158
- {
159
- return from_ptr(str);
160
- }
161
-
162
- inline AnyValue AnyValue::from_promise(JsPromise &&promise) noexcept
163
- {
164
- auto it = new JsPromise(std::move(promise));
165
- return from_ptr(it);
166
- }
167
-
168
- inline AnyValue AnyValue::from_iterator(JsIterator<AnyValue> &&iterator) noexcept
169
- {
170
- auto it = new JsIterator<AnyValue>(std::move(iterator));
171
- return from_ptr(it);
172
- }
173
- inline AnyValue AnyValue::from_iterator_ref(JsIterator<AnyValue> *iterator) noexcept
174
- {
175
- return from_ptr(iterator);
176
- }
177
- inline AnyValue AnyValue::from_async_iterator(JsAsyncIterator<AnyValue> &&iterator) noexcept
178
- {
179
- auto it = new JsAsyncIterator<AnyValue>(std::move(iterator));
180
- return from_ptr(it);
181
- }
182
-
183
- inline AnyValue AnyValue::resolve_property_for_read(const AnyValue &val, const AnyValue &thisVal, const std::string &propName) noexcept
184
- {
185
- if (val.is_data_descriptor())
186
- {
187
- return val.as_data_descriptor()->value;
188
- }
189
- if (val.is_accessor_descriptor())
190
- {
191
- auto accessor = val.as_accessor_descriptor();
192
- if (accessor->get.has_value())
193
- return accessor->get.value()(thisVal, std::span<const AnyValue>{});
194
- else
195
- {
196
- return Constants::UNDEFINED;
197
- }
198
- }
199
- return val;
200
- }
201
- inline AnyValue AnyValue::resolve_property_for_write(AnyValue &val, const AnyValue &thisVal, const AnyValue &new_val, const std::string &propName)
202
- {
203
- if (val.is_data_descriptor())
204
- {
205
- auto data = val.as_data_descriptor();
206
- if (data->writable)
207
- {
208
- data->value = new_val;
209
- return new_val;
210
- }
211
- else
212
- {
213
- throw Exception::make_exception("Cannot assign to read only property '" + propName + "' of object '#<Object>'", "TypeError");
214
- }
215
- }
216
- if (val.is_accessor_descriptor())
217
- {
218
- auto accessor = val.as_accessor_descriptor();
219
- if (accessor->set.has_value())
220
- {
221
- const AnyValue args[] = {new_val};
222
- accessor->set.value()(thisVal, std::span<const AnyValue>(args, 1));
223
- return new_val;
224
- }
225
- else
226
- {
227
- throw Exception::make_exception("Cannot set property of #<Object> which has only a getter", "TypeError");
228
- }
229
- }
230
- val = new_val;
231
- return new_val;
232
- }
233
-
234
- inline std::string AnyValue::to_std_string() const
235
- {
236
- switch (get_type())
237
- {
238
- case JsType::Undefined:
239
- return "undefined";
240
- case JsType::Null:
241
- return "null";
242
- case JsType::Boolean:
243
- return as_boolean() ? "true" : "false";
244
- case JsType::String:
245
- return as_string()->to_std_string();
246
- case JsType::Object:
247
- return as_object()->to_std_string();
248
- case JsType::Array:
249
- return as_array()->to_std_string();
250
- case JsType::Function:
251
- return as_function()->to_std_string();
252
- case JsType::Iterator:
253
- return as_iterator()->to_std_string();
254
- case JsType::AsyncIterator:
255
- return as_async_iterator()->to_std_string();
256
- case JsType::Promise:
257
- return as_promise()->to_std_string();
258
- case JsType::Symbol:
259
- return as_symbol()->to_std_string();
260
- case JsType::DataDescriptor:
261
- return as_data_descriptor()->value.to_std_string();
262
- case JsType::AccessorDescriptor:
263
- {
264
- if (as_accessor_descriptor()->get.has_value())
265
- return as_accessor_descriptor()->get.value()(*this, {}).to_std_string();
266
- else
267
- return "undefined";
268
- }
269
- case JsType::Number:
270
- {
271
- double num = as_double();
272
- if (std::isnan(num))
273
- {
274
- return "NaN";
275
- }
276
- if (std::abs(num) >= 1e21 || (std::abs(num) > 0 && std::abs(num) < 1e-6))
277
- {
278
- std::ostringstream oss;
279
- oss << std::scientific << std::setprecision(4) << num;
280
- return oss.str();
281
- }
282
- else
283
- {
284
- std::ostringstream oss;
285
- oss << std::setprecision(6) << std::fixed << num;
286
- std::string s = oss.str();
287
- s.erase(s.find_last_not_of('0') + 1, std::string::npos);
288
- if (!s.empty() && s.back() == '.')
289
- {
290
- s.pop_back();
291
- }
292
- return s;
293
- }
294
- }
295
- case JsType::Uninitialized:
296
- Exception::throw_uninitialized_reference("#<Object>");
297
- default:
298
- return "";
299
- }
300
- }
301
-
302
- inline void AnyValue::set_prototype(const AnyValue &proto)
303
- {
304
- if (is_object())
305
- {
306
- as_object()->proto = proto;
307
- }
308
- else if (is_array())
309
- {
310
- as_array()->proto = proto;
311
- }
312
- else if (is_function())
313
- {
314
- as_function()->proto = proto;
315
- }
316
- else if (is_uninitialized())
317
- {
318
- Exception::throw_uninitialized_reference("#<Object>");
319
- }
320
- }
321
-
322
- // AnyValue::call implementation
323
- inline AnyValue AnyValue::call(const AnyValue &thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr) const
324
- {
325
- if (!is_function())
326
- throw Exception::make_exception(expr.value_or(to_std_string()) + " is not a function", "TypeError");
327
- return as_function()->call(thisVal, args);
328
- }
329
- inline AnyValue AnyValue::optional_call(const AnyValue &thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr) const
330
- {
331
- if (is_null() || is_undefined())
332
- return Constants::UNDEFINED;
333
- return as_function()->call(thisVal, args);
334
- }
335
-
336
- // AnyValue::construct implementation
337
- inline AnyValue AnyValue::construct(std::span<const AnyValue> args, const std::optional<std::string> &name) const
338
- {
339
- if (!is_function() || !as_function()->is_constructor)
340
- {
341
- throw Exception::make_exception(name.value_or(to_std_string()) + " is not a constructor", "TypeError");
342
- }
343
-
344
- // 1. Get prototype
345
- AnyValue proto = get_own_property("prototype");
346
- if (!proto.is_object())
347
- {
348
- proto = AnyValue::make_object({});
349
- }
350
-
351
- // 2. Create instance
352
- AnyValue instance = AnyValue::make_object_with_proto({}, proto);
353
-
354
- // 3. Call function
355
- AnyValue result = call(instance, args);
356
-
357
- // 4. Return result if object, else instance
358
- if (result.is_object() || result.is_function() || result.is_array() || result.is_promise())
359
- {
360
- return result;
361
- }
362
- return instance;
363
- }
364
-
365
- }
1
+ #pragma once
2
+
3
+ #include "types.hpp"
4
+ #include "any_value.hpp"
5
+ #include "values/string.hpp"
6
+ #include "values/object.hpp"
7
+ #include "values/array.hpp"
8
+ #include "values/function.hpp"
9
+ #include "values/iterator.hpp"
10
+ #include "values/async_iterator.hpp"
11
+ #include "values/promise.hpp"
12
+ #include "values/symbol.hpp"
13
+ #include "values/descriptors.hpp"
14
+ #include "exception.hpp"
15
+
16
+ namespace jspp
17
+ {
18
+ // --- AnyValue GETTERS ---
19
+ inline JsString *AnyValue::as_string() const noexcept { return static_cast<JsString *>(get_ptr()); }
20
+ inline JsObject *AnyValue::as_object() const noexcept { return static_cast<JsObject *>(get_ptr()); }
21
+ inline JsArray *AnyValue::as_array() const noexcept { return static_cast<JsArray *>(get_ptr()); }
22
+ inline JsFunction *AnyValue::as_function() const noexcept { return static_cast<JsFunction *>(get_ptr()); }
23
+ inline JsSymbol *AnyValue::as_symbol() const noexcept { return static_cast<JsSymbol *>(get_ptr()); }
24
+ inline JsPromise *AnyValue::as_promise() const noexcept { return static_cast<JsPromise *>(get_ptr()); }
25
+ inline JsIterator<AnyValue> *AnyValue::as_iterator() const noexcept { return static_cast<JsIterator<AnyValue> *>(get_ptr()); }
26
+ inline JsAsyncIterator<AnyValue> *AnyValue::as_async_iterator() const noexcept { return static_cast<JsAsyncIterator<AnyValue> *>(get_ptr()); }
27
+ inline DataDescriptor *AnyValue::as_data_descriptor() const noexcept { return static_cast<DataDescriptor *>(get_ptr()); }
28
+ inline AccessorDescriptor *AnyValue::as_accessor_descriptor() const noexcept { return static_cast<AccessorDescriptor *>(get_ptr()); }
29
+
30
+ inline bool AnyValue::is_generator() const noexcept { return is_function() && as_function()->is_generator; }
31
+
32
+ // --- AnyValue FACTORIES ---
33
+ inline AnyValue AnyValue::make_string(const std::string &raw_s) noexcept
34
+ {
35
+ return from_ptr(new JsString(raw_s));
36
+ }
37
+ inline AnyValue AnyValue::make_object(std::initializer_list<std::pair<std::string, AnyValue>> props) noexcept
38
+ {
39
+ return from_ptr(new JsObject(props, make_null()));
40
+ }
41
+ inline AnyValue AnyValue::make_object(const std::map<std::string, AnyValue> &props) noexcept
42
+ {
43
+ return from_ptr(new JsObject(props, make_null()));
44
+ }
45
+ inline AnyValue AnyValue::make_object_with_proto(std::initializer_list<std::pair<std::string, AnyValue>> props, AnyValue proto) noexcept
46
+ {
47
+ return from_ptr(new JsObject(props, proto));
48
+ }
49
+ inline AnyValue AnyValue::make_object_with_proto(const std::map<std::string, AnyValue> &props, AnyValue proto) noexcept
50
+ {
51
+ return from_ptr(new JsObject(props, proto));
52
+ }
53
+ inline AnyValue AnyValue::make_array(std::span<const AnyValue> dense) noexcept
54
+ {
55
+ std::vector<AnyValue> vec;
56
+ vec.reserve(dense.size());
57
+ for (const auto &item : dense)
58
+ vec.push_back(item);
59
+ return from_ptr(new JsArray(std::move(vec)));
60
+ }
61
+ inline AnyValue AnyValue::make_array(const std::vector<AnyValue> &dense) noexcept
62
+ {
63
+ return from_ptr(new JsArray(dense));
64
+ }
65
+ inline AnyValue AnyValue::make_array(std::vector<AnyValue> &&dense) noexcept
66
+ {
67
+ return from_ptr(new JsArray(std::move(dense)));
68
+ }
69
+ inline AnyValue AnyValue::make_array_with_proto(std::span<const AnyValue> dense, AnyValue proto) noexcept
70
+ {
71
+ auto arr = new JsArray();
72
+ arr->dense.reserve(dense.size());
73
+ for (const auto &item : dense)
74
+ arr->dense.push_back(item);
75
+ arr->length = dense.size();
76
+ arr->proto = proto;
77
+ return from_ptr(arr);
78
+ }
79
+ inline AnyValue AnyValue::make_array_with_proto(const std::vector<AnyValue> &dense, AnyValue proto) noexcept
80
+ {
81
+ auto arr = new JsArray(dense);
82
+ arr->proto = proto;
83
+ return from_ptr(arr);
84
+ }
85
+ inline AnyValue AnyValue::make_array_with_proto(std::vector<AnyValue> &&dense, AnyValue proto) noexcept
86
+ {
87
+ auto arr = new JsArray(std::move(dense));
88
+ arr->proto = proto;
89
+ return from_ptr(arr);
90
+ }
91
+ inline AnyValue AnyValue::make_function(const JsFunctionCallable &call, const std::optional<std::string> &name, bool is_constructor) noexcept
92
+ {
93
+ auto v = from_ptr(new JsFunction(call, name, {}, false, is_constructor));
94
+ auto proto = make_object({});
95
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
96
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
97
+ return v;
98
+ }
99
+ inline AnyValue AnyValue::make_class(const JsFunctionCallable &call, const std::optional<std::string> &name) noexcept
100
+ {
101
+ auto v = from_ptr(new JsFunction(call, name, {}, true));
102
+ auto proto = make_object({});
103
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
104
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
105
+ return v;
106
+ }
107
+ inline AnyValue AnyValue::make_generator(const JsFunctionCallable &call, const std::optional<std::string> &name) noexcept
108
+ {
109
+ auto v = from_ptr(new JsFunction(call, true, name));
110
+ auto proto = make_object({});
111
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
112
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
113
+ return v;
114
+ }
115
+ inline AnyValue AnyValue::make_async_function(const JsFunctionCallable &call, const std::optional<std::string> &name) noexcept
116
+ {
117
+ auto v = from_ptr(new JsFunction(call, false, true, name));
118
+ auto proto = make_object({});
119
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
120
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
121
+ return v;
122
+ }
123
+ inline AnyValue AnyValue::make_async_generator(const JsFunctionCallable &call, const std::optional<std::string> &name) noexcept
124
+ {
125
+ auto v = from_ptr(new JsFunction(call, true, true, name));
126
+ auto proto = make_object({});
127
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
128
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
129
+ return v;
130
+ }
131
+ inline AnyValue AnyValue::make_symbol(const std::string &description) noexcept
132
+ {
133
+ return from_ptr(new JsSymbol(description));
134
+ }
135
+ inline AnyValue AnyValue::make_promise(const JsPromise &promise) noexcept
136
+ {
137
+ auto p = new JsPromise();
138
+ *p = promise;
139
+ return from_ptr(p);
140
+ }
141
+ inline AnyValue AnyValue::make_data_descriptor(AnyValue value, bool writable, bool enumerable, bool configurable) noexcept
142
+ {
143
+ return from_ptr(new DataDescriptor(value, writable, enumerable, configurable));
144
+ }
145
+ inline AnyValue AnyValue::make_accessor_descriptor(const std::optional<std::function<AnyValue(AnyValue, std::span<const AnyValue>)>> &get,
146
+ const std::optional<std::function<AnyValue(AnyValue, std::span<const AnyValue>)>> &set,
147
+ bool enumerable,
148
+ bool configurable) noexcept
149
+ {
150
+ return from_ptr(new AccessorDescriptor(get, set, enumerable, configurable));
151
+ }
152
+
153
+ inline AnyValue AnyValue::from_symbol(JsSymbol *sym) noexcept
154
+ {
155
+ return from_ptr(sym);
156
+ }
157
+ inline AnyValue AnyValue::from_string(JsString *str) noexcept
158
+ {
159
+ return from_ptr(str);
160
+ }
161
+
162
+ inline AnyValue AnyValue::from_promise(JsPromise &&promise) noexcept
163
+ {
164
+ auto it = new JsPromise(std::move(promise));
165
+ return from_ptr(it);
166
+ }
167
+
168
+ inline AnyValue AnyValue::from_iterator(JsIterator<AnyValue> &&iterator) noexcept
169
+ {
170
+ auto it = new JsIterator<AnyValue>(std::move(iterator));
171
+ return from_ptr(it);
172
+ }
173
+ inline AnyValue AnyValue::from_iterator_ref(JsIterator<AnyValue> *iterator) noexcept
174
+ {
175
+ return from_ptr(iterator);
176
+ }
177
+ inline AnyValue AnyValue::from_async_iterator(JsAsyncIterator<AnyValue> &&iterator) noexcept
178
+ {
179
+ auto it = new JsAsyncIterator<AnyValue>(std::move(iterator));
180
+ return from_ptr(it);
181
+ }
182
+
183
+ inline AnyValue AnyValue::resolve_property_for_read(const AnyValue &val, AnyValue thisVal, const std::string &propName) noexcept
184
+ {
185
+ if (val.is_data_descriptor())
186
+ {
187
+ return val.as_data_descriptor()->value;
188
+ }
189
+ if (val.is_accessor_descriptor())
190
+ {
191
+ auto accessor = val.as_accessor_descriptor();
192
+ if (accessor->get.has_value())
193
+ return accessor->get.value()(thisVal, std::span<const AnyValue>{});
194
+ else
195
+ {
196
+ return Constants::UNDEFINED;
197
+ }
198
+ }
199
+ return val;
200
+ }
201
+ inline AnyValue AnyValue::resolve_property_for_write(AnyValue &val, AnyValue thisVal, const AnyValue &new_val, const std::string &propName)
202
+ {
203
+ if (val.is_data_descriptor())
204
+ {
205
+ auto data = val.as_data_descriptor();
206
+ if (data->writable)
207
+ {
208
+ data->value = new_val;
209
+ return new_val;
210
+ }
211
+ else
212
+ {
213
+ throw Exception::make_exception("Cannot assign to read only property '" + propName + "' of object '#<Object>'", "TypeError");
214
+ }
215
+ }
216
+ if (val.is_accessor_descriptor())
217
+ {
218
+ auto accessor = val.as_accessor_descriptor();
219
+ if (accessor->set.has_value())
220
+ {
221
+ const AnyValue args[] = {new_val};
222
+ accessor->set.value()(thisVal, std::span<const AnyValue>(args, 1));
223
+ return new_val;
224
+ }
225
+ else
226
+ {
227
+ throw Exception::make_exception("Cannot set property of #<Object> which has only a getter", "TypeError");
228
+ }
229
+ }
230
+ val = new_val;
231
+ return new_val;
232
+ }
233
+
234
+ inline std::string AnyValue::to_std_string() const
235
+ {
236
+ switch (get_type())
237
+ {
238
+ case JsType::Undefined:
239
+ return "undefined";
240
+ case JsType::Null:
241
+ return "null";
242
+ case JsType::Boolean:
243
+ return as_boolean() ? "true" : "false";
244
+ case JsType::String:
245
+ return as_string()->to_std_string();
246
+ case JsType::Object:
247
+ return as_object()->to_std_string();
248
+ case JsType::Array:
249
+ return as_array()->to_std_string();
250
+ case JsType::Function:
251
+ return as_function()->to_std_string();
252
+ case JsType::Iterator:
253
+ return as_iterator()->to_std_string();
254
+ case JsType::AsyncIterator:
255
+ return as_async_iterator()->to_std_string();
256
+ case JsType::Promise:
257
+ return as_promise()->to_std_string();
258
+ case JsType::Symbol:
259
+ return as_symbol()->to_std_string();
260
+ case JsType::DataDescriptor:
261
+ return as_data_descriptor()->value.to_std_string();
262
+ case JsType::AccessorDescriptor:
263
+ {
264
+ if (as_accessor_descriptor()->get.has_value())
265
+ return as_accessor_descriptor()->get.value()(*this, {}).to_std_string();
266
+ else
267
+ return "undefined";
268
+ }
269
+ case JsType::Number:
270
+ {
271
+ double num = as_double();
272
+ if (std::isnan(num))
273
+ {
274
+ return "NaN";
275
+ }
276
+ if (std::abs(num) >= 1e21 || (std::abs(num) > 0 && std::abs(num) < 1e-6))
277
+ {
278
+ std::ostringstream oss;
279
+ oss << std::scientific << std::setprecision(4) << num;
280
+ return oss.str();
281
+ }
282
+ else
283
+ {
284
+ std::ostringstream oss;
285
+ oss << std::setprecision(6) << std::fixed << num;
286
+ std::string s = oss.str();
287
+ s.erase(s.find_last_not_of('0') + 1, std::string::npos);
288
+ if (!s.empty() && s.back() == '.')
289
+ {
290
+ s.pop_back();
291
+ }
292
+ return s;
293
+ }
294
+ }
295
+ case JsType::Uninitialized:
296
+ Exception::throw_uninitialized_reference("#<Object>");
297
+ default:
298
+ return "";
299
+ }
300
+ }
301
+
302
+ inline std::string AnyValue::to_property_key() const
303
+ {
304
+ if (is_symbol())
305
+ {
306
+ return as_symbol()->key;
307
+ }
308
+ return to_std_string();
309
+ }
310
+
311
+ inline void AnyValue::set_prototype(AnyValue proto)
312
+ {
313
+ if (is_object())
314
+ {
315
+ as_object()->proto = proto;
316
+ }
317
+ else if (is_array())
318
+ {
319
+ as_array()->proto = proto;
320
+ }
321
+ else if (is_function())
322
+ {
323
+ as_function()->proto = proto;
324
+ }
325
+ else if (is_uninitialized())
326
+ {
327
+ Exception::throw_uninitialized_reference("#<Object>");
328
+ }
329
+ }
330
+
331
+ // AnyValue::call implementation
332
+ inline AnyValue AnyValue::call(AnyValue thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr) const
333
+ {
334
+ if (!is_function())
335
+ throw Exception::make_exception(expr.value_or(to_std_string()) + " is not a function", "TypeError");
336
+ return as_function()->call(thisVal, args);
337
+ }
338
+ inline AnyValue AnyValue::optional_call(AnyValue thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr) const
339
+ {
340
+ if (is_null() || is_undefined())
341
+ return Constants::UNDEFINED;
342
+ return as_function()->call(thisVal, args);
343
+ }
344
+
345
+ // AnyValue::construct implementation
346
+ inline AnyValue AnyValue::construct(std::span<const AnyValue> args, const std::optional<std::string> &name) const
347
+ {
348
+ if (!is_function() || !as_function()->is_constructor)
349
+ {
350
+ throw Exception::make_exception(name.value_or(to_std_string()) + " is not a constructor", "TypeError");
351
+ }
352
+
353
+ // 1. Get prototype
354
+ AnyValue proto = get_own_property("prototype");
355
+ if (!proto.is_object())
356
+ {
357
+ proto = AnyValue::make_object({});
358
+ }
359
+
360
+ // 2. Create instance
361
+ AnyValue instance = AnyValue::make_object_with_proto({}, proto);
362
+
363
+ // 3. Call function
364
+ AnyValue result = call(instance, args);
365
+
366
+ // 4. Return result if object, else instance
367
+ if (result.is_object() || result.is_function() || result.is_array() || result.is_promise())
368
+ {
369
+ return result;
370
+ }
371
+ return instance;
372
+ }
373
+
374
+ }