@auto_js/napi 0.0.5 → 0.0.7
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 +18 -8
- package/_module.cc +0 -1
- package/api/api.cc +10 -8
- package/api/finalizer.cc +47 -23
- package/api/napi_scheduler.cc +39 -0
- package/api/napi_scheduler.h.cc +58 -0
- package/api/threadsafe_function.cc +155 -0
- package/handle/bound_value.cc +1 -0
- package/handle/remote.cc +4 -5
- package/handle/value.cc +5 -0
- package/package.json +4 -4
- package/support/callback.cc +1 -1
- package/support/environment.cc +12 -31
- package/support/environment.h.cc +1 -8
- package/support/host.cc +230 -0
- package/support/host.h.cc +56 -0
- package/support/host_shim.cc +42 -0
- package/support/promise.cc +4 -6
- package/support/utility.cc +10 -85
- package/transfer/accept.cc +1 -22
- package/transfer/accept.h.cc +1 -1
- package/transfer/visit.cc +87 -82
- package/value/array_buffer.cc +7 -20
- package/value/array_buffer.h.cc +1 -23
- package/value/class.cc +1 -1
- package/support/container.cc +0 -77
package/transfer/visit.cc
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export module napi_js:visit;
|
|
2
|
-
import :
|
|
2
|
+
import :utility;
|
|
3
3
|
import :value;
|
|
4
4
|
import std;
|
|
5
5
|
import util;
|
|
@@ -10,7 +10,7 @@ namespace js::napi {
|
|
|
10
10
|
// Instantiated in the acceptor that corresponds to a napi visitor
|
|
11
11
|
struct reference_map_type {
|
|
12
12
|
template <class Type>
|
|
13
|
-
using type = napi::
|
|
13
|
+
using type = napi::unordered_value_map<Type>;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
// Visitor which may visit only property names. `symbol` should probably be rethought since they are
|
|
@@ -104,7 +104,6 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
|
|
|
104
104
|
using reference_map_t<Reference, reference_map_type>::lookup_or_visit;
|
|
105
105
|
|
|
106
106
|
visit_value(auto* /*transfer*/, Environment& env) :
|
|
107
|
-
reference_map_t<Reference, reference_map_type>{env},
|
|
108
107
|
env_{env} {}
|
|
109
108
|
|
|
110
109
|
// If the private `immediate` operation is defined: this public operation will first
|
|
@@ -135,7 +134,7 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
|
|
|
135
134
|
|
|
136
135
|
template <class Accept>
|
|
137
136
|
auto operator()(value_of<number_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
|
|
138
|
-
if (
|
|
137
|
+
if (maybe_fast_is_number_int32(subject).value_or(false)) {
|
|
139
138
|
return immediate(value_of<number_tag_of<std::int32_t>>::from(subject), accept);
|
|
140
139
|
} else {
|
|
141
140
|
return immediate(value_of<number_tag_of<double>>::from(subject), accept);
|
|
@@ -153,81 +152,87 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
|
|
|
153
152
|
|
|
154
153
|
// Check the reference map, and lookup type via napi
|
|
155
154
|
return lookup_or_visit(subject, [ & ]() -> accept_target_t<Accept> {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return v8_subject->IsDate() ? immediate(value_of<date_tag>::from(subject), accept) : next();
|
|
181
|
-
},
|
|
182
|
-
[ & ](list_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
183
|
-
return v8_subject->IsArray() ? immediate(value_of<list_tag>::from(subject), accept) : next();
|
|
184
|
-
},
|
|
185
|
-
[ & ](object_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
186
|
-
// nb: You can't really skip the subsequent is promise, is date, is arraybuffer, etc
|
|
187
|
-
// checks. We don't really want to accept those types here, I don't think..
|
|
188
|
-
return v8_subject->IsObject() ? immediate(value_of<object_tag>::from(subject), accept) : next();
|
|
189
|
-
},
|
|
190
|
-
[ & ](function_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
191
|
-
return v8_subject->IsFunction() ? immediate(value_of<function_tag>::from(subject), accept) : next();
|
|
192
|
-
},
|
|
193
|
-
|
|
194
|
-
// Skip these, otherwise `number_tag` and `string_tag` are invoked twice, which we don't
|
|
195
|
-
// differentiate between.
|
|
196
|
-
[]<class Type>(number_tag_of<Type> /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
197
|
-
[]<class Type>(string_tag_of<Type> /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
198
|
-
|
|
199
|
-
// Unknown tag
|
|
200
|
-
[](auto /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
201
|
-
|
|
202
|
-
// Slow path
|
|
203
|
-
[ & ]() -> accept_target_t<Accept> {
|
|
204
|
-
auto type_of = napi::invoke(napi_typeof, napi_env{*this}, subject);
|
|
205
|
-
switch (type_of) {
|
|
206
|
-
case napi_undefined:
|
|
207
|
-
return (*this)(value_of<undefined_tag>::from(subject), accept);
|
|
208
|
-
case napi_null:
|
|
209
|
-
return (*this)(value_of<null_tag>::from(subject), accept);
|
|
210
|
-
case napi_boolean:
|
|
211
|
-
return (*this)(value_of<boolean_tag>::from(subject), accept);
|
|
212
|
-
case napi_number:
|
|
213
|
-
return (*this)(value_of<number_tag>::from(subject), accept);
|
|
214
|
-
case napi_string:
|
|
215
|
-
return immediate(value_of<string_tag>::from(subject), accept);
|
|
216
|
-
case napi_symbol:
|
|
217
|
-
return immediate(value_of<symbol_tag>::from(subject), accept);
|
|
218
|
-
case napi_object:
|
|
219
|
-
return immediate(value_of<object_tag>::from(subject), accept);
|
|
220
|
-
case napi_function:
|
|
221
|
-
return immediate(value_of<function_tag>::from(subject), accept);
|
|
222
|
-
case napi_external:
|
|
223
|
-
return immediate(value_of<external_tag>::from(subject), accept);
|
|
224
|
-
case napi_bigint:
|
|
225
|
-
return immediate(value_of<bigint_tag>::from(subject), accept);
|
|
226
|
-
}
|
|
227
|
-
std::unreachable();
|
|
228
|
-
},
|
|
155
|
+
// This is the pure-napi implementation
|
|
156
|
+
auto slow_path = [ & ]() -> accept_target_t<Accept> {
|
|
157
|
+
auto type_of = napi::invoke(napi_typeof, napi_env{*this}, subject);
|
|
158
|
+
switch (type_of) {
|
|
159
|
+
case napi_undefined:
|
|
160
|
+
return (*this)(value_of<undefined_tag>::from(subject), accept);
|
|
161
|
+
case napi_null:
|
|
162
|
+
return (*this)(value_of<null_tag>::from(subject), accept);
|
|
163
|
+
case napi_boolean:
|
|
164
|
+
return (*this)(value_of<boolean_tag>::from(subject), accept);
|
|
165
|
+
case napi_number:
|
|
166
|
+
return (*this)(value_of<number_tag>::from(subject), accept);
|
|
167
|
+
case napi_string:
|
|
168
|
+
return immediate(value_of<string_tag>::from(subject), accept);
|
|
169
|
+
case napi_symbol:
|
|
170
|
+
return immediate(value_of<symbol_tag>::from(subject), accept);
|
|
171
|
+
case napi_object:
|
|
172
|
+
return immediate(value_of<object_tag>::from(subject), accept);
|
|
173
|
+
case napi_function:
|
|
174
|
+
return immediate(value_of<function_tag>::from(subject), accept);
|
|
175
|
+
case napi_external:
|
|
176
|
+
return immediate(value_of<external_tag>::from(subject), accept);
|
|
177
|
+
case napi_bigint:
|
|
178
|
+
return immediate(value_of<bigint_tag>::from(subject), accept);
|
|
229
179
|
}
|
|
230
|
-
|
|
180
|
+
std::unreachable();
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
if (has_fast_is_functions) {
|
|
184
|
+
return util::template_traverse(
|
|
185
|
+
accept_tags_of_v<Accept>,
|
|
186
|
+
util::overloaded{
|
|
187
|
+
// Fast paths
|
|
188
|
+
[ & ](undefined_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
189
|
+
return fast_is_undefined(subject) ? (*this)(value_of<undefined_tag>::from(subject), accept) : next();
|
|
190
|
+
},
|
|
191
|
+
[ & ](null_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
192
|
+
return fast_is_null(subject) ? (*this)(value_of<null_tag>::from(subject), accept) : next();
|
|
193
|
+
},
|
|
194
|
+
[ & ](boolean_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
195
|
+
return fast_is_boolean(subject) ? (*this)(value_of<boolean_tag>::from(subject), accept) : next();
|
|
196
|
+
},
|
|
197
|
+
[ & ](number_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
198
|
+
return fast_is_number(subject) ? (*this)(value_of<number_tag>::from(subject), accept) : next();
|
|
199
|
+
},
|
|
200
|
+
[ & ](string_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
201
|
+
return fast_is_string(subject) ? immediate(value_of<string_tag>::from(subject), accept) : next();
|
|
202
|
+
},
|
|
203
|
+
[ & ](bigint_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
204
|
+
return fast_is_bigint(subject) ? immediate(value_of<bigint_tag>::from(subject), accept) : next();
|
|
205
|
+
},
|
|
206
|
+
[ & ](date_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
207
|
+
return napi::invoke(napi_is_date, napi_env{*this}, subject) ? immediate(value_of<date_tag>::from(subject), accept) : next();
|
|
208
|
+
},
|
|
209
|
+
[ & ](list_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
210
|
+
return fast_is_array(subject) ? immediate(value_of<list_tag>::from(subject), accept) : next();
|
|
211
|
+
},
|
|
212
|
+
[ & ](object_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
213
|
+
// nb: You can't really skip the subsequent is promise, is date, is arraybuffer, etc
|
|
214
|
+
// checks. We don't really want to accept those types here, I don't think..
|
|
215
|
+
return fast_is_object(subject) ? immediate(value_of<object_tag>::from(subject), accept) : next();
|
|
216
|
+
},
|
|
217
|
+
[ & ](function_tag /*tag*/, auto next) -> accept_target_t<Accept> {
|
|
218
|
+
return fast_is_function(subject) ? immediate(value_of<function_tag>::from(subject), accept) : next();
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
// Skip these, otherwise `number_tag` and `string_tag` are invoked twice, which we don't
|
|
222
|
+
// differentiate between.
|
|
223
|
+
[]<class Type>(number_tag_of<Type> /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
224
|
+
[]<class Type>(string_tag_of<Type> /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
225
|
+
|
|
226
|
+
// Unknown tag
|
|
227
|
+
[](auto /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
228
|
+
|
|
229
|
+
// Slow path
|
|
230
|
+
slow_path,
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
} else {
|
|
234
|
+
return slow_path();
|
|
235
|
+
}
|
|
231
236
|
});
|
|
232
237
|
}
|
|
233
238
|
|
|
@@ -267,10 +272,10 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
|
|
|
267
272
|
// strings
|
|
268
273
|
template <class Accept>
|
|
269
274
|
auto immediate(value_of<string_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
|
|
270
|
-
if (
|
|
271
|
-
return accept_tagged(value_of<string_tag_of<char16_t>>::from(subject), accept);
|
|
272
|
-
} else {
|
|
275
|
+
if (maybe_fast_is_string_one_byte(subject).value_or(false)) {
|
|
273
276
|
return accept_tagged(value_of<string_tag_of<char>>::from(subject), accept);
|
|
277
|
+
} else {
|
|
278
|
+
return accept_tagged(value_of<string_tag_of<char16_t>>::from(subject), accept);
|
|
274
279
|
}
|
|
275
280
|
}
|
|
276
281
|
|
|
@@ -291,7 +296,7 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
|
|
|
291
296
|
return immediate(value_of<typed_array_tag>::from(subject), accept);
|
|
292
297
|
} else if (napi::invoke(napi_is_dataview, napi_env{*this}, subject)) {
|
|
293
298
|
return immediate(value_of<data_view_tag>::from(subject), accept);
|
|
294
|
-
} else if (
|
|
299
|
+
} else if (maybe_is_shared_array_buffer(env_.get(), subject).value_or(false)) {
|
|
295
300
|
return immediate(value_of<shared_array_buffer_tag>::from(subject), accept);
|
|
296
301
|
} else if (napi::invoke(napi_is_arraybuffer, napi_env{*this}, subject)) {
|
|
297
302
|
return immediate(value_of<array_buffer_tag>::from(subject), accept);
|
package/value/array_buffer.cc
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
module napi_js;
|
|
2
2
|
import :api;
|
|
3
3
|
import :array_buffer;
|
|
4
|
+
import :support.host;
|
|
4
5
|
import std;
|
|
5
6
|
import v8;
|
|
6
7
|
|
|
@@ -8,18 +9,6 @@ namespace js::napi {
|
|
|
8
9
|
|
|
9
10
|
// `bound_value_for_data_block`
|
|
10
11
|
bound_value_for_data_block::operator std::span<std::byte>() const {
|
|
11
|
-
auto local = std::bit_cast<v8::Local<v8::ArrayBuffer>>(napi_value{*this});
|
|
12
|
-
auto* data = reinterpret_cast<std::byte*>(local->Data());
|
|
13
|
-
auto byte_length = local->ByteLength();
|
|
14
|
-
return std::span{data, byte_length};
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// `bound_value_for_array_buffer`
|
|
18
|
-
bound_value_for_array_buffer::operator js::array_buffer() const {
|
|
19
|
-
return js::array_buffer{std::span<std::byte>{*this}};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
bound_value_for_array_buffer::operator std::span<std::byte>() const {
|
|
23
12
|
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
|
|
24
13
|
void* bytes;
|
|
25
14
|
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
|
|
@@ -28,6 +17,11 @@ bound_value_for_array_buffer::operator std::span<std::byte>() const {
|
|
|
28
17
|
return std::span{reinterpret_cast<std::byte*>(bytes), byte_length};
|
|
29
18
|
}
|
|
30
19
|
|
|
20
|
+
// `bound_value_for_array_buffer`
|
|
21
|
+
bound_value_for_array_buffer::operator js::array_buffer() const {
|
|
22
|
+
return js::array_buffer{std::span<std::byte>{*this}};
|
|
23
|
+
}
|
|
24
|
+
|
|
31
25
|
// `bound_value_for_shared_array_buffer`
|
|
32
26
|
bound_value_for_shared_array_buffer::operator js::shared_array_buffer() const {
|
|
33
27
|
auto local = std::bit_cast<v8::Local<v8::SharedArrayBuffer>>(napi_value{*this});
|
|
@@ -37,11 +31,6 @@ bound_value_for_shared_array_buffer::operator js::shared_array_buffer() const {
|
|
|
37
31
|
return js::shared_array_buffer{local->ByteLength(), std::move(data_shared_ptr)};
|
|
38
32
|
}
|
|
39
33
|
|
|
40
|
-
bound_value_for_shared_array_buffer::operator std::span<std::byte>() const {
|
|
41
|
-
auto local = std::bit_cast<v8::Local<v8::SharedArrayBuffer>>(napi_value{*this});
|
|
42
|
-
return std::span{reinterpret_cast<std::byte*>(local->Data()), local->ByteLength()};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
34
|
// `value_for_typed_array`
|
|
46
35
|
auto value_for_typed_array::make(const environment& env, napi_typedarray_type type_tag, value_of<array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> value_of<typed_array_tag> {
|
|
47
36
|
return value_of<typed_array_tag>::from(napi::invoke(napi_create_typedarray, napi_env{env}, type_tag, length, napi_value{buffer}, byte_offset));
|
|
@@ -92,9 +81,7 @@ auto value_for_data_view::make(const environment& env, value_of<array_buffer_tag
|
|
|
92
81
|
}
|
|
93
82
|
|
|
94
83
|
auto value_for_data_view::make(const environment& /*env*/, value_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> value_of<data_view_tag> {
|
|
95
|
-
|
|
96
|
-
auto view_local = v8::DataView::New(buffer_local, byte_offset, length);
|
|
97
|
-
return value_of<data_view_tag>::from(std::bit_cast<napi_value>(view_local));
|
|
84
|
+
return make_sab_data_view(buffer, byte_offset, length);
|
|
98
85
|
}
|
|
99
86
|
|
|
100
87
|
// `bound_value_for_data_view`
|
package/value/array_buffer.h.cc
CHANGED
|
@@ -20,20 +20,14 @@ class bound_value_for_data_block : public bound_value_next<data_block_tag> {
|
|
|
20
20
|
class bound_value_for_array_buffer : public bound_value_next<array_buffer_tag> {
|
|
21
21
|
public:
|
|
22
22
|
using bound_value_next<array_buffer_tag>::bound_value_next;
|
|
23
|
-
[[nodiscard]] constexpr auto byte_length() const -> std::size_t { return std::span<std::byte>{*this}.size(); }
|
|
24
|
-
[[nodiscard]] constexpr auto data() const -> const std::byte* { return std::span<std::byte>{*this}.data(); }
|
|
25
23
|
explicit operator js::array_buffer() const;
|
|
26
|
-
explicit operator std::span<std::byte>() const;
|
|
27
24
|
};
|
|
28
25
|
|
|
29
26
|
// `SharedArrayBuffer`
|
|
30
27
|
class bound_value_for_shared_array_buffer : public bound_value_next<shared_array_buffer_tag> {
|
|
31
28
|
public:
|
|
32
29
|
using bound_value_next<shared_array_buffer_tag>::bound_value_next;
|
|
33
|
-
[[nodiscard]] constexpr auto byte_length() const -> std::size_t { return std::span<std::byte>{*this}.size(); }
|
|
34
|
-
[[nodiscard]] constexpr auto data() const -> const std::byte* { return std::span<std::byte>{*this}.data(); }
|
|
35
30
|
explicit operator js::shared_array_buffer() const;
|
|
36
|
-
explicit operator std::span<std::byte>() const;
|
|
37
31
|
};
|
|
38
32
|
|
|
39
33
|
// `ArrayBufferView` (hidden superclass of `TypedArray` and `DataView`)
|
|
@@ -120,23 +114,7 @@ class value_for_typed_array_of : public value_next<typed_array_tag_of<Type>> {
|
|
|
120
114
|
|
|
121
115
|
// napi doesn't provide a way to make a typed array view on a shared array buffer
|
|
122
116
|
static auto make(const environment& /*env*/, value_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> value_of<typed_array_tag_of<Type>> {
|
|
123
|
-
|
|
124
|
-
[](std::type_identity<double>) -> std::type_identity<v8::Float64Array> { return {}; },
|
|
125
|
-
[](std::type_identity<float>) -> std::type_identity<v8::Float32Array> { return {}; },
|
|
126
|
-
[](std::type_identity<js::float16_t>) -> std::type_identity<v8::Float16Array> { return {}; },
|
|
127
|
-
[](std::type_identity<js::uint8_clamped_t>) -> std::type_identity<v8::Uint8ClampedArray> { return {}; },
|
|
128
|
-
[](std::type_identity<std::int16_t>) -> std::type_identity<v8::Int16Array> { return {}; },
|
|
129
|
-
[](std::type_identity<std::int32_t>) -> std::type_identity<v8::Int32Array> { return {}; },
|
|
130
|
-
[](std::type_identity<std::int64_t>) -> std::type_identity<v8::BigInt64Array> { return {}; },
|
|
131
|
-
[](std::type_identity<std::int8_t>) -> std::type_identity<v8::Int8Array> { return {}; },
|
|
132
|
-
[](std::type_identity<std::uint16_t>) -> std::type_identity<v8::Uint16Array> { return {}; },
|
|
133
|
-
[](std::type_identity<std::uint32_t>) -> std::type_identity<v8::Uint32Array> { return {}; },
|
|
134
|
-
[](std::type_identity<std::uint64_t>) -> std::type_identity<v8::BigUint64Array> { return {}; },
|
|
135
|
-
[](std::type_identity<std::uint8_t>) -> std::type_identity<v8::Uint8Array> { return {}; },
|
|
136
|
-
}(type<Type>)>;
|
|
137
|
-
auto buffer_local = std::bit_cast<v8::Local<v8::SharedArrayBuffer>>(napi_value{buffer});
|
|
138
|
-
auto view_local = constructor_type::New(buffer_local, byte_offset, length);
|
|
139
|
-
return value_of<typed_array_tag_of<Type>>::from(std::bit_cast<napi_value>(view_local));
|
|
117
|
+
return make_sab_typed_array_of<Type>(buffer, byte_offset, length);
|
|
140
118
|
}
|
|
141
119
|
};
|
|
142
120
|
|
package/value/class.cc
CHANGED
|
@@ -42,7 +42,7 @@ auto value_for_class_of<Type>::transfer_construct(auto& env, auto instance, std:
|
|
|
42
42
|
napi::invoke0(napi_type_tag_object, napi_env{env}, this_arg, &type_tag_for<element_type>);
|
|
43
43
|
|
|
44
44
|
// Wrap w/ finalizer
|
|
45
|
-
return apply_finalizer(std::move(instance), [ & ](element_type* instance,
|
|
45
|
+
return apply_finalizer(std::move(instance), [ & ](element_type* instance, node_api_basic_finalize finalize, void* hint) -> napi_value {
|
|
46
46
|
napi::invoke0(napi_wrap, napi_env{env}, this_arg, instance, finalize, hint, nullptr);
|
|
47
47
|
return this_arg;
|
|
48
48
|
});
|
package/support/container.cc
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
export module napi_js:container;
|
|
2
|
-
import :environment;
|
|
3
|
-
import nodejs;
|
|
4
|
-
import std;
|
|
5
|
-
import util;
|
|
6
|
-
|
|
7
|
-
namespace js::napi {
|
|
8
|
-
|
|
9
|
-
// Map container for napi values
|
|
10
|
-
template <class Type>
|
|
11
|
-
struct virtual_value_map {
|
|
12
|
-
public:
|
|
13
|
-
using container_type = std::unordered_map<napi_value, Type>;
|
|
14
|
-
using iterator = container_type::iterator;
|
|
15
|
-
using key_type = container_type::key_type;
|
|
16
|
-
using mapped_type = container_type::mapped_type;
|
|
17
|
-
|
|
18
|
-
virtual auto end() const -> iterator = 0;
|
|
19
|
-
virtual auto find(napi_value key) const -> iterator = 0;
|
|
20
|
-
virtual auto try_emplace(napi_value key, Type value) -> std::pair<iterator, bool> = 0;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
template <class Map>
|
|
24
|
-
struct concrete_value_map final : virtual_value_map<typename Map::mapped_type> {
|
|
25
|
-
public:
|
|
26
|
-
using container_type = Map;
|
|
27
|
-
using typename virtual_value_map<typename Map::mapped_type>::mapped_type;
|
|
28
|
-
using typename virtual_value_map<typename Map::mapped_type>::iterator;
|
|
29
|
-
|
|
30
|
-
virtual auto end() const -> iterator {
|
|
31
|
-
return std::bit_cast<iterator>(map_.end());
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
virtual auto find(napi_value key) const -> iterator {
|
|
35
|
-
// nb: The iterator type between `std::unordered_map<int, int, left>` and
|
|
36
|
-
// `std::unordered_map<int, int, right>` are not technically compatible.
|
|
37
|
-
return std::bit_cast<iterator>(map_.find(key));
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
virtual auto try_emplace(napi_value key, mapped_type value) -> std::pair<iterator, bool> {
|
|
41
|
-
auto [ it, inserted ] = map_.try_emplace(key, std::move(value));
|
|
42
|
-
return std::pair{std::bit_cast<iterator>(it), inserted};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
private:
|
|
46
|
-
container_type map_;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export template <class Type>
|
|
50
|
-
class value_map {
|
|
51
|
-
private:
|
|
52
|
-
using direct_map_type = concrete_value_map<std::unordered_map<napi_value, Type, direct_address_hash, direct_address_equal>>;
|
|
53
|
-
using indirect_map_type = concrete_value_map<std::unordered_map<napi_value, Type, indirect_address_hash, indirect_address_equal>>;
|
|
54
|
-
using virtual_map_type = util::covariant_value<virtual_value_map<Type>, direct_map_type, indirect_map_type>;
|
|
55
|
-
|
|
56
|
-
public:
|
|
57
|
-
using container_type = virtual_value_map<Type>;
|
|
58
|
-
using iterator = container_type::iterator;
|
|
59
|
-
using key_type = container_type::key_type;
|
|
60
|
-
using mapped_type = container_type::mapped_type;
|
|
61
|
-
|
|
62
|
-
explicit value_map(const environment& env) :
|
|
63
|
-
map_{
|
|
64
|
-
env.uses_direct_handles()
|
|
65
|
-
? virtual_map_type{direct_map_type{}}
|
|
66
|
-
: virtual_map_type{indirect_map_type{}}
|
|
67
|
-
} {}
|
|
68
|
-
|
|
69
|
-
auto end() const -> iterator { return map_->end(); }
|
|
70
|
-
auto find(key_type key) const -> iterator { return map_->find(key); }
|
|
71
|
-
auto try_emplace(key_type key, mapped_type value) -> std::pair<iterator, bool> { return map_->try_emplace(key, std::move(value)); }
|
|
72
|
-
|
|
73
|
-
private:
|
|
74
|
-
virtual_map_type map_;
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
} // namespace js::napi
|