@isolated-vm/experimental 0.0.9 → 0.0.10

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.
Files changed (152) hide show
  1. package/addon/CMakeLists.txt +1 -1
  2. package/addon/handle/local_of.cc +150 -0
  3. package/addon/handle/types.cc +8 -137
  4. package/addon/handle/value_of.cc +82 -27
  5. package/addon/support/callback_info.cc +5 -5
  6. package/addon/support/callback_storage.cc +2 -2
  7. package/addon/support/free_function.cc +2 -2
  8. package/addon/support/initialize.cc +2 -2
  9. package/addon/transfer/accept.cc +84 -64
  10. package/addon/transfer/visit.cc +90 -47
  11. package/addon/value/array.cc +6 -6
  12. package/addon/value/array_buffer.cc +27 -18
  13. package/addon/value/function.cc +5 -5
  14. package/addon/value/function.h.cc +5 -5
  15. package/addon/value/object.cc +3 -3
  16. package/addon/value/primitive.cc +36 -36
  17. package/addon/value/prototype.cc +7 -7
  18. package/addon/value/record.cc +20 -20
  19. package/addon/value/value.cc +1 -1
  20. package/addon/value/vector.cc +9 -9
  21. package/backend/backend.d.cts +9 -9
  22. package/dist/frontend/agent.d.ts +1 -0
  23. package/dist/frontend/agent.d.ts.map +1 -1
  24. package/dist/frontend/agent.js.map +1 -1
  25. package/dist/frontend/module.d.ts +1 -1
  26. package/dist/frontend/module.d.ts.map +1 -1
  27. package/dist/frontend/module.js.map +1 -1
  28. package/dist/frontend/reference.d.ts +3 -3
  29. package/dist/frontend/reference.d.ts.map +1 -1
  30. package/dist/test/00.agent/00.prerequisites.d.ts +2 -0
  31. package/dist/test/00.agent/00.prerequisites.d.ts.map +1 -0
  32. package/dist/test/00.agent/00.prerequisites.js +25 -0
  33. package/dist/test/00.agent/00.prerequisites.js.map +1 -0
  34. package/dist/test/00.agent/10.clock.d.ts +2 -0
  35. package/dist/test/00.agent/10.clock.d.ts.map +1 -0
  36. package/dist/test/{00.datetime.js → 00.agent/10.clock.js} +8 -8
  37. package/dist/test/00.agent/10.clock.js.map +1 -0
  38. package/dist/test/00.agent/10.random.d.ts +2 -0
  39. package/dist/test/00.agent/10.random.d.ts.map +1 -0
  40. package/dist/test/{00.random.js → 00.agent/10.random.js} +4 -4
  41. package/dist/test/00.agent/10.random.js.map +1 -0
  42. package/dist/test/10.transfer/00.primitives.d.ts +2 -0
  43. package/dist/test/10.transfer/00.primitives.d.ts.map +1 -0
  44. package/dist/test/10.transfer/00.primitives.js +54 -0
  45. package/dist/test/10.transfer/00.primitives.js.map +1 -0
  46. package/dist/test/10.transfer/10.array_buffer.d.ts +2 -0
  47. package/dist/test/10.transfer/10.array_buffer.d.ts.map +1 -0
  48. package/dist/test/{20.array_buffer.js → 10.transfer/10.array_buffer.js} +69 -64
  49. package/dist/test/10.transfer/10.array_buffer.js.map +1 -0
  50. package/dist/test/10.transfer/50.interceptors.d.ts +2 -0
  51. package/dist/test/10.transfer/50.interceptors.d.ts.map +1 -0
  52. package/dist/test/10.transfer/50.interceptors.js +108 -0
  53. package/dist/test/10.transfer/50.interceptors.js.map +1 -0
  54. package/dist/test/10.transfer/90.regressions.d.ts +2 -0
  55. package/dist/test/10.transfer/90.regressions.d.ts.map +1 -0
  56. package/dist/test/10.transfer/90.regressions.js +72 -0
  57. package/dist/test/10.transfer/90.regressions.js.map +1 -0
  58. package/dist/test/20.intrinsics/00.script.d.ts +2 -0
  59. package/dist/test/20.intrinsics/00.script.d.ts.map +1 -0
  60. package/dist/test/{10.script.js → 20.intrinsics/00.script.js} +7 -7
  61. package/dist/test/20.intrinsics/00.script.js.map +1 -0
  62. package/dist/test/20.intrinsics/05.global.d.ts.map +1 -0
  63. package/dist/test/{05.global.js → 20.intrinsics/05.global.js} +5 -5
  64. package/dist/test/20.intrinsics/05.global.js.map +1 -0
  65. package/dist/test/20.intrinsics/10.reference.d.ts.map +1 -0
  66. package/dist/test/{10.reference.js → 20.intrinsics/10.reference.js} +15 -15
  67. package/dist/test/20.intrinsics/10.reference.js.map +1 -0
  68. package/dist/test/20.intrinsics/20.module.d.ts +2 -0
  69. package/dist/test/20.intrinsics/20.module.d.ts.map +1 -0
  70. package/dist/test/{10.module.js → 20.intrinsics/20.module.js} +18 -18
  71. package/dist/test/20.intrinsics/20.module.js.map +1 -0
  72. package/dist/test/50.features/50.timers.d.ts.map +1 -0
  73. package/dist/test/{50.timers.js → 50.features/50.timers.js} +8 -8
  74. package/dist/test/50.features/50.timers.js.map +1 -0
  75. package/dist/test/50.features/90.i18n.d.ts +2 -0
  76. package/dist/test/50.features/90.i18n.d.ts.map +1 -0
  77. package/dist/test/{99.i18n.js → 50.features/90.i18n.js} +6 -6
  78. package/dist/test/50.features/90.i18n.js.map +1 -0
  79. package/dist/test/90.isolation/00.dispose.d.ts +1 -1
  80. package/dist/test/90.isolation/00.dispose.d.ts.map +1 -1
  81. package/dist/test/90.isolation/00.dispose.js +23 -5
  82. package/dist/test/90.isolation/00.dispose.js.map +1 -1
  83. package/dist/test/90.isolation/10.memory.d.ts +2 -0
  84. package/dist/test/90.isolation/10.memory.d.ts.map +1 -0
  85. package/dist/test/90.isolation/10.memory.js +31 -0
  86. package/dist/test/90.isolation/10.memory.js.map +1 -0
  87. package/dist/test/fixtures.js +2 -2
  88. package/dist/test/fixtures.js.map +1 -1
  89. package/dist/test/glob.d.ts +2 -0
  90. package/dist/test/glob.d.ts.map +1 -0
  91. package/dist/test/glob.js +11 -0
  92. package/dist/test/glob.js.map +1 -0
  93. package/dist/tsconfig.tsbuildinfo +1 -1
  94. package/dist/utility/completion.d.ts +2 -1
  95. package/dist/utility/completion.d.ts.map +1 -1
  96. package/dist/utility/completion.js +4 -0
  97. package/dist/utility/completion.js.map +1 -1
  98. package/frontend/agent.ts +1 -0
  99. package/frontend/module.ts +1 -1
  100. package/frontend/reference.ts +3 -3
  101. package/package.json +13 -13
  102. package/test/00.agent/00.prerequisites.ts +12 -0
  103. package/test/{00.datetime.ts → 00.agent/10.clock.ts} +7 -7
  104. package/test/{00.random.ts → 00.agent/10.random.ts} +3 -3
  105. package/test/10.transfer/00.primitives.ts +47 -0
  106. package/test/{20.array_buffer.ts → 10.transfer/10.array_buffer.ts} +40 -35
  107. package/test/10.transfer/50.interceptors.ts +63 -0
  108. package/test/10.transfer/90.regressions.ts +38 -0
  109. package/test/{10.script.ts → 20.intrinsics/00.script.ts} +6 -6
  110. package/test/{05.global.ts → 20.intrinsics/05.global.ts} +5 -5
  111. package/test/{10.reference.ts → 20.intrinsics/10.reference.ts} +18 -17
  112. package/test/{10.module.ts → 20.intrinsics/20.module.ts} +17 -17
  113. package/test/{50.timers.ts → 50.features/50.timers.ts} +8 -8
  114. package/test/{99.i18n.ts → 50.features/90.i18n.ts} +5 -5
  115. package/test/90.isolation/00.dispose.ts +12 -5
  116. package/test/90.isolation/10.memory.ts +19 -0
  117. package/test/fixtures.ts +4 -4
  118. package/test/glob.ts +11 -0
  119. package/utility/completion.ts +6 -1
  120. package/addon/handle/bound_value.cc +0 -45
  121. package/dist/test/00.datetime.d.ts +0 -2
  122. package/dist/test/00.datetime.d.ts.map +0 -1
  123. package/dist/test/00.datetime.js.map +0 -1
  124. package/dist/test/00.random.d.ts +0 -2
  125. package/dist/test/00.random.d.ts.map +0 -1
  126. package/dist/test/00.random.js.map +0 -1
  127. package/dist/test/00.transfer.d.ts +0 -2
  128. package/dist/test/00.transfer.d.ts.map +0 -1
  129. package/dist/test/00.transfer.js +0 -168
  130. package/dist/test/00.transfer.js.map +0 -1
  131. package/dist/test/05.global.d.ts.map +0 -1
  132. package/dist/test/05.global.js.map +0 -1
  133. package/dist/test/10.module.d.ts +0 -2
  134. package/dist/test/10.module.d.ts.map +0 -1
  135. package/dist/test/10.module.js.map +0 -1
  136. package/dist/test/10.reference.d.ts.map +0 -1
  137. package/dist/test/10.reference.js.map +0 -1
  138. package/dist/test/10.script.d.ts +0 -2
  139. package/dist/test/10.script.d.ts.map +0 -1
  140. package/dist/test/10.script.js.map +0 -1
  141. package/dist/test/20.array_buffer.d.ts +0 -2
  142. package/dist/test/20.array_buffer.d.ts.map +0 -1
  143. package/dist/test/20.array_buffer.js.map +0 -1
  144. package/dist/test/50.timers.d.ts.map +0 -1
  145. package/dist/test/50.timers.js.map +0 -1
  146. package/dist/test/99.i18n.d.ts +0 -2
  147. package/dist/test/99.i18n.d.ts.map +0 -1
  148. package/dist/test/99.i18n.js.map +0 -1
  149. package/test/00.transfer.ts +0 -134
  150. /package/dist/test/{05.global.d.ts → 20.intrinsics/05.global.d.ts} +0 -0
  151. /package/dist/test/{10.reference.d.ts → 20.intrinsics/10.reference.d.ts} +0 -0
  152. /package/dist/test/{50.timers.d.ts → 50.features/50.timers.d.ts} +0 -0
