@ugo-studio/jspp 0.2.9 → 0.3.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 (35) hide show
  1. package/dist/core/codegen/class-handlers.js +6 -6
  2. package/dist/core/codegen/statement-handlers.js +1 -1
  3. package/package.json +1 -1
  4. package/src/prelude/any_value.hpp +362 -362
  5. package/src/prelude/any_value_access.hpp +170 -170
  6. package/src/prelude/any_value_defines.hpp +189 -189
  7. package/src/prelude/any_value_helpers.hpp +374 -374
  8. package/src/prelude/library/array.hpp +185 -185
  9. package/src/prelude/library/console.hpp +111 -111
  10. package/src/prelude/library/error.hpp +112 -112
  11. package/src/prelude/library/function.hpp +10 -10
  12. package/src/prelude/library/math.hpp +307 -307
  13. package/src/prelude/library/object.hpp +275 -275
  14. package/src/prelude/library/process.hpp +39 -39
  15. package/src/prelude/library/promise.hpp +123 -123
  16. package/src/prelude/library/symbol.hpp +52 -52
  17. package/src/prelude/library/timer.hpp +91 -91
  18. package/src/prelude/types.hpp +178 -178
  19. package/src/prelude/utils/access.hpp +411 -411
  20. package/src/prelude/utils/operators.hpp +336 -336
  21. package/src/prelude/values/array.hpp +0 -1
  22. package/src/prelude/values/async_iterator.hpp +83 -83
  23. package/src/prelude/values/function.hpp +82 -82
  24. package/src/prelude/values/helpers/array.hpp +198 -208
  25. package/src/prelude/values/helpers/async_iterator.hpp +275 -275
  26. package/src/prelude/values/helpers/function.hpp +108 -108
  27. package/src/prelude/values/helpers/iterator.hpp +144 -144
  28. package/src/prelude/values/helpers/promise.hpp +253 -253
  29. package/src/prelude/values/helpers/string.hpp +37 -61
  30. package/src/prelude/values/promise.hpp +72 -72
  31. package/src/prelude/values/prototypes/array.hpp +14 -2
  32. package/src/prelude/values/prototypes/iterator.hpp +201 -201
  33. package/src/prelude/values/prototypes/promise.hpp +196 -196
  34. package/src/prelude/values/prototypes/string.hpp +564 -542
  35. package/src/prelude/values/string.hpp +25 -26
