@ugo-studio/jspp 0.1.4 → 0.1.6

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 (71) hide show
  1. package/dist/analysis/scope.js +17 -0
  2. package/dist/analysis/typeAnalyzer.js +7 -1
  3. package/dist/ast/symbols.js +32 -0
  4. package/dist/ast/types.js +0 -6
  5. package/dist/cli-utils/args.js +57 -0
  6. package/dist/cli-utils/colors.js +9 -0
  7. package/dist/cli-utils/file-utils.js +20 -0
  8. package/dist/cli-utils/spinner.js +55 -0
  9. package/dist/cli.js +105 -30
  10. package/dist/core/codegen/class-handlers.js +10 -6
  11. package/dist/core/codegen/control-flow-handlers.js +57 -28
  12. package/dist/core/codegen/declaration-handlers.js +10 -6
  13. package/dist/core/codegen/expression-handlers.js +206 -61
  14. package/dist/core/codegen/function-handlers.js +203 -76
  15. package/dist/core/codegen/helpers.js +125 -28
  16. package/dist/core/codegen/index.js +23 -15
  17. package/dist/core/codegen/literal-handlers.js +15 -6
  18. package/dist/core/codegen/statement-handlers.js +282 -84
  19. package/dist/core/codegen/visitor.js +3 -1
  20. package/package.json +1 -1
  21. package/src/prelude/any_value.hpp +221 -342
  22. package/src/prelude/any_value_access.hpp +168 -81
  23. package/src/prelude/any_value_defines.hpp +74 -35
  24. package/src/prelude/any_value_helpers.hpp +75 -180
  25. package/src/prelude/exception.hpp +1 -0
  26. package/src/prelude/exception_helpers.hpp +4 -4
  27. package/src/prelude/index.hpp +12 -2
  28. package/src/prelude/library/array.hpp +190 -0
  29. package/src/prelude/library/console.hpp +6 -5
  30. package/src/prelude/library/error.hpp +10 -8
  31. package/src/prelude/library/function.hpp +10 -0
  32. package/src/prelude/library/global.hpp +20 -0
  33. package/src/prelude/library/math.hpp +308 -0
  34. package/src/prelude/library/object.hpp +288 -0
  35. package/src/prelude/library/performance.hpp +1 -1
  36. package/src/prelude/library/process.hpp +39 -0
  37. package/src/prelude/library/promise.hpp +57 -55
  38. package/src/prelude/library/symbol.hpp +45 -57
  39. package/src/prelude/library/timer.hpp +6 -6
  40. package/src/prelude/types.hpp +54 -0
  41. package/src/prelude/utils/access.hpp +215 -11
  42. package/src/prelude/utils/assignment_operators.hpp +99 -0
  43. package/src/prelude/utils/log_any_value/array.hpp +8 -8
  44. package/src/prelude/utils/log_any_value/function.hpp +6 -4
  45. package/src/prelude/utils/log_any_value/object.hpp +41 -24
  46. package/src/prelude/utils/log_any_value/primitives.hpp +3 -1
  47. package/src/prelude/utils/operators.hpp +750 -274
  48. package/src/prelude/utils/well_known_symbols.hpp +12 -0
  49. package/src/prelude/values/array.hpp +8 -6
  50. package/src/prelude/values/async_iterator.hpp +79 -0
  51. package/src/prelude/values/descriptors.hpp +2 -2
  52. package/src/prelude/values/function.hpp +72 -62
  53. package/src/prelude/values/helpers/array.hpp +64 -28
  54. package/src/prelude/values/helpers/async_iterator.hpp +275 -0
  55. package/src/prelude/values/helpers/function.hpp +81 -92
  56. package/src/prelude/values/helpers/iterator.hpp +3 -3
  57. package/src/prelude/values/helpers/object.hpp +54 -9
  58. package/src/prelude/values/helpers/promise.hpp +13 -6
  59. package/src/prelude/values/iterator.hpp +1 -1
  60. package/src/prelude/values/object.hpp +10 -3
  61. package/src/prelude/values/promise.hpp +7 -11
  62. package/src/prelude/values/prototypes/array.hpp +851 -12
  63. package/src/prelude/values/prototypes/async_iterator.hpp +50 -0
  64. package/src/prelude/values/prototypes/function.hpp +2 -2
  65. package/src/prelude/values/prototypes/iterator.hpp +5 -5
  66. package/src/prelude/values/prototypes/number.hpp +153 -0
  67. package/src/prelude/values/prototypes/object.hpp +2 -2
  68. package/src/prelude/values/prototypes/promise.hpp +40 -30
  69. package/src/prelude/values/prototypes/string.hpp +28 -28
  70. package/src/prelude/values/prototypes/symbol.hpp +20 -3
  71. package/src/prelude/values/shape.hpp +52 -0
