@ugo-studio/jspp 0.3.0 → 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 (95) 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/control-flow-handlers.js +10 -9
  8. package/dist/core/codegen/declaration-handlers.js +10 -3
  9. package/dist/core/codegen/destructuring-handlers.js +9 -4
  10. package/dist/core/codegen/expression-handlers.js +40 -29
  11. package/dist/core/codegen/function-handlers.js +78 -12
  12. package/dist/core/codegen/helpers.js +91 -14
  13. package/dist/core/codegen/index.js +4 -2
  14. package/dist/core/codegen/statement-handlers.js +8 -6
  15. package/package.json +2 -2
  16. package/scripts/precompile-headers.ts +249 -50
  17. package/scripts/setup-compiler.ts +63 -63
  18. package/src/prelude/any_value.cpp +636 -0
  19. package/src/prelude/any_value.hpp +23 -16
  20. package/src/prelude/{exception_helpers.hpp → exception.cpp} +53 -53
  21. package/src/prelude/exception.hpp +27 -27
  22. package/src/prelude/iterator_instantiations.hpp +10 -0
  23. package/src/prelude/{index.hpp → jspp.hpp} +10 -16
  24. package/src/prelude/library/array.cpp +191 -0
  25. package/src/prelude/library/array.hpp +5 -178
  26. package/src/prelude/library/console.cpp +125 -0
  27. package/src/prelude/library/console.hpp +9 -97
  28. package/src/prelude/library/error.cpp +100 -0
  29. package/src/prelude/library/error.hpp +8 -108
  30. package/src/prelude/library/function.cpp +69 -0
  31. package/src/prelude/library/function.hpp +6 -5
  32. package/src/prelude/library/global.cpp +96 -0
  33. package/src/prelude/library/global.hpp +12 -28
  34. package/src/prelude/library/global_usings.hpp +15 -0
  35. package/src/prelude/library/math.cpp +258 -0
  36. package/src/prelude/library/math.hpp +6 -288
  37. package/src/prelude/library/object.cpp +379 -0
  38. package/src/prelude/library/object.hpp +5 -267
  39. package/src/prelude/library/performance.cpp +21 -0
  40. package/src/prelude/library/performance.hpp +5 -20
  41. package/src/prelude/library/process.cpp +38 -0
  42. package/src/prelude/library/process.hpp +3 -31
  43. package/src/prelude/library/promise.cpp +131 -0
  44. package/src/prelude/library/promise.hpp +5 -116
  45. package/src/prelude/library/symbol.cpp +56 -0
  46. package/src/prelude/library/symbol.hpp +5 -46
  47. package/src/prelude/library/timer.cpp +88 -0
  48. package/src/prelude/library/timer.hpp +11 -87
  49. package/src/prelude/runtime.cpp +19 -0
  50. package/src/prelude/types.hpp +17 -12
  51. package/src/prelude/utils/access.hpp +122 -31
  52. package/src/prelude/utils/assignment_operators.hpp +99 -99
  53. package/src/prelude/utils/log_any_value/array.hpp +61 -40
  54. package/src/prelude/utils/log_any_value/function.hpp +39 -39
  55. package/src/prelude/utils/log_any_value/object.hpp +60 -3
  56. package/src/prelude/utils/operators.hpp +25 -10
  57. package/src/prelude/utils/operators_primitive.hpp +336 -336
  58. package/src/prelude/utils/well_known_symbols.hpp +24 -24
  59. package/src/prelude/values/array.cpp +1399 -0
  60. package/src/prelude/values/array.hpp +4 -0
  61. package/src/prelude/values/async_iterator.cpp +251 -0
  62. package/src/prelude/values/async_iterator.hpp +60 -32
  63. package/src/prelude/values/function.cpp +262 -0
  64. package/src/prelude/values/function.hpp +10 -30
  65. package/src/prelude/values/iterator.cpp +309 -0
  66. package/src/prelude/values/iterator.hpp +33 -64
  67. package/src/prelude/values/number.cpp +176 -0
  68. package/src/prelude/values/object.cpp +159 -0
  69. package/src/prelude/values/object.hpp +4 -0
  70. package/src/prelude/values/promise.cpp +479 -0
  71. package/src/prelude/values/promise.hpp +9 -2
  72. package/src/prelude/values/prototypes/array.hpp +46 -1348
  73. package/src/prelude/values/prototypes/async_iterator.hpp +19 -61
  74. package/src/prelude/values/prototypes/function.hpp +7 -46
  75. package/src/prelude/values/prototypes/iterator.hpp +15 -191
  76. package/src/prelude/values/prototypes/number.hpp +23 -210
  77. package/src/prelude/values/prototypes/object.hpp +7 -23
  78. package/src/prelude/values/prototypes/promise.hpp +8 -186
  79. package/src/prelude/values/prototypes/string.hpp +28 -553
  80. package/src/prelude/values/prototypes/symbol.hpp +9 -70
  81. package/src/prelude/values/shape.hpp +52 -52
  82. package/src/prelude/values/string.cpp +485 -0
  83. package/src/prelude/values/symbol.cpp +89 -0
  84. package/src/prelude/values/symbol.hpp +101 -101
  85. package/src/prelude/any_value_access.hpp +0 -170
  86. package/src/prelude/any_value_defines.hpp +0 -190
  87. package/src/prelude/any_value_helpers.hpp +0 -374
  88. package/src/prelude/values/helpers/array.hpp +0 -199
  89. package/src/prelude/values/helpers/async_iterator.hpp +0 -275
  90. package/src/prelude/values/helpers/function.hpp +0 -109
  91. package/src/prelude/values/helpers/iterator.hpp +0 -145
  92. package/src/prelude/values/helpers/object.hpp +0 -104
  93. package/src/prelude/values/helpers/promise.hpp +0 -254
  94. package/src/prelude/values/helpers/string.hpp +0 -37
  95. package/src/prelude/values/helpers/symbol.hpp +0 -21
