@auto_js/napi 0.0.4 → 0.0.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.
@@ -13,17 +13,22 @@ export struct callback_info : util::non_copyable {
13
13
  callback_info(napi_env env, napi_callback_info info) {
14
14
  napi::invoke0(napi_get_cb_info, env, info, &count_, storage_.data(), &this_, &data_);
15
15
  if (count_ > storage_.size()) {
16
- throw js::range_error{u"Too many arguments provided for a function call"};
16
+ constexpr auto message = std::string_view{"Too many arguments provided for a function call"};
17
+ napi::invoke0(napi_throw_range_error, env, nullptr, message.data());
18
+ count_ = 0;
19
+ } else {
20
+ ++count_;
17
21
  }
18
22
  }
19
23
 
20
- [[nodiscard]] auto arguments() const -> std::span<const napi_value> { return std::span{storage_}.first(count_); }
24
+ [[nodiscard]] auto arguments() const -> std::span<const napi_value> { return std::span{storage_}.first(count_ - 1); }
21
25
  [[nodiscard]] auto data() const -> void* { return data_; }
22
26
  [[nodiscard]] auto this_arg() const -> napi_value { return this_; }
27
+ explicit operator bool() const { return count_ != 0; }
23
28
 
24
29
  private:
25
30
  napi_value this_;
26
- std::array<napi_value, 8> storage_;
31
+ std::array<napi_value, 16> storage_;
27
32
  std::size_t count_{storage_.size()};
28
33
  void* data_;
29
34
  };
@@ -3,21 +3,12 @@ import :api.uv_handle;
3
3
  import std;
4
4
  import util;
5
5
 