@@ -1,362 +1,362 @@
1
- #pragma once
2
-
3
- #include <cassert>
4
- #include <cstdint>
5
- #include <cstring>
6
- #include <limits>
7
- #include <new>
8
- #include <sstream>
9
- #include <iomanip>
10
- #include <type_traits>
11
- #include <memory>
12
- #include <utility>
13
- #include <string>
14
- #include <map>
15
- #include <vector>
16
- #include <functional>
17
- #include <cmath>
18
- #include <optional>
19
- #include <coroutine>
20
-
21
- #include "types.hpp"
22
- #include "values/non_values.hpp"
23
-
24
- namespace jspp
25
- {
26
- // NAN BOXING SCHEME (64-bit)
27
- // -------------------------
28
- // Any value that is NOT a NaN double or is a "quiet" NaN is stored as a double.
29
- // We use the top bits of the NaN space for tagging.
30
- //
31
- // Any value >= 0xFFFC000000000000 is a special tag.
32
- //
33
- // Tagging (bits 48-63):
34
- // 0xFFFC: Pointer to HeapObject
35
- // 0xFFFD: Boolean (bit 0 is value)
36
- // 0xFFFE: Special (Undefined, Null, Uninitialized)
37
-
38
- class AnyValue
39
- {
40
- private:
41
- uint64_t storage;
42
-
43
- static constexpr uint64_t TAG_BASE = 0xFFFC000000000000ULL;
44
- static constexpr uint64_t TAG_POINTER = 0xFFFC000000000000ULL;
45
- static constexpr uint64_t TAG_BOOLEAN = 0xFFFD000000000000ULL;
46
- static constexpr uint64_t TAG_SPECIAL = 0xFFFE000000000000ULL;
47
-
48
- static constexpr uint64_t VAL_UNDEFINED = 0x1ULL;
49
- static constexpr uint64_t VAL_NULL = 0x2ULL;
50
- static constexpr uint64_t VAL_UNINITIALIZED = 0x3ULL;
51
-
52
- static constexpr uint64_t TAG_MASK = 0xFFFF000000000000ULL;
53
- static constexpr uint64_t PAYLOAD_MASK = 0x0000FFFFFFFFFFFFULL;
54
-
55
- inline bool has_tag(uint64_t tag) const noexcept
56
- {
57
- return (storage & TAG_MASK) == tag;
58
- }
59
-
60
- public:
61
- inline HeapObject *get_ptr() const noexcept
62
- {
63
- return reinterpret_cast<HeapObject *>(storage & PAYLOAD_MASK);
64
- }
65
-
66
- // default ctor (Undefined)
67
- AnyValue() noexcept : storage(TAG_SPECIAL | VAL_UNDEFINED) {}
68
-
69
- explicit AnyValue(double d) noexcept
70
- {
71
- std::memcpy(&storage, &d, 8);
72
- if (storage >= TAG_BASE) [[unlikely]]
73
- {
74
- storage = 0x7FF8000000000000ULL;
75
- }
76
- }
77
-
78
- explicit AnyValue(bool b) noexcept : storage(TAG_BOOLEAN | (b ? 1 : 0)) {}
79
-
80
- AnyValue(const AnyValue &other) noexcept : storage(other.storage)
81
- {
82
- if (is_heap_object())
83
- get_ptr()->ref();
84
- }
85
-
86
- AnyValue(AnyValue &&other) noexcept : storage(other.storage)
87
- {
88
- other.storage = TAG_SPECIAL | VAL_UNDEFINED;
89
- }
90
-
91
- AnyValue &operator=(const AnyValue &other) noexcept
92
- {
93
- if (this != &other)
94
- {
95
- if (is_heap_object())
96
- get_ptr()->deref();
97
- storage = other.storage;
98
- if (is_heap_object())
99
- get_ptr()->ref();
100
- }
101
- return *this;
102
- }
103
-
104
- AnyValue &operator=(AnyValue &&other) noexcept
105
- {
106
- if (this != &other)
107
- {
108
- if (is_heap_object())
109
- get_ptr()->deref();
110
- storage = other.storage;
111
- other.storage = TAG_SPECIAL | VAL_UNDEFINED;
112
- }
113
- return *this;
114
- }
115
-
116
- ~AnyValue()
117
- {
118
- if (is_heap_object())
119
- get_ptr()->deref();
120
- }
121
-
122
- // Assignments
123
- AnyValue &operator=(double val) noexcept
124
- {
125
- if (is_heap_object())
126
- get_ptr()->deref();
127
- std::memcpy(&storage, &val, 8);
128
- if (storage >= TAG_BASE) [[unlikely]]
129
- {
130
- storage = 0x7FF8000000000000ULL;
131
- }
132
- return *this;
133
- }
134
-
135
- friend void swap(AnyValue &a, AnyValue &b) noexcept
136
- {
137
- std::swap(a.storage, b.storage);
138
- }
139
-
140
- // --- FRIENDS for Optimized Operators
141
- friend AnyValue &operator+=(AnyValue &lhs, const AnyValue &rhs);
142
- friend AnyValue &operator-=(AnyValue &lhs, const AnyValue &rhs);
143
- friend AnyValue &operator*=(AnyValue &lhs, const AnyValue &rhs);
144
- friend AnyValue &operator/=(AnyValue &lhs, const AnyValue &rhs);
145
- friend AnyValue &operator%=(AnyValue &lhs, const AnyValue &rhs);
146
- friend AnyValue &operator++(AnyValue &val);
147
- friend AnyValue operator++(AnyValue &val, int);
148
- friend AnyValue &operator--(AnyValue &val);
149
- friend AnyValue operator--(AnyValue &val, int);
150
-
151
- // factories -------------------------------------------------------
152
- static AnyValue make_number(double d) noexcept
153
- {
154
- return AnyValue(d);
155
- }
156
- static AnyValue make_nan() noexcept
157
- {
158
- AnyValue v;
159
- v.storage = 0x7FF8000000000000ULL;
160
- return v;
161
- }
162
- static AnyValue make_uninitialized() noexcept
163
- {
164
- AnyValue v;
165
- v.storage = TAG_SPECIAL | VAL_UNINITIALIZED;
166
- return v;
167
- }
168
- static AnyValue make_undefined() noexcept
169
- {
170
- AnyValue v;
171
- v.storage = TAG_SPECIAL | VAL_UNDEFINED;
172
- return v;
173
- }
174
- static AnyValue make_null() noexcept
175
- {
176
- AnyValue v;
177
- v.storage = TAG_SPECIAL | VAL_NULL;
178
- return v;
179
- }
180
- static AnyValue make_boolean(bool b) noexcept
181
- {
182
- return AnyValue(b);
183
- }
184
-
185
- static AnyValue make_string(const std::string &raw_s) noexcept;
186
- static AnyValue make_object(std::initializer_list<std::pair<std::string, AnyValue>> props) noexcept;
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
- static AnyValue make_array(std::span<const AnyValue> dense) noexcept;
191
- static AnyValue make_array(const std::vector<AnyValue> &dense) noexcept;
192
- 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
- static AnyValue make_function(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt, bool is_constructor = true) noexcept;
197
- static AnyValue make_class(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept;
198
- static AnyValue make_generator(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept;
199
- static AnyValue make_async_function(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept;
200
- static AnyValue make_async_generator(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept;
201
- static AnyValue make_symbol(const std::string &description = "") noexcept;
202
- static AnyValue make_promise(const JsPromise &promise) noexcept;
203
- static AnyValue make_data_descriptor(AnyValue value, bool writable, bool enumerable, bool configurable) noexcept;
204
- static AnyValue make_accessor_descriptor(const std::optional<std::function<AnyValue(AnyValue, std::span<const AnyValue>)>> &get,
205
- const std::optional<std::function<AnyValue(AnyValue, std::span<const AnyValue>)>> &set,
206
- bool enumerable,
207
- bool configurable) noexcept;
208
-
209
- static AnyValue from_symbol(JsSymbol *sym) noexcept;
210
- static AnyValue from_string(JsString *str) noexcept;
211
- static AnyValue from_promise(JsPromise &&promise) noexcept;
212
- static AnyValue from_iterator(JsIterator<AnyValue> &&iterator) noexcept;
213
- static AnyValue from_iterator_ref(JsIterator<AnyValue> *iterator) noexcept;
214
- static AnyValue from_async_iterator(JsAsyncIterator<AnyValue> &&iterator) noexcept;
215
-
216
- // internal factory for wrapping raw heap object pointers
217
- static AnyValue from_ptr(HeapObject *ptr) noexcept
218
- {
219
- AnyValue v;
220
- v.storage = TAG_POINTER | reinterpret_cast<uint64_t>(ptr);
221
- ptr->ref();
222
- return v;
223
- }
224
-
225
- static AnyValue resolve_property_for_read(const AnyValue &val, AnyValue thisVal, const std::string &propName) noexcept;
226
- static AnyValue resolve_property_for_write(AnyValue &val, AnyValue thisVal, const AnyValue &new_val, const std::string &propName);
227
-
228
- // TYPE CHECKERS AND ACCESSORS ---------------------------------------
229
- inline JsType get_type() const noexcept
230
- {
231
- if (is_number())
232
- return JsType::Number;
233
- if (is_heap_object())
234
- return get_ptr()->get_heap_type();
235
- if (is_boolean())
236
- return JsType::Boolean;
237
- if (is_undefined())
238
- return JsType::Undefined;
239
- if (is_null())
240
- return JsType::Null;
241
- if (is_uninitialized())
242
- return JsType::Uninitialized;
243
- return JsType::Undefined;
244
- }
245
-
246
- inline bool is_number() const noexcept { return storage < TAG_BASE; }
247
- inline bool is_heap_object() const noexcept { return has_tag(TAG_POINTER); }
248
- inline bool is_string() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::String; }
249
- inline bool is_object() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::Object; }
250
- inline bool is_array() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::Array; }
251
- inline bool is_function() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::Function; }
252
- inline bool is_iterator() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::Iterator; }
253
- inline bool is_boolean() const noexcept { return has_tag(TAG_BOOLEAN); }
254
- inline bool is_symbol() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::Symbol; }
255
- inline bool is_promise() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::Promise; }
256
- inline bool is_null() const noexcept { return storage == (TAG_SPECIAL | VAL_NULL); }
257
- inline bool is_undefined() const noexcept { return storage == (TAG_SPECIAL | VAL_UNDEFINED); }
258
- inline bool is_uninitialized() const noexcept { return storage == (TAG_SPECIAL | VAL_UNINITIALIZED); }
259
- inline bool is_data_descriptor() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::DataDescriptor; }
260
- inline bool is_accessor_descriptor() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::AccessorDescriptor; }
261
- inline bool is_async_iterator() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::AsyncIterator; }
262
-
263
- JsString *as_string() const noexcept;
264
- JsObject *as_object() const noexcept;
265
- JsArray *as_array() const noexcept;
266
- JsFunction *as_function() const noexcept;
267
- JsSymbol *as_symbol() const noexcept;
268
- JsPromise *as_promise() const noexcept;
269
- JsIterator<AnyValue> *as_iterator() const noexcept;
270
- JsAsyncIterator<AnyValue> *as_async_iterator() const noexcept;
271
- DataDescriptor *as_data_descriptor() const noexcept;
272
- AccessorDescriptor *as_accessor_descriptor() const noexcept;
273
-
274
- bool is_generator() const noexcept;
275
-
276
- double as_double() const noexcept
277
- {
278
- double d;
279
- std::memcpy(&d, &storage, 8);
280
- return d;
281
- }
282
- bool as_boolean() const noexcept
283
- {
284
- return static_cast<bool>(storage & 1);
285
- }
286
-
287
- auto operator co_await() const;
288
-
289
- bool has_property(const std::string &key) const;
290
- bool has_property(const char *key) const { return has_property(std::string(key)); }
291
-
292
- AnyValue get_own_property(const std::string &key) const;
293
- AnyValue get_own_property(const char *key) const { return get_own_property(std::string(key)); }
294
- AnyValue get_own_property(uint32_t idx) const;
295
- AnyValue get_own_property(int idx) const { return get_own_property(static_cast<uint32_t>(idx)); }
296
- AnyValue get_own_property(const AnyValue &key) const;
297
-
298
- AnyValue get_property_with_receiver(const std::string &key, AnyValue receiver) const;
299
- AnyValue get_property_with_receiver(const char *key, AnyValue receiver) const { return get_property_with_receiver(std::string(key), receiver); }
300
-
301
- AnyValue set_own_property(const std::string &key, AnyValue value) const;
302
- AnyValue set_own_property(const char *key, AnyValue value) const { return set_own_property(std::string(key), value); }
303
- AnyValue set_own_property(uint32_t idx, AnyValue value) const;
304
- AnyValue set_own_property(int idx, AnyValue value) const { return set_own_property(static_cast<uint32_t>(idx), value); }
305
- AnyValue set_own_property(const AnyValue &key, AnyValue value) const;
306
-
307
- AnyValue call_own_property(const std::string &key, std::span<const AnyValue> args) const;
308
- AnyValue call_own_property(const char *key, std::span<const AnyValue> args) const { return call_own_property(std::string(key), args); }
309
- AnyValue call_own_property(uint32_t idx, std::span<const AnyValue> args) const;
310
- AnyValue call_own_property(int idx, std::span<const AnyValue> args) const { return call_own_property(static_cast<uint32_t>(idx), args); }
311
- AnyValue call_own_property(const AnyValue &key, std::span<const AnyValue> args) const;
312
-
313
- void define_data_property(const std::string &key, AnyValue value);
314
- void define_data_property(const char *key, AnyValue value) { define_data_property(std::string(key), value); }
315
- void define_data_property(const AnyValue &key, AnyValue value);
316
- void define_data_property(const std::string &key, AnyValue value, bool writable, bool enumerable, bool configurable);
317
- 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
- void define_getter(const std::string &key, AnyValue getter);
320
- void define_getter(const char *key, AnyValue getter) { define_getter(std::string(key), getter); }
321
- void define_getter(const AnyValue &key, AnyValue getter);
322
-
323
- void define_setter(const std::string &key, AnyValue setter);
324
- void define_setter(const char *key, AnyValue setter) { define_setter(std::string(key), setter); }
325
- void define_setter(const AnyValue &key, AnyValue setter);
326
-
327
- AnyValue call(AnyValue thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr = std::nullopt) const;
328
- AnyValue optional_call(AnyValue thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr = std::nullopt) const;
329
- AnyValue construct(std::span<const AnyValue> args, const std::optional<std::string> &name = std::nullopt) const;
330
- void set_prototype(AnyValue proto);
331
- std::string to_std_string() const;
332
- std::string to_property_key() const;
333
-
334
- inline uint64_t get_storage() const noexcept { return storage; }
335
- inline void *get_raw_ptr() const noexcept { return reinterpret_cast<void *>(storage & PAYLOAD_MASK); }
336
- };
337
-
338
- struct AnyValueAwaiter
339
- {
340
- AnyValue value;
341
- bool await_ready();
342
- void await_suspend(std::coroutine_handle<> h);
343
- AnyValue await_resume();
344
- };
345
-
346
- inline auto AnyValue::operator co_await() const
347
- {
348
- return AnyValueAwaiter{*this};
349
- }
350
-
351
- namespace Constants
352
- {
353
- inline const AnyValue UNINITIALIZED = AnyValue::make_uninitialized();
354
- inline const AnyValue UNDEFINED = AnyValue::make_undefined();
355
- inline const AnyValue Null = AnyValue::make_null();
356
- inline const AnyValue NaN = AnyValue::make_nan();
357
- inline const AnyValue TRUE = AnyValue::make_boolean(true);
358
- inline const AnyValue FALSE = AnyValue::make_boolean(false);
359
- inline const AnyValue ZERO = AnyValue::make_number(0.0);
360
- inline const AnyValue ONE = AnyValue::make_number(1.0);
361
- }
362
- }
1
+ #pragma once
2
+
3
+ #include <cassert>
4
+ #include <cstdint>
5
+ #include <cstring>
6
+ #include <limits>
7
+ #include <new>
8
+ #include <sstream>
9
+ #include <iomanip>
10
+ #include <type_traits>
11
+ #include <memory>
12
+ #include <utility>
13
+ #include <string>
14
+ #include <map>
15
+ #include <vector>
16
+ #include <functional>
17
+ #include <cmath>
18
+ #include <optional>
19
+ #include <coroutine>
20
+
21
+ #include "types.hpp"
22
+ #include "values/non_values.hpp"
23
+
24
+ namespace jspp
25
+ {
26
+ // NAN BOXING SCHEME (64-bit)
27
+ // -------------------------
28
+ // Any value that is NOT a NaN double or is a "quiet" NaN is stored as a double.
29
+ // We use the top bits of the NaN space for tagging.
30
+ //
31
+ // Any value >= 0xFFFC000000000000 is a special tag.
32
+ //
33
+ // Tagging (bits 48-63):
34
+ // 0xFFFC: Pointer to HeapObject
35
+ // 0xFFFD: Boolean (bit 0 is value)
36
+ // 0xFFFE: Special (Undefined, Null, Uninitialized)
37
+
38
+ class AnyValue
39
+ {
40
+ private:
41
+ uint64_t storage;
42
+
43
+ static constexpr uint64_t TAG_BASE = 0xFFFC000000000000ULL;
44
+ static constexpr uint64_t TAG_POINTER = 0xFFFC000000000000ULL;
45
+ static constexpr uint64_t TAG_BOOLEAN = 0xFFFD000000000000ULL;
46
+ static constexpr uint64_t TAG_SPECIAL = 0xFFFE000000000000ULL;
47
+
48
+ static constexpr uint64_t VAL_UNDEFINED = 0x1ULL;
49
+ static constexpr uint64_t VAL_NULL = 0x2ULL;
50
+ static constexpr uint64_t VAL_UNINITIALIZED = 0x3ULL;
51
+
52
+ static constexpr uint64_t TAG_MASK = 0xFFFF000000000000ULL;
53
+ static constexpr uint64_t PAYLOAD_MASK = 0x0000FFFFFFFFFFFFULL;
54
+
55
+ inline bool has_tag(uint64_t tag) const noexcept
56
+ {
57
+ return (storage & TAG_MASK) == tag;
58
+ }
59
+
60
+ public:
61
+ inline HeapObject *get_ptr() const noexcept
62
+ {
63
+ return reinterpret_cast<HeapObject *>(storage & PAYLOAD_MASK);
64
+ }
65
+
66
+ // default ctor (Undefined)
67
+ AnyValue() noexcept : storage(TAG_SPECIAL | VAL_UNDEFINED) {}
68
+
69
+ explicit AnyValue(double d) noexcept
70
+ {
71
+ std::memcpy(&storage, &d, 8);
72
+ if (storage >= TAG_BASE) [[unlikely]]
73
+ {
74
+ storage = 0x7FF8000000000000ULL;
75
+ }
76
+ }
77
+
78
+ explicit AnyValue(bool b) noexcept : storage(TAG_BOOLEAN | (b ? 1 : 0)) {}
79
+
80
+ AnyValue(const AnyValue &other) noexcept : storage(other.storage)
81
+ {
82
+ if (is_heap_object())
83
+ get_ptr()->ref();
84
+ }
85
+
86
+ AnyValue(AnyValue &&other) noexcept : storage(other.storage)
87
+ {
88
+ other.storage = TAG_SPECIAL | VAL_UNDEFINED;
89
+ }
90
+
91
+ AnyValue &operator=(const AnyValue &other) noexcept
92
+ {
93
+ if (this != &other)
94
+ {
95
+ if (is_heap_object())
96
+ get_ptr()->deref();
97
+ storage = other.storage;
98
+ if (is_heap_object())
99
+ get_ptr()->ref();
100
+ }
101
+ return *this;
102
+ }
103
+
104
+ AnyValue &operator=(AnyValue &&other) noexcept
105
+ {
106
+ if (this != &other)
107
+ {
108
+ if (is_heap_object())
109
+ get_ptr()->deref();
110
+ storage = other.storage;
111
+ other.storage = TAG_SPECIAL | VAL_UNDEFINED;
112
+ }
113
+ return *this;
114
+ }
115
+
116
+ ~AnyValue()
117
+ {
118
+ if (is_heap_object())
119
+ get_ptr()->deref();
120
+ }
121
+
122
+ // Assignments
123
+ AnyValue &operator=(double val) noexcept
124
+ {
125
+ if (is_heap_object())
126
+ get_ptr()->deref();
127
+ std::memcpy(&storage, &val, 8);
128
+ if (storage >= TAG_BASE) [[unlikely]]
129
+ {
130
+ storage = 0x7FF8000000000000ULL;
131
+ }
132
+ return *this;
133
+ }
134
+
135
+ friend void swap(AnyValue &a, AnyValue &b) noexcept
136
+ {
137
+ std::swap(a.storage, b.storage);
138
+ }
139
+
140
+ // --- FRIENDS for Optimized Operators
141
+ friend AnyValue &operator+=(AnyValue &lhs, const AnyValue &rhs);
142
+ friend AnyValue &operator-=(AnyValue &lhs, const AnyValue &rhs);
143
+ friend AnyValue &operator*=(AnyValue &lhs, const AnyValue &rhs);
144
+ friend AnyValue &operator/=(AnyValue &lhs, const AnyValue &rhs);
145
+ friend AnyValue &operator%=(AnyValue &lhs, const AnyValue &rhs);
146
+ friend AnyValue &operator++(AnyValue &val);
147
+ friend AnyValue operator++(AnyValue &val, int);
148
+ friend AnyValue &operator--(AnyValue &val);
149
+ friend AnyValue operator--(AnyValue &val, int);
150
+
151
+ // factories -------------------------------------------------------
152
+ static AnyValue make_number(double d) noexcept
153
+ {
154
+ return AnyValue(d);
155
+ }
156
+ static AnyValue make_nan() noexcept
157
+ {
158
+ AnyValue v;
159
+ v.storage = 0x7FF8000000000000ULL;
160
+ return v;
161
+ }
162
+ static AnyValue make_uninitialized() noexcept
163
+ {
164
+ AnyValue v;
165
+ v.storage = TAG_SPECIAL | VAL_UNINITIALIZED;
166
+ return v;
167
+ }
168
+ static AnyValue make_undefined() noexcept
169
+ {
170
+ AnyValue v;
171
+ v.storage = TAG_SPECIAL | VAL_UNDEFINED;
172
+ return v;
173
+ }
174
+ static AnyValue make_null() noexcept
175
+ {
176
+ AnyValue v;
177
+ v.storage = TAG_SPECIAL | VAL_NULL;
178
+ return v;
179
+ }
180
+ static AnyValue make_boolean(bool b) noexcept
181
+ {
182
+ return AnyValue(b);
183
+ }
184
+
185
+ static AnyValue make_string(const std::string &raw_s) noexcept;
186
+ static AnyValue make_object(std::initializer_list<std::pair<std::string, AnyValue>> props) noexcept;
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
+ static AnyValue make_array(std::span<const AnyValue> dense) noexcept;
191
+ static AnyValue make_array(const std::vector<AnyValue> &dense) noexcept;
192
+ 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
+ static AnyValue make_function(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt, bool is_constructor = true) noexcept;
197
+ static AnyValue make_class(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept;
198
+ static AnyValue make_generator(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept;
199
+ static AnyValue make_async_function(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept;
200
+ static AnyValue make_async_generator(const JsFunctionCallable &call, const std::optional<std::string> &name = std::nullopt) noexcept;
201
+ static AnyValue make_symbol(const std::string &description = "") noexcept;
202
+ static AnyValue make_promise(const JsPromise &promise) noexcept;
203
+ static AnyValue make_data_descriptor(AnyValue value, bool writable, bool enumerable, bool configurable) noexcept;
204
+ static AnyValue make_accessor_descriptor(const std::optional<std::function<AnyValue(AnyValue, std::span<const AnyValue>)>> &get,
205
+ const std::optional<std::function<AnyValue(AnyValue, std::span<const AnyValue>)>> &set,
206
+ bool enumerable,
207
+ bool configurable) noexcept;
208
+
209
+ static AnyValue from_symbol(JsSymbol *sym) noexcept;
210
+ static AnyValue from_string(JsString *str) noexcept;
211
+ static AnyValue from_promise(JsPromise &&promise) noexcept;
212
+ static AnyValue from_iterator(JsIterator<AnyValue> &&iterator) noexcept;
213
+ static AnyValue from_iterator_ref(JsIterator<AnyValue> *iterator) noexcept;
214
+ static AnyValue from_async_iterator(JsAsyncIterator<AnyValue> &&iterator) noexcept;
215
+
216
+ // internal factory for wrapping raw heap object pointers
217
+ static AnyValue from_ptr(HeapObject *ptr) noexcept
218
+ {
219
+ AnyValue v;
220
+ v.storage = TAG_POINTER | reinterpret_cast<uint64_t>(ptr);
221
+ ptr->ref();
222
+ return v;
223
+ }
224
+
225
+ static AnyValue resolve_property_for_read(const AnyValue &val, AnyValue thisVal, const std::string &propName) noexcept;
226
+ static AnyValue resolve_property_for_write(AnyValue &val, AnyValue thisVal, const AnyValue &new_val, const std::string &propName);
227
+
228
+ // TYPE CHECKERS AND ACCESSORS ---------------------------------------
229
+ inline JsType get_type() const noexcept
230
+ {
231
+ if (is_number())
232
+ return JsType::Number;
233
+ if (is_heap_object())
234
+ return get_ptr()->get_heap_type();
235
+ if (is_boolean())
236
+ return JsType::Boolean;
237
+ if (is_undefined())
238
+ return JsType::Undefined;
239
+ if (is_null())
240
+ return JsType::Null;
241
+ if (is_uninitialized())
242
+ return JsType::Uninitialized;
243
+ return JsType::Undefined;
244
+ }
245
+
246
+ inline bool is_number() const noexcept { return storage < TAG_BASE; }
247
+ inline bool is_heap_object() const noexcept { return has_tag(TAG_POINTER); }
248
+ inline bool is_string() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::String; }
249
+ inline bool is_object() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::Object; }
250
+ inline bool is_array() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::Array; }
251
+ inline bool is_function() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::Function; }
252
+ inline bool is_iterator() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::Iterator; }
253
+ inline bool is_boolean() const noexcept { return has_tag(TAG_BOOLEAN); }
254
+ inline bool is_symbol() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::Symbol; }
255
+ inline bool is_promise() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::Promise; }
256
+ inline bool is_null() const noexcept { return storage == (TAG_SPECIAL | VAL_NULL); }
257
+ inline bool is_undefined() const noexcept { return storage == (TAG_SPECIAL | VAL_UNDEFINED); }
258
+ inline bool is_uninitialized() const noexcept { return storage == (TAG_SPECIAL | VAL_UNINITIALIZED); }
259
+ inline bool is_data_descriptor() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::DataDescriptor; }
260
+ inline bool is_accessor_descriptor() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::AccessorDescriptor; }
261
+ inline bool is_async_iterator() const noexcept { return is_heap_object() && get_ptr()->get_heap_type() == JsType::AsyncIterator; }
262
+
263
+ JsString *as_string() const noexcept;
264
+ JsObject *as_object() const noexcept;
265
+ JsArray *as_array() const noexcept;
266
+ JsFunction *as_function() const noexcept;
267
+ JsSymbol *as_symbol() const noexcept;
268
+ JsPromise *as_promise() const noexcept;
269
+ JsIterator<AnyValue> *as_iterator() const noexcept;
270
+ JsAsyncIterator<AnyValue> *as_async_iterator() const noexcept;
271
+ DataDescriptor *as_data_descriptor() const noexcept;
272
+ AccessorDescriptor *as_accessor_descriptor() const noexcept;
273
+
274
+ bool is_generator() const noexcept;
275
+
276
+ double as_double() const noexcept
277
+ {
278
+ double d;
279
+ std::memcpy(&d, &storage, 8);
280
+ return d;
281
+ }
282
+ bool as_boolean() const noexcept
283
+ {
284
+ return static_cast<bool>(storage & 1);
285
+ }
286
+
287
+ auto operator co_await() const;
288
+
289
+ bool has_property(const std::string &key) const;
290
+ bool has_property(const char *key) const { return has_property(std::string(key)); }
291
+
292
+ AnyValue get_own_property(const std::string &key) const;
293
+ AnyValue get_own_property(const char *key) const { return get_own_property(std::string(key)); }
294
+ AnyValue get_own_property(uint32_t idx) const;
295
+ AnyValue get_own_property(int idx) const { return get_own_property(static_cast<uint32_t>(idx)); }
296
+ AnyValue get_own_property(const AnyValue &key) const;
297
+
298
+ AnyValue get_property_with_receiver(const std::string &key, AnyValue receiver) const;
299
+ AnyValue get_property_with_receiver(const char *key, AnyValue receiver) const { return get_property_with_receiver(std::string(key), receiver); }
300
+
301
+ AnyValue set_own_property(const std::string &key, AnyValue value) const;
302
+ AnyValue set_own_property(const char *key, AnyValue value) const { return set_own_property(std::string(key), value); }
303
+ AnyValue set_own_property(uint32_t idx, AnyValue value) const;
304
+ AnyValue set_own_property(int idx, AnyValue value) const { return set_own_property(static_cast<uint32_t>(idx), value); }
305
+ AnyValue set_own_property(const AnyValue &key, AnyValue value) const;
306
+
307
+ AnyValue call_own_property(const std::string &key, std::span<const AnyValue> args) const;
308
+ AnyValue call_own_property(const char *key, std::span<const AnyValue> args) const { return call_own_property(std::string(key), args); }
309
+ AnyValue call_own_property(uint32_t idx, std::span<const AnyValue> args) const;
310
+ AnyValue call_own_property(int idx, std::span<const AnyValue> args) const { return call_own_property(static_cast<uint32_t>(idx), args); }
311
+ AnyValue call_own_property(const AnyValue &key, std::span<const AnyValue> args) const;
312
+
313
+ void define_data_property(const std::string &key, AnyValue value);
314
+ void define_data_property(const char *key, AnyValue value) { define_data_property(std::string(key), value); }
315
+ void define_data_property(const AnyValue &key, AnyValue value);
316
+ void define_data_property(const std::string &key, AnyValue value, bool writable, bool enumerable, bool configurable);
317
+ 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
+ void define_getter(const std::string &key, AnyValue getter);
320
+ void define_getter(const char *key, AnyValue getter) { define_getter(std::string(key), getter); }
321
+ void define_getter(const AnyValue &key, AnyValue getter);
322
+
323
+ void define_setter(const std::string &key, AnyValue setter);
324
+ void define_setter(const char *key, AnyValue setter) { define_setter(std::string(key), setter); }
325
+ void define_setter(const AnyValue &key, AnyValue setter);
326
+
327
+ AnyValue call(AnyValue thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr = std::nullopt) const;
328
+ AnyValue optional_call(AnyValue thisVal, std::span<const AnyValue> args, const std::optional<std::string> &expr = std::nullopt) const;
329
+ AnyValue construct(std::span<const AnyValue> args, const std::optional<std::string> &name = std::nullopt) const;
330
+ void set_prototype(AnyValue proto);
331
+ std::string to_std_string() const;
332
+ std::string to_property_key() const;
333
+
334
+ inline uint64_t get_storage() const noexcept { return storage; }
335
+ inline void *get_raw_ptr() const noexcept { return reinterpret_cast<void *>(storage & PAYLOAD_MASK); }
336
+ };
337
+
338
+ struct AnyValueAwaiter
339
+ {
340
+ AnyValue value;
341
+ bool await_ready();
342
+ void await_suspend(std::coroutine_handle<> h);
343
+ AnyValue await_resume();
344
+ };
345
+
346
+ inline auto AnyValue::operator co_await() const
347
+ {
348
+ return AnyValueAwaiter{*this};
349
+ }
350
+
351
+ namespace Constants
352
+ {
353
+ inline const AnyValue UNINITIALIZED = AnyValue::make_uninitialized();
354
+ inline const AnyValue UNDEFINED = AnyValue::make_undefined();
355
+ inline const AnyValue Null = AnyValue::make_null();
356
+ inline const AnyValue NaN = AnyValue::make_nan();
357
+ inline const AnyValue TRUE = AnyValue::make_boolean(true);
358
+ inline const AnyValue FALSE = AnyValue::make_boolean(false);
359
+ inline const AnyValue ZERO = AnyValue::make_number(0.0);
360
+ inline const AnyValue ONE = AnyValue::make_number(1.0);
361
+ }
362
+ }