@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 +2 -2
- package/transfer/accept.h.cc +72 -3
- package/transfer/visit.cc +35 -0
- package/value/object.cc +33 -3
- package/value/object.h.cc +6 -3
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@auto_js/v8",
|
|
3
|
-
"version": "0.0.
|
|
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.
|
|
8
|
+
"@auto_js/js": "^0.0.4",
|
|
9
9
|
"@auto_js/v8_exports": "^0.0.2"
|
|
10
10
|
},
|
|
11
11
|
"repository": {
|
package/transfer/accept.h.cc
CHANGED
|
@@ -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::
|
|
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(
|
|
364
|
-
|
|
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::
|
|
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
|
|