6
- #if _LIBCPP_VERSION
7
- // clang 22.1.0
8
- // /usr/lib/llvm-22/bin/../include/c++/v1/__new/allocate.h:39:30: error: no matching function for call to 'operator new'
9
- // 39 | return static_cast<_Tp*>(__builtin_operator_new(__size, static_cast<align_val_t>(__align)));
10
- export {
11
- using ::operator new;
12
- }
13
- #endif
14
-
15
6
  namespace js::napi {
16
7
 
17
8
  // Shareable libuv scheduler
18
9
  export class uv_scheduler {
19
10
  private:
20
- using task_type = util::maybe_move_only_function<auto()->void>;
11
+ using task_type = util::move_only_function<auto()->void>;
21
12
 
22
13
  public:
23
14
  auto close(util::function_ref<auto()->void> close_hook) -> void;
@@ -57,7 +48,7 @@ auto uv_scheduler::operator()(auto task, auto&&... args) const -> void {
57
48
  auto& async = *async_;
58
49
  auto shared = async->shared.write();
59
50
  if (shared->is_open) {
60
- shared->tasks.push_back(
51
+ shared->tasks.emplace_back(
61
52
  [ task = std::move(task),
62
53
  ... args = std::forward<decltype(args)>(args) ]() mutable -> void {
63
54
  task(std::move(args)...);
package/handle/remote.cc CHANGED
@@ -59,12 +59,11 @@ template <class Tag>
59
59
  auto remote<Tag>::expire(remote* ptr) -> void {
60
60
  std::unique_ptr<remote> self{ptr};
61
61
  ptr->scheduler_(
62
- util::make_indirect_moveable_function(
63
- [ self = std::move(self) ] mutable -> auto {
64
- const auto scope = handle_scope{self->env()};
65
- self.reset();
66
- }
67
- )
62
+ [](auto self) -> void {
63
+ const auto scope = handle_scope{self->env()};
64
+ self.reset();
65
+ },
66
+ std::move(self)
68
67
  );
69
68
  }
70
69
 
package/handle/types.cc CHANGED
@@ -99,6 +99,11 @@ struct value_specialization<function_tag> : value_defaults<function_tag> {
99
99
  using value_type = class value_for_function;
100
100
  };
101
101
 
102
+ template <>
103
+ struct value_specialization<data_block_tag> : value_defaults<data_block_tag> {
104
+ using bound_type = class bound_value_for_data_block;
105
+ };
106
+
102
107
  template <>
103
108
  struct value_specialization<array_buffer_tag> : value_defaults<array_buffer_tag> {
104
109
  using bound_type = class bound_value_for_array_buffer;
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@auto_js/napi",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "author": "https://github.com/laverdet/",
5
5
  "description": "Automatic JavaScript to N-API bindings",
6
6
  "homepage": "https://github.com/laverdet/isolated-vm/tree/experimental/packages/auto_js/napi",
7
7
  "license": "ISC",
8
8
  "dependencies": {
9
- "@auto_js/js": "^0.0.4",
10
- "@auto_js/v8_exports": "^0.0.2",
11
- "@auto_js/napi_exports": "^0.0.4"
9
+ "@auto_js/v8_exports": "^0.0.3",
10
+ "@auto_js/js": "^0.0.5",
11
+ "@auto_js/napi_exports": "^0.0.5"
12
12
  },
13
13
  "repository": {
14
14
  "type": "git",
@@ -46,7 +46,7 @@ constexpr auto make_free_function(auto function) {
46
46
  callback,
47
47
  std::tuple_cat(
48
48
  std::forward_as_tuple(env),
49
- js::transfer_out<std::tuple<Args...>>(info.arguments(), env)
49
+ js::transfer_out<std::tuple<js::functional::parameter_transfer_as_t<Args>...>>(info.arguments(), env)
50
50
  )
51
51
  );
52
52
  }};
@@ -117,7 +117,7 @@ constexpr auto make_constructor_function(auto constructor) {
117
117
  callback,
118
118
  std::tuple_cat(
119
119
  std::forward_as_tuple(env, value_of<object_tag>::from(info.this_arg())),
120
- js::transfer_out<std::tuple<Args...>>(info.arguments(), env)
120
+ js::transfer_out<std::tuple<js::functional::parameter_transfer_as_t<Args>...>>(info.arguments(), env)
121
121
  )
122
122
  );
123
123
  return wrap(std::move(instance));
@@ -214,7 +214,7 @@ constexpr auto make_member_function(Method method) {
214
214
  callback,
215
215
  std::tuple_cat(
216
216
  std::forward_as_tuple(**maybe_that, env),
217
- js::transfer_out<std::tuple<Args...>>(info.arguments(), env)
217
+ js::transfer_out<std::tuple<js::functional::parameter_transfer_as_t<Args>...>>(info.arguments(), env)
218
218
  )
219
219
  );
220
220
  }};
@@ -22,9 +22,13 @@ auto make_callback_storage(Environment& env, std::invocable<Environment&, const
22
22
  // Constant expression function, expressed entirely in the type. `data` is the environment.
23
23
  const auto callback = napi_callback{[](napi_env nenv, napi_callback_info info) -> napi_value {
24
24
  const auto args = callback_info{nenv, info};
25
- auto invoke = function_type{};
26
- auto& env = *static_cast<Environment*>(args.data());
27
- return invoke(env, args);
25
+ if (args) {
26
+ auto invoke = function_type{};
27
+ auto& env = *static_cast<Environment*>(args.data());
28
+ return invoke(env, args);
29
+ } else {
30
+ return {};
31
+ }
28
32
  }};
29
33
  return std::tuple{callback, &env};
30
34
  } else if constexpr (sizeof(function_type) <= sizeof(void*)) {
@@ -34,10 +38,14 @@ auto make_callback_storage(Environment& env, std::invocable<Environment&, const
34
38
  auto* data = reinterpret_cast<void*&>(function);
35
39
  const auto callback = napi_callback{[](napi_env nenv, napi_callback_info info) -> napi_value {
36
40
  const auto args = callback_info{nenv, info};
37
- auto* data = args.data();
38
- auto& invoke = reinterpret_cast<function_type&>(data);
39
- auto& env = *callback_env_local<Environment>;
40
- return invoke(env, args);
41
+ if (args) {
42
+ auto* data = args.data();
43
+ auto& invoke = reinterpret_cast<function_type&>(data);
44
+ auto& env = *callback_env_local<Environment>;
45
+ return invoke(env, args);
46
+ } else {
47
+ return {};
48
+ }
41
49
  }};
42
50
  return std::tuple{callback, data};
43
51
  } else {
@@ -49,8 +57,12 @@ auto make_callback_storage(Environment& env, std::invocable<Environment&, const
49
57
  auto external_data = std::make_unique<pair_type>(&env, std::move(function));
50
58
  const auto callback = napi_callback{[](napi_env nenv, napi_callback_info info) -> napi_value {
51
59
  const auto args = callback_info{nenv, info};
52
- auto& state = *static_cast<pair_type*>(args.data());
53
- return state.second(*state.first, args);
60
+ if (args) {
61
+ auto& state = *static_cast<pair_type*>(args.data());
62
+ return state.second(*state.first, args);
63
+ } else {
64
+ return {};
65
+ }
54
66
  }};
55
67
  return std::tuple{callback, std::move(external_data)};
56
68
  }
@@ -5,16 +5,6 @@ import std;
5
5
  import util;
6
6
  using namespace std::string_literals;
7
7
 
8
- #if _LIBCPP_VERSION || _MSVC_STL_UPDATE
9
- // clang 22.1.0 w/ -stdlib=libc++ (and also MS STL)
10
- // /workspace/packages/auto_js/napi/support/class_template_storage.cc:28:45: error: invalid operands
11
- // to binary expression ('basic_string<char>' and 'const std::basic_string_view<char>')
12
- // 28 | static_assert(index, "Class template '"s + name_sv + "' is missing in storage"s);
13
- export {
14
- using std::operator+;
15
- }
16
- #endif
17
-
18
8
  namespace js::napi {
19
9
 
20
10
  // Given a pack of strings it returns a static reference to a `util::sealed_map` of napi object
@@ -105,15 +105,16 @@ auto accept_basic_napi_value::operator()(error_tag /*tag*/, visit_holder visit,
105
105
  // data blocks (array buffer, shared array buffer)
106
106
  auto accept_basic_napi_value::operator()(array_buffer_tag /*tag*/, visit_holder /*visit*/, const js::array_buffer& subject) const
107
107
  -> js::referenceable_value<value_of<array_buffer_tag>> {
108
+ auto view = std::span<const std::byte>{subject};
108
109
  // You could avoid the extra copy for `js::data_block&&` here w/ v8 API. Napi requires the copy
109
110
  // though.
110
111
  // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
111
112
  void* bytes;
112
- auto* result = napi::invoke(napi_create_arraybuffer, napi_env{*this}, subject.size(), &bytes);
113
+ auto* result = napi::invoke(napi_create_arraybuffer, napi_env{*this}, view.size(), &bytes);
113
114
  // nb: `std::memcpy` *technically* results in undefined behavior on block size 0
114
115
  // (and also) it maybe causes an infinite loop with musl
115
116
  // 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
+ std::ranges::copy(view, static_cast<std::byte*>(bytes));
117
118
  auto value = value_of<array_buffer_tag>::from(result);
118
119
  return js::referenceable_value{value};
119
120
  }
@@ -121,7 +122,7 @@ auto accept_basic_napi_value::operator()(array_buffer_tag /*tag*/, visit_holder
121
122
  auto accept_basic_napi_value::operator()(shared_array_buffer_tag /*tag*/, visit_holder /*visit*/, js::shared_array_buffer&& subject) const
122
123
  -> js::referenceable_value<value_of<shared_array_buffer_tag>> {
123
124
  auto backing_store = [ & ]() -> auto {
124
- auto byte_length = subject.size();
125
+ auto byte_length = subject.byte_length();
125
126
  // v8 does not call the deleter `byte_length` is zero. So the heap-allocated shared_ptr trick
126
127
  // does not work in that case.
127
128
  if (byte_length == 0) {
@@ -168,15 +168,16 @@ struct accept_napi_value : accept_basic_napi_value {
168
168
  // vectors
169
169
  auto operator()(this const auto& self, vector_tag /*tag*/, auto& visit, auto&& subject)
170
170
  -> js::deferred_receiver<value_of<vector_tag>, decltype(self), decltype(visit), decltype(subject)> {
171
+ auto [... size ] = util::maybe_range_size(subject, 0);
171
172
  return {
172
- value_of<vector_tag>::from(napi::invoke(napi_create_array_with_length, napi_env{self}, subject.size())),
173
+ value_of<vector_tag>::from(napi::invoke(napi_create_array_with_length, napi_env{self}, size...)),
173
174
  std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
174
175
  [](value_of<vector_tag> array, auto& self, auto& visit, auto /*&&*/ subject) -> void {
175
176
  int ii = 0;
176
177
  auto&& range = util::into_range(std::forward<decltype(subject)>(subject));
177
- for (auto&& subject : util::forward_range(std::forward<decltype(range)>(range))) {
178
- auto* element = napi_value{visit(std::forward<decltype(subject)>(subject), self)};
179
- napi::invoke0(napi_set_element, napi_env{self}, napi_value{array}, ii++, element);
178
+ for (auto&& element : util::forward_range(std::forward<decltype(range)>(range))) {
179
+ auto* item = napi_value{visit(std::forward<decltype(element)>(element), self)};
180
+ napi::invoke0(napi_set_element, napi_env{self}, napi_value{array}, ii++, item);
180
181
  }
181
182
  },
182
183
  };
package/transfer/visit.cc CHANGED
@@ -153,48 +153,101 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
153
153
 
154
154
  // Check the reference map, and lookup type via napi
155
155
  return lookup_or_visit(subject, [ & ]() -> accept_target_t<Accept> {
156
- auto type_of = napi::invoke(napi_typeof, napi_env{*this}, subject);
157
- switch (type_of) {
158
- case napi_undefined:
159
- return (*this)(value_of<undefined_tag>::from(subject), accept);
160
- case napi_null:
161
- return (*this)(value_of<null_tag>::from(subject), accept);
162
- case napi_boolean:
163
- return (*this)(value_of<boolean_tag>::from(subject), accept);
164
- case napi_number:
165
- return (*this)(value_of<number_tag>::from(subject), accept);
166
- case napi_string:
167
- return immediate(value_of<string_tag>::from(subject), accept);
168
- case napi_symbol:
169
- return immediate(value_of<symbol_tag>::from(subject), accept);
170
- case napi_object:
171
- {
172
- if (napi::invoke(napi_is_array, napi_env{*this}, subject)) {
173
- return immediate(value_of<list_tag>::from(subject), accept);
174
- } else if (napi::invoke(napi_is_date, napi_env{*this}, subject)) {
175
- return immediate(value_of<date_tag>::from(subject), accept);
176
- } else if (napi::invoke(napi_is_typedarray, napi_env{*this}, subject)) {
177
- return immediate(value_of<typed_array_tag>::from(subject), accept);
178
- } else if (napi::invoke(napi_is_dataview, napi_env{*this}, subject)) {
179
- return immediate(value_of<data_view_tag>::from(subject), accept);
180
- } else if (std::bit_cast<v8::Local<v8::Object>>(subject)->IsSharedArrayBuffer()) {
181
- return immediate(value_of<shared_array_buffer_tag>::from(subject), accept);
182
- } else if (napi::invoke(napi_is_arraybuffer, napi_env{*this}, subject)) {
183
- return immediate(value_of<array_buffer_tag>::from(subject), accept);
184
- } else if (napi::invoke(napi_is_promise, napi_env{*this}, subject)) {
185
- return immediate(value_of<promise_tag>::from(subject), accept);
186
- } else {
187
- return immediate(value_of<dictionary_tag>::from(subject), accept);
156
+ auto v8_subject = std::bit_cast<v8::Local<v8::Value>>(subject);
157
+ return util::template_traverse(
158
+ accept_tags_of_v<Accept>,
159
+ util::overloaded{
160
+ // Fast paths
161
+ [ & ](undefined_tag /*tag*/, auto next) -> accept_target_t<Accept> {
162
+ return v8_subject->IsUndefined() ? (*this)(value_of<undefined_tag>::from(subject), accept) : next();
163
+ },
164
+ [ & ](null_tag /*tag*/, auto next) -> accept_target_t<Accept> {
165
+ return v8_subject->IsNull() ? (*this)(value_of<null_tag>::from(subject), accept) : next();
166
+ },
167
+ [ & ](boolean_tag /*tag*/, auto next) -> accept_target_t<Accept> {
168
+ return v8_subject->IsBoolean() ? (*this)(value_of<boolean_tag>::from(subject), accept) : next();
169
+ },
170
+ [ & ](number_tag /*tag*/, auto next) -> accept_target_t<Accept> {
171
+ return v8_subject->IsNumber() ? (*this)(value_of<number_tag>::from(subject), accept) : next();
172
+ },
173
+ [ & ](string_tag /*tag*/, auto next) -> accept_target_t<Accept> {
174
+ return v8_subject->IsString() ? immediate(value_of<string_tag>::from(subject), accept) : next();
175
+ },
176
+ [ & ](bigint_tag /*tag*/, auto next) -> accept_target_t<Accept> {
177
+ return v8_subject->IsBigInt() ? immediate(value_of<bigint_tag>::from(subject), accept) : next();
178
+ },
179
+ [ & ](date_tag /*tag*/, auto next) -> accept_target_t<Accept> {
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);
188
226
  }
227
+ std::unreachable();
228
+ },
229
+ }
230
+ );
231
+ });
232
+ }
233
+
234
+ template <class Accept>
235
+ auto operator()(value_of<data_block_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
236
+ return lookup_or_visit(subject, [ & ]() -> accept_target_t<Accept> {
237
+ return util::template_traverse(
238
+ accept_tags_of_v<Accept>,
239
+ util::overloaded{
240
+ // Fast paths
241
+ [ & ](data_block_tag /*tag*/, auto /*next*/) -> accept_target_t<Accept> { return accept_tagged(subject, accept); },
242
+ [ & ](array_buffer_tag /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
243
+ [ & ](shared_array_buffer_tag /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
244
+
245
+ // Slow path
246
+ [ & ]() -> accept_target_t<Accept> {
247
+ return immediate(subject, accept);
189
248
  }
190
- case napi_function:
191
- return immediate(value_of<function_tag>::from(subject), accept);
192
- case napi_external:
193
- return immediate(value_of<external_tag>::from(subject), accept);
194
- case napi_bigint:
195
- return immediate(value_of<bigint_tag>::from(subject), accept);
196
- }
197
- std::unreachable();
249
+ }
250
+ );
198
251
  });
199
252
  }
200
253
 
@@ -206,7 +259,7 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
206
259
  private:
207
260
  // I think this only applies to `symbol_tag`
208
261
  template <class Accept, class Tag>
209
- requires std::is_base_of_v<primitive_tag, Tag>
262
+ requires std::is_convertible_v<Tag, primitive_tag>
210
263
  auto immediate(value_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept> {
211
264
  return accept_tagged(subject, accept);
212
265
  }
@@ -227,6 +280,28 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
227
280
  return accept_tagged(value_of<bigint_tag_of<bigint>>::from(subject), accept);
228
281
  }
229
282
 
283
+ // date
284
+ template <class Accept>
285
+ auto immediate(value_of<object_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
286
+ if (napi::invoke(napi_is_array, napi_env{*this}, subject)) {
287
+ return immediate(value_of<list_tag>::from(subject), accept);
288
+ } else if (napi::invoke(napi_is_date, napi_env{*this}, subject)) {
289
+ return immediate(value_of<date_tag>::from(subject), accept);
290
+ } else if (napi::invoke(napi_is_typedarray, napi_env{*this}, subject)) {
291
+ return immediate(value_of<typed_array_tag>::from(subject), accept);
292
+ } else if (napi::invoke(napi_is_dataview, napi_env{*this}, subject)) {
293
+ return immediate(value_of<data_view_tag>::from(subject), accept);
294
+ } else if (std::bit_cast<v8::Local<v8::Object>>(subject)->IsSharedArrayBuffer()) {
295
+ return immediate(value_of<shared_array_buffer_tag>::from(subject), accept);
296
+ } else if (napi::invoke(napi_is_arraybuffer, napi_env{*this}, subject)) {
297
+ return immediate(value_of<array_buffer_tag>::from(subject), accept);
298
+ } else if (napi::invoke(napi_is_promise, napi_env{*this}, subject)) {
299
+ return immediate(value_of<promise_tag>::from(subject), accept);
300
+ } else {
301
+ return immediate(value_of<dictionary_tag>::from(subject), accept);
302
+ }
303
+ }
304
+
230
305
  // date
231
306
  template <class Accept>
232
307
  auto immediate(value_of<date_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
@@ -244,7 +319,7 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
244
319
  }
245
320
 
246
321
  template <class Accept, class Tag>
247
- requires std::is_base_of_v<data_block_tag, Tag>
322
+ requires std::is_convertible_v<Tag, data_block_tag>
248
323
  auto immediate(value_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept> {
249
324
  return accept_tagged(subject, accept);
250
325
  }
@@ -6,6 +6,14 @@ import v8;
6
6
 
7
7
  namespace js::napi {
8
8
 
9
+ // `bound_value_for_data_block`
10
+ 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
+
9
17
  // `bound_value_for_array_buffer`
10
18
  bound_value_for_array_buffer::operator js::array_buffer() const {
11
19
  return js::array_buffer{std::span<std::byte>{*this}};
@@ -17,7 +25,7 @@ bound_value_for_array_buffer::operator std::span<std::byte>() const {
17
25
  // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
18
26
  std::size_t byte_length;
19
27
  napi::invoke0(napi_get_arraybuffer_info, env(), napi_value{*this}, &bytes, &byte_length);
20
- return std::span<std::byte>{reinterpret_cast<std::byte*>(bytes), byte_length};
28
+ return std::span{reinterpret_cast<std::byte*>(bytes), byte_length};
21
29
  }
22
30
 
23
31
  // `bound_value_for_shared_array_buffer`
@@ -31,7 +39,7 @@ bound_value_for_shared_array_buffer::operator js::shared_array_buffer() const {
31
39
 
32
40
  bound_value_for_shared_array_buffer::operator std::span<std::byte>() const {
33
41
  auto local = std::bit_cast<v8::Local<v8::SharedArrayBuffer>>(napi_value{*this});
34
- return std::span<std::byte>{reinterpret_cast<std::byte*>(local->Data()), local->ByteLength()};
42
+ return std::span{reinterpret_cast<std::byte*>(local->Data()), local->ByteLength()};
35
43
  }
36
44
 
37
45
  // `value_for_typed_array`
@@ -56,7 +64,7 @@ auto bound_value_for_typed_array::make_bound(const environment& env, value_of<ty
56
64
  switch (type_tag) {
57
65
  case napi_bigint64_array: return make(typed_array_tag_of<std::int64_t>{});
58
66
  case napi_biguint64_array: return make(typed_array_tag_of<std::uint64_t>{});
59
- case napi_float16_array: throw std::logic_error{"unsupported"};
67
+ case napi_float16_array: return make(typed_array_tag_of<js::float16_t>{});
60
68
  case napi_float32_array: return make(typed_array_tag_of<float>{});
61
69
  case napi_float64_array: return make(typed_array_tag_of<double>{});
62
70
  case napi_int16_array: return make(typed_array_tag_of<std::int16_t>{});
@@ -65,7 +73,7 @@ auto bound_value_for_typed_array::make_bound(const environment& env, value_of<ty
65
73
  case napi_uint16_array: return make(typed_array_tag_of<std::uint16_t>{});
66
74
  case napi_uint32_array: return make(typed_array_tag_of<std::uint32_t>{});
67
75
  case napi_uint8_array: return make(typed_array_tag_of<std::uint8_t>{});
68
- case napi_uint8_clamped_array: return make(typed_array_tag_of<std::byte>{});
76
+ case napi_uint8_clamped_array: return make(typed_array_tag_of<js::uint8_clamped_t>{});
69
77
  }
70
78
  std::unreachable();
71
79
  }
@@ -7,11 +7,21 @@ import v8;
7
7
 
8
8
  namespace js::napi {
9
9
 
10
+ // Data blocks
11
+ class bound_value_for_data_block : public bound_value_next<data_block_tag> {
12
+ public:
13
+ using bound_value_next<data_block_tag>::bound_value_next;
14
+ [[nodiscard]] constexpr auto byte_length() const -> std::size_t { return std::span<std::byte>{*this}.size(); }
15
+ [[nodiscard]] constexpr auto data() const -> const std::byte* { return std::span<std::byte>{*this}.data(); }
16
+ explicit operator std::span<std::byte>() const;
17
+ };
18
+
10
19
  // `ArrayBuffer`
11
20
  class bound_value_for_array_buffer : public bound_value_next<array_buffer_tag> {
12
21
  public:
13
22
  using bound_value_next<array_buffer_tag>::bound_value_next;
14
-
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(); }
15
25
  explicit operator js::array_buffer() const;
16
26
  explicit operator std::span<std::byte>() const;
17
27
  };
@@ -20,7 +30,8 @@ class bound_value_for_array_buffer : public bound_value_next<array_buffer_tag> {
20
30
  class bound_value_for_shared_array_buffer : public bound_value_next<shared_array_buffer_tag> {
21
31
  public:
22
32
  using bound_value_next<shared_array_buffer_tag>::bound_value_next;
23
-
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(); }
24
35
  explicit operator js::shared_array_buffer() const;
25
36
  explicit operator std::span<std::byte>() const;
26
37
  };
@@ -62,7 +73,8 @@ class bound_value_for_typed_array : public bound_value_next<typed_array_tag> {
62
73
  using any_bound_typed_array = std::variant<
63
74
  bound_value<typed_array_tag_of<double>>,
64
75
  bound_value<typed_array_tag_of<float>>,
65
- bound_value<typed_array_tag_of<std::byte>>,
76
+ bound_value<typed_array_tag_of<js::float16_t>>,
77
+ bound_value<typed_array_tag_of<js::uint8_clamped_t>>,
66
78
  bound_value<typed_array_tag_of<std::int16_t>>,
67
79
  bound_value<typed_array_tag_of<std::int32_t>>,
68
80
  bound_value<typed_array_tag_of<std::int64_t>>,
@@ -92,7 +104,8 @@ class value_for_typed_array_of : public value_next<typed_array_tag_of<Type>> {
92
104
  constexpr auto type_tag = util::overloaded{
93
105
  [](std::type_identity<double>) -> napi_typedarray_type { return napi_float64_array; },
94
106
  [](std::type_identity<float>) -> napi_typedarray_type { return napi_float32_array; },
95
- [](std::type_identity<std::byte>) -> napi_typedarray_type { return napi_uint8_clamped_array; },
107
+ [](std::type_identity<js::float16_t>) -> napi_typedarray_type { return napi_float16_array; },
108
+ [](std::type_identity<js::uint8_clamped_t>) -> napi_typedarray_type { return napi_uint8_clamped_array; },
96
109
  [](std::type_identity<std::int16_t>) -> napi_typedarray_type { return napi_int16_array; },
97
110
  [](std::type_identity<std::int32_t>) -> napi_typedarray_type { return napi_int32_array; },
98
111
  [](std::type_identity<std::int64_t>) -> napi_typedarray_type { return napi_bigint64_array; },
@@ -110,7 +123,8 @@ class value_for_typed_array_of : public value_next<typed_array_tag_of<Type>> {
110
123
  using constructor_type = type_t<util::overloaded{
111
124
  [](std::type_identity<double>) -> std::type_identity<v8::Float64Array> { return {}; },
112
125
  [](std::type_identity<float>) -> std::type_identity<v8::Float32Array> { return {}; },
113
- [](std::type_identity<std::byte>) -> std::type_identity<v8::Uint8ClampedArray> { 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 {}; },
114
128
  [](std::type_identity<std::int16_t>) -> std::type_identity<v8::Int16Array> { return {}; },
115
129
  [](std::type_identity<std::int32_t>) -> std::type_identity<v8::Int32Array> { return {}; },
116
130
  [](std::type_identity<std::int64_t>) -> std::type_identity<v8::BigInt64Array> { return {}; },
package/value/class.cc CHANGED
@@ -37,7 +37,7 @@ template <class Type>
37
37
  template <class... Args>
38
38
  auto value_for_class_of<Type>::transfer_construct(auto& env, auto instance, std::tuple<Args...> runtime_args) const -> value_of<object_tag> {
39
39
  using element_type = decltype(instance)::element_type;
40
- auto construct = [ & ](napi_value this_arg) mutable -> napi_value {
40
+ auto construct = [ & ](napi_value this_arg) -> napi_value {
41
41
  // Tag `this_arg`
42
42
  napi::invoke0(napi_type_tag_object, napi_env{env}, this_arg, &type_tag_for<element_type>);
43
43
 
package/value/function.cc CHANGED
@@ -6,14 +6,14 @@ namespace js::napi {
6
6
 
7
7
  template <class Result>
8
8
  auto value_for_function::apply(auto_environment auto& env, auto&& args) -> Result {
9
- auto arg_values = js::transfer_in_strict<std::vector<napi_value>>(std::forward<decltype(args)>(args), env);
10
- return invoke<Result>(env, std::span{arg_values});
9
+ auto argv = js::transfer_in_strict<std::vector<napi_value>>(std::forward<decltype(args)>(args), env);
10
+ return invoke<Result>(env, std::span{argv});
11
11
  }
12
12
 
13
13
  template <class Result>
14
14
  auto value_for_function::call(auto_environment auto& env, auto&&... args) -> Result {
15
- auto arg_values = js::transfer_in_strict<std::array<napi_value, sizeof...(args)>>(std::forward_as_tuple(args...), env);
16
- return invoke<Result>(env, std::span{arg_values});
15
+ auto argv = js::transfer_in_strict<std::array<napi_value, sizeof...(args)>>(std::forward_as_tuple(args...), env);
16
+ return invoke<Result>(env, std::span{argv});
17
17
  }
18
18
 
19
19
  template <class Result>
@@ -20,14 +20,6 @@ bound_value_for_number::operator std::int32_t() const {
20
20
  return napi::invoke(napi_get_value_int32, env(), napi_value{*this});
21
21
  }
22
22
 
23
- bound_value_for_number::operator std::int64_t() const {
24
- return napi::invoke(napi_get_value_int64, env(), napi_value{*this});
25
- }
26
-
27
- bound_value_for_number::operator std::uint32_t() const {
28
- return napi::invoke(napi_get_value_uint32, env(), napi_value{*this});
29
- }
30
-
31
23
  // bigint
32
24
  bound_value_for_bigint::operator bigint() const {
33
25
  js::bigint value;
@@ -55,13 +47,6 @@ bound_value_for_bigint::operator std::int64_t() const {
55
47
  return value;
56
48
  }
57
49
 
58
- bound_value_for_bigint::operator std::uint64_t() const {
59
- // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
60
- std::uint64_t value;
61
- napi::invoke(napi_get_value_bigint_uint64, env(), napi_value{*this}, &value);
62
- return value;
63
- }
64
-
65
50
  // string
66
51
  bound_value_for_string::operator std::string() const {
67
52
  std::string string;
@@ -19,8 +19,6 @@ class bound_value_for_number : public bound_value_next<number_tag> {
19
19
  using bound_value_next<number_tag>::bound_value_next;
20
20
  [[nodiscard]] explicit operator double() const;
21
21
  [[nodiscard]] explicit operator std::int32_t() const;
22
- [[nodiscard]] explicit operator std::int64_t() const;
23
- [[nodiscard]] explicit operator std::uint32_t() const;
24
22
  };
25
23
 
26
24
  // bigint
@@ -29,7 +27,6 @@ class bound_value_for_bigint : public bound_value_next<bigint_tag> {
29
27
  using bound_value_next<bigint_tag>::bound_value_next;
30
28
  [[nodiscard]] explicit operator bigint() const;
31
29
  [[nodiscard]] explicit operator std::int64_t() const;
32
- [[nodiscard]] explicit operator std::uint64_t() const;
33
30
  };
34
31
 
35
32
  // string