@ugo-studio/jspp 0.1.8 → 0.2.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 (50) hide show
  1. package/README.md +1 -1
  2. package/dist/cli-utils/args.js +2 -0
  3. package/dist/cli.js +1 -1
  4. package/package.json +3 -2
  5. package/scripts/precompile-headers.ts +110 -0
  6. package/scripts/setup-compiler.ts +63 -0
  7. package/src/prelude/any_value.hpp +185 -391
  8. package/src/prelude/any_value_access.hpp +170 -190
  9. package/src/prelude/any_value_defines.hpp +12 -12
  10. package/src/prelude/any_value_helpers.hpp +208 -26
  11. package/src/prelude/exception.hpp +27 -31
  12. package/src/prelude/exception_helpers.hpp +53 -49
  13. package/src/prelude/index.hpp +9 -4
  14. package/src/prelude/library/array.hpp +4 -9
  15. package/src/prelude/library/console.hpp +112 -112
  16. package/src/prelude/library/error.hpp +8 -8
  17. package/src/prelude/library/math.hpp +3 -3
  18. package/src/prelude/library/object.hpp +12 -24
  19. package/src/prelude/library/promise.hpp +1 -1
  20. package/src/prelude/library/symbol.hpp +1 -1
  21. package/src/prelude/library/timer.hpp +3 -3
  22. package/src/prelude/types.hpp +178 -130
  23. package/src/prelude/utils/access.hpp +338 -378
  24. package/src/prelude/utils/log_any_value/function.hpp +39 -39
  25. package/src/prelude/utils/log_any_value/log_any_value.hpp +1 -1
  26. package/src/prelude/utils/operators.hpp +20 -82
  27. package/src/prelude/utils/well_known_symbols.hpp +14 -15
  28. package/src/prelude/values/array.hpp +5 -3
  29. package/src/prelude/values/async_iterator.hpp +3 -1
  30. package/src/prelude/values/descriptors.hpp +15 -3
  31. package/src/prelude/values/function.hpp +5 -9
  32. package/src/prelude/values/helpers/array.hpp +208 -219
  33. package/src/prelude/values/helpers/async_iterator.hpp +7 -11
  34. package/src/prelude/values/helpers/function.hpp +12 -17
  35. package/src/prelude/values/helpers/iterator.hpp +108 -107
  36. package/src/prelude/values/helpers/object.hpp +104 -109
  37. package/src/prelude/values/helpers/promise.hpp +185 -119
  38. package/src/prelude/values/helpers/string.hpp +7 -10
  39. package/src/prelude/values/helpers/symbol.hpp +21 -23
  40. package/src/prelude/values/iterator.hpp +4 -1
  41. package/src/prelude/values/object.hpp +6 -4
  42. package/src/prelude/values/promise.hpp +5 -2
  43. package/src/prelude/values/prototypes/array.hpp +22 -22
  44. package/src/prelude/values/prototypes/async_iterator.hpp +3 -10
  45. package/src/prelude/values/prototypes/iterator.hpp +51 -58
  46. package/src/prelude/values/prototypes/promise.hpp +32 -28
  47. package/src/prelude/values/prototypes/string.hpp +5 -5
  48. package/src/prelude/values/prototypes/symbol.hpp +1 -1
  49. package/src/prelude/values/string.hpp +3 -1
  50. package/src/prelude/values/symbol.hpp +101 -102
