@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
@@ -42,7 +42,7 @@ namespace jspp
42
42
  {
43
43
  if (args.empty())
44
44
  {
45
- return AnyValue::make_undefined();
45
+ return Constants::UNDEFINED;
46
46
  }
47
47
 
48
48
  const auto &new_len_val = args[0];
@@ -103,7 +103,7 @@ namespace jspp
103
103
  {
104
104
  if (self->length == 0)
105
105
  {
106
- return AnyValue::make_undefined();
106
+ return Constants::UNDEFINED;
107
107
  }
108
108
  uint64_t last_idx = self->length - 1;
109
109
  AnyValue last_val = self->get_property(static_cast<uint32_t>(last_idx));
@@ -128,7 +128,7 @@ namespace jspp
128
128
  {
129
129
  if (self->length == 0)
130
130
  {
131
- return AnyValue::make_undefined();
131
+ return Constants::UNDEFINED;
132
132
  }
133
133
  AnyValue first_val = self->get_property(0u);
134
134
 
@@ -227,7 +227,7 @@ namespace jspp
227
227
  callback->call(thisVal, cbArgs);
228
228
  }
229
229
  }
230
- return AnyValue::make_undefined(); },
230
+ return Constants::UNDEFINED; },
231
231
  key);
232
232
  }
233
233
 
@@ -241,7 +241,7 @@ namespace jspp
241
241
  double k;
242
242
  if (relativeIndex >= 0) k = relativeIndex;
243
243
  else k = len + relativeIndex;
244
- if (k < 0 || k >= len) return AnyValue::make_undefined();
244
+ if (k < 0 || k >= len) return Constants::UNDEFINED;
245
245
  return self->get_property(static_cast<uint32_t>(k)); },
246
246
  key);
247
247
  }
@@ -251,9 +251,9 @@ namespace jspp
251
251
  {
252
252
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
253
253
  {
254
- AnyValue searchElement = args.empty() ? AnyValue::make_undefined() : args[0];
254
+ AnyValue searchElement = args.empty() ? Constants::UNDEFINED : args[0];
255
255
  double len = static_cast<double>(self->length);
256
- if (len == 0) return AnyValue::make_boolean(false);
256
+ if (len == 0) return Constants::FALSE;
257
257
  double n = (args.size() > 1) ? Operators_Private::ToNumber(args[1]) : 0;
258
258
  double k;
259
259
  if (n >= 0) k = n;
@@ -264,10 +264,10 @@ namespace jspp
264
264
  {
265
265
  AnyValue element = self->get_property(static_cast<uint32_t>(i));
266
266
  // SameValueZero algorithm (includes handles NaN)
267
- if (element.is_number() && searchElement.is_number() && std::isnan(element.as_double()) && std::isnan(searchElement.as_double())) return AnyValue::make_boolean(true);
268
- if (is_strictly_equal_to_primitive(element, searchElement)) return AnyValue::make_boolean(true);
267
+ if (element.is_number() && searchElement.is_number() && std::isnan(element.as_double()) && std::isnan(searchElement.as_double())) return Constants::TRUE;
268
+ if (is_strictly_equal_to_primitive(element, searchElement)) return Constants::TRUE;
269
269
  }
270
- return AnyValue::make_boolean(false); },
270
+ return Constants::FALSE; },
271
271
  key);
272
272
  }
273
273
 
@@ -276,7 +276,7 @@ namespace jspp
276
276
  {
277
277
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
278
278
  {
279
- AnyValue searchElement = args.empty() ? AnyValue::make_undefined() : args[0];
279
+ AnyValue searchElement = args.empty() ? Constants::UNDEFINED : args[0];
280
280
  double len = static_cast<double>(self->length);
281
281
  if (len == 0) return AnyValue::make_number(-1);
282
282
  double n = (args.size() > 1) ? Operators_Private::ToNumber(args[1]) : 0;
@@ -301,7 +301,7 @@ namespace jspp
301
301
  {
302
302
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
303
303
  {
304
- AnyValue searchElement = args.empty() ? AnyValue::make_undefined() : args[0];
304
+ AnyValue searchElement = args.empty() ? Constants::UNDEFINED : args[0];
305
305
  double len = static_cast<double>(self->length);
306
306
  if (len == 0) return AnyValue::make_number(-1);
307
307
  double n = (args.size() > 1) ? Operators_Private::ToNumber(args[1]) : len - 1;
@@ -341,7 +341,7 @@ namespace jspp
341
341
  return element;
342
342
  }
343
343
  }
344
- return AnyValue::make_undefined(); },
344
+ return Constants::UNDEFINED; },
345
345
  key);
