@ugo-studio/jspp 0.1.3 → 0.1.4

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 (69) hide show
  1. package/README.md +2 -2
  2. package/dist/analysis/scope.js +16 -4
  3. package/dist/analysis/typeAnalyzer.js +253 -20
  4. package/dist/ast/types.js +6 -0
  5. package/dist/cli.js +1 -2
  6. package/dist/core/codegen/class-handlers.js +127 -0
  7. package/dist/core/codegen/control-flow-handlers.js +464 -0
  8. package/dist/core/codegen/declaration-handlers.js +31 -14
  9. package/dist/core/codegen/expression-handlers.js +429 -117
  10. package/dist/core/codegen/function-handlers.js +91 -15
  11. package/dist/core/codegen/helpers.js +66 -2
  12. package/dist/core/codegen/index.js +17 -6
  13. package/dist/core/codegen/literal-handlers.js +3 -0
  14. package/dist/core/codegen/statement-handlers.js +133 -204
  15. package/dist/core/codegen/visitor.js +29 -3
  16. package/package.json +3 -3
  17. package/src/prelude/any_value.hpp +658 -634
  18. package/src/prelude/any_value_access.hpp +103 -0
  19. package/src/prelude/any_value_defines.hpp +151 -0
  20. package/src/prelude/any_value_helpers.hpp +246 -225
  21. package/src/prelude/exception.hpp +31 -0
  22. package/src/prelude/exception_helpers.hpp +49 -0
  23. package/src/prelude/index.hpp +18 -9
  24. package/src/prelude/library/console.hpp +13 -13
  25. package/src/prelude/library/error.hpp +111 -0
  26. package/src/prelude/library/global.hpp +15 -4
  27. package/src/prelude/library/performance.hpp +2 -2
  28. package/src/prelude/library/promise.hpp +121 -0
  29. package/src/prelude/library/symbol.hpp +3 -4
  30. package/src/prelude/library/timer.hpp +92 -0
  31. package/src/prelude/scheduler.hpp +145 -0
  32. package/src/prelude/types.hpp +10 -1
  33. package/src/prelude/utils/access.hpp +174 -0
  34. package/src/prelude/utils/log_any_value/array.hpp +245 -0
  35. package/src/prelude/utils/log_any_value/config.hpp +32 -0
  36. package/src/prelude/utils/log_any_value/function.hpp +37 -0
  37. package/src/prelude/utils/log_any_value/fwd.hpp +15 -0
  38. package/src/prelude/utils/log_any_value/helpers.hpp +62 -0
  39. package/src/prelude/utils/log_any_value/log_any_value.hpp +94 -0
  40. package/src/prelude/utils/log_any_value/object.hpp +119 -0
  41. package/src/prelude/utils/log_any_value/primitives.hpp +41 -0
  42. package/src/prelude/{operators.hpp → utils/operators.hpp} +29 -10
  43. package/src/prelude/{well_known_symbols.hpp → utils/well_known_symbols.hpp} +0 -1
  44. package/src/prelude/values/array.hpp +3 -2
  45. package/src/prelude/{descriptors.hpp → values/descriptors.hpp} +2 -2
  46. package/src/prelude/values/function.hpp +76 -51
  47. package/src/prelude/values/helpers/array.hpp +20 -11
  48. package/src/prelude/values/helpers/function.hpp +125 -77
  49. package/src/prelude/values/helpers/iterator.hpp +13 -7
  50. package/src/prelude/values/helpers/object.hpp +36 -6
  51. package/src/prelude/values/helpers/promise.hpp +181 -0
  52. package/src/prelude/values/helpers/string.hpp +3 -3
  53. package/src/prelude/values/helpers/symbol.hpp +2 -2
  54. package/src/prelude/values/iterator.hpp +13 -5
  55. package/src/prelude/values/object.hpp +6 -2
  56. package/src/prelude/values/promise.hpp +73 -0
  57. package/src/prelude/values/prototypes/array.hpp +16 -16
  58. package/src/prelude/values/prototypes/function.hpp +4 -4
  59. package/src/prelude/values/prototypes/iterator.hpp +11 -10
  60. package/src/prelude/values/prototypes/object.hpp +26 -0
  61. package/src/prelude/values/prototypes/promise.hpp +124 -0
  62. package/src/prelude/values/prototypes/string.hpp +26 -26
  63. package/src/prelude/values/prototypes/symbol.hpp +5 -3
  64. package/src/prelude/values/string.hpp +1 -1
  65. package/src/prelude/values/symbol.hpp +1 -1
  66. package/src/prelude/access.hpp +0 -91
  67. package/src/prelude/error.hpp +0 -31
  68. package/src/prelude/error_helpers.hpp +0 -59
  69. package/src/prelude/log_string.hpp +0 -407
