@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.
- package/dist/analysis/scope.js +17 -0
- package/dist/analysis/typeAnalyzer.js +7 -1
- package/dist/ast/symbols.js +32 -0
- package/dist/ast/types.js +0 -6
- package/dist/cli-utils/args.js +57 -0
- package/dist/cli-utils/colors.js +9 -0
- package/dist/cli-utils/file-utils.js +20 -0
- package/dist/cli-utils/spinner.js +55 -0
- package/dist/cli.js +105 -30
- package/dist/core/codegen/class-handlers.js +10 -6
- package/dist/core/codegen/control-flow-handlers.js +57 -28
- package/dist/core/codegen/declaration-handlers.js +10 -6
- package/dist/core/codegen/expression-handlers.js +206 -61
- package/dist/core/codegen/function-handlers.js +203 -76
- package/dist/core/codegen/helpers.js +125 -28
- package/dist/core/codegen/index.js +23 -15
- package/dist/core/codegen/literal-handlers.js +15 -6
- package/dist/core/codegen/statement-handlers.js +282 -84
- package/dist/core/codegen/visitor.js +3 -1
- package/package.json +1 -1
- package/src/prelude/any_value.hpp +221 -342
- package/src/prelude/any_value_access.hpp +168 -81
- package/src/prelude/any_value_defines.hpp +74 -35
- package/src/prelude/any_value_helpers.hpp +75 -180
- package/src/prelude/exception.hpp +1 -0
- package/src/prelude/exception_helpers.hpp +4 -4
- package/src/prelude/index.hpp +12 -2
- package/src/prelude/library/array.hpp +190 -0
- package/src/prelude/library/console.hpp +6 -5
- package/src/prelude/library/error.hpp +10 -8
- package/src/prelude/library/function.hpp +10 -0
- package/src/prelude/library/global.hpp +20 -0
- package/src/prelude/library/math.hpp +308 -0
- package/src/prelude/library/object.hpp +288 -0
- package/src/prelude/library/performance.hpp +1 -1
- package/src/prelude/library/process.hpp +39 -0
- package/src/prelude/library/promise.hpp +57 -55
- package/src/prelude/library/symbol.hpp +45 -57
- package/src/prelude/library/timer.hpp +6 -6
- package/src/prelude/types.hpp +54 -0
- package/src/prelude/utils/access.hpp +215 -11
- package/src/prelude/utils/assignment_operators.hpp +99 -0
- package/src/prelude/utils/log_any_value/array.hpp +8 -8
- package/src/prelude/utils/log_any_value/function.hpp +6 -4
- package/src/prelude/utils/log_any_value/object.hpp +41 -24
- package/src/prelude/utils/log_any_value/primitives.hpp +3 -1
- package/src/prelude/utils/operators.hpp +750 -274
- package/src/prelude/utils/well_known_symbols.hpp +12 -0
- package/src/prelude/values/array.hpp +8 -6
- package/src/prelude/values/async_iterator.hpp +79 -0
- package/src/prelude/values/descriptors.hpp +2 -2
- package/src/prelude/values/function.hpp +72 -62
- package/src/prelude/values/helpers/array.hpp +64 -28
- package/src/prelude/values/helpers/async_iterator.hpp +275 -0
- package/src/prelude/values/helpers/function.hpp +81 -92
- package/src/prelude/values/helpers/iterator.hpp +3 -3
- package/src/prelude/values/helpers/object.hpp +54 -9
- package/src/prelude/values/helpers/promise.hpp +13 -6
- package/src/prelude/values/iterator.hpp +1 -1
- package/src/prelude/values/object.hpp +10 -3
- package/src/prelude/values/promise.hpp +7 -11
- package/src/prelude/values/prototypes/array.hpp +851 -12
- package/src/prelude/values/prototypes/async_iterator.hpp +50 -0
- package/src/prelude/values/prototypes/function.hpp +2 -2
- package/src/prelude/values/prototypes/iterator.hpp +5 -5
- package/src/prelude/values/prototypes/number.hpp +153 -0
- package/src/prelude/values/prototypes/object.hpp +2 -2
- package/src/prelude/values/prototypes/promise.hpp +40 -30
- package/src/prelude/values/prototypes/string.hpp +28 -28
- package/src/prelude/values/prototypes/symbol.hpp +20 -3
- package/src/prelude/values/shape.hpp +52 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include "values/async_iterator.hpp"
|
|
5
|
+
#include "any_value.hpp"
|
|
6
|
+
#include "exception.hpp"
|
|
7
|
+
#include "utils/operators.hpp"
|
|
8
|
+
|
|
9
|
+
namespace jspp
|
|
10
|
+
{
|
|
11
|
+
namespace AsyncIteratorPrototypes
|
|
12
|
+
{
|
|
13
|
+
inline std::optional<AnyValue> get(const std::string &key, JsAsyncIterator<AnyValue> *self)
|
|
14
|
+
{
|
|
15
|
+
// --- toString() method ---
|
|
16
|
+
if (key == "toString" || key == WellKnownSymbols::toStringTag->key)
|
|
17
|
+
{
|
|
18
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
|
|
19
|
+
{ return AnyValue::make_string(self->to_std_string()); },
|
|
20
|
+
key);
|
|
21
|
+
}
|
|
22
|
+
// --- [Symbol.asyncIterator]() method ---
|
|
23
|
+
// For async iterators, the async iterator is itself (similar to sync iterators)
|
|
24
|
+
if (key == WellKnownSymbols::asyncIterator->key)
|
|
25
|
+
{
|
|
26
|
+
// We return 'this'. Since we can't easily create a shared_ptr from raw pointer,
|
|
27
|
+
// we rely on the context to hold the reference or implement better shared_from_this strategy.
|
|
28
|
+
// For now, assume it works like Iterator.
|
|
29
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
|
|
30
|
+
{
|
|
31
|
+
// This is slightly dangerous as we create a new shared_ptr from raw.
|
|
32
|
+
// TODO: fix lifetime management
|
|
33
|
+
return thisVal; },
|
|
34
|
+
key);
|
|
35
|
+
}
|
|
36
|
+
// --- next() method ---
|
|
37
|
+
if (key == "next")
|
|
38
|
+
{
|
|
39
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
|
|
40
|
+
{
|
|
41
|
+
AnyValue val = args.empty() ? AnyValue::make_undefined() : args[0];
|
|
42
|
+
auto res = self->next(val);
|
|
43
|
+
return AnyValue::make_promise(res); },
|
|
44
|
+
key);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return std::nullopt;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -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" || key == WellKnownSymbols::toStringTag->key)
|
|
17
17
|
{
|
|
18
|
-
return AnyValue::make_function([self](const AnyValue &thisVal,
|
|
18
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> _) -> AnyValue
|
|
19
19
|
{ return AnyValue::make_string(self->to_std_string()); },
|
|
20
20
|
key);
|
|
21
21
|
}
|
|
@@ -13,16 +13,16 @@ 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" || key == WellKnownSymbols::toStringTag->key)
|
|
17
17
|
{
|
|
18
|
-
return AnyValue::make_function([self](const AnyValue &thisVal,
|
|
18
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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::make_generator([self](const AnyValue &thisVal,
|
|
25
|
+
return AnyValue::make_generator([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
|
|
26
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.
|
|
@@ -37,7 +37,7 @@ namespace jspp
|
|
|
37
37
|
// --- next() method ---
|
|
38
38
|
if (key == "next")
|
|
39
39
|
{
|
|
40
|
-
return AnyValue::make_function([self](const AnyValue &thisVal,
|
|
40
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
|
|
41
41
|
{
|
|
42
42
|
AnyValue val = args.empty() ? AnyValue::make_undefined() : args[0];
|
|
43
43
|
auto res = self->next(val);
|
|
@@ -47,7 +47,7 @@ namespace jspp
|
|
|
47
47
|
// --- toArray() method ---
|
|
48
48
|
if (key == "toArray")
|
|
49
49
|
{
|
|
50
|
-
return AnyValue::make_function([self](const AnyValue &thisVal,
|
|
50
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
|
|
51
51
|
{ return AnyValue::make_array(self->to_vector()); },
|
|
52
52
|
key);
|
|
53
53
|
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include "any_value.hpp"
|
|
5
|
+
#include "exception.hpp"
|
|
6
|
+
#include "utils/operators.hpp"
|
|
7
|
+
#include <string>
|
|
8
|
+
#include <vector>
|
|
9
|
+
#include <iomanip>
|
|
10
|
+
#include <sstream>
|
|
11
|
+
#include <cmath>
|
|
12
|
+
#include <algorithm>
|
|
13
|
+
|
|
14
|
+
namespace jspp
|
|
15
|
+
{
|
|
16
|
+
namespace NumberPrototypes
|
|
17
|
+
{
|
|
18
|
+
// Helper for radix conversion
|
|
19
|
+
inline std::string number_to_radix_string(double value, int radix)
|
|
20
|
+
{
|
|
21
|
+
if (std::isnan(value))
|
|
22
|
+
return "NaN";
|
|
23
|
+
if (!std::isfinite(value))
|
|
24
|
+
return value > 0 ? "Infinity" : "-Infinity";
|
|
25
|
+
|
|
26
|
+
// For radix != 10, we only support integer part for now
|
|
27
|
+
// as implementing full float-to-radix is complex.
|
|
28
|
+
long long intPart = static_cast<long long>(value);
|
|
29
|
+
|
|
30
|
+
if (radix == 10)
|
|
31
|
+
{
|
|
32
|
+
return AnyValue::make_number(value).to_std_string();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
bool negative = intPart < 0;
|
|
36
|
+
if (negative)
|
|
37
|
+
intPart = -intPart;
|
|
38
|
+
|
|
39
|
+
std::string chars = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
40
|
+
std::string res = "";
|
|
41
|
+
|
|
42
|
+
if (intPart == 0)
|
|
43
|
+
res = "0";
|
|
44
|
+
else
|
|
45
|
+
{
|
|
46
|
+
while (intPart > 0)
|
|
47
|
+
{
|
|
48
|
+
res += chars[intPart % radix];
|
|
49
|
+
intPart /= radix;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (negative)
|
|
53
|
+
res += "-";
|
|
54
|
+
std::reverse(res.begin(), res.end());
|
|
55
|
+
return res;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
inline std::optional<AnyValue> get(const std::string &key, double self)
|
|
59
|
+
{
|
|
60
|
+
// --- toExponential(fractionDigits) ---
|
|
61
|
+
if (key == "toExponential")
|
|
62
|
+
{
|
|
63
|
+
return AnyValue::make_function([self](const AnyValue &, std::span<const AnyValue> args) -> AnyValue
|
|
64
|
+
{
|
|
65
|
+
int digits = -1;
|
|
66
|
+
if (!args.empty() && !args[0].is_undefined()) {
|
|
67
|
+
digits = Operators_Private::ToInt32(args[0]);
|
|
68
|
+
if (digits < 0 || digits > 100) {
|
|
69
|
+
throw Exception::make_exception("toExponential() digits argument must be between 0 and 100", "RangeError");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
std::ostringstream ss;
|
|
74
|
+
if (digits >= 0) {
|
|
75
|
+
ss << std::scientific << std::setprecision(digits) << self;
|
|
76
|
+
} else {
|
|
77
|
+
ss << std::scientific << self;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
std::string res = ss.str();
|
|
81
|
+
return AnyValue::make_string(res); }, "toExponential");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// --- toFixed(digits) ---
|
|
85
|
+
if (key == "toFixed")
|
|
86
|
+
{
|
|
87
|
+
return AnyValue::make_function([self](const AnyValue &, std::span<const AnyValue> args) -> AnyValue
|
|
88
|
+
{
|
|
89
|
+
int digits = 0;
|
|
90
|
+
if (!args.empty() && !args[0].is_undefined()) {
|
|
91
|
+
digits = Operators_Private::ToInt32(args[0]);
|
|
92
|
+
}
|
|
93
|
+
if (digits < 0 || digits > 100) {
|
|
94
|
+
throw Exception::make_exception("toFixed() digits argument must be between 0 and 100", "RangeError");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
std::ostringstream ss;
|
|
98
|
+
ss << std::fixed << std::setprecision(digits) << self;
|
|
99
|
+
return AnyValue::make_string(ss.str()); }, "toFixed");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// --- toPrecision(precision) ---
|
|
103
|
+
if (key == "toPrecision")
|
|
104
|
+
{
|
|
105
|
+
return AnyValue::make_function([self](const AnyValue &, std::span<const AnyValue> args) -> AnyValue
|
|
106
|
+
{
|
|
107
|
+
if (args.empty() || args[0].is_undefined()) {
|
|
108
|
+
return AnyValue::make_number(self).get_own_property("toString").call(AnyValue::make_number(self), {}, "toString");
|
|
109
|
+
}
|
|
110
|
+
int precision = Operators_Private::ToInt32(args[0]);
|
|
111
|
+
if (precision < 1 || precision > 100) {
|
|
112
|
+
throw Exception::make_exception("toPrecision() precision argument must be between 1 and 100", "RangeError");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
std::ostringstream ss;
|
|
116
|
+
ss << std::setprecision(precision) << self;
|
|
117
|
+
return AnyValue::make_string(ss.str()); }, "toPrecision");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// --- toString(radix) ---
|
|
121
|
+
if (key == "toString")
|
|
122
|
+
{
|
|
123
|
+
return AnyValue::make_function([self](const AnyValue &, std::span<const AnyValue> args) -> AnyValue
|
|
124
|
+
{
|
|
125
|
+
int radix = 10;
|
|
126
|
+
if (!args.empty() && !args[0].is_undefined()) {
|
|
127
|
+
radix = Operators_Private::ToInt32(args[0]);
|
|
128
|
+
}
|
|
129
|
+
if (radix < 2 || radix > 36) {
|
|
130
|
+
throw Exception::make_exception("toString() radix argument must be between 2 and 36", "RangeError");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return AnyValue::make_string(number_to_radix_string(self, radix)); }, "toString");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// --- valueOf() ---
|
|
137
|
+
if (key == "valueOf")
|
|
138
|
+
{
|
|
139
|
+
return AnyValue::make_function([self](const AnyValue &, std::span<const AnyValue>) -> AnyValue
|
|
140
|
+
{ return AnyValue::make_number(self); }, "valueOf");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// --- toLocaleString() ---
|
|
144
|
+
if (key == "toLocaleString")
|
|
145
|
+
{
|
|
146
|
+
return AnyValue::make_function([self](const AnyValue &, std::span<const AnyValue>) -> AnyValue
|
|
147
|
+
{ return AnyValue::make_string(AnyValue::make_number(self).to_std_string()); }, "toLocaleString");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return std::nullopt;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -13,9 +13,9 @@ namespace jspp
|
|
|
13
13
|
inline std::optional<AnyValue> get(const std::string &key, JsObject *self)
|
|
14
14
|
{
|
|
15
15
|
// --- toString() method ---
|
|
16
|
-
if (key == "toString" )
|
|
16
|
+
if (key == "toString" || key == WellKnownSymbols::toStringTag->key)
|
|
17
17
|
{
|
|
18
|
-
return AnyValue::make_function([self](const AnyValue &thisVal,
|
|
18
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> _) -> AnyValue
|
|
19
19
|
{ return AnyValue::make_string(self->to_std_string()); },
|
|
20
20
|
key);
|
|
21
21
|
}
|
|
@@ -4,12 +4,17 @@
|
|
|
4
4
|
#include "values/promise.hpp"
|
|
5
5
|
#include "any_value.hpp"
|
|
6
6
|
|
|
7
|
-
namespace jspp
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
namespace jspp
|
|
8
|
+
{
|
|
9
|
+
namespace PromisePrototypes
|
|
10
|
+
{
|
|
11
|
+
inline std::optional<AnyValue> get(const std::string &key, JsPromise *self)
|
|
12
|
+
{
|
|
13
|
+
|
|
14
|
+
if (key == "then")
|
|
15
|
+
{
|
|
16
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
|
|
17
|
+
{
|
|
13
18
|
AnyValue onFulfilled = (args.size() > 0 && args[0].is_function()) ? args[0] : AnyValue::make_undefined();
|
|
14
19
|
AnyValue onRejected = (args.size() > 1 && args[1].is_function()) ? args[1] : AnyValue::make_undefined();
|
|
15
20
|
|
|
@@ -31,16 +36,17 @@ namespace jspp {
|
|
|
31
36
|
|
|
32
37
|
|
|
33
38
|
// Resolve handler
|
|
34
|
-
auto resolveHandler = [resolveNew, rejectNew, onFulfilled](AnyValue val) mutable {
|
|
39
|
+
auto resolveHandler = [resolveNew, rejectNew, onFulfilled](const AnyValue& val) mutable {
|
|
35
40
|
if (onFulfilled.is_function()) {
|
|
36
41
|
try {
|
|
37
|
-
|
|
42
|
+
const AnyValue cbArgs[] = {val};
|
|
43
|
+
auto res = onFulfilled.call(AnyValue::make_undefined(), cbArgs, "onFulfilled");
|
|
38
44
|
if (res.is_promise()) {
|
|
39
45
|
// Chaining: newPromise follows res
|
|
40
46
|
auto chained = res.as_promise();
|
|
41
47
|
chained->then(
|
|
42
|
-
[resolveNew](AnyValue v) { resolveNew(v); },
|
|
43
|
-
[rejectNew](AnyValue e) { rejectNew(e); }
|
|
48
|
+
[resolveNew](const AnyValue& v) { resolveNew(v); },
|
|
49
|
+
[rejectNew](const AnyValue& e) { rejectNew(e); }
|
|
44
50
|
);
|
|
45
51
|
} else {
|
|
46
52
|
resolveNew(res);
|
|
@@ -56,15 +62,16 @@ namespace jspp {
|
|
|
56
62
|
};
|
|
57
63
|
|
|
58
64
|
// Reject handler
|
|
59
|
-
auto rejectHandler = [resolveNew, rejectNew, onRejected](AnyValue reason) mutable {
|
|
65
|
+
auto rejectHandler = [resolveNew, rejectNew, onRejected](const AnyValue& reason) mutable {
|
|
60
66
|
if (onRejected.is_function()) {
|
|
61
67
|
try {
|
|
62
|
-
|
|
68
|
+
const AnyValue cbArgs[] = {reason};
|
|
69
|
+
auto res = onRejected.call(AnyValue::make_undefined(), cbArgs,"onRejected");
|
|
63
70
|
if (res.is_promise()) {
|
|
64
71
|
auto chained = res.as_promise();
|
|
65
72
|
chained->then(
|
|
66
|
-
[resolveNew](AnyValue v) { resolveNew(v); },
|
|
67
|
-
[rejectNew](AnyValue e) { rejectNew(e); }
|
|
73
|
+
[resolveNew](const AnyValue& v) { resolveNew(v); },
|
|
74
|
+
[rejectNew](const AnyValue& e) { rejectNew(e); }
|
|
68
75
|
);
|
|
69
76
|
} else {
|
|
70
77
|
resolveNew(res); // Recovered
|
|
@@ -80,44 +87,47 @@ namespace jspp {
|
|
|
80
87
|
};
|
|
81
88
|
|
|
82
89
|
self->then(resolveHandler, rejectHandler);
|
|
83
|
-
return newPromiseVal;
|
|
84
|
-
}, "then");
|
|
90
|
+
return newPromiseVal; }, "then");
|
|
85
91
|
}
|
|
86
92
|
|
|
87
|
-
if (key == "catch")
|
|
88
|
-
|
|
93
|
+
if (key == "catch")
|
|
94
|
+
{
|
|
95
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
|
|
96
|
+
{
|
|
89
97
|
// catch(onRejected) is then(undefined, onRejected)
|
|
90
98
|
AnyValue onRejected = (args.size() > 0 && args[0].is_function()) ? args[0] : AnyValue::make_undefined();
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
const AnyValue thenArgs[] = {AnyValue::make_undefined(), onRejected};
|
|
100
|
+
return thisVal.get_own_property("then").call(thisVal, thenArgs,"then"); }, "catch");
|
|
93
101
|
}
|
|
94
102
|
|
|
95
|
-
if (key == "finally")
|
|
96
|
-
|
|
103
|
+
if (key == "finally")
|
|
104
|
+
{
|
|
105
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
|
|
106
|
+
{
|
|
97
107
|
AnyValue onFinally = (args.size() > 0 && args[0].is_function()) ? args[0] : AnyValue::make_undefined();
|
|
98
108
|
|
|
99
109
|
// finally(onFinally) returns a promise that passes through value/reason,
|
|
100
110
|
// but executes onFinally first.
|
|
101
111
|
|
|
102
|
-
|
|
103
|
-
AnyValue::make_function([onFinally](const AnyValue&,
|
|
112
|
+
const AnyValue thenArgs[] = {
|
|
113
|
+
AnyValue::make_function([onFinally](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
104
114
|
AnyValue val = args.empty() ? AnyValue::make_undefined() : args[0];
|
|
105
115
|
if (onFinally.is_function()) {
|
|
106
|
-
onFinally.
|
|
116
|
+
onFinally.call(AnyValue::make_undefined(), {}, "onFinally");
|
|
107
117
|
}
|
|
108
118
|
return val;
|
|
109
119
|
}, ""),
|
|
110
|
-
AnyValue::make_function([onFinally](const AnyValue&,
|
|
120
|
+
AnyValue::make_function([onFinally](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
111
121
|
AnyValue reason = args.empty() ? AnyValue::make_undefined() : args[0];
|
|
112
122
|
if (onFinally.is_function()) {
|
|
113
|
-
onFinally.
|
|
123
|
+
onFinally.call(AnyValue::make_undefined(), {}, "onFinally");
|
|
114
124
|
}
|
|
115
125
|
throw Exception(reason);
|
|
116
126
|
}, "")
|
|
117
|
-
}
|
|
118
|
-
|
|
127
|
+
};
|
|
128
|
+
return thisVal.get_own_property("then").call(thisVal, thenArgs,"then"); }, "finally");
|
|
119
129
|
}
|
|
120
|
-
|
|
130
|
+
|
|
121
131
|
return std::nullopt;
|
|
122
132
|
}
|
|
123
133
|
}
|
|
@@ -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" || key == "valueOf")
|
|
22
|
+
if (key == "toString" || key == "valueOf" || key == WellKnownSymbols::toStringTag->key)
|
|
23
23
|
{
|
|
24
|
-
return AnyValue::make_function([self](const AnyValue &thisVal,
|
|
24
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
32
|
+
return AnyValue::make_generator([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
40
|
+
return AnyValue::make_accessor_descriptor([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
|
|
41
41
|
{ return AnyValue::make_number(self->value.length()); },
|
|
42
|
-
[self](const AnyValue &thisVal,
|
|
42
|
+
[self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
51
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
65
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
79
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
95
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
108
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
121
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
134
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
151
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
168
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
187
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
205
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
225
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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,10 +242,10 @@ namespace jspp
|
|
|
242
242
|
// --- split(separator) ---
|
|
243
243
|
if (key == "split")
|
|
244
244
|
{
|
|
245
|
-
return AnyValue::make_function([self](const AnyValue &thisVal,
|
|
245
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
|
|
246
246
|
{
|
|
247
247
|
std::string separator = (args.empty() || args[0].is_undefined()) ? "" : args[0].to_std_string();
|
|
248
|
-
std::vector<
|
|
248
|
+
std::vector<jspp::AnyValue> result_vec;
|
|
249
249
|
|
|
250
250
|
if (separator.empty()) {
|
|
251
251
|
for (char c : (self->value)) {
|
|
@@ -260,14 +260,14 @@ namespace jspp
|
|
|
260
260
|
}
|
|
261
261
|
result_vec.push_back(AnyValue::make_string(temp));
|
|
262
262
|
}
|
|
263
|
-
return AnyValue::make_array(result_vec); },
|
|
263
|
+
return AnyValue::make_array(std::move(result_vec)); },
|
|
264
264
|
key);
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
// --- startsWith(searchString, position) ---
|
|
268
268
|
if (key == "startsWith")
|
|
269
269
|
{
|
|
270
|
-
return AnyValue::make_function([self](const AnyValue &thisVal,
|
|
270
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
284
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
305
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
317
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
329
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
342
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const 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 AnyValue &thisVal,
|
|
354
|
+
return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
|
|
355
355
|
{
|
|
356
356
|
const char* whitespace = " \t\n\r\f\v";
|
|
357
357
|
std::string result = self->value;
|
|
@@ -363,4 +363,4 @@ namespace jspp
|
|
|
363
363
|
return std::nullopt;
|
|
364
364
|
}
|
|
365
365
|
}
|
|
366
|
-
}
|
|
366
|
+
}
|