@@ -13,79 +13,79 @@ struct accept_vm_primitive {
13
13
  explicit accept_vm_primitive(const basic_lock& lock) : lock_{lock} {}
14
14
 
15
15
  // undefined
16
- auto operator()(undefined_tag /*tag*/, visit_holder /*visit*/, std::monostate /*subject*/) const -> value_of<undefined_tag> {
17
- return value_of<undefined_tag>::make(lock());
16
+ auto operator()(undefined_tag /*tag*/, visit_holder /*visit*/, std::monostate /*subject*/) const -> local_of<undefined_tag> {
17
+ return local_of<undefined_tag>::make(lock());
18
18
  }
19
19
 
20
- auto operator()(undefined_tag tag, visit_holder visit, const auto& /*subject*/) const -> value_of<undefined_tag> {
20
+ auto operator()(undefined_tag tag, visit_holder visit, const auto& /*subject*/) const -> local_of<undefined_tag> {
21
21
  return (*this)(tag, visit, std::monostate{});
22
22
  }
23
23
 
24
24
  // null
25
- auto operator()(null_tag /*tag*/, visit_holder /*visit*/, std::nullptr_t /*subject*/) const -> value_of<null_tag> {
26
- return value_of<null_tag>::make(lock());
25
+ auto operator()(null_tag /*tag*/, visit_holder /*visit*/, std::nullptr_t /*subject*/) const -> local_of<null_tag> {
26
+ return local_of<null_tag>::make(lock());
27
27
  }
28
28
 
29
- auto operator()(null_tag tag, visit_holder visit, const auto& /*subject*/) const -> value_of<null_tag> {
29
+ auto operator()(null_tag tag, visit_holder visit, const auto& /*subject*/) const -> local_of<null_tag> {
30
30
  return (*this)(tag, visit, nullptr);
31
31
  }
32
32
 
33
33
  // boolean
34
- auto operator()(boolean_tag /*tag*/, visit_holder /*visit*/, bool subject) const -> value_of<boolean_tag> {
35
- return value_of<boolean_tag>::make(lock(), subject);
34
+ auto operator()(boolean_tag /*tag*/, visit_holder /*visit*/, bool subject) const -> local_of<boolean_tag> {
35
+ return local_of<boolean_tag>::make(lock(), subject);
36
36
  }
37
37
 
38
38
  // number
39
- auto operator()(number_tag_of<double> /*tag*/, visit_holder /*visit*/, double subject) const -> value_of<number_tag_of<double>> {
40
- return value_of<number_tag>::make(lock(), subject);
39
+ auto operator()(number_tag_of<double> /*tag*/, visit_holder /*visit*/, double subject) const -> local_of<number_tag_of<double>> {
40
+ return local_of<number_tag_of<double>>::make(lock(), subject);
41
41
  }
42
42
 
43
- auto operator()(number_tag_of<std::int32_t> /*tag*/, visit_holder /*visit*/, std::int32_t subject) const -> value_of<number_tag_of<std::int32_t>> {
44
- return value_of<number_tag>::make(lock(), subject);
43
+ auto operator()(number_tag_of<std::int32_t> /*tag*/, visit_holder /*visit*/, std::int32_t subject) const -> local_of<number_tag_of<std::int32_t>> {
44
+ return local_of<number_tag_of<std::int32_t>>::make(lock(), subject);
45
45
  }
46
46
 
47
- auto operator()(number_tag /*tag*/, visit_holder visit, auto&& subject) const -> value_of<number_tag> {
47
+ auto operator()(number_tag /*tag*/, visit_holder visit, auto&& subject) const -> local_of<number_tag> {
48
48
  return (*this)(number_tag_of<double>{}, visit, double{std::forward<decltype(subject)>(subject)});
49
49
  }
50
50
 
51
51
  template <class Type>
52
- auto operator()(number_tag_of<Type> tag, visit_holder visit, auto&& subject) const -> value_of<number_tag_of<Type>> {
52
+ auto operator()(number_tag_of<Type> tag, visit_holder visit, auto&& subject) const -> local_of<number_tag_of<Type>> {
53
53
  return (*this)(tag, visit, Type{std::forward<decltype(subject)>(subject)});
54
54
  }
55
55
 
56
56
  // string
57
57
  auto operator()(string_tag_of<char> /*tag*/, visit_holder /*visit*/, std::string_view subject) const
58
- -> js::referenceable_value<value_of<string_tag_of<char>>> {
59
- return js::referenceable_value{value_of<string_tag>::make(lock(), subject)};
58
+ -> js::referenceable_value<local_of<string_tag_of<char>>> {
59
+ return js::referenceable_value{local_of<string_tag_of<char>>::make(lock(), subject)};
60
60
  }
61
61
 
62
62
  auto operator()(string_tag_of<char16_t> /*tag*/, visit_holder /*visit*/, std::u16string_view subject) const
63
- -> js::referenceable_value<value_of<string_tag_of<char16_t>>> {
64
- return js::referenceable_value{value_of<string_tag>::make(lock(), subject)};
63
+ -> js::referenceable_value<local_of<string_tag_of<char16_t>>> {
64
+ return js::referenceable_value{local_of<string_tag_of<char16_t>>::make(lock(), subject)};
65
65
  }
66
66
 
67
67
  auto operator()(string_tag /*tag*/, visit_holder visit, auto&& subject) const
68
- -> js::referenceable_value<value_of<string_tag>> {
68
+ -> js::referenceable_value<local_of<string_tag>> {
69
69
  auto value = (*this)(string_tag_of<char16_t>{}, visit, std::u16string_view{std::forward<decltype(subject)>(subject)});
70
- return js::referenceable_value{value_of<string_tag>{*value}};
70
+ return js::referenceable_value{local_of<string_tag>{*value}};
71
71
  }
72
72
 
73
73
  template <class Char>
74
74
  auto operator()(string_tag_of<Char> tag, visit_holder visit, std::convertible_to<std::basic_string_view<Char>> auto&& subject) const
75
- -> js::referenceable_value<value_of<string_tag_of<Char>>> {
75
+ -> js::referenceable_value<local_of<string_tag_of<Char>>> {
76
76
  return (*this)(tag, visit, std::basic_string_view<Char>{std::forward<decltype(subject)>(subject)});
77
77
  }
78
78
 
79
79
  template <class Char>
80
80
  auto operator()(string_tag_of<Char> tag, visit_holder visit, auto&& subject) const
81
- -> js::referenceable_value<value_of<string_tag_of<Char>>> {
81
+ -> js::referenceable_value<local_of<string_tag_of<Char>>> {
82
82
  return (*this)(tag, visit, std::basic_string<Char>{std::forward<decltype(subject)>(subject)});
83
83
  }
84
84
 
85
85
  // bigint (int64)
86
86
  auto operator()(bigint_tag_of<std::int64_t> /*tag*/, visit_holder /*visit*/, std::int64_t subject) const
87
- -> js::referenceable_value<value_of<bigint_tag_of<std::int64_t>>> {
88
- return js::referenceable_value{value_of<bigint_tag>::make(lock(), subject)};
87
+ -> js::referenceable_value<local_of<bigint_tag_of<std::int64_t>>> {
88
+ return js::referenceable_value{local_of<bigint_tag_of<std::int64_t>>::make(lock(), subject)};
89
89
  }
90
90
 
91
91
  [[nodiscard]] auto lock() const -> const basic_lock& { return lock_; }
@@ -102,22 +102,22 @@ struct accept_vm_prototype : accept_vm_primitive {
102
102
 
103
103
  // cast primitive to prototype
104
104
  template <std::convertible_to<primitive_tag> Tag>
105
- auto operator()(Tag tag, auto& visit, auto&& subject) const -> value_of<prototype_tag> {
105
+ auto operator()(Tag tag, auto& visit, auto&& subject) const -> local_of<prototype_tag> {
106
106
  const accept_vm_primitive& accept = *this;
107
107
  auto result = accept(tag, visit, std::forward<decltype(subject)>(subject));
108
108
  constexpr auto unwrap = util::overloaded{
109
109
  [](auto value) { return value; },
110
110
  []<class Type>(js::referenceable_value<Type> value) { return *std::move(value); },
111
111
  };
112
- return value_of<prototype_tag>::from(unwrap(result));
112
+ return local_of<prototype_tag>::from(unwrap(result));
113
113
  }
114
114
 
115
115
  // function
116
- auto operator()(function_prototype_tag /*tag*/, visit_holder /*visit*/, auto subject) const -> value_of<function_prototype_tag> {
116
+ auto operator()(function_prototype_tag /*tag*/, visit_holder /*visit*/, auto subject) const -> local_of<function_prototype_tag> {
117
117
  using lock_type = const runtime_lock&;
118
118
  auto [ function, length ] = make_free_function<lock_type>(std::move(subject).callback);
119
119
  auto data = make_callback_storage(std::move(function));
120
- return value_of<function_prototype_tag>::make(lock(), std::move(data), length);
120
+ return local_of<function_prototype_tag>::make(lock(), std::move(data), length);
121
121
  }
122
122
  };
123
123
 
@@ -128,39 +128,39 @@ struct accept_vm_value : accept_vm_primitive {
128
128
 
129
129
  // bigint (from words)
130
130
  auto operator()(bigint_tag_of<js::bigint> /*tag*/, visit_holder /*visit*/, const js::bigint& subject) const
131
- -> js::referenceable_value<value_of<bigint_tag_of<js::bigint>>> {
132
- return js::referenceable_value{value_of<bigint_tag>::make(lock(), subject)};
131
+ -> js::referenceable_value<local_of<bigint_tag_of<js::bigint>>> {
132
+ return js::referenceable_value{local_of<bigint_tag_of<js::bigint>>::make(lock(), subject)};
133
133
  }
134
134
 
135
135
  auto operator()(bigint_tag_of<js::bigint> /*tag*/, visit_holder /*visit*/, js::bigint&& subject) const
136
- -> js::referenceable_value<value_of<bigint_tag_of<js::bigint>>> {
137
- return js::referenceable_value{value_of<bigint_tag>::make(lock(), std::move(subject))};
136
+ -> js::referenceable_value<local_of<bigint_tag_of<js::bigint>>> {
137
+ return js::referenceable_value{local_of<bigint_tag_of<js::bigint>>::make(lock(), std::move(subject))};
138
138
  }
139
139
 
140
140
  auto operator()(bigint_tag /*tag*/, visit_holder visit, auto&& subject) const
141
- -> js::referenceable_value<value_of<bigint_tag>> {
141
+ -> js::referenceable_value<local_of<bigint_tag>> {
142
142
  auto value = (*this)(bigint_tag_of<js::bigint>{}, visit, js::bigint{std::forward<decltype(subject)>(subject)});
143
- return js::referenceable_value{value_of<bigint_tag>{*std::move(value)}};
143
+ return js::referenceable_value{local_of<bigint_tag>{*std::move(value)}};
144
144
  }
145
145
 
146
146
  template <class Type>
147
147
  auto operator()(bigint_tag_of<Type> tag, visit_holder visit, auto&& subject) const
148
- -> js::referenceable_value<value_of<bigint_tag_of<Type>>> {
148
+ -> js::referenceable_value<local_of<bigint_tag_of<Type>>> {
149
149
  return (*this)(tag, visit, Type{std::forward<decltype(subject)>(subject)});
150
150
  }
151
151
 
152
152
  // array
153
153
  auto operator()(this const auto& self, list_tag /*tag*/, auto& visit, auto&& subject)
154
- -> js::deferred_receiver<value_of<list_tag>, decltype(self), decltype(visit), decltype(subject)> {
154
+ -> js::deferred_receiver<local_of<list_tag>, decltype(self), decltype(visit), decltype(subject)> {
155
155
  return {
156
- value_of<list_tag>::make(self.lock()),
156
+ local_of<list_tag>::make(self.lock()),
157
157
  std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
158
- [](value_of<list_tag> receiver, auto& self, auto& visit, auto /*&&*/ subject) -> void {
158
+ [](local_of<list_tag> receiver, auto& self, auto& visit, auto /*&&*/ subject) -> void {
159
159
  auto&& range = util::into_range(std::forward<decltype(subject)>(subject));
160
160
  for (auto&& [ key, value ] : util::forward_range(std::forward<decltype(range)>(range))) {
161
161
  auto name = visit.first(std::forward<decltype(key)>(key), self);
162
162
  auto item = visit.first(std::forward<decltype(value)>(value), self);
163
- receiver.set(self.lock(), name, item);
163
+ receiver->set(self.lock(), name, item);
164
164
  }
165
165
  },
166
166
  };
@@ -168,17 +168,17 @@ struct accept_vm_value : accept_vm_primitive {
168
168
 
169
169
  // vectors
170
170
  auto operator()(this const auto& self, vector_tag /*tag*/, auto& visit, auto&& subject)
171
- -> js::deferred_receiver<value_of<list_tag>, decltype(self), decltype(visit), decltype(subject)> {
171
+ -> js::deferred_receiver<local_of<list_tag>, decltype(self), decltype(visit), decltype(subject)> {
172
172
  auto [... size ] = util::maybe_range_size(subject);
173
173
  return {
174
- value_of<list_tag>::make(self.lock(), size...),
174
+ local_of<list_tag>::make(self.lock(), size...),
175
175
  std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
176
- [](value_of<list_tag> receiver, auto& self, auto& visit, auto /*&&*/ subject) -> void {
176
+ [](local_of<list_tag> receiver, auto& self, auto& visit, auto /*&&*/ subject) -> void {
177
177
  int ii = 0;
178
178
  auto&& range = util::into_range(std::forward<decltype(subject)>(subject));
179
179
  for (auto&& element : util::forward_range(std::forward<decltype(range)>(range))) {
180
180
  auto item = visit(std::forward<decltype(element)>(element), self);
181
- receiver.set(self.lock(), ii++, item);
181
+ receiver->set(self.lock(), ii++, item);
182
182
  }
183
183
  },
184
184
  };
@@ -186,15 +186,15 @@ struct accept_vm_value : accept_vm_primitive {
186
186
 
187
187
  template <std::size_t Size>
188
188
  auto operator()(this const auto& self, tuple_tag<Size> /*tag*/, auto& visit, auto&& subject)
189
- -> js::deferred_receiver<value_of<list_tag>, decltype(self), decltype(visit), decltype(subject)> {
189
+ -> js::deferred_receiver<local_of<list_tag>, decltype(self), decltype(visit), decltype(subject)> {
190
190
  return {
191
- value_of<list_tag>::make(self.lock(), Size),
191
+ local_of<list_tag>::make(self.lock(), Size),
192
192
  std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
193
- [](value_of<list_tag> receiver, auto& self, auto& visit, auto /*&&*/ tuple) -> void {
193
+ [](local_of<list_tag> receiver, auto& self, auto& visit, auto /*&&*/ tuple) -> void {
194
194
  const auto [... indices ] = util::sequence<Size>;
195
195
  (..., [ & ]() -> void {
196
196
  auto element = visit(indices, std::forward<decltype(tuple)>(tuple), self);
197
- unmaybe(receiver.set(self.lock(), indices, element));
197
+ unmaybe(receiver->set(self.lock(), indices, element));
198
198
  }());
199
199
  }
200
200
  };
@@ -202,15 +202,15 @@ struct accept_vm_value : accept_vm_primitive {
202
202
 
203
203
  // dictionary
204
204
  auto operator()(this const auto& self, dictionary_tag /*tag*/, auto& visit, auto&& subject)
205
- -> js::deferred_receiver<value_of<dictionary_tag>, decltype(self), decltype(visit), decltype(subject)> {
205
+ -> js::deferred_receiver<local_of<dictionary_tag>, decltype(self), decltype(visit), decltype(subject)> {
206
206
  return {
207
- value_of<record_tag>::make(self.lock()),
207
+ local_of<record_tag>::make(self.lock()),
208
208
  std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
209
- [](value_of<dictionary_tag> receiver, auto& self, auto& visit, auto /*&&*/ subject) -> void {
209
+ [](local_of<dictionary_tag> receiver, auto& self, auto& visit, auto /*&&*/ subject) -> void {
210
210
  for (auto&& [ key, value ] : util::into_range(subject)) {
211
211
  auto name = visit.first(std::forward<decltype(key)>(key), self);
212
212
  auto item = visit.first(std::forward<decltype(value)>(value), self);
213
- receiver.set(self.lock(), name, item);
213
+ receiver->set(self.lock(), name, item);
214
214
  }
215
215
  },
216
216
  };
@@ -219,30 +219,30 @@ struct accept_vm_value : accept_vm_primitive {
219
219
  // structs
220
220
  template <std::size_t Size>
221
221
  auto operator()(this const auto& self, struct_tag<Size> /*tag*/, auto& visit, auto&& subject)
222
- -> js::deferred_receiver<value_of<record_tag>, decltype(self), decltype(visit), decltype(subject)> {
222
+ -> js::deferred_receiver<local_of<record_tag>, decltype(self), decltype(visit), decltype(subject)> {
223
223
  return {
224
- value_of<record_tag>::make(self.lock()),
224
+ local_of<record_tag>::make(self.lock()),
225
225
  std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
226
- [](value_of<record_tag> receiver, auto& self, auto& visit, auto /*&&*/ subject) -> void {
226
+ [](local_of<record_tag> receiver, auto& self, auto& visit, auto /*&&*/ subject) -> void {
227
227
  self.template accept_entry_pair_struct<Size>(visit, receiver, std::forward<decltype(subject)>(subject));
228
228
  }
229
229
  };
230
230
  }
231
231
 
232
232
  template <std::size_t Size>
233
- auto accept_entry_pair_struct(this const auto& self, auto& visit, value_of<record_tag> receiver, auto&& subject) -> void {
233
+ auto accept_entry_pair_struct(this const auto& self, auto& visit, local_of<record_tag> receiver, auto&& subject) -> void {
234
234
  const auto [... indices ] = util::sequence<Size>;
235
235
  (..., [ & ]() -> void {
236
236
  auto accept_entry = accept_entry_pair<decltype(self), decltype(self)>{self};
237
237
  auto entry = visit(std::integral_constant<std::size_t, indices>{}, std::forward<decltype(subject)>(subject), accept_entry);
238
- receiver.set(self.lock(), entry.first, entry.second);
238
+ receiver->set(self.lock(), entry.first, entry.second);
239
239
  }());
240
240
  }
241
241
 
242
242
  // array buffer
243
243
  auto operator()(array_buffer_tag /*tag*/, visit_holder /*visit*/, js::array_buffer subject) const
244
- -> js::referenceable_value<value_of<array_buffer_tag>> {
245
- return js::referenceable_value{value_of<array_buffer_tag>::make(lock(), std::move(subject))};
244
+ -> js::referenceable_value<local_of<array_buffer_tag>> {
245
+ return js::referenceable_value{local_of<array_buffer_tag>::make(lock(), std::move(subject))};
246
246
  }
247
247
 
248
248
  [[nodiscard]] auto lock() const -> const runtime_lock& {
@@ -250,6 +250,20 @@ struct accept_vm_value : accept_vm_primitive {
250
250
  }
251
251
  };
252
252
 
253
+ // Forward `value_of<T>`
254
+ template <class Tag>
255
+ struct accept_vm_value_of {
256
+ public:
257
+ explicit accept_vm_value_of(auto* /*transfer*/) {}
258
+
259
+ auto operator()(Tag /*tag*/, visit_holder /*visit*/, value_of<Tag> subject) const -> value_of<Tag> {
260
+ return subject;
261
+ }
262
+
263
+ consteval static auto accept_tags_of() { return std::tuple{Tag{}}; }
264
+ consteval static auto types(auto /*recursive*/) { return util::type_pack{}; }
265
+ };
266
+
253
267
  // Object key lookup (struct_template, etc)
254
268
  template <class Meta, auto Key, class Type>
255
269
  struct accept_vm_property_value {
@@ -267,7 +281,7 @@ struct accept_vm_property_value {
267
281
  }
268
282
 
269
283
  private:
270
- mutable visit_key_literal<Key, value_of<record_tag>> first;
284
+ mutable visit_key_literal<Key, local_of<record_tag>> first;
271
285
  accept_value<Meta, Type> second;
272
286
  };
273
287
 
@@ -277,31 +291,37 @@ namespace js {
277
291
  using namespace isolated_vm;
278
292
 
279
293
  template <class Tag>
280
- struct accept_property_subject<value_of<Tag>> : std::type_identity<value_of<record_tag>> {};
294
+ struct accept_property_subject<local_of<Tag>> : std::type_identity<local_of<record_tag>> {};
281
295
 
282
296
  // Primitive acceptor
283
297
  template <std::convertible_to<value_tag> Tag>
284
298
  requires std::is_convertible_v<Tag, primitive_tag>
285
- struct accept<void, value_of<Tag>> : accept_vm_primitive {
299
+ struct accept<void, local_of<Tag>> : accept_vm_primitive {
286
300
  using accept_vm_primitive::accept_vm_primitive;
287
301
  };
288
302
 
289
303
  // Template / prototype acceptor
290
304
  template <class Tag>
291
305
  requires std::is_convertible_v<Tag, prototype_tag>
292
- struct accept<void, value_of<Tag>> : accept_vm_prototype {
306
+ struct accept<void, local_of<Tag>> : accept_vm_prototype {
293
307
  using accept_vm_prototype::accept_vm_prototype;
294
308
  };
295
309
 
296
310
  // Value acceptor
297
311
  template <std::convertible_to<value_tag> Tag>
298
- struct accept<void, value_of<Tag>> : accept_vm_value {
312
+ struct accept<void, local_of<Tag>> : accept_vm_value {
299
313
  using accept_vm_value::accept_vm_value;
300
314
  };
301
315
 
316
+ // Forward `value_of<T>`
317
+ template <class Meta, class Tag>
318
+ struct accept<Meta, isolated_vm::value_of<Tag>> : isolated_vm::accept_vm_value_of<Tag> {
319
+ using isolated_vm::accept_vm_value_of<Tag>::accept_vm_value_of;
320
+ };
321
+
302
322
  // Object key lookup (struct_template, etc)
303
323
  template <class Meta, auto Key, class Type>
304
- struct accept_property_value<Meta, Key, Type, value_of<record_tag>> : accept_vm_property_value<Meta, Key, Type> {
324
+ struct accept_property_value<Meta, Key, Type, local_of<record_tag>> : accept_vm_property_value<Meta, Key, Type> {
305
325
  using accept_vm_property_value<Meta, Key, Type>::accept_vm_property_value;
306
326
  };
307
327
 
@@ -47,18 +47,18 @@ struct visit_vm_property_key {
47
47
  explicit visit_vm_property_key(Visit& visit) : visit_{visit} {}
48
48
 
49
49
  template <class Accept>
50
- auto operator()(value_of<primitive_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
50
+ auto operator()(local_of<primitive_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
51
51
  auto accept_as = [ & ]<class Tag>(Tag tag) -> auto {
52
- auto value = bound_value{lock(), value_of<Tag>::from(subject)};
52
+ auto value = value_of{lock(), local_of<Tag>::from(subject)};
53
53
  return accept(tag, *this, value);
54
54
  };
55
- if (subject.is_string()) {
56
- if (value_of<string_tag>::from(subject).is_latin1()) {
55
+ if (subject->is_string()) {
56
+ if (local_of<string_tag>::from(subject)->is_latin1()) {
57
57
  return accept_as(string_tag_of<char>{});
58
58
  } else {
59
59
  return accept_as(string_tag_of<char16_t>{});
60
60
  }
61
- } else if (subject.is_number()) {
61
+ } else if (subject->is_number()) {
62
62
  return accept_as(number_tag_of<std::int32_t>{});
63
63
  } else {
64
64
  return accept_as(symbol_tag{});
@@ -75,16 +75,16 @@ template <auto Key>
75
75
  struct visit_vm_key_literal {
76
76
  explicit constexpr visit_vm_key_literal(auto* /*transfer*/) {}
77
77
 
78
- auto operator()(const auto& /*anything*/, const auto& accept_or_visit) -> value_of<name_tag> {
78
+ auto operator()(const auto& /*anything*/, const auto& accept_or_visit) -> local_of<name_tag> {
79
79
  if (!local_key_) {
80
80
  constexpr auto key = util::make_consteval_string_view(Key);
81
- local_key_ = transfer_in<value_of<name_tag>>(key, accept_or_visit.lock());
81
+ local_key_ = transfer_in<local_of<name_tag>>(key, accept_or_visit.lock());
82
82
  }
83
83
  return local_key_;
84
84
  }
85
85
 
86
86
  private:
87
- value_of<name_tag> local_key_;
87
+ local_of<name_tag> local_key_;
88
88
  };
89
89
 
90
90
  struct visit_vm_value {
@@ -92,38 +92,38 @@ struct visit_vm_value {
92
92
  explicit visit_vm_value(const runtime_lock& lock) : lock_{lock} {}
93
93
 
94
94
  template <class Accept>
95
- auto operator()(value_of<> subject, const Accept& accept) -> accept_target_t<Accept> {
95
+ auto operator()(local_of<> subject, const Accept& accept) -> accept_target_t<Accept> {
96
96
  // TODO: reference map
97
97
  return util::template_traverse(
98
98
  accept_tags_of_v<Accept>,
99
99
  util::overloaded{
100
100
  // Fast paths
101
101
  [ & ](undefined_tag /*tag*/, auto next) -> accept_target_t<Accept> {
102
- return subject.is_undefined() ? accept_as(undefined_tag{}, subject, accept) : next();
102
+ return subject->is_undefined() ? accept_as(undefined_tag{}, subject, accept) : next();
103
103
  },
104
104
  [ & ](null_tag /*tag*/, auto next) -> accept_target_t<Accept> {
105
- return subject.is_null() ? accept_as(null_tag{}, subject, accept) : next();
105
+ return subject->is_null() ? accept_as(null_tag{}, subject, accept) : next();
106
106
  },
107
107
  [ & ](boolean_tag /*tag*/, auto next) -> accept_target_t<Accept> {
108
- return subject.is_boolean() ? accept_as(boolean_tag{}, subject, accept) : next();
108
+ return subject->is_boolean() ? accept_as(boolean_tag{}, subject, accept) : next();
109
109
  },
110
110
  [ & ](number_tag /*tag*/, auto next) -> accept_target_t<Accept> {
111
- return subject.is_number() ? accept_as(number_tag{}, subject, accept) : next();
111
+ return subject->is_number() ? accept_as(number_tag{}, subject, accept) : next();
112
112
  },
113
113
  [ & ](string_tag /*tag*/, auto next) -> accept_target_t<Accept> {
114
- return subject.is_string() ? accept_as(string_tag{}, subject, accept) : next();
114
+ return subject->is_string() ? accept_as(string_tag{}, subject, accept) : next();
115
115
  },
116
116
  [ & ](bigint_tag /*tag*/, auto next) -> accept_target_t<Accept> {
117
- return subject.is_bigint() ? accept_as(bigint_tag{}, subject, accept) : next();
117
+ return subject->is_bigint() ? accept_as(bigint_tag{}, subject, accept) : next();
118
118
  },
119
119
  [ & ](date_tag /*tag*/, auto next) -> accept_target_t<Accept> {
120
- return subject.is_date() ? accept_as(date_tag{}, subject, accept) : next();
120
+ return subject->is_date() ? accept_as(date_tag{}, subject, accept) : next();
121
121
  },
122
122
  [ & ](list_tag /*tag*/, auto next) -> accept_target_t<Accept> {
123
- return subject.is_array() ? accept_as(list_tag{}, subject, accept) : next();
123
+ return subject->is_array() ? accept_as(list_tag{}, subject, accept) : next();
124
124
  },
125
125
  [ & ](function_tag /*tag*/, auto next) -> accept_target_t<Accept> {
126
- return subject.is_function() ? accept_as(function_tag{}, subject, accept) : next();
126
+ return subject->is_function() ? accept_as(function_tag{}, subject, accept) : next();
127
127
  },
128
128
 
129
129
  // Unknown tag
@@ -131,12 +131,12 @@ struct visit_vm_value {
131
131
 
132
132
  // Slow path
133
133
  [ & ]() -> accept_target_t<Accept> {
134
- auto type = subject.inspect();
134
+ auto type = subject->inspect();
135
135
  const auto [... primitive_types ] = primitive_typeofs;
136
136
  if ((... || (type == primitive_types))) {
137
- return inspected(type, value_of<primitive_tag>::from(subject), accept);
137
+ return inspected(type, local_of<primitive_tag>::from(subject), accept);
138
138
  } else {
139
- return inspected(type, value_of<object_tag>::from(subject), accept);
139
+ return inspected(type, local_of<object_tag>::from(subject), accept);
140
140
  }
141
141
  },
142
142
  }
@@ -144,13 +144,13 @@ struct visit_vm_value {
144
144
  }
145
145
 
146
146
  template <class Accept>
147
- auto operator()(value_of<primitive_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
148
- return inspected(subject.inspect(), subject, accept);
147
+ auto operator()(local_of<primitive_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
148
+ return inspected(subject->inspect(), subject, accept);
149
149
  }
150
150
 
151
151
  template <class Accept>
152
- auto operator()(value_of<number_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
153
- switch (subject.inspect()) {
152
+ auto operator()(local_of<number_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
153
+ switch (subject->inspect()) {
154
154
  case value_typeof::number: return accept_as(number_tag{}, subject, accept);
155
155
  case value_typeof::number_i32: return accept_as(number_tag_of<std::int32_t>{}, subject, accept);
156
156
  default: std::unreachable();
@@ -158,8 +158,8 @@ struct visit_vm_value {
158
158
  }
159
159
 
160
160
  template <class Accept>
161
- auto operator()(value_of<string_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
162
- switch (subject.inspect()) {
161
+ auto operator()(local_of<string_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
162
+ switch (subject->inspect()) {
163
163
  case value_typeof::string: return accept_as(string_tag_of<char16_t>{}, subject, accept);
164
164
  case value_typeof::string_latin1: return accept_as(string_tag_of<char>{}, subject, accept);
165
165
  default: std::unreachable();
@@ -167,8 +167,8 @@ struct visit_vm_value {
167
167
  }
168
168
 
169
169
  template <class Accept>
170
- auto operator()(value_of<bigint_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
171
- switch (subject.inspect()) {
170
+ auto operator()(local_of<bigint_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
171
+ switch (subject->inspect()) {
172
172
  case value_typeof::bigint: return accept_as(bigint_tag{}, subject, accept);
173
173
  case value_typeof::bigint_i64: return accept_as(bigint_tag_of<std::int64_t>{}, subject, accept);
174
174
  default: std::unreachable();
@@ -176,18 +176,18 @@ struct visit_vm_value {
176
176
  }
177
177
 
178
178
  template <class Accept>
179
- auto operator()(value_of<object_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
180
- return inspected(subject.inspect(), subject, accept);
179
+ auto operator()(local_of<object_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
180
+ return inspected(subject->inspect(), subject, accept);
181
181
  }
182
182
 
183
183
  template <class Accept>
184
- auto operator()(value_of<data_block_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
185
- return inspected(subject.inspect(), subject, accept);
184
+ auto operator()(local_of<data_block_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
185
+ return inspected(subject->inspect(), subject, accept);
186
186
  }
187
187
 
188
188
  template <class Accept>
189
- auto operator()(value_of<array_buffer_view_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
190
- return inspected(subject.inspect(), subject, accept);
189
+ auto operator()(local_of<array_buffer_view_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
190
+ return inspected(subject->inspect(), subject, accept);
191
191
  }
192
192
 
193
193
  [[nodiscard]] auto lock() const -> const runtime_lock& { return lock_.get(); }
@@ -195,7 +195,7 @@ struct visit_vm_value {
195
195
 
196
196
  private:
197
197
  template <class Accept>
198
- constexpr auto inspected(value_typeof type_of, value_of<primitive_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
198
+ constexpr auto inspected(value_typeof type_of, local_of<primitive_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
199
199
  switch (type_of) {
200
200
  case value_typeof::undefined: return accept_as(undefined_tag{}, subject, accept);
201
201
  case value_typeof::null: return accept_as(null_tag{}, subject, accept);
@@ -212,13 +212,13 @@ struct visit_vm_value {
212
212
  }
213
213
 
214
214
  template <class Accept>
215
- constexpr auto inspected(value_typeof type_of, value_of<object_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
215
+ constexpr auto inspected(value_typeof type_of, local_of<object_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
216
216
  const auto [... data_block_types ] = data_block_typeofs;
217
217
  const auto [... array_buffer_view_types ] = array_buffer_view_typeofs;
218
218
  if ((... || (type_of == data_block_types))) {
219
- return inspected(type_of, value_of<data_block_tag>::from(subject), accept);
219
+ return inspected(type_of, local_of<data_block_tag>::from(subject), accept);
220
220
  } else if ((... || (type_of == array_buffer_view_types))) {
221
- return inspected(type_of, value_of<array_buffer_view_tag>::from(subject), accept);
221
+ return inspected(type_of, local_of<array_buffer_view_tag>::from(subject), accept);
222
222
  } else {
223
223
  switch (type_of) {
224
224
  case value_typeof::external: return accept_as(external_tag{}, subject, accept);
@@ -228,12 +228,12 @@ struct visit_vm_value {
228
228
  case value_typeof::array:
229
229
  {
230
230
  auto visit_entry = visit_entry_pair<visit_vm_property_key<visit_vm_value>, visit_vm_value&>{*this};
231
- return accept(list_tag{}, visit_entry, bound_value{lock_, value_of<record_tag>::from(subject)});
231
+ return accept(list_tag{}, visit_entry, value_of{lock_, local_of<record_tag>::from(subject)});
232
232
  }
233
233
  case value_typeof::dictionary:
234
234
  {
235
235
  auto visit_entry = visit_entry_pair<visit_vm_property_key<visit_vm_value>, visit_vm_value&>{*this};
236
- return accept(dictionary_tag{}, visit_entry, bound_value{lock_, value_of<record_tag>::from(subject)});
236
+ return accept(dictionary_tag{}, visit_entry, value_of{lock_, local_of<record_tag>::from(subject)});
237
237
  }
238
238
  default: std::unreachable();
239
239
  }
@@ -241,7 +241,7 @@ struct visit_vm_value {
241
241
  }
242
242
 
243
243
  template <class Accept>
244
- constexpr auto inspected(value_typeof type_of, value_of<data_block_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
244
+ constexpr auto inspected(value_typeof type_of, local_of<data_block_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
245
245
  switch (type_of) {
246
246
  case value_typeof::array_buffer: return accept_as(array_buffer_tag{}, subject, accept);
247
247
  case value_typeof::shared_array_buffer: return accept_as(shared_array_buffer_tag{}, subject, accept);
@@ -250,7 +250,7 @@ struct visit_vm_value {
250
250
  }
251
251
 
252
252
  template <class Accept>
253
- constexpr auto inspected(value_typeof type_of, value_of<array_buffer_view_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
253
+ constexpr auto inspected(value_typeof type_of, local_of<array_buffer_view_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
254
254
  switch (type_of) {
255
255
  case value_typeof::bigint64_array: return accept_as(typed_array_tag_of<std::int64_t>{}, subject, accept);
256
256
  case value_typeof::biguint64_array: return accept_as(typed_array_tag_of<std::uint64_t>{}, subject, accept);
@@ -270,25 +270,68 @@ struct visit_vm_value {
270
270
  }
271
271
 
272
272
  template <class Accept, class Tag>
273
- auto accept_as(Tag tag, value_of<> subject, const Accept& accept) -> accept_target_t<Accept> {
274
- return accept(tag, *this, bound_value{lock_, value_of<Tag>::from(subject)});
273
+ auto accept_as(Tag tag, local_of<> subject, const Accept& accept) -> accept_target_t<Accept> {
274
+ return accept(tag, *this, value_of{lock_, local_of<Tag>::from(subject)});
275
275
  }
276
276
 
277
277
  std::reference_wrapper<const runtime_lock> lock_;
278
278
  };
279
279
 
280
+ // Forward `value_of<T>` back to acceptor
281
+ template <class Tag>
282
+ struct visit_vm_value_of {
283
+ private:
284
+ using visit_type = visit_vm_value;
285
+
286
+ public:
287
+ constexpr explicit visit_vm_value_of(const runtime_lock& lock) : visit_{lock} {}
288
+
289
+ template <class Accept>
290
+ constexpr auto operator()(value_of<Tag> subject, const Accept& accept) -> accept_target_t<Accept> {
291
+ return accept(Tag{}, visit_, subject);
292
+ }
293
+
294
+ template <class Accept>
295
+ requires std::is_same_v<Tag, object_tag>
296
+ constexpr auto operator()(value_of<object_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
297
+ auto visit_entry = visit_entry_pair<visit_vm_property_key<visit_type>, visit_type&>{visit_};
298
+ return accept(object_tag{}, visit_entry, subject);
299
+ }
300
+
301
+ template <class Accept>
302
+ requires std::is_same_v<Tag, list_tag>
303
+ constexpr auto operator()(value_of<list_tag> subject, const Accept& accept) -> accept_target_t<Accept> {
304
+ auto visit_entry = visit_entry_pair<visit_vm_property_key<visit_type>, visit_type&>{visit_};
305
+ return accept(list_tag{}, visit_entry, subject);
306
+ }
307
+
308
+ consteval static auto types(auto /*recursive*/) { return util::type_pack{}; }
309
+
310
+ private:
311
+ visit_type visit_;
312
+ };
313
+
280
314
  } // namespace isolated_vm
281
315
 
282
316
  namespace js {
283
317
  using namespace isolated_vm;
284
318
 
285
319
  template <class Tag>
286
- struct visit<void, value_of<Tag>> : visit_vm_value {
320
+ struct visit<void, local_of<Tag>> : visit_vm_value {
287
321
  using visit_vm_value::visit_vm_value;
288
322
  };
289
323
 
324
+ // Pass through `value_of<Tag>`
325
+ template <class Tag>
326
+ struct visit<void, isolated_vm::value_of<Tag>> : isolated_vm::visit_vm_value_of<Tag> {
327
+ using isolated_vm::visit_vm_value_of<Tag>::visit_vm_value_of;
328
+ };
329
+
330
+ template <class Tag>
331
+ struct visit_subject_for<isolated_vm::value_of<Tag>> : std::type_identity<isolated_vm::local_of<Tag>> {};
332
+
290
333
  template <auto Key>
291
- struct visit_key_literal<Key, value_of<record_tag>> : visit_vm_key_literal<Key> {
334
+ struct visit_key_literal<Key, local_of<record_tag>> : visit_vm_key_literal<Key> {
292
335
  using visit_vm_key_literal<Key>::visit_vm_key_literal;
293
336
  };
294
337