@auto_js/v8 0.0.8 → 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/CMakeLists.txt +2 -0
- package/_module.cc +1 -0
- package/handle/value_of.cc +7 -3
- package/isolated/agent.cc +9 -5
- package/isolated/agent.h.cc +3 -0
- package/isolated/memory_policy.cc +49 -0
- package/isolated/memory_policy.h.cc +48 -0
- package/package.json +3 -3
- package/transfer/accept.h.cc +21 -0
- package/transfer/visit.cc +44 -1
package/CMakeLists.txt
CHANGED
|
@@ -64,6 +64,7 @@ if(v8_js STREQUAL isolated_v8_js)
|
|
|
64
64
|
isolated/clock.cc
|
|
65
65
|
isolated/cluster.cc
|
|
66
66
|
isolated/executor.cc
|
|
67
|
+
isolated/memory_policy.cc
|
|
67
68
|
isolated/platform.cc
|
|
68
69
|
platform/delegate.cc
|
|
69
70
|
platform/foreground_runner.cc
|
|
@@ -76,6 +77,7 @@ if(v8_js STREQUAL isolated_v8_js)
|
|
|
76
77
|
isolated/clock.h.cc
|
|
77
78
|
isolated/cluster.h.cc
|
|
78
79
|
isolated/executor.h.cc
|
|
80
|
+
isolated/memory_policy.h.cc
|
|
79
81
|
isolated/platform.h.cc
|
|
80
82
|
platform/delegate.h.cc
|
|
81
83
|
platform/foreground_runner.h.cc
|
package/_module.cc
CHANGED
|
@@ -24,6 +24,7 @@ export import :evaluation.script;
|
|
|
24
24
|
export import :isolated.agent;
|
|
25
25
|
export import :isolated.clock;
|
|
26
26
|
export import :isolated.cluster;
|
|
27
|
+
export import :isolated.memory_policy;
|
|
27
28
|
export import :isolated.platform;
|
|
28
29
|
export import :platform.delegate;
|
|
29
30
|
export import :platform.foreground_runner;
|
package/handle/value_of.cc
CHANGED
|
@@ -9,9 +9,9 @@ namespace js::iv8 {
|
|
|
9
9
|
template <class Tag>
|
|
10
10
|
struct value_specialization;
|
|
11
11
|
|
|
12
|
-
// nb: This corresponds to `js::napi::
|
|
13
|
-
// `js::napi::
|
|
14
|
-
template <class Tag>
|
|
12
|
+
// nb: This corresponds to `js::napi::value_of<T>`. `v8::Local<T>` is more like
|
|
13
|
+
// `js::napi::local_of<T>`.
|
|
14
|
+
export template <class Tag>
|
|
15
15
|
class value_of : public value_specialization<Tag>::type {
|
|
16
16
|
public:
|
|
17
17
|
using value_specialization<Tag>::type::type;
|
|
@@ -50,9 +50,13 @@ struct value_specialization<date_tag> : std::type_identity<class value_for_date>
|
|
|
50
50
|
template <>
|
|
51
51
|
struct value_specialization<external_tag> : std::type_identity<class value_for_external> {};
|
|
52
52
|
|
|
53
|
+
// TODO: value_for_record
|
|
53
54
|
template <>
|
|
54
55
|
struct value_specialization<object_tag> : std::type_identity<class value_for_object> {};
|
|
55
56
|
|
|
57
|
+
template <>
|
|
58
|
+
struct value_specialization<list_tag> : std::type_identity<class value_for_object> {};
|
|
59
|
+
|
|
56
60
|
template <>
|
|
57
61
|
struct value_specialization<array_buffer_tag> : std::type_identity<class value_for_array_buffer> {};
|
|
58
62
|
|
package/isolated/agent.cc
CHANGED
|
@@ -75,18 +75,22 @@ agent_host::agent_host(
|
|
|
75
75
|
behavior_params params
|
|
76
76
|
) :
|
|
77
77
|
storage_{std::move(storage)},
|
|
78
|
+
memory_policy_{std::move(params.memory_policy)},
|
|
78
79
|
clock_{params.clock},
|
|
79
80
|
destroy_callback_{destroy_callback},
|
|
80
81
|
reset_handle_callback_{reset_handle_type{util::fn<&agent_host::remote_expiration_callback>, *this}},
|
|
81
82
|
random_seed_{params.random_seed} {
|
|
82
83
|
executor_.initialize([ & ](v8::Isolate* isolate) noexcept -> auto {
|
|
83
84
|
isolate->SetData(0, this);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
v8::Isolate::CreateParams params;
|
|
86
|
+
auto memory_params = memory_policy_->make_create_params();
|
|
87
|
+
params.constraints = memory_params.constraints;
|
|
88
|
+
params.array_buffer_allocator_shared = std::move(memory_params.allocator);
|
|
89
|
+
return params;
|
|
88
90
|
});
|
|
89
|
-
executor_.isolate()
|
|
91
|
+
auto* isolate = executor_.isolate();
|
|
92
|
+
isolate->SetCaptureStackTraceForUncaughtExceptions(true);
|
|
93
|
+
memory_policy_->initialize(isolate);
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
agent_host::~agent_host() {
|
package/isolated/agent.h.cc
CHANGED
|
@@ -4,6 +4,7 @@ export module v8_js:isolated.agent;
|
|
|
4
4
|
import :collected_handle;
|
|
5
5
|
import :isolated.clock;
|
|
6
6
|
import :isolated.executor;
|
|
7
|
+
import :isolated.memory_policy;
|
|
7
8
|
import :platform.foreground_runner;
|
|
8
9
|
import :remote;
|
|
9
10
|
import std;
|
|
@@ -18,6 +19,7 @@ class agent_host_of;
|
|
|
18
19
|
|
|
19
20
|
// `agent_host` behavior parameters
|
|
20
21
|
export struct behavior_params {
|
|
22
|
+
memory_policy::covariant memory_policy;
|
|
21
23
|
clock::any_clock clock;
|
|
22
24
|
std::optional<double> random_seed;
|
|
23
25
|
};
|
|
@@ -146,6 +148,7 @@ export class agent_host
|
|
|
146
148
|
// Order matters for these members
|
|
147
149
|
std::shared_ptr<agent_storage> storage_;
|
|
148
150
|
isolated::executor executor_;
|
|
151
|
+
isolated::memory_policy::covariant memory_policy_;
|
|
149
152
|
|
|
150
153
|
// Order doesn't really matter
|
|
151
154
|
bool should_give_seed_{};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module v8_js;
|
|
2
|
+
import :isolated.memory_policy;
|
|
3
|
+
|
|
4
|
+
namespace js::iv8::isolated {
|
|
5
|
+
|
|
6
|
+
// memory_policy::none
|
|
7
|
+
auto memory_policy::none::make_create_params() -> create_params {
|
|
8
|
+
return {
|
|
9
|
+
.allocator = std::shared_ptr<v8::ArrayBuffer::Allocator>(v8::ArrayBuffer::Allocator::NewDefaultAllocator()),
|
|
10
|
+
.constraints = {}
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// memory_policy::limited
|
|
15
|
+
auto memory_policy::limited::initialize(v8::Isolate* isolate) -> void {
|
|
16
|
+
isolate->AddNearHeapLimitCallback(
|
|
17
|
+
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
|
18
|
+
[](void* data, std::size_t current_heap_limit, std::size_t initial_heap_limit) -> std::size_t {
|
|
19
|
+
auto& self = *static_cast<memory_policy::limited*>(data);
|
|
20
|
+
return self.near_heap_limit_callback(current_heap_limit, initial_heap_limit);
|
|
21
|
+
},
|
|
22
|
+
this
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
auto memory_policy::limited::make_create_params() -> create_params {
|
|
27
|
+
v8::ResourceConstraints constraints{};
|
|
28
|
+
constraints.ConfigureDefaultsFromHeapSize(0, memory_limit_);
|
|
29
|
+
return {
|
|
30
|
+
.allocator = std::shared_ptr<v8::ArrayBuffer::Allocator>(v8::ArrayBuffer::Allocator::NewDefaultAllocator()),
|
|
31
|
+
.constraints = constraints,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
|
|
36
|
+
auto memory_policy::limited::near_heap_limit_callback(std::size_t current_heap_limit, std::size_t /*initial_heap_limit*/) const -> std::size_t {
|
|
37
|
+
auto* isolate = v8::Isolate::GetCurrent();
|
|
38
|
+
v8::HeapStatistics heap;
|
|
39
|
+
isolate->GetHeapStatistics(&heap);
|
|
40
|
+
|
|
41
|
+
if (current_heap_limit > memory_limit_) {
|
|
42
|
+
auto& executor = agent_host::get_current(isolate).executor();
|
|
43
|
+
executor.terminate();
|
|
44
|
+
}
|
|
45
|
+
// Increase heap limit 64mb at a time
|
|
46
|
+
return current_heap_limit + (64 << 20);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
} // namespace js::iv8::isolated
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export module v8_js:isolated.memory_policy;
|
|
2
|
+
import std;
|
|
3
|
+
import util;
|
|
4
|
+
import v8;
|
|
5
|
+
|
|
6
|
+
namespace js::iv8::isolated {
|
|
7
|
+
|
|
8
|
+
export class memory_policy {
|
|
9
|
+
protected:
|
|
10
|
+
~memory_policy() = default;
|
|
11
|
+
|
|
12
|
+
public:
|
|
13
|
+
struct create_params;
|
|
14
|
+
|
|
15
|
+
// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor)
|
|
16
|
+
class none;
|
|
17
|
+
// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor)
|
|
18
|
+
class limited;
|
|
19
|
+
|
|
20
|
+
virtual auto initialize(v8::Isolate* isolate) -> void = 0;
|
|
21
|
+
virtual auto make_create_params() -> create_params = 0;
|
|
22
|
+
// virtual auto check_soft_limit(v8::Isolate* isolate) -> bool = 0;
|
|
23
|
+
using covariant = util::covariant_value<memory_policy, none, limited>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
struct memory_policy::create_params {
|
|
27
|
+
std::shared_ptr<v8::ArrayBuffer::Allocator> allocator;
|
|
28
|
+
v8::ResourceConstraints constraints;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
class memory_policy::none final : public memory_policy {
|
|
32
|
+
public:
|
|
33
|
+
auto initialize(v8::Isolate* isolate) -> void override {};
|
|
34
|
+
auto make_create_params() -> create_params override;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
class memory_policy::limited final : public memory_policy {
|
|
38
|
+
public:
|
|
39
|
+
explicit limited(std::size_t memory_limit_bytes) : memory_limit_{memory_limit_bytes} {}
|
|
40
|
+
auto initialize(v8::Isolate* isolate) -> void override;
|
|
41
|
+
auto make_create_params() -> create_params override;
|
|
42
|
+
|
|
43
|
+
private:
|
|
44
|
+
std::size_t memory_limit_;
|
|
45
|
+
[[nodiscard]] auto near_heap_limit_callback(std::size_t current_heap_limit, std::size_t initial_heap_limit) const -> std::size_t;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
} // namespace js::iv8::isolated
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@auto_js/v8",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
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/
|
|
9
|
-
"@auto_js/
|
|
8
|
+
"@auto_js/js": "^0.0.9",
|
|
9
|
+
"@auto_js/v8_exports": "^0.0.7"
|
|
10
10
|
},
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
package/transfer/accept.h.cc
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export module v8_js:accept;
|
|
2
2
|
import :callback_storage;
|
|
3
|
+
import :handle.value;
|
|
3
4
|
import :hash;
|
|
4
5
|
import :value;
|
|
5
6
|
import auto_js;
|
|
@@ -370,6 +371,20 @@ struct accept_v8_property_value {
|
|
|
370
371
|
accept_value<Meta, Type> second;
|
|
371
372
|
};
|
|
372
373
|
|
|
374
|
+
// Forward `value_of<T>`
|
|
375
|
+
template <class Tag>
|
|
376
|
+
struct accept_v8_value_of {
|
|
377
|
+
public:
|
|
378
|
+
explicit accept_v8_value_of(auto* /*transfer*/) {}
|
|
379
|
+
|
|
380
|
+
auto operator()(Tag /*tag*/, visit_holder /*visit*/, value_of<Tag> subject) const -> value_of<Tag> {
|
|
381
|
+
return subject;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
consteval static auto accept_tags_of() { return std::tuple{Tag{}}; }
|
|
385
|
+
consteval static auto types(auto /*recursive*/) { return util::type_pack{}; }
|
|
386
|
+
};
|
|
387
|
+
|
|
373
388
|
// `return_into(...)`
|
|
374
389
|
struct return_into_marker {};
|
|
375
390
|
|
|
@@ -475,6 +490,12 @@ struct accept<Meta, v8::Local<Type>> : iv8::accept_v8_value_with<typename Meta::
|
|
|
475
490
|
using iv8::accept_v8_value_with<typename Meta::accept_context_type>::accept_v8_value_with;
|
|
476
491
|
};
|
|
477
492
|
|
|
493
|
+
// forward `value_of<T>`
|
|
494
|
+
template <class Meta, class Tag>
|
|
495
|
+
struct accept<Meta, iv8::value_of<Tag>> : iv8::accept_v8_value_of<Tag> {
|
|
496
|
+
using iv8::accept_v8_value_of<Tag>::accept_v8_value_of;
|
|
497
|
+
};
|
|
498
|
+
|
|
478
499
|
// templates
|
|
479
500
|
template <class Meta, class Type>
|
|
480
501
|
requires std::is_convertible_v<Type, v8::Template>
|
package/transfer/visit.cc
CHANGED
|
@@ -380,7 +380,7 @@ struct visit_value : visit_flat_value<Target> {
|
|
|
380
380
|
template <class Accept>
|
|
381
381
|
auto immediate(v8::Local<v8::Array> subject, const Accept& accept) -> accept_target_t<Accept> {
|
|
382
382
|
auto visit_entry = visit_entry_pair<visit_property_name<visit_value>, visit_value&>{*this};
|
|
383
|
-
return accept(list_tag{}, visit_entry, value_of{witness(), subject.As<v8::
|
|
383
|
+
return accept(list_tag{}, visit_entry, value_of{witness(), subject.As<v8::Array>()});
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
// function template
|
|
@@ -433,6 +433,40 @@ struct visit_value : visit_flat_value<Target> {
|
|
|
433
433
|
v8::Local<v8::Context> context_;
|
|
434
434
|
};
|
|
435
435
|
|
|
436
|
+
// Forward `value_of<T>` back to acceptor
|
|
437
|
+
template <class Tag>
|
|
438
|
+
struct visit_v8_value_of {
|
|
439
|
+
private:
|
|
440
|
+
using visit_type = visit_value<void>;
|
|
441
|
+
|
|
442
|
+
public:
|
|
443
|
+
constexpr explicit visit_v8_value_of(auto* transfer, context_lock_witness lock) : visit_{transfer, lock} {}
|
|
444
|
+
|
|
445
|
+
template <class Accept>
|
|
446
|
+
constexpr auto operator()(value_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept> {
|
|
447
|
+
return accept(Tag{}, visit_, subject);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
template <class Accept>
|
|
451
|
+
requires std::is_same_v<Tag, object_tag>
|
|
452
|
+
constexpr auto operator()(value_of<object_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
|
|
453
|
+
auto visit_entry = visit_entry_pair<visit_property_name<visit_type>, visit_type&>{visit_};
|
|
454
|
+
return accept(object_tag{}, visit_entry, subject);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
template <class Accept>
|
|
458
|
+
requires std::is_same_v<Tag, list_tag>
|
|
459
|
+
constexpr auto operator()(value_of<list_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
|
|
460
|
+
auto visit_entry = visit_entry_pair<visit_property_name<visit_type>, visit_type&>{visit_};
|
|
461
|
+
return accept(list_tag{}, visit_entry, subject);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
consteval static auto types(auto /*recursive*/) { return util::type_pack{}; }
|
|
465
|
+
|
|
466
|
+
private:
|
|
467
|
+
visit_type visit_;
|
|
468
|
+
};
|
|
469
|
+
|
|
436
470
|
// Template visitor needs no lock. The acceptor will instantiate values.
|
|
437
471
|
struct visit_template {
|
|
438
472
|
explicit visit_template(auto* /*transfer*/) {}
|
|
@@ -467,6 +501,15 @@ struct visit<Meta, v8::Local<Type>> : iv8::visit_value_with<Meta> {
|
|
|
467
501
|
using iv8::visit_value_with<Meta>::visit_value_with;
|
|
468
502
|
};
|
|
469
503
|
|
|
504
|
+
// value_of<T> visitor
|
|
505
|
+
template <class Meta, class Tag>
|
|
506
|
+
struct visit<Meta, iv8::value_of<Tag>> : iv8::visit_v8_value_of<Tag> {
|
|
507
|
+
using iv8::visit_v8_value_of<Tag>::visit_v8_value_of;
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
template <class Tag>
|
|
511
|
+
struct visit_subject_for<iv8::value_of<Tag>> : std::type_identity<v8::Local<v8::Value>> {};
|
|
512
|
+
|
|
470
513
|
// Template visitor
|
|
471
514
|
template <class Meta, class Type>
|
|
472
515
|
requires std::is_convertible_v<Type, v8::Template>
|