@@ -185,14 +185,9 @@ namespace jspp
185
185
  static AnyValue make_string(const std::string &raw_s) noexcept;
186
186
  static AnyValue make_object(std::initializer_list<std::pair<std::string, AnyValue>> props) noexcept;
187
187
  static AnyValue make_object(const std::map<std::string, AnyValue> &props) noexcept;
188
- static AnyValue make_object_with_proto(std::initializer_list<std::pair<std::string, AnyValue>> props, AnyValue proto) noexcept;
189
- static AnyValue make_object_with_proto(const std::map<std::string, AnyValue> &props, AnyValue proto) noexcept;
190
188
  static AnyValue make_array(std::span<const AnyValue> dense) noexcept;
191
189
  static AnyValue make_array(const std::vector<AnyValue> &dense) noexcept;
192
190
  static AnyValue make_array(std::vector<AnyValue> &&dense) noexcept;
193
- static AnyValue make_array_with_proto(std::span<const AnyValue> dense, AnyValue proto) noexcept;
194
- static AnyValue make_array_with_proto(const std::vector<AnyValue> &dense, AnyValue proto) noexcept;
195
- static AnyValue make_array_with_proto(std::vector<AnyValue> &&dense, AnyValue proto) noexcept;
196
191
  static AnyValue make_function(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt, bool is_constructor = true) noexcept;
