@ugo-studio/jspp 0.3.0 → 0.3.2

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 (127) hide show
  1. package/LICENSE +25 -25
  2. package/README.md +20 -12
  3. package/dist/cli/args.js +22 -0
  4. package/dist/cli/compiler.js +53 -0
  5. package/dist/cli/index.js +43 -107
  6. package/dist/cli/pch.js +71 -0
  7. package/dist/cli/runner.js +23 -0
  8. package/dist/cli/spinner.js +27 -11
  9. package/dist/cli/transpiler.js +20 -0
  10. package/dist/cli/utils.js +59 -0
  11. package/dist/cli/wasm.js +70 -0
  12. package/dist/index.js +17 -6
  13. package/dist/{analysis → interpreter/analysis}/scope.js +38 -3
  14. package/dist/{analysis → interpreter/analysis}/typeAnalyzer.js +563 -28
  15. package/dist/{core → interpreter/core}/codegen/class-handlers.js +1 -1
  16. package/dist/{core → interpreter/core}/codegen/control-flow-handlers.js +12 -11
  17. package/dist/{core → interpreter/core}/codegen/declaration-handlers.js +28 -9
  18. package/dist/{core → interpreter/core}/codegen/destructuring-handlers.js +9 -4
  19. package/dist/{core → interpreter/core}/codegen/expression-handlers.js +82 -88
  20. package/dist/{core → interpreter/core}/codegen/function-handlers.js +159 -46
  21. package/dist/{core → interpreter/core}/codegen/helpers.js +170 -25
  22. package/dist/interpreter/core/codegen/index.js +156 -0
  23. package/dist/{core → interpreter/core}/codegen/literal-handlers.js +9 -0
  24. package/dist/{core → interpreter/core}/codegen/statement-handlers.js +47 -7
  25. package/package.json +6 -4
  26. package/scripts/precompile-headers.ts +293 -50
  27. package/scripts/setup-compiler.ts +63 -63
  28. package/scripts/setup-emsdk.ts +114 -0
  29. package/src/prelude/any_value.cpp +888 -0
  30. package/src/prelude/any_value.hpp +29 -24
  31. package/src/prelude/{exception_helpers.hpp → exception.cpp} +53 -53
  32. package/src/prelude/exception.hpp +27 -27
  33. package/src/prelude/iterator_instantiations.hpp +10 -0
  34. package/src/prelude/{index.hpp → jspp.hpp} +13 -17
  35. package/src/prelude/library/array.cpp +191 -0
  36. package/src/prelude/library/array.hpp +5 -178
  37. package/src/prelude/library/boolean.cpp +30 -0
  38. package/src/prelude/library/boolean.hpp +14 -0
  39. package/src/prelude/library/console.cpp +125 -0
  40. package/src/prelude/library/console.hpp +9 -97
  41. package/src/prelude/library/error.cpp +100 -0
  42. package/src/prelude/library/error.hpp +8 -108
  43. package/src/prelude/library/function.cpp +69 -0
  44. package/src/prelude/library/function.hpp +6 -5
  45. package/src/prelude/library/global.cpp +98 -0
  46. package/src/prelude/library/global.hpp +12 -28
  47. package/src/prelude/library/global_usings.hpp +15 -0
  48. package/src/prelude/library/math.cpp +261 -0
  49. package/src/prelude/library/math.hpp +8 -288
  50. package/src/prelude/library/object.cpp +379 -0
  51. package/src/prelude/library/object.hpp +5 -267
  52. package/src/prelude/library/performance.cpp +21 -0
  53. package/src/prelude/library/performance.hpp +5 -20
  54. package/src/prelude/library/process.cpp +38 -0
  55. package/src/prelude/library/process.hpp +3 -31
  56. package/src/prelude/library/promise.cpp +131 -0
  57. package/src/prelude/library/promise.hpp +5 -116
  58. package/src/prelude/library/symbol.cpp +56 -0
  59. package/src/prelude/library/symbol.hpp +5 -46
  60. package/src/prelude/library/timer.cpp +88 -0
  61. package/src/prelude/library/timer.hpp +11 -87
  62. package/src/prelude/runtime.cpp +19 -0
  63. package/src/prelude/types.hpp +26 -20
  64. package/src/prelude/utils/access.hpp +123 -32
  65. package/src/prelude/utils/assignment_operators.hpp +119 -99
  66. package/src/prelude/utils/log_any_value/array.hpp +61 -40
  67. package/src/prelude/utils/log_any_value/function.hpp +39 -39
  68. package/src/prelude/utils/log_any_value/log_any_value.hpp +1 -1
  69. package/src/prelude/utils/log_any_value/object.hpp +60 -3
  70. package/src/prelude/utils/log_any_value/primitives.hpp +1 -1
  71. package/src/prelude/utils/operators.hpp +109 -94
  72. package/src/prelude/utils/operators_native.hpp +349 -0
  73. package/src/prelude/utils/well_known_symbols.hpp +24 -24
  74. package/src/prelude/values/array.cpp +1399 -0
  75. package/src/prelude/values/array.hpp +4 -0
  76. package/src/prelude/values/async_iterator.cpp +251 -0
  77. package/src/prelude/values/async_iterator.hpp +60 -32
  78. package/src/prelude/values/boolean.cpp +64 -0
  79. package/src/prelude/values/function.cpp +262 -0
  80. package/src/prelude/values/function.hpp +10 -30
  81. package/src/prelude/values/iterator.cpp +309 -0
  82. package/src/prelude/values/iterator.hpp +33 -64
  83. package/src/prelude/values/number.cpp +221 -0
  84. package/src/prelude/values/object.cpp +200 -0
  85. package/src/prelude/values/object.hpp +4 -0
  86. package/src/prelude/values/promise.cpp +479 -0
  87. package/src/prelude/values/promise.hpp +9 -2
  88. package/src/prelude/values/prototypes/array.hpp +46 -1348
  89. package/src/prelude/values/prototypes/async_iterator.hpp +19 -61
  90. package/src/prelude/values/prototypes/boolean.hpp +24 -0
  91. package/src/prelude/values/prototypes/function.hpp +7 -46
  92. package/src/prelude/values/prototypes/iterator.hpp +15 -191
  93. package/src/prelude/values/prototypes/number.hpp +30 -210
  94. package/src/prelude/values/prototypes/object.hpp +7 -23
  95. package/src/prelude/values/prototypes/promise.hpp +8 -186
  96. package/src/prelude/values/prototypes/string.hpp +28 -553
  97. package/src/prelude/values/prototypes/symbol.hpp +9 -70
  98. package/src/prelude/values/shape.hpp +52 -52
  99. package/src/prelude/values/string.cpp +485 -0
  100. package/src/prelude/values/symbol.cpp +89 -0
  101. package/src/prelude/values/symbol.hpp +101 -101
  102. package/dist/cli/file-utils.js +0 -20
  103. package/dist/cli-utils/args.js +0 -59
  104. package/dist/cli-utils/colors.js +0 -9
  105. package/dist/cli-utils/file-utils.js +0 -20
  106. package/dist/cli-utils/spinner.js +0 -55
  107. package/dist/cli.js +0 -153
  108. package/dist/core/codegen/index.js +0 -86
  109. package/src/prelude/any_value_access.hpp +0 -170
  110. package/src/prelude/any_value_defines.hpp +0 -190
  111. package/src/prelude/any_value_helpers.hpp +0 -374
  112. package/src/prelude/utils/operators_primitive.hpp +0 -337
  113. package/src/prelude/values/helpers/array.hpp +0 -199
  114. package/src/prelude/values/helpers/async_iterator.hpp +0 -275
  115. package/src/prelude/values/helpers/function.hpp +0 -109
  116. package/src/prelude/values/helpers/iterator.hpp +0 -145
  117. package/src/prelude/values/helpers/object.hpp +0 -104
  118. package/src/prelude/values/helpers/promise.hpp +0 -254
  119. package/src/prelude/values/helpers/string.hpp +0 -37
  120. package/src/prelude/values/helpers/symbol.hpp +0 -21
  121. /package/dist/{ast → interpreter/ast}/symbols.js +0 -0
  122. /package/dist/{ast → interpreter/ast}/types.js +0 -0
  123. /package/dist/{core → interpreter/core}/codegen/visitor.js +0 -0
  124. /package/dist/{core → interpreter/core}/constants.js +0 -0
  125. /package/dist/{core → interpreter/core}/error.js +0 -0
  126. /package/dist/{core → interpreter/core}/parser.js +0 -0
  127. /package/dist/{core → interpreter/core}/traverser.js +0 -0