@@ -1,39 +1,39 @@
1
- #pragma once
2
- #include "types.hpp"
3
- #include "any_value.hpp"
4
- #include "utils/log_any_value/config.hpp"
5
- #include <string>
6
-
7
- namespace jspp
8
- {
9
- namespace LogAnyValue
10
- {
11
- inline std::string format_function(const AnyValue &val)
12
- {
13
- auto fn = val.as_function();
14
-
15
- if (fn->is_class)
16
- {
17
- std::string extends_part = "";
18
- if (fn->proto && !fn->proto->is_uninitialized() && !fn->proto->is_undefined() && !fn->proto->is_null())
19
- {
20
- if (fn->proto->is_function())
21
- {
22
- auto parent = fn->proto->as_function();
23
- std::string name = parent->name.value_or("");
24
- if (!name.empty())
25
- {
26
- extends_part = " extends " + name;
27
- }
28
- }
29
- }
30
- std::string name = fn->name.value_or("");
31
- return Color::CYAN + std::string("[class ") + (name.empty() ? "(anonymous)" : name) + extends_part + "]" + Color::RESET;
32
- }
33
-
34
- auto type_part = fn->is_generator ? "GeneratorFunction" : "Function";
35
- auto name_part = fn->name.has_value() ? ": " + fn->name.value() : " (anonymous)";
36
- return Color::CYAN + "[" + type_part + name_part + "]" + Color::RESET;
37
- }
38
- }
39
- }
1
+ #pragma once
2
+ #include "types.hpp"
3
+ #include "any_value.hpp"
4
+ #include "utils/log_any_value/config.hpp"
5
+ #include <string>
6
+
7
+ namespace jspp
8
+ {
9
+ namespace LogAnyValue
10
+ {
11
+ inline std::string format_function(const AnyValue &val)
12
+ {
13
+ auto fn = val.as_function();
14
+
15
+ if (fn->is_class)
16
+ {
17
+ std::string extends_part = "";
18
+ if (!fn->proto.is_uninitialized() && !fn->proto.is_undefined() && !fn->proto.is_null())
19
+ {
20
+ if (fn->proto.is_function())
21
+ {
22
+ auto parent = fn->proto.as_function();
23
+ std::string name = parent->name.value_or("");
24
+ if (!name.empty())
25
+ {
26
+ extends_part = " extends " + name;
27
+ }
28
+ }
29
+ }
30
+ std::string name = fn->name.value_or("");
31
+ return Color::CYAN + std::string("[class ") + (name.empty() ? "(anonymous)" : name) + extends_part + "]" + Color::RESET;
32
+ }
33
+
34
+ auto type_part = fn->is_generator ? "GeneratorFunction" : "Function";
35
+ auto name_part = fn->name.has_value() ? ": " + fn->name.value() : " (anonymous)";
36
+ return Color::CYAN + "[" + type_part + name_part + "]" + Color::RESET;
37
+ }
38
+ }
39
+ }
@@ -78,7 +78,7 @@ namespace jspp
78
78
  auto desc = val.as_data_descriptor();
79
79
  if (desc->enumerable)
80
80
  {
81
- return to_log_string((*desc->value), visited, depth);
81
+ return to_log_string(desc->value, visited, depth);
82
82
  }
83
83
  else
84
84
  {
@@ -30,15 +30,14 @@ namespace jspp
30
30
  case JsType::String:
31
31
  {
32
32
  const std::string &s = val.as_string()->value;
33
- // JS considers empty or whitespace-only strings as 0.
34
- if (s.empty() || std::all_of(s.begin(), s.end(), isspace))
33
+ if (s.empty() || std::all_of(s.begin(), s.end(), [](unsigned char c)
34
+ { return std::isspace(c); }))
35
35
  return 0.0;
36
36
  try
37
37
  {
38
38
  size_t pos;
39
39
  double num = std::stod(s, &pos);
40
- // Ensure the entire string was parsed, allowing for trailing whitespace.
41
- while (pos < s.length() && std::isspace(s[pos]))
40
+ while (pos < s.length() && std::isspace(static_cast<unsigned char>(s[pos])))
42
41
  pos++;
43
42
  if (pos != s.length())
44
43
  return std::numeric_limits<double>::quiet_NaN();
@@ -50,8 +49,6 @@ namespace jspp
50
49
  }
51
50
  }
52
51
  default:
53
- // In a full engine, objects would be converted via valueOf/toString.
54
- // Here we simplify and return NaN.
55
52
  return std::numeric_limits<double>::quiet_NaN();
56
53
  }
57
54
  }
@@ -84,15 +81,15 @@ namespace jspp
84
81
  }
85
82
 
86
83
  // --- TRUTHY CHECKER ---
87
- const bool is_truthy(const double &val) noexcept
84
+ inline const bool is_truthy(const double &val) noexcept
88
85
  {
89
86
  return val != 0.0 && !std::isnan(val);
90
87
  }
91
- const bool is_truthy(const std::string &val) noexcept
88
+ inline const bool is_truthy(const std::string &val) noexcept
92
89
  {
93
90
  return !val.empty();
94
91
  }
