@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,220 +1,209 @@
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
- jspp::JsArray::JsArray(const std::vector<jspp::AnyValue> &items) : dense(items), proto(nullptr), length(items.size()) {}
10
- jspp::JsArray::JsArray(std::vector<jspp::AnyValue> &&items) : dense(std::move(items)), proto(nullptr), length(dense.size()) {}
11
-
12
- std::string jspp::JsArray::to_std_string() const
13
- {
14
- if (length == 0)
15
- {
16
- return "";
17
- }
18
-
19
- std::string result = "";
20
- for (uint64_t i = 0; i < length; ++i)
21
- {
22
- const AnyValue *itemPtr = nullptr;
23
- if (i < dense.size())
24
- {
25
- itemPtr = &dense[i];
26
- }
27
- else
28
- {
29
- auto it = sparse.find(static_cast<uint32_t>(i));
30
- if (it != sparse.end())
31
- {
32
- itemPtr = &it->second;
33
- }
34
- }
35
-
36
- if (itemPtr && !itemPtr->is_uninitialized())
37
- {
38
- const auto &item = *itemPtr;
39
- if (!item.is_undefined() && !item.is_null())
40
- {
41
- result += item.to_std_string();
42
- }
43
- }
44
-
45
- if (i < length - 1)
46
- {
47
- result += ",";
48
- }
49
- }
50
- return result;
51
- }
52
-
53
- 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
- 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 && !(*proto).is_null() && !(*proto).is_undefined())
79
- {
80
- if ((*proto).has_property(key))
81
- return true;
82
- }
83
-
84
- if (ArrayPrototypes::get(key, const_cast<JsArray *>(this)).has_value())
85
- return true;
86
- return false;
87
- }
88
-
89
- 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])) // Quick check: if the first character is not a digit, it can't be a standard index.
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
- // check special own properties (length)
104
- if (key == "length")
105
- {
106
- auto proto_it = ArrayPrototypes::get(key, this);
107
- if (proto_it.has_value())
108
- {
109
- return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
110
- }
111
- }
112
-
113
- // check explicit proto chain
114
- if (proto && !(*proto).is_null() && !(*proto).is_undefined())
115
- {
116
- if ((*proto).has_property(key))
117
- {
118
- return (*proto).get_property_with_receiver(key, thisVal);
119
- }
120
- }
121
-
122
- // check prototype (implicit Array.prototype)
123
- auto proto_it = ArrayPrototypes::get(key, this);
124
- if (proto_it.has_value())
125
- {
126
- return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
127
- }
128
- // not found
129
- return AnyValue::make_undefined();
130
- }
131
- return AnyValue::resolve_property_for_read(it->second, thisVal, key);
132
- }
133
- }
134
-
135
- jspp::AnyValue jspp::JsArray::get_property(uint32_t idx)
136
- {
137
- if (idx < dense.size())
138
- {
139
- const auto &val = dense[idx];
140
- return val.is_uninitialized() ? AnyValue::make_undefined() : val;
141
- }
142
- const auto &it = sparse.find(idx);
143
- if (it != sparse.end())
144
- {
145
- const auto &val = it->second;
146
- return val.is_uninitialized() ? AnyValue::make_undefined() : val;
147
- }
148
- return AnyValue::make_undefined();
149
- }
150
-
151
- jspp::AnyValue jspp::JsArray::set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal)
152
- {
153
- if (
154
- !key.empty() && std::isdigit(static_cast<unsigned char>(key[0])) // Quick check: if the first character is not a digit, it can't be a standard index.
155
- && is_array_index(key))
156
- {
157
- uint32_t idx = static_cast<uint32_t>(std::stoull(key));
158
- return set_property(idx, value);
159
- }
160
- else
161
- {
162
- // set prototype property if accessor descriptor
163
- auto proto_val_opt = ArrayPrototypes::get(key, this);
164
- if (!proto_val_opt.has_value() && proto && !(*proto).is_null() && !(*proto).is_undefined())
165
- {
166
- // This is a bit simplified, ideally we should call get_property on proto to check descriptors
167
- // For now, let's assume if it's not in ArrayPrototypes, it might be in the explicit proto chain
168
- }
169
-
170
- if (proto_val_opt.has_value())
171
- {
172
- auto proto_value = proto_val_opt.value();
173
- if (proto_value.is_accessor_descriptor())
174
- {
175
- return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
176
- }
177
- if (proto_value.is_data_descriptor() && !proto_value.as_data_descriptor()->writable)
178
- {
179
- return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
180
- }
181
- }
182
-
183
- // set own property
184
- auto it = props.find(key);
185
- if (it != props.end())
186
- {
187
- return AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
188
- }
189
- else
190
- {
191
- props[key] = value;
192
- return value;
193
- }
194
- }
195
- }
196
-
197
- jspp::AnyValue jspp::JsArray::set_property(uint32_t idx, const AnyValue &value)
198
- {
199
- uint64_t newLen = static_cast<uint64_t>(idx) + 1;
200
- if (newLen > length)
201
- length = newLen;
202
-
203
- const uint32_t DENSE_GROW_THRESHOLD = 1024;
204
- if (idx < dense.size())
205
- {
206
- dense[idx] = value;
207
- return value;
208
- }
209
- else if (idx <= dense.size() + DENSE_GROW_THRESHOLD)
210
- {
211
- dense.resize(idx + 1, AnyValue::make_uninitialized());
212
- dense[idx] = value;
213
- return value;
214
- }
215
- else
216
- {
217
- sparse[idx] = value;
218
- return value;
219
- }
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, const_cast<JsArray *>(this)).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, this);
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, this);
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, this);
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
+ }
220
209
  }
