@auto_js/napi 0.0.7 → 0.0.9

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/handle/types.cc CHANGED
@@ -4,14 +4,13 @@ import nodejs;
4
4
 
5
5
  namespace js::napi {
6
6
 
7
- // `value_handle` is the base class of `value_of<T>`, and `bound_value<T>`.
8
- class value_handle {
7
+ // `runtime_handle` is the base class of `local_of<T>` and `value_of<T>` member types.
8
+ class runtime_handle {
9
9
  protected:
10
- explicit value_handle(napi_value value) :
11
- value_{value} {}
12
-
13
10
  public:
14
- value_handle() = default;
11
+ explicit runtime_handle(int, napi_value value) : value_{value} {}
12
+ explicit runtime_handle(napi_value value) : value_{value} {}
13
+ runtime_handle() = default;
15
14
 
16
15
  // Implicit cast back to a `napi_value`
17
16
  // NOLINTNEXTLINE(google-explicit-constructor)
@@ -24,133 +23,11 @@ class value_handle {
24
23
  napi_value value_{};
25
24
  };
26
25
 
27
- // `value_of` forward declarations
26
+ // Forward declarations for handle types which declare template deduction guides on each other.
28
27
  export template <class Tag = value_tag>
29
- class value_of;
30
-
31
- template <class Tag>
32
- class value_next;
33
-
34
- template <class Type>
35
- class value_for_class_of;
36
-
37
- template <class Type>
38
- class value_for_typed_array_of;
39
-
40
- // `bound_value` forward declarations
41
- template <class Tag>
42
- class bound_value;
43
-
44
- template <class Tag>
45
- class bound_value_next;
46
-
47
- template <class Type>
48
- class bound_value_for_typed_array_of;
49
-
50
- // Map of `value_of<Tag>` / `bound_value<Tag>` to concrete implementation classes.
51
- template <class Tag>
52
- struct value_defaults {
53
- using value_type = value_next<Tag>;
54
- using bound_type = bound_value_next<Tag>;
55
- };
56
-
57
- template <class Tag>
58
- struct value_specialization : value_defaults<Tag> {};
59
-
60
- // Typed specializations
61
- template <>
62
- struct value_specialization<boolean_tag> : value_defaults<boolean_tag> {
63
- using bound_type = class bound_value_for_boolean;
64
- };
65
-
66
- template <>
67
- struct value_specialization<number_tag> : value_defaults<number_tag> {
68
- using bound_type = class bound_value_for_number;
69
- };
70
-
71
- template <>
72
- struct value_specialization<bigint_tag> : value_defaults<bigint_tag> {
73
- using bound_type = class bound_value_for_bigint;
74
- };
75
-
76
- template <>
77
- struct value_specialization<string_tag> : value_defaults<string_tag> {
78
- using bound_type = class bound_value_for_string;
79
- };
80
-
81
- template <>
82
- struct value_specialization<date_tag> : value_defaults<date_tag> {
83
- using bound_type = class bound_value_for_date;
84
- };
85
-
86
- template <>
87
- struct value_specialization<object_tag> {
88
- using value_type = class value_for_object;
89
- using bound_type = class bound_value_for_object;
90
- };
91
-
92
- template <>
93
- struct value_specialization<record_tag> : value_defaults<record_tag> {
94
- using bound_type = class bound_value_for_record;
95
- };
96
-
97
- template <>
98
- struct value_specialization<function_tag> : value_defaults<function_tag> {
99
- using value_type = class value_for_function;
100
- };
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
-
107
- template <>
108
- struct value_specialization<array_buffer_tag> : value_defaults<array_buffer_tag> {
109
- using bound_type = class bound_value_for_array_buffer;
110
- };
111
-
112
- template <>
113
- struct value_specialization<shared_array_buffer_tag> : value_defaults<shared_array_buffer_tag> {
114
- using bound_type = class bound_value_for_shared_array_buffer;
115
- };
116
-
117
- template <>
118
- struct value_specialization<array_buffer_view_tag> : value_defaults<array_buffer_view_tag> {
119
- using bound_type = class bound_value_for_array_buffer_view;
120
- };
121
-
122
- template <>
123
- struct value_specialization<typed_array_tag> {
124
- using value_type = class value_for_typed_array;
125
- using bound_type = class bound_value_for_typed_array;
126
- };
127
-
128
- template <class Type>
129
- struct value_specialization<typed_array_tag_of<Type>> {
130
- using value_type = value_for_typed_array_of<Type>;
131
- using bound_type = bound_value_for_typed_array_of<Type>;
132
- };
133
-
134
- template <>
135
- struct value_specialization<data_view_tag> {
136
- using value_type = class value_for_data_view;
137
- using bound_type = class bound_value_for_data_view;
138
- };
139
-
140
- template <class Type>
141
- struct value_specialization<class_tag_of<Type>> : value_defaults<class_tag_of<Type>> {
142
- using value_type = value_for_class_of<Type>;
143
- };
144
-
145
- template <>
146
- struct value_specialization<external_tag> {
147
- using value_type = class value_for_external;
148
- using bound_type = class bound_value_for_external;
149
- };
28
+ class local_of;
150
29
 
151
- template <>
152
- struct value_specialization<vector_tag> : value_defaults<vector_tag> {
153
- using bound_type = class bound_value_for_vector;
154
- };
30
+ export template <class Tag = value_tag>
31
+ class value_of;
155
32
 
156
33
  } // namespace js::napi
package/handle/value.cc CHANGED
@@ -1,55 +1,147 @@
1
- export module napi_js:value_handle;
1
+ export module napi_js:handle.value_of;
2
2
  import :handle.types;
3
- import auto_js;
4
3
  import nodejs;
5
4
  import std;
6
5
 
7
6
  namespace js::napi {
8
7
 
9
- // Heirarchy:
10
- // value_of<object_tag> ->
8
+ // Map of `value_of<Tag>` to concrete implementation classes.
9
+ template <class Tag>
10
+ struct value_specialization;
11
+
12
+ // Heirarchy (for example):
13
+ // value_of<record_tag>
14
+ // value_for_record ->
15
+ // value_next<record_tag> ->
11
16
  // value_for_object ->
12
17
  // value_next<object_tag> ->
13
- // value_of<value_tag> -> ...
18
+ // value_next<value_tag> ->
19
+ // value_next<datum_tag> ->
20
+ // value_of<void>
14
21
 
15
22
  // Details applied to each level of the `value_of<T>` hierarchy.
16
23
  template <class Tag>
17
24
  class value_next : public value_of<typename Tag::tag_type> {
18
25
  public:
19
- using value_of<typename Tag::tag_type>::value_of;
26
+ using tag_type = Tag;
27
+ value_next() = default;
28
+ value_next(auto&& env, local_of<Tag> value, auto&&... rest) :
29
+ value_of<typename Tag::tag_type>{std::forward<decltype(env)>(env), value, std::forward<decltype(rest)>(rest)...} {}
20
30
 
21
- // "Downcast" to a more specific tag. Potentially unsafe.
22
- template <std::convertible_to<Tag> To>
23
- auto cast(To /*tag*/) const -> value_of<To> { return value_of<To>::from(*this); }
24
-
25
- // Construct from any `napi_value`. Potentially unsafe.
26
- static auto from(napi_value value_) -> value_of<Tag> { return std::bit_cast<value_of<Tag>>(value_); }
31
+ // NOLINTNEXTLINE(google-explicit-constructor)
32
+ operator local_of<Tag>() const { return local_of<Tag>::from(napi_value{*this}); }
27
33
  };
28
34
 
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
-
34
- // Tagged napi_value
35
- export template <class Tag>
36
- class value_of : public value_specialization<Tag>::value_type {
35
+ // Member & method implementation for value semantics objects. It holds the type-erased environment
36
+ // and is used for common operations like casting & iteration.
37
+ template <class Tag>
38
+ class value_of : public value_specialization<Tag>::type {
37
39
  public:
38
- using value_specialization<Tag>::value_type::value_type;
40
+ using value_type = value_specialization<Tag>::type;
41
+ using value_type::value_type;
39
42
  };
40
43
 
41
44
  // Sentinel instantiation
42
45
  template <>
43
- class value_of<void> : public value_handle {
44
- public:
45
- using value_handle::value_handle;
46
+ class value_of<void> : public runtime_handle {
47
+ protected:
48
+ value_of() = default;
49
+ value_of(napi_env env, napi_value value) :
50
+ runtime_handle{value},
51
+ env_{env} {}
52
+
53
+ [[nodiscard]] auto env() const -> napi_env { return env_; }
54
+
55
+ private:
56
+ napi_env env_{};
46
57
  };
47
58
 
48
- } // namespace js::napi
59
+ // Deduction guide
60
+ template <class Tag>
61
+ value_of(auto, local_of<Tag>) -> value_of<Tag>;
62
+
63
+ // `value_of<Tag>` specializations. The default specialization selects `value_next` for the
64
+ // immediate parent tag, instantiating it for each tag unconditionally.
65
+ template <class Type> class value_for_typed_array_of;
49
66
 
50
- // Specialize for `js::forward`. Makes `js::forward{value_of<Tag>}` infer
51
- // `js::forward<Tag, ...>`.
52
- namespace js {
53
67
  template <class Tag>
54
- struct forward_tag_for<napi::value_of<Tag>> : std::type_identity<Tag> {};
55
- } // namespace js
68
+ struct value_specialization
69
+ : std::type_identity<value_next<Tag>> {};
70
+
71
+ template <>
72
+ struct value_specialization<void>
73
+ : std::type_identity<value_of<void>> {};
74
+
75
+ template <>
76
+ struct value_specialization<boolean_tag>
77
+ : std::type_identity<class value_for_boolean> {};
78
+
79
+ template <>
80
+ struct value_specialization<false_tag>
81
+ : std::type_identity<class value_for_false> {};
82
+
83
+ template <>
84
+ struct value_specialization<true_tag>
85
+ : std::type_identity<class value_for_true> {};
86
+
87
+ template <>
88
+ struct value_specialization<number_tag>
89
+ : std::type_identity<class value_for_number> {};
90
+
91
+ template <>
92
+ struct value_specialization<bigint_tag>
93
+ : std::type_identity<class value_for_bigint> {};
94
+
95
+ template <>
96
+ struct value_specialization<string_tag>
97
+ : std::type_identity<class value_for_string> {};
98
+
99
+ template <>
100
+ struct value_specialization<object_tag>
101
+ : std::type_identity<class value_for_object> {};
102
+
103
+ template <>
104
+ struct value_specialization<date_tag>
105
+ : std::type_identity<class value_for_date> {};
106
+
107
+ template <>
108
+ struct value_specialization<record_tag>
109
+ : std::type_identity<class value_for_record> {};
110
+
111
+ template <>
112
+ struct value_specialization<data_block_tag>
113
+ : std::type_identity<class value_for_data_block> {};
114
+
115
+ template <>
116
+ struct value_specialization<array_buffer_tag>
117
+ : std::type_identity<class value_for_array_buffer> {};
118
+
119
+ template <>
120
+ struct value_specialization<shared_array_buffer_tag>
121
+ : std::type_identity<class value_for_shared_array_buffer> {};
122
+
123
+ template <>
124
+ struct value_specialization<array_buffer_view_tag>
125
+ : std::type_identity<class value_for_array_buffer_view> {};
126
+
127
+ template <>
128
+ struct value_specialization<typed_array_tag>
129
+ : std::type_identity<class value_for_typed_array> {};
130
+
131
+ template <class Type>
132
+ struct value_specialization<typed_array_tag_of<Type>>
133
+ : std::type_identity<value_for_typed_array_of<Type>> {};
134
+
135
+ template <>
136
+ struct value_specialization<data_view_tag>
137
+ : std::type_identity<class value_for_data_view> {};
138
+
139
+ template <>
140
+ struct value_specialization<external_tag>
141
+ : std::type_identity<class value_for_external> {};
142
+
143
+ template <>
144
+ struct value_specialization<vector_tag>
145
+ : std::type_identity<class value_for_vector> {};
146
+
147
+ } // namespace js::napi
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@auto_js/napi",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
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.7",
10
- "@auto_js/napi_exports": "^0.0.7",
11
- "@auto_js/v8_exports": "^0.0.5"
9
+ "@auto_js/v8_exports": "^0.0.7",
10
+ "@auto_js/js": "^0.0.9",
11
+ "@auto_js/napi_exports": "^0.0.9"
12
12
  },
13
13
  "repository": {
14
14
  "type": "git",
@@ -13,7 +13,7 @@ template <class Type>
13
13
  constexpr auto unwrap_member_this = [](auto_environment auto& env, napi_value this_arg) noexcept -> std::optional<tagged_external<Type>> {
14
14
  return napi::invoke_maybe(napi_coerce_to_object, napi_env{env}, this_arg)
15
15
  .and_then([ &env ](napi_value coerced_this_arg) -> std::optional<tagged_external<Type>> {
16
- auto as_object = bound_value{env, value_of<object_tag>::from(coerced_this_arg)};
16
+ auto as_object = value_of{env, local_of<object_tag>::from(coerced_this_arg)};
17
17
  // Technically `try_cast` can throw but it should only be in catastrophic cases.
18
18
  Type* unwrapped = as_object.try_cast(type<Type>);
19
19
  if (unwrapped == nullptr) {
@@ -116,7 +116,7 @@ constexpr auto make_constructor_function(auto constructor) {
116
116
  auto instance = std::apply(
117
117
  callback,
118
118
  std::tuple_cat(
119
- std::forward_as_tuple(env, value_of<object_tag>::from(info.this_arg())),
119
+ std::forward_as_tuple(env, local_of<object_tag>::from(info.this_arg())),
120
120
  js::transfer_out<std::tuple<js::functional::parameter_transfer_as_t<Args>...>>(info.arguments(), env)
121
121
  )
122
122
  );
@@ -136,7 +136,7 @@ constexpr auto make_constructor_function(auto constructor) {
136
136
  using callback_type = decltype(callback);
137
137
  return util::bind{
138
138
  [](callback_type& callback, Environment& env, const callback_info& info) noexcept -> napi_value {
139
- return wrap(callback(env, value_of<object_tag>::from(info.this_arg())));
139
+ return wrap(callback(env, local_of<object_tag>::from(info.this_arg())));
140
140
  },
141
141
  std::move(callback),
142
142
  };
@@ -35,12 +35,12 @@ auto make_callback_storage(Environment& env, std::invocable<Environment&, const
35
35
  // Trivial function type containing less than or equal to a pointer size. `data` is the
36
36
  // function and environment is stored in a thread local.
37
37
  callback_env_local<Environment> = &env;
38
- auto* data = reinterpret_cast<void*&>(function);
38
+ auto* data = util::bit_padding_cast<void*>(function);
39
39
  const auto callback = napi_callback{[](napi_env nenv, napi_callback_info info) -> napi_value {
40
40
  const auto args = callback_info{nenv, info};
41
41
  if (args) {
42
42
  auto* data = args.data();
43
- auto& invoke = reinterpret_cast<function_type&>(data);
43
+ auto invoke = util::bit_truncation_cast<function_type>(data);
44
44
  auto& env = *callback_env_local<Environment>;
45
45
  return invoke(env, args);
46
46
  } else {
@@ -20,7 +20,7 @@ export template <const auto& Strings>
20
20
  class class_template_references {
21
21
  public:
22
22
  template <class Type>
23
- auto class_template(this auto& self, std::type_identity<Type> /*type*/, const auto& class_template) -> value_of<class_tag_of<Type>> {
23
+ auto class_template(this auto& self, std::type_identity<Type> /*type*/, const auto& class_template) -> local_of<class_tag_of<Type>> {
24
24
  constexpr auto name_sv = util::make_consteval_string_view(class_template.constructor.name);
25
25
  constexpr auto index = class_template_references_of<Strings>.lookup(name_sv);
26
26
  if constexpr (!index) {
@@ -33,7 +33,7 @@ class class_template_references {
33
33
  static_assert(index, "Class template '"s + name_sv + "' is missing in storage"s);
34
34
  }
35
35
  auto& reference = self.class_template_references_.at(index).second;
36
- using value_type = js::napi::value_of<class_tag_of<Type>>;
36
+ using value_type = js::napi::local_of<class_tag_of<Type>>;
37
37
  if (reference) {
38
38
  return value_type::from(reference.get(self));
39
39
  } else {