@auto_js/napi 0.0.1 → 0.0.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/CMakeLists.txt +10 -4
- package/README.md +30 -3
- package/_module.cc +12 -10
- package/api/api.cc +8 -7
- package/api/callback_info.cc +1 -7
- package/api/finalizer.cc +1 -4
- package/api/invoke.cc +4 -9
- package/api/uv_dlib.cc +27 -0
- package/api/uv_dlib.h.cc +21 -0
- package/api/uv_handle.cc +9 -9
- package/api/uv_scheduler.cc +11 -17
- package/api/uv_scheduler.h.cc +3 -6
- package/handle/bound_value.cc +4 -7
- package/handle/reference.cc +9 -5
- package/handle/remote.cc +11 -17
- package/handle/types.cc +61 -46
- package/handle/value.cc +12 -14
- package/package.json +7 -6
- package/support/callback.cc +7 -19
- package/support/callback_storage.cc +4 -9
- package/support/class_template_storage.cc +4 -6
- package/support/container.cc +9 -10
- package/support/environment.cc +32 -20
- package/support/environment.h.cc +8 -18
- package/support/environment_fwd.cc +1 -2
- package/support/error_scope.cc +0 -2
- package/support/initialize.h.cc +2 -5
- package/support/promise.cc +3 -10
- package/support/string_table.cc +3 -5
- package/support/utility.cc +54 -28
- package/transfer/accept.cc +131 -327
- package/transfer/accept.h.cc +390 -0
- package/transfer/visit.cc +201 -132
- package/value/array.cc +1 -3
- package/value/array.h.cc +5 -11
- package/value/array_buffer.cc +109 -0
- package/value/array_buffer.h.cc +150 -0
- package/value/class.cc +12 -21
- package/value/class.h.cc +5 -10
- package/value/external.cc +6 -10
- package/value/function.cc +5 -12
- package/value/function.h.cc +2 -9
- package/value/object.cc +2 -6
- package/value/object.h.cc +7 -15
- package/value/primitive.cc +12 -81
- package/value/primitive.h.cc +6 -64
- package/value/record.cc +38 -0
- package/value/record.h.cc +39 -0
- package/value/value.cc +8 -8
- package/value/dictionary.cc +0 -33
- package/value/dictionary.h.cc +0 -56
package/support/string_table.cc
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
module;
|
|
2
|
-
#include <string> // IWYU pragma: keep
|
|
3
|
-
#include <type_traits>
|
|
4
1
|
export module napi_js:string_table;
|
|
5
2
|
import :reference;
|
|
6
3
|
import auto_js;
|
|
4
|
+
import std;
|
|
7
5
|
import util;
|
|
8
6
|
using namespace std::string_literals;
|
|
9
7
|
|
|
@@ -26,8 +24,8 @@ struct string_table_options {
|
|
|
26
24
|
export template <const auto& Strings, string_table_options Options = {}>
|
|
27
25
|
class string_table {
|
|
28
26
|
public:
|
|
29
|
-
auto string_table_storage(
|
|
30
|
-
constexpr auto string_sv = util::
|
|
27
|
+
auto string_table_storage(auto string_value) {
|
|
28
|
+
constexpr auto string_sv = util::make_consteval_string_view(string_value);
|
|
31
29
|
constexpr auto index = string_table_of<Strings>.lookup(string_sv);
|
|
32
30
|
if constexpr (index) {
|
|
33
31
|
return util::just<napi::reference<string_tag>&>{string_literal_storage_.at(index).second};
|
package/support/utility.cc
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module;
|
|
2
|
-
#include
|
|
2
|
+
#include "auto_js/no_unique_address.h"
|
|
3
3
|
export module napi_js:utility;
|
|
4
|
-
import :environment;
|
|
5
4
|
import nodejs;
|
|
5
|
+
import std;
|
|
6
6
|
import util;
|
|
7
7
|
|
|
8
8
|
namespace js::napi {
|
|
@@ -11,47 +11,71 @@ namespace js::napi {
|
|
|
11
11
|
|
|
12
12
|
// Null handle for both direct and indirect handles
|
|
13
13
|
// Note: 1 -> 0x1'0000'0000
|
|
14
|
-
const
|
|
15
|
-
|
|
14
|
+
const std::uint64_t null_value_handle_data = 0x7f7f'7f7f'7f7f'7f7f;
|
|
15
|
+
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
|
16
|
+
auto* const null_value_handle = reinterpret_cast<napi_value>(const_cast<std::uint64_t*>(&null_value_handle_data));
|
|
16
17
|
|
|
17
|
-
//
|
|
18
|
+
// Unwrap the v8 address of the napi handle. This points into the v8 heap.
|
|
18
19
|
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
|
|
19
|
-
|
|
20
|
+
struct virtual_handle_address {
|
|
20
21
|
protected:
|
|
21
|
-
~
|
|
22
|
+
~virtual_handle_address() = default;
|
|
22
23
|
|
|
23
24
|
public:
|
|
24
|
-
virtual auto operator()(napi_value
|
|
25
|
+
virtual auto operator()(napi_value value) const noexcept -> void* = 0;
|
|
25
26
|
};
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
auto operator()(napi_value
|
|
29
|
-
return
|
|
28
|
+
struct direct_handle_address final : virtual_handle_address {
|
|
29
|
+
auto operator()(napi_value value) const noexcept -> void* final {
|
|
30
|
+
return value;
|
|
30
31
|
}
|
|
31
32
|
};
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
auto operator()(napi_value
|
|
35
|
-
|
|
36
|
-
auto* indirect_right = reinterpret_cast<void**>(right);
|
|
37
|
-
return *indirect_left == *indirect_right;
|
|
34
|
+
struct indirect_handle_address final : virtual_handle_address {
|
|
35
|
+
auto operator()(napi_value value) const noexcept -> void* final {
|
|
36
|
+
return *reinterpret_cast<void**>(value);
|
|
38
37
|
}
|
|
39
38
|
};
|
|
40
39
|
|
|
41
|
-
//
|
|
40
|
+
// Address equality for underlying napi handles.
|
|
41
|
+
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
|
|
42
|
+
struct virtual_address_equal {
|
|
43
|
+
protected:
|
|
44
|
+
~virtual_address_equal() = default;
|
|
45
|
+
|
|
46
|
+
public:
|
|
47
|
+
virtual auto operator()(napi_value left, napi_value right) const noexcept -> bool = 0;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
template <class Address>
|
|
51
|
+
struct virtual_address_equal_of final : virtual_address_equal {
|
|
52
|
+
public:
|
|
53
|
+
auto operator()(napi_value left, napi_value right) const noexcept -> bool final {
|
|
54
|
+
return address_(left) == address_(right);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private:
|
|
58
|
+
NO_UNIQUE_ADDRESS Address address_;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
using direct_address_equal = virtual_address_equal_of<direct_handle_address>;
|
|
62
|
+
using indirect_address_equal = virtual_address_equal_of<indirect_handle_address>;
|
|
63
|
+
|
|
64
|
+
// Polymorphic address equality operator
|
|
42
65
|
export class address_equal {
|
|
43
66
|
private:
|
|
44
67
|
using virtual_equal_type = util::covariant_value<virtual_address_equal, direct_address_equal, indirect_address_equal>;
|
|
45
68
|
|
|
46
69
|
public:
|
|
47
|
-
explicit address_equal(
|
|
70
|
+
explicit address_equal(bool uses_direct_handles) :
|
|
48
71
|
equal_{
|
|
49
|
-
|
|
72
|
+
uses_direct_handles
|
|
50
73
|
? virtual_equal_type{direct_address_equal{}}
|
|
51
74
|
: virtual_equal_type{indirect_address_equal{}}
|
|
52
75
|
} {}
|
|
53
76
|
|
|
54
|
-
auto operator()(napi_value left, napi_value right) const -> bool {
|
|
77
|
+
auto operator()(napi_value left, napi_value right) const noexcept -> bool {
|
|
78
|
+
// NOLINTNEXTLINE(bugprone-exception-escape)
|
|
55
79
|
return (*equal_)(left, right);
|
|
56
80
|
}
|
|
57
81
|
|
|
@@ -60,17 +84,19 @@ export class address_equal {
|
|
|
60
84
|
};
|
|
61
85
|
|
|
62
86
|
// Address hash for napi value handles.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
export struct indirect_address_hash : std::hash<void*> {
|
|
66
|
-
private:
|
|
67
|
-
using std::hash<void*>::operator();
|
|
68
|
-
|
|
87
|
+
template <class Address>
|
|
88
|
+
struct address_hash_of final {
|
|
69
89
|
public:
|
|
70
90
|
auto operator()(napi_value value) const noexcept -> std::size_t {
|
|
71
|
-
|
|
72
|
-
return (*this)(*indirect_handle);
|
|
91
|
+
return hash_(address_(value));
|
|
73
92
|
}
|
|
93
|
+
|
|
94
|
+
private:
|
|
95
|
+
NO_UNIQUE_ADDRESS Address address_;
|
|
96
|
+
NO_UNIQUE_ADDRESS std::hash<void*> hash_;
|
|
74
97
|
};
|
|
75
98
|
|
|
99
|
+
using direct_address_hash = address_hash_of<direct_handle_address>;
|
|
100
|
+
using indirect_address_hash = address_hash_of<indirect_handle_address>;
|
|
101
|
+
|
|
76
102
|
} // namespace js::napi
|
package/transfer/accept.cc
CHANGED
|
@@ -1,349 +1,153 @@
|
|
|
1
|
-
module;
|
|
2
|
-
|
|
3
|
-
#include <string_view>
|
|
4
|
-
#include <tuple>
|
|
5
|
-
#include <utility>
|
|
6
|
-
#include <variant>
|
|
7
|
-
#include <vector>
|
|
8
|
-
export module napi_js:accept;
|
|
9
|
-
import :api;
|
|
10
|
-
import :container;
|
|
11
|
-
import :environment_fwd;
|
|
12
|
-
import :value;
|
|
13
|
-
import util;
|
|
1
|
+
module napi_js;
|
|
2
|
+
import std;
|
|
14
3
|
|
|
15
|
-
namespace js {
|
|
16
|
-
using namespace napi;
|
|
4
|
+
namespace js::napi {
|
|
17
5
|
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
template <class Meta>
|
|
23
|
-
using accept_napi_value_with = accept_napi_value<typename Meta::accept_context_type>;
|
|
24
|
-
|
|
25
|
-
template <class Environment>
|
|
26
|
-
struct accept_napi_value : napi::environment_scope<Environment> {
|
|
27
|
-
public:
|
|
28
|
-
// nb: This marks this acceptor as referential!
|
|
29
|
-
using accept_reference_type = napi_value;
|
|
30
|
-
|
|
31
|
-
using napi::environment_scope<Environment>::environment;
|
|
32
|
-
|
|
33
|
-
explicit accept_napi_value(auto* /*transfer*/, auto& env) :
|
|
34
|
-
napi::environment_scope<Environment>{env} {}
|
|
35
|
-
|
|
36
|
-
// reference provider
|
|
37
|
-
constexpr auto operator()(std::type_identity<napi_value> /*type*/, napi_value value) const -> napi_value { return value; }
|
|
38
|
-
|
|
39
|
-
template <class Tag>
|
|
40
|
-
constexpr auto operator()(std::type_identity<napi::value<Tag>> /*type*/, napi_value value) const -> napi::value<Tag> {
|
|
41
|
-
return napi::value<Tag>::from(value);
|
|
42
|
-
}
|
|
6
|
+
// undefined & null
|
|
7
|
+
auto accept_basic_napi_value::operator()(undefined_tag /*tag*/, visit_holder /*visit*/, std::monostate /*subject*/) const -> value_of<undefined_tag> {
|
|
8
|
+
return value_of<undefined_tag>::from(napi::invoke(napi_get_undefined, napi_env{*this}));
|
|
9
|
+
}
|
|
43
10
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
11
|
+
auto accept_basic_napi_value::operator()(null_tag /*tag*/, visit_holder /*visit*/, std::nullptr_t /*subject*/) const -> value_of<null_tag> {
|
|
12
|
+
return value_of<null_tag>::from(napi::invoke(napi_get_null, napi_env{*this}));
|
|
13
|
+
}
|
|
48
14
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
15
|
+
// boolean
|
|
16
|
+
auto accept_basic_napi_value::operator()(boolean_tag /*tag*/, visit_holder /*visit*/, bool subject) const -> value_of<boolean_tag> {
|
|
17
|
+
return value_of<boolean_tag>::from(napi::invoke(napi_get_boolean, napi_env{*this}, subject));
|
|
18
|
+
}
|
|
52
19
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
20
|
+
// number
|
|
21
|
+
auto accept_basic_napi_value::operator()(number_tag_of<double> /*tag*/, visit_holder /*visit*/, double subject) const -> value_of<number_tag_of<double>> {
|
|
22
|
+
return value_of<number_tag_of<double>>::from(napi::invoke(napi_create_double, napi_env{*this}, subject));
|
|
23
|
+
}
|
|
57
24
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
25
|
+
auto accept_basic_napi_value::operator()(number_tag_of<std::int32_t> /*tag*/, visit_holder /*visit*/, std::int32_t subject) const -> value_of<number_tag_of<std::int32_t>> {
|
|
26
|
+
return value_of<number_tag_of<std::int32_t>>::from(napi::invoke(napi_create_int32, napi_env{*this}, subject));
|
|
27
|
+
}
|
|
62
28
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
29
|
+
auto accept_basic_napi_value::operator()(number_tag_of<std::uint32_t> /*tag*/, visit_holder /*visit*/, std::uint32_t subject) const -> value_of<number_tag_of<std::uint32_t>> {
|
|
30
|
+
return value_of<number_tag_of<std::uint32_t>>::from(napi::invoke(napi_create_uint32, napi_env{*this}, subject));
|
|
31
|
+
}
|
|
67
32
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
33
|
+
// string
|
|
34
|
+
auto accept_basic_napi_value::operator()(string_tag_of<char> /*tag*/, visit_holder /*visit*/, std::string_view subject) const
|
|
35
|
+
-> js::referenceable_value<value_of<string_tag_of<char>>> {
|
|
36
|
+
auto* value = napi::invoke(napi_create_string_latin1, napi_env{*this}, subject.data(), subject.length());
|
|
37
|
+
return js::referenceable_value{value_of<string_tag_of<char>>::from(value)};
|
|
38
|
+
}
|
|
73
39
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
40
|
+
auto accept_basic_napi_value::operator()(string_tag_of<char8_t> /*tag*/, visit_holder /*visit*/, std::u8string_view subject) const
|
|
41
|
+
-> js::referenceable_value<value_of<string_tag_of<char8_t>>> {
|
|
42
|
+
auto* value = napi::invoke(napi_create_string_utf8, napi_env{*this}, reinterpret_cast<const char*>(subject.data()), subject.length());
|
|
43
|
+
return js::referenceable_value{value_of<string_tag_of<char8_t>>::from(value)};
|
|
44
|
+
}
|
|
78
45
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
46
|
+
auto accept_basic_napi_value::operator()(string_tag_of<char16_t> /*tag*/, visit_holder /*visit*/, std::u16string_view subject) const
|
|
47
|
+
-> js::referenceable_value<value_of<string_tag_of<char16_t>>> {
|
|
48
|
+
auto* value = napi::invoke(napi_create_string_utf16, napi_env{*this}, subject.data(), subject.length());
|
|
49
|
+
return js::referenceable_value{value_of<string_tag_of<char16_t>>::from(value)};
|
|
50
|
+
}
|
|
83
51
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
52
|
+
// bigint
|
|
53
|
+
auto accept_basic_napi_value::operator()(bigint_tag_of<std::int64_t> /*tag*/, visit_holder /*visit*/, std::int64_t subject) const
|
|
54
|
+
-> js::referenceable_value<value_of<bigint_tag_of<std::int64_t>>> {
|
|
55
|
+
auto* value = napi::invoke(napi_create_bigint_int64, napi_env{*this}, subject);
|
|
56
|
+
return js::referenceable_value{value_of<bigint_tag_of<std::int64_t>>::from(value)};
|
|
57
|
+
}
|
|
89
58
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
59
|
+
auto accept_basic_napi_value::operator()(bigint_tag_of<std::uint64_t> /*tag*/, visit_holder /*visit*/, std::uint64_t subject) const
|
|
60
|
+
-> js::referenceable_value<value_of<bigint_tag_of<std::uint64_t>>> {
|
|
61
|
+
auto* value = napi::invoke(napi_create_bigint_uint64, napi_env{*this}, subject);
|
|
62
|
+
return js::referenceable_value{value_of<bigint_tag_of<std::uint64_t>>::from(value)};
|
|
63
|
+
}
|
|
95
64
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
65
|
+
auto accept_basic_napi_value::operator()(bigint_tag_of<js::bigint> /*tag*/, visit_holder /*visit*/, const js::bigint& subject) const
|
|
66
|
+
-> js::referenceable_value<value_of<bigint_tag_of<js::bigint>>> {
|
|
67
|
+
auto* value = napi::invoke(napi_create_bigint_words, napi_env{*this}, subject.sign_bit(), subject.size(), subject.data());
|
|
68
|
+
return js::referenceable_value{value_of<bigint_tag_of<js::bigint>>::from(value)};
|
|
69
|
+
}
|
|
101
70
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
71
|
+
// NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
|
|
72
|
+
auto accept_basic_napi_value::operator()(bigint_tag_of<js::bigint> tag, visit_holder visit, js::bigint&& subject) const
|
|
73
|
+
-> js::referenceable_value<value_of<bigint_tag_of<js::bigint>>> {
|
|
74
|
+
return (*this)(tag, visit, static_cast<const js::bigint&>(subject));
|
|
75
|
+
}
|
|
107
76
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
77
|
+
// date
|
|
78
|
+
auto accept_basic_napi_value::operator()(date_tag /*tag*/, visit_holder /*visit*/, js_clock::time_point subject) const
|
|
79
|
+
-> js::referenceable_value<value_of<date_tag>> {
|
|
80
|
+
auto value = value_of<date_tag>::from(napi::invoke(napi_create_date, napi_env{*this}, subject.time_since_epoch().count()));
|
|
81
|
+
return js::referenceable_value{value};
|
|
82
|
+
}
|
|
113
83
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
84
|
+
// error
|
|
85
|
+
auto accept_basic_napi_value::operator()(error_tag /*tag*/, visit_holder visit, const js::error_value& subject) const
|
|
86
|
+
-> js::referenceable_value<value_of<error_tag>> {
|
|
87
|
+
auto* message = napi_value{js::transfer_in<value_of<string_tag>>(subject.message(), environment())};
|
|
88
|
+
auto* error = [ & ] -> napi_value {
|
|
89
|
+
switch (subject.name()) {
|
|
90
|
+
default:
|
|
91
|
+
return napi::invoke(napi_create_error, napi_env{*this}, napi_value{}, message);
|
|
92
|
+
case js::error_name::range_error:
|
|
93
|
+
return napi::invoke(napi_create_range_error, napi_env{*this}, napi_value{}, message);
|
|
94
|
+
case js::error_name::syntax_error:
|
|
95
|
+
return napi::invoke(node_api_create_syntax_error, napi_env{*this}, napi_value{}, message);
|
|
96
|
+
case js::error_name::type_error:
|
|
97
|
+
return napi::invoke(napi_create_type_error, napi_env{*this}, napi_value{}, message);
|
|
98
|
+
}
|
|
99
|
+
}();
|
|
100
|
+
auto stack = (*this)(string_tag{}, visit, subject.stack());
|
|
101
|
+
napi::invoke0(napi_set_named_property, napi_env{*this}, error, "stack", *std::move(stack));
|
|
102
|
+
return js::referenceable_value{value_of<error_tag>::from(error)};
|
|
103
|
+
}
|
|
119
104
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}();
|
|
136
|
-
return js::referenceable_value{napi::value<error_tag>::from(error)};
|
|
137
|
-
}
|
|
105
|
+
// data blocks (array buffer, shared array buffer)
|
|
106
|
+
auto accept_basic_napi_value::operator()(array_buffer_tag /*tag*/, visit_holder /*visit*/, const js::array_buffer& subject) const
|
|
107
|
+
-> js::referenceable_value<value_of<array_buffer_tag>> {
|
|
108
|
+
// You could avoid the extra copy for `js::data_block&&` here w/ v8 API. Napi requires the copy
|
|
109
|
+
// though.
|
|
110
|
+
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
|
|
111
|
+
void* bytes;
|
|
112
|
+
auto* result = napi::invoke(napi_create_arraybuffer, napi_env{*this}, subject.size(), &bytes);
|
|
113
|
+
// nb: `std::memcpy` *technically* results in undefined behavior on block size 0
|
|
114
|
+
// (and also) it maybe causes an infinite loop with musl
|
|
115
|
+
// https://stackoverflow.com/questions/5243012/is-it-guaranteed-to-be-safe-to-perform-memcpy0-0-0
|
|
116
|
+
std::ranges::copy(std::span<const std::byte>{subject}, static_cast<std::byte*>(bytes));
|
|
117
|
+
auto value = value_of<array_buffer_tag>::from(result);
|
|
118
|
+
return js::referenceable_value{value};
|
|
119
|
+
}
|
|
138
120
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
121
|
+
auto accept_basic_napi_value::operator()(shared_array_buffer_tag /*tag*/, visit_holder /*visit*/, js::shared_array_buffer&& subject) const
|
|
122
|
+
-> js::referenceable_value<value_of<shared_array_buffer_tag>> {
|
|
123
|
+
auto backing_store = [ & ]() -> auto {
|
|
124
|
+
auto byte_length = subject.size();
|
|
125
|
+
// v8 does not call the deleter `byte_length` is zero. So the heap-allocated shared_ptr trick
|
|
126
|
+
// does not work in that case.
|
|
127
|
+
if (byte_length == 0) {
|
|
128
|
+
return v8::SharedArrayBuffer::NewBackingStore(nullptr, 0, nullptr, nullptr);
|
|
129
|
+
} else {
|
|
130
|
+
auto holder = std::make_unique<js::shared_array_buffer::shared_pointer_type>(std::move(subject).acquire_ownership());
|
|
131
|
+
auto backing_store = v8::SharedArrayBuffer::NewBackingStore(
|
|
132
|
+
holder->get(),
|
|
133
|
+
byte_length,
|
|
134
|
+
[](void* /*data*/, std::size_t /*length*/, void* param) -> void {
|
|
135
|
+
delete static_cast<js::shared_array_buffer::shared_pointer_type*>(param);
|
|
152
136
|
},
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const auto [... indices ] = util::sequence<Size>;
|
|
164
|
-
(..., [ & ]() -> void {
|
|
165
|
-
// nb: This is forwarded to *each* visitor. The visitor should be aware and only lvalue
|
|
166
|
-
// reference members one at a time.
|
|
167
|
-
auto* element = napi_value{visit(indices, std::forward<decltype(tuple)>(tuple), self)};
|
|
168
|
-
napi::invoke0(napi_set_element, napi_env{self}, napi_value{array}, indices, element);
|
|
169
|
-
}());
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// arrays & dictionaries
|
|
175
|
-
auto operator()(this const auto& self, list_tag /*tag*/, auto& visit, auto&& subject)
|
|
176
|
-
-> js::deferred_receiver<napi::value<list_tag>, decltype(self), decltype(visit), decltype(subject)> {
|
|
177
|
-
return {
|
|
178
|
-
napi::value<list_tag>::from(napi::invoke(napi_create_array, napi_env{self})),
|
|
179
|
-
std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
|
|
180
|
-
[](napi::value<list_tag> array, auto& self, auto& visit, auto /*&&*/ subject) -> void {
|
|
181
|
-
self.accept_entry_pair_vector(visit, array, std::forward<decltype(subject)>(subject));
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
auto operator()(this const auto& self, dictionary_tag /*tag*/, auto& visit, auto&& subject)
|
|
187
|
-
-> js::deferred_receiver<napi::value<dictionary_tag>, decltype(self), decltype(visit), decltype(subject)> {
|
|
188
|
-
return {
|
|
189
|
-
napi::value<dictionary_tag>::from(napi::invoke(napi_create_object, napi_env{self})),
|
|
190
|
-
std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
|
|
191
|
-
[](napi::value<dictionary_tag> object, auto& self, auto& visit, auto /*&&*/ subject) -> void {
|
|
192
|
-
self.accept_entry_pair_vector(visit, object, std::forward<decltype(subject)>(subject));
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
auto accept_entry_pair_vector(this const auto& self, auto& visit, value<object_tag> target, auto&& subject) -> void {
|
|
198
|
-
std::vector<napi_property_descriptor> properties;
|
|
199
|
-
auto&& range = util::into_range(std::forward<decltype(subject)>(subject));
|
|
200
|
-
properties.reserve(std::size(range));
|
|
201
|
-
for (auto&& [ key, value ] : util::forward_range(std::forward<decltype(range)>(range))) {
|
|
202
|
-
properties.emplace_back(napi_property_descriptor{
|
|
203
|
-
.utf8name{},
|
|
204
|
-
.name = napi_value{visit.first(std::forward<decltype(key)>(key), self)},
|
|
205
|
-
|
|
206
|
-
.method{},
|
|
207
|
-
.getter{},
|
|
208
|
-
.setter{},
|
|
209
|
-
.value = napi_value{visit.second(std::forward<decltype(value)>(value), self)},
|
|
210
|
-
|
|
211
|
-
// NOLINTNEXTLINE(hicpp-signed-bitwise)
|
|
212
|
-
.attributes = static_cast<napi_property_attributes>(napi_writable | napi_enumerable | napi_configurable),
|
|
213
|
-
.data{},
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
napi::invoke0(napi_define_properties, napi_env{self}, napi_value{target}, properties.size(), properties.data());
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// structs
|
|
220
|
-
template <std::size_t Size>
|
|
221
|
-
auto operator()(this const auto& self, struct_tag<Size> /*tag*/, auto& visit, auto&& subject)
|
|
222
|
-
-> js::deferred_receiver<napi::value<dictionary_tag>, decltype(self), decltype(visit), decltype(subject)> {
|
|
223
|
-
return {
|
|
224
|
-
napi::value<dictionary_tag>::from(napi::invoke(napi_create_object, napi_env{self})),
|
|
225
|
-
std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
|
|
226
|
-
[](napi::value<dictionary_tag> object, auto& self, auto& visit, auto /*&&*/ subject) -> void {
|
|
227
|
-
self.template accept_entry_pair_struct<Size>(visit, object, std::forward<decltype(subject)>(subject));
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
template <std::size_t Size>
|
|
233
|
-
auto accept_entry_pair_struct(this const auto& self, auto& visit, value<object_tag> target, auto&& subject) -> void {
|
|
234
|
-
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
|
|
235
|
-
std::array<napi_property_descriptor, Size> properties;
|
|
236
|
-
const auto [... indices ] = util::sequence<Size>;
|
|
237
|
-
(..., [ & ]() -> void {
|
|
238
|
-
// nb: This is forwarded to *each* visitor. The visitor should be aware and only lvalue
|
|
239
|
-
// reference members one at a time.
|
|
240
|
-
auto accept_entry = accept_entry_pair<decltype(self), decltype(self)>{self};
|
|
241
|
-
auto entry = visit(std::integral_constant<std::size_t, indices>{}, std::forward<decltype(subject)>(subject), accept_entry);
|
|
242
|
-
// NOLINTNEXTLINE(modernize-type-traits)
|
|
243
|
-
properties.at(indices) = {
|
|
244
|
-
.utf8name{},
|
|
245
|
-
.name = entry.first,
|
|
246
|
-
|
|
247
|
-
.method{},
|
|
248
|
-
.getter{},
|
|
249
|
-
.setter{},
|
|
250
|
-
.value = entry.second,
|
|
251
|
-
|
|
252
|
-
// NOLINTNEXTLINE(hicpp-signed-bitwise)
|
|
253
|
-
.attributes = static_cast<napi_property_attributes>(napi_writable | napi_enumerable | napi_configurable),
|
|
254
|
-
.data{},
|
|
255
|
-
};
|
|
256
|
-
}());
|
|
257
|
-
napi::invoke0(napi_define_properties, napi_env{self}, napi_value{target}, properties.size(), properties.data());
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// no required types
|
|
261
|
-
consteval static auto types(auto /*recursive*/) { return util::type_pack{}; }
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
// Plain napi_value acceptor
|
|
265
|
-
template <>
|
|
266
|
-
struct accept_property_subject<napi_value> : std::type_identity<napi_value> {};
|
|
267
|
-
|
|
268
|
-
template <class Meta>
|
|
269
|
-
struct accept<Meta, napi_value> : accept_napi_value_with<Meta> {
|
|
270
|
-
using accept_type = accept_napi_value_with<Meta>;
|
|
271
|
-
using accept_type::accept_type;
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
// Tagged `napi::value<T>` acceptor
|
|
275
|
-
template <>
|
|
276
|
-
struct accept_property_subject<napi::value<value_tag>> : std::type_identity<napi_value> {};
|
|
277
|
-
|
|
278
|
-
template <class Meta>
|
|
279
|
-
struct accept<Meta, napi::value<value_tag>> : accept_napi_value_with<Meta> {
|
|
280
|
-
using accept_type = accept_napi_value_with<Meta>;
|
|
281
|
-
using accept_type::accept_type;
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
// Forwarded `napi::value<T>` acceptor
|
|
285
|
-
template <class Tag>
|
|
286
|
-
struct accept<void, js::forward<napi::value<Tag>, Tag>> {
|
|
287
|
-
auto operator()(Tag /*tag*/, visit_holder /*visit*/, napi::value<Tag> value) const -> js::forward<napi::value<Tag>, Tag> {
|
|
288
|
-
return js::forward{napi::value<Tag>{value}, Tag{}};
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
consteval static auto types(auto /*recursive*/) { return util::type_pack{}; }
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
// Object key lookup via napi
|
|
295
|
-
template <class Meta, auto Key, class Type>
|
|
296
|
-
struct accept_property_value<Meta, Key, Type, napi_value> {
|
|
297
|
-
public:
|
|
298
|
-
explicit constexpr accept_property_value(auto* transfer) :
|
|
299
|
-
first{transfer},
|
|
300
|
-
second{transfer} {}
|
|
301
|
-
|
|
302
|
-
auto operator()(dictionary_tag /*tag*/, auto& visit, const auto& object) const -> Type {
|
|
303
|
-
if (auto local = first(std::type_identity<void>{}, visit.first); object.has(local)) {
|
|
304
|
-
return visit.second(object.get(local), second);
|
|
305
|
-
} else {
|
|
306
|
-
return second(undefined_in_tag{}, visit.second, std::monostate{});
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
private:
|
|
311
|
-
mutable visit_key_literal<Key, napi_value> first;
|
|
312
|
-
accept_value<Meta, Type> second;
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
// `value<object_tag>{}.assign(...)` implementation
|
|
316
|
-
struct object_assign_delegate {
|
|
317
|
-
public:
|
|
318
|
-
explicit object_assign_delegate(value<object_tag> object) : object_{object} {}
|
|
319
|
-
auto operator*() const { return object_; }
|
|
320
|
-
|
|
321
|
-
private:
|
|
322
|
-
value<object_tag> object_;
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
template <class Meta>
|
|
326
|
-
struct accept<Meta, object_assign_delegate> {
|
|
327
|
-
public:
|
|
328
|
-
accept(auto* transfer, auto& env, object_assign_delegate object) :
|
|
329
|
-
accept_{transfer, env},
|
|
330
|
-
object_{object} {}
|
|
331
|
-
|
|
332
|
-
template <std::size_t Size>
|
|
333
|
-
auto operator()(this const auto& self, tuple_tag<Size> /*tag*/, auto& visit, auto&& subject) -> object_assign_delegate {
|
|
334
|
-
self.accept_.template accept_entry_pair_struct<Size>(visit, *self.object_, std::forward<decltype(subject)>(subject));
|
|
335
|
-
return self.object_;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
consteval static auto types(auto recursive) { return accept<Meta, napi_value>::types(recursive); }
|
|
339
|
-
|
|
340
|
-
private:
|
|
341
|
-
accept_value<Meta, napi_value> accept_;
|
|
342
|
-
object_assign_delegate object_;
|
|
343
|
-
};
|
|
137
|
+
holder.get()
|
|
138
|
+
);
|
|
139
|
+
std::ignore = holder.release();
|
|
140
|
+
return backing_store;
|
|
141
|
+
}
|
|
142
|
+
}();
|
|
143
|
+
auto shared_array_buffer = v8::SharedArrayBuffer::New(v8::Isolate::GetCurrent(), std::move(backing_store));
|
|
144
|
+
auto value = value_of<shared_array_buffer_tag>::from(std::bit_cast<napi_value>(shared_array_buffer));
|
|
145
|
+
return js::referenceable_value{value};
|
|
146
|
+
}
|
|
344
147
|
|
|
345
|
-
auto
|
|
346
|
-
js::
|
|
148
|
+
auto accept_basic_napi_value::operator()(shared_array_buffer_tag tag, visit_holder visit, const js::shared_array_buffer& subject) const
|
|
149
|
+
-> js::referenceable_value<value_of<shared_array_buffer_tag>> {
|
|
150
|
+
return (*this)(tag, visit, js::shared_array_buffer{subject});
|
|
347
151
|
}
|
|
348
152
|
|
|
349
|
-
} // namespace js
|
|
153
|
+
} // namespace js::napi
|