95
- const bool is_truthy(const AnyValue &val) noexcept
92
+ inline const bool is_truthy(const AnyValue &val) noexcept
96
93
  {
97
94
  switch (val.get_type())
98
95
  {
@@ -118,7 +115,9 @@ namespace jspp
118
115
  // Operator === (returns primitive boolean)
119
116
  inline const bool is_strictly_equal_to_primitive(const AnyValue &lhs, const double &rhs) noexcept
120
117
  {
121
- return is_strictly_equal_to_primitive(rhs, lhs);
118
+ if (lhs.is_number())
119
+ return lhs.as_double() == rhs;
120
+ return false;
122
121
  }
123
122
  inline const bool is_strictly_equal_to_primitive(const double &lhs, const AnyValue &rhs) noexcept
124
123
  {
@@ -151,6 +150,8 @@ namespace jspp
151
150
  return lhs.as_function() == rhs.as_function();
152
151
  case JsType::Iterator:
153
152
  return lhs.as_iterator() == rhs.as_iterator();
153
+ case JsType::AsyncIterator:
154
+ return lhs.as_async_iterator() == rhs.as_async_iterator();
154
155
  case JsType::Promise:
155
156
  return lhs.as_promise() == rhs.as_promise();
156
157
  case JsType::Symbol:
@@ -167,49 +168,11 @@ namespace jspp
167
168
  // Operator == (returns primitive boolean)
168
169
  inline const bool is_equal_to_primitive(const AnyValue &lhs, const double &rhs) noexcept
169
170
  {
170
- return is_equal_to_primitive(rhs, lhs);
171
+ return is_equal_to_primitive(lhs, AnyValue::make_number(rhs));
171
172
  }
172
173
  inline const bool is_equal_to_primitive(const double &lhs, const AnyValue &rhs) noexcept
173
174
  {
174
- JsType rhs_type = rhs.get_type();
175
- if (rhs_type == JsType::Number)
176
- {
177
- return lhs == rhs.as_double();
178
- }
179
- if (rhs_type == JsType::String)
180
- {
181
- double num_rhs;
182
- try
183
- {
184
- const std::string &s = rhs.as_string()->value;
185
- // JS considers empty string or whitespace-only string to be 0
186
- if (s.empty() || std::all_of(s.begin(), s.end(), [](unsigned char c)
187
- { return std::isspace(c); }))
188
- {
189
- num_rhs = 0.0;
190
- }
191
- else
192
- {
193
- size_t pos;
194
- num_rhs = std::stod(s, &pos);
195
- // Check if the entire string was consumed, allowing for trailing whitespace
196
- while (pos < s.length() && std::isspace(static_cast<unsigned char>(s[pos])))
197
- {
198
- pos++;
199
- }
200
- if (pos != s.length())
201
- {
202
- num_rhs = std::numeric_limits<double>::quiet_NaN();
203
- }
204
- }
205
- }
206
- catch (...)
207
- {
208
- num_rhs = std::numeric_limits<double>::quiet_NaN();
209
- }
210
- return lhs == num_rhs;
211
- }
212
- return is_equal_to_primitive(rhs, AnyValue::make_number(lhs));
175
+ return is_equal_to_primitive(AnyValue::make_number(lhs), rhs);
213
176
  }
214
177
  inline const bool is_equal_to_primitive(const double &lhs, const double &rhs) noexcept
215
178
  {
@@ -219,58 +182,44 @@ namespace jspp
219
182
  {
220
183
  JsType lhs_type = lhs.get_type();
221
184
  JsType rhs_type = rhs.get_type();
222
- // Implements JavaScript's Abstract Equality Comparison Algorithm (==)
223
- // Step 1: If types are the same, use strict equality (===)
224
185
  if (lhs_type == rhs_type)
225
186
  {
226
187
  return is_strictly_equal_to_primitive(lhs, rhs);
227
188
  }
228
- // Steps 2 & 3: null == undefined
229
189
  if ((lhs_type == JsType::Null && rhs_type == JsType::Undefined) || (lhs_type == JsType::Undefined && rhs_type == JsType::Null))
230
190
  {
231
191
  return true;
232
192
  }
233
- // Step 4 & 5: number == string
234
193
  if (lhs_type == JsType::Number && rhs_type == JsType::String)
235
194
  {
236
- return is_equal_to_primitive(lhs.as_double(), rhs);
195
+ return lhs.as_double() == Operators_Private::ToNumber(rhs);
237
196
  }
238
197
  if (lhs_type == JsType::String && rhs_type == JsType::Number)
239
198
  {
240
- // Delegate to the other operand to avoid code duplication
241
- return is_equal_to_primitive(rhs.as_double(), lhs);
199
+ return Operators_Private::ToNumber(lhs) == rhs.as_double();
242
200
  }
243
- // Step 6 & 7: boolean == any
244
201
  if (lhs_type == JsType::Boolean)
245
202
  {
246
- // Convert boolean to number and re-compare
247
203
  return is_equal_to_primitive(lhs.as_boolean() ? 1.0 : 0.0, rhs);
248
204
  }
249
205
  if (rhs_type == JsType::Boolean)
250
206
  {
251
- // Convert boolean to number and re-compare
252
207
  return is_equal_to_primitive(lhs, AnyValue::make_number(rhs.as_boolean() ? 1.0 : 0.0));
253
208
  }
254
- // Step 8 & 9: object == (string or number or symbol)
255
- // Simplified: Objects convert to primitives.
256
209
  if ((lhs_type == JsType::Object || lhs_type == JsType::Array || lhs_type == JsType::Function || lhs_type == JsType::Promise || lhs_type == JsType::Iterator) &&
257
210
  (rhs_type == JsType::String || rhs_type == JsType::Number || rhs_type == JsType::Symbol))
258
211
  {
259
- // Convert object to primitive (string) and re-compare.
260
- // This is a simplification of JS's ToPrimitive.
261
212
  return is_equal_to_primitive(AnyValue::make_string(lhs.to_std_string()), rhs);
262
213
  }
263
214
  if ((rhs_type == JsType::Object || rhs_type == JsType::Array || rhs_type == JsType::Function || rhs_type == JsType::Promise || rhs_type == JsType::Iterator) &&
264
215
  (lhs_type == JsType::String || lhs_type == JsType::Number || lhs_type == JsType::Symbol))
265
216
  {
266
- return is_equal_to_primitive(rhs, lhs);
217
+ return is_equal_to_primitive(lhs, AnyValue::make_string(rhs.to_std_string()));
267
218
  }
268
- // Step 10: Datacriptor or accessor descriptor
269
219
  if (lhs_type == JsType::DataDescriptor || lhs_type == JsType::AccessorDescriptor)
270
220
  {
271
221
  return is_strictly_equal_to_primitive(lhs, rhs);
272
222
  }
273
- // Step 11: All other cases (e.g., object == null) are false.
274
223
  return false;
275
224
  }
276
225
 
@@ -351,13 +300,10 @@ namespace jspp
351
300
  // Operator +
352
301
  inline AnyValue operator+(const AnyValue &lhs, const AnyValue &rhs)
353
302
  {
354
- // Check for number optimization
355
303
  if (lhs.is_number() && rhs.is_number())
356
304
  return AnyValue::make_number(lhs.as_double() + rhs.as_double());
357
- // String concatenation priority
358
305
  if (lhs.is_string() || rhs.is_string())
359
306
  return AnyValue::make_string(lhs.to_std_string() + rhs.to_std_string());
360
- // Fallback
361
307
  return AnyValue::make_number(Operators_Private::ToNumber(lhs) + Operators_Private::ToNumber(rhs));
362
308
  }
363
309
  inline AnyValue operator+(const AnyValue &lhs, const double &rhs)
@@ -505,7 +451,6 @@ namespace jspp
505
451
  if (lhs.is_number() && rhs.is_number())
506
452
  return AnyValue::make_boolean(lhs.as_double() < rhs.as_double());
507
453
 
508
- // String comparison support
509
454
  if (lhs.is_string() && rhs.is_string())
510
455
  return AnyValue::make_boolean(lhs.as_string()->value < rhs.as_string()->value);
511
456
 
@@ -513,7 +458,7 @@ namespace jspp
513
458
  double r = Operators_Private::ToNumber(rhs);
514
459
 
515
460
  if (std::isnan(l) || std::isnan(r))
516
- return AnyValue::make_boolean(false);
461
+ return Constants::FALSE;
517
462
 
518
463
  return AnyValue::make_boolean(l < r);
519
464
  }
@@ -524,7 +469,7 @@ namespace jspp
524
469
 
525
470
  double l = Operators_Private::ToNumber(lhs);
526
471
  if (std::isnan(l) || std::isnan(rhs))
527
- return AnyValue::make_boolean(false);
472
+ return Constants::FALSE;
528
473
 
529
474
  return AnyValue::make_boolean(l < rhs);
530
475
  }
@@ -535,17 +480,15 @@ namespace jspp
535
480
 
536
481
  double r = Operators_Private::ToNumber(rhs);
537
482
  if (std::isnan(lhs) || std::isnan(r))
538
- return AnyValue::make_boolean(false);
483
+ return Constants::FALSE;
539
484
 
540
485
  return AnyValue::make_boolean(lhs < r);
541
486
  }
542
487
 
543
- // Greater than > (Derived from <)
544
488
  inline AnyValue operator>(const AnyValue &lhs, const AnyValue &rhs) { return rhs < lhs; }
545
489
  inline AnyValue operator>(const AnyValue &lhs, const double &rhs) { return operator<(rhs, lhs); }
546
490
  inline AnyValue operator>(const double &lhs, const AnyValue &rhs) { return operator<(rhs, lhs); }
547
491
 
548
- // Less than or equal <= (Derived from >)
549
492
  inline AnyValue operator<=(const AnyValue &lhs, const AnyValue &rhs)
550
493
  {
551
494
  AnyValue result = rhs < lhs;
@@ -553,18 +496,15 @@ namespace jspp
553
496
  }
554
497
  inline AnyValue operator<=(const AnyValue &lhs, const double &rhs)
555
498
  {
556
- // a <= b is equivalent to !(b < a) -> !(rhs < lhs)
557
499
  AnyValue result = operator<(rhs, lhs);
558
500
  return AnyValue::make_boolean(!result.as_boolean());
559
501
  }
560
502
  inline AnyValue operator<=(const double &lhs, const AnyValue &rhs)
561
503
  {
562
- // a <= b is equivalent to !(b < a) -> !(rhs < lhs)
563
504
  AnyValue result = operator<(rhs, lhs);
564
505
  return AnyValue::make_boolean(!result.as_boolean());
565
506
  }
566
507
 
567
- // Greater than or equal >= (Derived from <)
568
508
  inline AnyValue operator>=(const AnyValue &lhs, const AnyValue &rhs)
569
509
  {
570
510
  AnyValue result = lhs < rhs;
@@ -588,7 +528,6 @@ namespace jspp
588
528
  }
589
529
  inline AnyValue operator==(const AnyValue &lhs, const double &rhs)
590
530
  {
591
- // Optimization: check if lhs is number first
592
531
  if (lhs.is_number())
593
532
  return AnyValue::make_boolean(lhs.as_double() == rhs);
594
533
  return AnyValue::make_boolean(is_equal_to_primitive(lhs, AnyValue::make_number(rhs)));
@@ -600,7 +539,6 @@ namespace jspp
600
539
  return AnyValue::make_boolean(is_equal_to_primitive(rhs, AnyValue::make_number(lhs)));
601
540
  }
602
541
 
603
- // Inequality !=
604
542
  inline AnyValue operator!=(const AnyValue &lhs, const AnyValue &rhs) { return AnyValue::make_boolean(!is_equal_to_primitive(lhs, rhs)); }
605
543
  inline AnyValue operator!=(const AnyValue &lhs, const double &rhs) { return AnyValue::make_boolean(!operator==(lhs, rhs).as_boolean()); }
606
544
  inline AnyValue operator!=(const double &lhs, const AnyValue &rhs) { return AnyValue::make_boolean(!operator==(lhs, rhs).as_boolean()); }
@@ -748,4 +686,4 @@ namespace jspp
748
686
  lhs = rhs;
749
687
  return lhs;
750
688
  }