@@ -1,77 +1,125 @@
1
- #pragma once
2
-
3
- #include <variant>
4
-
5
- #include "types.hpp"
6
- #include "values/function.hpp"
7
- #include "any_value.hpp"
8
- #include "values/prototypes/function.hpp"
9
-
10
- std::string jspp::JsFunction::to_std_string() const
11
- {
12
- if (is_generator)
13
- {
14
- return "function* " + name + "() { [native code] }";
15
- }
16
- return "function " + name + "() { [native code] }";
17
- }
18
-
19
- jspp::AnyValue jspp::JsFunction::call(const std::vector<AnyValue> &args)
20
- {
21
-
22
- if (std::function<AnyValue(const std::vector<AnyValue> &)> *func = std::get_if<0>(&callable))
23
- {
24
- return (*func)(args);
25
- }
26
- else if (std::function<jspp::JsIterator<jspp::AnyValue>(const std::vector<jspp::AnyValue> &)> *func = std::get_if<1>(&callable))
27
- {
28
- return AnyValue::from_iterator((*func)(args));
29
- }
30
- else
31
- {
32
- return AnyValue::make_undefined();
33
- }
34
- }
35
-
36
- jspp::AnyValue jspp::JsFunction::get_property(const std::string &key)
37
- {
38
- auto it = props.find(key);
39
- if (it == props.end())
40
- {
41
- // check prototype
42
- auto proto_it = FunctionPrototypes::get(key, this);
43
- if (proto_it.has_value())
44
- {
45
- return AnyValue::resolve_property_for_read(proto_it.value());
46
- }
47
- // not found
48
- return AnyValue::make_undefined();
49
- }
50
- return AnyValue::resolve_property_for_read(it->second);
51
- }
52
-
53
- jspp::AnyValue jspp::JsFunction::set_property(const std::string &key, const AnyValue &value)
54
- {
55
- // set prototype property if accessor descriptor
56
- auto proto_it = FunctionPrototypes::get(key, this);
57
- if (proto_it.has_value())
58
- {
59
- auto proto_value = proto_it.value();
60
- if (proto_value.is_accessor_descriptor())
61
- {
62
- return AnyValue::resolve_property_for_write(proto_value, value);
63
- }
64
- }
65
-
66
- // set own property
67
- auto it = props.find(key);
68
- if (it != props.end())
69
- {
70
- return AnyValue::resolve_property_for_write(it->second, value);
71
- }
72
- else
73
- {
74
- props[key] = value;
75
- return value;
76
- }
77
- }
1
+ #pragma once
2
+
3
+ #include <variant>
4
+
5
+ #include "types.hpp"
6
+ #include "values/function.hpp"
7
+ #include "any_value.hpp"
8
+ #include "values/prototypes/function.hpp"
9
+
10
+ std::string jspp::JsFunction::to_std_string() const
11
+ {
12
+ if (is_async) {
13
+ return "async function " + name + "() { [native code] }";
14
+ }
15
+ if (is_generator)
16
+ {
17
+ return "function* " + name + "() { [native code] }";
18
+ }
19
+ return "function " + name + "() { [native code] }";
20
+ }
21
+
22
+ jspp::AnyValue jspp::JsFunction::call(const AnyValue &thisVal, const std::vector<AnyValue> &args)
23
+ {
24
+ if (std::function<AnyValue(const AnyValue &, const std::vector<AnyValue> &)> *func = std::get_if<0>(&callable))
25
+ {
26
+ return (*func)(thisVal, args);
27
+ }
28
+ else if (std::function<jspp::JsIterator<jspp::AnyValue>(const AnyValue &, const std::vector<jspp::AnyValue> &)> *func = std::get_if<1>(&callable))
29
+ {
30
+ return AnyValue::from_iterator((*func)(thisVal, args));
31
+ }
32
+ else if (std::function<jspp::JsPromise(const AnyValue &, const std::vector<jspp::AnyValue> &)> *func = std::get_if<2>(&callable))
33
+ {
34
+ return AnyValue::make_promise((*func)(thisVal, args));
35
+ }
36
+ else
37
+ {
38
+ return AnyValue::make_undefined();
39
+ }
40
+ }
41
+
42
+ jspp::AnyValue jspp::JsFunction::get_property(const std::string &key, const AnyValue &thisVal)
43
+ {
44
+ auto it = props.find(key);
45
+ if (it == props.end())
46
+ {
47
+ // check explicit proto chain (e.g. for classes extending other classes)
48
+ if (proto && !(*proto).is_null() && !(*proto).is_undefined())
49
+ {
50
+ return (*proto).get_property_with_receiver(key, thisVal);
51
+ }
52
+
53
+ // check prototype (implicit Function.prototype)
54
+ auto proto_it = FunctionPrototypes::get(key, this);
55
+ if (proto_it.has_value())
56
+ {
57
+ return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
58
+ }
59
+ // not found
60
+ return AnyValue::make_undefined();
61
+ }
62
+ return AnyValue::resolve_property_for_read(it->second, thisVal, key);
63
+ }
64
+
65
+ jspp::AnyValue jspp::JsFunction::set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal)
66
+ {
67
+ // set prototype property if accessor descriptor
68
+ auto proto_it = FunctionPrototypes::get(key, this);
69
+ if (proto_it.has_value())
70
+ {
71
+ auto proto_value = proto_it.value();
72
+ if (proto_value.is_accessor_descriptor())
73
+ {
74
+ return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
75
+ }
76
+ if (proto_value.is_data_descriptor() && !proto_value.as_data_descriptor()->writable)
77
+ {
78
+ return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
79
+ }
80
+ }
81
+
82
+ // set own property
83
+ auto it = props.find(key);
84
+ if (it != props.end())
85
+ {
86
+ return AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
87
+ }
88
+ else
89
+ {
90
+ props[key] = value;
91
+ return value;
92
+ }
93
+ }
94
+
95
+ // AnyValue::construct implementation
96
+ const jspp::AnyValue jspp::AnyValue::construct(const std::vector<AnyValue> &args) const
97
+ {
98
+ if (!is_function())
99
+ {
100
+ throw Exception::make_exception(to_std_string() + " is not a constructor", "TypeError");
101
+ }
102
+
103
+ // 1. Get prototype
104
+ AnyValue proto = get_own_property("prototype");
105
+ // If prototype is not an object, default to a plain object (which ideally inherits from Object.prototype)
106
+ // Here we just make a plain object.
107
+ if (!proto.is_object())
108
+ {
109
+ proto = AnyValue::make_object({});
110
+ }
111
+
112
+ // 2. Create instance
113
+ AnyValue instance = AnyValue::make_object_with_proto({}, proto);
114
+
115
+ // 3. Call function
116
+ // We pass 'instance' as 'this'
117
+ AnyValue result = as_function()->call(instance, args);
118
+
119
+ // 4. Return result if object, else instance
120
+ if (result.is_object() || result.is_function() || result.is_array() || result.is_promise())
121
+ {
122
+ return result;
123
+ }
124
+ return instance;
125
+ }
@@ -11,12 +11,14 @@ std::string jspp::JsIterator<T>::to_std_string() const
11
11
  }