346
346
  }
347
347
 
@@ -387,7 +387,7 @@ namespace jspp
387
387
  return element;
388
388
  }
389
389
  }
390
- return AnyValue::make_undefined(); },
390
+ return Constants::UNDEFINED; },
391
391
  key);
392
392
  }
393
393
 
@@ -431,7 +431,7 @@ namespace jspp
431
431
  for (uint64_t i = 0; i < self->length; ++i) {
432
432
  co_yield AnyValue::make_number(i);
433
433
  }
434
- co_return AnyValue::make_undefined(); },
434
+ co_return Constants::UNDEFINED; },
435
435
  key);
436
436
  }
437
437
 
@@ -447,7 +447,7 @@ namespace jspp
447
447
  entry.push_back(self->get_property(static_cast<uint32_t>(i)));
448
448
  co_yield AnyValue::make_array(std::move(entry));
449
449
  }
450
- co_return AnyValue::make_undefined(); },
450
+ co_return Constants::UNDEFINED; },
451
451
  key);
452
452
  }
453
453
 
@@ -517,11 +517,11 @@ namespace jspp
517
517
  AnyValue kVal = AnyValue::make_number(i);
518
518
  const AnyValue cbArgs[] = {val, kVal, thisVal};
519
519
  if (!is_truthy(callback->call(thisArg, std::span<const AnyValue>(cbArgs, 3)))) {
520
- return AnyValue::make_boolean(false);
520
+ return Constants::FALSE;
521
521
  }
522
522
  }
523
523
  }
524
- return AnyValue::make_boolean(true); },
524
+ return Constants::TRUE; },
525
525
  key);
526
526
  }
527
527
 
@@ -540,11 +540,11 @@ namespace jspp
540
540
  AnyValue kVal = AnyValue::make_number(i);
541
541
  const AnyValue cbArgs[] = {val, kVal, thisVal};
542
542
  if (is_truthy(callback->call(thisArg, std::span<const AnyValue>(cbArgs, 3)))) {
543
- return AnyValue::make_boolean(true);
543
+ return Constants::TRUE;
544
544
  }
545
545
  }
546
546
  }
547
- return AnyValue::make_boolean(false); },
547
+ return Constants::FALSE; },
548
548
  key);
549
549
  }
550
550
 
@@ -698,7 +698,7 @@ namespace jspp
698
698
  {
699
699
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
700
700
  {
701
- AnyValue value = args.empty() ? AnyValue::make_undefined() : args[0];
701
+ AnyValue value = args.empty() ? Constants::UNDEFINED : args[0];
702
702
  double len = static_cast<double>(self->length);
703
703
  double start = (args.size() > 1) ? Operators_Private::ToNumber(args[1]) : 0;
704
704
  double end = (args.size() > 2 && !args[2].is_undefined()) ? Operators_Private::ToNumber(args[2]) : len;
@@ -755,7 +755,7 @@ namespace jspp
755
755
  {
756
756
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
757
757
  {
758
- AnyValue compareFn = args.empty() ? AnyValue::make_undefined() : args[0];
758
+ AnyValue compareFn = args.empty() ? Constants::UNDEFINED : args[0];
759
759
 
760
760
  std::vector<AnyValue> items;
761
761
  for (uint64_t i = 0; i < self->length; ++i) {
@@ -20,17 +20,10 @@ namespace jspp
20
20
  key);
21
21
  }
22
22
  // --- [Symbol.asyncIterator]() method ---
23
- // For async iterators, the async iterator is itself (similar to sync iterators)
24
23
  if (key == WellKnownSymbols::asyncIterator->key)
25
24
  {
26
- // We return 'this'. Since we can't easily create a shared_ptr from raw pointer,
27
- // we rely on the context to hold the reference or implement better shared_from_this strategy.
28
- // For now, assume it works like Iterator.
29
25
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
30
- {
31
- // This is slightly dangerous as we create a new shared_ptr from raw.
32
- // TODO: fix lifetime management
33
- return thisVal; },
26
+ { return thisVal; },
34
27
  key);
35
28
  }
36
29
  // --- next() method ---
@@ -38,7 +31,7 @@ namespace jspp
38
31
  {
39
32
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
40
33
  {
41
- AnyValue val = args.empty() ? AnyValue::make_undefined() : args[0];
34
+ AnyValue val = args.empty() ? Constants::UNDEFINED : args[0];
42
35
  auto res = self->next(val);
43
36
  return AnyValue::make_promise(res); },
44
37
  key);
@@ -47,4 +40,4 @@ namespace jspp
47
40
  return std::nullopt;
48
41
  }
49
42
  }
