@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
@@ -1,374 +0,0 @@
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
- }
@@ -1,209 +0,0 @@
1
- #pragma once
2
-
3
- #include "types.hpp"
4
- #include "values/array.hpp"
5
- #include "exception.hpp"
6
- #include "any_value.hpp"
7
- #include "values/prototypes/array.hpp"
8
-
9
- inline jspp::JsArray::JsArray() : proto(Constants::Null), length(0) {}
10
- inline jspp::JsArray::JsArray(const std::vector<jspp::AnyValue> &items) : dense(items), proto(Constants::Null), length(items.size()) {}
11
- inline jspp::JsArray::JsArray(std::vector<jspp::AnyValue> &&items) : dense(std::move(items)), proto(Constants::Null), length(dense.size()) {}
12
-
13
- inline std::string jspp::JsArray::to_std_string() const
14
- {
15
- if (length == 0)
16
- {
17
- return "";
18
- }
19
-
20
- std::string result = "";
21
- for (uint64_t i = 0; i < length; ++i)
22
- {
23
- AnyValue itemVal = Constants::UNINITIALIZED;
24
- if (i < dense.size())
25
- {
26
- itemVal = dense[i];
27
- }
28
- else
29
- {
30
- auto it = sparse.find(static_cast<uint32_t>(i));
31
- if (it != sparse.end())
32
- {
33
- itemVal = it->second;
34
- }
35
- }
36
-
37
- if (!itemVal.is_uninitialized())
38
- {
39
- if (!itemVal.is_undefined() && !itemVal.is_null())
40
- {
41
- result += itemVal.to_std_string();
42
- }
43
- }
44
-
45
- if (i < length - 1)
46
- {
47
- result += ",";
48
- }
49
- }
50
- return result;
51
- }
52
-
53
- inline jspp::JsIterator<jspp::AnyValue> jspp::JsArray::get_iterator()
54
- {
55
- for (uint64_t idx = 0; idx < length; ++idx)
56
- {
57
- co_yield get_property(static_cast<uint32_t>(idx));
58
- }
59
-
60
- co_return AnyValue::make_undefined();
61
- }
62
-
63
- inline bool jspp::JsArray::has_property(const std::string &key) const
64
- {
65
- if (key == "length")
66
- return true;
67
- if (is_array_index(key))
68
- {
69
- uint32_t idx = static_cast<uint32_t>(std::stoull(key));
70
- if (idx < dense.size())
71
- return true;
72
- if (sparse.find(idx) != sparse.end())
73
- return true;
74
- }
75
- if (props.find(key) != props.end())
76
- return true;
77
-
78
- if (!proto.is_null() && !proto.is_undefined())
79
- {
80
- if (proto.has_property(key))
81
- return true;
82
- }
83
-
84
- if (ArrayPrototypes::get(key).has_value())
85
- return true;
86
- return false;
87
- }
88
-
89
- inline jspp::AnyValue jspp::JsArray::get_property(const std::string &key, const AnyValue &thisVal)
90
- {
91
- if (
92
- !key.empty() && std::isdigit(static_cast<unsigned char>(key[0]))
93
- && is_array_index(key))
94
- {
95
- uint32_t idx = static_cast<uint32_t>(std::stoull(key));
96
- return get_property(idx);
97
- }
98
- else
99
- {
100
- auto it = props.find(key);
101
- if (it == props.end())
102
- {
103
- if (key == "length")
104
- {
105
- auto proto_it = ArrayPrototypes::get(key);
106
- if (proto_it.has_value())
107
- {
108
- return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
109
- }
110
- }
111
-
112
- if (!proto.is_null() && !proto.is_undefined())
113
- {
114
- if (proto.has_property(key))
115
- {
116
- return proto.get_property_with_receiver(key, thisVal);
117
- }
118
- }
119
-
120
- auto proto_it = ArrayPrototypes::get(key);
121
- if (proto_it.has_value())
122
- {
123
- return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
124
- }
125
- return Constants::UNDEFINED;
126
- }
127
- return AnyValue::resolve_property_for_read(it->second, thisVal, key);
128
- }
129
- }
130
-
131
- inline jspp::AnyValue jspp::JsArray::get_property(uint32_t idx)
132
- {
133
- if (idx < dense.size())
134
- {
135
- const auto &val = dense[idx];
136
- return val.is_uninitialized() ? Constants::UNDEFINED : val;
137
- }
138
- const auto &it = sparse.find(idx);
139
- if (it != sparse.end())
140
- {
141
- const auto &val = it->second;
142
- return val.is_uninitialized() ? Constants::UNDEFINED : val;
143
- }
144
- return Constants::UNDEFINED;
145
- }
146
-
147
- inline jspp::AnyValue jspp::JsArray::set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal)
148
- {
149
- if (
150
- !key.empty() && std::isdigit(static_cast<unsigned char>(key[0]))
151
- && is_array_index(key))
152
- {
153
- uint32_t idx = static_cast<uint32_t>(std::stoull(key));
154
- return set_property(idx, value);
155
- }
156
- else
157
- {
158
- auto proto_val_opt = ArrayPrototypes::get(key);
159
-
160
- if (proto_val_opt.has_value())
161
- {
162
- auto proto_value = proto_val_opt.value();
163
- if (proto_value.is_accessor_descriptor())
164
- {
165
- return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
166
- }
167
- if (proto_value.is_data_descriptor() && !proto_value.as_data_descriptor()->writable)
168
- {
169
- return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
170
- }
171
- }
172
-
173
- auto it = props.find(key);
174
- if (it != props.end())
175
- {
176
- return AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
177
- }
178
- else
179
- {
180
- props[key] = value;
181
- return value;
182
- }
183
- }
184
- }
185
-
186
- inline jspp::AnyValue jspp::JsArray::set_property(uint32_t idx, const AnyValue &value)
187
- {
188
- uint64_t newLen = static_cast<uint64_t>(idx) + 1;
189
- if (newLen > length)
190
- length = newLen;
191
-
192
- const uint32_t DENSE_GROW_THRESHOLD = 1024;
193
- if (idx < dense.size())
194
- {
195
- dense[idx] = value;
196
- return value;
197
- }
198
- else if (idx <= dense.size() + DENSE_GROW_THRESHOLD)
199
- {
200
- dense.resize(idx + 1, Constants::UNINITIALIZED);
201
- dense[idx] = value;
202
- return value;
203
- }
204
- else
205
- {
206
- sparse[idx] = value;
207
- return value;
208
- }
209
- }