12
12
 
13
13
  template <typename T>
14
- jspp::JsIterator<T>::NextResult jspp::JsIterator<T>::next()
14
+ jspp::JsIterator<T>::NextResult jspp::JsIterator<T>::next(const T &val)
15
15
  {
16
16
  // If the generator is already finished or invalid, return {undefined, true}
17
17
  if (!handle || handle.done())
18
18
  return {std::nullopt, true};
19
19
 
20
+ handle.promise().input_value = val;
21
+
20
22
  // Resume execution until next co_yield or co_return
21
23
  handle.resume();
22
24
 
@@ -49,7 +51,7 @@ std::vector<std::optional<T>> jspp::JsIterator<T>::to_vector()
49
51
  }
50
52
 
51
53
  template <typename T>
52
- jspp::AnyValue jspp::JsIterator<T>::get_property(const std::string &key)
54
+ jspp::AnyValue jspp::JsIterator<T>::get_property(const std::string &key, const AnyValue &thisVal)
53
55
  {
54
56
  auto it = props.find(key);
55
57
  if (it == props.end())
@@ -60,18 +62,18 @@ jspp::AnyValue jspp::JsIterator<T>::get_property(const std::string &key)
60
62
  auto proto_it = IteratorPrototypes::get(key, this);
61
63
  if (proto_it.has_value())
62
64
  {
63
- return AnyValue::resolve_property_for_read(proto_it.value());
65
+ return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
64
66
  }
65
67
  }