50
- }
43
+ }
@@ -1,58 +1,51 @@
1
- #pragma once
2
-
3
- #include "types.hpp"
4
- #include "values/iterator.hpp"
5
- #include "any_value.hpp"
6
- #include "exception.hpp"
7
- #include "utils/operators.hpp"
8
-
9
- namespace jspp
10
- {
11
- namespace IteratorPrototypes
12
- {
13
- inline std::optional<AnyValue> get(const std::string &key, JsIterator<AnyValue> *self)
14
- {
15
- // --- toString() method ---
16
- if (key == "toString" || key == WellKnownSymbols::toStringTag->key)
17
- {
18
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
19
- { return AnyValue::make_string(self->to_std_string()); },
20
- key);
21
- }
22
- // --- [Symbol.iterator]() method ---
23
- if (key == WellKnownSymbols::iterator->key)
24
- {
25
- return AnyValue::make_generator([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
26
- {
27
- // An iterator's iterator is itself.
28
- // We need to return an AnyValue that holds a shared_ptr to this JsIterator.
29
- // Since we only have a raw pointer `self`, we can't directly make a new shared_ptr.
30
- // We'll return an AnyValue wrapping the raw pointer for now.
31
- // This relies on the calling context to manage lifetime, which is true for `for-of`.
32
- // A better solution might involve passing a shared_ptr to `self` into the prototype getters.
33
- // For now, let's assume the object containing the iterator is alive.
34
- return AnyValue::from_iterator_ref(self); },
35
- key);
36
- }
37
- // --- next() method ---
38
- if (key == "next")
39
- {
40
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
41
- {
42
- AnyValue val = args.empty() ? AnyValue::make_undefined() : args[0];
43
- auto res = self->next(val);
44
- return AnyValue::make_object({{"value",res.value.value_or(AnyValue::make_undefined())},{"done",AnyValue::make_boolean(res.done)},}); },
45
- key);
46
- }
47
- // --- toArray() method ---
48
- if (key == "toArray")
49
- {
50
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
51
- { return AnyValue::make_array(self->to_vector()); },
52
- key);
53
- }
54
-
55
- return std::nullopt;
56
- }
57
- }
58
- }
1
+ #pragma once
2
+
3
+ #include "types.hpp"
4
+ #include "values/iterator.hpp"
5
+ #include "any_value.hpp"
6
+ #include "exception.hpp"
7
+ #include "utils/operators.hpp"
8
+
9
+ namespace jspp
10
+ {
11
+ namespace IteratorPrototypes
12
+ {
13
+ inline std::optional<AnyValue> get(const std::string &key, JsIterator<AnyValue> *self)
14
+ {
15
+ // --- toString() method ---
16
+ if (key == "toString" || key == WellKnownSymbols::toStringTag->key)
17
+ {
18
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
19
+ { return AnyValue::make_string(self->to_std_string()); },
20
+ key);
21
+ }
22
+ // --- [Symbol.iterator]() method ---
23
+ if (key == WellKnownSymbols::iterator->key)
24
+ {
25
+ return AnyValue::make_generator([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
26
+ {
27
+ return thisVal; },
28
+ key);
29
+ }
30
+ // --- next() method ---
31
+ if (key == "next")
32
+ {
33
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
34
+ {
35
+ AnyValue val = args.empty() ? Constants::UNDEFINED : args[0];
36
+ auto res = self->next(val);
37
+ return AnyValue::make_object({{"value",res.value.value_or(Constants::UNDEFINED)},{"done",AnyValue::make_boolean(res.done)},}); },
38
+ key);
39
+ }
40
+ // --- toArray() method ---
41
+ if (key == "toArray")
42
+ {
43
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
44
+ { return AnyValue::make_array(self->to_vector()); },
45
+ key);
46
+ }
47
+
48
+ return std::nullopt;
49
+ }
50
+ }
51
+ }
@@ -15,23 +15,32 @@ namespace jspp
15
15
  {
16
16
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
17
17
  {
18
- AnyValue onFulfilled = (args.size() > 0 && args[0].is_function()) ? args[0] : AnyValue::make_undefined();
19
- AnyValue onRejected = (args.size() > 1 && args[1].is_function()) ? args[1] : AnyValue::make_undefined();
18
+ AnyValue onFulfilled = (args.size() > 0 && args[0].is_function()) ? args[0] : Constants::UNDEFINED;
19
+ AnyValue onRejected = (args.size() > 1 && args[1].is_function()) ? args[1] : Constants::UNDEFINED;
20
20
 
21
21
  // "then" returns a new Promise
22
22
  JsPromise newPromise;
23
23
  AnyValue newPromiseVal = AnyValue::make_promise(newPromise);
24
24
 
25
- // Capture shared pointer to the new promise's state to keep it alive and modify it
26
25
  auto newPromiseState = newPromise.state;
27
- // Helper wrapper to interact with state
28
26
  auto resolveNew = [newPromiseState](const AnyValue& v) {
29
- JsPromise p; p.state = newPromiseState;
30
- p.resolve(v);
27
+ // Manual state resolution to avoid HeapObject management issues here
28
+ if (newPromiseState->status != PromiseStatus::Pending) return;
29
+ newPromiseState->status = PromiseStatus::Fulfilled;
30
+ newPromiseState->result = v;
31
+ auto callbacks = newPromiseState->onFulfilled;
32
+ newPromiseState->onFulfilled.clear();
33
+ newPromiseState->onRejected.clear();
34
+ for (auto& cb : callbacks) jspp::Scheduler::instance().enqueue([cb, v]() { cb(v); });
31
35
  };
32
36
  auto rejectNew = [newPromiseState](const AnyValue& r) {
33
- JsPromise p; p.state = newPromiseState;
34
- p.reject(r);
37
+ if (newPromiseState->status != PromiseStatus::Pending) return;
38
+ newPromiseState->status = PromiseStatus::Rejected;
39
+ newPromiseState->result = r;
40
+ auto callbacks = newPromiseState->onRejected;
41
+ newPromiseState->onFulfilled.clear();
42
+ newPromiseState->onRejected.clear();
43
+ for (auto& cb : callbacks) jspp::Scheduler::instance().enqueue([cb, r]() { cb(r); });
35
44
  };
36
45
 
37
46
 
@@ -40,9 +49,8 @@ namespace jspp
40
49
  if (onFulfilled.is_function()) {
41
50
  try {
42
51
  const AnyValue cbArgs[] = {val};
43
- auto res = onFulfilled.call(AnyValue::make_undefined(), cbArgs, "onFulfilled");
52
+ auto res = onFulfilled.call(Constants::UNDEFINED, cbArgs, "onFulfilled");
44
53
  if (res.is_promise()) {
45
- // Chaining: newPromise follows res
46
54
  auto chained = res.as_promise();
47
55
  chained->then(
48
56
  [resolveNew](const AnyValue& v) { resolveNew(v); },
@@ -52,12 +60,12 @@ namespace jspp
52
60
  resolveNew(res);
53
61
  }
54
62
  } catch (const Exception& e) {
55
- rejectNew(*e.data);
63
+ rejectNew(e.data);
56
64
  } catch (...) {
57
65
  rejectNew(AnyValue::make_string("Unknown error"));
58
66
  }
59
67
  } else {
60
- resolveNew(val); // Fallthrough
68
+ resolveNew(val);
61
69
  }
62
70
  };
63
71
 
@@ -66,7 +74,7 @@ namespace jspp
66
74
  if (onRejected.is_function()) {
67
75
  try {
68
76
  const AnyValue cbArgs[] = {reason};
69
- auto res = onRejected.call(AnyValue::make_undefined(), cbArgs,"onRejected");
77
+ auto res = onRejected.call(Constants::UNDEFINED, cbArgs,"onRejected");
70
78
  if (res.is_promise()) {
71
79
  auto chained = res.as_promise();
72
80
  chained->then(
@@ -74,15 +82,15 @@ namespace jspp
74
82
  [rejectNew](const AnyValue& e) { rejectNew(e); }
75
83
  );
76
84
  } else {
77
- resolveNew(res); // Recovered
85
+ resolveNew(res);
78
86
  }
79
87
  } catch (const Exception& e) {
80
- rejectNew(*e.data);
88
+ rejectNew(e.data);
81
89
  } catch (...) {
82
90
  rejectNew(AnyValue::make_string("Unknown error"));
83
91
  }
84
92
  } else {
85
- rejectNew(reason); // Fallthrough
93
+ rejectNew(reason);
86
94
  }
87
95
  };
88
96
 
@@ -94,9 +102,8 @@ namespace jspp
94
102
  {
95
103
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
96
104
  {
97
- // catch(onRejected) is then(undefined, onRejected)
98
- AnyValue onRejected = (args.size() > 0 && args[0].is_function()) ? args[0] : AnyValue::make_undefined();
99
- const AnyValue thenArgs[] = {AnyValue::make_undefined(), onRejected};
105
+ AnyValue onRejected = (args.size() > 0 && args[0].is_function()) ? args[0] : Constants::UNDEFINED;
106
+ const AnyValue thenArgs[] = {Constants::UNDEFINED, onRejected};
100
107
  return thisVal.get_own_property("then").call(thisVal, thenArgs,"then"); }, "catch");
101
108
  }
