@ugo-studio/jspp 0.1.4 → 0.1.5
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 +29 -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 +31 -21
- package/dist/core/codegen/declaration-handlers.js +10 -6
- package/dist/core/codegen/expression-handlers.js +202 -60
- package/dist/core/codegen/function-handlers.js +179 -70
- package/dist/core/codegen/helpers.js +107 -17
- package/dist/core/codegen/index.js +9 -8
- package/dist/core/codegen/literal-handlers.js +15 -6
- package/dist/core/codegen/statement-handlers.js +67 -53
- package/dist/core/codegen/visitor.js +3 -1
- package/package.json +1 -1
- package/src/prelude/any_value.hpp +195 -342
- package/src/prelude/any_value_access.hpp +78 -30
- package/src/prelude/any_value_defines.hpp +74 -35
- package/src/prelude/any_value_helpers.hpp +73 -180
- package/src/prelude/exception.hpp +1 -0
- package/src/prelude/exception_helpers.hpp +4 -4
- package/src/prelude/index.hpp +9 -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 +53 -43
- package/src/prelude/library/symbol.hpp +45 -57
- package/src/prelude/library/timer.hpp +6 -6
- package/src/prelude/types.hpp +48 -0
- package/src/prelude/utils/access.hpp +182 -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/descriptors.hpp +2 -2
- package/src/prelude/values/function.hpp +71 -62
- package/src/prelude/values/helpers/array.hpp +64 -28
- package/src/prelude/values/helpers/function.hpp +77 -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 +3 -3
- package/src/prelude/values/iterator.hpp +1 -1
- package/src/prelude/values/object.hpp +10 -3
- package/src/prelude/values/promise.hpp +3 -3
- package/src/prelude/values/prototypes/array.hpp +851 -12
- 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
|
@@ -9,5 +9,17 @@ namespace jspp
|
|
|
9
9
|
{
|
|
10
10
|
// We use a specific prefix "@@" for well-known symbols to distinguish them from user symbols
|
|
11
11
|
inline std::shared_ptr<JsSymbol> iterator = std::make_shared<JsSymbol>("Symbol.iterator", "@@iterator");
|
|
12
|
+
inline std::shared_ptr<JsSymbol> asyncIterator = std::make_shared<JsSymbol>("Symbol.asyncIterator", "@@asyncIterator");
|
|
13
|
+
inline std::shared_ptr<JsSymbol> hasInstance = std::make_shared<JsSymbol>("Symbol.hasInstance", "@@hasInstance");
|
|
14
|
+
inline std::shared_ptr<JsSymbol> isConcatSpreadable = std::make_shared<JsSymbol>("Symbol.isConcatSpreadable", "@@isConcatSpreadable");
|
|
15
|
+
inline std::shared_ptr<JsSymbol> match = std::make_shared<JsSymbol>("Symbol.match", "@@match");
|
|
16
|
+
inline std::shared_ptr<JsSymbol> matchAll = std::make_shared<JsSymbol>("Symbol.matchAll", "@@matchAll");
|
|
17
|
+
inline std::shared_ptr<JsSymbol> replace = std::make_shared<JsSymbol>("Symbol.replace", "@@replace");
|
|
18
|
+
inline std::shared_ptr<JsSymbol> search = std::make_shared<JsSymbol>("Symbol.search", "@@search");
|
|
19
|
+
inline std::shared_ptr<JsSymbol> species = std::make_shared<JsSymbol>("Symbol.species", "@@species");
|
|
20
|
+
inline std::shared_ptr<JsSymbol> split = std::make_shared<JsSymbol>("Symbol.split", "@@split");
|
|
21
|
+
inline std::shared_ptr<JsSymbol> toPrimitive = std::make_shared<JsSymbol>("Symbol.toPrimitive", "@@toPrimitive");
|
|
22
|
+
inline std::shared_ptr<JsSymbol> toStringTag = std::make_shared<JsSymbol>("Symbol.toStringTag", "@@toStringTag");
|
|
23
|
+
inline std::shared_ptr<JsSymbol> unscopables = std::make_shared<JsSymbol>("Symbol.unscopables", "@@unscopables");
|
|
12
24
|
}
|
|
13
25
|
}
|
|
@@ -10,18 +10,20 @@ namespace jspp
|
|
|
10
10
|
|
|
11
11
|
struct JsArray
|
|
12
12
|
{
|
|
13
|
-
std::vector<
|
|
14
|
-
std::unordered_map<uint32_t,
|
|
15
|
-
std::unordered_map<std::string, AnyValue> props;
|
|
13
|
+
std::vector<AnyValue> dense; // dense storage for small/contiguous indices
|
|
14
|
+
std::unordered_map<uint32_t, AnyValue> sparse; // sparse indices (very large indices)
|
|
15
|
+
std::unordered_map<std::string, AnyValue> props; // non-index string properties
|
|
16
|
+
std::shared_ptr<AnyValue> proto;
|
|
16
17
|
uint64_t length = 0;
|
|
17
18
|
|
|
18
|
-
JsArray()
|
|
19
|
-
explicit JsArray(const std::vector<
|
|
20
|
-
explicit JsArray(std::vector<
|
|
19
|
+
JsArray() : proto(nullptr) {}
|
|
20
|
+
explicit JsArray(const std::vector<AnyValue> &items) : dense(items), proto(nullptr), length(items.size()) {}
|
|
21
|
+
explicit JsArray(std::vector<AnyValue> &&items) : dense(std::move(items)), proto(nullptr), length(dense.size()) {}
|
|
21
22
|
|
|
22
23
|
std::string to_std_string() const;
|
|
23
24
|
JsIterator<AnyValue> get_iterator();
|
|
24
25
|
|
|
26
|
+
bool has_property(const std::string &key) const;
|
|
25
27
|
AnyValue get_property(const std::string &key, const AnyValue &thisVal);
|
|
26
28
|
AnyValue get_property(uint32_t idx);
|
|
27
29
|
AnyValue set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal);
|
|
@@ -17,8 +17,8 @@ namespace jspp
|
|
|
17
17
|
|
|
18
18
|
struct AccessorDescriptor
|
|
19
19
|
{
|
|
20
|
-
std::optional<std::function<AnyValue(const AnyValue &,
|
|
21
|
-
std::optional<std::function<AnyValue(const AnyValue &,
|
|
20
|
+
std::optional<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>> get; // getter = function or undefined
|
|
21
|
+
std::optional<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>> set; // setter = function or undefined
|
|
22
22
|
bool enumerable = false;
|
|
23
23
|
bool configurable = true;
|
|
24
24
|
};
|
|
@@ -1,76 +1,85 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include "types.hpp"
|
|
4
|
-
#include <variant>
|
|
4
|
+
#include <variant>
|
|
5
|
+
#include <optional>
|
|
5
6
|
|
|
6
7
|
namespace jspp
|
|
7
8
|
{
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
// Forward declaration of AnyValue
|
|
10
|
+
class AnyValue;
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
using JsFunctionCallable = std::variant<std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)>, // 0: Normal
|
|
13
|
+
std::function<jspp::JsIterator<jspp::AnyValue>(const AnyValue &, std::span<const AnyValue>)>, // 1: Generator
|
|
14
|
+
std::function<jspp::JsPromise(const AnyValue &, std::span<const AnyValue>)>>; // 2: Async
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
struct JsFunction
|
|
17
|
+
{
|
|
18
|
+
JsFunctionCallable callable;
|
|
19
|
+
std::optional<std::string> name;
|
|
20
|
+
std::unordered_map<std::string, AnyValue> props;
|
|
21
|
+
std::shared_ptr<AnyValue> proto = nullptr;
|
|
22
|
+
bool is_generator;
|
|
23
|
+
bool is_async;
|
|
24
|
+
bool is_class;
|
|
25
|
+
bool is_constructor;
|
|
26
|
+
|
|
27
|
+
// ---- Constructor A: infer flags ----
|
|
28
|
+
JsFunction(const JsFunctionCallable &c,
|
|
29
|
+
std::optional<std::string> n = std::nullopt,
|
|
30
|
+
std::unordered_map<std::string, AnyValue> p = {},
|
|
31
|
+
bool is_cls = false,
|
|
32
|
+
bool is_ctor = true)
|
|
33
|
+
: callable(c),
|
|
34
|
+
name(std::move(n)),
|
|
35
|
+
props(std::move(p)),
|
|
36
|
+
is_generator(callable.index() == 1),
|
|
37
|
+
is_async(callable.index() == 2),
|
|
38
|
+
is_class(is_cls),
|
|
39
|
+
is_constructor(is_ctor && !is_generator && !is_async) // Generators and asyncs are never constructors
|
|
16
40
|
{
|
|
17
|
-
|
|
18
|
-
std::string name;
|
|
19
|
-
std::unordered_map<std::string, AnyValue> props;
|
|
20
|
-
std::shared_ptr<AnyValue> proto = nullptr;
|
|
21
|
-
bool is_generator;
|
|
22
|
-
bool is_async;
|
|
23
|
-
bool is_class;
|
|
41
|
+
}
|
|
24
42
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
43
|
+
// ---- Constructor B: explicit generator flag (backward compat) ----
|
|
44
|
+
JsFunction(const JsFunctionCallable &c,
|
|
45
|
+
bool is_gen,
|
|
46
|
+
std::optional<std::string> n = std::nullopt,
|
|
47
|
+
std::unordered_map<std::string, AnyValue> p = {},
|
|
48
|
+
bool is_cls = false,
|
|
49
|
+
bool is_ctor = true)
|
|
50
|
+
: callable(c),
|
|
51
|
+
name(std::move(n)),
|
|
52
|
+
props(std::move(p)),
|
|
53
|
+
is_generator(is_gen),
|
|
54
|
+
is_async(callable.index() == 2),
|
|
55
|
+
is_class(is_cls),
|
|
56
|
+
is_constructor(is_ctor && !is_gen && !is_async)
|
|
57
|
+
{
|
|
58
|
+
}
|
|
38
59
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
bool is_gen,
|
|
57
|
-
bool is_async_func,
|
|
58
|
-
std::string n = {},
|
|
59
|
-
std::unordered_map<std::string, AnyValue> p = {},
|
|
60
|
-
bool is_cls = false)
|
|
61
|
-
: callable(c),
|
|
62
|
-
name(std::move(n)),
|
|
63
|
-
props(std::move(p)),
|
|
64
|
-
is_generator(is_gen),
|
|
65
|
-
is_async(is_async_func),
|
|
66
|
-
is_class(is_cls)
|
|
67
|
-
{
|
|
68
|
-
}
|
|
60
|
+
// ---- Constructor C: explicit async flag ----
|
|
61
|
+
JsFunction(const JsFunctionCallable &c,
|
|
62
|
+
bool is_gen,
|
|
63
|
+
bool is_async_func,
|
|
64
|
+
std::optional<std::string> n = std::nullopt,
|
|
65
|
+
std::unordered_map<std::string, AnyValue> p = {},
|
|
66
|
+
bool is_cls = false,
|
|
67
|
+
bool is_ctor = true)
|
|
68
|
+
: callable(c),
|
|
69
|
+
name(std::move(n)),
|
|
70
|
+
props(std::move(p)),
|
|
71
|
+
is_generator(is_gen),
|
|
72
|
+
is_async(is_async_func),
|
|
73
|
+
is_class(is_cls),
|
|
74
|
+
is_constructor(is_ctor && !is_gen && !is_async_func)
|
|
75
|
+
{
|
|
76
|
+
}
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
std::string to_std_string() const;
|
|
79
|
+
AnyValue call(const AnyValue &thisVal, std::span<const AnyValue> args);
|
|
72
80
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
81
|
+
bool has_property(const std::string &key) const;
|
|
82
|
+
AnyValue get_property(const std::string &key, const AnyValue &thisVal);
|
|
83
|
+
AnyValue set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal);
|
|
84
|
+
};
|
|
76
85
|
}
|
|
@@ -16,23 +16,23 @@ std::string jspp::JsArray::to_std_string() const
|
|
|
16
16
|
std::string result = "";
|
|
17
17
|
for (uint64_t i = 0; i < length; ++i)
|
|
18
18
|
{
|
|
19
|
-
|
|
19
|
+
const AnyValue *itemPtr = nullptr;
|
|
20
20
|
if (i < dense.size())
|
|
21
21
|
{
|
|
22
|
-
|
|
22
|
+
itemPtr = &dense[i];
|
|
23
23
|
}
|
|
24
24
|
else
|
|
25
25
|
{
|
|
26
26
|
auto it = sparse.find(static_cast<uint32_t>(i));
|
|
27
27
|
if (it != sparse.end())
|
|
28
28
|
{
|
|
29
|
-
|
|
29
|
+
itemPtr = &it->second;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
if (
|
|
33
|
+
if (itemPtr && !itemPtr->is_uninitialized())
|
|
34
34
|
{
|
|
35
|
-
const auto &item =
|
|
35
|
+
const auto &item = *itemPtr;
|
|
36
36
|
if (!item.is_undefined() && !item.is_null())
|
|
37
37
|
{
|
|
38
38
|
result += item.to_std_string();
|
|
@@ -57,6 +57,32 @@ jspp::JsIterator<jspp::AnyValue> jspp::JsArray::get_iterator()
|
|
|
57
57
|
co_return AnyValue::make_undefined();
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
bool jspp::JsArray::has_property(const std::string &key) const
|
|
61
|
+
{
|
|
62
|
+
if (key == "length")
|
|
63
|
+
return true;
|
|
64
|
+
if (is_array_index(key))
|
|
65
|
+
{
|
|
66
|
+
uint32_t idx = static_cast<uint32_t>(std::stoull(key));
|
|
67
|
+
if (idx < dense.size())
|
|
68
|
+
return true;
|
|
69
|
+
if (sparse.find(idx) != sparse.end())
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
if (props.find(key) != props.end())
|
|
73
|
+
return true;
|
|
74
|
+
|
|
75
|
+
if (proto && !(*proto).is_null() && !(*proto).is_undefined())
|
|
76
|
+
{
|
|
77
|
+
if ((*proto).has_property(key))
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (ArrayPrototypes::get(key, const_cast<JsArray *>(this)).has_value())
|
|
82
|
+
return true;
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
60
86
|
jspp::AnyValue jspp::JsArray::get_property(const std::string &key, const AnyValue &thisVal)
|
|
61
87
|
{
|
|
62
88
|
if (
|
|
@@ -71,7 +97,26 @@ jspp::AnyValue jspp::JsArray::get_property(const std::string &key, const AnyValu
|
|
|
71
97
|
auto it = props.find(key);
|
|
72
98
|
if (it == props.end())
|
|
73
99
|
{
|
|
74
|
-
// check
|
|
100
|
+
// check special own properties (length)
|
|
101
|
+
if (key == "length")
|
|
102
|
+
{
|
|
103
|
+
auto proto_it = ArrayPrototypes::get(key, this);
|
|
104
|
+
if (proto_it.has_value())
|
|
105
|
+
{
|
|
106
|
+
return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// check explicit proto chain
|
|
111
|
+
if (proto && !(*proto).is_null() && !(*proto).is_undefined())
|
|
112
|
+
{
|
|
113
|
+
if ((*proto).has_property(key))
|
|
114
|
+
{
|
|
115
|
+
return (*proto).get_property_with_receiver(key, thisVal);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// check prototype (implicit Array.prototype)
|
|
75
120
|
auto proto_it = ArrayPrototypes::get(key, this);
|
|
76
121
|
if (proto_it.has_value())
|
|
77
122
|
{
|
|
@@ -88,12 +133,14 @@ jspp::AnyValue jspp::JsArray::get_property(uint32_t idx)
|
|
|
88
133
|
{
|
|
89
134
|
if (idx < dense.size())
|
|
90
135
|
{
|
|
91
|
-
|
|
136
|
+
const auto &val = dense[idx];
|
|
137
|
+
return val.is_uninitialized() ? AnyValue::make_undefined() : val;
|
|
92
138
|
}
|
|
93
139
|
const auto &it = sparse.find(idx);
|
|
94
140
|
if (it != sparse.end())
|
|
95
141
|
{
|
|
96
|
-
|
|
142
|
+
const auto &val = it->second;
|
|
143
|
+
return val.is_uninitialized() ? AnyValue::make_undefined() : val;
|
|
97
144
|
}
|
|
98
145
|
return AnyValue::make_undefined();
|
|
99
146
|
}
|
|
@@ -111,6 +158,12 @@ jspp::AnyValue jspp::JsArray::set_property(const std::string &key, const AnyValu
|
|
|
111
158
|
{
|
|
112
159
|
// set prototype property if accessor descriptor
|
|
113
160
|
auto proto_val_opt = ArrayPrototypes::get(key, this);
|
|
161
|
+
if (!proto_val_opt.has_value() && proto && !(*proto).is_null() && !(*proto).is_undefined())
|
|
162
|
+
{
|
|
163
|
+
// This is a bit simplified, ideally we should call get_property on proto to check descriptors
|
|
164
|
+
// For now, let's assume if it's not in ArrayPrototypes, it might be in the explicit proto chain
|
|
165
|
+
}
|
|
166
|
+
|
|
114
167
|
if (proto_val_opt.has_value())
|
|
115
168
|
{
|
|
116
169
|
auto proto_value = proto_val_opt.value();
|
|
@@ -147,35 +200,18 @@ jspp::AnyValue jspp::JsArray::set_property(uint32_t idx, const AnyValue &value)
|
|
|
147
200
|
const uint32_t DENSE_GROW_THRESHOLD = 1024;
|
|
148
201
|
if (idx < dense.size())
|
|
149
202
|
{
|
|
150
|
-
if (!dense[idx].has_value())
|
|
151
|
-
{
|
|
152
|
-
dense[idx] = AnyValue::make_undefined();
|
|
153
|
-
}
|
|
154
203
|
dense[idx] = value;
|
|
155
204
|
return value;
|
|
156
205
|
}
|
|
157
206
|
else if (idx <= dense.size() + DENSE_GROW_THRESHOLD)
|
|
158
207
|
{
|
|
159
|
-
dense.resize(idx + 1);
|
|
208
|
+
dense.resize(idx + 1, AnyValue::make_uninitialized());
|
|
160
209
|
dense[idx] = value;
|
|
161
210
|
return value;
|
|
162
211
|
}
|
|
163
212
|
else
|
|
164
213
|
{
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
{
|
|
168
|
-
if (!it->second.has_value())
|
|
169
|
-
{
|
|
170
|
-
it->second = AnyValue::make_undefined();
|
|
171
|
-
}
|
|
172
|
-
it->second = value;
|
|
173
|
-
return value;
|
|
174
|
-
}
|
|
175
|
-
else
|
|
176
|
-
{
|
|
177
|
-
sparse[idx] = value;
|
|
178
|
-
return value;
|
|
179
|
-
}
|
|
214
|
+
sparse[idx] = value;
|
|
215
|
+
return value;
|
|
180
216
|
}
|
|
181
217
|
}
|
|
@@ -1,125 +1,110 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include <variant>
|
|
4
|
+
#include <optional>
|
|
4
5
|
|
|
5
6
|
#include "types.hpp"
|
|
6
7
|
#include "values/function.hpp"
|
|
7
8
|
#include "any_value.hpp"
|
|
8
9
|
#include "values/prototypes/function.hpp"
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
namespace jspp
|
|
11
12
|
{
|
|
12
|
-
|
|
13
|
-
return "async function " + name + "() { [native code] }";
|
|
14
|
-
}
|
|
15
|
-
if (is_generator)
|
|
13
|
+
std::string JsFunction::to_std_string() const
|
|
16
14
|
{
|
|
17
|
-
|
|
15
|
+
std::string type_part = this->is_async ? "async function" : this->is_generator ? "function*"
|
|
16
|
+
: "function";
|
|
17
|
+
std::string name_part = this->name.value_or("");
|
|
18
|
+
return type_part + " " + name_part + "() { [native code] }";
|
|
18
19
|
}
|
|
19
|
-
return "function " + name + "() { [native code] }";
|
|
20
|
-
}
|
|
21
20
|
|
|
22
|
-
|
|
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))
|
|
21
|
+
AnyValue JsFunction::call(const AnyValue &thisVal, std::span<const AnyValue> args)
|
|
33
22
|
{
|
|
34
|
-
|
|
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())
|
|
23
|
+
if (std::function<AnyValue(const AnyValue &, std::span<const AnyValue>)> *func = std::get_if<0>(&callable))
|
|
49
24
|
{
|
|
50
|
-
return (*
|
|
25
|
+
return (*func)(thisVal, args);
|
|
51
26
|
}
|
|
52
|
-
|
|
53
|
-
// check prototype (implicit Function.prototype)
|
|
54
|
-
auto proto_it = FunctionPrototypes::get(key, this);
|
|
55
|
-
if (proto_it.has_value())
|
|
27
|
+
else if (std::function<jspp::JsIterator<jspp::AnyValue>(const AnyValue &, std::span<const AnyValue>)> *func = std::get_if<1>(&callable))
|
|
56
28
|
{
|
|
57
|
-
return AnyValue::
|
|
29
|
+
return AnyValue::from_iterator((*func)(thisVal, args));
|
|
58
30
|
}
|
|
59
|
-
|
|
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())
|
|
31
|
+
else if (std::function<jspp::JsPromise(const AnyValue &, std::span<const AnyValue>)> *func = std::get_if<2>(&callable))
|
|
73
32
|
{
|
|
74
|
-
return AnyValue::
|
|
33
|
+
return AnyValue::make_promise((*func)(thisVal, args));
|
|
75
34
|
}
|
|
76
|
-
|
|
35
|
+
else
|
|
77
36
|
{
|
|
78
|
-
return AnyValue::
|
|
37
|
+
return AnyValue::make_undefined();
|
|
79
38
|
}
|
|
80
39
|
}
|
|
81
40
|
|
|
82
|
-
|
|
83
|
-
auto it = props.find(key);
|
|
84
|
-
if (it != props.end())
|
|
41
|
+
bool JsFunction::has_property(const std::string &key) const
|
|
85
42
|
{
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
43
|
+
if (props.find(key) != props.end())
|
|
44
|
+
return true;
|
|
45
|
+
if (proto && !(*proto).is_null() && !(*proto).is_undefined())
|
|
46
|
+
{
|
|
47
|
+
if ((*proto).has_property(key))
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
if (FunctionPrototypes::get(key, const_cast<JsFunction *>(this)).has_value())
|
|
51
|
+
return true;
|
|
52
|
+
return false;
|
|
92
53
|
}
|
|
93
|
-
}
|
|
94
54
|
|
|
95
|
-
|
|
96
|
-
const jspp::AnyValue jspp::AnyValue::construct(const std::vector<AnyValue> &args) const
|
|
97
|
-
{
|
|
98
|
-
if (!is_function())
|
|
55
|
+
AnyValue JsFunction::get_property(const std::string &key, const AnyValue &thisVal)
|
|
99
56
|
{
|
|
100
|
-
|
|
101
|
-
|
|
57
|
+
auto it = props.find(key);
|
|
58
|
+
if (it == props.end())
|
|
59
|
+
{
|
|
60
|
+
// check explicit proto chain (e.g. for classes extending other classes)
|
|
61
|
+
if (proto && !(*proto).is_null() && !(*proto).is_undefined())
|
|
62
|
+
{
|
|
63
|
+
if ((*proto).has_property(key))
|
|
64
|
+
{
|
|
65
|
+
return (*proto).get_property_with_receiver(key, thisVal);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
102
68
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
69
|
+
// check prototype (implicit Function.prototype)
|
|
70
|
+
auto proto_it = FunctionPrototypes::get(key, this);
|
|
71
|
+
if (proto_it.has_value())
|
|
72
|
+
{
|
|
73
|
+
return AnyValue::resolve_property_for_read(proto_it.value(), thisVal, key);
|
|
74
|
+
}
|
|
75
|
+
// not found
|
|
76
|
+
return AnyValue::make_undefined();
|
|
77
|
+
}
|
|
78
|
+
return AnyValue::resolve_property_for_read(it->second, thisVal, key);
|
|
110
79
|
}
|
|
111
80
|
|
|
112
|
-
|
|
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())
|
|
81
|
+
AnyValue JsFunction::set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal)
|
|
121
82
|
{
|
|
122
|
-
|
|
83
|
+
// set prototype property if accessor descriptor
|
|
84
|
+
auto proto_it = FunctionPrototypes::get(key, this);
|
|
85
|
+
if (proto_it.has_value())
|
|
86
|
+
{
|
|
87
|
+
auto proto_value = proto_it.value();
|
|
88
|
+
if (proto_value.is_accessor_descriptor())
|
|
89
|
+
{
|
|
90
|
+
return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
|
|
91
|
+
}
|
|
92
|
+
if (proto_value.is_data_descriptor() && !proto_value.as_data_descriptor()->writable)
|
|
93
|
+
{
|
|
94
|
+
return AnyValue::resolve_property_for_write(proto_value, thisVal, value, key);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// set own property
|
|
99
|
+
auto it = props.find(key);
|
|
100
|
+
if (it != props.end())
|
|
101
|
+
{
|
|
102
|
+
return AnyValue::resolve_property_for_write(it->second, thisVal, value, key);
|
|
103
|
+
}
|
|
104
|
+
else
|
|
105
|
+
{
|
|
106
|
+
props[key] = value;
|
|
107
|
+
return value;
|
|
108
|
+
}
|
|
123
109
|
}
|
|
124
|
-
|
|
125
|
-
}
|
|
110
|
+
}
|
|
@@ -35,9 +35,9 @@ jspp::JsIterator<T>::NextResult jspp::JsIterator<T>::next(const T &val)
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
template <typename T>
|
|
38
|
-
std::vector<
|
|
38
|
+
std::vector<T> jspp::JsIterator<T>::to_vector()
|
|
39
39
|
{
|
|
40
|
-
std::vector<
|
|
40
|
+
std::vector<T> result;
|
|
41
41
|
while (true)
|
|
42
42
|
{
|
|
43
43
|
auto next = this->next();
|
|
@@ -45,7 +45,7 @@ std::vector<std::optional<T>> jspp::JsIterator<T>::to_vector()
|
|
|
45
45
|
{
|
|
46
46
|
break;
|
|
47
47
|
}
|
|
48
|
-
result.push_back(next.value);
|
|
48
|
+
result.push_back(next.value.value_or(AnyValue::make_undefined()));
|
|
49
49
|
}
|
|
50
50
|
return result;
|
|
51
51
|
}
|