66
68
  // prototype not found
67
69
  return jspp::AnyValue::make_undefined();
68
70
  }
69
71
 
70
- return jspp::AnyValue::resolve_property_for_read(it->second);
72
+ return jspp::AnyValue::resolve_property_for_read(it->second, thisVal, key);
71
73
  }
72
74
 
73
75
  template <typename T>
74
- jspp::AnyValue jspp::JsIterator<T>::set_property(const std::string &key, const AnyValue &value)
76
+ jspp::AnyValue jspp::JsIterator<T>::set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal)
75
77
  {
76
78
  // set prototype property if accessor descriptor
77
79
  if constexpr (std::is_same_v<T, AnyValue>)
@@ -82,7 +84,11 @@ jspp::AnyValue jspp::JsIterator<T>::set_property(const std::string &key, const A
82
84
  auto proto_value = proto_it.value();
83
85
  if (proto_value.is_accessor_descriptor())
84
86
  {
85
- return AnyValue::resolve_property_for_write(proto_it.value(), value);
87
+ return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
88
+ }
89
+ if (proto_value.is_data_descriptor() && !proto_value.as_data_descriptor()->writable)
90
+ {
91
+ return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
86
92
  }
87
93
  }
88
94
  }
@@ -91,7 +97,7 @@ jspp::AnyValue jspp::JsIterator<T>::set_property(const std::string &key, const A
91
97
  auto it = props.find(key);
92
98
  if (it != props.end())
93
99
  {
94
- return jspp::AnyValue::resolve_property_for_write(it->second, value);
100
+ return jspp::AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
95
101
  }
96
102
  else
97
103
  {
@@ -9,22 +9,52 @@ std::string jspp::JsObject::to_std_string() const
9
9
  return "[Object Object]";
10
10
  }
11
11
 
12
- jspp::AnyValue jspp::JsObject::get_property(const std::string &key)
12
+ jspp::AnyValue jspp::JsObject::get_property(const std::string &key, const AnyValue &thisVal)
13
13
  {
14
14
  auto it = props.find(key);
15
- if (it != props.end())
15
+ if (it == props.end())
16
16
  {
17
- return jspp::AnyValue::resolve_property_for_read(it->second);
17
+ // check prototype chain
18
+ if (proto && !(*proto).is_null() && !(*proto).is_undefined())
19
+ {
20
+ return (*proto).get_property_with_receiver(key, thisVal);
21
+ }
22
+
23
+ // check built-in prototype methods (Object.prototype)
24
+ // ideally these should be on the root prototype object, but for now we keep this fallback
25
+ auto proto_it = ObjectPrototypes::get(key, this);
26
+ if (proto_it.has_value())
27
+ {
28
+ return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
29
+ }
30
+ // not found
31
+ return AnyValue::make_undefined();
18
32
  }
19
- return jspp::AnyValue::make_undefined();
33
+ return AnyValue::resolve_property_for_read(it->second, thisVal, key);
20
34
  }
21
35
 
22
- jspp::AnyValue jspp::JsObject::set_property(const std::string &key, const AnyValue &value)
36
+ jspp::AnyValue jspp::JsObject::set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal)
23
37
  {
38
+ // set prototype property if accessor descriptor
39
+ auto proto_it = ObjectPrototypes::get(key, this);
40
+ if (proto_it.has_value())
41
+ {
42
+ auto proto_value = proto_it.value();
43
+ if (proto_value.is_accessor_descriptor())
44
+ {
45
+ return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
46
+ }
47
+ if (proto_value.is_data_descriptor() && !proto_value.as_data_descriptor()->writable)
48
+ {
49
+ return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
50
+ }
51
+ }
52
+
53
+ // set own property
24
54
  auto it = props.find(key);
25
55
  if (it != props.end())
26
56
  {
27
- return jspp::AnyValue::resolve_property_for_write(it->second, value);
57
+ return AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
28
58
  }
29
59
  else
30
60
  {
@@ -0,0 +1,181 @@
1
+ #pragma once
2
+
3
+ #include "types.hpp"
4
+ #include "values/promise.hpp"
5
+ #include "any_value.hpp"
6
+ #include "values/prototypes/promise.hpp"
7
+
8
+ namespace jspp {
9
+
10
+ inline PromiseState::PromiseState() : result(std::make_shared<AnyValue>(AnyValue::make_undefined())) {}
11
+
12
+ inline JsPromise::JsPromise() : state(std::make_shared<PromiseState>()) {}
13
+
14
+ inline void JsPromise::resolve(const AnyValue& value) {
15
+ if (state->status != PromiseStatus::Pending) return;
16
+
17
+ if (value.is_promise()) {
18
+ auto p = value.as_promise();
19
+ if (p->state == state) {
20
+ reject(AnyValue::make_string("TypeError: Chaining cycle detected for promise"));
21
+ return;
22
+ }
23
+
24
+ auto weak_state = std::weak_ptr<PromiseState>(state);
25
+
26
+ p->then(
27
+ [weak_state](AnyValue v) {
28
+ if (auto s = weak_state.lock()) {
29
+ JsPromise localP; localP.state = s;
30
+ localP.resolve(v);
31
+ }
32
+ },
33
+ [weak_state](AnyValue r) {
34
+ if (auto s = weak_state.lock()) {
35
+ JsPromise localP; localP.state = s;
36
+ localP.reject(r);
37
+ }
38
+ }
39
+ );
40
+ return;
41
+ }
42
+
43
+ state->status = PromiseStatus::Fulfilled;
44
+ *(state->result) = value;
45
+
46
+ // Schedule callbacks
47
+ auto callbacks = state->onFulfilled;
48
+ state->onFulfilled.clear();
49
+ state->onRejected.clear();
50
+
51
+ for (auto& cb : callbacks) {
52
+ jspp::Scheduler::instance().enqueue([cb, value]() {
53
+ cb(value);
54
+ });
55
+ }
56
+ }
57
+
58
+ inline void JsPromise::reject(const AnyValue& reason) {
59
+ if (state->status != PromiseStatus::Pending) return;
60
+ state->status = PromiseStatus::Rejected;
61
+ *(state->result) = reason;
62
+
63
+ auto callbacks = state->onRejected;
64
+ state->onFulfilled.clear();
65
+ state->onRejected.clear();
66
+
67
+ for (auto& cb : callbacks) {
68
+ jspp::Scheduler::instance().enqueue([cb, reason]() {
69
+ cb(reason);
70
+ });
71
+ }
72
+ }
73
+
74
+ inline void JsPromise::then(std::function<void(AnyValue)> onFulfilled, std::function<void(AnyValue)> onRejected) {
75
+ if (state->status == PromiseStatus::Fulfilled) {
76
+ if (onFulfilled) {
77
+ AnyValue val = *(state->result);
78
+ jspp::Scheduler::instance().enqueue([onFulfilled, val]() {
79
+ onFulfilled(val);
80
+ });
81
+ }
82
+ } else if (state->status == PromiseStatus::Rejected) {
83
+ if (onRejected) {
84
+ AnyValue val = *(state->result);
85
+ jspp::Scheduler::instance().enqueue([onRejected, val]() {
86
+ onRejected(val);
87
+ });
88
+ }
89
+ } else {
90
+ if (onFulfilled) state->onFulfilled.push_back(onFulfilled);
91
+ if (onRejected) state->onRejected.push_back(onRejected);
92
+ }
93
+ }
94
+
95
+ inline std::string JsPromise::to_std_string() const {
96
+ return "[object Promise]";
97
+ }
98
+
99
+ inline AnyValue JsPromise::get_property(const std::string& key, const AnyValue& thisVal) {
100
+ // Prototype lookup
101
+ auto proto_it = PromisePrototypes::get(key, const_cast<JsPromise*>(this));
102
+ if (proto_it.has_value()) {
103
+ return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
104
+ }
105
+
106
+ auto it = props.find(key);
107
+ if (it != props.end()) {
108
+ return AnyValue::resolve_property_for_read(it->second, thisVal, key);
109
+ }
110
+ return AnyValue::make_undefined();
111
+ }
112
+
113
+ inline AnyValue JsPromise::set_property(const std::string& key, const AnyValue& value, const AnyValue& thisVal) {
114
+ // Prototype check (if we had setters on prototype)
115
+
116
+ auto it = props.find(key);
117
+ if (it != props.end()) {
118
+ return AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
119
+ } else {
120
+ props[key] = value;
121
+ return value;
122
+ }
123
+ }
124
+
125
+ // --- Coroutine Methods ---
126
+
127
+ inline void JsPromisePromiseType::return_value(const AnyValue& val) {
128
+ promise.resolve(val);
129
+ }
130
+
131
+ inline void JsPromisePromiseType::unhandled_exception() {
132
+ try {
133
+ throw;
134
+ } catch (const Exception& e) {
135
+ promise.reject(*(e.data));
136
+ } catch (const std::exception& e) {
137
+ promise.reject(AnyValue::make_string(e.what()));
138
+ } catch (...) {
139
+ promise.reject(AnyValue::make_string("Unknown exception"));
140
+ }
141
+ }
142
+
143
+ inline auto JsPromisePromiseType::await_transform(const AnyValue& value) {
144
+ return AnyValueAwaiter{value};
145
+ }
146
+
147
+ // --- AnyValueAwaiter ---
148
+
149
+ inline bool AnyValueAwaiter::await_ready() {
150
+ if (!value.is_promise()) return true; // Non-promise values are ready immediately (for now)
151
+ // Always suspend for promises to ensure microtask interleaving, even if already resolved.
152
+ return false;
153
+ }
154
+
155
+ inline void AnyValueAwaiter::await_suspend(std::coroutine_handle<> h) {
156
+ if (!value.is_promise()) {
157
+ h.resume();
158
+ return;
159
+ }
160
+ auto p = value.as_promise();
161
+
162
+ // Attach resume to promise resolution.
163
+ // Since we are using the Scheduler in .then(), this will be queued.
164
+ p->then(
165
+ [h](AnyValue v) mutable { h.resume(); },
166
+ [h](AnyValue e) mutable { h.resume(); }
167
+ );
168
+ }
169
+
170
+ inline AnyValue AnyValueAwaiter::await_resume() {
171
+ if (!value.is_promise()) return value;
172
+ auto p = value.as_promise();
173
+ if (p->state->status == PromiseStatus::Fulfilled) {
174
+ return *(p->state->result);
175
+ } else {
176
+ // Throw exception to be caught by try/catch in coroutine
177
+ throw Exception(*(p->state->result));
178
+ }
179
+ }
180
+
181
+ }
@@ -3,7 +3,7 @@
3
3
  #include "types.hpp"
4
4
  #include "values/array.hpp"
5
5
  #include "values/string.hpp"
6
- #include "error.hpp"
6
+ #include "exception.hpp"
7
7
  #include "any_value.hpp"
8
8
  #include "values/prototypes/string.hpp"
9
9
 
@@ -22,13 +22,13 @@ jspp::JsIterator<jspp::AnyValue> jspp::JsString::get_iterator()
22
22
  co_return AnyValue::make_undefined();
23
23
  }
24
24
 
25
- jspp::AnyValue jspp::JsString::get_property(const std::string &key)
25
+ jspp::AnyValue jspp::JsString::get_property(const std::string &key, const AnyValue &thisVal)
26
26
  {
27
27
  // Check for prototype methods
28
28
  auto proto_fn = StringPrototypes::get(key, this);
29
29
  if (proto_fn.has_value())
30
30
  {
31
- return AnyValue::resolve_property_for_read(proto_fn.value());
31
+ return AnyValue::resolve_property_for_read(proto_fn.value(), thisVal, key);
32
32
  }
33
33
  // Handle character access by string index (e.g., "abc"["1"])
34
34
  if (JsArray::is_array_index(key))
@@ -10,13 +10,13 @@ std::string jspp::JsSymbol::to_std_string() const
10
10
  return "Symbol(" + description + ")";
11
11
  }
12
12
 
13
- jspp::AnyValue jspp::JsSymbol::get_property(const std::string &key)
13
+ jspp::AnyValue jspp::JsSymbol::get_property(const std::string &key, const AnyValue &thisVal)
14
14
  {
15
15
  // check prototype
16
16
  auto proto_it = SymbolPrototypes::get(key, this);
17
17
  if (proto_it.has_value())
18
18
  {
19
- return AnyValue::resolve_property_for_read(proto_it.value());
19
+ return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
20
20
  }
21
21
  // not found
22
22
  return AnyValue::make_undefined();
@@ -25,6 +25,7 @@ namespace jspp
25
25
  {
26
26
  std::optional<T> current_value;
27
27
  std::exception_ptr exception_;
28
+ T input_value;
28
29
 
29
30
  JsIterator get_return_object()
30
31
  {
@@ -40,10 +41,17 @@ namespace jspp
40
41
 
41
42
  // Handle co_yield
42
43
  template <typename From>
43
- std::suspend_always yield_value(From &&from)
44
+ auto yield_value(From &&from)
44
45
  {
45
46
  current_value = std::forward<From>(from);
46
- return {};
47
+ struct Awaiter
48
+ {
49
+ promise_type &p;
50
+ bool await_ready() { return false; }
51
+ void await_suspend(std::coroutine_handle<promise_type>) {}
52
+ T await_resume() { return p.input_value; }
53
+ };
54
+ return Awaiter{*this};
47
55
  }
48
56
 
49
57
  // Handle co_return
@@ -80,9 +88,9 @@ namespace jspp
80
88
  std::unordered_map<std::string, AnyValue> props;
81
89
 
82
90
  std::string to_std_string() const;
83
- NextResult next();
91
+ NextResult next(const T &val = T());
84
92
  std::vector<std::optional<T>> to_vector();
85
- AnyValue get_property(const std::string &key);
86
- AnyValue set_property(const std::string &key, const AnyValue &value);
93
+ AnyValue get_property(const std::string &key, const AnyValue &thisVal);
94
+ AnyValue set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal);
87
95
  };
88
96
  }
@@ -10,9 +10,13 @@ namespace jspp
10
10
  struct JsObject
11
11
  {
12
12
  std::map<std::string, AnyValue> props;
13
+ std::shared_ptr<AnyValue> proto;
14
+
15
+ JsObject() : proto(nullptr) {}
16
+ explicit JsObject(const std::map<std::string, AnyValue> &p, std::shared_ptr<AnyValue> pr = nullptr) : props(p), proto(pr) {}
13
17
 
14
18
  std::string to_std_string() const;
15
- AnyValue get_property(const std::string &key);
16
- AnyValue set_property(const std::string &key, const AnyValue &value);
19
+ AnyValue get_property(const std::string &key, const AnyValue &thisVal);
20
+ AnyValue set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal);
17
21
  };
18
22
  }