@@ -1,275 +0,0 @@
1
- #pragma once
2
-
3
- #include "types.hpp"
4
- #include "values/async_iterator.hpp"
5
- #include "any_value.hpp"
6
- #include "values/prototypes/async_iterator.hpp"
7
-
8
- // --- JsAsyncIterator methods ---
9
-
10
- template <typename T>
11
- std::string jspp::JsAsyncIterator<T>::to_std_string() const
12
- {
13
- return "[object AsyncGenerator]";
14
- }
15
-
16
- template <typename T>
17
- jspp::AnyValue jspp::JsAsyncIterator<T>::get_property(const std::string &key, AnyValue thisVal)
18
- {
19
- auto it = props.find(key);
20
- if (it == props.end())
21
- {
22
- if constexpr (std::is_same_v<T, AnyValue>)
23
- {
24
- auto proto_it = AsyncIteratorPrototypes::get(key);
25
- if (proto_it.has_value())
26
- {
27
- return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
28
- }
29
- }
30
- return Constants::UNDEFINED;
31
- }
32
- return AnyValue::resolve_property_for_read(it->second, thisVal, key);
33
- }
34
-
35
- template <typename T>
36
- jspp::AnyValue jspp::JsAsyncIterator<T>::set_property(const std::string &key, AnyValue value, AnyValue thisVal)
37
- {
38
- if constexpr (std::is_same_v<T, AnyValue>)
39
- {
40
- auto proto_it = AsyncIteratorPrototypes::get(key);
41
- if (proto_it.has_value())
42
- {
43
- auto proto_value = proto_it.value();
44
- if (proto_value.is_accessor_descriptor())
45
- {
46
- return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
47
- }
48
- if (proto_value.is_data_descriptor() && !proto_value.as_data_descriptor()->writable)
49
- {
50
- return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
51
- }
52
- }
53
- }
54
-
55
- auto it = props.find(key);
56
- if (it != props.end())
57
- {
58
- return jspp::AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
59
- }
60
- else
61
- {
62
- props[key] = value;
63
- return value;
64
- }
65
- }
66
-
67
- template <typename T>
68
- void jspp::JsAsyncIterator<T>::resume_next()
69
- {
70
- if (!handle || handle.done())
71
- return;
72
- auto &p = handle.promise();
73
- if (p.is_awaiting || p.is_running)
74
- return;
75
- if (p.pending_calls.empty())
76
- return;
77
-
78
- p.is_running = true;
79
-
80
- auto &next_call = p.pending_calls.front();
81
- p.current_input = next_call.second;
82
-
83
- handle.resume();
84
-
85
- p.is_running = false;
86
-
87
- // After yield/return, if more calls are pending, handle them.
88
- if (!p.pending_calls.empty() && !p.is_awaiting && !handle.done())
89
- {
90
- this->ref();
91
- Scheduler::instance().enqueue([this]()
92
- {
93
- this->resume_next();
94
- this->deref();
95
- });
96
- }
97
- }
98
-
99
- template <typename T>
100
- jspp::JsPromise jspp::JsAsyncIterator<T>::next(const T &val)
101
- {
102
- // JsPromise is now a HeapObject.
103
- // We should return it by value (which AnyValue will then wrap).
104
- // Wait, coroutines return JsPromise by value.
105
- JsPromise p;
106
- if (handle)
107
- {
108
- if (handle.done())
109
- {
110
- p.resolve(AnyValue::make_object({{"value", Constants::UNDEFINED}, {"done", Constants::TRUE}}));
111
- }
112
- else
113
- {
114
- handle.promise().pending_calls.push({p, val});
115
- resume_next();
116
- }
117
- }
118
- else
119
- {
120
- p.resolve(AnyValue::make_object({{"value", Constants::UNDEFINED}, {"done", Constants::TRUE}}));
121
- }
122
- return p;
123
- }
124
-
125
- // --- JsAsyncIterator::promise_type methods ---
126
-
127
- template <typename T>
128
- template <typename From>
129
- auto jspp::JsAsyncIterator<T>::promise_type::yield_value(From &&from)
130
- {
131
- if (!pending_calls.empty())
132
- {
133
- auto call = pending_calls.front();
134
- pending_calls.pop();
135
- AnyValue result = AnyValue::make_object({{"value", std::forward<From>(from)}, {"done", Constants::FALSE}});
136
- call.first.resolve(result);
137
- }
138
-
139
- struct YieldAwaiter
140
- {
141
- promise_type &p;
142
- bool await_ready() { return false; }
143
- void await_suspend(std::coroutine_handle<promise_type> h)
144
- {
145
- // Suspended at yield.
146
- }
147
- T await_resume() { return p.current_input; }
148
- };
149
- return YieldAwaiter{*this};
150
- }
151
-
152
- template <typename T>
153
- template <typename From>
154
- void jspp::JsAsyncIterator<T>::promise_type::return_value(From &&from)
155
- {
156
- if (!pending_calls.empty())
157
- {
158
- auto call = pending_calls.front();
159
- pending_calls.pop();
160
- AnyValue result = AnyValue::make_object({{"value", std::forward<From>(from)}, {"done", Constants::TRUE}});
161
- call.first.resolve(result);
162
- }
163
-
164
- while (!pending_calls.empty())
165
- {
166
- auto call = pending_calls.front();
167
- pending_calls.pop();
168
- AnyValue result = AnyValue::make_object({{"value", Constants::UNDEFINED}, {"done", Constants::TRUE}});
169
- call.first.resolve(result);
170
- }
171
- }
172
-
173
- template <typename T>
174
- void jspp::JsAsyncIterator<T>::promise_type::fail_all(const AnyValue &reason)
175
- {
176
- while (!pending_calls.empty())
177
- {
178
- auto call = pending_calls.front();
179
- pending_calls.pop();
180
- call.first.reject(reason);
181
- }
182
- }
183
-
184
- template <typename T>
185
- void jspp::JsAsyncIterator<T>::promise_type::unhandled_exception()
186
- {
187
- try
188
- {
189
- std::rethrow_exception(std::current_exception());
190
- }
191
- catch (const Exception &e)
192
- {
193
- fail_all(e.data);
194
- }
195
- catch (const std::exception &e)
196
- {
197
- fail_all(AnyValue::make_string(e.what()));
198
- }
199
- catch (...)
200
- {
201
- fail_all(AnyValue::make_string("Unknown error in async generator"));
202
- }
203
- }
204
-
205
- template <typename T>
206
- auto jspp::JsAsyncIterator<T>::promise_type::await_transform(AnyValue value)
207
- {
208
- is_awaiting = true;
209
- struct AsyncIterAwaiter
210
- {
211
- AnyValueAwaiter base_awaiter;
212
- promise_type &p_ref;
213
-
214
- bool await_ready() { return base_awaiter.await_ready(); }
215
- void await_suspend(std::coroutine_handle<promise_type> h)
216
- {
217
- if (!base_awaiter.value.is_promise())
218
- {
219
- jspp::Scheduler::instance().enqueue([h]() mutable
220
- {
221
- auto &pr = h.promise();
222
- pr.is_awaiting = false;
223
- pr.is_running = true;
224
- h.resume();
225
- pr.is_running = false;
226
-
227
- if (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
228
- {
229
- while (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
230
- {
231
- pr.is_running = true;
232
- pr.current_input = pr.pending_calls.front().second;
233
- h.resume();
234
- pr.is_running = false;
235
- }
236
- } });
237
- return;
238
- }
239
- auto p = base_awaiter.value.as_promise();
240
- p->then(
241
- [h](AnyValue v) mutable
242
- {
243
- auto &pr = h.promise();
244
- pr.is_awaiting = false;
245
- pr.is_running = true;
246
- h.resume();
247
- pr.is_running = false;
248
-
249
- if (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
250
- {
251
- while (!h.done() && !pr.is_awaiting && !pr.pending_calls.empty())
252
- {
253
- pr.is_running = true;
254
- pr.current_input = pr.pending_calls.front().second;
255
- h.resume();
256
- pr.is_running = false;
257
- }
258
- }
259
- },
260
- [h](AnyValue e) mutable
261
- {
262
- auto &pr = h.promise();
263
- pr.is_awaiting = false;
264
- pr.is_running = true;
265
- h.resume();
266
- pr.is_running = false;
267
- });
268
- }
269
- AnyValue await_resume()
270
- {
271
- return base_awaiter.await_resume();
272
- }
273
- };
274
- return AsyncIterAwaiter{AnyValueAwaiter{std::move(value)}, *this};
275
- }
@@ -1,109 +0,0 @@
1
- #pragma once
2
-
3
- #include <variant>
4
- #include <optional>
5
-
6
- #include "types.hpp"
7
- #include "values/function.hpp"
8
- #include "any_value.hpp"
9
- #include "values/prototypes/function.hpp"
10
-
11
- namespace jspp
12
- {
13
- inline std::string JsFunction::to_std_string() const
14
- {
15
- std::string type_part = this->is_async ? "async function" : this->is_generator ? "function*"
16
- : "function";
17
- std::string name_part = this->name.value_or("");
18
- return type_part + " " + name_part + "() { [native code] }";
19
- }
20
-
21
- inline AnyValue JsFunction::call(AnyValue thisVal, std::span<const AnyValue> args)
22
- {
23
- if (std::function<AnyValue(AnyValue, std::span<const AnyValue>)> *func = std::get_if<0>(&callable))
24
- {
25
- return (*func)(thisVal, args);
26
- }
27
- else if (std::function<jspp::JsIterator<jspp::AnyValue>(AnyValue, std::vector<AnyValue>)> *func = std::get_if<1>(&callable))
28
- {
29
- return AnyValue::from_iterator((*func)(thisVal, std::vector<AnyValue>(args.begin(), args.end())));
30
- }
31
- else if (std::function<jspp::JsPromise(AnyValue, std::vector<AnyValue>)> *func = std::get_if<2>(&callable))
32
- {
33
- return AnyValue::make_promise((*func)(thisVal, std::vector<AnyValue>(args.begin(), args.end())));
34
- }
35
- else if (std::function<jspp::JsAsyncIterator<jspp::AnyValue>(AnyValue, std::vector<AnyValue>)> *func = std::get_if<3>(&callable))
36
- {
37
- return AnyValue::from_async_iterator((*func)(thisVal, std::vector<AnyValue>(args.begin(), args.end())));
38
- }
39
- else
40
- {
41
- return Constants::UNDEFINED;
42
- }
43
- }
44
-
45
- inline bool JsFunction::has_property(const std::string &key) const
46
- {
47
- if (props.find(key) != props.end())
48
- return true;
49
- if (!proto.is_null() && !proto.is_undefined())
50
- {
51
- if (proto.has_property(key))
52
- return true;
53
- }
54
- if (FunctionPrototypes::get(key).has_value())
55
- return true;
56
- return false;
57
- }
58
-
59
- inline AnyValue JsFunction::get_property(const std::string &key, AnyValue thisVal)
60
- {
61
- auto it = props.find(key);
62
- if (it == props.end())
63
- {
64
- if (!proto.is_null() && !proto.is_undefined())
65
- {
66
- if (proto.has_property(key))
67
- {
68
- return proto.get_property_with_receiver(key, thisVal);
69
- }
70
- }
71
-
72
- auto proto_it = FunctionPrototypes::get(key);
73
- if (proto_it.has_value())
74
- {
75
- return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
76
- }
77
- return Constants::UNDEFINED;
78
- }
79
- return AnyValue::resolve_property_for_read(it->second, thisVal, key);
80
- }
81
-
82
- inline AnyValue JsFunction::set_property(const std::string &key, AnyValue value, AnyValue thisVal)
83
- {
84
- auto proto_it = FunctionPrototypes::get(key);
85
- if (proto_it.has_value())
86
- {
87
- auto proto_value = proto_it.value();
88
- if (proto_value.is_accessor_descriptor())
89
- {
90
- return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
91
- }
92
- if (proto_value.is_data_descriptor() && !proto_value.as_data_descriptor()->writable)
93
- {
94
- return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
95
- }
96
- }
97
-
98
- auto it = props.find(key);
99
- if (it != props.end())
100
- {
101
- return AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
102
- }
103
- else
104
- {
105
- props[key] = value;
106
- return value;
107
- }
108
- }
109
- }
@@ -1,145 +0,0 @@
1
- #pragma once
2
-
3
- #include "types.hpp"
4
- #include "values/iterator.hpp"
5
- #include "any_value.hpp"
6
- #include "values/prototypes/iterator.hpp"
7
-
8
- template <typename T>
9
- std::string jspp::JsIterator<T>::to_std_string() const
10
- {
11
- return "[object Generator]";
12
- }
13
-
14
- template <typename T>
15
- typename jspp::JsIterator<T>::NextResult jspp::JsIterator<T>::next(const T &val)
16
- {
17
- // If the generator is already finished or invalid, return {undefined, true}
18
- if (!handle || handle.done())
19
- return {std::nullopt, true};
20
-
21
- handle.promise().input_value = val;
22
-
23
- // Resume execution until next co_yield or co_return
24
- handle.resume();
25
-
26
- if (handle.promise().exception_)
27
- {
28
- std::rethrow_exception(handle.promise().exception_);
29
- }
30
-
31
- // If handle.done() is TRUE, we hit co_return (value: X, done: true)
32
- // If handle.done() is FALSE, we hit co_yield (value: X, done: false)
33
- bool is_done = handle.done();
34
-
35
- return {handle.promise().current_value, is_done};
36
- }
37
-
38
- template <typename T>
39
- typename jspp::JsIterator<T>::NextResult jspp::JsIterator<T>::return_(const T &val)
40
- {
41
- if (!handle || handle.done())
42
- return {val, true};
43
-
44
- handle.promise().pending_return = true;
45
- handle.promise().current_value = val;
46
- handle.resume();
47
-
48
- if (handle.promise().exception_)
49
- {
50
- std::rethrow_exception(handle.promise().exception_);
51
- }
52
-
53
- return {handle.promise().current_value, true};
54
- }
55
-
56
- template <typename T>
57
- typename jspp::JsIterator<T>::NextResult jspp::JsIterator<T>::throw_(const AnyValue &err)
58
- {
59
- if (!handle || handle.done()) {
60
- throw Exception(err);
61
- }
62
-
63
- handle.promise().pending_exception = std::make_exception_ptr(Exception(err));
64
- handle.resume();
65
-
66
- if (handle.promise().exception_)
67
- {
68
- std::rethrow_exception(handle.promise().exception_);
69
- }
70
-
71
- bool is_done = handle.done();
72
- return {handle.promise().current_value, is_done};
73
- }
74
-
75
- template <typename T>
76
- std::vector<T> jspp::JsIterator<T>::to_vector()
77
- {
78
- std::vector<T> result;
79
- while (true)
80
- {
81
- auto next_res = this->next();
82
- if (next_res.done)
83
- {
84
- break;
85
- }
86
- result.push_back(next_res.value.value_or(Constants::UNDEFINED));
87
- }
88
- return result;
89
- }
90
-
91
- template <typename T>
92
- jspp::AnyValue jspp::JsIterator<T>::get_property(const std::string &key, AnyValue thisVal)
93
- {
94
- auto it = props.find(key);
95
- if (it == props.end())
96
- {
97
- // check prototype
98
- if constexpr (std::is_same_v<T, AnyValue>)
99
- {
100
- auto proto_it = IteratorPrototypes::get(key);
101
- if (proto_it.has_value())
102
- {
103
- return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
104
- }
105
- }
106
- // prototype not found
107
- return Constants::UNDEFINED;
108
- }
109
-
110
- return AnyValue::resolve_property_for_read(it->second, thisVal, key);
111
- }
112
-
113
- template <typename T>
114
- jspp::AnyValue jspp::JsIterator<T>::set_property(const std::string &key, AnyValue value, AnyValue thisVal)
115
- {
116
- // set prototype property if accessor descriptor
117
- if constexpr (std::is_same_v<T, AnyValue>)
118
- {
119
- auto proto_it = IteratorPrototypes::get(key);
120
- if (proto_it.has_value())
121
- {
122
- auto proto_value = proto_it.value();
123
- if (proto_value.is_accessor_descriptor())
124
- {
125
- return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
126
- }
127
- if (proto_value.is_data_descriptor() && !proto_value.as_data_descriptor()->writable)
128
- {
129
- return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
130
- }
131
- }
132
- }
133
-
134
- // set own property
135
- auto it = props.find(key);
136
- if (it != props.end())
137
- {
138
- return jspp::AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
139
- }
140
- else
141
- {
142
- props[key] = value;
143
- return value;
144
- }
145
- }
@@ -1,104 +0,0 @@
1
- #pragma once
2
-
3
- #include "types.hpp"
4
- #include "values/object.hpp"
5
- #include "any_value.hpp"
6
-
7
- namespace jspp {
8
- inline JsObject::JsObject() : shape(Shape::empty_shape()), proto(Constants::Null) {}
9
-
10
- inline JsObject::JsObject(std::initializer_list<std::pair<std::string, AnyValue>> p, AnyValue pr) : proto(pr) {
11
- shape = Shape::empty_shape();
12
- storage.reserve(p.size());
13
- for (const auto& pair : p) {
14
- shape = shape->transition(pair.first);
15
- storage.push_back(pair.second);
16
- }
17
- }
18
-
19
- inline JsObject::JsObject(const std::map<std::string, AnyValue> &p, AnyValue pr) : proto(pr) {
20
- shape = Shape::empty_shape();
21
- storage.reserve(p.size());
22
- for (const auto& pair : p) {
23
- shape = shape->transition(pair.first);
24
- storage.push_back(pair.second);
25
- }
26
- }
27
- }
28
-
29
- inline std::string jspp::JsObject::to_std_string() const
30
- {
31
- return "[Object Object]";
32
- }
33
-
34
- inline bool jspp::JsObject::has_property(const std::string &key) const
35
- {
36
- if (deleted_keys.count(key)) return false;
37
-
38
- if (shape->get_offset(key).has_value())
39
- return true;
40
- if (!proto.is_null() && !proto.is_undefined())
41
- {
42
- if (proto.has_property(key))
43
- return true;
44
- }
45
- if (ObjectPrototypes::get(key).has_value())
46
- return true;
47
- return false;
48
- }
49
-
50
- inline jspp::AnyValue jspp::JsObject::get_property(const std::string &key, const AnyValue &thisVal)
51
- {
52
- if (deleted_keys.count(key)) return Constants::UNDEFINED;
53
-
54
- auto offset = shape->get_offset(key);
55
- if (!offset.has_value())
56
- {
57
- if (!proto.is_null() && !proto.is_undefined())
58
- {
59
- if (proto.has_property(key))
60
- {
61
- return proto.get_property_with_receiver(key, thisVal);
62
- }
63
- }
64
-
65
- auto proto_it = ObjectPrototypes::get(key);
66
- if (proto_it.has_value())
67
- {
68
- return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
69
- }
70
- return Constants::UNDEFINED;
71
- }
72
- return AnyValue::resolve_property_for_read(storage[offset.value()], thisVal, key);
73
- }
74
-
75
- inline jspp::AnyValue jspp::JsObject::set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal)
76
- {
77
- auto proto_it = ObjectPrototypes::get(key);
78
- if (proto_it.has_value())
79
- {
80
- auto proto_value = proto_it.value();
81
- if (proto_value.is_accessor_descriptor())
82
- {
83
- return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
84
- }
85
- if (proto_value.is_data_descriptor() && !proto_value.as_data_descriptor()->writable)
86
- {
87
- return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
88
- }
89
- }
90
-
91
- if (deleted_keys.count(key)) deleted_keys.erase(key);
92
-
93
- auto offset = shape->get_offset(key);
94
- if (offset.has_value())
95
- {
96
- return AnyValue::resolve_property_for_write(storage[offset.value()], thisVal, value, key);
97
- }
98
- else
99
- {
100
- shape = shape->transition(key);
101
- storage.push_back(value);
102
- return value;
103
- }
104
- }