197
192
  static AnyValue make_class(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept;
198
193
  static AnyValue make_generator(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept;
@@ -287,22 +282,27 @@ namespace jspp
287
282
  auto operator co_await() const;
288
283
 
289
284
  bool has_property(const std::string &key) const;
285
+ bool has_property(const AnyValue &key) const;
290
286
  bool has_property(const char *key) const { return has_property(std::string(key)); }
291
287
 
292
288
  AnyValue get_own_property(const std::string &key) const;
289
+ AnyValue get_own_property_descriptor(const AnyValue &key) const;
293
290
  AnyValue get_own_property(const char *key) const { return get_own_property(std::string(key)); }
294
291
  AnyValue get_own_property(uint32_t idx) const;
295
292
  AnyValue get_own_property(int idx) const { return get_own_property(static_cast<uint32_t>(idx)); }
296
293
  AnyValue get_own_property(const AnyValue &key) const;
294
+ AnyValue get_own_symbol_property(const AnyValue &key) const;
297
295
 
298
296
  AnyValue get_property_with_receiver(const std::string &key, AnyValue receiver) const;
299
297
  AnyValue get_property_with_receiver(const char *key, AnyValue receiver) const { return get_property_with_receiver(std::string(key), receiver); }
298
+ AnyValue get_symbol_property_with_receiver(const AnyValue &key, AnyValue receiver) const;
300
299
 
301
300
  AnyValue set_own_property(const std::string &key, AnyValue value) const;
302
301
  AnyValue set_own_property(const char *key, AnyValue value) const { return set_own_property(std::string(key), value); }
303
302
  AnyValue set_own_property(uint32_t idx, AnyValue value) const;
304
303
  AnyValue set_own_property(int idx, AnyValue value) const { return set_own_property(static_cast<uint32_t>(idx), value); }
305
304
  AnyValue set_own_property(const AnyValue &key, AnyValue value) const;
305
+ AnyValue set_own_symbol_property(const AnyValue &key, AnyValue value) const;
306
306
 
307
307
  AnyValue call_own_property(const std::string &key, std::span<const AnyValue> args) const;
308
308
  AnyValue call_own_property(const char *key, std::span<const AnyValue> args) const { return call_own_property(std::string(key), args); }
@@ -313,6 +313,7 @@ namespace jspp
313
313
  void define_data_property(const std::string &key, AnyValue value);
314
314
  void define_data_property(const char *key, AnyValue value) { define_data_property(std::string(key), value); }
315
315
  void define_data_property(const AnyValue &key, AnyValue value);
316
+ void define_data_property(const AnyValue &key, AnyValue value, bool writable, bool enumerable, bool configurable);
316
317
  void define_data_property(const std::string &key, AnyValue value, bool writable, bool enumerable, bool configurable);
317
318
  void define_data_property(const char *key, AnyValue value, bool writable, bool enumerable, bool configurable) { define_data_property(std::string(key), value, writable, enumerable, configurable); }
318
319
 
@@ -327,30 +328,36 @@ namespace jspp
327
328
  AnyValue call(AnyValue thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr = std::nullopt) const;
328
329
  AnyValue optional_call(AnyValue thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr = std::nullopt) const;
329
330
  AnyValue construct(std::span<const AnyValue> args, const std::optional<std::string> &name = std::nullopt) const;
330
- void set_prototype(AnyValue proto);
331
+ AnyValue &set_prototype(AnyValue proto);
331
332
  std::string to_std_string() const;
332
333
  std::string to_property_key() const;
333
334
 
334
335
  inline uint64_t get_storage() const noexcept { return storage; }
335
336
  inline void *get_raw_ptr() const noexcept { return reinterpret_cast<void *>(storage & PAYLOAD_MASK); }
336
- };
337
337
 
338
- struct AnyValueAwaiter
339
- {
338
+ bool operator==(const AnyValue &other) const noexcept;
339
+ bool operator==(const std::string &other) const noexcept;
340
+ bool operator<(const AnyValue &other) const noexcept;
341
+ };
342
+
343
+ struct AnyValueAwaiter
344
+ {
340
345
  AnyValue value;
341
346
  bool await_ready();
342
347
  void await_suspend(std::coroutine_handle<> h);
343
348
  AnyValue await_resume();
344
- };
349
+ };
345
350
 
