@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.
- package/README.md +2 -2
- package/dist/analysis/scope.js +16 -4
- package/dist/analysis/typeAnalyzer.js +253 -20
- package/dist/ast/types.js +6 -0
- package/dist/cli.js +1 -2
- package/dist/core/codegen/class-handlers.js +127 -0
- package/dist/core/codegen/control-flow-handlers.js +464 -0
- package/dist/core/codegen/declaration-handlers.js +31 -14
- package/dist/core/codegen/expression-handlers.js +429 -117
- package/dist/core/codegen/function-handlers.js +91 -15
- package/dist/core/codegen/helpers.js +66 -2
- package/dist/core/codegen/index.js +17 -6
- package/dist/core/codegen/literal-handlers.js +3 -0
- package/dist/core/codegen/statement-handlers.js +133 -204
- package/dist/core/codegen/visitor.js +29 -3
- package/package.json +3 -3
- package/src/prelude/any_value.hpp +658 -634
- package/src/prelude/any_value_access.hpp +103 -0
- package/src/prelude/any_value_defines.hpp +151 -0
- package/src/prelude/any_value_helpers.hpp +246 -225
- package/src/prelude/exception.hpp +31 -0
- package/src/prelude/exception_helpers.hpp +49 -0
- package/src/prelude/index.hpp +18 -9
- package/src/prelude/library/console.hpp +13 -13
- package/src/prelude/library/error.hpp +111 -0
- package/src/prelude/library/global.hpp +15 -4
- package/src/prelude/library/performance.hpp +2 -2
- package/src/prelude/library/promise.hpp +121 -0
- package/src/prelude/library/symbol.hpp +3 -4
- package/src/prelude/library/timer.hpp +92 -0
- package/src/prelude/scheduler.hpp +145 -0
- package/src/prelude/types.hpp +10 -1
- package/src/prelude/utils/access.hpp +174 -0
- package/src/prelude/utils/log_any_value/array.hpp +245 -0
- package/src/prelude/utils/log_any_value/config.hpp +32 -0
- package/src/prelude/utils/log_any_value/function.hpp +37 -0
- package/src/prelude/utils/log_any_value/fwd.hpp +15 -0
- package/src/prelude/utils/log_any_value/helpers.hpp +62 -0
- package/src/prelude/utils/log_any_value/log_any_value.hpp +94 -0
- package/src/prelude/utils/log_any_value/object.hpp +119 -0
- package/src/prelude/utils/log_any_value/primitives.hpp +41 -0
- package/src/prelude/{operators.hpp → utils/operators.hpp} +29 -10
- package/src/prelude/{well_known_symbols.hpp → utils/well_known_symbols.hpp} +0 -1
- package/src/prelude/values/array.hpp +3 -2
- package/src/prelude/{descriptors.hpp → values/descriptors.hpp} +2 -2
- package/src/prelude/values/function.hpp +76 -51
- package/src/prelude/values/helpers/array.hpp +20 -11
- package/src/prelude/values/helpers/function.hpp +125 -77
- package/src/prelude/values/helpers/iterator.hpp +13 -7
- package/src/prelude/values/helpers/object.hpp +36 -6
- package/src/prelude/values/helpers/promise.hpp +181 -0
- package/src/prelude/values/helpers/string.hpp +3 -3
- package/src/prelude/values/helpers/symbol.hpp +2 -2
- package/src/prelude/values/iterator.hpp +13 -5
- package/src/prelude/values/object.hpp +6 -2
- package/src/prelude/values/promise.hpp +73 -0
- package/src/prelude/values/prototypes/array.hpp +16 -16
- package/src/prelude/values/prototypes/function.hpp +4 -4
- package/src/prelude/values/prototypes/iterator.hpp +11 -10
- package/src/prelude/values/prototypes/object.hpp +26 -0
- package/src/prelude/values/prototypes/promise.hpp +124 -0
- package/src/prelude/values/prototypes/string.hpp +26 -26
- package/src/prelude/values/prototypes/symbol.hpp +5 -3
- package/src/prelude/values/string.hpp +1 -1
- package/src/prelude/values/symbol.hpp +1 -1
- package/src/prelude/access.hpp +0 -91
- package/src/prelude/error.hpp +0 -31
- package/src/prelude/error_helpers.hpp +0 -59
- package/src/prelude/log_string.hpp +0 -407
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include <vector>
|
|
5
|
+
#include <functional>
|
|
6
|
+
#include <memory>
|
|
7
|
+
#include <variant>
|
|
8
|
+
#include <coroutine>
|
|
9
|
+
#include <unordered_map>
|
|
10
|
+
#include <string>
|
|
11
|
+
|
|
12
|
+
namespace jspp
|
|
13
|
+
{
|
|
14
|
+
// Forward declaration of AnyValue
|
|
15
|
+
class AnyValue;
|
|
16
|
+
|
|
17
|
+
enum class PromiseStatus { Pending, Fulfilled, Rejected };
|
|
18
|
+
|
|
19
|
+
struct PromiseState
|
|
20
|
+
{
|
|
21
|
+
PromiseStatus status = PromiseStatus::Pending;
|
|
22
|
+
std::shared_ptr<AnyValue> result; // Value if fulfilled, reason if rejected
|
|
23
|
+
std::vector<std::function<void(AnyValue)>> onFulfilled;
|
|
24
|
+
std::vector<std::function<void(AnyValue)>> onRejected;
|
|
25
|
+
|
|
26
|
+
PromiseState(); // Defined in helpers
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
struct JsPromisePromiseType; // Forward declaration
|
|
30
|
+
|
|
31
|
+
struct JsPromise
|
|
32
|
+
{
|
|
33
|
+
using promise_type = JsPromisePromiseType;
|
|
34
|
+
|
|
35
|
+
std::shared_ptr<PromiseState> state;
|
|
36
|
+
std::unordered_map<std::string, AnyValue> props;
|
|
37
|
+
|
|
38
|
+
JsPromise();
|
|
39
|
+
|
|
40
|
+
// --- Promise Logic ---
|
|
41
|
+
void resolve(const AnyValue& value);
|
|
42
|
+
void reject(const AnyValue& reason);
|
|
43
|
+
void then(std::function<void(AnyValue)> onFulfilled, std::function<void(AnyValue)> onRejected = nullptr);
|
|
44
|
+
|
|
45
|
+
// --- Methods ---
|
|
46
|
+
std::string to_std_string() const;
|
|
47
|
+
AnyValue get_property(const std::string& key, const AnyValue& thisVal);
|
|
48
|
+
AnyValue set_property(const std::string& key, const AnyValue& value, const AnyValue& thisVal);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
struct JsPromisePromiseType {
|
|
52
|
+
JsPromise promise;
|
|
53
|
+
|
|
54
|
+
JsPromise get_return_object() { return promise; }
|
|
55
|
+
std::suspend_never initial_suspend() { return {}; }
|
|
56
|
+
std::suspend_never final_suspend() noexcept { return {}; }
|
|
57
|
+
|
|
58
|
+
void return_value(const AnyValue& val);
|
|
59
|
+
|
|
60
|
+
void unhandled_exception();
|
|
61
|
+
|
|
62
|
+
// await_transform for AnyValue
|
|
63
|
+
auto await_transform(const AnyValue& value);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Awaiter for AnyValue
|
|
67
|
+
struct AnyValueAwaiter {
|
|
68
|
+
const AnyValue& value; // Reference to the value being awaited
|
|
69
|
+
bool await_ready();
|
|
70
|
+
void await_suspend(std::coroutine_handle<> h);
|
|
71
|
+
AnyValue await_resume();
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
#include "types.hpp"
|
|
4
4
|
#include "values/array.hpp"
|
|
5
5
|
#include "any_value.hpp"
|
|
6
|
-
#include "
|
|
7
|
-
#include "operators.hpp"
|
|
6
|
+
#include "exception.hpp"
|
|
7
|
+
#include "utils/operators.hpp"
|
|
8
8
|
#include <algorithm>
|
|
9
9
|
#include <vector>
|
|
10
10
|
|
|
@@ -15,9 +15,9 @@ namespace jspp
|
|
|
15
15
|
inline std::optional<AnyValue> get(const std::string &key, JsArray *self)
|
|
16
16
|
{
|
|
17
17
|
// --- toString() method ---
|
|
18
|
-
if (key == "toString"
|
|
18
|
+
if (key == "toString" )
|
|
19
19
|
{
|
|
20
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &_) -> AnyValue
|
|
20
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &_) -> AnyValue
|
|
21
21
|
{ return AnyValue::make_string(self->to_std_string()); },
|
|
22
22
|
key);
|
|
23
23
|
}
|
|
@@ -25,7 +25,7 @@ namespace jspp
|
|
|
25
25
|
// --- [Symbol.iterator]() method ---
|
|
26
26
|
if (key == WellKnownSymbols::iterator->key)
|
|
27
27
|
{
|
|
28
|
-
return AnyValue::make_generator([self](const std::vector<AnyValue> &_) -> AnyValue
|
|
28
|
+
return AnyValue::make_generator([self](const AnyValue &thisVal, const std::vector<AnyValue> &_) -> AnyValue
|
|
29
29
|
{ return AnyValue::from_iterator(self->get_iterator()); },
|
|
30
30
|
key);
|
|
31
31
|
}
|
|
@@ -33,12 +33,12 @@ namespace jspp
|
|
|
33
33
|
// --- length property ---
|
|
34
34
|
if (key == "length")
|
|
35
35
|
{
|
|
36
|
-
auto getter = [self](const std::vector<AnyValue> &args) -> AnyValue
|
|
36
|
+
auto getter = [self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
37
37
|
{
|
|
38
38
|
return AnyValue::make_number(self->length);
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
auto setter = [self](const std::vector<AnyValue> &args) -> AnyValue
|
|
41
|
+
auto setter = [self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
42
42
|
{
|
|
43
43
|
if (args.empty())
|
|
44
44
|
{
|
|
@@ -50,7 +50,7 @@ namespace jspp
|
|
|
50
50
|
|
|
51
51
|
if (new_len_double < 0 || std::isnan(new_len_double) || std::isinf(new_len_double) || new_len_double != static_cast<uint64_t>(new_len_double))
|
|
52
52
|
{
|
|
53
|
-
throw
|
|
53
|
+
throw Exception::make_exception("Invalid array length", "RangeError");
|
|
54
54
|
}
|
|
55
55
|
uint64_t new_len = static_cast<uint64_t>(new_len_double);
|
|
56
56
|
|
|
@@ -86,7 +86,7 @@ namespace jspp
|
|
|
86
86
|
// --- push() method ---
|
|
87
87
|
if (key == "push")
|
|
88
88
|
{
|
|
89
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
89
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
90
90
|
{
|
|
91
91
|
for (const auto &arg : args)
|
|
92
92
|
{
|
|
@@ -99,7 +99,7 @@ namespace jspp
|
|
|
99
99
|
// --- pop() method ---
|
|
100
100
|
if (key == "pop")
|
|
101
101
|
{
|
|
102
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
102
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
103
103
|
{
|
|
104
104
|
if (self->length == 0)
|
|
105
105
|
{
|
|
@@ -124,7 +124,7 @@ namespace jspp
|
|
|
124
124
|
// --- shift() method ---
|
|
125
125
|
if (key == "shift")
|
|
126
126
|
{
|
|
127
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
127
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
128
128
|
{
|
|
129
129
|
if (self->length == 0)
|
|
130
130
|
{
|
|
@@ -155,7 +155,7 @@ namespace jspp
|
|
|
155
155
|
// --- unshift() method ---
|
|
156
156
|
if (key == "unshift")
|
|
157
157
|
{
|
|
158
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
158
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
159
159
|
{
|
|
160
160
|
size_t args_count = args.size();
|
|
161
161
|
if (args_count == 0)
|
|
@@ -182,7 +182,7 @@ namespace jspp
|
|
|
182
182
|
// --- join() method ---
|
|
183
183
|
if (key == "join")
|
|
184
184
|
{
|
|
185
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
185
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
186
186
|
{
|
|
187
187
|
std::string sep = ",";
|
|
188
188
|
if (!args.empty() && !args[0].is_undefined())
|
|
@@ -210,11 +210,11 @@ namespace jspp
|
|
|
210
210
|
// --- forEach() method ---
|
|
211
211
|
if (key == "forEach")
|
|
212
212
|
{
|
|
213
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
213
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
214
214
|
{
|
|
215
215
|
if (args.empty() || !args[0].is_function())
|
|
216
216
|
{
|
|
217
|
-
throw
|
|
217
|
+
throw Exception::make_exception("callback is not a function", "TypeError");
|
|
218
218
|
}
|
|
219
219
|
auto callback = args[0].as_function();
|
|
220
220
|
for (uint64_t i = 0; i < self->length; ++i)
|
|
@@ -222,7 +222,7 @@ namespace jspp
|
|
|
222
222
|
AnyValue val = self->get_property(static_cast<uint32_t>(i));
|
|
223
223
|
if (!val.is_undefined())
|
|
224
224
|
{ // forEach skips empty slots
|
|
225
|
-
callback->call({val, AnyValue::make_number(i)});
|
|
225
|
+
callback->call(thisVal, {val, AnyValue::make_number(i)});
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
228
|
return AnyValue::make_undefined(); },
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
#include "types.hpp"
|
|
4
4
|
#include "values/function.hpp"
|
|
5
5
|
#include "any_value.hpp"
|
|
6
|
-
#include "
|
|
7
|
-
#include "operators.hpp"
|
|
6
|
+
#include "exception.hpp"
|
|
7
|
+
#include "utils/operators.hpp"
|
|
8
8
|
|
|
9
9
|
namespace jspp
|
|
10
10
|
{
|
|
@@ -13,9 +13,9 @@ namespace jspp
|
|
|
13
13
|
inline std::optional<AnyValue> get(const std::string &key, JsFunction *self)
|
|
14
14
|
{
|
|
15
15
|
// --- toString() method ---
|
|
16
|
-
if (key == "toString"
|
|
16
|
+
if (key == "toString" )
|
|
17
17
|
{
|
|
18
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &_) -> AnyValue
|
|
18
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &_) -> AnyValue
|
|
19
19
|
{ return AnyValue::make_string(self->to_std_string()); },
|
|
20
20
|
key);
|
|
21
21
|
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
#include "types.hpp"
|
|
4
4
|
#include "values/iterator.hpp"
|
|
5
5
|
#include "any_value.hpp"
|
|
6
|
-
#include "
|
|
7
|
-
#include "operators.hpp"
|
|
6
|
+
#include "exception.hpp"
|
|
7
|
+
#include "utils/operators.hpp"
|
|
8
8
|
|
|
9
9
|
namespace jspp
|
|
10
10
|
{
|
|
@@ -13,17 +13,17 @@ namespace jspp
|
|
|
13
13
|
inline std::optional<AnyValue> get(const std::string &key, JsIterator<AnyValue> *self)
|
|
14
14
|
{
|
|
15
15
|
// --- toString() method ---
|
|
16
|
-
if (key == "toString"
|
|
16
|
+
if (key == "toString" )
|
|
17
17
|
{
|
|
18
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &) -> AnyValue
|
|
18
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &) -> AnyValue
|
|
19
19
|
{ return AnyValue::make_string(self->to_std_string()); },
|
|
20
20
|
key);
|
|
21
21
|
}
|
|
22
22
|
// --- [Symbol.iterator]() method ---
|
|
23
23
|
if (key == WellKnownSymbols::iterator->key)
|
|
24
24
|
{
|
|
25
|
-
return AnyValue::
|
|
26
|
-
|
|
25
|
+
return AnyValue::make_generator([self](const AnyValue &thisVal, const std::vector<AnyValue> &) -> AnyValue
|
|
26
|
+
{
|
|
27
27
|
// An iterator's iterator is itself.
|
|
28
28
|
// We need to return an AnyValue that holds a shared_ptr to this JsIterator.
|
|
29
29
|
// Since we only have a raw pointer `self`, we can't directly make a new shared_ptr.
|
|
@@ -32,21 +32,22 @@ namespace jspp
|
|
|
32
32
|
// A better solution might involve passing a shared_ptr to `self` into the prototype getters.
|
|
33
33
|
// For now, let's assume the object containing the iterator is alive.
|
|
34
34
|
return AnyValue::from_iterator_ref(self); },
|
|
35
|
-
|
|
35
|
+
key);
|
|
36
36
|
}
|
|
37
37
|
// --- next() method ---
|
|
38
38
|
if (key == "next")
|
|
39
39
|
{
|
|
40
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &) -> AnyValue
|
|
40
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
41
41
|
{
|
|
42
|
-
|
|
42
|
+
AnyValue val = args.empty() ? AnyValue::make_undefined() : args[0];
|
|
43
|
+
auto res = self->next(val);
|
|
43
44
|
return AnyValue::make_object({{"value",res.value.value_or(AnyValue::make_undefined())},{"done",AnyValue::make_boolean(res.done)},}); },
|
|
44
45
|
key);
|
|
45
46
|
}
|
|
46
47
|
// --- toArray() method ---
|
|
47
48
|
if (key == "toArray")
|
|
48
49
|
{
|
|
49
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &) -> AnyValue
|
|
50
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &) -> AnyValue
|
|
50
51
|
{ return AnyValue::make_array(self->to_vector()); },
|
|
51
52
|
key);
|
|
52
53
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include "values/object.hpp"
|
|
5
|
+
#include "any_value.hpp"
|
|
6
|
+
#include "exception.hpp"
|
|
7
|
+
#include "utils/operators.hpp"
|
|
8
|
+
|
|
9
|
+
namespace jspp
|
|
10
|
+
{
|
|
11
|
+
namespace ObjectPrototypes
|
|
12
|
+
{
|
|
13
|
+
inline std::optional<AnyValue> get(const std::string &key, JsObject *self)
|
|
14
|
+
{
|
|
15
|
+
// --- toString() method ---
|
|
16
|
+
if (key == "toString" )
|
|
17
|
+
{
|
|
18
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &_) -> AnyValue
|
|
19
|
+
{ return AnyValue::make_string(self->to_std_string()); },
|
|
20
|
+
key);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return std::nullopt;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include "values/promise.hpp"
|
|
5
|
+
#include "any_value.hpp"
|
|
6
|
+
|
|
7
|
+
namespace jspp {
|
|
8
|
+
namespace PromisePrototypes {
|
|
9
|
+
inline std::optional<AnyValue> get(const std::string& key, JsPromise* self) {
|
|
10
|
+
|
|
11
|
+
if (key == "then") {
|
|
12
|
+
return AnyValue::make_function([self](const AnyValue& thisVal, const std::vector<AnyValue>& args) -> AnyValue {
|
|
13
|
+
AnyValue onFulfilled = (args.size() > 0 && args[0].is_function()) ? args[0] : AnyValue::make_undefined();
|
|
14
|
+
AnyValue onRejected = (args.size() > 1 && args[1].is_function()) ? args[1] : AnyValue::make_undefined();
|
|
15
|
+
|
|
16
|
+
// "then" returns a new Promise
|
|
17
|
+
JsPromise newPromise;
|
|
18
|
+
AnyValue newPromiseVal = AnyValue::make_promise(newPromise);
|
|
19
|
+
|
|
20
|
+
// Capture shared pointer to the new promise's state to keep it alive and modify it
|
|
21
|
+
auto newPromiseState = newPromise.state;
|
|
22
|
+
// Helper wrapper to interact with state
|
|
23
|
+
auto resolveNew = [newPromiseState](const AnyValue& v) {
|
|
24
|
+
JsPromise p; p.state = newPromiseState;
|
|
25
|
+
p.resolve(v);
|
|
26
|
+
};
|
|
27
|
+
auto rejectNew = [newPromiseState](const AnyValue& r) {
|
|
28
|
+
JsPromise p; p.state = newPromiseState;
|
|
29
|
+
p.reject(r);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
// Resolve handler
|
|
34
|
+
auto resolveHandler = [resolveNew, rejectNew, onFulfilled](AnyValue val) mutable {
|
|
35
|
+
if (onFulfilled.is_function()) {
|
|
36
|
+
try {
|
|
37
|
+
auto res = onFulfilled.as_function()->call(AnyValue::make_undefined(), {val});
|
|
38
|
+
if (res.is_promise()) {
|
|
39
|
+
// Chaining: newPromise follows res
|
|
40
|
+
auto chained = res.as_promise();
|
|
41
|
+
chained->then(
|
|
42
|
+
[resolveNew](AnyValue v) { resolveNew(v); },
|
|
43
|
+
[rejectNew](AnyValue e) { rejectNew(e); }
|
|
44
|
+
);
|
|
45
|
+
} else {
|
|
46
|
+
resolveNew(res);
|
|
47
|
+
}
|
|
48
|
+
} catch (const Exception& e) {
|
|
49
|
+
rejectNew(*e.data);
|
|
50
|
+
} catch (...) {
|
|
51
|
+
rejectNew(AnyValue::make_string("Unknown error"));
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
resolveNew(val); // Fallthrough
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Reject handler
|
|
59
|
+
auto rejectHandler = [resolveNew, rejectNew, onRejected](AnyValue reason) mutable {
|
|
60
|
+
if (onRejected.is_function()) {
|
|
61
|
+
try {
|
|
62
|
+
auto res = onRejected.as_function()->call(AnyValue::make_undefined(), {reason});
|
|
63
|
+
if (res.is_promise()) {
|
|
64
|
+
auto chained = res.as_promise();
|
|
65
|
+
chained->then(
|
|
66
|
+
[resolveNew](AnyValue v) { resolveNew(v); },
|
|
67
|
+
[rejectNew](AnyValue e) { rejectNew(e); }
|
|
68
|
+
);
|
|
69
|
+
} else {
|
|
70
|
+
resolveNew(res); // Recovered
|
|
71
|
+
}
|
|
72
|
+
} catch (const Exception& e) {
|
|
73
|
+
rejectNew(*e.data);
|
|
74
|
+
} catch (...) {
|
|
75
|
+
rejectNew(AnyValue::make_string("Unknown error"));
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
rejectNew(reason); // Fallthrough
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
self->then(resolveHandler, rejectHandler);
|
|
83
|
+
return newPromiseVal;
|
|
84
|
+
}, "then");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (key == "catch") {
|
|
88
|
+
return AnyValue::make_function([self](const AnyValue& thisVal, const std::vector<AnyValue>& args) -> AnyValue {
|
|
89
|
+
// catch(onRejected) is then(undefined, onRejected)
|
|
90
|
+
AnyValue onRejected = (args.size() > 0 && args[0].is_function()) ? args[0] : AnyValue::make_undefined();
|
|
91
|
+
return thisVal.get_own_property("then").as_function()->call(thisVal, {AnyValue::make_undefined(), onRejected});
|
|
92
|
+
}, "catch");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (key == "finally") {
|
|
96
|
+
return AnyValue::make_function([self](const AnyValue& thisVal, const std::vector<AnyValue>& args) -> AnyValue {
|
|
97
|
+
AnyValue onFinally = (args.size() > 0 && args[0].is_function()) ? args[0] : AnyValue::make_undefined();
|
|
98
|
+
|
|
99
|
+
// finally(onFinally) returns a promise that passes through value/reason,
|
|
100
|
+
// but executes onFinally first.
|
|
101
|
+
|
|
102
|
+
return thisVal.get_own_property("then").as_function()->call(thisVal, {
|
|
103
|
+
AnyValue::make_function([onFinally](const AnyValue&, const std::vector<AnyValue>& args) -> AnyValue {
|
|
104
|
+
AnyValue val = args.empty() ? AnyValue::make_undefined() : args[0];
|
|
105
|
+
if (onFinally.is_function()) {
|
|
106
|
+
onFinally.as_function()->call(AnyValue::make_undefined(), {});
|
|
107
|
+
}
|
|
108
|
+
return val;
|
|
109
|
+
}, ""),
|
|
110
|
+
AnyValue::make_function([onFinally](const AnyValue&, const std::vector<AnyValue>& args) -> AnyValue {
|
|
111
|
+
AnyValue reason = args.empty() ? AnyValue::make_undefined() : args[0];
|
|
112
|
+
if (onFinally.is_function()) {
|
|
113
|
+
onFinally.as_function()->call(AnyValue::make_undefined(), {});
|
|
114
|
+
}
|
|
115
|
+
throw Exception(reason);
|
|
116
|
+
}, "")
|
|
117
|
+
});
|
|
118
|
+
}, "finally");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return std::nullopt;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#include "types.hpp"
|
|
4
4
|
#include "values/string.hpp" // Make sure this is included
|
|
5
5
|
#include "any_value.hpp"
|
|
6
|
-
#include "operators.hpp"
|
|
6
|
+
#include "utils/operators.hpp"
|
|
7
7
|
#include <optional>
|
|
8
8
|
#include <string>
|
|
9
9
|
#include <vector>
|
|
@@ -19,9 +19,9 @@ namespace jspp
|
|
|
19
19
|
inline std::optional<AnyValue> get(const std::string &key, JsString *self)
|
|
20
20
|
{
|
|
21
21
|
// --- toString() & valueOf() ---
|
|
22
|
-
if (key == "toString"
|
|
22
|
+
if (key == "toString" || key == "valueOf")
|
|
23
23
|
{
|
|
24
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
24
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
25
25
|
{ return AnyValue::make_string(self->value); },
|
|
26
26
|
key);
|
|
27
27
|
}
|
|
@@ -29,7 +29,7 @@ namespace jspp
|
|
|
29
29
|
// --- [Symbol.iterator]() method ---
|
|
30
30
|
if (key == WellKnownSymbols::iterator->key)
|
|
31
31
|
{
|
|
32
|
-
return AnyValue::make_generator([self](const std::vector<AnyValue> &_) -> AnyValue
|
|
32
|
+
return AnyValue::make_generator([self](const AnyValue &thisVal, const std::vector<AnyValue> &_) -> AnyValue
|
|
33
33
|
{ return AnyValue::from_iterator(self->get_iterator()); },
|
|
34
34
|
key);
|
|
35
35
|
}
|
|
@@ -37,9 +37,9 @@ namespace jspp
|
|
|
37
37
|
// --- length property ---
|
|
38
38
|
if (key == "length")
|
|
39
39
|
{
|
|
40
|
-
return AnyValue::make_accessor_descriptor([self](const std::vector<AnyValue>) -> AnyValue
|
|
40
|
+
return AnyValue::make_accessor_descriptor([self](const AnyValue &thisVal, const std::vector<AnyValue>) -> AnyValue
|
|
41
41
|
{ return AnyValue::make_number(self->value.length()); },
|
|
42
|
-
[self](const std::vector<AnyValue>) -> AnyValue
|
|
42
|
+
[self](const AnyValue &thisVal, const std::vector<AnyValue>) -> AnyValue
|
|
43
43
|
{ return AnyValue::make_undefined(); },
|
|
44
44
|
false,
|
|
45
45
|
false);
|
|
@@ -48,7 +48,7 @@ namespace jspp
|
|
|
48
48
|
// --- charAt(pos) ---
|
|
49
49
|
if (key == "charAt")
|
|
50
50
|
{
|
|
51
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
51
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
52
52
|
{
|
|
53
53
|
double pos = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
|
|
54
54
|
int index = static_cast<int>(pos);
|
|
@@ -62,7 +62,7 @@ namespace jspp
|
|
|
62
62
|
// --- concat(str1, str2, ...) ---
|
|
63
63
|
if (key == "concat")
|
|
64
64
|
{
|
|
65
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
65
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
66
66
|
{
|
|
67
67
|
std::string result = self->value;
|
|
68
68
|
for (const auto& arg : args)
|
|
@@ -76,7 +76,7 @@ namespace jspp
|
|
|
76
76
|
// --- endsWith(searchString, endPosition) ---
|
|
77
77
|
if (key == "endsWith")
|
|
78
78
|
{
|
|
79
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
79
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
80
80
|
{
|
|
81
81
|
if(args.empty()) return AnyValue::make_boolean(false);
|
|
82
82
|
std::string search = args[0].to_std_string();
|
|
@@ -92,7 +92,7 @@ namespace jspp
|
|
|
92
92
|
// --- includes(searchString, position) ---
|
|
93
93
|
if (key == "includes")
|
|
94
94
|
{
|
|
95
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
95
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
96
96
|
{
|
|
97
97
|
if(args.empty()) return AnyValue::make_boolean(false);
|
|
98
98
|
std::string search = args[0].to_std_string();
|
|
@@ -105,7 +105,7 @@ namespace jspp
|
|
|
105
105
|
// --- indexOf(searchString, position) ---
|
|
106
106
|
if (key == "indexOf")
|
|
107
107
|
{
|
|
108
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
108
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
109
109
|
{
|
|
110
110
|
if (args.empty()) return AnyValue::make_number(-1);
|
|
111
111
|
std::string search = args[0].to_std_string();
|
|
@@ -118,7 +118,7 @@ namespace jspp
|
|
|
118
118
|
// --- lastIndexOf(searchString, position) ---
|
|
119
119
|
if (key == "lastIndexOf")
|
|
120
120
|
{
|
|
121
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
121
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
122
122
|
{
|
|
123
123
|
if (args.empty()) return AnyValue::make_number(-1);
|
|
124
124
|
std::string search = args[0].to_std_string();
|
|
@@ -131,7 +131,7 @@ namespace jspp
|
|
|
131
131
|
// --- padEnd(targetLength, padString) ---
|
|
132
132
|
if (key == "padEnd")
|
|
133
133
|
{
|
|
134
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
134
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
135
135
|
{
|
|
136
136
|
size_t target_length = args.empty() ? 0 : static_cast<size_t>(Operators_Private::ToNumber(args[0]));
|
|
137
137
|
if (self->value.length() >= target_length) return AnyValue::make_string(self->value);
|
|
@@ -148,7 +148,7 @@ namespace jspp
|
|
|
148
148
|
// --- padStart(targetLength, padString) ---
|
|
149
149
|
if (key == "padStart")
|
|
150
150
|
{
|
|
151
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
151
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
152
152
|
{
|
|
153
153
|
size_t target_length = args.empty() ? 0 : static_cast<size_t>(Operators_Private::ToNumber(args[0]));
|
|
154
154
|
if (self->value.length() >= target_length) return AnyValue::make_string(self->value);
|
|
@@ -165,7 +165,7 @@ namespace jspp
|
|
|
165
165
|
// --- repeat(count) ---
|
|
166
166
|
if (key == "repeat")
|
|
167
167
|
{
|
|
168
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
168
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
169
169
|
{
|
|
170
170
|
double count = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
|
|
171
171
|
if (count < 0) {
|
|
@@ -184,7 +184,7 @@ namespace jspp
|
|
|
184
184
|
// --- replace(substr, newSubstr) ---
|
|
185
185
|
if (key == "replace")
|
|
186
186
|
{
|
|
187
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
187
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
188
188
|
{
|
|
189
189
|
if (args.size() < 2) return AnyValue::make_string(self->value);
|
|
190
190
|
std::string search = args[0].to_std_string();
|
|
@@ -202,7 +202,7 @@ namespace jspp
|
|
|
202
202
|
// --- replaceAll(substr, newSubstr) ---
|
|
203
203
|
if (key == "replaceAll")
|
|
204
204
|
{
|
|
205
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
205
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
206
206
|
{
|
|
207
207
|
if (args.size() < 2) return AnyValue::make_string(self->value);
|
|
208
208
|
std::string search = args[0].to_std_string();
|
|
@@ -222,7 +222,7 @@ namespace jspp
|
|
|
222
222
|
// --- slice(beginIndex, endIndex) ---
|
|
223
223
|
if (key == "slice")
|
|
224
224
|
{
|
|
225
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
225
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
226
226
|
{
|
|
227
227
|
int len = self->value.length();
|
|
228
228
|
int start = args.empty() ? 0 : Operators_Private::ToInt32(args[0]);
|
|
@@ -242,7 +242,7 @@ namespace jspp
|
|
|
242
242
|
// --- split(separator) ---
|
|
243
243
|
if (key == "split")
|
|
244
244
|
{
|
|
245
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
245
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
246
246
|
{
|
|
247
247
|
std::string separator = (args.empty() || args[0].is_undefined()) ? "" : args[0].to_std_string();
|
|
248
248
|
std::vector<std::optional<AnyValue>> result_vec;
|
|
@@ -267,7 +267,7 @@ namespace jspp
|
|
|
267
267
|
// --- startsWith(searchString, position) ---
|
|
268
268
|
if (key == "startsWith")
|
|
269
269
|
{
|
|
270
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
270
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
271
271
|
{
|
|
272
272
|
if(args.empty()) return AnyValue::make_boolean(false);
|
|
273
273
|
std::string search = args[0].to_std_string();
|
|
@@ -281,7 +281,7 @@ namespace jspp
|
|
|
281
281
|
// --- substring(indexStart, indexEnd) ---
|
|
282
282
|
if (key == "substring")
|
|
283
283
|
{
|
|
284
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
284
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
285
285
|
{
|
|
286
286
|
int len = self->value.length();
|
|
287
287
|
int start = args.empty() ? 0 : Operators_Private::ToInt32(args[0]);
|
|
@@ -302,7 +302,7 @@ namespace jspp
|
|
|
302
302
|
// --- toLowerCase() ---
|
|
303
303
|
if (key == "toLowerCase")
|
|
304
304
|
{
|
|
305
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
305
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
306
306
|
{
|
|
307
307
|
std::string result = self->value;
|
|
308
308
|
std::transform(result.begin(), result.end(), result.begin(),
|
|
@@ -314,7 +314,7 @@ namespace jspp
|
|
|
314
314
|
// --- toUpperCase() ---
|
|
315
315
|
if (key == "toUpperCase")
|
|
316
316
|
{
|
|
317
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
317
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
318
318
|
{
|
|
319
319
|
std::string result = self->value;
|
|
320
320
|
std::transform(result.begin(), result.end(), result.begin(),
|
|
@@ -326,7 +326,7 @@ namespace jspp
|
|
|
326
326
|
// --- trim() ---
|
|
327
327
|
if (key == "trim")
|
|
328
328
|
{
|
|
329
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
329
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
330
330
|
{
|
|
331
331
|
const char* whitespace = " \t\n\r\f\v";
|
|
332
332
|
std::string result = self->value;
|
|
@@ -339,7 +339,7 @@ namespace jspp
|
|
|
339
339
|
// --- trimEnd() ---
|
|
340
340
|
if (key == "trimEnd")
|
|
341
341
|
{
|
|
342
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
342
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
343
343
|
{
|
|
344
344
|
const char* whitespace = " \t\n\r\f\v";
|
|
345
345
|
std::string result = self->value;
|
|
@@ -351,7 +351,7 @@ namespace jspp
|
|
|
351
351
|
// --- trimStart() ---
|
|
352
352
|
if (key == "trimStart")
|
|
353
353
|
{
|
|
354
|
-
return AnyValue::make_function([self](const std::vector<AnyValue> &args) -> AnyValue
|
|
354
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
|
|
355
355
|
{
|
|
356
356
|
const char* whitespace = " \t\n\r\f\v";
|
|
357
357
|
std::string result = self->value;
|