File indexing completed on 2025-12-15 10:19:09
0001
0002
0003
0004
0005 #ifndef INCLUDE_V8_LOCAL_HANDLE_H_
0006 #define INCLUDE_V8_LOCAL_HANDLE_H_
0007
0008 #include <stddef.h>
0009
0010 #include <type_traits>
0011 #include <vector>
0012
0013 #include "v8-handle-base.h" // NOLINT(build/include_directory)
0014 #include "v8-internal.h" // NOLINT(build/include_directory)
0015
0016 namespace v8 {
0017
0018 template <class T>
0019 class LocalBase;
0020 template <class T>
0021 class Local;
0022 template <class T>
0023 class LocalVector;
0024 template <class F>
0025 class MaybeLocal;
0026
0027 template <class T>
0028 class Eternal;
0029 template <class T>
0030 class Global;
0031
0032 template <class T>
0033 class NonCopyablePersistentTraits;
0034 template <class T>
0035 class PersistentBase;
0036 template <class T, class M = NonCopyablePersistentTraits<T>>
0037 class Persistent;
0038
0039 class TracedReferenceBase;
0040 template <class T>
0041 class BasicTracedReference;
0042 template <class F>
0043 class TracedReference;
0044
0045 class Boolean;
0046 class Context;
0047 class EscapableHandleScope;
0048 template <class F>
0049 class FunctionCallbackInfo;
0050 class Isolate;
0051 class Object;
0052 template <class F1, class F2, class F3>
0053 class PersistentValueMapBase;
0054 template <class F1, class F2>
0055 class PersistentValueVector;
0056 class Primitive;
0057 class Private;
0058 template <class F>
0059 class PropertyCallbackInfo;
0060 template <class F>
0061 class ReturnValue;
0062 class String;
0063 template <class F>
0064 class Traced;
0065 class TypecheckWitness;
0066 class Utils;
0067
0068 namespace debug {
0069 class ConsoleCallArguments;
0070 }
0071
0072 namespace internal {
0073 template <typename T>
0074 class CustomArguments;
0075 template <typename T>
0076 class LocalUnchecked;
0077 class SamplingHeapProfiler;
0078 }
0079
0080 namespace api_internal {
0081
0082 V8_EXPORT void ToLocalEmpty();
0083 }
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099 class V8_EXPORT V8_NODISCARD HandleScope {
0100 public:
0101 explicit HandleScope(Isolate* isolate);
0102
0103 ~HandleScope();
0104
0105
0106
0107
0108 static int NumberOfHandles(Isolate* isolate);
0109
0110 V8_INLINE Isolate* GetIsolate() const {
0111 return reinterpret_cast<Isolate*>(i_isolate_);
0112 }
0113
0114 HandleScope(const HandleScope&) = delete;
0115 void operator=(const HandleScope&) = delete;
0116
0117 static internal::Address* CreateHandleForCurrentIsolate(
0118 internal::Address value);
0119
0120 protected:
0121 V8_INLINE HandleScope() = default;
0122
0123 void Initialize(Isolate* isolate);
0124
0125 static internal::Address* CreateHandle(internal::Isolate* i_isolate,
0126 internal::Address value);
0127
0128 private:
0129
0130
0131 void* operator new(size_t size);
0132 void* operator new[](size_t size);
0133 void operator delete(void*, size_t);
0134 void operator delete[](void*, size_t);
0135
0136 internal::Isolate* i_isolate_;
0137 internal::Address* prev_next_;
0138 internal::Address* prev_limit_;
0139 #ifdef V8_ENABLE_CHECKS
0140 int scope_level_ = 0;
0141 #endif
0142
0143
0144 template <typename T>
0145 friend class LocalBase;
0146
0147
0148
0149 friend class Object;
0150 friend class Context;
0151 };
0152
0153
0154
0155
0156
0157
0158
0159 #ifdef V8_ENABLE_DIRECT_LOCAL
0160
0161 template <typename T>
0162 class LocalBase : public api_internal::DirectHandleBase {
0163 protected:
0164 template <class F>
0165 friend class Local;
0166
0167 V8_INLINE LocalBase() = default;
0168
0169 V8_INLINE explicit LocalBase(internal::Address ptr) : DirectHandleBase(ptr) {}
0170
0171 template <typename S>
0172 V8_INLINE LocalBase(const LocalBase<S>& other) : DirectHandleBase(other) {}
0173
0174 V8_INLINE static LocalBase<T> New(Isolate* isolate, internal::Address value) {
0175 return LocalBase<T>(value);
0176 }
0177
0178 V8_INLINE static LocalBase<T> New(Isolate* isolate, T* that) {
0179 return LocalBase<T>::New(isolate,
0180 internal::ValueHelper::ValueAsAddress(that));
0181 }
0182
0183 V8_INLINE static LocalBase<T> FromSlot(internal::Address* slot) {
0184 return LocalBase<T>(*slot);
0185 }
0186 };
0187
0188 #else
0189
0190 template <typename T>
0191 class LocalBase : public api_internal::IndirectHandleBase {
0192 protected:
0193 template <class F>
0194 friend class Local;
0195
0196 V8_INLINE LocalBase() = default;
0197
0198 V8_INLINE explicit LocalBase(internal::Address* location)
0199 : IndirectHandleBase(location) {}
0200
0201 template <typename S>
0202 V8_INLINE LocalBase(const LocalBase<S>& other) : IndirectHandleBase(other) {}
0203
0204 V8_INLINE static LocalBase<T> New(Isolate* isolate, internal::Address value) {
0205 return LocalBase(HandleScope::CreateHandle(
0206 reinterpret_cast<internal::Isolate*>(isolate), value));
0207 }
0208
0209 V8_INLINE static LocalBase<T> New(Isolate* isolate, T* that) {
0210 if (internal::ValueHelper::IsEmpty(that)) return LocalBase<T>();
0211 return LocalBase<T>::New(isolate,
0212 internal::ValueHelper::ValueAsAddress(that));
0213 }
0214
0215 V8_INLINE static LocalBase<T> FromSlot(internal::Address* slot) {
0216 return LocalBase<T>(slot);
0217 }
0218 };
0219
0220 #endif
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 template <class T>
0252 class V8_TRIVIAL_ABI Local : public LocalBase<T>,
0253 #ifdef V8_ENABLE_LOCAL_OFF_STACK_CHECK
0254 public api_internal::StackAllocated<true>
0255 #else
0256 public api_internal::StackAllocated<false>
0257 #endif
0258 {
0259 public:
0260 V8_INLINE Local() = default;
0261
0262 template <class S>
0263 V8_INLINE Local(Local<S> that) : LocalBase<T>(that) {
0264
0265
0266
0267
0268
0269 static_assert(std::is_base_of<T, S>::value, "type check");
0270 }
0271
0272 V8_INLINE T* operator->() const { return this->template value<T>(); }
0273
0274 V8_INLINE T* operator*() const { return this->operator->(); }
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287 template <class S>
0288 V8_INLINE bool operator==(const Local<S>& that) const {
0289 return internal::HandleHelper::EqualHandles(*this, that);
0290 }
0291
0292 template <class S>
0293 V8_INLINE bool operator==(const PersistentBase<S>& that) const {
0294 return internal::HandleHelper::EqualHandles(*this, that);
0295 }
0296
0297 template <class S>
0298 V8_INLINE bool operator!=(const Local<S>& that) const {
0299 return !operator==(that);
0300 }
0301
0302 template <class S>
0303 V8_INLINE bool operator!=(const Persistent<S>& that) const {
0304 return !operator==(that);
0305 }
0306
0307
0308
0309
0310
0311
0312 template <class S>
0313 V8_INLINE static Local<T> Cast(Local<S> that) {
0314 #ifdef V8_ENABLE_CHECKS
0315
0316
0317 if (that.IsEmpty()) return Local<T>();
0318 T::Cast(that.template value<S>());
0319 #endif
0320 return Local<T>(LocalBase<T>(that));
0321 }
0322
0323
0324
0325
0326
0327
0328 template <class S>
0329 V8_INLINE Local<S> As() const {
0330 return Local<S>::Cast(*this);
0331 }
0332
0333
0334
0335
0336
0337
0338 V8_INLINE static Local<T> New(Isolate* isolate, Local<T> that) {
0339 return New(isolate, that.template value<T, true>());
0340 }
0341
0342 V8_INLINE static Local<T> New(Isolate* isolate,
0343 const PersistentBase<T>& that) {
0344 return New(isolate, that.template value<T, true>());
0345 }
0346
0347 V8_INLINE static Local<T> New(Isolate* isolate,
0348 const BasicTracedReference<T>& that) {
0349 return New(isolate, that.template value<T, true>());
0350 }
0351
0352 private:
0353 friend class TracedReferenceBase;
0354 friend class Utils;
0355 template <class F>
0356 friend class Eternal;
0357 template <class F>
0358 friend class Global;
0359 template <class F>
0360 friend class Local;
0361 template <class F>
0362 friend class MaybeLocal;
0363 template <class F, class M>
0364 friend class Persistent;
0365 template <class F>
0366 friend class FunctionCallbackInfo;
0367 template <class F>
0368 friend class PropertyCallbackInfo;
0369 friend class String;
0370 friend class Object;
0371 friend class Context;
0372 friend class Isolate;
0373 friend class Private;
0374 template <class F>
0375 friend class internal::CustomArguments;
0376 friend Local<Primitive> Undefined(Isolate* isolate);
0377 friend Local<Primitive> Null(Isolate* isolate);
0378 friend Local<Boolean> True(Isolate* isolate);
0379 friend Local<Boolean> False(Isolate* isolate);
0380 friend class HandleScope;
0381 friend class EscapableHandleScope;
0382 friend class InternalEscapableScope;
0383 template <class F1, class F2, class F3>
0384 friend class PersistentValueMapBase;
0385 template <class F1, class F2>
0386 friend class PersistentValueVector;
0387 template <class F>
0388 friend class ReturnValue;
0389 template <class F>
0390 friend class Traced;
0391 friend class internal::SamplingHeapProfiler;
0392 friend class internal::HandleHelper;
0393 friend class debug::ConsoleCallArguments;
0394 friend class internal::LocalUnchecked<T>;
0395
0396 explicit Local(no_checking_tag do_not_check)
0397 : LocalBase<T>(), StackAllocated(do_not_check) {}
0398 explicit Local(const Local<T>& other, no_checking_tag do_not_check)
0399 : LocalBase<T>(other), StackAllocated(do_not_check) {}
0400
0401 V8_INLINE explicit Local(const LocalBase<T>& other) : LocalBase<T>(other) {}
0402
0403 V8_INLINE static Local<T> FromSlot(internal::Address* slot) {
0404 return Local<T>(LocalBase<T>::FromSlot(slot));
0405 }
0406
0407 #ifdef V8_ENABLE_DIRECT_LOCAL
0408 friend class TypecheckWitness;
0409
0410 V8_INLINE static Local<T> FromAddress(internal::Address ptr) {
0411 return Local<T>(LocalBase<T>(ptr));
0412 }
0413 #endif
0414
0415 V8_INLINE static Local<T> New(Isolate* isolate, internal::Address value) {
0416 return Local<T>(LocalBase<T>::New(isolate, value));
0417 }
0418
0419 V8_INLINE static Local<T> New(Isolate* isolate, T* that) {
0420 return Local<T>(LocalBase<T>::New(isolate, that));
0421 }
0422
0423
0424 template <class S>
0425 V8_INLINE Local<S> UnsafeAs() const {
0426 return Local<S>(LocalBase<S>(*this));
0427 }
0428 };
0429
0430 namespace internal {
0431
0432
0433 template <typename T>
0434 class V8_TRIVIAL_ABI LocalUnchecked : public Local<T> {
0435 public:
0436 LocalUnchecked() : Local<T>(Local<T>::do_not_check) {}
0437
0438 #if defined(V8_ENABLE_LOCAL_OFF_STACK_CHECK) && V8_HAS_ATTRIBUTE_TRIVIAL_ABI
0439
0440
0441 LocalUnchecked(const LocalUnchecked& other)
0442 : Local<T>(other, Local<T>::do_not_check) {}
0443 LocalUnchecked& operator=(const LocalUnchecked&) = default;
0444 #endif
0445
0446
0447 LocalUnchecked(const Local<T>& other)
0448 : Local<T>(other, Local<T>::do_not_check) {}
0449 };
0450
0451 #ifdef V8_ENABLE_DIRECT_LOCAL
0452
0453
0454
0455 template <typename T>
0456 class StrongRootAllocator<LocalUnchecked<T>> : public StrongRootAllocatorBase {
0457 public:
0458 using value_type = LocalUnchecked<T>;
0459 static_assert(std::is_standard_layout_v<value_type>);
0460 static_assert(sizeof(value_type) == sizeof(Address));
0461
0462 explicit StrongRootAllocator(Heap* heap) : StrongRootAllocatorBase(heap) {}
0463 explicit StrongRootAllocator(v8::Isolate* isolate)
0464 : StrongRootAllocatorBase(isolate) {}
0465 template <typename U>
0466 StrongRootAllocator(const StrongRootAllocator<U>& other) noexcept
0467 : StrongRootAllocatorBase(other) {}
0468
0469 value_type* allocate(size_t n) {
0470 return reinterpret_cast<value_type*>(allocate_impl(n));
0471 }
0472 void deallocate(value_type* p, size_t n) noexcept {
0473 return deallocate_impl(reinterpret_cast<Address*>(p), n);
0474 }
0475 };
0476 #endif
0477 }
0478
0479 template <typename T>
0480 class LocalVector {
0481 private:
0482 using element_type = internal::LocalUnchecked<T>;
0483
0484 #ifdef V8_ENABLE_DIRECT_LOCAL
0485 using allocator_type = internal::StrongRootAllocator<element_type>;
0486
0487 static allocator_type make_allocator(Isolate* isolate) noexcept {
0488 return allocator_type(isolate);
0489 }
0490 #else
0491 using allocator_type = std::allocator<element_type>;
0492
0493 static allocator_type make_allocator(Isolate* isolate) noexcept {
0494 return allocator_type();
0495 }
0496 #endif
0497
0498 using vector_type = std::vector<element_type, allocator_type>;
0499
0500 public:
0501 using value_type = Local<T>;
0502 using reference = value_type&;
0503 using const_reference = const value_type&;
0504 using size_type = size_t;
0505 using difference_type = ptrdiff_t;
0506 using iterator =
0507 internal::WrappedIterator<typename vector_type::iterator, Local<T>>;
0508 using const_iterator =
0509 internal::WrappedIterator<typename vector_type::const_iterator,
0510 const Local<T>>;
0511
0512 explicit LocalVector(Isolate* isolate) : backing_(make_allocator(isolate)) {}
0513 LocalVector(Isolate* isolate, size_t n)
0514 : backing_(n, make_allocator(isolate)) {}
0515 explicit LocalVector(Isolate* isolate, std::initializer_list<Local<T>> init)
0516 : backing_(make_allocator(isolate)) {
0517 if (init.size() == 0) return;
0518 backing_.reserve(init.size());
0519 backing_.insert(backing_.end(), init.begin(), init.end());
0520 }
0521
0522 iterator begin() noexcept { return iterator(backing_.begin()); }
0523 const_iterator begin() const noexcept {
0524 return const_iterator(backing_.begin());
0525 }
0526 iterator end() noexcept { return iterator(backing_.end()); }
0527 const_iterator end() const noexcept { return const_iterator(backing_.end()); }
0528
0529 size_t size() const noexcept { return backing_.size(); }
0530 bool empty() const noexcept { return backing_.empty(); }
0531 void reserve(size_t n) { backing_.reserve(n); }
0532 void shrink_to_fit() { backing_.shrink_to_fit(); }
0533
0534 Local<T>& operator[](size_t n) { return backing_[n]; }
0535 const Local<T>& operator[](size_t n) const { return backing_[n]; }
0536
0537 Local<T>& at(size_t n) { return backing_.at(n); }
0538 const Local<T>& at(size_t n) const { return backing_.at(n); }
0539
0540 Local<T>& front() { return backing_.front(); }
0541 const Local<T>& front() const { return backing_.front(); }
0542 Local<T>& back() { return backing_.back(); }
0543 const Local<T>& back() const { return backing_.back(); }
0544
0545 Local<T>* data() noexcept { return backing_.data(); }
0546 const Local<T>* data() const noexcept { return backing_.data(); }
0547
0548 iterator insert(const_iterator pos, const Local<T>& value) {
0549 return iterator(backing_.insert(pos.base(), value));
0550 }
0551
0552 template <typename InputIt>
0553 iterator insert(const_iterator pos, InputIt first, InputIt last) {
0554 return iterator(backing_.insert(pos.base(), first, last));
0555 }
0556
0557 iterator insert(const_iterator pos, std::initializer_list<Local<T>> init) {
0558 return iterator(backing_.insert(pos.base(), init.begin(), init.end()));
0559 }
0560
0561 LocalVector<T>& operator=(std::initializer_list<Local<T>> init) {
0562 backing_.clear();
0563 backing_.insert(backing_.end(), init.begin(), init.end());
0564 return *this;
0565 }
0566
0567 void push_back(const Local<T>& x) { backing_.push_back(x); }
0568 void pop_back() { backing_.pop_back(); }
0569 void emplace_back(const Local<T>& x) { backing_.emplace_back(x); }
0570
0571 void clear() noexcept { backing_.clear(); }
0572 void resize(size_t n) { backing_.resize(n); }
0573 void swap(LocalVector<T>& other) { backing_.swap(other.backing_); }
0574
0575 friend bool operator==(const LocalVector<T>& x, const LocalVector<T>& y) {
0576 return x.backing_ == y.backing_;
0577 }
0578 friend bool operator!=(const LocalVector<T>& x, const LocalVector<T>& y) {
0579 return x.backing_ != y.backing_;
0580 }
0581 friend bool operator<(const LocalVector<T>& x, const LocalVector<T>& y) {
0582 return x.backing_ < y.backing_;
0583 }
0584 friend bool operator>(const LocalVector<T>& x, const LocalVector<T>& y) {
0585 return x.backing_ > y.backing_;
0586 }
0587 friend bool operator<=(const LocalVector<T>& x, const LocalVector<T>& y) {
0588 return x.backing_ <= y.backing_;
0589 }
0590 friend bool operator>=(const LocalVector<T>& x, const LocalVector<T>& y) {
0591 return x.backing_ >= y.backing_;
0592 }
0593
0594 private:
0595 vector_type backing_;
0596 };
0597
0598 #if !defined(V8_IMMINENT_DEPRECATION_WARNINGS)
0599
0600 template <class T>
0601 using Handle = Local<T>;
0602 #endif
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614 template <class T>
0615 class MaybeLocal {
0616 public:
0617 V8_INLINE MaybeLocal() : local_() {}
0618 template <class S>
0619 V8_INLINE MaybeLocal(Local<S> that) : local_(that) {}
0620
0621 V8_INLINE bool IsEmpty() const { return local_.IsEmpty(); }
0622
0623
0624
0625
0626
0627 template <class S>
0628 V8_WARN_UNUSED_RESULT V8_INLINE bool ToLocal(Local<S>* out) const {
0629 *out = local_;
0630 return !IsEmpty();
0631 }
0632
0633
0634
0635
0636
0637 V8_INLINE Local<T> ToLocalChecked() {
0638 if (V8_UNLIKELY(IsEmpty())) api_internal::ToLocalEmpty();
0639 return local_;
0640 }
0641
0642
0643
0644
0645
0646 template <class S>
0647 V8_INLINE Local<S> FromMaybe(Local<S> default_value) const {
0648 return IsEmpty() ? default_value : Local<S>(local_);
0649 }
0650
0651
0652
0653
0654
0655
0656 template <class S>
0657 V8_INLINE static MaybeLocal<T> Cast(MaybeLocal<S> that) {
0658 #ifdef V8_ENABLE_CHECKS
0659
0660
0661 if (that.IsEmpty()) return MaybeLocal<T>();
0662 T::Cast(that.local_.template value<S>());
0663 #endif
0664 return MaybeLocal<T>(that.local_);
0665 }
0666
0667
0668
0669
0670
0671
0672 template <class S>
0673 V8_INLINE MaybeLocal<S> As() const {
0674 return MaybeLocal<S>::Cast(*this);
0675 }
0676
0677 private:
0678 Local<T> local_;
0679
0680 template <typename S>
0681 friend class MaybeLocal;
0682 };
0683
0684
0685
0686
0687
0688 class V8_EXPORT V8_NODISCARD EscapableHandleScopeBase : public HandleScope {
0689 public:
0690 explicit EscapableHandleScopeBase(Isolate* isolate);
0691 V8_INLINE ~EscapableHandleScopeBase() = default;
0692
0693 EscapableHandleScopeBase(const EscapableHandleScopeBase&) = delete;
0694 void operator=(const EscapableHandleScopeBase&) = delete;
0695 void* operator new(size_t size) = delete;
0696 void* operator new[](size_t size) = delete;
0697 void operator delete(void*, size_t) = delete;
0698 void operator delete[](void*, size_t) = delete;
0699
0700 protected:
0701
0702
0703
0704
0705 internal::Address* EscapeSlot(internal::Address* escape_value);
0706
0707 private:
0708 internal::Address* escape_slot_;
0709 };
0710
0711 class V8_EXPORT V8_NODISCARD EscapableHandleScope
0712 : public EscapableHandleScopeBase {
0713 public:
0714 explicit EscapableHandleScope(Isolate* isolate)
0715 : EscapableHandleScopeBase(isolate) {}
0716 V8_INLINE ~EscapableHandleScope() = default;
0717 template <class T>
0718 V8_INLINE Local<T> Escape(Local<T> value) {
0719 #ifdef V8_ENABLE_DIRECT_LOCAL
0720 return value;
0721 #else
0722 if (value.IsEmpty()) return value;
0723 return Local<T>::FromSlot(EscapeSlot(value.slot()));
0724 #endif
0725 }
0726
0727 template <class T>
0728 V8_INLINE MaybeLocal<T> EscapeMaybe(MaybeLocal<T> value) {
0729 return Escape(value.FromMaybe(Local<T>()));
0730 }
0731 };
0732
0733
0734
0735
0736
0737
0738 class V8_EXPORT V8_NODISCARD SealHandleScope {
0739 public:
0740 explicit SealHandleScope(Isolate* isolate);
0741 ~SealHandleScope();
0742
0743 SealHandleScope(const SealHandleScope&) = delete;
0744 void operator=(const SealHandleScope&) = delete;
0745 void* operator new(size_t size) = delete;
0746 void* operator new[](size_t size) = delete;
0747 void operator delete(void*, size_t) = delete;
0748 void operator delete[](void*, size_t) = delete;
0749
0750 private:
0751 internal::Isolate* const i_isolate_;
0752 internal::Address* prev_limit_;
0753 int prev_sealed_level_;
0754 };
0755
0756 }
0757
0758 #endif