346
- inline auto AnyValue::operator co_await() const
347
- {
351
+ inline auto AnyValue::operator co_await() const
352
+ {
348
353
  return AnyValueAwaiter{*this};
349
- }
354
+ }
355
+ }
350
356
 
351
- namespace Constants
352
- {
353
- inline const AnyValue UNINITIALIZED = AnyValue::make_uninitialized();
357
+ namespace jspp
358
+ {
359
+ namespace Constants
360
+ { inline const AnyValue UNINITIALIZED = AnyValue::make_uninitialized();
354
361
  inline const AnyValue UNDEFINED = AnyValue::make_undefined();
355
362
  inline const AnyValue Null = AnyValue::make_null();
356
363
  inline const AnyValue NaN = AnyValue::make_nan();
@@ -1,53 +1,53 @@
1
- #pragma once
2
-
3
- #include "types.hpp"
4
- #include "exception.hpp"
5
- #include "any_value.hpp"
6
-
7
- const char *jspp::Exception::what() const noexcept
8
- {
9
- // Note: this returns a pointer to a temporary string if we are not careful.
10
- // In a real implementation, we might need to store the message string in the Exception object.
11
- static thread_local std::string last_msg;
12
- last_msg = data.to_std_string();
13
- return last_msg.c_str();
14
- }
15
-
16
- jspp::Exception jspp::Exception::make_exception(const std::string &message, const std::string &name)
17
- {
18
- // Use the global Error object to construct the exception
19
- std::vector<AnyValue> args = {AnyValue::make_string(message)};
20
- AnyValue errorObj = ::Error.construct(args, name);
21
- errorObj.define_data_property("name", AnyValue::make_string(name), true, false, true);
22
-
23
- return Exception(errorObj);
24
- }
25
- jspp::AnyValue jspp::Exception::exception_to_any_value(const std::exception &ex)
26
- {
27
- if (const jspp::Exception *err = dynamic_cast<const jspp::Exception *>(&ex))
28
- {
29
- return err->data;
30
- }
31
- else
32
- {
33
- return AnyValue::make_string(ex.what());
34
- }
35
- }
36
-
37
- // --- THROWERS
38
- jspp::AnyValue jspp::Exception::throw_unresolved_reference(const std::string &var_name)
39
- {
40
- throw Exception::make_exception(var_name + " is not defined", "ReferenceError");
41
- }
42
- jspp::AnyValue jspp::Exception::throw_uninitialized_reference(const std::string &var_name)
43
- {
44
- throw Exception::make_exception("Cannot access '" + var_name + "' before initialization", "ReferenceError");
45
- }
46
- jspp::AnyValue jspp::Exception::throw_immutable_assignment()
47
- {
48
- throw Exception::make_exception("Assignment to constant variable.", "TypeError");
49
- }
50
- jspp::AnyValue jspp::Exception::throw_invalid_return_statement()
51
- {
52
- throw Exception::make_exception("Return statements are only valid inside functions.", "SyntaxError");
53
- }
1
+ #include "jspp.hpp"
2
+ #include "exception.hpp"
3
+ #include "any_value.hpp"
4
+
5
+ namespace jspp {
6
+
7
+ const char *Exception::what() const noexcept
8
+ {
9
+ static thread_local std::string last_msg;
10
+ last_msg = data.to_std_string();
11
+ return last_msg.c_str();
12
+ }
13
+
14
+ Exception Exception::make_exception(const std::string &message, const std::string &name)
15
+ {
16
+ std::vector<AnyValue> args = {AnyValue::make_string(message)};
17
+ AnyValue errorObj = ::Error.construct(args, name);
18
+ errorObj.define_data_property("name", AnyValue::make_string(name), true, false, true);
19
+
20
+ return Exception(errorObj);
21
+ }
22
+
23
+ AnyValue Exception::exception_to_any_value(const std::exception &ex)
24
+ {
25
+ if (const jspp::Exception *err = dynamic_cast<const jspp::Exception *>(&ex))
26
+ {
27
+ return err->data;
28
+ }
29
+ else
30
+ {
31
+ return AnyValue::make_string(ex.what());
32
+ }
33
+ }
34
+
35
+ // --- THROWERS
36
+ AnyValue Exception::throw_unresolved_reference(const std::string &var_name)
37
+ {
38
+ throw Exception::make_exception(var_name + " is not defined", "ReferenceError");
39
+ }
40
+ AnyValue Exception::throw_uninitialized_reference(const std::string &var_name)
41
+ {
42
+ throw Exception::make_exception("Cannot access '" + var_name + "' before initialization", "ReferenceError");
43
+ }
44
+ AnyValue Exception::throw_immutable_assignment()
45
+ {
46
+ throw Exception::make_exception("Assignment to constant variable.", "TypeError");
47
+ }
48
+ AnyValue Exception::throw_invalid_return_statement()
49
+ {
50
+ throw Exception::make_exception("Return statements are only valid inside functions.", "SyntaxError");
51
+ }
52
+
53
+ } // namespace jspp
@@ -1,28 +1,28 @@
1
- #pragma once
2
-
3
- #include <exception>
4
- #include "types.hpp"
5
- #include "any_value.hpp"
6
-
7
- namespace jspp
8
- {
9
- struct Exception : std::exception
10
- {
11
- AnyValue data;
12
-
13
- explicit Exception(const AnyValue &value)
14
- : data(value) {}
15
- explicit Exception(AnyValue &&value)
16
- : data(std::move(value)) {}
17
-
18
- const char *what() const noexcept override;
19
- static Exception make_exception(const std::string &message, const std::string &name);
20
- static AnyValue exception_to_any_value(const std::exception &ex);
21
-
22
- // --- THROWERS
23
- static AnyValue throw_unresolved_reference(const std::string &var_name);
24
- static AnyValue throw_uninitialized_reference(const std::string &var_name);
25
- static AnyValue throw_immutable_assignment();
26
- static AnyValue throw_invalid_return_statement();
27
- };
1
+ #pragma once
2
+
3
+ #include <exception>
4
+ #include "types.hpp"
5
+ #include "any_value.hpp"
6
+
7
+ namespace jspp
8
+ {
9
+ struct Exception : std::exception
10
+ {
11
+ AnyValue data;
12
+
13
+ explicit Exception(const AnyValue &value)
14
+ : data(value) {}
15
+ explicit Exception(AnyValue &&value)
16
+ : data(std::move(value)) {}
17
+
18
+ const char *what() const noexcept override;
19
+ static Exception make_exception(const std::string &message, const std::string &name);
20
+ static AnyValue exception_to_any_value(const std::exception &ex);
21
+
22
+ // --- THROWERS
23
+ static AnyValue throw_unresolved_reference(const std::string &var_name);
24
+ static AnyValue throw_uninitialized_reference(const std::string &var_name);
25
+ static AnyValue throw_immutable_assignment();
26
+ static AnyValue throw_invalid_return_statement();
27
+ };
28
28
  }
@@ -0,0 +1,10 @@
1
+ #pragma once
2
+ #include "values/iterator.hpp"
3
+ #include "values/async_iterator.hpp"
4
+
5
+ namespace jspp {
6
+ // Explicit template instantiation declarations
7
+ // This tells the compiler that the implementation is in libjspp.a
8
+ extern template class JsIterator<AnyValue>;
9
+ extern template class JsAsyncIterator<AnyValue>;
10
+ }
@@ -1,4 +1,5 @@
1
- #pragma once
1
+ #ifndef JSPP_PRELUDE_JSPP_HPP
2
+ #define JSPP_PRELUDE_JSPP_HPP
2
3
 
3
4
  #include "types.hpp"
4
5
  #include "utils/well_known_symbols.hpp"
@@ -7,21 +8,19 @@
7
8
  #include "values/shape.hpp"
8
9
  #include "values/symbol.hpp"
9
10
  #include "values/non_values.hpp"
11
+ #include "values/string.hpp"
12
+
13
+ #include "any_value.hpp" // Must be before iterators for AnyValueAwaiter
10
14
  #include "values/iterator.hpp"
11
15
  #include "values/async_iterator.hpp"
12
- #include "values/string.hpp"
13
16
 
14
- #include "any_value.hpp"
15
17
  #include "values/object.hpp"
16
18
  #include "values/array.hpp"
17
19
  #include "values/function.hpp"
18
20
  #include "values/promise.hpp"
19
21
  #include "values/descriptors.hpp"
20
- #include "any_value_helpers.hpp"
21
- #include "any_value_access.hpp"
22
- #include "any_value_defines.hpp"
22
+ #include "exception.hpp"
23
23
  #include "library/error.hpp"
24
- #include "exception_helpers.hpp"
25
24
  #include "scheduler.hpp"
26
25
 
27
26
  #include "values/prototypes/symbol.hpp"
@@ -34,15 +33,6 @@
34
33
  #include "values/prototypes/string.hpp"
35
34
  #include "values/prototypes/number.hpp"
36
35
 
37
- #include "values/helpers/symbol.hpp"
38
- #include "values/helpers/object.hpp"
39
- #include "values/helpers/array.hpp"
40
- #include "values/helpers/function.hpp"
41
- #include "values/helpers/iterator.hpp"
42
- #include "values/helpers/async_iterator.hpp"
43
- #include "values/helpers/promise.hpp"
44
- #include "values/helpers/string.hpp"
45
-
46
36
  // utilities
47
37
  #include "utils/operators_primitive.hpp"
48
38
  #include "utils/operators.hpp"
@@ -61,3 +51,7 @@
61
51
  #include "library/object.hpp"
62
52
  #include "library/array.hpp"
63
53
  #include "library/global.hpp"
54
+
55
+ #include "iterator_instantiations.hpp"
56
+
57
+ #endif // JSPP_PRELUDE_JSPP_HPP
@@ -0,0 +1,191 @@
1
+ #include "jspp.hpp"
2
+ #include "library/array.hpp"
3
+
4
+ namespace jspp {
5
+ jspp::AnyValue Array = jspp::AnyValue::make_class(
6
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
7
+ {
8
+ if (args.size() == 1 && args[0].is_number()) {
9
+ double len = args[0].as_double();
10
+ if (len < 0 || len > 4294967295.0) { // Max uint32
11
+ throw jspp::Exception::make_exception("Invalid array length", "RangeError");
12
+ }
13
+ auto arr = jspp::AnyValue::make_array(std::vector<jspp::AnyValue>());
14
+ auto arr_ptr = arr.as_array();
15
+ arr_ptr->length = static_cast<uint64_t>(len);
16
+ arr_ptr->dense.resize(static_cast<size_t>(len), jspp::Constants::UNINITIALIZED);
17
+ return arr;
18
+ }
19
+ std::vector<jspp::AnyValue> elements;
20
+ for(const auto& arg : args) {
21
+ elements.push_back(arg);
22
+ }
23
+ return jspp::AnyValue::make_array(std::move(elements));
24
+ }), "Array");
25
+
26
+ struct ArrayInit
27
+ {
28
+ ArrayInit()
29
+ {
30
+ Array.define_data_property("isArray", jspp::AnyValue::make_function(
31
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>([](jspp::AnyValue, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
32
+ {
33
+ if (args.empty()) return jspp::Constants::FALSE;
34
+ return jspp::AnyValue::make_boolean(args[0].is_array());
35
+ }), "isArray"));
36
+
37
+ Array.define_data_property("of", jspp::AnyValue::make_function(
38
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>([](jspp::AnyValue, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
39
+ {
40
+ std::vector<jspp::AnyValue> elements;
41
+ for(const auto& arg : args) {
42
+ elements.push_back(arg);
43
+ }
44
+ return jspp::AnyValue::make_array(std::move(elements));
45
+ }), "of"));
46
+
47
+ Array.define_data_property("from", jspp::AnyValue::make_function(
48
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>([](jspp::AnyValue, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
49
+ {
50
+ if (args.empty() || args[0].is_null() || args[0].is_undefined()) {
51
+ throw jspp::Exception::make_exception("Array.from requires an array-like object", "TypeError");
52
+ }
53
+
54
+ const auto& items = args[0];
55
+ const auto& mapFn = (args.size() > 1 && args[1].is_function()) ? args[1] : jspp::Constants::UNDEFINED;
56
+ const auto& thisArg = (args.size() > 2) ? args[2] : jspp::Constants::UNDEFINED;
57
+
58
+ std::vector<jspp::AnyValue> result;
59
+
60
+ auto iteratorSym = jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::iterator);
61
+ if (items.has_property(iteratorSym)) {
62
+ auto iter = jspp::Access::get_object_iterator(items, "Array.from source");
63
+ auto nextFn = iter.get_own_property("next");
64
+
65
+ size_t k = 0;
66
+ while (true) {
67
+ auto nextRes = nextFn.call(iter, std::span<const jspp::AnyValue>{}, "next");
68
+ if (jspp::is_truthy(nextRes.get_own_property("done"))) break;
69
+
70
+ auto val = nextRes.get_own_property("value");
71
+ if (mapFn.is_function()) {
72
+ jspp::AnyValue kVal = jspp::AnyValue::make_number(k);
73
+ const jspp::AnyValue mapArgs[] = {val, kVal};
74
+ val = mapFn.call(thisArg, std::span<const jspp::AnyValue>(mapArgs, 2));
75
+ }
76
+ result.push_back(val);
77
+ k++;
78
+ }
79
+ } else {
80
+ auto lenVal = items.get_property_with_receiver("length", items);
81
+ size_t len = static_cast<size_t>(jspp::Operators_Private::ToUint32(lenVal));
82
+
83
+ for (size_t k = 0; k < len; ++k) {
84
+ auto kVal = items.get_property_with_receiver(std::to_string(k), items);
85
+ if (mapFn.is_function()) {
86
+ jspp::AnyValue kNum = jspp::AnyValue::make_number(k);
87
+ const jspp::AnyValue mapArgs[] = {kVal, kNum};
88
+ kVal = mapFn.call(thisArg, std::span<const jspp::AnyValue>(mapArgs, 2));
89
+ }
90
+ result.push_back(kVal);
91
+ }
92
+ }
93
+
94
+ return jspp::AnyValue::make_array(std::move(result));
95
+ }), "from"));
96
+
97
+ Array.define_data_property("fromAsync", jspp::AnyValue::make_async_function(
98
+ std::function<JsPromise(AnyValue, std::vector<AnyValue>)>([](jspp::AnyValue, std::vector<jspp::AnyValue> args) -> jspp::JsPromise
99
+ {
100
+ if (args.empty() || args[0].is_null() || args[0].is_undefined()) {
101
+ throw jspp::Exception::make_exception("Array.fromAsync requires an iterable or array-like object", "TypeError");
102
+ }
103
+
104
+ const auto& items = args[0];
105
+ const auto& mapFn = (args.size() > 1 && args[1].is_function()) ? args[1] : jspp::Constants::UNDEFINED;
106
+ const auto& thisArg = (args.size() > 2) ? args[2] : jspp::Constants::UNDEFINED;
107
+
108
+ std::vector<jspp::AnyValue> result;
109
+ bool isAsync = false;
110
+ jspp::AnyValue iter = jspp::Constants::UNDEFINED;
111
+ jspp::AnyValue nextFn = jspp::Constants::UNDEFINED;
112
+
113
+ auto asyncIterSym = jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::asyncIterator);
114
+ if (items.has_property(asyncIterSym)) {
115
+ auto method = items.get_own_property(asyncIterSym);
116
+ if (method.is_function()) {
117
+ iter = method.call(items, {});
118
+ nextFn = iter.get_own_property("next");
119
+ isAsync = true;
120
+ }
121
+ }
122
+
123
+ auto iterSym = jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::iterator);
124
+ if (!isAsync && items.has_property(iterSym)) {
125
+ auto method = items.get_own_property(iterSym);
126
+ if (method.is_function()) {
127
+ iter = method.call(items, {});
128
+ nextFn = iter.get_own_property("next");
129
+ }
130
+ }
131
+
132
+ if (!iter.is_undefined()) {
133
+ size_t k = 0;
134
+ while (true) {
135
+ auto nextRes = nextFn.call(iter, {});
136
+ if (nextRes.is_promise()) {
137
+ nextRes = co_await nextRes;
138
+ }
139
+ if (jspp::is_truthy(nextRes.get_own_property("done"))) break;
140
+ auto val = nextRes.get_own_property("value");
141
+ if (mapFn.is_function()) {
142
+ jspp::AnyValue kVal = jspp::AnyValue::make_number(k);
143
+ const jspp::AnyValue mapArgs[] = {val, kVal};
144
+ auto mapRes = mapFn.call(thisArg, std::span<const jspp::AnyValue>(mapArgs, 2));
145
+ if (mapRes.is_promise()) val = co_await mapRes; else val = mapRes;
146
+ }
147
+ result.push_back(val);
148
+ k++;
149
+ }
150
+ } else {
151
+ auto lenVal = items.get_property_with_receiver("length", items);
152
+ size_t len = static_cast<size_t>(jspp::Operators_Private::ToUint32(lenVal));
153
+ for (size_t k = 0; k < len; ++k) {
154
+ auto kVal = items.get_property_with_receiver(std::to_string(k), items);
155
+ if (kVal.is_promise()) kVal = co_await kVal;
156
+ if (mapFn.is_function()) {
157
+ jspp::AnyValue kNum = jspp::AnyValue::make_number(k);
158
+ const jspp::AnyValue mapArgs[] = {kVal, kNum};
159
+ auto mapRes = mapFn.call(thisArg, std::span<const jspp::AnyValue>(mapArgs, 2));
160
+ if (mapRes.is_promise()) kVal = co_await mapRes; else kVal = mapRes;
161
+ }
162
+ result.push_back(kVal);
163
+ }
164
+ }
165
+ co_return jspp::AnyValue::make_array(std::move(result));
166
+ }), "fromAsync"));
167
+
168
+ // Array[Symbol.species]
169
+ Array.define_getter(jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::species), jspp::AnyValue::make_function([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
170
+ { return thisVal; }, "get [Symbol.species]"));
171
+
172
+ auto proto = Array.get_own_property("prototype");
173
+ const char *methods[] = {"push", "pop", "shift", "unshift", "join", "forEach", "map", "filter", "slice", "splice", "concat", "indexOf", "lastIndexOf", "includes", "every", "some", "reduce", "reduceRight", "flat", "flatMap", "fill", "reverse", "sort", "at", "values", "keys", "entries", "toString", "toLocaleString"};
174
+ for (const char *m : methods)
175
+ {
176
+ auto method_fn = jspp::ArrayPrototypes::get(m);
177
+ if (method_fn.has_value())
178
+ {
179
+ proto.define_data_property(m, method_fn.value(), true, false, true);
180
+ }
181
+ }
182
+
183
+ auto iteratorSym = jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::iterator);
184
+ proto.define_data_property(iteratorSym, jspp::ArrayPrototypes::get(iteratorSym).value(), true, false, true);
185
+ }
186
+ };
187
+ void init_array()
188
+ {
189
+ static ArrayInit arrayInit;
190
+ }
191
+ }