@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 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;
@@ -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::bound_value_of<T>`. `v8::Local<T>` is more like
13
- // `js::napi::value_of<T>`.
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
- auto create_params = v8::Isolate::CreateParams{};
85
- create_params.array_buffer_allocator_shared =
86
- std::shared_ptr<v8::ArrayBuffer::Allocator>(v8::ArrayBuffer::Allocator::NewDefaultAllocator());
87
- return create_params;
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()->SetCaptureStackTraceForUncaughtExceptions(true);
91
+ auto* isolate = executor_.isolate();
92
+ isolate->SetCaptureStackTraceForUncaughtExceptions(true);
93
+ memory_policy_->initialize(isolate);
90
94
  }
91
95
 
92
96
  agent_host::~agent_host() {
@@ -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.8",
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/v8_exports": "^0.0.6",
9
- "@auto_js/js": "^0.0.8"
8
+ "@auto_js/js": "^0.0.9",
9
+ "@auto_js/v8_exports": "^0.0.7"
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
@@ -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::Object>()});
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>