@ugo-studio/jspp 0.2.9 → 0.3.1

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 (97) hide show
  1. package/LICENSE +25 -25
  2. package/README.md +20 -12
  3. package/dist/analysis/scope.js +5 -3
  4. package/dist/analysis/typeAnalyzer.js +21 -25
  5. package/dist/cli/index.js +14 -4
  6. package/dist/cli/utils.js +61 -0
  7. package/dist/core/codegen/class-handlers.js +6 -6
  8. package/dist/core/codegen/control-flow-handlers.js +10 -9
  9. package/dist/core/codegen/declaration-handlers.js +10 -3
  10. package/dist/core/codegen/destructuring-handlers.js +9 -4
  11. package/dist/core/codegen/expression-handlers.js +40 -29
  12. package/dist/core/codegen/function-handlers.js +78 -12
  13. package/dist/core/codegen/helpers.js +91 -14
  14. package/dist/core/codegen/index.js +4 -2
  15. package/dist/core/codegen/statement-handlers.js +9 -7
  16. package/package.json +2 -2
  17. package/scripts/precompile-headers.ts +249 -50
  18. package/scripts/setup-compiler.ts +63 -63
  19. package/src/prelude/any_value.cpp +636 -0
  20. package/src/prelude/any_value.hpp +369 -362
  21. package/src/prelude/{exception_helpers.hpp → exception.cpp} +53 -53
  22. package/src/prelude/exception.hpp +27 -27
  23. package/src/prelude/iterator_instantiations.hpp +10 -0
  24. package/src/prelude/{index.hpp → jspp.hpp} +10 -16
  25. package/src/prelude/library/array.cpp +191 -0
  26. package/src/prelude/library/array.hpp +13 -186
  27. package/src/prelude/library/console.cpp +125 -0
  28. package/src/prelude/library/console.hpp +24 -112
  29. package/src/prelude/library/error.cpp +100 -0
  30. package/src/prelude/library/error.hpp +13 -113
  31. package/src/prelude/library/function.cpp +69 -0
  32. package/src/prelude/library/function.hpp +11 -10
  33. package/src/prelude/library/global.cpp +96 -0
  34. package/src/prelude/library/global.hpp +12 -28
  35. package/src/prelude/library/global_usings.hpp +15 -0
  36. package/src/prelude/library/math.cpp +258 -0
  37. package/src/prelude/library/math.hpp +26 -308
  38. package/src/prelude/library/object.cpp +379 -0
  39. package/src/prelude/library/object.hpp +14 -276
  40. package/src/prelude/library/performance.cpp +21 -0
  41. package/src/prelude/library/performance.hpp +5 -20
  42. package/src/prelude/library/process.cpp +38 -0
  43. package/src/prelude/library/process.hpp +11 -39
  44. package/src/prelude/library/promise.cpp +131 -0
  45. package/src/prelude/library/promise.hpp +12 -123
  46. package/src/prelude/library/symbol.cpp +56 -0
  47. package/src/prelude/library/symbol.hpp +11 -52
  48. package/src/prelude/library/timer.cpp +88 -0
  49. package/src/prelude/library/timer.hpp +16 -92
  50. package/src/prelude/runtime.cpp +19 -0
  51. package/src/prelude/types.hpp +184 -179
  52. package/src/prelude/utils/access.hpp +502 -411
  53. package/src/prelude/utils/assignment_operators.hpp +99 -99
  54. package/src/prelude/utils/log_any_value/array.hpp +61 -40
  55. package/src/prelude/utils/log_any_value/function.hpp +39 -39
  56. package/src/prelude/utils/log_any_value/object.hpp +60 -3
  57. package/src/prelude/utils/operators.hpp +351 -336
  58. package/src/prelude/utils/operators_primitive.hpp +336 -336
  59. package/src/prelude/utils/well_known_symbols.hpp +24 -24
  60. package/src/prelude/values/array.cpp +1399 -0
  61. package/src/prelude/values/array.hpp +4 -1
  62. package/src/prelude/values/async_iterator.cpp +251 -0
  63. package/src/prelude/values/async_iterator.hpp +111 -83
  64. package/src/prelude/values/function.cpp +262 -0
  65. package/src/prelude/values/function.hpp +62 -82
  66. package/src/prelude/values/iterator.cpp +309 -0
  67. package/src/prelude/values/iterator.hpp +33 -64
  68. package/src/prelude/values/number.cpp +176 -0
  69. package/src/prelude/values/object.cpp +159 -0
  70. package/src/prelude/values/object.hpp +4 -0
  71. package/src/prelude/values/promise.cpp +479 -0
  72. package/src/prelude/values/promise.hpp +79 -72
  73. package/src/prelude/values/prototypes/array.hpp +46 -1336
  74. package/src/prelude/values/prototypes/async_iterator.hpp +19 -61
  75. package/src/prelude/values/prototypes/function.hpp +7 -46
  76. package/src/prelude/values/prototypes/iterator.hpp +25 -201
  77. package/src/prelude/values/prototypes/number.hpp +23 -210
  78. package/src/prelude/values/prototypes/object.hpp +7 -23
  79. package/src/prelude/values/prototypes/promise.hpp +18 -196
  80. package/src/prelude/values/prototypes/string.hpp +39 -542
  81. package/src/prelude/values/prototypes/symbol.hpp +9 -70
  82. package/src/prelude/values/shape.hpp +52 -52
  83. package/src/prelude/values/string.cpp +485 -0
  84. package/src/prelude/values/string.hpp +25 -26
  85. package/src/prelude/values/symbol.cpp +89 -0
  86. package/src/prelude/values/symbol.hpp +101 -101
  87. package/src/prelude/any_value_access.hpp +0 -170
  88. package/src/prelude/any_value_defines.hpp +0 -190
  89. package/src/prelude/any_value_helpers.hpp +0 -374
  90. package/src/prelude/values/helpers/array.hpp +0 -209
  91. package/src/prelude/values/helpers/async_iterator.hpp +0 -275
  92. package/src/prelude/values/helpers/function.hpp +0 -109
  93. package/src/prelude/values/helpers/iterator.hpp +0 -145
  94. package/src/prelude/values/helpers/object.hpp +0 -104
  95. package/src/prelude/values/helpers/promise.hpp +0 -254
  96. package/src/prelude/values/helpers/string.hpp +0 -61
  97. package/src/prelude/values/helpers/symbol.hpp +0 -21
