@auto_js/v8 0.0.2 → 0.0.4

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/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@auto_js/v8",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "author": "https://github.com/laverdet/",
5
5
  "homepage": "https://github.com/laverdet/isolated-vm/tree/experimental/packages/auto_js/v8",
6
6
  "license": "ISC",
7
7
  "dependencies": {
8
- "@auto_js/js": "^0.0.2",
8
+ "@auto_js/js": "^0.0.4",
9
9
  "@auto_js/v8_exports": "^0.0.2"
10
10
  },
11
11
  "repository": {
@@ -105,6 +105,7 @@ struct accept_v8_primitive {
105
105
  struct accept_v8_value : accept_v8_primitive {
106
106
  public:
107
107
  using accept_type = accept_v8_primitive;
108
+ using accept_target_type = v8::Local<v8::Value>;
108
109
  explicit accept_v8_value(auto* transfer, context_lock_witness lock) :
109
110
  accept_type{transfer, lock},
110
111
  context_{lock.context()} {}
@@ -177,6 +178,40 @@ struct accept_v8_value : accept_v8_primitive {
177
178
  };
178
179
  }
179
180
 
181
+ // vectors
182
+ auto operator()(this const auto& self, vector_tag /*tag*/, auto& visit, auto&& subject)
183
+ -> js::deferred_receiver<v8::Local<v8::Array>, decltype(self), decltype(visit), decltype(subject)> {
184
+ auto [... size ] = util::maybe_range_size(subject);
185
+ return {
186
+ v8::Array::New(self.isolate(), size...),
187
+ std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
188
+ [](v8::Local<v8::Array> array, auto& self, auto& visit, auto /*&&*/ subject) -> void {
189
+ std::uint32_t ii = 0;
190
+ auto&& range = util::into_range(std::forward<decltype(subject)>(subject));
191
+ for (auto&& subject : util::forward_range(std::forward<decltype(range)>(range))) {
192
+ auto element = visit(std::forward<decltype(subject)>(subject), self);
193
+ unmaybe(array->Set(self.context_, ii++, element));
194
+ }
195
+ },
196
+ };
197
+ }
198
+
199
+ template <std::size_t Size>
200
+ auto operator()(this const auto& self, tuple_tag<Size> /*tag*/, auto& visit, auto&& subject)
201
+ -> js::deferred_receiver<v8::Local<v8::Array>, decltype(self), decltype(visit), decltype(subject)> {
202
+ return {
203
+ v8::Array::New(self.isolate(), Size),
204
+ std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
205
+ [](v8::Local<v8::Array> array, auto& self, auto& visit, auto /*&&*/ tuple) -> void {
206
+ const auto [... indices ] = util::sequence<Size>;
207
+ (..., [ & ]() -> void {
208
+ auto element = visit(indices, std::forward<decltype(tuple)>(tuple), self);
209
+ unmaybe(array->Set(self.context_, indices, element));
210
+ }());
211
+ }
212
+ };
213
+ }
214
+
180
215
  // object
181
216
  auto operator()(this const auto& self, dictionary_tag /*tag*/, auto& visit, auto&& subject)
182
217
  -> js::deferred_receiver<v8::Local<v8::Object>, decltype(self), decltype(visit), decltype(subject)> {
@@ -236,7 +271,7 @@ struct accept_v8_value : accept_v8_primitive {
236
271
  auto operator()(this const auto& self, struct_tag<Size> /*tag*/, auto& visit, auto&& subject)
237
272
  -> js::deferred_receiver<v8::Local<v8::Object>, decltype(self), decltype(visit), decltype(subject)> {
238
273
  return {
239
- v8::Local<v8::Object>::New(self.isolate()),
274
+ v8::Object::New(self.isolate()),
240
275
  std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
241
276
  [](v8::Local<v8::Object> object, auto& self, auto& visit, auto /*&&*/ subject) -> void {
242
277
  self.template accept_entry_pair_struct<Size>(visit, object, std::forward<decltype(subject)>(subject));
@@ -315,6 +350,27 @@ struct accept_v8_template : accept_v8_primitive {
315
350
  std::reference_wrapper<const Lock> lock_;
316
351
  };
317
352
 
353
+ // object key lookup (struct_template, etc)
354
+ template <class Meta, auto Key, class Type>
355
+ struct accept_v8_property_value {
356
+ public:
357
+ explicit constexpr accept_v8_property_value(auto* transfer) :
358
+ first{transfer},
359
+ second{transfer} {}
360
+
361
+ auto operator()(dictionary_tag /*tag*/, auto& visit, const auto& subject) const -> Type {
362
+ if (auto local = first(std::type_identity<void>{}, visit.first); subject.has(local)) {
363
+ return visit.second(subject.get(local), second);
364
+ } else {
365
+ return second(undefined_in_tag{}, visit.second, std::monostate{});
366
+ }
367
+ }
368
+
369
+ private:
370
+ mutable visit_key_literal<Key, v8::Local<v8::Object>> first;
371
+ accept_value<Meta, Type> second;
372
+ };
373
+
318
374
  // `return_into(...)`
319
375
  struct return_into_marker {};
320
376
 
@@ -360,8 +416,9 @@ struct accept_v8_return_into : accept_v8_value_with<Lock> {
360
416
  }
361
417
 
362
418
  auto operator()(auto tag, auto& visit, auto&& subject) const -> return_into_marker
363
- requires std::invocable<const accept_type&, decltype(visit), decltype(tag), decltype(subject)> {
364
- return_value_.Set(util::invoke_as<accept_type>(*this, tag, visit, std::forward<decltype(subject)>(subject)));
419
+ requires std::invocable<const accept_type&, decltype(tag), decltype(visit), decltype(subject)> {
420
+ auto value = util::invoke_as<accept_type>(*this, tag, visit, std::forward<decltype(subject)>(subject));
421
+ return_value_.Set(js::dispatch_referenceable(std::move(value)));
365
422
  return {};
366
423
  }
367
424
 
@@ -403,6 +460,9 @@ struct accept_v8_object_assign {
403
460
 
404
461
  namespace js {
405
462
 
463
+ template <class Type>
464
+ struct accept_property_subject<v8::Local<Type>> : std::type_identity<v8::Local<v8::Object>> {};
465
+
406
466
  // primitives
407
467
  template <class Meta, class Type>
408
468
  requires std::is_base_of_v<v8::Primitive, Type>
@@ -441,7 +501,16 @@ struct accept<Meta, v8::MaybeLocal<Type>> : accept<Meta, v8::Local<Type>> {
441
501
  }
442
502
  };
443
503
 
504
+ // object key lookup (struct_template, etc)
505
+ template <class Meta, auto Key, class Type>
506
+ struct accept_property_value<Meta, Key, Type, v8::Local<v8::Object>> : iv8::accept_v8_property_value<Meta, Key, Type> {
507
+ using iv8::accept_v8_property_value<Meta, Key, Type>::accept_v8_property_value;
508
+ };
509
+
444
510
  // return_into
511
+ template <>
512
+ struct accept_property_subject<iv8::return_into_marker> : accept_property_subject<v8::Local<v8::Value>> {};
513
+
445
514
  template <class Meta>
446
515
  struct accept<Meta, iv8::return_into_marker> : iv8::accept_v8_return_into<typename Meta::accept_context_type> {
447
516
  using iv8::accept_v8_return_into<typename Meta::accept_context_type>::accept_v8_return_into;
package/transfer/visit.cc CHANGED
@@ -51,6 +51,35 @@ struct visit_property_name {
51
51
  std::reference_wrapper<Visit> visit_;
52
52
  };
53
53
 
54
+ // `visit_key_literal` instantiation for v8
55
+ template <auto Key>
56
+ struct visit_v8_key_literal {
57
+ explicit constexpr visit_v8_key_literal(auto* /*transfer*/) {}
58
+
59
+ auto operator()(const auto& /*anything*/, const auto& accept_or_visit) -> v8::Local<v8::Name> {
60
+ const auto make = util::overloaded{
61
+ [](v8::Isolate* isolate, std::string_view subject) -> v8::Local<v8::String> {
62
+ const auto* data = reinterpret_cast<const std::uint8_t*>(subject.data());
63
+ auto size = static_cast<int>(subject.size());
64
+ return unmaybe(v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kInternalized, size));
65
+ },
66
+ [](v8::Isolate* isolate, std::u16string_view subject) -> v8::Local<v8::String> {
67
+ const auto* data = reinterpret_cast<const std::uint16_t*>(subject.data());
68
+ auto size = static_cast<int>(subject.size());
69
+ return unmaybe(v8::String::NewFromTwoByte(isolate, data, v8::NewStringType::kInternalized, size));
70
+ },
71
+ };
72
+ if (local_key_.IsEmpty()) {
73
+ constexpr auto key = util::make_consteval_string_view(Key);
74
+ local_key_ = make(accept_or_visit.witness().isolate(), key);
75
+ }
76
+ return local_key_;
77
+ }
78
+
79
+ private:
80
+ v8::Local<v8::String> local_key_;
81
+ };
82
+
54
83
  // Implements `Visit`'s non-caching `immediate()` function as a caching visit operation.
55
84
  template <class Visit>
56
85
  struct visit_cached_immediate : Visit {
@@ -434,4 +463,10 @@ struct visit<Meta, v8::FunctionCallbackInfo<v8::Value>> : visit<Meta, v8::Local<
434
463
  }
435
464
  };
436
465
 
466
+ // Object key maker for v8 objects
467
+ template <auto Key>
468
+ struct visit_key_literal<Key, v8::Local<v8::Object>> : iv8::visit_v8_key_literal<Key> {
469
+ using iv8::visit_v8_key_literal<Key>::visit_v8_key_literal;
470
+ };
471
+
437
472
  } // namespace js
package/value/object.cc CHANGED
@@ -8,6 +8,24 @@ import v8;
8
8
 
9
9
  namespace js::iv8 {
10
10
 
11
+ constexpr auto has_property(v8::Local<v8::Context> context, v8::Local<v8::Object> object, v8::Local<v8::Name> key) -> bool {
12
+ return iv8::unmaybe(object->HasRealNamedProperty(context, key));
13
+ }
14
+
15
+ constexpr auto has_property(v8::Local<v8::Context> context, v8::Local<v8::Object> object, v8::Local<v8::Number> key) -> bool {
16
+ return iv8::unmaybe(object->HasRealIndexedProperty(context, key.As<v8::Uint32>()->Value()));
17
+ }
18
+
19
+ constexpr auto has_property(v8::Local<v8::Context> context, v8::Local<v8::Object> object, v8::Local<v8::Primitive> key) -> bool {
20
+ // Weird `if` here since there is a "quick" `IsString()` internally, but not for name, number, or
21
+ // symbol.
22
+ if (key->IsString() || !key->IsNumber()) {
23
+ return has_property(context, object, key.As<v8::Name>());
24
+ } else {
25
+ return has_property(context, object, key.As<v8::Number>());
26
+ }
27
+ }
28
+
11
29
  constexpr auto get_property(v8::Local<v8::Context> context, v8::Local<v8::Object> object, v8::Local<v8::Name> key) -> v8::Local<v8::Value> {
12
30
  // Maybe I'm misunderstanding the "without causing side effects" part of `GetRealNamedProperty`'s
13
31
  // documentation, but it definitely invokes getters.
@@ -42,15 +60,27 @@ auto value_for_object::keys() const -> const value_for_array& {
42
60
  return keys_;
43
61
  }
44
62
 
45
- auto value_for_object::get(v8::Local<v8::Name> key) -> v8::Local<v8::Value> {
63
+ auto value_for_object::has(v8::Local<v8::Name> key) const -> bool {
64
+ return has_property(context(), util::slice(*this), key);
65
+ }
66
+
67
+ auto value_for_object::has(v8::Local<v8::Number> key) const -> bool {
68
+ return has_property(context(), util::slice(*this), key);
69
+ }
70
+
71
+ auto value_for_object::has(v8::Local<v8::Primitive> key) const -> bool {
72
+ return has_property(context(), util::slice(*this), key);
73
+ }
74
+
75
+ auto value_for_object::get(v8::Local<v8::Name> key) const -> v8::Local<v8::Value> {
46
76
  return get_property(context(), util::slice(*this), key);
47
77
  }
48
78
 
49
- auto value_for_object::get(v8::Local<v8::Number> key) -> v8::Local<v8::Value> {
79
+ auto value_for_object::get(v8::Local<v8::Number> key) const -> v8::Local<v8::Value> {
50
80
  return get_property(context(), util::slice(*this), key);
51
81
  }
52
82
 
53
- auto value_for_object::get(v8::Local<v8::Primitive> key) -> v8::Local<v8::Value> {
83
+ auto value_for_object::get(v8::Local<v8::Primitive> key) const -> v8::Local<v8::Value> {
54
84
  return get_property(context(), util::slice(*this), key);
55
85
  }
56
86
 
package/value/object.h.cc CHANGED
@@ -33,9 +33,12 @@ class value_for_object : public handle_with_context<v8::Object> {
33
33
  using range_type = std::ranges::transform_view<std::views::all_t<const value_for_array&>, iterator_transform>;
34
34
  using iterator = std::ranges::iterator_t<range_type>;
35
35
 
36
- [[nodiscard]] auto get(v8::Local<v8::Name> key) -> v8::Local<v8::Value>;
37
- [[nodiscard]] auto get(v8::Local<v8::Number> key) -> v8::Local<v8::Value>;
38
- [[nodiscard]] auto get(v8::Local<v8::Primitive> key) -> v8::Local<v8::Value>;
36
+ [[nodiscard]] auto get(v8::Local<v8::Name> key) const -> v8::Local<v8::Value>;
37
+ [[nodiscard]] auto get(v8::Local<v8::Number> key) const -> v8::Local<v8::Value>;
38
+ [[nodiscard]] auto get(v8::Local<v8::Primitive> key) const -> v8::Local<v8::Value>;
39
+ [[nodiscard]] auto has(v8::Local<v8::Name> key) const -> bool;
40
+ [[nodiscard]] auto has(v8::Local<v8::Number> key) const -> bool;
41
+ [[nodiscard]] auto has(v8::Local<v8::Primitive> key) const -> bool;
39
42
  [[nodiscard]] auto into_range() -> range_type;
40
43
  [[nodiscard]] auto size() const -> std::size_t;
41
44