@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/transfer/visit.cc CHANGED
@@ -24,7 +24,7 @@ struct visit_property_name {
24
24
  auto operator()(napi_value subject, const Accept& accept) -> accept_target_t<Accept> {
25
25
  return visit_.get().lookup_or_visit(subject, [ & ]() -> accept_target_t<Accept> {
26
26
  auto accept_as = [ & ]<class Tag>(Tag tag) -> auto {
27
- auto value = bound_value{napi_env{visit_.get()}, value_of<Tag>::from(subject)};
27
+ auto value = value_of{napi_env{visit_.get()}, local_of<Tag>::from(subject)};
28
28
  return accept(tag, *this, value);
29
29
  };
30
30
  switch (napi::invoke(napi_typeof, napi_env{visit_.get()}, subject)) {
@@ -50,17 +50,17 @@ struct visit_napi_key_literal {
50
50
 
51
51
  auto operator()(const auto& /*could_be_literally_anything*/, const auto& accept_or_visit) -> napi_value {
52
52
  const auto make = util::overloaded{
53
- [](auto& env, std::string_view subject) -> napi::value_of<string_tag_of<char>> {
53
+ [](auto& env, std::string_view subject) -> napi::local_of<string_tag_of<char>> {
54
54
  auto* value = napi::invoke(node_api_create_property_key_latin1, napi_env{env}, subject.data(), subject.length());
55
- return napi::value_of<string_tag_of<char>>::from(value);
55
+ return napi::local_of<string_tag_of<char>>::from(value);
56
56
  },
57
- [](auto& env, std::u16string_view subject) -> napi::value_of<string_tag_of<char16_t>> {
57
+ [](auto& env, std::u16string_view subject) -> napi::local_of<string_tag_of<char16_t>> {
58
58
  auto* value = napi::invoke(node_api_create_property_key_utf16, napi_env{env}, subject.data(), subject.length());
59
- return napi::value_of<string_tag_of<char16_t>>::from(value);
59
+ return napi::local_of<string_tag_of<char16_t>>::from(value);
60
60
  },
61
- [](auto& env, std::u8string_view subject) -> napi::value_of<string_tag_of<char8_t>> {
61
+ [](auto& env, std::u8string_view subject) -> napi::local_of<string_tag_of<char8_t>> {
62
62
  auto* value = napi::invoke(node_api_create_property_key_utf8, napi_env{env}, reinterpret_cast<const char*>(subject.data()), subject.length());
63
- return napi::value_of<string_tag_of<char8_t>>::from(value);
63
+ return napi::local_of<string_tag_of<char8_t>>::from(value);
64
64
  },
65
65
  };
66
66
  if (local_key_ == napi_value{}) {
@@ -109,7 +109,7 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
109
109
  // If the private `immediate` operation is defined: this public operation will first
110
110
  // perform a reference map lookup, then delegate to the private operation if not found.
111
111
  template <class Tag, class Accept>
112
- auto operator()(value_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept>
112
+ auto operator()(local_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept>
113
113
  requires requires { immediate(subject, accept); } {
114
114
  return lookup_or_visit(subject, [ & ]() -> accept_target_t<Accept> {
115
115
  return immediate(subject, accept);
@@ -118,31 +118,31 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
118
118
 
119
119
  // Visit operations for non-refable types.
120
120
  template <class Accept>
121
- auto operator()(value_of<null_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
121
+ auto operator()(local_of<null_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
122
122
  return immediate(subject, accept);
123
123
  }
124
124
 
125
125
  template <class Accept>
126
- auto operator()(value_of<undefined_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
126
+ auto operator()(local_of<undefined_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
127
127
  return immediate(subject, accept);
128
128
  }
129
129
 
130
130
  template <class Accept>
131
- auto operator()(value_of<boolean_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
131
+ auto operator()(local_of<boolean_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
132
132
  return immediate(subject, accept);
133
133
  }
134
134
 
135
135
  template <class Accept>
136
- auto operator()(value_of<number_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
137
- if (maybe_fast_is_number_int32(subject).value_or(false)) {
138
- return immediate(value_of<number_tag_of<std::int32_t>>::from(subject), accept);
136
+ auto operator()(local_of<number_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
137
+ if (maybe_is_number_int32(subject).value_or(false)) {
138
+ return immediate(local_of<number_tag_of<std::int32_t>>::from(subject), accept);
139
139
  } else {
140
- return immediate(value_of<number_tag_of<double>>::from(subject), accept);
140
+ return immediate(local_of<number_tag_of<double>>::from(subject), accept);
141
141
  }
142
142
  }
143
143
 
144
144
  template <class Accept, class Type>
145
- auto operator()(value_of<number_tag_of<Type>> subject, const Accept& accept) -> accept_target_t<Accept> {
145
+ auto operator()(local_of<number_tag_of<Type>> subject, const Accept& accept) -> accept_target_t<Accept> {
146
146
  return immediate(subject, accept);
147
147
  }
148
148
 
@@ -153,91 +153,100 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
153
153
  // Check the reference map, and lookup type via napi
154
154
  return lookup_or_visit(subject, [ & ]() -> accept_target_t<Accept> {
155
155
  // This is the pure-napi implementation
156
- auto slow_path = [ & ]() -> accept_target_t<Accept> {
157
- auto type_of = napi::invoke(napi_typeof, napi_env{*this}, subject);
158
- switch (type_of) {
159
- case napi_undefined:
160
- return (*this)(value_of<undefined_tag>::from(subject), accept);
161
- case napi_null:
162
- return (*this)(value_of<null_tag>::from(subject), accept);
163
- case napi_boolean:
164
- return (*this)(value_of<boolean_tag>::from(subject), accept);
165
- case napi_number:
166
- return (*this)(value_of<number_tag>::from(subject), accept);
167
- case napi_string:
168
- return immediate(value_of<string_tag>::from(subject), accept);
169
- case napi_symbol:
170
- return immediate(value_of<symbol_tag>::from(subject), accept);
171
- case napi_object:
172
- return immediate(value_of<object_tag>::from(subject), accept);
173
- case napi_function:
174
- return immediate(value_of<function_tag>::from(subject), accept);
175
- case napi_external:
176
- return immediate(value_of<external_tag>::from(subject), accept);
177
- case napi_bigint:
178
- return immediate(value_of<bigint_tag>::from(subject), accept);
179
- }
180
- std::unreachable();
156
+ auto slow_path = util::overloaded{
157
+ [ & ]() -> accept_target_t<Accept> {
158
+ auto type_of = napi::invoke(napi_typeof, napi_env{*this}, subject);
159
+ switch (type_of) {
160
+ case napi_undefined:
161
+ return (*this)(local_of<undefined_tag>::from(subject), accept);
162
+ case napi_null:
163
+ return (*this)(local_of<null_tag>::from(subject), accept);
164
+ case napi_boolean:
165
+ return (*this)(local_of<boolean_tag>::from(subject), accept);
166
+ case napi_number:
167
+ return (*this)(local_of<number_tag>::from(subject), accept);
168
+ case napi_string:
169
+ return immediate(local_of<string_tag>::from(subject), accept);
170
+ case napi_symbol:
171
+ return immediate(local_of<symbol_tag>::from(subject), accept);
172
+ case napi_object:
173
+ return immediate(local_of<object_tag>::from(subject), accept);
174
+ case napi_function:
175
+ return immediate(local_of<function_tag>::from(subject), accept);
176
+ case napi_external:
177
+ return immediate(local_of<external_tag>::from(subject), accept);
178
+ case napi_bigint:
179
+ return immediate(local_of<bigint_tag>::from(subject), accept);
180
+ }
181
+ std::unreachable();
182
+ },
183
+
184
+ [](auto /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
181
185
  };
182
186
 
183
- if (has_fast_is_functions) {
184
- return util::template_traverse(
185
- accept_tags_of_v<Accept>,
186
- util::overloaded{
187
- // Fast paths
188
- [ & ](undefined_tag /*tag*/, auto next) -> accept_target_t<Accept> {
189
- return fast_is_undefined(subject) ? (*this)(value_of<undefined_tag>::from(subject), accept) : next();
190
- },
191
- [ & ](null_tag /*tag*/, auto next) -> accept_target_t<Accept> {
192
- return fast_is_null(subject) ? (*this)(value_of<null_tag>::from(subject), accept) : next();
193
- },
194
- [ & ](boolean_tag /*tag*/, auto next) -> accept_target_t<Accept> {
195
- return fast_is_boolean(subject) ? (*this)(value_of<boolean_tag>::from(subject), accept) : next();
196
- },
197
- [ & ](number_tag /*tag*/, auto next) -> accept_target_t<Accept> {
198
- return fast_is_number(subject) ? (*this)(value_of<number_tag>::from(subject), accept) : next();
199
- },
200
- [ & ](string_tag /*tag*/, auto next) -> accept_target_t<Accept> {
201
- return fast_is_string(subject) ? immediate(value_of<string_tag>::from(subject), accept) : next();
202
- },
203
- [ & ](bigint_tag /*tag*/, auto next) -> accept_target_t<Accept> {
204
- return fast_is_bigint(subject) ? immediate(value_of<bigint_tag>::from(subject), accept) : next();
205
- },
206
- [ & ](date_tag /*tag*/, auto next) -> accept_target_t<Accept> {
207
- return napi::invoke(napi_is_date, napi_env{*this}, subject) ? immediate(value_of<date_tag>::from(subject), accept) : next();
208
- },
209
- [ & ](list_tag /*tag*/, auto next) -> accept_target_t<Accept> {
210
- return fast_is_array(subject) ? immediate(value_of<list_tag>::from(subject), accept) : next();
211
- },
212
- [ & ](object_tag /*tag*/, auto next) -> accept_target_t<Accept> {
213
- // nb: You can't really skip the subsequent is promise, is date, is arraybuffer, etc
214
- // checks. We don't really want to accept those types here, I don't think..
215
- return fast_is_object(subject) ? immediate(value_of<object_tag>::from(subject), accept) : next();
216
- },
217
- [ & ](function_tag /*tag*/, auto next) -> accept_target_t<Accept> {
218
- return fast_is_function(subject) ? immediate(value_of<function_tag>::from(subject), accept) : next();
219
- },
220
-
221
- // Skip these, otherwise `number_tag` and `string_tag` are invoked twice, which we don't
222
- // differentiate between.
223
- []<class Type>(number_tag_of<Type> /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
224
- []<class Type>(string_tag_of<Type> /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
225
-
226
- // Unknown tag
227
- [](auto /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
228
-
229
- // Slow path
230
- slow_path,
187
+ // Universal fast checks
188
+ auto fast_path = util::overloaded{
189
+ [ & ](undefined_tag /*tag*/, auto next) -> accept_target_t<Accept> {
190
+ return fast_is_undefined(napi_env{*this}, subject) ? (*this)(local_of<undefined_tag>::from(subject), accept) : next();
191
+ },
192
+ [ & ](null_tag /*tag*/, auto next) -> accept_target_t<Accept> {
193
+ return fast_is_null(napi_env{*this}, subject) ? (*this)(local_of<null_tag>::from(subject), accept) : next();
194
+ },
195
+ [ & ](boolean_tag /*tag*/, auto next) -> accept_target_t<Accept> {
196
+ if (fast_is_false(napi_env{*this}, subject)) {
197
+ return (*this)(local_of<false_tag>::from(subject), accept);
198
+ } else if (fast_is_true(napi_env{*this}, subject)) {
199
+ return (*this)(local_of<true_tag>::from(subject), accept);
200
+ } else {
201
+ return next();
231
202
  }
232
- );
203
+ },
204
+ };
205
+
206
+ // Extended fast checks
207
+ auto extended_fast_path = util::overloaded{
208
+ [ & ](number_tag /*tag*/, auto next) -> accept_target_t<Accept> {
209
+ return fast_is_number(subject) ? (*this)(local_of<number_tag>::from(subject), accept) : next();
210
+ },
211
+ [ & ](string_tag /*tag*/, auto next) -> accept_target_t<Accept> {
212
+ return fast_is_string(subject) ? immediate(local_of<string_tag>::from(subject), accept) : next();
213
+ },
214
+ [ & ](bigint_tag /*tag*/, auto next) -> accept_target_t<Accept> {
215
+ return fast_is_bigint(subject) ? immediate(local_of<bigint_tag>::from(subject), accept) : next();
216
+ },
217
+ [ & ](date_tag /*tag*/, auto next) -> accept_target_t<Accept> {
218
+ return napi::invoke(napi_is_date, napi_env{*this}, subject) ? immediate(local_of<date_tag>::from(subject), accept) : next();
219
+ },
220
+ [ & ](list_tag /*tag*/, auto next) -> accept_target_t<Accept> {
221
+ return fast_is_array(subject) ? immediate(local_of<list_tag>::from(subject), accept) : next();
222
+ },
223
+ [ & ](object_tag /*tag*/, auto next) -> accept_target_t<Accept> {
224
+ // nb: You can't really skip the subsequent is promise, is date, is arraybuffer, etc
225
+ // checks. We don't really want to accept those types here, I don't think..
226
+ return fast_is_object(subject) ? immediate(local_of<object_tag>::from(subject), accept) : next();
227
+ },
228
+ [ & ](function_tag /*tag*/, auto next) -> accept_target_t<Accept> {
229
+ return fast_is_function(subject) ? immediate(local_of<function_tag>::from(subject), accept) : next();
230
+ },
231
+
232
+ // Skip these, otherwise `number_tag` and `string_tag` are invoked twice, which we don't
233
+ // differentiate between.
234
+ []<class Type>(number_tag_of<Type> /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
235
+ []<class Type>(string_tag_of<Type> /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
236
+ };
237
+
238
+ if (has_extended_fast_is_functions) {
239
+ auto traverse = util::overloaded{fast_path, extended_fast_path, slow_path};
240
+ return util::template_traverse(accept_tags_of_v<Accept>, traverse);
233
241
  } else {
234
- return slow_path();
242
+ auto traverse = util::overloaded{fast_path, slow_path};
243
+ return util::template_traverse(accept_tags_of_v<Accept>, traverse);
235
244
  }
236
245
  });
237
246
  }
238
247
 
239
248
  template <class Accept>
240
- auto operator()(value_of<data_block_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
249
+ auto operator()(local_of<data_block_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
241
250
  return lookup_or_visit(subject, [ & ]() -> accept_target_t<Accept> {
242
251
  return util::template_traverse(
243
252
  accept_tags_of_v<Accept>,
@@ -265,79 +274,79 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
265
274
  // I think this only applies to `symbol_tag`
266
275
  template <class Accept, class Tag>
267
276
  requires std::is_convertible_v<Tag, primitive_tag>
268
- auto immediate(value_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept> {
277
+ auto immediate(local_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept> {
269
278
  return accept_tagged(subject, accept);
270
279
  }
271
280
 
272
281
  // strings
273
282
  template <class Accept>
274
- auto immediate(value_of<string_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
275
- if (maybe_fast_is_string_one_byte(subject).value_or(false)) {
276
- return accept_tagged(value_of<string_tag_of<char>>::from(subject), accept);
283
+ auto immediate(local_of<string_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
284
+ if (maybe_is_string_latin1(subject).value_or(false)) {
285
+ return accept_tagged(local_of<string_tag_of<char>>::from(subject), accept);
277
286
  } else {
278
- return accept_tagged(value_of<string_tag_of<char16_t>>::from(subject), accept);
287
+ return accept_tagged(local_of<string_tag_of<char16_t>>::from(subject), accept);
279
288
  }
280
289
  }
281
290
 
282
291
  // bigint
283
292
  template <class Accept>
284
- auto immediate(value_of<bigint_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
285
- return accept_tagged(value_of<bigint_tag_of<bigint>>::from(subject), accept);
293
+ auto immediate(local_of<bigint_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
294
+ return accept_tagged(local_of<bigint_tag_of<bigint>>::from(subject), accept);
286
295
  }
287
296
 
288
297
  // date
289
298
  template <class Accept>
290
- auto immediate(value_of<object_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
299
+ auto immediate(local_of<object_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
291
300
  if (napi::invoke(napi_is_array, napi_env{*this}, subject)) {
292
- return immediate(value_of<list_tag>::from(subject), accept);
301
+ return immediate(local_of<list_tag>::from(subject), accept);
293
302
  } else if (napi::invoke(napi_is_date, napi_env{*this}, subject)) {
294
- return immediate(value_of<date_tag>::from(subject), accept);
303
+ return immediate(local_of<date_tag>::from(subject), accept);
295
304
  } else if (napi::invoke(napi_is_typedarray, napi_env{*this}, subject)) {
296
- return immediate(value_of<typed_array_tag>::from(subject), accept);
305
+ return immediate(local_of<typed_array_tag>::from(subject), accept);
297
306
  } else if (napi::invoke(napi_is_dataview, napi_env{*this}, subject)) {
298
- return immediate(value_of<data_view_tag>::from(subject), accept);
307
+ return immediate(local_of<data_view_tag>::from(subject), accept);
299
308
  } else if (maybe_is_shared_array_buffer(env_.get(), subject).value_or(false)) {
300
- return immediate(value_of<shared_array_buffer_tag>::from(subject), accept);
301
- } else if (napi::invoke(napi_is_arraybuffer, napi_env{*this}, subject)) {
302
- return immediate(value_of<array_buffer_tag>::from(subject), accept);
309
+ return immediate(local_of<shared_array_buffer_tag>::from(subject), accept);
310
+ } else if (is_object_array_buffer(env_.get(), subject)) {
311
+ return immediate(local_of<array_buffer_tag>::from(subject), accept);
303
312
  } else if (napi::invoke(napi_is_promise, napi_env{*this}, subject)) {
304
- return immediate(value_of<promise_tag>::from(subject), accept);
313
+ return immediate(local_of<promise_tag>::from(subject), accept);
305
314
  } else {
306
- return immediate(value_of<dictionary_tag>::from(subject), accept);
315
+ return immediate(local_of<dictionary_tag>::from(subject), accept);
307
316
  }
308
317
  }
309
318
 
310
319
  // date
311
320
  template <class Accept>
312
- auto immediate(value_of<date_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
321
+ auto immediate(local_of<date_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
313
322
  return accept_tagged(subject, accept);
314
323
  }
315
324
 
316
325
  // data blocks
317
326
  template <class Accept>
318
- auto immediate(value_of<data_block_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
319
- if (napi::invoke(napi_is_arraybuffer, napi_env{*this}, subject)) {
320
- return immediate(value_of<array_buffer_tag>::from(subject), accept);
327
+ auto immediate(local_of<data_block_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
328
+ if (is_data_block_array_buffer(env_.get(), subject)) {
329
+ return immediate(local_of<array_buffer_tag>::from(subject), accept);
321
330
  } else {
322
- return immediate(value_of<shared_array_buffer_tag>::from(subject), accept);
331
+ return immediate(local_of<shared_array_buffer_tag>::from(subject), accept);
323
332
  }
324
333
  }
325
334
 
326
335
  template <class Accept, class Tag>
327
336
  requires std::is_convertible_v<Tag, data_block_tag>
328
- auto immediate(value_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept> {
337
+ auto immediate(local_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept> {
329
338
  return accept_tagged(subject, accept);
330
339
  }
331
340
 
332
341
  // array buffer views
333
342
  template <class Accept>
334
- auto immediate(value_of<typed_array_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
335
- auto bound_subject_variant = bound_value_for_typed_array::make_bound(environment(), subject);
343
+ auto immediate(local_of<typed_array_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
344
+ auto bound_subject_variant = value_for_typed_array::make_bound(environment(), subject);
336
345
  if (bound_subject_variant.index() == std::variant_npos) {
337
346
  std::unreachable();
338
347
  } else {
339
348
  return std::visit(
340
- [ & ]<class Tag>(bound_value<Tag> value) -> accept_target_t<Accept> {
349
+ [ & ]<class Tag>(value_of<Tag> value) -> accept_target_t<Accept> {
341
350
  return accept(Tag{}, *this, value);
342
351
  },
343
352
  bound_subject_variant
@@ -346,53 +355,87 @@ struct visit_value : reference_map_t<Reference, reference_map_type> {
346
355
  }
347
356
 
348
357
  template <class Accept>
349
- auto immediate(value_of<data_view_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
358
+ auto immediate(local_of<data_view_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
350
359
  return accept_tagged(subject, accept);
351
360
  }
352
361
 
353
362
  // externals
354
363
  template <class Accept>
355
- auto immediate(value_of<external_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
364
+ auto immediate(local_of<external_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
356
365
  return accept_tagged(subject, accept);
357
366
  }
358
367
 
359
368
  // promise
360
369
  template <class Accept>
361
- auto immediate(value_of<promise_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
370
+ auto immediate(local_of<promise_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
362
371
  return accept_tagged(subject, accept);
363
372
  }
364
373
 
365
374
  // function
366
375
  template <class Accept>
367
- auto immediate(value_of<function_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
376
+ auto immediate(local_of<function_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
368
377
  return accept_tagged(subject, accept);
369
378
  }
370
379
 
371
380
  // array
372
381
  template <class Accept>
373
- auto immediate(value_of<list_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
374
- auto target = napi::bound_value{napi_env{*this}, value_of<list_tag>::from(subject)};
382
+ auto immediate(local_of<list_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
383
+ auto target = napi::value_of{napi_env{*this}, local_of<list_tag>::from(subject)};
375
384
  auto visit_entry = visit_entry_pair<visit_property_name<visit_value>, visit_value&>{*this};
376
385
  return accept(list_tag{}, visit_entry, target);
377
386
  }
378
387
 
379
388
  // object / record
380
389
  template <class Accept>
381
- auto immediate(value_of<dictionary_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
382
- auto target = napi::bound_value{napi_env{*this}, value_of<dictionary_tag>::from(subject)};
390
+ auto immediate(local_of<dictionary_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
391
+ auto target = napi::value_of{napi_env{*this}, local_of<dictionary_tag>::from(subject)};
383
392
  auto visit_entry = visit_entry_pair<visit_property_name<visit_value>, visit_value&>{*this};
384
393
  return accept(dictionary_tag{}, visit_entry, target);
385
394
  }
386
395
 
387
- // Convenience function which wraps in `napi::bound_value` and invokes `accept`.
396
+ // Convenience function which wraps in `napi::value_of` and invokes `accept`.
388
397
  template <class Tag, class Accept>
389
- [[nodiscard]] auto accept_tagged(value_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept> {
390
- return accept(Tag{}, *this, napi::bound_value{environment(), subject});
398
+ [[nodiscard]] auto accept_tagged(local_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept> {
399
+ return accept(Tag{}, *this, napi::value_of{environment(), subject});
391
400
  }
392
401
 
393
402
  std::reference_wrapper<Environment> env_;
394
403
  };
395
404
 
405
+ // Forward `value_of<T>` back to acceptor
406
+ template <class Meta, class Tag>
407
+ struct visit_napi_value_of {
408
+ private:
409
+ using visit_type = visit_value_with<Meta>;
410
+
411
+ public:
412
+ constexpr explicit visit_napi_value_of(auto* transfer, auto& environment) : visit_{transfer, environment} {}
413
+
414
+ template <class Accept>
415
+ constexpr auto operator()(value_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept> {
416
+ return accept(Tag{}, visit_, subject);
417
+ }
418
+
419
+ template <class Accept>
420
+ requires std::is_same_v<Tag, object_tag>
421
+ constexpr auto operator()(value_of<object_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
422
+ auto visit_entry = visit_entry_pair<visit_property_name<visit_type>, visit_type&>{visit_};
423
+ return accept(object_tag{}, visit_entry, subject);
424
+ }
425
+
426
+ template <class Accept>
427
+ requires std::is_same_v<Tag, list_tag>
428
+ constexpr auto operator()(value_of<list_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
429
+ auto visit_entry = visit_entry_pair<visit_property_name<visit_type>, visit_type&>{visit_};
430
+ return accept(list_tag{}, visit_entry, subject);
431
+ }
432
+
433
+ consteval static auto types(auto /*recursive*/) { return util::type_pack{}; }
434
+
435
+ private:
436
+ visit_type visit_;
437
+ };
438
+
396
439
  } // namespace js::napi
397
440
 
398
441
  namespace js {
@@ -404,10 +447,19 @@ struct visit<Meta, napi_value> : napi::visit_value_with<Meta> {
404
447
  };
405
448
 
406
449
  template <class Meta, class Tag>
407
- struct visit<Meta, napi::value_of<Tag>> : napi::visit_value_with<Meta> {
450
+ struct visit<Meta, napi::local_of<Tag>> : napi::visit_value_with<Meta> {
408
451
  using napi::visit_value_with<Meta>::visit_value_with;
409
452
  };
410
453
 
454
+ // Pass through `value_of<Tag>`
455
+ template <class Meta, class Tag>
456
+ struct visit<Meta, napi::value_of<Tag>> : napi::visit_napi_value_of<Meta, Tag> {
457
+ using napi::visit_napi_value_of<Meta, Tag>::visit_napi_value_of;
458
+ };
459
+
460
+ template <class Tag>
461
+ struct visit_subject_for<napi::value_of<Tag>> : std::type_identity<napi_value> {};
462
+
411
463
  // Object key maker via napi
412
464
  template <auto Key>
413
465
  struct visit_key_literal<Key, napi_value> : napi::visit_napi_key_literal<Key> {
package/value/array.cc CHANGED
@@ -1,29 +1,27 @@
1
1
  module napi_js;
2
- import :api;
3
- import :bound_value;
4
2
 
5
3
  namespace js::napi {
6
4
 
7
- auto bound_value_for_vector::begin() const -> iterator {
5
+ auto value_for_vector::begin() const -> iterator {
8
6
  return {*this, 0};
9
7
  }
10
8
 
11
- auto bound_value_for_vector::end() const -> iterator {
9
+ auto value_for_vector::end() const -> iterator {
12
10
  return {*this, size()};
13
11
  }
14
12
 
15
- auto bound_value_for_vector::size() const -> std::uint32_t {
13
+ auto value_for_vector::size() const -> std::uint32_t {
16
14
  if (size_ == 0) {
17
15
  size_ = napi::invoke(napi_get_array_length, env(), napi_value{*this}) + 1;
18
16
  }
19
17
  return size_ - 1;
20
18
  }
21
19
 
22
- bound_value_for_vector::iterator::iterator(bound_value_for_vector subject, size_type index) :
20
+ value_for_vector::iterator::iterator(value_for_vector subject, size_type index) :
23
21
  subject_{subject},
24
22
  index_{index} {}
25
23
 
26
- auto bound_value_for_vector::iterator::operator*() const -> value_type {
24
+ auto value_for_vector::iterator::operator*() const -> value_type {
27
25
  return value_type::from(napi::invoke(napi_get_element, subject_.env(), napi_value{subject_}, index_));
28
26
  }
29
27
 
package/value/array.h.cc CHANGED
@@ -5,11 +5,11 @@ import util;
5
5
 
6
6
  namespace js::napi {
7
7
 
8
- class bound_value_for_vector : public bound_value_next<vector_tag> {
8
+ class value_for_vector : public value_next<vector_tag> {
9
9
  public:
10
10
  class iterator;
11
- using bound_value_next<vector_tag>::bound_value_next;
12
- using value_type = value_of<value_tag>;
11
+ using value_next<vector_tag>::value_next;
12
+ using value_type = local_of<value_tag>;
13
13
 
14
14
  [[nodiscard]] auto begin() const -> iterator;
15
15
  [[nodiscard]] auto end() const -> iterator;
@@ -19,15 +19,15 @@ class bound_value_for_vector : public bound_value_next<vector_tag> {
19
19
  mutable std::uint32_t size_{};
20
20
  };
21
21
 
22
- class bound_value_for_vector::iterator : public util::random_access_iterator_facade<std::int32_t, std::int64_t> {
22
+ class value_for_vector::iterator : public util::random_access_iterator_facade<std::int32_t, std::int64_t> {
23
23
  public:
24
24
  using arithmetic_facade::operator+;
25
25
  using difference_type = arithmetic_facade::difference_type;
26
26
  using size_type = std::uint32_t;
27
- using value_type = bound_value_for_vector::value_type;
27
+ using value_type = value_for_vector::value_type;
28
28
 
29
29
  iterator() = default;
30
- iterator(bound_value_for_vector subject, size_type index);
30
+ iterator(value_for_vector subject, size_type index);
31
31
 
32
32
  auto operator*() const -> value_type;
33
33
 
@@ -42,7 +42,7 @@ class bound_value_for_vector::iterator : public util::random_access_iterator_fac
42
42
  private:
43
43
  auto operator+() const -> size_type { return index_; }
44
44
 
45
- bound_value_for_vector subject_;
45
+ value_for_vector subject_;
46
46
  size_type index_{};
47
47
  };
48
48