@@ -27,7 +27,7 @@ jspp::AnyValue jspp::JsAsyncIterator<T>::get_property(const std::string &key, co
27
27
  return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
28
28
  }
29
29
  }
30
- return AnyValue::make_undefined();
30
+ return Constants::UNDEFINED;
31
31
  }
32
32
  return AnyValue::resolve_property_for_read(it->second, thisVal, key);
33
33
  }
@@ -95,6 +95,9 @@ void jspp::JsAsyncIterator<T>::resume_next()
95
95
  template <typename T>
96
96
  jspp::JsPromise jspp::JsAsyncIterator<T>::next(const T &val)
97
97
  {
98
+ // JsPromise is now a HeapObject.
99
+ // We should return it by value (which AnyValue will then wrap).
100
+ // Wait, coroutines return JsPromise by value.
98
101
  JsPromise p;
99
102
  if (handle)
100
103
  {
@@ -125,7 +128,7 @@ auto jspp::JsAsyncIterator<T>::promise_type::yield_value(From &&from)
125
128
  {
126
129
  auto call = pending_calls.front();
127
130
  pending_calls.pop();
128
- AnyValue result = AnyValue::make_object({{"value", std::forward<From>(from)}, {"done", AnyValue::make_boolean(false)}});
131
+ AnyValue result = AnyValue::make_object({{"value", std::forward<From>(from)}, {"done", Constants::FALSE}});
129
132
  call.first.resolve(result);
130
133
  }
131
134
 
@@ -183,7 +186,7 @@ void jspp::JsAsyncIterator<T>::promise_type::unhandled_exception()
183
186
  }
184
187
  catch (const Exception &e)
185
188
  {
186
- fail_all(*e.data);
189
+ fail_all(e.data);
187
190
  }
188
191
  catch (const std::exception &e)
189
192
  {
@@ -239,14 +242,8 @@ auto jspp::JsAsyncIterator<T>::promise_type::await_transform(AnyValue value)
239
242
  h.resume();
240
243
  pr.is_running = false;
241
244
 
242
- // After resume, if we suspended at a yield and have more calls, loop.
243
245
  if (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
244
246
  {
245
- // We need to call resume_next, but we don't have the iterator.
246
- // Actually, the loop in resume_next handles this.
247
- // But wait, who calls resume_next?
248
- // If we are here, we are in a microtask.
249
- // Let's just manually continue if needed.
250
247
  while (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
251
248
  {
252
249
  pr.is_running = true;
@@ -263,7 +260,6 @@ auto jspp::JsAsyncIterator<T>::promise_type::await_transform(AnyValue value)
263
260
  pr.is_running = true;
264
261
  h.resume();
265
262
  pr.is_running = false;
266
- // Errors handled via await_resume/exception throw
267
263
  });
268
264
  }
269
265
  AnyValue await_resume()
@@ -272,4 +268,4 @@ auto jspp::JsAsyncIterator<T>::promise_type::await_transform(AnyValue value)
272
268
  }
273
269
  };
274
270
  return AsyncIterAwaiter{AnyValueAwaiter{std::move(value)}, *this};
275
- }
271
+ }
@@ -10,7 +10,7 @@
10
10
 