102
109
 
@@ -104,23 +111,20 @@ namespace jspp
104
111
  {
105
112
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
106
113
  {
107
- AnyValue onFinally = (args.size() > 0 && args[0].is_function()) ? args[0] : AnyValue::make_undefined();
108
-
109
- // finally(onFinally) returns a promise that passes through value/reason,
110
- // but executes onFinally first.
114
+ AnyValue onFinally = (args.size() > 0 && args[0].is_function()) ? args[0] : Constants::UNDEFINED;
111
115
 
112
116
  const AnyValue thenArgs[] = {
113
117
  AnyValue::make_function([onFinally](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
114
- AnyValue val = args.empty() ? AnyValue::make_undefined() : args[0];
118
+ AnyValue val = args.empty() ? Constants::UNDEFINED : args[0];
115
119
  if (onFinally.is_function()) {
116
- onFinally.call(AnyValue::make_undefined(), {}, "onFinally");
120
+ onFinally.call(Constants::UNDEFINED, {}, "onFinally");
117
121
  }
118
122
  return val;
119
123
  }, ""),
120
124
  AnyValue::make_function([onFinally](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
121
- AnyValue reason = args.empty() ? AnyValue::make_undefined() : args[0];
125
+ AnyValue reason = args.empty() ? Constants::UNDEFINED : args[0];
122
126
  if (onFinally.is_function()) {
123
- onFinally.call(AnyValue::make_undefined(), {}, "onFinally");
127
+ onFinally.call(Constants::UNDEFINED, {}, "onFinally");
124
128
  }
125
129
  throw Exception(reason);
126
130
  }, "")
@@ -131,4 +135,4 @@ namespace jspp
131
135
  return std::nullopt;
132
136
  }
133
137
  }
134
- }
138
+ }
@@ -40,7 +40,7 @@ namespace jspp
40
40
  return AnyValue::make_accessor_descriptor([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
41
41
  { return AnyValue::make_number(self->value.length()); },
42
42
  [self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
43
- { return AnyValue::make_undefined(); },
43
+ { return Constants::UNDEFINED; },
44
44
  false,
45
45
  false);
46
46
  }
@@ -78,12 +78,12 @@ namespace jspp
78
78
  {
79
79
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
80
80
  {
81
- if(args.empty()) return AnyValue::make_boolean(false);
81
+ if(args.empty()) return Constants::FALSE;
82
82
  std::string search = args[0].to_std_string();
83
83
  size_t end_pos = (args.size() > 1 && !args[1].is_undefined()) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : self->value.length();
84
84
 
85
85
  if (end_pos > self->value.length()) end_pos = self->value.length();
86
- if (search.length() > end_pos) return AnyValue::make_boolean(false);
86
+ if (search.length() > end_pos) return Constants::FALSE;
87
87
 
88
88
  return AnyValue::make_boolean(self->value.substr(end_pos - search.length(), search.length()) == search); },
89
89
  key);
@@ -94,7 +94,7 @@ namespace jspp
94
94
  {
95
95
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
96
96
  {
97
- if(args.empty()) return AnyValue::make_boolean(false);
97
+ if(args.empty()) return Constants::FALSE;
98
98
  std::string search = args[0].to_std_string();
99
99
  size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
100
100
 
@@ -269,7 +269,7 @@ namespace jspp
269
269
  {
270
270
  return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
271
271
  {
272
- if(args.empty()) return AnyValue::make_boolean(false);
272
+ if(args.empty()) return Constants::FALSE;
273
273
  std::string search = args[0].to_std_string();
274
274
  size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
275
275
  if (pos > self->value.length()) pos = self->value.length();
@@ -43,7 +43,7 @@ namespace jspp
43
43
  {
44
44
  if (self->description.empty())
45
45
  {
46
- return AnyValue::make_undefined();
46
+ return Constants::UNDEFINED;
47
47
  }
48
48
  return AnyValue::make_string(self->description);
49
49
  },
@@ -9,13 +9,15 @@ namespace jspp
9
9
  // Forward declaration of AnyValue
10
10
  class AnyValue;
11
11
 
12
- struct JsString
12
+ struct JsString : HeapObject
13
13
  {
14
14
  std::string value;
15
15
 
16
16
  JsString() = default;
17
17
  explicit JsString(const std::string &s) : value(s) {}
18
18
 
19
+ JsType get_heap_type() const override { return JsType::String; }
20
+
19
21
  std::string to_std_string() const;
20
22
  JsIterator<AnyValue> get_iterator();
21
23