@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
|
@@ -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);
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include <coroutine>
|
|
5
|
+
#include <optional>
|
|
6
|
+
#include <queue>
|
|
7
|
+
#include <iostream>
|
|
8
|
+
#include <utility>
|
|
9
|
+
#include <exception>
|
|
10
|
+
#include "values/promise.hpp"
|
|
11
|
+
#include "scheduler.hpp"
|
|
12
|
+
|
|
13
|
+
namespace jspp
|
|
14
|
+
{
|
|
15
|
+
// Forward declaration of AnyValue
|
|
16
|
+
class AnyValue;
|
|
17
|
+
|
|
18
|
+
template <typename T>
|
|
19
|
+
class JsAsyncIterator
|
|
20
|
+
{
|
|
21
|
+
public:
|
|
22
|
+
struct promise_type
|
|
23
|
+
{
|
|
24
|
+
std::queue<std::pair<JsPromise, T>> pending_calls;
|
|
25
|
+
bool is_awaiting = false;
|
|
26
|
+
bool is_running = false;
|
|
27
|
+
T current_input;
|
|
28
|
+
|
|
29
|
+
JsAsyncIterator get_return_object()
|
|
30
|
+
{
|
|
31
|
+
return JsAsyncIterator{
|
|
32
|
+
std::coroutine_handle<promise_type>::from_promise(*this)};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
std::suspend_always initial_suspend() noexcept { return {}; }
|
|
36
|
+
|
|
37
|
+
std::suspend_always final_suspend() noexcept { return {}; }
|
|
38
|
+
|
|
39
|
+
// Declarations
|
|
40
|
+
template <typename From>
|
|
41
|
+
auto yield_value(From &&from);
|
|
42
|
+
|
|
43
|
+
template <typename From>
|
|
44
|
+
void return_value(From &&from);
|
|
45
|
+
|
|
46
|
+
void unhandled_exception();
|
|
47
|
+
|
|
48
|
+
void fail_all(const AnyValue &reason);
|
|
49
|
+
|
|
50
|
+
auto await_transform(AnyValue value);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
using handle_type = std::coroutine_handle<promise_type>;
|
|
54
|
+
handle_type handle;
|
|
55
|
+
|
|
56
|
+
explicit JsAsyncIterator(handle_type h) : handle(h) {}
|
|
57
|
+
JsAsyncIterator(JsAsyncIterator &&other) noexcept : handle(std::exchange(other.handle, nullptr)) {}
|
|
58
|
+
|
|
59
|
+
JsAsyncIterator(const JsAsyncIterator &) = delete;
|
|
60
|
+
JsAsyncIterator &operator=(const JsAsyncIterator &) = delete;
|
|
61
|
+
|
|
62
|
+
~JsAsyncIterator()
|
|
63
|
+
{
|
|
64
|
+
if (handle)
|
|
65
|
+
handle.destroy();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
std::unordered_map<std::string, AnyValue> props;
|
|
69
|
+
|
|
70
|
+
std::string to_std_string() const;
|
|
71
|
+
|
|
72
|
+
JsPromise next(const T &val = T());
|
|
73
|
+
|
|
74
|
+
AnyValue get_property(const std::string &key, const AnyValue &thisVal);
|
|
75
|
+
AnyValue set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal);
|
|
76
|
+
|
|
77
|
+
void resume_next();
|
|
78
|
+
};
|
|
79
|
+
}
|
|
@@ -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,86 @@
|
|
|
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
|
|
15
|
+
std::function<jspp::JsAsyncIterator<jspp::AnyValue>(const AnyValue &, std::span<const AnyValue>)>>; // 3: Async Generator
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
struct JsFunction
|
|
18
|
+
{
|
|
19
|
+
JsFunctionCallable callable;
|
|
20
|
+
std::optional<std::string> name;
|
|
21
|
+
std::unordered_map<std::string, AnyValue> props;
|
|
22
|
+
std::shared_ptr<AnyValue> proto = nullptr;
|
|
23
|
+
bool is_generator;
|
|
24
|
+
bool is_async;
|
|
25
|
+
bool is_class;
|
|
26
|
+
bool is_constructor;
|
|
27
|
+
|
|
28
|
+
// ---- Constructor A: infer flags ----
|
|
29
|
+
JsFunction(const JsFunctionCallable &c,
|
|
30
|
+
std::optional<std::string> n = std::nullopt,
|
|
31
|
+
std::unordered_map<std::string, AnyValue> p = {},
|
|
32
|
+
bool is_cls = false,
|
|
33
|
+
bool is_ctor = true)
|
|
34
|
+
: callable(c),
|
|
35
|
+
name(std::move(n)),
|
|
36
|
+
props(std::move(p)),
|
|
37
|
+
is_generator(callable.index() == 1),
|
|
38
|
+
is_async(callable.index() == 2),
|
|
39
|
+
is_class(is_cls),
|
|
40
|
+
is_constructor(is_ctor && !is_generator && !is_async) // Generators and asyncs are never constructors
|
|
16
41
|
{
|
|
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;
|
|
42
|
+
}
|
|
24
43
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
// ---- Constructor B: explicit generator flag (backward compat) ----
|
|
45
|
+
JsFunction(const JsFunctionCallable &c,
|
|
46
|
+
bool is_gen,
|
|
47
|
+
std::optional<std::string> n = std::nullopt,
|
|
48
|
+
std::unordered_map<std::string, AnyValue> p = {},
|
|
49
|
+
bool is_cls = false,
|
|
50
|
+
bool is_ctor = true)
|
|
51
|
+
: callable(c),
|
|
52
|
+
name(std::move(n)),
|
|
53
|
+
props(std::move(p)),
|
|
54
|
+
is_generator(is_gen),
|
|
55
|
+
is_async(callable.index() == 2),
|
|
56
|
+
is_class(is_cls),
|
|
57
|
+
is_constructor(is_ctor && !is_gen && !is_async)
|
|
58
|
+
{
|
|
59
|
+
}
|
|
38
60
|
|
|
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
|
-
}
|
|
61
|
+
// ---- Constructor C: explicit async flag ----
|
|
62
|
+
JsFunction(const JsFunctionCallable &c,
|
|
63
|
+
bool is_gen,
|
|
64
|
+
bool is_async_func,
|
|
65
|
+
std::optional<std::string> n = std::nullopt,
|
|
66
|
+
std::unordered_map<std::string, AnyValue> p = {},
|
|
67
|
+
bool is_cls = false,
|
|
68
|
+
bool is_ctor = true)
|
|
69
|
+
: callable(c),
|
|
70
|
+
name(std::move(n)),
|
|
71
|
+
props(std::move(p)),
|
|
72
|
+
is_generator(is_gen),
|
|
73
|
+
is_async(is_async_func),
|
|
74
|
+
is_class(is_cls),
|
|
75
|
+
is_constructor(is_ctor && !is_gen && !is_async_func)
|
|
76
|
+
{
|
|
77
|
+
}
|
|
69
78
|
|
|
70
|
-
|
|
71
|
-
|
|
79
|
+
std::string to_std_string() const;
|
|
80
|
+
AnyValue call(const AnyValue &thisVal, std::span<const AnyValue> args);
|
|
72
81
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
bool has_property(const std::string &key) const;
|
|
83
|
+
AnyValue get_property(const std::string &key, const AnyValue &thisVal);
|
|
84
|
+
AnyValue set_property(const std::string &key, const AnyValue &value, const AnyValue &thisVal);
|
|
85
|
+
};
|
|
76
86
|
}
|
|
@@ -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
|
}
|