@auto_js/napi 0.0.6 → 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 CHANGED
@@ -14,9 +14,12 @@ target_link_libraries(${napi_js} PUBLIC nodejs)
14
14
 
15
15
  target_sources(${napi_js}
16
16
  PRIVATE
17
+ api/napi_scheduler.cc
17
18
  api/uv_dlib.cc
18
19
  api/uv_scheduler.cc
19
20
  support/environment.cc
21
+ support/host_shim.cc
22
+ support/host.cc
20
23
  support/initialize.cc
21
24
  transfer/accept.cc
22
25
  value/array_buffer.cc
@@ -31,6 +34,8 @@ target_sources(${napi_js}
31
34
  api/finalizer.cc
32
35
  api/handle_scope.cc
33
36
  api/invoke.cc
37
+ api/napi_scheduler.h.cc
38
+ api/threadsafe_function.cc
34
39
  api/uv_dlib.h.cc
35
40
  api/uv_handle.cc
36
41
  api/uv_scheduler.h.cc
@@ -42,10 +47,10 @@ target_sources(${napi_js}
42
47
  support/callback_storage.cc
43
48
  support/callback.cc
44
49
  support/class_template_storage.cc
45
- support/container.cc
46
50
  support/environment_fwd.cc
47
51
  support/environment.h.cc
48
52
  support/error_scope.cc
53
+ support/host.h.cc
49
54
  support/initialize.h.cc
50
55
  support/promise.cc
51
56
  support/string_table.cc
package/_module.cc CHANGED
@@ -5,7 +5,6 @@ export import :bound_value;
5
5
  export import :callback;
6
6
  export import :class_definitions;
7
7
  export import :class_template_storage;
8
- export import :container;
9
8
  export import :environment;
10
9
  export import :error_scope;
11
10
  export import :function_definitions;
package/api/api.cc CHANGED
@@ -1,11 +1,13 @@
1
1
  export module napi_js:api;
2
- // Internal nodejs API utilities which have no dependencies on anything else in `napi_js`
3
- export import nodejs;
4
2
  export import auto_js;
5
- export import :api.uv_scheduler;
6
- export import :api.uv_handle;
7
- export import :api.uv_dlib;
8
- export import :api.invoke;
9
- export import :api.handle_scope;
10
- export import :api.finalizer;
3
+ export import nodejs;
4
+ // Internal nodejs API utilities which have no dependencies on anything else in `napi_js`
11
5
  export import :api.callback_info;
6
+ export import :api.finalizer;
7
+ export import :api.handle_scope;
8
+ export import :api.invoke;
9
+ export import :api.napi_scheduler;
10
+ export import :api.threadsafe_function;
11
+ export import :api.uv_dlib;
12
+ export import :api.uv_handle;
13
+ export import :api.uv_scheduler;
package/api/finalizer.cc CHANGED
@@ -5,36 +5,60 @@ import util;
5
5
 
6
6
  namespace js::napi {
7
7
 
8
- // Finalizer for basic unique_ptr
9
- export template <class Type, class Deleter>
10
- auto apply_finalizer(std::unique_ptr<Type, Deleter> unique, std::invocable<Type*, napi_finalize, void*> auto accept) -> decltype(auto)
11
- requires std::is_empty_v<Deleter> {
12
- // Finalizer uses a default-constructed deleter
13
- const napi_finalize finalize = [](napi_env /*env*/, void* data, void* /*hint*/) -> void {
14
- Deleter deleter{};
15
- deleter(static_cast<Type*>(data));
16
- };
17
- auto result = util::regular_return{[ & ]() -> decltype(auto) {
18
- return accept(unique.get(), finalize, nullptr);
19
- }}();
20
- unique.release();
21
- return *std::move(result);
8
+ // Generic finalizer for basic `std::unique_ptr<T>`
9
+ template <class Env, class Type, class Deleter>
10
+ auto make_finalizer(std::type_identity<Env> /*type*/, std::unique_ptr<Type, Deleter>* unique) {
11
+ if constexpr (std::is_empty_v<Deleter>) {
12
+ // Finalizer uses a default-constructed deleter
13
+ auto finalize = [](Env /*env*/, void* data, void* /*hint*/) -> void {
14
+ Deleter deleter{};
15
+ deleter(static_cast<Type*>(data));
16
+ };
17
+ auto release = [ unique ] { unique->release(); };
18
+ return std::tuple{finalize, nullptr, release};
19
+ } else {
20
+ static_assert(std::is_trivially_destructible_v<Deleter>);
21
+ static_assert(sizeof(Deleter) == sizeof(void*));
22
+ // Hint is the deleter object
23
+ auto finalize = [](Env /*env*/, void* data, void* hint) -> void {
24
+ std::bit_cast<Deleter>(hint)(static_cast<Type*>(data));
25
+ };
26
+ auto release = [ unique ] { unique->release(); };
27
+ return std::tuple{finalize, std::bit_cast<void*>(unique->get_deleter()), release};
28
+ }
22
29
  }
23
30
 
24
- // Finalizer for shared_ptr
25
- export template <class Type>
26
- auto apply_finalizer(std::shared_ptr<Type> shared, std::invocable<Type*, napi_finalize, void*> auto accept) -> decltype(auto) {
31
+ // Generic finalizer for `std::shared_ptr<T>`
32
+ template <class Env, class Type>
33
+ auto make_finalizer(std::type_identity<Env> /*type*/, std::shared_ptr<Type>* shared) {
27
34
  // `shared_ptr<T>*` is passed as the finalizer hint
28
35
  using shared_ptr_type = std::shared_ptr<Type>;
29
- auto* ptr = shared.get();
30
- auto ptr_ptr = std::make_unique<shared_ptr_type>(std::move(shared));
31
- const napi_finalize finalize = [](napi_env /*env*/, void* /*data*/, void* hint) -> void {
36
+ auto* ptr = shared->get();
37
+ auto ptr_ptr = std::make_unique<shared_ptr_type>(std::move(*shared));
38
+ auto finalize = [](Env /*env*/, void* /*data*/, void* hint) -> void {
32
39
  delete static_cast<shared_ptr_type*>(hint);
33
40
  };
34
- auto result = util::regular_return{[ & ]() -> decltype(auto) {
35
- return accept(ptr, finalize, ptr_ptr.get());
41
+ auto release = [ ptr_ptr = std::move(ptr_ptr) ] mutable { ptr_ptr.release(); };
42
+ return std::tuple{finalize, ptr_ptr.get(), std::move(release)};
43
+ }
44
+
45
+ // Apply a finalizer to the given smart pointer type
46
+ template <class Pointer, class Apply>
47
+ auto apply_finalizer(Pointer unique, Apply apply) -> decltype(auto) {
48
+ using element_type = Pointer::element_type;
49
+ constexpr auto napi_env_type = []() consteval -> auto {
50
+ if constexpr (std::invocable<Apply, element_type*, node_api_basic_finalize, void*>) {
51
+ return type<node_api_basic_env>;
52
+ } else {
53
+ static_assert(std::invocable<Apply, element_type*, napi_finalize, void*>);
54
+ return type<napi_env>;
55
+ }
56
+ }();
57
+ auto [ finalize, hint, release ] = make_finalizer(napi_env_type, &unique);
58
+ auto result = util::regular_return{[ & ] -> decltype(auto) {
59
+ return apply(unique.get(), finalize, hint);
36
60
  }}();
37
- ptr_ptr.release();
61
+ release();
38
62
  return *std::move(result);
39
63
  }
40
64
 
@@ -0,0 +1,39 @@
1
+ module napi_js;
2
+ import std;
3
+
4
+ namespace js::napi {
5
+
6
+ // napi_scheduler
7
+ napi_scheduler::napi_scheduler(napi_env env) :
8
+ fn_{env, nullptr} {
9
+ // It starts ref'd, so we need to unref it
10
+ fn_.unref(env);
11
+ }
12
+
13
+ napi_scheduler::operator bool() const {
14
+ return bool{fn_};
15
+ }
16
+
17
+ auto napi_scheduler::close(threadsafe_function_type::close_callback close) -> void {
18
+ fn_.close(close);
19
+ }
20
+
21
+ auto napi_scheduler::decrement_ref(node_api_basic_env env) const -> void {
22
+ auto& storage = *fn_;
23
+ if (--storage.refs == 0) {
24
+ fn_.unref(env);
25
+ }
26
+ }
27
+
28
+ auto napi_scheduler::increment_ref(node_api_basic_env env) const -> void {
29
+ auto& storage = *fn_;
30
+ if (++storage.refs == 1) {
31
+ fn_.ref(env);
32
+ }
33
+ }
34
+
35
+ auto napi_scheduler::storage::operator()(napi_env env, napi_value value, task_type& task) -> void {
36
+ task(env, value);
37
+ }
38
+
39
+ } // namespace js::napi
@@ -0,0 +1,58 @@
1
+ export module napi_js:api.napi_scheduler;
2
+ import :api.threadsafe_function;
3
+ import nodejs;
4
+ import std;
5
+ import util;
6
+
7
+ namespace js::napi {
8
+
9
+ // Shareable napi scheduler via napi_threadsafe_function
10
+ export class napi_scheduler {
11
+ private:
12
+ struct storage;
13
+ using task_type = util::move_only_function<auto(napi_env, napi_value)->void>;
14
+ using threadsafe_function_type = threadsafe_function_of<storage, task_type>;
15
+
16
+ public:
17
+ explicit napi_scheduler(napi_env env);
18
+ auto operator()(auto task, auto&&... args) const -> bool;
19
+ explicit operator bool() const;
20
+ auto close(threadsafe_function_type::close_callback close) -> void;
21
+ auto decrement_ref(node_api_basic_env env) const -> void;
22
+ auto increment_ref(node_api_basic_env env) const -> void;
23
+
24
+ private:
25
+ struct storage {
26
+ storage() = default;
27
+ auto operator()(napi_env env, napi_value value, task_type& task) -> void;
28
+ int refs{};
29
+ };
30
+
31
+ threadsafe_function_of<storage, task_type> fn_;
32
+ };
33
+
34
+ // An environment with an uv loop and scheduler
35
+ export class napi_schedulable {
36
+ public:
37
+ explicit napi_schedulable(napi_env env) : scheduler_{env} {}
38
+ [[nodiscard]] auto scheduler(this auto& self) -> auto& { return self.scheduler_; }
39
+
40
+ private:
41
+ napi_scheduler scheduler_;
42
+ };
43
+
44
+ // ---
45
+
46
+ auto napi_scheduler::operator()(auto task, auto&&... args) const -> bool {
47
+ return fn_(
48
+ [ task = std::move(task),
49
+ ... args = std::forward<decltype(args)>(args) ](
50
+ napi_env env,
51
+ napi_value value
52
+ ) mutable -> void {
53
+ task(env, value, std::move(args)...);
54
+ }
55
+ );
56
+ }
57
+
58
+ } // namespace js::napi
@@ -0,0 +1,155 @@
1
+ export module napi_js:api.threadsafe_function;
2
+ import :api.invoke;
3
+ import nodejs;
4
+ import std;
5
+ import util;
6
+
7
+ namespace js::napi {
8
+
9
+ // Maintain a "threadsafe function" via napi. `Context` must be invocable with
10
+ // `(napi_env, napi_value, Message&)`.
11
+ export template <class Context, class Message>
12
+ class threadsafe_function_of : util::non_copyable {
13
+ public:
14
+ using close_callback = util::function_ref<auto()->void>;
15
+
16
+ explicit threadsafe_function_of(auto& env, napi_value value, auto&&... args);
17
+ threadsafe_function_of(const threadsafe_function_of&);
18
+ threadsafe_function_of(threadsafe_function_of&&) noexcept;
19
+ ~threadsafe_function_of();
20
+ auto operator=(const threadsafe_function_of&) -> threadsafe_function_of& = delete;
21
+ auto operator=(threadsafe_function_of&&) -> threadsafe_function_of& = delete;
22
+
23
+ auto close(close_callback callback) -> void;
24
+ auto ref(node_api_basic_env env) const -> void;
25
+ auto unref(node_api_basic_env env) const -> void;
26
+ auto operator()(Message message) const -> bool;
27
+ auto operator*() const -> Context& { return get(); }
28
+ explicit operator bool() const { return tsfn_ != nullptr; }
29
+
30
+ private:
31
+ struct storage : Context {
32
+ public:
33
+ friend threadsafe_function_of;
34
+ using Context::Context;
35
+
36
+ private:
37
+ close_callback close_hook_{[] -> void {}};
38
+ };
39
+ auto get() const -> storage&;
40
+
41
+ constexpr static auto trivial_message =
42
+ std::is_trivially_destructible_v<Message> && sizeof(Message) <= sizeof(void*);
43
+ mutable napi_threadsafe_function tsfn_;
44
+ };
45
+
46
+ // ---
47
+
48
+ template <class Context, class Message>
49
+ threadsafe_function_of<Context, Message>::threadsafe_function_of(auto& env, napi_value value, auto&&... args) :
50
+ tsfn_{[ & ]() -> auto {
51
+ constexpr auto name = util::make_consteval_string_view(util::cw<"threadsafe_function_of">);
52
+ auto resource_name = napi::invoke(napi_create_string_latin1, env, name.data(), name.size());
53
+ auto context = std::make_unique<storage>(std::forward<decltype(args)>(args)...);
54
+ // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
55
+ auto callback = napi_threadsafe_function_call_js{[](napi_env env, napi_value value, void* context_ptr, void* data) -> void {
56
+ auto& context = *static_cast<storage*>(context_ptr);
57
+ if constexpr (trivial_message) {
58
+ if (env != nullptr) {
59
+ auto message = Message{};
60
+ std::memcpy(&message, &data, sizeof(Message));
61
+ context(env, value, message);
62
+ }
63
+ } else {
64
+ auto message = std::unique_ptr<Message>{static_cast<Message*>(data)};
65
+ if (env != nullptr) {
66
+ context(env, value, *message);
67
+ }
68
+ }
69
+ }};
70
+ auto finalize = napi_finalize{[](napi_env /*env*/, void* /*data*/, void* hint) -> void {
71
+ auto* storage_ptr = static_cast<storage*>(hint);
72
+ storage_ptr->close_hook_();
73
+ delete storage_ptr;
74
+ }};
75
+ auto* tsfn = napi::invoke(napi_create_threadsafe_function, env, value, nullptr, resource_name, 0, 1, nullptr, finalize, context.get(), callback);
76
+ context.release();
77
+ return tsfn;
78
+ }()} {
79
+ }
80
+
81
+ template <class Context, class Message>
82
+ threadsafe_function_of<Context, Message>::threadsafe_function_of(const threadsafe_function_of& that) :
83
+ tsfn_{that.tsfn_} {
84
+ if (that) {
85
+ napi::invoke0_noexcept(napi_acquire_threadsafe_function, tsfn_);
86
+ }
87
+ }
88
+
89
+ template <class Context, class Message>
90
+ threadsafe_function_of<Context, Message>::threadsafe_function_of(threadsafe_function_of&& that) noexcept :
91
+ tsfn_{std::exchange(that.tsfn_, nullptr)} {}
92
+
93
+ template <class Context, class Message>
94
+ threadsafe_function_of<Context, Message>::~threadsafe_function_of() {
95
+ if (*this) {
96
+ napi::invoke0_noexcept(napi_release_threadsafe_function, tsfn_, napi_tsfn_release);
97
+ }
98
+ }
99
+
100
+ template <class Context, class Message>
101
+ auto threadsafe_function_of<Context, Message>::close(close_callback callback) -> void {
102
+ get().close_hook_ = callback;
103
+ napi::invoke0_noexcept(napi_release_threadsafe_function, std::exchange(tsfn_, nullptr), napi_tsfn_abort);
104
+ }
105
+
106
+ template <class Context, class Message>
107
+ auto threadsafe_function_of<Context, Message>::ref(node_api_basic_env env) const -> void {
108
+ napi::invoke0(napi_ref_threadsafe_function, env, tsfn_);
109
+ }
110
+
111
+ template <class Context, class Message>
112
+ auto threadsafe_function_of<Context, Message>::unref(node_api_basic_env env) const -> void {
113
+ napi::invoke0(napi_unref_threadsafe_function, env, tsfn_);
114
+ }
115
+
116
+ template <class Context, class Message>
117
+ auto threadsafe_function_of<Context, Message>::operator()(Message message) const -> bool {
118
+ auto check = [ & ](napi_status status) {
119
+ switch (status) {
120
+ case napi_ok:
121
+ return true;
122
+ case napi_queue_full:
123
+ return false;
124
+ case napi_closing:
125
+ // nb: This is undocumented, but if you got this return it means the internal ref count was
126
+ // decremented.
127
+ this->tsfn_ = nullptr;
128
+ return false;
129
+ case napi_invalid_arg:
130
+ std::terminate();
131
+ default:
132
+ std::unreachable();
133
+ }
134
+ };
135
+ if constexpr (trivial_message) {
136
+ void* data{};
137
+ std::memcpy(&data, &message, sizeof(Message));
138
+ return check(napi_call_threadsafe_function(tsfn_, data, napi_tsfn_nonblocking));
139
+ } else {
140
+ auto message_ptr = std::make_unique<Message>(std::move(message));
141
+ auto result = check(napi_call_threadsafe_function(tsfn_, message_ptr.get(), napi_tsfn_nonblocking));
142
+ if (result) {
143
+ message_ptr.release();
144
+ }
145
+ return result;
146
+ }
147
+ }
148
+
149
+ template <class Context, class Message>
150
+ auto threadsafe_function_of<Context, Message>::get() const -> storage& {
151
+ auto* context = napi::invoke_noexcept(napi_get_threadsafe_function_context, tsfn_);
152
+ return *reinterpret_cast<storage*>(context);
153
+ }
154
+
155
+ } // namespace js::napi
@@ -8,6 +8,7 @@ namespace js::napi {
8
8
  template <class Tag>
9
9
  class bound_value_next : public bound_value<typename Tag::tag_type> {
10
10
  public:
11
+ using tag_type = Tag;
11
12
  using bound_value<typename Tag::tag_type>::bound_value;
12
13
  bound_value_next() = default;
13
14
  bound_value_next(napi_env env, value_of<Tag> value) :
package/handle/remote.cc CHANGED
@@ -9,7 +9,7 @@ namespace js::napi {
9
9
  template <class Type>
10
10
  concept remote_handle_environment =
11
11
  std::is_base_of_v<environment, Type> &&
12
- std::is_base_of_v<uv_schedulable, Type>;
12
+ std::is_base_of_v<napi_schedulable, Type>;
13
13
 
14
14
  // Thread safe persistent value reference
15
15
  export template <class Tag>
@@ -23,7 +23,7 @@ class remote : protected reference_handle {
23
23
  public:
24
24
  using unique_remote = std::unique_ptr<remote, util::function_constant<expire>>;
25
25
 
26
- remote(private_constructor /*private*/, const environment& env, value_of<Tag> value, uv_scheduler scheduler) :
26
+ remote(private_constructor /*private*/, const environment& env, value_of<Tag> value, napi_scheduler scheduler) :
27
27
  reference_handle{napi_env{env}, napi_value{value}},
28
28
  scheduler_{std::move(scheduler)} {}
29
29
 
@@ -33,7 +33,7 @@ class remote : protected reference_handle {
33
33
  static auto make_unique(remote_handle_environment auto& env, value_of<Tag> value) -> unique_remote;
34
34
 
35
35
  private:
36
- uv_scheduler scheduler_;
36
+ napi_scheduler scheduler_;
37
37
  };
38
38
 
39
39
  // Convenience helpers
@@ -59,8 +59,7 @@ 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
- [](auto self) -> void {
63
- const auto scope = handle_scope{self->env()};
62
+ [](napi_env /*env*/, napi_value /*nothing*/, auto self) -> void {
64
63
  self.reset();
65
64
  },
66
65
  std::move(self)
package/handle/value.cc CHANGED
@@ -26,6 +26,11 @@ class value_next : public value_of<typename Tag::tag_type> {
26
26
  static auto from(napi_value value_) -> value_of<Tag> { return std::bit_cast<value_of<Tag>>(value_); }
27
27
  };
28
28
 
29
+ // Deduction guide for `value_of{bound_value}`
30
+ template <class Type>
31
+ requires requires { typename Type::tag_type; }
32
+ value_of(Type value) -> value_of<typename Type::tag_type>;
33
+
29
34
  // Tagged napi_value
30
35
  export template <class Tag>
31
36
  class value_of : public value_specialization<Tag>::value_type {
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@auto_js/napi",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
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.6",
10
- "@auto_js/napi_exports": "^0.0.6",
11
- "@auto_js/v8_exports": "^0.0.4"
9
+ "@auto_js/js": "^0.0.7",
10
+ "@auto_js/napi_exports": "^0.0.7",
11
+ "@auto_js/v8_exports": "^0.0.5"
12
12
  },
13
13
  "repository": {
14
14
  "type": "git",
@@ -96,7 +96,7 @@ constexpr auto make_constructor_function(auto constructor) {
96
96
  // Tag the result
97
97
  napi::invoke0(napi_type_tag_object, napi_env{env}, info.this_arg(), &type_tag_for<Type>);
98
98
  // Wrap w/ finalizer
99
- return apply_finalizer(std::move(instance), [ & ](Type* instance, napi_finalize finalize, void* hint) -> napi_value {
99
+ return apply_finalizer(std::move(instance), [ & ](Type* instance, node_api_basic_finalize finalize, void* hint) -> napi_value {
100
100
  napi::invoke0(napi_wrap, napi_env{env}, info.this_arg(), instance, finalize, hint, nullptr);
101
101
  return info.this_arg();
102
102
  });
@@ -1,45 +1,26 @@
1
1
  module napi_js;
2
2
  import :api;
3
- import :utility;
3
+ import :support.host;
4
4
  import util;
5
5
 
6
6
  namespace js::napi {
7
7
 
8
- environment::environment(napi_env env, bool uses_direct_handles) :
9
- env_{env},
10
- address_equal_{uses_direct_handles},
11
- uses_direct_handles_{uses_direct_handles} {
12
- scheduler().open(napi::invoke(napi_get_uv_event_loop, env));
13
- // nb: `uv_async_t` is closed with an async hook, and not as the finalizer of
14
- // `napi_set_instance_data`. `uv_close` is async and since nothing is keeping this shared library
15
- // alive, the finalizer code can be unloaded.
16
- auto finalizer = [](napi_async_cleanup_hook_handle handle, void* data) -> void {
17
- auto& env = *static_cast<environment*>(data);
8
+ environment::environment(napi_env env) :
9
+ napi_schedulable{env},
10
+ env_{env} {
11
+ // Initialize napi_js platform hooks
12
+ initialize_host_environment(env);
13
+
14
+ // nb: Closing the schedule needs to be the first thing we do, and deleting it needs to be the
15
+ // last thing we do. Otherwise we get deadlocks or use-after-free problems.
16
+ auto release_scheduler = [](napi_async_cleanup_hook_handle handle, void* data) -> void {
18
17
  auto finalizer = util::fn<[](napi_async_cleanup_hook_handle handle) -> void {
19
18
  napi::invoke0_noexcept(napi_remove_async_cleanup_hook, handle);
20
19
  }>;
20
+ auto& env = *static_cast<environment*>(data);
21
21
  env.scheduler().close(util::function_ref{finalizer, handle});
22
22
  };
23
- napi::invoke0_noexcept(napi_add_async_cleanup_hook, env, finalizer, this, &cleanup_hook_handle_);
23
+ napi::invoke0_noexcept(napi_add_async_cleanup_hook, env, release_scheduler, this, &cleanup_hook_handle_);
24
24
  }
25
25
 
26
- environment::environment(napi_env env) :
27
- environment{
28
- env,
29
- [ & ]() -> bool {
30
- const auto direct_equal = direct_address_equal{};
31
- const auto indirect_equal = indirect_address_equal{};
32
- auto* array = napi::invoke(napi_create_array_with_length, env, 1);
33
- napi::invoke0(napi_set_element, env, array, 0, array);
34
- auto* result = napi::invoke(napi_get_element, env, array, 0);
35
- if (direct_equal(array, result)) {
36
- return true;
37
- } else if (indirect_equal(array, result)) {
38
- return false;
39
- } else {
40
- throw std::runtime_error{"Exotic napi handle behavior detected"};
41
- }
42
- }()
43
- } {}
44
-
45
26
  } // namespace js::napi
@@ -9,17 +9,12 @@ namespace js::napi {
9
9
 
10
10
  // A reference to an environment is used as the lock witness. Generally, you should not have an
11
11
  // `environment&` unless you're in the napi thread and locked.
12
- export class environment : util::non_moveable, public uv_schedulable {
13
- private:
14
- environment(napi_env env, bool uses_direct_handles);
15
-
12
+ export class environment : util::non_moveable, public napi_schedulable {
16
13
  public:
17
14
  explicit environment(napi_env env);
18
15
 
19
16
  // NOLINTNEXTLINE(google-explicit-constructor)
20
17
  [[nodiscard]] operator napi_env() const { return env_; }
21
- [[nodiscard]] auto address_equal() const -> const auto& { return address_equal_; }
22
- [[nodiscard]] auto uses_direct_handles() const -> bool { return uses_direct_handles_; }
23
18
 
24
19
  template <class Type>
25
20
  static auto make_and_set_environment(napi_env env, auto&&... args) -> Type&
@@ -39,8 +34,6 @@ export class environment : util::non_moveable, public uv_schedulable {
39
34
  private:
40
35
  napi_env env_;
41
36
  napi_async_cleanup_hook_handle cleanup_hook_handle_{};
42
- napi::address_equal address_equal_;
43
- bool uses_direct_handles_;
44
37
  };
45
38
 
46
39
  } // namespace js::napi