11
11
  namespace jspp
12
12
  {
13
- std::string JsFunction::to_std_string() const
13
+ inline std::string JsFunction::to_std_string() const
14
14
  {
15
15
  std::string type_part = this->is_async ? "async function" : this->is_generator ? "function*"
16
16
  : "function";
@@ -18,7 +18,7 @@ namespace jspp
18
18
  return type_part + " " + name_part + "() { [native code] }";
19
19
  }
20
20
 
21
- AnyValue JsFunction::call(const AnyValue &thisVal, std::span<const AnyValue> args)
21
+ inline AnyValue JsFunction::call(const AnyValue &thisVal, std::span<const AnyValue> args)
22
22
  {
23
23
  if (std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)> *func = std::get_if<0>(&callable))
24
24
  {
@@ -38,17 +38,17 @@ namespace jspp
38
38
  }
39
39
  else
40
40
  {
41
- return AnyValue::make_undefined();
41
+ return Constants::UNDEFINED;
42
42
  }
43
43
  }
44
44
 
45
- bool JsFunction::has_property(const std::string &key) const
45
+ inline bool JsFunction::has_property(const std::string &key) const
46
46
  {
47
47
  if (props.find(key) != props.end())
48
48
  return true;
49
- if (proto && !(*proto).is_null() && !(*proto).is_undefined())
49
+ if (!proto.is_null() && !proto.is_undefined())
50
50
  {
51
- if ((*proto).has_property(key))
51
+ if (proto.has_property(key))
52
52
  return true;
53
53
  }
54
54
  if (FunctionPrototypes::get(key, const_cast<JsFunction *>(this)).has_value())
@@ -56,35 +56,31 @@ namespace jspp
56
56
  return false;
57
57
  }
58
58
 
59
- AnyValue JsFunction::get_property(const std::string &key, const AnyValue &thisVal)
59
+ inline AnyValue JsFunction::get_property(const std::string &key, const AnyValue &thisVal)
60
60
  {
61
61
  auto it = props.find(key);
62
62
  if (it == props.end())
63
63
  {
64
- // check explicit proto chain (e.g. for classes extending other classes)
65
- if (proto && !(*proto).is_null() && !(*proto).is_undefined())
64
+ if (!proto.is_null() && !proto.is_undefined())
66
65
  {
67
- if ((*proto).has_property(key))
66
+ if (proto.has_property(key))
68
67
  {
69
- return (*proto).get_property_with_receiver(key, thisVal);
68
+ return proto.get_property_with_receiver(key, thisVal);
70
69
  }
71
70
  }
72
71
 
73
- // check prototype (implicit Function.prototype)
74
72
  auto proto_it = FunctionPrototypes::get(key, this);
75
73
  if (proto_it.has_value())
76
74
  {
77
75
  return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
78
76
  }
79
- // not found
80
- return AnyValue::make_undefined();
77
+ return Constants::UNDEFINED;
81
78
  }
82
79
  return AnyValue::resolve_property_for_read(it->second, thisVal, key);
83
80
  }
84
81
 
85
- AnyValue JsFunction::set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal)
82
+ inline AnyValue JsFunction::set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal)
86
83
  {
87
- // set prototype property if accessor descriptor
88
84
  auto proto_it = FunctionPrototypes::get(key, this);
89
85
  if (proto_it.has_value())
90
86
  {
@@ -99,7 +95,6 @@ namespace jspp
99
95
  }
100
96
  }
101
97
 
102
- // set own property
103
98
  auto it = props.find(key);
104
99
  if (it != props.end())
105
100
  {