751
- }
689
+ }
@@ -1,25 +1,24 @@
1
1
  #pragma once
2
2
 
3
3
  #include "values/symbol.hpp"
4
- #include <memory>
5
4
 
6
5
  namespace jspp
7
6
  {
8
7
  namespace WellKnownSymbols
9
8
  {
10
9
  // We use a specific prefix "@@" for well-known symbols to distinguish them from user symbols
11
- inline std::shared_ptr<JsSymbol> iterator = std::make_shared<JsSymbol>("Symbol.iterator", "@@iterator");
12
- inline std::shared_ptr<JsSymbol> asyncIterator = std::make_shared<JsSymbol>("Symbol.asyncIterator", "@@asyncIterator");
13
- inline std::shared_ptr<JsSymbol> hasInstance = std::make_shared<JsSymbol>("Symbol.hasInstance", "@@hasInstance");
14
- inline std::shared_ptr<JsSymbol> isConcatSpreadable = std::make_shared<JsSymbol>("Symbol.isConcatSpreadable", "@@isConcatSpreadable");
15
- inline std::shared_ptr<JsSymbol> match = std::make_shared<JsSymbol>("Symbol.match", "@@match");
16
- inline std::shared_ptr<JsSymbol> matchAll = std::make_shared<JsSymbol>("Symbol.matchAll", "@@matchAll");
17
- inline std::shared_ptr<JsSymbol> replace = std::make_shared<JsSymbol>("Symbol.replace", "@@replace");
18
- inline std::shared_ptr<JsSymbol> search = std::make_shared<JsSymbol>("Symbol.search", "@@search");
19
- inline std::shared_ptr<JsSymbol> species = std::make_shared<JsSymbol>("Symbol.species", "@@species");
20
- inline std::shared_ptr<JsSymbol> split = std::make_shared<JsSymbol>("Symbol.split", "@@split");
21
- inline std::shared_ptr<JsSymbol> toPrimitive = std::make_shared<JsSymbol>("Symbol.toPrimitive", "@@toPrimitive");
22
- inline std::shared_ptr<JsSymbol> toStringTag = std::make_shared<JsSymbol>("Symbol.toStringTag", "@@toStringTag");
23
- inline std::shared_ptr<JsSymbol> unscopables = std::make_shared<JsSymbol>("Symbol.unscopables", "@@unscopables");
10
+ inline JsSymbol* iterator = new JsSymbol("Symbol.iterator", "@@iterator");
11
+ inline JsSymbol* asyncIterator = new JsSymbol("Symbol.asyncIterator", "@@asyncIterator");
12
+ inline JsSymbol* hasInstance = new JsSymbol("Symbol.hasInstance", "@@hasInstance");
13
+ inline JsSymbol* isConcatSpreadable = new JsSymbol("Symbol.isConcatSpreadable", "@@isConcatSpreadable");
14
+ inline JsSymbol* match = new JsSymbol("Symbol.match", "@@match");
15
+ inline JsSymbol* matchAll = new JsSymbol("Symbol.matchAll", "@@matchAll");
16
+ inline JsSymbol* replace = new JsSymbol("Symbol.replace", "@@replace");
17
+ inline JsSymbol* search = new JsSymbol("Symbol.search", "@@search");
18
+ inline JsSymbol* species = new JsSymbol("Symbol.species", "@@species");
19
+ inline JsSymbol* split = new JsSymbol("Symbol.split", "@@split");
20
+ inline JsSymbol* toPrimitive = new JsSymbol("Symbol.toPrimitive", "@@toPrimitive");
21
+ inline JsSymbol* toStringTag = new JsSymbol("Symbol.toStringTag", "@@toStringTag");
22
+ inline JsSymbol* unscopables = new JsSymbol("Symbol.unscopables", "@@unscopables");
24
23
  }
25
- }
24
+ }
@@ -8,18 +8,20 @@ namespace jspp
8
8
  // Forward declaration of AnyValue