@@ -0,0 +1,636 @@
1
+ #include "jspp.hpp"
2
+ #include "any_value.hpp"
3
+ #include "values/iterator.hpp"
4
+ #include "values/async_iterator.hpp"
5
+ #include "values/string.hpp"
6
+ #include "values/object.hpp"
7
+ #include "values/array.hpp"
8
+ #include "values/function.hpp"
9
+ #include "values/promise.hpp"
10
+ #include "values/symbol.hpp"
11
+ #include "values/descriptors.hpp"
12
+ #include "exception.hpp"
13
+
14
+ namespace jspp {
15
+
16
+ // --- AnyValue methods that were in any_value_helpers.hpp ---
17
+
18
+ bool AnyValue::operator==(const AnyValue &other) const noexcept {
19
+ return storage == other.storage;
20
+ }
21
+ bool AnyValue::operator==(const std::string &other) const noexcept {
22
+ if (!is_string())
23
+ return false;
24
+ return as_string()->value == other;
25
+ }
26
+ bool AnyValue::operator<(const AnyValue &other) const noexcept {
27
+ return storage < other.storage;
28
+ }
29
+
30
+ JsString *AnyValue::as_string() const noexcept { return static_cast<JsString *>(get_ptr()); }
31
+ JsObject *AnyValue::as_object() const noexcept { return static_cast<JsObject *>(get_ptr()); }
32
+ JsArray *AnyValue::as_array() const noexcept { return static_cast<JsArray *>(get_ptr()); }
33
+ JsFunction *AnyValue::as_function() const noexcept { return static_cast<JsFunction *>(get_ptr()); }
34
+ JsSymbol *AnyValue::as_symbol() const noexcept { return static_cast<JsSymbol *>(get_ptr()); }
35
+ JsPromise *AnyValue::as_promise() const noexcept { return static_cast<JsPromise *>(get_ptr()); }
36
+ DataDescriptor *AnyValue::as_data_descriptor() const noexcept { return static_cast<DataDescriptor *>(get_ptr()); }
37
+ AccessorDescriptor *AnyValue::as_accessor_descriptor() const noexcept { return static_cast<AccessorDescriptor *>(get_ptr()); }
38
+
39
+ bool AnyValue::is_generator() const noexcept { return is_function() && as_function()->is_generator; }
40
+
41
+ // --- AnyValue FACTORIES ---
42
+ AnyValue AnyValue::make_string(const std::string &raw_s) noexcept
43
+ {
44
+ return from_ptr(new JsString(raw_s));
45
+ }
46
+ AnyValue AnyValue::make_object(std::initializer_list<std::pair<std::string, AnyValue>> props) noexcept
47
+ {
48
+ return from_ptr(new JsObject(props, make_null()));
49
+ }
50
+ AnyValue AnyValue::make_object(const std::map<std::string, AnyValue> &props) noexcept
51
+ {
52
+ return from_ptr(new JsObject(props, make_null()));
53
+ }
54
+ AnyValue AnyValue::make_array(std::span<const AnyValue> dense) noexcept
55
+ {
56
+ std::vector<AnyValue> vec;
57
+ vec.reserve(dense.size());
58
+ for (const auto &item : dense)
59
+ vec.push_back(item);
60
+ return from_ptr(new JsArray(std::move(vec)));
61
+ }
62
+ AnyValue AnyValue::make_array(const std::vector<AnyValue> &dense) noexcept
63
+ {
64
+ return from_ptr(new JsArray(dense));
65
+ }
66
+ AnyValue AnyValue::make_array(std::vector<AnyValue> &&dense) noexcept
67
+ {
68
+ return from_ptr(new JsArray(std::move(dense)));
69
+ }
70
+ AnyValue AnyValue::make_function(const JsFunctionCallable &call, const std::optional<std::string> &name, bool is_constructor) noexcept
71
+ {
72
+ auto v = from_ptr(new JsFunction(call, name, {}, {}, false, is_constructor));
73
+ auto proto = make_object({});
74
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
75
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
76
+ return v;
77
+ }
78
+ AnyValue AnyValue::make_class(const JsFunctionCallable &call, const std::optional<std::string> &name) noexcept
79
+ {
80
+ auto v = from_ptr(new JsFunction(call, name, {}, {}, true));
81
+ auto proto = make_object({});
82
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
83
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
84
+ return v;
85
+ }
86
+ AnyValue AnyValue::make_generator(const JsFunctionCallable &call, const std::optional<std::string> &name) noexcept
87
+ {
88
+ auto v = from_ptr(new JsFunction(call, true, name, {}, {}, false));
89
+ auto proto = make_object({});
90
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
91
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
92
+ return v;
93
+ }
94
+ AnyValue AnyValue::make_async_function(const JsFunctionCallable &call, const std::optional<std::string> &name) noexcept
95
+ {
96
+ auto v = from_ptr(new JsFunction(call, false, true, name, {}, {}, false));
97
+ auto proto = make_object({});
98
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
99
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
100
+ return v;
101
+ }
102
+ AnyValue AnyValue::make_async_generator(const JsFunctionCallable &call, const std::optional<std::string> &name) noexcept
103
+ {
104
+ auto v = from_ptr(new JsFunction(call, true, true, name, {}, {}, false));
105
+ auto proto = make_object({});
106
+ proto.define_data_property("constructor", AnyValue::make_data_descriptor(v, true, false, false));
107
+ v.define_data_property("prototype", AnyValue::make_data_descriptor(proto, false, false, false));
108
+ return v;
109
+ }
110
+ AnyValue AnyValue::make_symbol(const std::string &description) noexcept
111
+ {
112
+ return from_ptr(new JsSymbol(description));
113
+ }
114
+ AnyValue AnyValue::make_promise(const JsPromise &promise) noexcept
115
+ {
116
+ auto p = new JsPromise();
117
+ *p = promise;
118
+ return from_ptr(p);
119
+ }
120
+ AnyValue AnyValue::make_data_descriptor(AnyValue value, bool writable, bool enumerable, bool configurable) noexcept
121
+ {
122
+ return from_ptr(new DataDescriptor(value, writable, enumerable, configurable));
123
+ }
124
+ AnyValue AnyValue::make_accessor_descriptor(const std::optional<std::function<AnyValue(AnyValue, std::span<const AnyValue>)>> &get,
125
+ const std::optional<std::function<AnyValue(AnyValue, std::span<const AnyValue>)>> &set,
126
+ bool enumerable,
127
+ bool configurable) noexcept
128
+ {
129
+ return from_ptr(new AccessorDescriptor(get, set, enumerable, configurable));
130
+ }
131
+
132
+ AnyValue AnyValue::from_symbol(JsSymbol *sym) noexcept {
133
+ return from_ptr(sym);
134
+ }
135
+ AnyValue AnyValue::from_string(JsString *str) noexcept {
136
+ return from_ptr(str);
137
+ }
138
+ AnyValue AnyValue::from_promise(JsPromise &&promise) noexcept {
139
+ auto it = new JsPromise(std::move(promise));
140
+ return from_ptr(it);
141
+ }
142
+ AnyValue AnyValue::from_iterator(JsIterator<AnyValue> &&iterator) noexcept {
143
+ auto it = new JsIterator<AnyValue>(std::move(iterator));
144
+ return from_ptr(it);
145
+ }
146
+ AnyValue AnyValue::from_iterator_ref(JsIterator<AnyValue> *iterator) noexcept {
147
+ return from_ptr(iterator);
148
+ }
149
+ AnyValue AnyValue::from_async_iterator(JsAsyncIterator<AnyValue> &&iterator) noexcept {
150
+ auto it = new JsAsyncIterator<AnyValue>(std::move(iterator));
151
+ return from_ptr(it);
152
+ }
153
+
154
+ AnyValue AnyValue::resolve_property_for_read(const AnyValue &val, AnyValue thisVal, const std::string &propName) noexcept {
155
+ if (val.is_data_descriptor()) {
156
+ return val.as_data_descriptor()->value;
157
+ }
158
+ if (val.is_accessor_descriptor()) {
159
+ auto accessor = val.as_accessor_descriptor();
160
+ if (accessor->get.has_value())
161
+ return accessor->get.value()(thisVal, std::span<const AnyValue>{});
162
+ else {
163
+ return Constants::UNDEFINED;
164
+ }
165
+ }
166
+ return val;
167
+ }
168
+
169
+ AnyValue AnyValue::resolve_property_for_write(AnyValue &val, AnyValue thisVal, const AnyValue &new_val, const std::string &propName) {
170
+ if (val.is_data_descriptor()) {
171
+ auto data = val.as_data_descriptor();
172
+ if (data->writable) {
173
+ data->value = new_val;
174
+ return new_val;
175
+ } else {
176
+ throw Exception::make_exception("Cannot assign to read only property '" + propName + "' of object '#<Object>'", "TypeError");
177
+ }
178
+ }
179
+ if (val.is_accessor_descriptor()) {
180
+ auto accessor = val.as_accessor_descriptor();
181
+ if (accessor->set.has_value()) {
182
+ const AnyValue args[] = {new_val};
183
+ accessor->set.value()(thisVal, std::span<const AnyValue>(args, 1));
184
+ return new_val;
185
+ } else {
186
+ throw Exception::make_exception("Cannot set property of #<Object> which has only a getter", "TypeError");
187
+ }
188
+ }
189
+ val = new_val;
190
+ return new_val;
191
+ }
192
+
193
+ std::string AnyValue::to_std_string() const {
194
+ switch (get_type()) {
195
+ case JsType::Undefined: return "undefined";
196
+ case JsType::Null: return "null";
197
+ case JsType::Boolean: return as_boolean() ? "true" : "false";
198
+ case JsType::String: return as_string()->to_std_string();
199
+ case JsType::Object: return as_object()->to_std_string();
200
+ case JsType::Array: return as_array()->to_std_string();
201
+ case JsType::Function: return as_function()->to_std_string();
202
+ case JsType::Iterator: return as_iterator()->to_std_string();
203
+ case JsType::AsyncIterator: return as_async_iterator()->to_std_string();
204
+ case JsType::Promise: return as_promise()->to_std_string();
205
+ case JsType::Symbol: return as_symbol()->to_std_string();
206
+ case JsType::DataDescriptor: return as_data_descriptor()->value.to_std_string();
207
+ case JsType::AccessorDescriptor: {
208
+ if (as_accessor_descriptor()->get.has_value())
209
+ return as_accessor_descriptor()->get.value()(*this, {}).to_std_string();
210
+ else
211
+ return "undefined";
212
+ }
213
+ case JsType::Number: {
214
+ double num = as_double();
215
+ if (std::isnan(num)) return "NaN";
216
+ if (std::abs(num) >= 1e21 || (std::abs(num) > 0 && std::abs(num) < 1e-6)) {
217
+ std::ostringstream oss;
218
+ oss << std::scientific << std::setprecision(4) << num;
219
+ return oss.str();
220
+ } else {
221
+ std::ostringstream oss;
222
+ oss << std::setprecision(6) << std::fixed << num;
223
+ std::string s = oss.str();
224
+ s.erase(s.find_last_not_of('0') + 1, std::string::npos);
225
+ if (!s.empty() && s.back() == '.') s.pop_back();
226
+ return s;
227
+ }
228
+ }
229
+ case JsType::Uninitialized: Exception::throw_uninitialized_reference("#<Object>");
230
+ default: return "";
231
+ }
232
+ }
233
+
234
+ std::string AnyValue::to_property_key() const {
235
+ if (is_symbol()) return as_symbol()->key;
236
+ return to_std_string();
237
+ }
238
+
239
+ AnyValue &AnyValue::set_prototype(AnyValue proto) {
240
+ if (is_object()) as_object()->proto = proto;
241
+ else if (is_array()) as_array()->proto = proto;
242
+ else if (is_function()) as_function()->proto = proto;
243
+ else if (is_uninitialized()) Exception::throw_uninitialized_reference("#<Object>");
244
+ return *this;
245
+ }
246
+
247
+ AnyValue AnyValue::call(AnyValue thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr) const {
248
+ if (!is_function())
249
+ throw Exception::make_exception(expr.value_or(to_std_string()) + " is not a function", "TypeError");
250
+ return as_function()->call(thisVal, args);
251
+ }
252
+ AnyValue AnyValue::optional_call(AnyValue thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr) const {
253
+ if (is_null() || is_undefined()) return Constants::UNDEFINED;
254
+ return as_function()->call(thisVal, args);
255
+ }
256
+
257
+ AnyValue AnyValue::construct(std::span<const AnyValue> args, const std::optional<std::string> &name) const {
258
+ if (!is_function() || !as_function()->is_constructor) {
259
+ throw Exception::make_exception(name.value_or(to_std_string()) + " is not a constructor", "TypeError");
260
+ }
261
+ AnyValue proto = get_own_property("prototype");
262
+ if (!proto.is_object()) proto = AnyValue::make_object({});
263
+ AnyValue instance = AnyValue::make_object({}).set_prototype(proto);
264
+ AnyValue result = call(instance, args);
265
+ if (result.is_object() || result.is_function() || result.is_array() || result.is_promise()) return result;
266
+ return instance;
267
+ }
268
+
269
+ // --- AnyValue methods that were in any_value_access.hpp ---
270
+
271
+ AnyValue AnyValue::get_own_property(const std::string &key) const {
272
+ return get_property_with_receiver(key, *this);
273
+ }
274
+
275
+ AnyValue AnyValue::get_own_property_descriptor(const AnyValue &key) const {
276
+ if (key.is_symbol()) {
277
+ switch (get_type()) {
278
+ case JsType::Object: {
279
+ auto obj = as_object();
280
+ auto it = obj->symbol_props.find(key);
281
+ if (it != obj->symbol_props.end()) return it->second;
282
+ return Constants::UNDEFINED;
283
+ }
284
+ case JsType::Array: {
285
+ auto arr = as_array();
286
+ auto it = arr->symbol_props.find(key);
287
+ if (it != arr->symbol_props.end()) return it->second;
288
+ return Constants::UNDEFINED;
289
+ }
290
+ case JsType::Function: {
291
+ auto func = as_function();
292
+ auto it = func->symbol_props.find(key);
293
+ if (it != func->symbol_props.end()) return it->second;
294
+ return Constants::UNDEFINED;
295
+ }
296
+ default: return Constants::UNDEFINED;
297
+ }
298
+ }
299
+
300
+ std::string key_str = key.to_std_string();
301
+ switch (get_type()) {
302
+ case JsType::Object: {
303
+ auto obj = as_object();
304
+ if (obj->deleted_keys.count(key_str)) return Constants::UNDEFINED;
305
+ auto offset = obj->shape->get_offset(key_str);
306
+ if (offset.has_value()) return obj->storage[offset.value()];
307
+ return Constants::UNDEFINED;
308
+ }
309
+ case JsType::Array: {
310
+ auto arr = as_array();
311
+ if (key_str == "length") return AnyValue::make_number(arr->length);
312
+ if (JsArray::is_array_index(key_str)) {
313
+ uint32_t idx = static_cast<uint32_t>(std::stoull(key_str));
314
+ if (idx < arr->dense.size() && !arr->dense[idx].is_uninitialized()) return arr->dense[idx];
315
+ if (arr->sparse.count(idx)) return arr->sparse[idx];
316
+ }
317
+ if (arr->props.count(key_str)) return arr->props.at(key_str);
318
+ return Constants::UNDEFINED;
319
+ }
320
+ case JsType::Function: {
321
+ auto func = as_function();
322
+ if (func->props.count(key_str)) return func->props.at(key_str);
323
+ return Constants::UNDEFINED;
324
+ }
325
+ case JsType::String: {
326
+ auto str = as_string();
327
+ if (key_str == "length") return AnyValue::make_number(str->value.length());
328
+ if (JsArray::is_array_index(key_str)) {
329
+ uint32_t idx = static_cast<uint32_t>(std::stoull(key_str));
330
+ if (idx < str->value.length()) return AnyValue::make_string(std::string(1, str->value[idx]));
331
+ }
332
+ return Constants::UNDEFINED;
333
+ }
334
+ default: return Constants::UNDEFINED;
335
+ }
336
+ }
337
+
338
+ bool AnyValue::has_property(const std::string &key) const {
339
+ switch (get_type()) {
340
+ case JsType::Object: return as_object()->has_property(key);
341
+ case JsType::Array: return as_array()->has_property(key);
342
+ case JsType::Function: return as_function()->has_property(key);
343
+ case JsType::Promise: return as_promise()->get_property(key, *this).is_undefined() == false;
344
+ case JsType::Iterator: return static_cast<JsIterator<AnyValue> *>(get_ptr())->get_property(key, *this).is_undefined() == false;
345
+ case JsType::AsyncIterator: return static_cast<JsAsyncIterator<AnyValue> *>(get_ptr())->get_property(key, *this).is_undefined() == false;
346
+ case JsType::Symbol: return SymbolPrototypes::get(key).has_value();
347
+ case JsType::String:
348
+ if (key == "length") return true;
349
+ if (JsArray::is_array_index(key)) {
350
+ uint32_t idx = static_cast<uint32_t>(std::stoull(key));
351
+ return idx < as_string()->value.length();
352
+ }
353
+ return StringPrototypes::get(key).has_value();
354
+ case JsType::Number: return NumberPrototypes::get(key).has_value();
355
+ case JsType::Uninitialized: Exception::throw_uninitialized_reference("#<Object>"); return false;
356
+ default: return false;
357
+ }
358
+ }
359
+
360
+ bool AnyValue::has_property(const AnyValue &key) const {
361
+ if (key.is_symbol()) {
362
+ switch (get_type()) {
363
+ case JsType::Object: return as_object()->has_symbol_property(key);
364
+ case JsType::Array: return as_array()->has_symbol_property(key);
365
+ case JsType::Function: return as_function()->has_symbol_property(key);
366
+ case JsType::Promise: return as_promise()->has_symbol_property(key);
367
+ case JsType::Iterator: return static_cast<JsIterator<AnyValue> *>(get_ptr())->has_symbol_property(key);
368
+ case JsType::AsyncIterator: return static_cast<JsAsyncIterator<AnyValue> *>(get_ptr())->has_symbol_property(key);
369
+ default: return false;
370
+ }
371
+ }
372
+ return has_property(key.to_std_string());
373
+ }
374
+
375
+ AnyValue AnyValue::get_own_property(uint32_t idx) const {
376
+ if (is_array()) return as_array()->get_property(idx);
377
+ if (is_string()) return as_string()->get_property(idx);
378
+ return get_own_property(std::to_string(idx));
379
+ }
380
+
381
+ AnyValue AnyValue::get_own_property(const AnyValue &key) const {
382
+ if (key.is_number() && is_array()) return as_array()->get_property(key.as_double());
383
+ if (key.is_number() && is_string()) return as_string()->get_property(key.as_double());
384
+ if (key.is_symbol()) return get_own_symbol_property(key);
385
+ return get_own_property(key.to_std_string());
386
+ }
387
+
388
+ AnyValue AnyValue::get_own_symbol_property(const AnyValue &key) const {
389
+ return get_symbol_property_with_receiver(key, *this);
390
+ }
391
+
392
+ AnyValue AnyValue::get_property_with_receiver(const std::string &key, AnyValue receiver) const {
393
+ switch (get_type()) {
394
+ case JsType::Object: return as_object()->get_property(key, receiver);
395
+ case JsType::Array: return as_array()->get_property(key, receiver);
396
+ case JsType::Function: return as_function()->get_property(key, receiver);
397
+ case JsType::Promise: return as_promise()->get_property(key, receiver);
398
+ case JsType::Iterator: return static_cast<JsIterator<AnyValue> *>(get_ptr())->get_property(key, receiver);
399
+ case JsType::AsyncIterator: return static_cast<JsAsyncIterator<AnyValue> *>(get_ptr())->get_property(key, receiver);
400
+ case JsType::Symbol: return as_symbol()->get_property(key, receiver);
401
+ case JsType::String: return as_string()->get_property(key, receiver);
402
+ case JsType::Number: {
403
+ auto proto_it = NumberPrototypes::get(key);
404
+ if (proto_it.has_value()) return AnyValue::resolve_property_for_read(proto_it.value(), receiver, key);
405
+ return Constants::UNDEFINED;
406
+ }
407
+ case JsType::Undefined: throw Exception::make_exception("Cannot read properties of undefined (reading '" + key + "')", "TypeError");
408
+ case JsType::Null: throw Exception::make_exception("Cannot read properties of null (reading '" + key + "')", "TypeError");
409
+ case JsType::Uninitialized: Exception::throw_uninitialized_reference("#<Object>");
410
+ default: return Constants::UNDEFINED;
411
+ }
412
+ }
413
+
414
+ AnyValue AnyValue::get_symbol_property_with_receiver(const AnyValue &key, AnyValue receiver) const {
415
+ switch (get_type()) {
416
+ case JsType::Object: return as_object()->get_symbol_property(key, receiver);
417
+ case JsType::Array: return as_array()->get_symbol_property(key, receiver);
418
+ case JsType::Function: return as_function()->get_symbol_property(key, receiver);
419
+ case JsType::Promise: return as_promise()->get_symbol_property(key, receiver);
420
+ case JsType::Iterator: return static_cast<JsIterator<AnyValue> *>(get_ptr())->get_symbol_property(key, receiver);
421
+ case JsType::AsyncIterator: return static_cast<JsAsyncIterator<AnyValue> *>(get_ptr())->get_symbol_property(key, receiver);
422
+ case JsType::Symbol: {
423
+ auto proto_it = SymbolPrototypes::get(key);
424
+ if (proto_it.has_value()) return AnyValue::resolve_property_for_read(proto_it.value(), receiver, key.to_std_string());
425
+ return Constants::UNDEFINED;
426
+ }
427
+ case JsType::String: {
428
+ auto proto_it = StringPrototypes::get(key);
429
+ if (proto_it.has_value()) return AnyValue::resolve_property_for_read(proto_it.value(), receiver, key.to_std_string());
430
+ return Constants::UNDEFINED;
431
+ }
432
+ case JsType::Number: {
433
+ auto proto_it = NumberPrototypes::get(key);
434
+ if (proto_it.has_value()) return AnyValue::resolve_property_for_read(proto_it.value(), receiver, key.to_std_string());
435
+ return Constants::UNDEFINED;
436
+ }
437
+ case JsType::Undefined: throw Exception::make_exception("Cannot read properties of undefined (reading Symbol)", "TypeError");
438
+ case JsType::Null: throw Exception::make_exception("Cannot read properties of null (reading Symbol)", "TypeError");
439
+ case JsType::Uninitialized: Exception::throw_uninitialized_reference("#<Object>");
440
+ default: return Constants::UNDEFINED;
441
+ }
442
+ }
443
+
444
+ AnyValue AnyValue::set_own_property(const std::string &key, AnyValue value) const {
445
+ switch (get_type()) {
446
+ case JsType::Object: return as_object()->set_property(key, value, *this);
447
+ case JsType::Array: return as_array()->set_property(key, value, *this);
448
+ case JsType::Function: return as_function()->set_property(key, value, *this);
449
+ case JsType::Promise: return as_promise()->set_property(key, value, *this);
450
+ case JsType::Undefined: throw Exception::make_exception("Cannot set properties of undefined (setting '" + key + "')", "TypeError");
451
+ case JsType::Null: throw Exception::make_exception("Cannot set properties of null (setting '" + key + "')", "TypeError");
452
+ default: return value;
453
+ }
454
+ }
455
+
456
+ AnyValue AnyValue::set_own_property(uint32_t idx, AnyValue value) const {
457
+ if (is_array()) return as_array()->set_property(idx, value);
458
+ return set_own_property(std::to_string(idx), value);
459
+ }
460
+
461
+ AnyValue AnyValue::set_own_property(const AnyValue &key, AnyValue value) const {
462
+ if (key.is_number() && is_array()) return as_array()->set_property(key.as_double(), value);
463
+ if (key.is_symbol()) return set_own_symbol_property(key, value);
464
+ return set_own_property(key.to_std_string(), value);
465
+ }
466
+
467
+ AnyValue AnyValue::set_own_symbol_property(const AnyValue &key, AnyValue value) const {
468
+ switch (get_type()) {
469
+ case JsType::Object: return as_object()->set_symbol_property(key, value, *this);
470
+ case JsType::Array: return as_array()->set_symbol_property(key, value, *this);
471
+ case JsType::Function: return as_function()->set_symbol_property(key, value, *this);
472
+ case JsType::Promise: return as_promise()->set_symbol_property(key, value, *this);
473
+ case JsType::Iterator: return static_cast<JsIterator<AnyValue> *>(get_ptr())->set_symbol_property(key, value, *this);
474
+ case JsType::AsyncIterator: return static_cast<JsAsyncIterator<AnyValue> *>(get_ptr())->set_symbol_property(key, value, *this);
475
+ case JsType::Undefined: throw Exception::make_exception("Cannot set properties of undefined (setting Symbol)", "TypeError");
476
+ case JsType::Null: throw Exception::make_exception("Cannot set properties of null (setting Symbol)", "TypeError");
477
+ default: return value;
478
+ }
479
+ }
480
+
481
+ AnyValue AnyValue::call_own_property(const std::string &key, std::span<const AnyValue> args) const {
482
+ return get_own_property(key).call((*this), args, key);
483
+ }
484
+ AnyValue AnyValue::call_own_property(uint32_t idx, std::span<const AnyValue> args) const {
485
+ if (is_array()) return as_array()->get_property(idx).call((*this), args, "[" + std::to_string(idx) + "]");
486
+ if (is_string()) return as_string()->get_property(idx).call((*this), args, "[" + std::to_string(idx) + "]");
487
+ return call_own_property(std::to_string(idx), args);
488
+ }
489
+ AnyValue AnyValue::call_own_property(const AnyValue &key, std::span<const AnyValue> args) const {
490
+ if (key.is_number() && is_array()) return as_array()->get_property(key.as_double()).call((*this), args, "[" + key.to_std_string() + "]");
491
+ if (key.is_number() && is_string()) return as_string()->get_property(key.as_double()).call((*this), args, "[" + key.to_std_string() + "]");
492
+ if (key.is_symbol()) return get_own_symbol_property(key).call((*this), args, key.to_std_string());
493
+ return call_own_property(key.to_std_string(), args);
494
+ }
495
+
496
+ // --- AnyValue methods that were in any_value_defines.hpp ---
497
+
498
+ void AnyValue::define_data_property(const std::string &key, AnyValue value) {
499
+ if (is_object()) {
500
+ auto obj = as_object();
501
+ auto offset = obj->shape->get_offset(key);
502
+ if (offset.has_value()) obj->storage[offset.value()] = value;
503
+ else {
504
+ obj->shape = obj->shape->transition(key);
505
+ obj->storage.push_back(value);
506
+ }
507
+ } else if (is_function()) as_function()->props[key] = value;
508
+ }
509
+
510
+ void AnyValue::define_data_property(const AnyValue &key, AnyValue value) {
511
+ if (key.is_symbol()) {
512
+ if (is_object()) as_object()->symbol_props[key] = value;
513
+ else if (is_function()) as_function()->symbol_props[key] = value;
514
+ } else define_data_property(key.to_std_string(), value);
515
+ }
516
+
517
+ void AnyValue::define_data_property(const std::string &key, AnyValue value, bool writable, bool enumerable, bool configurable) {
518
+ define_data_property(key, AnyValue::make_data_descriptor(value, writable, enumerable, configurable));
519
+ }
520
+
521
+ void AnyValue::define_getter(const std::string &key, AnyValue getter) {
522
+ if (is_object()) {
523
+ auto obj = as_object();
524
+ auto offset = obj->shape->get_offset(key);
525
+ if (offset.has_value()) {
526
+ auto &val = obj->storage[offset.value()];
527
+ if (val.is_accessor_descriptor()) {
528
+ auto desc = val.as_accessor_descriptor();
529
+ desc->get = [getter](AnyValue thisVal, std::span<const AnyValue> args) -> AnyValue { return getter.call(thisVal, args); };
530
+ } else {
531
+ auto getFunc = [getter](AnyValue thisVal, std::span<const AnyValue> args) -> AnyValue { return getter.call(thisVal, args); };
532
+ obj->storage[offset.value()] = AnyValue::make_accessor_descriptor(getFunc, std::nullopt, true, true);
533
+ }
534
+ } else {
535
+ auto getFunc = [getter](AnyValue thisVal, std::span<const AnyValue> args) -> AnyValue { return getter.call(thisVal, args); };
536
+ obj->shape = obj->shape->transition(key);
537
+ obj->storage.push_back(AnyValue::make_accessor_descriptor(getFunc, std::nullopt, true, true));
538
+ }
539
+ } else if (is_function()) {
540
+ auto &props = as_function()->props;
541
+ auto it = props.find(key);
542
+ if (it != props.end() && it->second.is_accessor_descriptor()) {
543
+ auto desc = it->second.as_accessor_descriptor();
544
+ desc->get = [getter](AnyValue thisVal, std::span<const AnyValue> args) -> AnyValue { return getter.call(thisVal, args); };
545
+ } else {
546
+ auto getFunc = [getter](AnyValue thisVal, std::span<const AnyValue> args) -> AnyValue { return getter.call(thisVal, args); };
547
+ props[key] = AnyValue::make_accessor_descriptor(getFunc, std::nullopt, true, true);
548
+ }
549
+ }
550
+ }
551
+
552
+ void AnyValue::define_data_property(const AnyValue &key, AnyValue value, bool writable, bool enumerable, bool configurable) {
553
+ if (key.is_symbol()) {
554
+ auto desc = AnyValue::make_data_descriptor(value, writable, enumerable, configurable);
555
+ if (is_object()) as_object()->symbol_props[key] = desc;
556
+ else if (is_function()) as_function()->symbol_props[key] = desc;
557
+ } else define_data_property(key.to_std_string(), value, writable, enumerable, configurable);
558
+ }
559
+
560
+ void AnyValue::define_getter(const AnyValue &key, AnyValue getter) {
561
+ if (key.is_symbol()) {
562
+ auto getFunc = [getter](AnyValue thisVal, std::span<const AnyValue> args) -> AnyValue { return getter.call(thisVal, args); };
563
+ auto desc = AnyValue::make_accessor_descriptor(getFunc, std::nullopt, true, true);
564
+ if (is_object()) as_object()->symbol_props[key] = desc;
565
+ else if (is_function()) as_function()->symbol_props[key] = desc;
566
+ } else define_getter(key.to_std_string(), getter);
567
+ }
568
+
569
+ void AnyValue::define_setter(const std::string &key, AnyValue setter) {
570
+ if (is_object()) {
571
+ auto obj = as_object();
572
+ auto offset = obj->shape->get_offset(key);
573
+ if (offset.has_value()) {
574
+ auto &val = obj->storage[offset.value()];
575
+ if (val.is_accessor_descriptor()) {
576
+ auto desc = val.as_accessor_descriptor();
577
+ desc->set = [setter](AnyValue thisVal, std::span<const AnyValue> args) -> AnyValue {
578
+ if (args.empty()) return Constants::UNDEFINED;
579
+ return setter.call(thisVal, args);
580
+ };
581
+ } else {
582
+ auto setFunc = [setter](AnyValue thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue {
583
+ if (args.empty()) return jspp::Constants::UNDEFINED;
584
+ return setter.call(thisVal, args);
585
+ };
586
+ obj->storage[offset.value()] = AnyValue::make_accessor_descriptor(std::nullopt, setFunc, true, true);
587
+ }
588
+ } else {
589
+ auto setFunc = [setter](AnyValue thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue {
590
+ if (args.empty()) return jspp::Constants::UNDEFINED;
591
+ return setter.call(thisVal, args);
592
+ };
593
+ obj->shape = obj->shape->transition(key);
594
+ obj->storage.push_back(AnyValue::make_accessor_descriptor(std::nullopt, setFunc, true, true));
595
+ }
596
+ } else if (is_function()) {
597
+ auto &props = as_function()->props;
598
+ auto it = props.find(key);
599
+ if (it != props.end() && it->second.is_accessor_descriptor()) {
600
+ auto desc = it->second.as_accessor_descriptor();
601
+ desc->set = [setter](AnyValue thisVal, std::span<const AnyValue> args) -> AnyValue {
602
+ if (args.empty()) return Constants::UNDEFINED;
603
+ return setter.call(thisVal, args);
604
+ };
605
+ } else {
606
+ auto setFunc = [setter](AnyValue thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue {
607
+ if (args.empty()) return jspp::Constants::UNDEFINED;
608
+ return setter.call(thisVal, args);
609
+ };
610
+ props[key] = AnyValue::make_accessor_descriptor(std::nullopt, setFunc, true, true);
611
+ }
612
+ }
613
+ }
614
+
615
+ void AnyValue::define_setter(const AnyValue &key, AnyValue setter) {
616
+ if (key.is_symbol()) {
617
+ auto setFunc = [setter](AnyValue thisVal, std::span<const AnyValue> args) -> AnyValue {
618
+ if (args.empty()) return Constants::UNDEFINED;
619
+ return setter.call(thisVal, args);
620
+ };
621
+ auto desc = AnyValue::make_accessor_descriptor(std::nullopt, setFunc, true, true);
622
+ if (is_object()) as_object()->symbol_props[key] = desc;
623
+ else if (is_function()) as_function()->symbol_props[key] = desc;
624
+ } else define_setter(key.to_std_string(), setter);
625
+ }
626
+
627
+ // AnyValue iterator methods from runtime.cpp
628
+ JsIterator<AnyValue>* AnyValue::as_iterator() const noexcept {
629
+ return static_cast<JsIterator<AnyValue> *>(get_ptr());
630
+ }
631
+
632
+ JsAsyncIterator<AnyValue>* AnyValue::as_async_iterator() const noexcept {
633
+ return static_cast<JsAsyncIterator<AnyValue> *>(get_ptr());
634
+ }
635
+
636
+ } // namespace jspp