@@ -0,0 +1,288 @@
1
+ #pragma once
2
+
3
+ #include "types.hpp"
4
+ #include "any_value.hpp"
5
+ #include "utils/access.hpp"
6
+ #include "exception.hpp"
7
+
8
+ // Define Object constructor
9
+ inline auto Object = jspp::AnyValue::make_class([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
10
+ {
11
+ if (args.empty() || args[0].is_undefined() || args[0].is_null()) {
12
+ return jspp::AnyValue::make_object({});
13
+ }
14
+ // Return argument if it is an object
15
+ if (args[0].is_object() || args[0].is_array() || args[0].is_function() || args[0].is_promise() || args[0].is_iterator()) {
16
+ return args[0];
17
+ }
18
+ // TODO: Wrapper objects for primitives
19
+ return jspp::AnyValue::make_object({}); }, "Object");
20
+
21
+ struct ObjectInit
22
+ {
23
+ ObjectInit()
24
+ {
25
+ // Object.keys(obj)
26
+ Object.define_data_property("keys", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
27
+ {
28
+ if (args.empty()) throw jspp::Exception::make_exception("Object.keys called on non-object", "TypeError");
29
+ auto obj = args[0];
30
+ if (obj.is_null() || obj.is_undefined()) throw jspp::Exception::make_exception("Object.keys called on null or undefined", "TypeError");
31
+
32
+ auto keys = jspp::Access::get_object_keys(obj);
33
+ std::vector<jspp::AnyValue> keyValues;
34
+ for(const auto& k : keys) {
35
+ keyValues.push_back(jspp::AnyValue::make_string(k));
36
+ }
37
+ return jspp::AnyValue::make_array(std::move(keyValues)); }, "keys"));
38
+
39
+ // Object.values(obj)
40
+ Object.define_data_property("values", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
41
+ {
42
+ if (args.empty()) throw jspp::Exception::make_exception("Object.values called on non-object", "TypeError");
43
+ auto obj = args[0];
44
+ if (obj.is_null() || obj.is_undefined()) throw jspp::Exception::make_exception("Object.values called on null or undefined", "TypeError");
45
+
46
+ auto keys = jspp::Access::get_object_keys(obj);
47
+ std::vector<jspp::AnyValue> values;
48
+ for(const auto& k : keys) {
49
+ values.push_back(obj.get_property_with_receiver(k, obj));
50
+ }
51
+ return jspp::AnyValue::make_array(std::move(values)); }, "values"));
52
+
53
+ // Object.entries(obj)
54
+ Object.define_data_property("entries", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
55
+ {
56
+ if (args.empty()) throw jspp::Exception::make_exception("Object.entries called on non-object", "TypeError");
57
+ auto obj = args[0];
58
+ if (obj.is_null() || obj.is_undefined()) throw jspp::Exception::make_exception("Object.entries called on null or undefined", "TypeError");
59
+
60
+ auto keys = jspp::Access::get_object_keys(obj);
61
+ std::vector<jspp::AnyValue> entries;
62
+ for(const auto& k : keys) {
63
+ std::vector<jspp::AnyValue> entry;
64
+ entry.push_back(jspp::AnyValue::make_string(k));
65
+ entry.push_back(obj.get_property_with_receiver(k, obj));
66
+ entries.push_back(jspp::AnyValue::make_array(std::move(entry)));
67
+ }
68
+ return jspp::AnyValue::make_array(std::move(entries)); }, "entries"));
69
+
70
+ // Object.assign(target, ...sources)
71
+ Object.define_data_property("assign", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
72
+ {
73
+ if (args.empty()) throw jspp::Exception::make_exception("Cannot convert undefined or null to object", "TypeError");
74
+ auto target = args[0];
75
+ if (target.is_null() || target.is_undefined()) throw jspp::Exception::make_exception("Cannot convert undefined or null to object", "TypeError");
76
+
77
+ // In JS, Object.assign modifies target in place if it's an object.
78
+ // If it's a primitive, it wraps it (but our primitives are tricky, let's assume objects for now).
79
+
80
+ for (size_t i = 1; i < args.size(); ++i) {
81
+ auto source = args[i];
82
+ if (source.is_null() || source.is_undefined()) continue;
83
+
84
+ auto keys = jspp::Access::get_object_keys(source);
85
+ for(const auto& k : keys) {
86
+ auto val = source.get_property_with_receiver(k, source);
87
+ target.set_own_property(k, val);
88
+ }
89
+ }
90
+ return target; }, "assign"));
91
+
92
+ // Object.is(value1, value2)
93
+ Object.define_data_property("is", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
94
+ {
95
+ jspp::AnyValue v1 = args.size() > 0 ? args[0] : jspp::AnyValue::make_undefined();
96
+ jspp::AnyValue v2 = args.size() > 1 ? args[1] : jspp::AnyValue::make_undefined();
97
+
98
+ if (v1.is_number() && v2.is_number()) {
99
+ double d1 = v1.as_double();
100
+ double d2 = v2.as_double();
101
+ if (std::isnan(d1) && std::isnan(d2)) return jspp::Constants::TRUE;
102
+ if (d1 == 0 && d2 == 0) {
103
+ // check signs
104
+ return jspp::AnyValue::make_boolean(std::signbit(d1) == std::signbit(d2));
105
+ }
106
+ return jspp::AnyValue::make_boolean(d1 == d2);
107
+ }
108
+
109
+ return jspp::is_strictly_equal_to(v1, v2); }, "is"));
110
+
111
+ // Object.getPrototypeOf(obj)
112
+ Object.define_data_property("getPrototypeOf", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
113
+ {
114
+ if (args.empty()) throw jspp::Exception::make_exception("Object.getPrototypeOf called on non-object", "TypeError");
115
+ auto obj = args[0];
116
+ // In ES6+, primitives are coerced to objects.
117
+ // We'll focus on Objects/Arrays/Functions for now.
118
+
119
+ if (obj.is_object()) {
120
+ auto p = obj.as_object()->proto;
121
+ return p ? *p : jspp::AnyValue::make_null();
122
+ }
123
+ if (obj.is_array()) {
124
+ auto p = obj.as_array()->proto;
125
+ return p ? *p : jspp::AnyValue::make_null();
126
+ }
127
+ if (obj.is_function()) {
128
+ auto p = obj.as_function()->proto;
129
+ return p ? *p : jspp::AnyValue::make_null();
130
+ }
131
+
132
+ // For primitives, they use their prototype from the global constructors usually
133
+ // e.g. Number.prototype. For now return null or implement if needed.
134
+ return jspp::AnyValue::make_null(); }, "getPrototypeOf"));
135
+
136
+ // Object.setPrototypeOf(obj, proto)
137
+ Object.define_data_property("setPrototypeOf", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
138
+ {
139
+ if (args.size() < 2) throw jspp::Exception::make_exception("Object.setPrototypeOf requires at least 2 arguments", "TypeError");
140
+ auto obj = args[0];
141
+ auto proto = args[1];
142
+
143
+ if (!proto.is_object() && !proto.is_null()) {
144
+ throw jspp::Exception::make_exception("Object prototype may only be an Object or null", "TypeError");
145
+ }
146
+
147
+ if (obj.is_object()) {
148
+ obj.as_object()->proto = std::make_shared<jspp::AnyValue>(proto);
149
+ } else if (obj.is_array()) {
150
+ obj.as_array()->proto = std::make_shared<jspp::AnyValue>(proto);
151
+ } else if (obj.is_function()) {
152
+ obj.as_function()->proto = std::make_shared<jspp::AnyValue>(proto);
153
+ }
154
+
155
+ return obj; }, "setPrototypeOf"));
156
+
157
+ // Object.create(proto, [propertiesObject])
158
+ Object.define_data_property("create", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
159
+ {
160
+ if (args.empty()) throw jspp::Exception::make_exception("Object prototype may only be an Object or null", "TypeError");
161
+ auto proto = args[0];
162
+ if (!proto.is_object() && !proto.is_null()) {
163
+ throw jspp::Exception::make_exception("Object prototype may only be an Object or null", "TypeError");
164
+ }
165
+
166
+ auto newObj = jspp::AnyValue::make_object_with_proto({}, proto);
167
+
168
+ if (args.size() > 1 && !args[1].is_undefined()) {
169
+ // Object.defineProperties(newObj, propertiesObject)
170
+ // TODO: implement defineProperties logic if needed.
171
+ }
172
+
173
+ return newObj; }, "create"));
174
+
175
+ // Object.defineProperty(obj, prop, descriptor)
176
+ Object.define_data_property("defineProperty", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
177
+ {
178
+ if (args.size() < 3) throw jspp::Exception::make_exception("Object.defineProperty requires 3 arguments", "TypeError");
179
+ auto obj = args[0];
180
+ if (!obj.is_object() && !obj.is_array() && !obj.is_function()) throw jspp::Exception::make_exception("Object.defineProperty called on non-object", "TypeError");
181
+
182
+ std::string prop = args[1].to_std_string();
183
+ auto descObj = args[2];
184
+
185
+ bool enumerable = false;
186
+ bool configurable = false;
187
+ bool writable = false;
188
+
189
+ if (descObj.has_property("enumerable")) enumerable = jspp::is_truthy(descObj.get_own_property("enumerable"));
190
+ if (descObj.has_property("configurable")) configurable = jspp::is_truthy(descObj.get_own_property("configurable"));
191
+ if (descObj.has_property("writable")) writable = jspp::is_truthy(descObj.get_own_property("writable"));
192
+
193
+ bool hasValue = descObj.has_property("value");
194
+ bool hasGet = descObj.has_property("get");
195
+ bool hasSet = descObj.has_property("set");
196
+
197
+ if (hasValue && (hasGet || hasSet)) {
198
+ throw jspp::Exception::make_exception("Invalid property descriptor. Cannot both specify accessors and a value or writable attribute", "TypeError");
199
+ }
200
+
201
+ if (hasValue) {
202
+ auto value = descObj.get_own_property("value");
203
+ obj.define_data_property(prop, value, writable, enumerable, configurable);
204
+ } else {
205
+ jspp::AnyValue getter = jspp::AnyValue::make_undefined();
206
+ jspp::AnyValue setter = jspp::AnyValue::make_undefined();
207
+
208
+ if (hasGet) getter = descObj.get_own_property("get");
209
+ if (hasSet) setter = descObj.get_own_property("set");
210
+
211
+ if (!getter.is_undefined() && !getter.is_function()) throw jspp::Exception::make_exception("Getter must be a function: " + getter.to_std_string(), "TypeError");
212
+ if (!setter.is_undefined() && !setter.is_function()) throw jspp::Exception::make_exception("Setter must be a function", "TypeError");
213
+
214
+ if (obj.is_object()) {
215
+ auto o_ptr = obj.as_object();
216
+ std::optional<std::function<jspp::AnyValue(const jspp::AnyValue &, std::span<const jspp::AnyValue>)>> getFunc;
217
+ std::optional<std::function<jspp::AnyValue(const jspp::AnyValue &, std::span<const jspp::AnyValue>)>> setFunc;
218
+
219
+ if (getter.is_function()) {
220
+ getFunc = [getter](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue {
221
+ return getter.call(thisVal, args);
222
+ };
223
+ }
224
+ if (setter.is_function()) {
225
+ setFunc = [setter](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue {
226
+ return setter.call(thisVal, args);
227
+ };
228
+ }
229
+
230
+ auto desc = jspp::AnyValue::make_accessor_descriptor(getFunc, setFunc, enumerable, configurable);
231
+ auto offset = o_ptr->shape->get_offset(prop);
232
+ if (offset.has_value()) {
233
+ o_ptr->storage[offset.value()] = desc;
234
+ } else {
235
+ o_ptr->shape = o_ptr->shape->transition(prop);
236
+ o_ptr->storage.push_back(desc);
237
+ }
238
+ }
239
+ // TODO: Handle Array/Function/others
240
+ }
241
+
242
+ return obj; }, "defineProperty"));
243
+
244
+ // Object.hasOwn(obj, prop)
245
+ Object.define_data_property("hasOwn", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
246
+ {
247
+ if (args.empty()) throw jspp::Exception::make_exception("Object.hasOwn called on non-object", "TypeError");
248
+ auto obj = args[0];
249
+ if (obj.is_null() || obj.is_undefined()) throw jspp::Exception::make_exception("Object.hasOwn called on null or undefined", "TypeError");
250
+ std::string prop = args.size() > 1 ? args[1].to_std_string() : "undefined";
251
+
252
+ if (obj.is_object()) return jspp::AnyValue::make_boolean(obj.as_object()->shape->get_offset(prop).has_value());
253
+ if (obj.is_function()) return jspp::AnyValue::make_boolean(obj.as_function()->props.count(prop));
254
+ if (obj.is_array()) {
255
+ if (prop == "length") return jspp::Constants::TRUE;
256
+ if (jspp::JsArray::is_array_index(prop)) {
257
+ uint32_t idx = static_cast<uint32_t>(std::stoull(prop));
258
+ auto arr = obj.as_array();
259
+ if (idx < arr->dense.size() && !(arr->dense[idx].is_uninitialized())) return jspp::Constants::TRUE;
260
+ if (arr->sparse.count(idx)) return jspp::Constants::TRUE;
261
+ return jspp::Constants::FALSE;
262
+ }
263
+ return jspp::AnyValue::make_boolean(obj.as_array()->props.count(prop));
264
+ }
265
+
266
+ return jspp::Constants::FALSE; }, "hasOwn"));
267
+
268
+ // Object.prototype.hasOwnProperty
269
+ auto proto = Object.get_own_property("prototype");
270
+ proto.define_data_property("hasOwnProperty", jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
271
+ {
272
+ std::string prop = args.size() > 0 ? args[0].to_std_string() : "undefined";
273
+ if (thisVal.is_object()) return jspp::AnyValue::make_boolean(thisVal.as_object()->shape->get_offset(prop).has_value());
274
+ if (thisVal.is_function()) return jspp::AnyValue::make_boolean(thisVal.as_function()->props.count(prop));
275
+ if (thisVal.is_array()) {
276
+ if (prop == "length") return jspp::Constants::TRUE;
277
+ if (jspp::JsArray::is_array_index(prop)) {
278
+ uint32_t idx = static_cast<uint32_t>(std::stoull(prop));
279
+ auto arr = thisVal.as_array();
280
+ if (idx < arr->dense.size() && !(arr->dense[idx].is_uninitialized())) return jspp::Constants::TRUE;
281
+ if (arr->sparse.count(idx)) return jspp::Constants::TRUE;
282
+ return jspp::Constants::FALSE;
283
+ }
284
+ return jspp::AnyValue::make_boolean(thisVal.as_array()->props.count(prop));
285
+ }
286
+ return jspp::Constants::FALSE; }, "hasOwnProperty"));
287
+ }
288
+ } objectInit;
@@ -13,7 +13,7 @@ inline auto performance = jspp::AnyValue::make_object({
13
13
  // [C++14 Feature] Generalized Lambda Capture
14
14
  // We initialize 'startTime' RIGHT HERE inside the [].
15
15
  // It acts like a private variable stored inside this specific function.
16
- [startTime = std::chrono::steady_clock::now()](const jspp::AnyValue &thisVal, const std::vector<jspp::AnyValue> &)
16
+ [startTime = std::chrono::steady_clock::now()](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue>)
17
17
  {
18
18
  // We calculate the diff against the captured startTime
19
19
  std::chrono::duration<double, std::milli> duration =
@@ -0,0 +1,39 @@
1
+ #pragma once
2
+
3
+ #include "types.hpp"
4
+ #include "any_value.hpp"
5
+
6
+ #ifdef _WIN32
7
+ #define JSPP_PLATFORM "win32"
8
+ #else
9
+ #define JSPP_PLATFORM "linux"
10
+ #endif
11
+
12
+ inline auto process = jspp::AnyValue::make_object({
13
+ {"argv", jspp::AnyValue::make_array(std::vector<jspp::AnyValue>{})},
14
+ {"env", jspp::AnyValue::make_object({})},
15
+ {"platform", jspp::AnyValue::make_string(JSPP_PLATFORM)},
16
+ {"exit", jspp::AnyValue::make_function([](const jspp::AnyValue&, std::span<const jspp::AnyValue> args) -> jspp::AnyValue {
17
+ int code = 0;
18
+ if (!args.empty() && args[0].is_number()) {
19
+ code = static_cast<int>(args[0].as_double());
20
+ }
21
+ std::exit(code);
22
+ return jspp::Constants::UNDEFINED;
23
+ }, "exit")}
24
+ });
25
+
26
+ namespace jspp {
27
+ inline void setup_process_argv(int argc, char** argv) {
28
+ std::vector<jspp::AnyValue> args;
29
+ if (argc > 0) {
30
+ args.push_back(jspp::AnyValue::make_string(argv[0]));
31
+ args.push_back(jspp::AnyValue::make_string("index.js"));
32
+ for (int i = 1; i < argc; ++i) {
33
+ args.push_back(jspp::AnyValue::make_string(argv[i]));
34
+ }
35
+ }
36
+ process.set_own_property("argv", jspp::AnyValue::make_array(std::move(args)));
37
+ }
38
+ }
39
+
@@ -5,67 +5,69 @@
5
5
  #include "any_value.hpp"
6
6
  #include "exception.hpp"
7
7
 
8
- inline auto Promise = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
9
- if (args.empty() || !args[0].is_function()) {
10
- throw jspp::Exception::make_exception("Promise resolver undefined is not a function", "TypeError");
11
- }
12
- auto executor = args[0].as_function();
8
+ inline auto Promise = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
9
+ {
10
+ if (args.empty() || !args[0].is_function())
11
+ {
12
+ throw jspp::Exception::make_exception("Promise resolver undefined is not a function", "TypeError");
13
+ }
14
+ auto executor = args[0].as_function();
13
15
 
14
- jspp::JsPromise promise;
15
- auto state = promise.state; // Share state
16
+ jspp::JsPromise promise;
17
+ auto state = promise.state; // Share state
16
18
 
17
- // resolve function
18
- auto resolveFn = jspp::AnyValue::make_function([state](const jspp::AnyValue&, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
19
+ // resolve function
20
+ auto resolveFn = jspp::AnyValue::make_function([state](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
21
+ {
19
22
  jspp::JsPromise p; p.state = state;
20
- p.resolve(args.empty() ? jspp::AnyValue::make_undefined() : args[0]);
21
- return jspp::AnyValue::make_undefined();
22
- }, "resolve");
23
+ p.resolve(args.empty() ? jspp::Constants::UNDEFINED : args[0]);
24
+ return jspp::Constants::UNDEFINED; }, "resolve");
23
25
 
24
- // reject function
25
- auto rejectFn = jspp::AnyValue::make_function([state](const jspp::AnyValue&, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
26
+ // reject function
27
+ auto rejectFn = jspp::AnyValue::make_function([state](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
28
+ {
26
29
  jspp::JsPromise p; p.state = state;
27
- p.reject(args.empty() ? jspp::AnyValue::make_undefined() : args[0]);
28
- return jspp::AnyValue::make_undefined();
29
- }, "reject");
30
-
31
- try {
32
- executor->call(jspp::AnyValue::make_undefined(), {resolveFn, rejectFn});
33
- } catch (const jspp::Exception& e) {
34
- promise.reject(*e.data);
35
- } catch (...) {
36
- promise.reject(jspp::AnyValue::make_string("Unknown error during Promise execution"));
37
- }
30
+ p.reject(args.empty() ? jspp::Constants::UNDEFINED : args[0]);
31
+ return jspp::Constants::UNDEFINED; }, "reject");
38
32
 
39
- return jspp::AnyValue::make_promise(promise);
33
+ try
34
+ {
35
+ const jspp::AnyValue executorArgs[] = {resolveFn, rejectFn};
36
+ executor->call(jspp::Constants::UNDEFINED, std::span<const jspp::AnyValue>(executorArgs, 2));
37
+ }
38
+ catch (const jspp::Exception &e)
39
+ {
40
+ promise.reject(*e.data);
41
+ }
42
+ catch (...)
43
+ {
44
+ promise.reject(jspp::AnyValue::make_string("Unknown error during Promise execution"));
45
+ }
40
46
 
41
- }, "Promise");
47
+ return jspp::AnyValue::make_promise(promise); },
48
+ "Promise");
42
49
 
43
- struct PromiseInit {
44
- PromiseInit() {
50
+ struct PromiseInit
51
+ {
52
+ PromiseInit()
53
+ {
45
54
  // Promise.resolve(value)
46
- Promise.define_data_property("resolve", jspp::AnyValue::make_function([](const jspp::AnyValue&, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
55
+ Promise.define_data_property("resolve", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
56
+ {
47
57
  jspp::JsPromise p;
48
- p.resolve(args.empty() ? jspp::AnyValue::make_undefined() : args[0]);
49
- return jspp::AnyValue::make_promise(p);
50
- }, "resolve"));
58
+ p.resolve(args.empty() ? jspp::Constants::UNDEFINED : args[0]);
59
+ return jspp::AnyValue::make_promise(p); }, "resolve"));
51
60
 
52
61
  // Promise.reject(reason)
53
- Promise.define_data_property("reject", jspp::AnyValue::make_function([](const jspp::AnyValue&, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
62
+ Promise.define_data_property("reject", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
63
+ {
54
64
  jspp::JsPromise p;
55
- p.reject(args.empty() ? jspp::AnyValue::make_undefined() : args[0]);
56
- return jspp::AnyValue::make_promise(p);
57
- }, "reject"));
58
-
65
+ p.reject(args.empty() ? jspp::Constants::UNDEFINED : args[0]);
66
+ return jspp::AnyValue::make_promise(p); }, "reject"));
67
+
59
68
  // Promise.all(iterable)
60
- Promise.define_data_property("all", jspp::AnyValue::make_function([](const jspp::AnyValue&, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
61
- // Basic implementation for arrays
62
- if (args.empty() || !args[0].is_array()) {
63
- // If not array, reject? Or treat as non-iterable?
64
- // Should throw TypeError if not iterable. For now assume array.
65
- // If empty array, return resolved empty array.
66
- // TODO: Strict iterable check
67
- }
68
-
69
+ Promise.define_data_property("all", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
70
+ {
69
71
  // Handle non-array iterable or empty args
70
72
  if (args.empty() || !args[0].is_array()) {
71
73
  jspp::JsPromise p; p.reject(jspp::AnyValue::make_string("Promise.all argument must be an array"));
@@ -73,16 +75,16 @@ struct PromiseInit {
73
75
  }
74
76
 
75
77
  auto arr = args[0].as_array();
76
- size_t len = arr->length;
78
+ size_t len = static_cast<size_t>(arr->length);
77
79
  if (len == 0) {
78
- jspp::JsPromise p; p.resolve(jspp::AnyValue::make_array({}));
80
+ jspp::JsPromise p; p.resolve(jspp::AnyValue::make_array(std::vector<jspp::AnyValue>()));
79
81
  return jspp::AnyValue::make_promise(p);
80
82
  }
81
83
 
82
84
  jspp::JsPromise masterPromise;
83
85
  auto masterState = masterPromise.state;
84
86
 
85
- auto results = std::make_shared<std::vector<std::optional<jspp::AnyValue>>>(len);
87
+ auto results = std::make_shared<std::vector<jspp::AnyValue>>(len, jspp::Constants::UNDEFINED);
86
88
  auto count = std::make_shared<size_t>(len);
87
89
 
88
90
  // Check if already rejected to avoid further processing
@@ -91,20 +93,21 @@ struct PromiseInit {
91
93
  for (size_t i = 0; i < len; ++i) {
92
94
  jspp::AnyValue item = arr->get_property(static_cast<uint32_t>(i));
93
95
 
94
- auto handleResult = [masterState, results, count, i, rejected](jspp::AnyValue res) {
96
+ auto handleResult = [masterState, results, count, i, rejected](const jspp::AnyValue& res) {
95
97
  if (*rejected) return;
96
98
  (*results)[i] = res;
97
99
  (*count)--;
98
100
  if (*count == 0) {
99
101
  jspp::JsPromise p; p.state = masterState;
100
- p.resolve(jspp::AnyValue::make_array(*results));
102
+ p.resolve(jspp::AnyValue::make_array(std::move(*results)));
101
103
  }
102
104
  };
103
105
 
104
- auto handleReject = [masterState, rejected](jspp::AnyValue reason) {
106
+ auto handleReject = [masterState, rejected](const jspp::AnyValue& reason) {
105
107
  if (*rejected) return;
106
108
  *rejected = true;
107
109
  jspp::JsPromise p; p.state = masterState;
110
+ masterState->status =jspp::PromiseStatus::Rejected; // ensure master state updated
108
111
  p.reject(reason);
109
112
  };
110
113
 
@@ -115,7 +118,6 @@ struct PromiseInit {
115
118
  }
116
119
  }
117
120
 
118
- return jspp::AnyValue::make_promise(masterPromise);
119
- }, "all"));
121
+ return jspp::AnyValue::make_promise(masterPromise); }, "all"));
120
122
  }
121
123
  } promiseInit;
@@ -2,63 +2,51 @@
2
2
 
3
3
  #include "types.hpp"
4
4
  #include "utils/well_known_symbols.hpp"
5
-
6
5
  #include "values/object.hpp"
7
6
  #include "any_value.hpp"
8
7
 
9
- inline auto Symbol = jspp::AnyValue::make_object({
10
- {"iterator", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::iterator)},
11
- });
12
-
13
- // #pragma once
14
-
15
- // #include "types.hpp"
16
- // #include "utils/well_known_symbols.hpp"
17
- // #include "values/object.hpp"
18
- // #include "any_value.hpp"
19
-
20
- // // We define the Symbol constructor function
21
- // inline auto symbolConstructor = [](const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
22
- // std::string desc = "";
23
- // if (!args.empty() && !args[0].is_undefined()) {
24
- // desc = args[0].to_std_string();
25
- // }
26
- // return jspp::AnyValue::make_symbol(desc);
27
- // };
28
-
29
- // inline auto Symbol = jspp::AnyValue::make_function(symbolConstructor, "Symbol");
30
-
31
- // // Implementation of Symbol.for(key)
32
- // inline auto forFn = jspp::AnyValue::make_function([](const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
33
- // std::string key = "";
34
- // if (!args.empty()) {
35
- // key = args[0].to_std_string();
36
- // }
37
- // auto symPtr = jspp::JsSymbol::for_global(key);
38
- // return jspp::AnyValue::from_symbol(symPtr);
39
- // }, "for");
40
-
41
- // // Implementation of Symbol.keyFor(sym)
42
- // inline auto keyForFn = jspp::AnyValue::make_function([](const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
43
- // if (args.empty() || !args[0].is_symbol()) {
44
- // throw jspp::Exception::make_exception("Symbol.keyFor requires a symbol argument", "TypeError");
45
- // }
46
-
47
- // jspp::JsSymbol* sym = args[0].as_symbol();
48
- // auto result = jspp::JsSymbol::key_for(sym);
49
-
50
- // if (result.has_value()) {
51
- // return jspp::AnyValue::make_string(result.value());
52
- // } else {
53
- // return jspp::AnyValue::make_undefined();
54
- // }
55
- // }, "keyFor");
56
-
57
- // // Attach static properties/methods to the Symbol object
58
- // struct SymbolInit {
59
- // SymbolInit() {
60
- // Symbol.set_own_property("iterator", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::iterator));
61
- // Symbol.set_own_property("for", forFn);
62
- // Symbol.set_own_property("keyFor", keyForFn);
63
- // }
64
- // } symbolInit;
8
+ // Define Symbol as a function
9
+ inline auto Symbol = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
10
+ {
11
+ std::string description = "";
12
+ if (!args.empty() && !args[0].is_undefined()) {
13
+ description = args[0].to_std_string();
14
+ }
15
+ return jspp::AnyValue::make_symbol(description); }, "Symbol", false);
16
+
17
+ // Initialize Symbol properties
18
+ struct SymbolInit
19
+ {
20
+ SymbolInit()
21
+ {
22
+ // Static methods
23
+ Symbol.define_data_property("for", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
24
+ {
25
+ std::string key = "";
26
+ if (!args.empty()) key = args[0].to_std_string();
27
+ return jspp::AnyValue::from_symbol(jspp::JsSymbol::for_global(key)); }, "for"));
28
+
29
+ Symbol.define_data_property("keyFor", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
30
+ {
31
+ if (args.empty() || !args[0].is_symbol()) throw jspp::Exception::make_exception("Symbol.keyFor requires a symbol", "TypeError");
32
+ auto sym = args[0].as_symbol();
33
+ auto key = jspp::JsSymbol::key_for(sym);
34
+ if (key.has_value()) return jspp::AnyValue::make_string(key.value());
35
+ return jspp::AnyValue::make_undefined(); }, "keyFor"));
36
+
37
+ // Well-known symbols
38
+ Symbol.define_data_property("iterator", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::iterator), false, false, false);
39
+ Symbol.define_data_property("asyncIterator", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::asyncIterator), false, false, false);
40
+ Symbol.define_data_property("hasInstance", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::hasInstance), false, false, false);
41
+ Symbol.define_data_property("isConcatSpreadable", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::isConcatSpreadable), false, false, false);
42
+ Symbol.define_data_property("match", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::match), false, false, false);
43
+ Symbol.define_data_property("matchAll", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::matchAll), false, false, false);
44
+ Symbol.define_data_property("replace", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::replace), false, false, false);
45
+ Symbol.define_data_property("search", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::search), false, false, false);
46
+ Symbol.define_data_property("species", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::species), false, false, false);
47
+ Symbol.define_data_property("split", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::split), false, false, false);
48
+ Symbol.define_data_property("toPrimitive", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::toPrimitive), false, false, false);
49
+ Symbol.define_data_property("toStringTag", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::toStringTag), false, false, false);
50
+ Symbol.define_data_property("unscopables", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::unscopables), false, false, false);
51
+ }
52
+ } symbolInit;