9
9
  class AnyValue;
10
10
 
11
- struct JsArray
11
+ struct JsArray : HeapObject
12
12
  {
13
13
  std::vector<AnyValue> dense; // dense storage for small/contiguous indices
14
14
  std::unordered_map<uint32_t, AnyValue> sparse; // sparse indices (very large indices)
15
15
  std::unordered_map<std::string, AnyValue> props; // non-index string properties
16
- std::shared_ptr<AnyValue> proto;
16
+ AnyValue proto;
17
17
  uint64_t length = 0;
18
18
 
19
- JsArray() : proto(nullptr) {}
19
+ JsArray();
20
20
  explicit JsArray(const std::vector<AnyValue> &items);
21
21
  explicit JsArray(std::vector<AnyValue> &&items);
22
22
 
23
+ JsType get_heap_type() const override { return JsType::Array; }
24
+
23
25
  std::string to_std_string() const;
24
26
  JsIterator<AnyValue> get_iterator();
25
27
 
@@ -16,9 +16,11 @@ namespace jspp
16
16
  class AnyValue;
17
17
 
18
18
  template <typename T>
19
- class JsAsyncIterator
19
+ class JsAsyncIterator : public HeapObject
20
20
  {
21
21
  public:
22
+ JsType get_heap_type() const override { return JsType::AsyncIterator; }
23
+
22
24
  struct promise_type
23
25
  {
24
26
  std::queue<std::pair<JsPromise, T>> pending_calls;
@@ -7,19 +7,31 @@ namespace jspp
7
7
  {
8
8
  class AnyValue;
9
9
 
10
- struct DataDescriptor
10
+ struct DataDescriptor : HeapObject
11
11
  {
12
- std::shared_ptr<AnyValue> value;
12
+ AnyValue value;
13
13
  bool writable = true;
14
14
  bool enumerable = false;
15
15
  bool configurable = true;
16
+
17
+ DataDescriptor(AnyValue v, bool w, bool e, bool c)
18
+ : value(v), writable(w), enumerable(e), configurable(c) {}
19
+
20
+ JsType get_heap_type() const override { return JsType::DataDescriptor; }
16
21
  };
17
22
 
18
- struct AccessorDescriptor
23
+ struct AccessorDescriptor : HeapObject
19
24
  {
20
25
  std::optional<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>> get; // getter = function or undefined
21
26
  std::optional<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>> set; // setter = function or undefined
22
27
  bool enumerable = false;
23
28
  bool configurable = true;
29
+
30
+ AccessorDescriptor(std::optional<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>> g,
31
+ std::optional<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>> s,
32
+ bool e, bool c)
33
+ : get(std::move(g)), set(std::move(s)), enumerable(e), configurable(c) {}
34
+
35
+ JsType get_heap_type() const override { return JsType::AccessorDescriptor; }
24
36
  };
25
37
  }
@@ -1,7 +1,6 @@
1
1
  #pragma once
2
2
 
3
3
  #include "types.hpp"
4
- #include <variant>
5
4
  #include <optional>
6
5
 
7
6
  namespace jspp
@@ -9,17 +8,12 @@ namespace jspp
9
8
  // Forward declaration of AnyValue
10
9
  class AnyValue;
11
10
 
12
- using JsFunctionCallable = std::variant<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>, // 0: Normal
13
- std::function<jspp::JsIterator<jspp::AnyValue>(const AnyValue &, std::span<const AnyValue>)>, // 1: Generator
14
- std::function<jspp::JsPromise(const AnyValue &, std::span<const AnyValue>)>, // 2: Async
15
- std::function<jspp::JsAsyncIterator<jspp::AnyValue>(const AnyValue &, std::span<const AnyValue>)>>; // 3: Async Generator
16
-
17
- struct JsFunction
11
+ struct JsFunction : HeapObject
18
12
  {
19
13
  JsFunctionCallable callable;
20
14
  std::optional<std::string> name;
21
15
  std::unordered_map<std::string, AnyValue> props;
22
- std::shared_ptr<AnyValue> proto = nullptr;
16
+ AnyValue proto;
23
17
  bool is_generator;
24
18
  bool is_async;
25
19
  bool is_class;
@@ -76,6 +70,8 @@ namespace jspp
76
70
  {
77
71
  }
78
72
 
73
+ JsType get_heap_type() const override { return JsType::Function; }
74
+
79
75
  std::string to_std_string() const;
80
76
  AnyValue call(const AnyValue &thisVal, std::span<const AnyValue> args);
81
77
 
@@ -83,4 +79,4 @@ namespace jspp
83
79
  AnyValue get_property(const std::string &key, const AnyValue &thisVal);
84
80
  AnyValue set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal);
85
81
  };
86
- }
82
+ }