@auto_js/napi 0.0.11 → 0.0.12

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.
@@ -5,6 +5,10 @@ import v8;
5
5
  namespace js::napi {
6
6
 
7
7
  // `value_for_data_block`
8
+ auto value_for_data_block::detach() const -> void {
9
+ napi::invoke0(napi_detach_arraybuffer, env(), napi_value{*this});
10
+ }
11
+
8
12
  value_for_data_block::operator std::span<std::byte>() const {
9
13
  // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
10
14
  void* bytes;
@@ -27,12 +31,12 @@ value_for_shared_array_buffer::operator js::shared_array_buffer() const {
27
31
  }
28
32
 
29
33
  // `local_for_typed_array`
30
- auto local_for_typed_array::make(const environment& env, napi_typedarray_type type_tag, local_of<array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<typed_array_tag> {
31
- return local_of<typed_array_tag>::from(napi::invoke(napi_create_typedarray, napi_env{env}, type_tag, length, napi_value{buffer}, byte_offset));
34
+ auto local_for_typed_array::make(environment_lock_witness lock, napi_typedarray_type type_tag, local_of<array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<typed_array_tag> {
35
+ return local_of<typed_array_tag>::from(napi::invoke(napi_create_typedarray, napi_env{lock}, type_tag, length, napi_value{buffer}, byte_offset));
32
36
  }
33
37
 
34
38
  // `value_for_typed_array`
35
- auto value_for_typed_array::make_bound(const environment& env, local_of<typed_array_tag> typed_array) -> any_value_typed_array {
39
+ auto value_for_typed_array::make_bound(environment_lock_witness lock, local_of<typed_array_tag> typed_array) -> any_value_typed_array {
36
40
  // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
37
41
  napi_typedarray_type type_tag;
38
42
  // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
@@ -41,9 +45,9 @@ auto value_for_typed_array::make_bound(const environment& env, local_of<typed_ar
41
45
  std::size_t length;
42
46
  // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
43
47
  std::size_t byte_offset;
44
- napi::invoke0(napi_get_typedarray_info, env, napi_value{typed_array}, &type_tag, &length, nullptr, &array_buffer, &byte_offset);
48
+ napi::invoke0(napi_get_typedarray_info, napi_env{lock}, napi_value{typed_array}, &type_tag, &length, nullptr, &array_buffer, &byte_offset);
45
49
  const auto make = [ & ]<class Tag>(Tag /*tag*/) -> any_value_typed_array {
46
- return value_of<Tag>{env, local_of<Tag>::from(typed_array), std::tuple{local_of<data_block_tag>::from(array_buffer), byte_offset, length}};
50
+ return value_of<Tag>{lock, local_of<Tag>::from(typed_array), std::tuple{local_of<data_block_tag>::from(array_buffer), byte_offset, length}};
47
51
  };
48
52
  switch (type_tag) {
49
53
  case napi_bigint64_array: return make(typed_array_tag_of<std::int64_t>{});
@@ -63,26 +67,26 @@ auto value_for_typed_array::make_bound(const environment& env, local_of<typed_ar
63
67
  }
64
68
 
65
69
  // `local_for_data_view`
66
- auto local_for_data_view::make(const environment& env, local_of<data_block_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<data_view_tag> {
67
- if (napi::invoke(napi_is_arraybuffer, napi_env{env}, buffer)) {
68
- return make(env, local_of<array_buffer_tag>::from(buffer), byte_offset, length);
70
+ auto local_for_data_view::make(environment_lock_witness lock, local_of<data_block_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<data_view_tag> {
71
+ if (napi::invoke(napi_is_arraybuffer, napi_env{lock}, buffer)) {
72
+ return make(lock, local_of<array_buffer_tag>::from(buffer), byte_offset, length);
69
73
  } else {
70
- return make(env, local_of<shared_array_buffer_tag>::from(buffer), byte_offset, length);
74
+ return make(lock, local_of<shared_array_buffer_tag>::from(buffer), byte_offset, length);
71
75
  }
72
76
  }
73
77
 
74
- auto local_for_data_view::make(const environment& env, local_of<array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<data_view_tag> {
75
- return local_of<data_view_tag>::from(napi::invoke(napi_create_dataview, napi_env{env}, length, napi_value{buffer}, byte_offset));
78
+ auto local_for_data_view::make(environment_lock_witness lock, local_of<array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<data_view_tag> {
79
+ return local_of<data_view_tag>::from(napi::invoke(napi_create_dataview, napi_env{lock}, length, napi_value{buffer}, byte_offset));
76
80
  }
77
81
 
78
- auto local_for_data_view::make(const environment& /*env*/, local_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<data_view_tag> {
82
+ auto local_for_data_view::make(environment_lock_witness /*lock*/, local_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<data_view_tag> {
79
83
  return make_sab_data_view(buffer, byte_offset, length);
80
84
  }
81
85
 
82
86
  // `value_for_data_view`
83
- value_for_data_view::value_for_data_view(napi_env env, local_of<data_view_tag> data_view) :
87
+ value_for_data_view::value_for_data_view(environment_lock_witness lock, local_of<data_view_tag> data_view) :
84
88
  value_next{
85
- env,
89
+ lock,
86
90
  data_view,
87
91
  [ & ] -> auto {
88
92
  // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
@@ -91,7 +95,7 @@ value_for_data_view::value_for_data_view(napi_env env, local_of<data_view_tag> d
91
95
  std::size_t length;
92
96
  // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
93
97
  std::size_t byte_offset;
94
- napi::invoke0(napi_get_dataview_info, env, napi_value{data_view}, &length, nullptr, &array_buffer, &byte_offset);
98
+ napi::invoke0(napi_get_dataview_info, napi_env{lock}, napi_value{data_view}, &length, nullptr, &array_buffer, &byte_offset);
95
99
  return std::tuple{local_of<data_block_tag>::from(array_buffer), byte_offset, length};
96
100
  }(),
97
101
  } {}
@@ -1,5 +1,6 @@
1
1
  export module napi_js:array_buffer;
2
2
  import :object;
3
+ import :support.host;
3
4
  import std;
4
5
  import v8;
5
6
 
@@ -11,6 +12,7 @@ class value_for_data_block : public value_next<data_block_tag> {
11
12
  using value_next<data_block_tag>::value_next;
12
13
  [[nodiscard]] constexpr auto byte_length() const -> std::size_t { return std::span<std::byte>{*this}.size(); }
13
14
  [[nodiscard]] constexpr auto data() const -> const std::byte* { return std::span<std::byte>{*this}.data(); }
15
+ auto detach() const -> void;
14
16
  explicit operator std::span<std::byte>() const;
15
17
  };
16
18
 
@@ -32,11 +34,11 @@ class value_for_shared_array_buffer : public value_next<shared_array_buffer_tag>
32
34
  class value_for_array_buffer_view : public value_next<array_buffer_view_tag> {
33
35
  protected:
34
36
  value_for_array_buffer_view(
35
- napi_env env,
37
+ environment_lock_witness lock,
36
38
  local_of<array_buffer_view_tag> typed_array,
37
39
  std::tuple<local_of<data_block_tag>, std::size_t, std::size_t> array_buffer_info
38
40
  ) :
39
- value_next<array_buffer_view_tag>{env, typed_array},
41
+ value_next<array_buffer_view_tag>{lock, typed_array},
40
42
  array_buffer_{std::get<0>(array_buffer_info)},
41
43
  byte_offset_{std::get<1>(array_buffer_info)},
42
44
  length_{std::get<2>(array_buffer_info)} {}
@@ -55,8 +57,8 @@ class value_for_array_buffer_view : public value_next<array_buffer_view_tag> {
55
57
  // `TypedArray`
56
58
  class local_for_typed_array : public local_next<typed_array_tag> {
57
59
  protected:
58
- static auto make(const environment& env, napi_typedarray_type type, local_of<array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<typed_array_tag>;
59
- static auto make(const environment& env, napi_typedarray_type type, local_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<typed_array_tag>;
60
+ static auto make(environment_lock_witness lock, napi_typedarray_type type, local_of<array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<typed_array_tag>;
61
+ static auto make(environment_lock_witness lock, napi_typedarray_type type, local_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<typed_array_tag>;
60
62
  };
61
63
 
62
64
  class value_for_typed_array : public value_next<typed_array_tag> {
@@ -76,7 +78,7 @@ class value_for_typed_array : public value_next<typed_array_tag> {
76
78
  value_of<typed_array_tag_of<std::uint64_t>>,
77
79
  value_of<typed_array_tag_of<std::uint8_t>>>;
78
80
 
79
- static auto make_bound(const environment& env, local_of<typed_array_tag> typed_array) -> any_value_typed_array;
81
+ static auto make_bound(environment_lock_witness lock, local_of<typed_array_tag> typed_array) -> any_value_typed_array;
80
82
  };
81
83
 
82
84
  template <class Type>
@@ -84,15 +86,15 @@ class local_for_typed_array_of : public local_next<typed_array_tag_of<Type>> {
84
86
  public:
85
87
  using local_next<typed_array_tag_of<Type>>::local_next;
86
88
 
87
- static auto make(const environment& env, local_of<data_block_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<typed_array_tag_of<Type>> {
88
- if (napi::invoke(napi_is_arraybuffer, napi_env{env}, buffer)) {
89
- return make(env, local_of<array_buffer_tag>::from(buffer), byte_offset, length);
89
+ static auto make(environment_lock_witness lock, local_of<data_block_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<typed_array_tag_of<Type>> {
90
+ if (napi::invoke(napi_is_arraybuffer, napi_env{lock}, buffer)) {
91
+ return make(lock, local_of<array_buffer_tag>::from(buffer), byte_offset, length);
90
92
  } else {
91
- return make(env, local_of<shared_array_buffer_tag>::from(buffer), byte_offset, length);
93
+ return make(lock, local_of<shared_array_buffer_tag>::from(buffer), byte_offset, length);
92
94
  }
93
95
  }
94
96
 
95
- static auto make(const environment& env, local_of<array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<typed_array_tag_of<Type>> {
97
+ static auto make(environment_lock_witness lock, local_of<array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<typed_array_tag_of<Type>> {
96
98
  constexpr auto type_tag = util::overloaded{
97
99
  [](std::type_identity<double>) -> napi_typedarray_type { return napi_float64_array; },
98
100
  [](std::type_identity<float>) -> napi_typedarray_type { return napi_float32_array; },
@@ -107,11 +109,11 @@ class local_for_typed_array_of : public local_next<typed_array_tag_of<Type>> {
107
109
  [](std::type_identity<std::uint64_t>) -> napi_typedarray_type { return napi_biguint64_array; },
108
110
  [](std::type_identity<std::uint8_t>) -> napi_typedarray_type { return napi_uint8_array; },
109
111
  }(type<Type>);
110
- return local_of<typed_array_tag_of<Type>>::from(local_for_typed_array::make(env, type_tag, buffer, byte_offset, length));
112
+ return local_of<typed_array_tag_of<Type>>::from(local_for_typed_array::make(lock, type_tag, buffer, byte_offset, length));
111
113
  }
112
114
 
113
115
  // napi doesn't provide a way to make a typed array view on a shared array buffer
114
- static auto make(const environment& /*env*/, local_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<typed_array_tag_of<Type>> {
116
+ static auto make(environment_lock_witness /*lock*/, local_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<typed_array_tag_of<Type>> {
115
117
  return make_sab_typed_array_of<Type>(buffer, byte_offset, length);
116
118
  }
117
119
  };
@@ -127,14 +129,14 @@ class local_for_data_view : public local_next<data_view_tag> {
127
129
  public:
128
130
  using local_next<data_view_tag>::local_next;
129
131
 
130
- static auto make(const environment& env, local_of<data_block_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<data_view_tag>;
131
- static auto make(const environment& env, local_of<array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<data_view_tag>;
132
- static auto make(const environment& env, local_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<data_view_tag>;
132
+ static auto make(environment_lock_witness lock, local_of<data_block_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<data_view_tag>;
133
+ static auto make(environment_lock_witness lock, local_of<array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<data_view_tag>;
134
+ static auto make(environment_lock_witness lock, local_of<shared_array_buffer_tag> buffer, std::size_t byte_offset, std::size_t length) -> local_of<data_view_tag>;
133
135
  };
134
136
 
135
137
  class value_for_data_view : public value_next<data_view_tag> {
136
138
  public:
137
- value_for_data_view(napi_env env, local_of<data_view_tag> data_view);
139
+ value_for_data_view(environment_lock_witness lock, local_of<data_view_tag> data_view);
138
140
  };
139
141
 
140
142
  } // namespace js::napi
package/value/class.cc CHANGED
@@ -8,7 +8,7 @@ namespace js::napi {
8
8
 
9
9
  template <class Type>
10
10
  template <class... Args>
11
- auto local_for_class_of<Type>::construct(auto& env, Args&&... args) const -> local_of<object_tag>
11
+ auto local_for_class_of<Type>::construct(const auto& lock, Args&&... args) const -> local_of<object_tag>
12
12
  requires std::constructible_from<Type, Args...> {
13
13
  // NOLINTNEXTLINE(readability-simplify-boolean-expr)
14
14
  if (false) {
@@ -16,33 +16,33 @@ auto local_for_class_of<Type>::construct(auto& env, Args&&... args) const -> loc
16
16
  std::ignore = std::tuple<std::remove_cvref_t<Args>...>{std::forward<Args>(args)...};
17
17
  }
18
18
  // NOLINTNEXTLINE(bugprone-use-after-move)
19
- return runtime_construct(env, std::forward_as_tuple(std::forward<Args>(args)...), std::tuple{});
19
+ return runtime_construct(lock, std::forward_as_tuple(std::forward<Args>(args)...), std::tuple{});
20
20
  }
21
21
 
22
22
  template <class Type>
23
23
  template <class... HostArgs, class... RuntimeArgs>
24
24
  auto local_for_class_of<Type>::runtime_construct(
25
- auto& env,
25
+ const auto& lock,
26
26
  std::tuple<HostArgs...> host_args,
27
27
  std::tuple<RuntimeArgs...> runtime_args
28
28
  ) const -> local_of<object_tag>
29
29
  requires std::constructible_from<Type, HostArgs...> {
30
30
  constexpr auto [... indices ] = util::sequence<sizeof...(HostArgs)>;
31
31
  auto instance = std::make_unique<Type>(std::get<indices>(std::move(host_args))...);
32
- return transfer_construct(env, std::move(instance), std::move(runtime_args));
32
+ return transfer_construct(lock, std::move(instance), std::move(runtime_args));
33
33
  }
34
34
 
35
35
  template <class Type>
36
36
  template <class... Args>
37
- auto local_for_class_of<Type>::transfer_construct(auto& env, auto instance, std::tuple<Args...> runtime_args) const -> local_of<object_tag> {
37
+ auto local_for_class_of<Type>::transfer_construct(const auto& lock, auto instance, std::tuple<Args...> runtime_args) const -> local_of<object_tag> {
38
38
  using element_type = decltype(instance)::element_type;
39
39
  auto construct = [ & ](napi_value this_arg) -> napi_value {
40
40
  // Tag `this_arg`
41
- napi::invoke0(napi_type_tag_object, napi_env{env}, this_arg, &type_tag_for<element_type>);
41
+ napi::invoke0(napi_type_tag_object, napi_env{lock}, this_arg, &type_tag_for<element_type>);
42
42
 
43
43
  // Wrap w/ finalizer
44
44
  return apply_finalizer(std::move(instance), [ & ](element_type* instance, node_api_basic_finalize finalize, void* hint) -> napi_value {
45
- napi::invoke0(napi_wrap, napi_env{env}, this_arg, instance, finalize, hint, nullptr);
45
+ napi::invoke0(napi_wrap, napi_env{lock}, this_arg, instance, finalize, hint, nullptr);
46
46
  return this_arg;
47
47
  });
48
48
  };
@@ -50,27 +50,27 @@ auto local_for_class_of<Type>::transfer_construct(auto& env, auto instance, std:
50
50
  // Now an external (of `internal_constructor`) gets passed to JavaScript for a moment and
51
51
  // hopefully it jumps into `construct`
52
52
  auto construct_ref = internal_constructor{construct};
53
- auto* construct_external = napi_value{local_of<external_tag>::make(env, &construct_ref)};
54
- auto [... runtime_arg_values ] = js::transfer_in_strict<std::array<napi_value, sizeof...(Args)>>(std::move(runtime_args), env);
53
+ auto* construct_external = napi_value{local_of<external_tag>::make(lock, &construct_ref)};
54
+ auto [... runtime_arg_values ] = js::transfer_in_strict<std::array<napi_value, sizeof...(Args)>>(std::move(runtime_args), lock);
55
55
  auto arg_vector = std::array{construct_external, runtime_arg_values...};
56
- auto* this_arg = napi::invoke(napi_new_instance, napi_env{env}, napi_value{*this}, arg_vector.size(), arg_vector.data());
56
+ auto* this_arg = napi::invoke(napi_new_instance, napi_env{lock}, napi_value{*this}, arg_vector.size(), arg_vector.data());
57
57
  return local_of<object_tag>::from(this_arg);
58
58
  }
59
59
 
60
60
  template <class Type>
61
61
  template <class Environment>
62
- auto local_for_class_of<Type>::make(Environment& env, const auto& class_template) -> local_of<class_tag_of<Type>> {
62
+ auto local_for_class_of<Type>::make(const environment_lock_witness_of<Environment>& lock, const auto& class_template) -> local_of<class_tag_of<Type>> {
63
63
  // Make constructor callback
64
64
  auto [ construct_ptr, constructor_data ] =
65
- make_callback_storage(env, make_constructor_function<Environment, Type>(class_template.constructor.function));
65
+ make_callback_storage(lock, make_constructor_function<Environment, Type>(class_template.constructor.function));
66
66
  static_assert(std::remove_cvref_t<decltype(class_template.constructor)>::disposition == property_disposition::function);
67
67
  static_assert(!requires { typename decltype(constructor_data)::element_type; });
68
68
 
69
69
  // Member function property descriptor
70
70
  const auto make_member_function_descriptor = [ & ]<class Property>(const Property& property) -> napi_property_descriptor
71
- requires(Property::scope == class_property_scope::prototype) {
71
+ requires(Property::scope == class_property_scope::prototype && Property::disposition == property_disposition::function) {
72
72
  constexpr auto u8_name = util::make_consteval_string_view(util::transcode_string<char>(property.name));
73
- auto [ callback, data ] = make_callback_storage(env, make_member_function<Environment, Type>(property.function));
73
+ auto [ callback, data ] = make_callback_storage(lock, make_member_function<Environment, Type>(property.function));
74
74
  static_assert(!requires { typename decltype(data)::element_type; });
75
75
  return {
76
76
  .utf8name = u8_name.data(),
@@ -87,11 +87,31 @@ auto local_for_class_of<Type>::make(Environment& env, const auto& class_template
87
87
  };
88
88
  };
89
89
 
90
+ // Member getter property descriptor
91
+ const auto make_member_getter_descriptor = [ & ]<class Property>(const Property& property) -> napi_property_descriptor
92
+ requires(Property::scope == class_property_scope::prototype && Property::disposition == property_disposition::accessor) {
93
+ constexpr auto u8_name = util::make_consteval_string_view(util::transcode_string<char>(property.name));
94
+ auto [ callback, data ] = make_callback_storage(lock, make_member_function<Environment, Type>(property.function));
95
+ static_assert(!requires { typename decltype(data)::element_type; });
96
+ return {
97
+ .utf8name = u8_name.data(),
98
+ .name{},
99
+
100
+ .method{},
101
+ .getter = callback,
102
+ .setter{},
103
+ .value{},
104
+
105
+ .attributes = napi_configurable,
106
+ .data = data,
107
+ };
108
+ };
109
+
90
110
  // Static function property descriptor
91
111
  const auto make_static_function_descriptor = [ & ]<class Property>(const Property& property) -> napi_property_descriptor
92
112
  requires(Property::scope == class_property_scope::constructor) {
93
113
  constexpr auto u8_name = util::make_consteval_string_view(util::transcode_string<char>(property.name));
94
- auto [ callback, data ] = make_callback_storage(env, make_free_function<Environment>(property.function));
114
+ auto [ callback, data ] = make_callback_storage(lock, make_free_function<Environment>(property.function));
95
115
  static_assert(!requires { typename decltype(data)::element_type; });
96
116
  return {
97
117
  .utf8name = u8_name.data(),
@@ -111,6 +131,7 @@ auto local_for_class_of<Type>::make(Environment& env, const auto& class_template
111
131
  // Make class property descriptors
112
132
  const auto make_property_descriptor = util::overloaded{
113
133
  make_member_function_descriptor,
134
+ make_member_getter_descriptor,
114
135
  make_static_function_descriptor,
115
136
  };
116
137
  const auto [... properties ] = class_template.properties;
@@ -123,7 +144,7 @@ auto local_for_class_of<Type>::make(Environment& env, const auto& class_template
123
144
  constexpr auto u8_name = util::make_consteval_string_view(util::transcode_string<char>(class_template.constructor.name));
124
145
  auto result = napi::invoke(
125
146
  napi_define_class,
126
- napi_env{env},
147
+ napi_env{lock},
127
148
  u8_name.data(),
128
149
  u8_name.length(),
129
150
  construct_ptr,
package/value/class.h.cc CHANGED
@@ -1,4 +1,5 @@
1
1
  export module napi_js:class_;
2
+ import :lock;
2
3
  import :object;
3
4
  import std;
4
5
 
@@ -9,19 +10,19 @@ class local_for_class_of : public local_next<class_tag_of<Type>> {
9
10
  public:
10
11
  // Construct a new C++ instance & JavaScript value
11
12
  template <class... Args>
12
- auto construct(auto& env, Args&&... args) const -> local_of<object_tag>
13
+ auto construct(const auto& lock, Args&&... args) const -> local_of<object_tag>
13
14
  requires std::constructible_from<Type, Args...>;
14
15
 
15
16
  template <class... HostArgs, class... RuntimeArgs>
16
- auto runtime_construct(auto& env, std::tuple<HostArgs...> host_args, std::tuple<RuntimeArgs...> runtime_args) const -> local_of<object_tag>
17
+ auto runtime_construct(const auto& lock, std::tuple<HostArgs...> host_args, std::tuple<RuntimeArgs...> runtime_args) const -> local_of<object_tag>
17
18
  requires std::constructible_from<Type, HostArgs...>;
18
19
 
19
20
  // Create a JavaScript value from an already-created instance smart pointer
20
21
  template <class... Args>
21
- auto transfer_construct(auto& env, auto instance, std::tuple<Args...> runtime_args) const -> local_of<object_tag>;
22
+ auto transfer_construct(const auto& lock, auto instance, std::tuple<Args...> runtime_args) const -> local_of<object_tag>;
22
23
 
23
24
  template <class Environment>
24
- static auto make(Environment& env, const auto& class_template) -> local_of<class_tag_of<Type>>;
25
+ static auto make(const environment_lock_witness_of<Environment>& lock, const auto& class_template) -> local_of<class_tag_of<Type>>;
25
26
  };
26
27
 
27
28
  } // namespace js::napi
package/value/external.cc CHANGED
@@ -7,11 +7,11 @@ namespace js::napi {
7
7
  class local_for_external : public local_next<external_tag> {
8
8
  public:
9
9
  // untagged
10
- static auto make(auto& env, void* pointer) -> local_of<external_tag>;
10
+ static auto make(environment_lock_witness lock, void* pointer) -> local_of<external_tag>;
11
11
 
12
12
  // tagged
13
13
  template <class Type>
14
- static auto make(auto& env, Type* pointer) -> local_of<external_tag>;
14
+ static auto make(environment_lock_witness lock, Type* pointer) -> local_of<external_tag>;
15
15
  };
16
16
 
17
17
  class value_for_external : public value_next<external_tag> {
@@ -24,15 +24,15 @@ class value_for_external : public value_next<external_tag> {
24
24
 
25
25
  // ---
26
26
 
27
- auto local_for_external::make(auto& env, void* pointer) -> local_of<external_tag> {
28
- auto* external = napi::invoke(napi_create_external, napi_env{env}, pointer, nullptr, nullptr);
27
+ auto local_for_external::make(environment_lock_witness lock, void* pointer) -> local_of<external_tag> {
28
+ auto* external = napi::invoke(napi_create_external, napi_env{lock}, pointer, nullptr, nullptr);
29
29
  return local_of<external_tag>::from(external);
30
30
  }
31
31
 
32
32
  template <class Type>
33
- auto local_for_external::make(auto& env, Type* pointer) -> local_of<external_tag> {
34
- auto external = make(env, static_cast<void*>(pointer));
35
- napi::invoke0(napi_type_tag_object, napi_env{env}, external, &type_tag_for<Type>);
33
+ auto local_for_external::make(environment_lock_witness lock, Type* pointer) -> local_of<external_tag> {
34
+ auto external = make(lock, static_cast<void*>(pointer));
35
+ napi::invoke0(napi_type_tag_object, napi_env{lock}, external, &type_tag_for<Type>);
36
36
  return external;
37
37
  };
38
38
 
package/value/function.cc CHANGED
@@ -5,35 +5,35 @@ import std;
5
5
  namespace js::napi {
6
6
 
7
7
  template <class Result>
8
- auto local_for_function::apply(auto_environment auto& env, auto&& args) -> Result {
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});
8
+ auto local_for_function::apply(const auto& lock, auto&& args) -> Result {
9
+ auto argv = js::transfer_in_strict<std::vector<napi_value>>(std::forward<decltype(args)>(args), lock);
10
+ return invoke<Result>(lock, std::span{argv});
11
11
  }
12
12
 
13
13
  template <class Result>
14
- auto local_for_function::call(auto_environment auto& env, auto&&... args) -> Result {
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});
14
+ auto local_for_function::call(const auto& lock, auto&&... args) -> Result {
15
+ auto argv = js::transfer_in_strict<std::array<napi_value, sizeof...(args)>>(std::forward_as_tuple(args...), lock);
16
+ return invoke<Result>(lock, std::span{argv});
17
17
  }
18
18
 
19
19
  template <class Result>
20
- auto local_for_function::invoke(auto_environment auto& env, std::span<napi_value> args) -> Result {
21
- auto undefined = js::transfer_in_strict<napi_value>(std::monostate{}, env);
22
- auto* result = napi::invoke(napi_call_function, napi_env{env}, undefined, napi_value{*this}, args.size(), args.data());
23
- return js::transfer_out<Result>(result, env);
20
+ auto local_for_function::invoke(const auto& lock, std::span<napi_value> args) -> Result {
21
+ auto undefined = js::transfer_in_strict<napi_value>(std::monostate{}, lock);
22
+ auto* result = napi::invoke(napi_call_function, napi_env{lock}, undefined, napi_value{*this}, args.size(), args.data());
23
+ return js::transfer_out<Result>(result, lock);
24
24
  }
25
25
 
26
- template <auto_environment Environment>
27
- auto local_for_function::make(Environment& env, auto function) -> local_of<function_tag> {
28
- auto [ callback, data ] = make_callback_storage(env, make_free_function<Environment>(std::move(function).callback));
26
+ template <class Environment>
27
+ auto local_for_function::make(const environment_lock_witness_of<Environment>& lock, auto function) -> local_of<function_tag> {
28
+ auto [ callback, data ] = make_callback_storage(lock, make_free_function<Environment>(std::move(function).callback));
29
29
  auto make = [ & ](void* data) -> local_of<function_tag> {
30
- return local_of<function_tag>::from(napi::invoke(napi_create_function, napi_env{env}, function.name.data(), function.name.length(), callback, data));
30
+ return local_of<function_tag>::from(napi::invoke(napi_create_function, napi_env{lock}, function.name.data(), function.name.length(), callback, data));
31
31
  };
32
32
  if constexpr (requires { typename decltype(data)::element_type; }) {
33
33
  // Function requires finalizer
34
34
  auto function = make(data.get());
35
35
  return apply_finalizer(std::move(data), [ & ](auto* data, napi_finalize finalize, void* hint) -> local_of<function_tag> {
36
- napi::invoke0(napi_add_finalizer, napi_env{env}, function, data, finalize, hint, nullptr);
36
+ napi::invoke0(napi_add_finalizer, napi_env{lock}, function, data, finalize, hint, nullptr);
37
37
  return function;
38
38
  });
39
39
  } else {
@@ -1,4 +1,5 @@
1
1
  export module napi_js:function;
2
+ import :lock;
2
3
  import :primitive;
3
4
  import std;
4
5
 
@@ -7,17 +8,17 @@ namespace js::napi {
7
8
  class local_for_function : public local_next<function_tag> {
8
9
  public:
9
10
  template <class Result = std::monostate>
10
- auto apply(auto_environment auto& env, auto&& args) -> Result;
11
+ auto apply(const auto& lock, auto&& args) -> Result;
11
12
 
12
13
  template <class Result = std::monostate>
13
- auto call(auto_environment auto& env, auto&&... args) -> Result;
14
+ auto call(const auto& lock, auto&&... args) -> Result;
14
15
 
15
- template <auto_environment Environment>
16
- static auto make(Environment& env, auto function) -> local_of<function_tag>;
16
+ template <class Environment>
17
+ static auto make(const environment_lock_witness_of<Environment>& lock, auto function) -> local_of<function_tag>;
17
18
 
18
19
  private:
19
20
  template <class Result>
20
- auto invoke(auto_environment auto& env, std::span<napi_value> args) -> Result;
21
+ auto invoke(const auto& lock, std::span<napi_value> args) -> Result;
21
22
  };
22
23
 
23
24
  } // namespace js::napi
package/value/object.cc CHANGED
@@ -3,8 +3,8 @@ module napi_js;
3
3
  namespace js::napi {
4
4
 
5
5
  // object
6
- auto value_for_object::get(napi_value key) const -> local_of<value_tag> {
7
- return local_of<value_tag>::from(napi::invoke(napi_get_property, env(), napi_value{*this}, key));
6
+ auto value_for_object::get(napi_value key) const -> local_of<> {
7
+ return local_of<>::from(napi::invoke(napi_get_property, env(), napi_value{*this}, key));
8
8
  }
9
9
 
10
10
  auto value_for_object::has(napi_value key) const -> bool {
package/value/object.h.cc CHANGED
@@ -7,7 +7,7 @@ namespace js::napi {
7
7
  // object
8
8
  class local_for_object : public local_next<object_tag> {
9
9
  public:
10
- auto assign(auto_environment auto& env, auto source) const -> void;
10
+ auto assign(const auto& lock, auto source) const -> void;
11
11
  };
12
12
 
13
13
  class value_for_object : public value_next<object_tag> {
@@ -17,7 +17,7 @@ class value_for_object : public value_next<object_tag> {
17
17
  template <class Type>
18
18
  [[nodiscard]] auto try_cast(std::type_identity<Type> /*type*/) const -> Type*;
19
19
 
20
- [[nodiscard]] auto get(napi_value key) const -> local_of<value_tag>;
20
+ [[nodiscard]] auto get(napi_value key) const -> local_of<>;
21
21
  [[nodiscard]] auto has(napi_value key) const -> bool;
22
22
 
23
23
  auto set(napi_value key, napi_value value) -> void;
package/value/record.cc CHANGED
@@ -3,6 +3,7 @@ import std;
3
3
 
4
4
  namespace js::napi {
5
5
 
6
+ // value_for_record
6
7
  auto value_for_record::into_range() const -> range_type {
7
8
  return keys() | std::views::transform(iterator_transform{*this});
8
9
  }
@@ -21,7 +22,7 @@ auto value_for_record::keys() const -> const keys_type& {
21
22
  static_cast<napi_key_filter>(napi_key_enumerable | napi_key_skip_symbols),
22
23
  napi_key_keep_numbers
23
24
  );
24
- keys_ = keys_type{env(), js::napi::local_of<vector_tag>::from(property_names)};
25
+ keys_ = keys_type{lock(), js::napi::local_of<vector_tag>::from(property_names), false};
25
26
  }
26
27
  return keys_;
27
28
  }
@@ -29,8 +30,13 @@ auto value_for_record::keys() const -> const keys_type& {
29
30
  value_for_record::iterator_transform::iterator_transform(const value_for_record& subject) :
30
31
  subject_{&subject} {}
31
32
 
32
- auto value_for_record::iterator_transform::operator()(local_of<value_tag> key) const -> value_type {
33
+ auto value_for_record::iterator_transform::operator()(local_of<> key) const -> value_type {
33
34
  return std::pair{key_type::from(key), subject_->get(key)};
34
35
  }
35
36
 
37
+ // value_for_list
38
+ auto value_for_list::values() const -> value_of<vector_tag> {
39
+ return value_of<vector_tag>{lock(), local_of<vector_tag>::from(*this)};
40
+ }
41
+
36
42
  } // namespace js::napi
package/value/record.h.cc CHANGED
@@ -10,14 +10,14 @@ class value_for_record : public value_next<record_tag> {
10
10
  using value_next<record_tag>::value_next;
11
11
  using keys_type = value_of<vector_tag>;
12
12
  using key_type = local_of<primitive_tag>;
13
- using mapped_type = local_of<value_tag>;
13
+ using mapped_type = local_of<>;
14
14
  using value_type = std::pair<key_type, mapped_type>;
15
15
 
16
16
  private:
17
17
  class iterator_transform {
18
18
  public:
19
19
  explicit iterator_transform(const value_for_record& subject_);
20
- auto operator()(local_of<value_tag> key) const -> value_type;
20
+ auto operator()(local_of<> key) const -> value_type;
21
21
 
22
22
  private:
23
23
  const value_for_record* subject_;
@@ -36,4 +36,10 @@ class value_for_record : public value_next<record_tag> {
36
36
  mutable keys_type keys_;
37
37
  };
38
38
 
39
+ class value_for_list : public value_next<list_tag> {
40
+ public:
41
+ using value_next<list_tag>::value_next;
42
+ auto values() const -> value_of<vector_tag>;
43
+ };
44
+
39
45
  } // namespace js::napi