File indexing completed on 2025-02-21 10:05:25
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<T>(const LocalBase<T>& other)
0402 : LocalBase<T>(other) {}
0403
0404 V8_INLINE static Local<T> FromSlot(internal::Address* slot) {
0405 return Local<T>(LocalBase<T>::FromSlot(slot));
0406 }
0407
0408 #ifdef V8_ENABLE_DIRECT_LOCAL
0409 friend class TypecheckWitness;
0410
0411 V8_INLINE static Local<T> FromAddress(internal::Address ptr) {
0412 return Local<T>(LocalBase<T>(ptr));
0413 }
0414 #endif
0415
0416 V8_INLINE static Local<T> New(Isolate* isolate, internal::Address value) {
0417 return Local<T>(LocalBase<T>::New(isolate, value));
0418 }
0419
0420 V8_INLINE static Local<T> New(Isolate* isolate, T* that) {
0421 return Local<T>(LocalBase<T>::New(isolate, that));
0422 }
0423
0424
0425 template <class S>
0426 V8_INLINE Local<S> UnsafeAs() const {
0427 return Local<S>(LocalBase<S>(*this));
0428 }
0429 };
0430
0431 namespace internal {
0432
0433
0434 template <typename T>
0435 class V8_TRIVIAL_ABI LocalUnchecked : public Local<T> {
0436 public:
0437 LocalUnchecked() : Local<T>(Local<T>::do_not_check) {}
0438
0439 #if defined(V8_ENABLE_LOCAL_OFF_STACK_CHECK) && V8_HAS_ATTRIBUTE_TRIVIAL_ABI
0440
0441
0442 LocalUnchecked(const LocalUnchecked& other)
0443 : Local<T>(other, Local<T>::do_not_check) {}
0444 LocalUnchecked& operator=(const LocalUnchecked&) = default;
0445 #endif
0446
0447
0448 LocalUnchecked(const Local<T>& other)
0449 : Local<T>(other, Local<T>::do_not_check) {}
0450 };
0451
0452 #ifdef V8_ENABLE_DIRECT_LOCAL
0453
0454
0455
0456 template <typename T>
0457 class StrongRootAllocator<LocalUnchecked<T>> : public StrongRootAllocatorBase {
0458 public:
0459 using value_type = LocalUnchecked<T>;
0460 static_assert(std::is_standard_layout_v<value_type>);
0461 static_assert(sizeof(value_type) == sizeof(Address));
0462
0463 explicit StrongRootAllocator(Heap* heap) : StrongRootAllocatorBase(heap) {}
0464 explicit StrongRootAllocator(v8::Isolate* isolate)
0465 : StrongRootAllocatorBase(isolate) {}
0466 template <typename U>
0467 StrongRootAllocator(const StrongRootAllocator<U>& other) noexcept
0468 : StrongRootAllocatorBase(other) {}
0469
0470 value_type* allocate(size_t n) {
0471 return reinterpret_cast<value_type*>(allocate_impl(n));
0472 }
0473 void deallocate(value_type* p, size_t n) noexcept {
0474 return deallocate_impl(reinterpret_cast<Address*>(p), n);
0475 }
0476 };
0477 #endif
0478 }
0479
0480 template <typename T>
0481 class LocalVector {
0482 private:
0483 using element_type = internal::LocalUnchecked<T>;
0484
0485 #ifdef V8_ENABLE_DIRECT_LOCAL
0486 using allocator_type = internal::StrongRootAllocator<element_type>;
0487
0488 static allocator_type make_allocator(Isolate* isolate) noexcept {
0489 return allocator_type(isolate);
0490 }
0491 #else
0492 using allocator_type = std::allocator<element_type>;
0493
0494 static allocator_type make_allocator(Isolate* isolate) noexcept {
0495 return allocator_type();
0496 }
0497 #endif
0498
0499 using vector_type = std::vector<element_type, allocator_type>;
0500
0501 public:
0502 using value_type = Local<T>;
0503 using reference = value_type&;
0504 using const_reference = const value_type&;
0505 using size_type = size_t;
0506 using difference_type = ptrdiff_t;
0507 using iterator =
0508 internal::WrappedIterator<typename vector_type::iterator, Local<T>>;
0509 using const_iterator =
0510 internal::WrappedIterator<typename vector_type::const_iterator,
0511 const Local<T>>;
0512
0513 explicit LocalVector(Isolate* isolate) : backing_(make_allocator(isolate)) {}
0514 LocalVector(Isolate* isolate, size_t n)
0515 : backing_(n, make_allocator(isolate)) {}
0516 explicit LocalVector(Isolate* isolate, std::initializer_list<Local<T>> init)
0517 : backing_(make_allocator(isolate)) {
0518 if (init.size() == 0) return;
0519 backing_.reserve(init.size());
0520 backing_.insert(backing_.end(), init.begin(), init.end());
0521 }
0522
0523 iterator begin() noexcept { return iterator(backing_.begin()); }
0524 const_iterator begin() const noexcept {
0525 return const_iterator(backing_.begin());
0526 }
0527 iterator end() noexcept { return iterator(backing_.end()); }
0528 const_iterator end() const noexcept { return const_iterator(backing_.end()); }
0529
0530 size_t size() const noexcept { return backing_.size(); }
0531 bool empty() const noexcept { return backing_.empty(); }
0532 void reserve(size_t n) { backing_.reserve(n); }
0533 void shrink_to_fit() { backing_.shrink_to_fit(); }
0534
0535 Local<T>& operator[](size_t n) { return backing_[n]; }
0536 const Local<T>& operator[](size_t n) const { return backing_[n]; }
0537
0538 Local<T>& at(size_t n) { return backing_.at(n); }
0539 const Local<T>& at(size_t n) const { return backing_.at(n); }
0540
0541 Local<T>& front() { return backing_.front(); }
0542 const Local<T>& front() const { return backing_.front(); }
0543 Local<T>& back() { return backing_.back(); }
0544 const Local<T>& back() const { return backing_.back(); }
0545
0546 Local<T>* data() noexcept { return backing_.data(); }
0547 const Local<T>* data() const noexcept { return backing_.data(); }
0548
0549 iterator insert(const_iterator pos, const Local<T>& value) {
0550 return iterator(backing_.insert(pos.base(), value));
0551 }
0552
0553 template <typename InputIt>
0554 iterator insert(const_iterator pos, InputIt first, InputIt last) {
0555 return iterator(backing_.insert(pos.base(), first, last));
0556 }
0557
0558 iterator insert(const_iterator pos, std::initializer_list<Local<T>> init) {
0559 return iterator(backing_.insert(pos.base(), init.begin(), init.end()));
0560 }
0561
0562 LocalVector<T>& operator=(std::initializer_list<Local<T>> init) {
0563 backing_.clear();
0564 backing_.insert(backing_.end(), init.begin(), init.end());
0565 return *this;
0566 }
0567
0568 void push_back(const Local<T>& x) { backing_.push_back(x); }
0569 void pop_back() { backing_.pop_back(); }
0570 void emplace_back(const Local<T>& x) { backing_.emplace_back(x); }
0571
0572 void clear() noexcept { backing_.clear(); }
0573 void resize(size_t n) { backing_.resize(n); }
0574 void swap(LocalVector<T>& other) { backing_.swap(other.backing_); }
0575
0576 friend bool operator==(const LocalVector<T>& x, const LocalVector<T>& y) {
0577 return x.backing_ == y.backing_;
0578 }
0579 friend bool operator!=(const LocalVector<T>& x, const LocalVector<T>& y) {
0580 return x.backing_ != y.backing_;
0581 }
0582 friend bool operator<(const LocalVector<T>& x, const LocalVector<T>& y) {
0583 return x.backing_ < y.backing_;
0584 }
0585 friend bool operator>(const LocalVector<T>& x, const LocalVector<T>& y) {
0586 return x.backing_ > y.backing_;
0587 }
0588 friend bool operator<=(const LocalVector<T>& x, const LocalVector<T>& y) {
0589 return x.backing_ <= y.backing_;
0590 }
0591 friend bool operator>=(const LocalVector<T>& x, const LocalVector<T>& y) {
0592 return x.backing_ >= y.backing_;
0593 }
0594
0595 private:
0596 vector_type backing_;
0597 };
0598
0599 #if !defined(V8_IMMINENT_DEPRECATION_WARNINGS)
0600
0601 template <class T>
0602 using Handle = Local<T>;
0603 #endif
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615 template <class T>
0616 class MaybeLocal {
0617 public:
0618 V8_INLINE MaybeLocal() : local_() {}
0619 template <class S>
0620 V8_INLINE MaybeLocal(Local<S> that) : local_(that) {}
0621
0622 V8_INLINE bool IsEmpty() const { return local_.IsEmpty(); }
0623
0624
0625
0626
0627
0628 template <class S>
0629 V8_WARN_UNUSED_RESULT V8_INLINE bool ToLocal(Local<S>* out) const {
0630 *out = local_;
0631 return !IsEmpty();
0632 }
0633
0634
0635
0636
0637
0638 V8_INLINE Local<T> ToLocalChecked() {
0639 if (V8_UNLIKELY(IsEmpty())) api_internal::ToLocalEmpty();
0640 return local_;
0641 }
0642
0643
0644
0645
0646
0647 template <class S>
0648 V8_INLINE Local<S> FromMaybe(Local<S> default_value) const {
0649 return IsEmpty() ? default_value : Local<S>(local_);
0650 }
0651
0652
0653
0654
0655
0656
0657 template <class S>
0658 V8_INLINE static MaybeLocal<T> Cast(MaybeLocal<S> that) {
0659 #ifdef V8_ENABLE_CHECKS
0660
0661
0662 if (that.IsEmpty()) return MaybeLocal<T>();
0663 T::Cast(that.local_.template value<S>());
0664 #endif
0665 return MaybeLocal<T>(that.local_);
0666 }
0667
0668
0669
0670
0671
0672
0673 template <class S>
0674 V8_INLINE MaybeLocal<S> As() const {
0675 return MaybeLocal<S>::Cast(*this);
0676 }
0677
0678 private:
0679 Local<T> local_;
0680
0681 template <typename S>
0682 friend class MaybeLocal;
0683 };
0684
0685
0686
0687
0688
0689 class V8_EXPORT V8_NODISCARD EscapableHandleScopeBase : public HandleScope {
0690 public:
0691 explicit EscapableHandleScopeBase(Isolate* isolate);
0692 V8_INLINE ~EscapableHandleScopeBase() = default;
0693
0694 EscapableHandleScopeBase(const EscapableHandleScopeBase&) = delete;
0695 void operator=(const EscapableHandleScopeBase&) = delete;
0696 void* operator new(size_t size) = delete;
0697 void* operator new[](size_t size) = delete;
0698 void operator delete(void*, size_t) = delete;
0699 void operator delete[](void*, size_t) = delete;
0700
0701 protected:
0702
0703
0704
0705
0706 internal::Address* EscapeSlot(internal::Address* escape_value);
0707
0708 private:
0709 internal::Address* escape_slot_;
0710 };
0711
0712 class V8_EXPORT V8_NODISCARD EscapableHandleScope
0713 : public EscapableHandleScopeBase {
0714 public:
0715 explicit EscapableHandleScope(Isolate* isolate)
0716 : EscapableHandleScopeBase(isolate) {}
0717 V8_INLINE ~EscapableHandleScope() = default;
0718 template <class T>
0719 V8_INLINE Local<T> Escape(Local<T> value) {
0720 #ifdef V8_ENABLE_DIRECT_LOCAL
0721 return value;
0722 #else
0723 if (value.IsEmpty()) return value;
0724 return Local<T>::FromSlot(EscapeSlot(value.slot()));
0725 #endif
0726 }
0727
0728 template <class T>
0729 V8_INLINE MaybeLocal<T> EscapeMaybe(MaybeLocal<T> value) {
0730 return Escape(value.FromMaybe(Local<T>()));
0731 }
0732 };
0733
0734
0735
0736
0737
0738
0739 class V8_EXPORT V8_NODISCARD SealHandleScope {
0740 public:
0741 explicit SealHandleScope(Isolate* isolate);
0742 ~SealHandleScope();
0743
0744 SealHandleScope(const SealHandleScope&) = delete;
0745 void operator=(const SealHandleScope&) = delete;
0746 void* operator new(size_t size) = delete;
0747 void* operator new[](size_t size) = delete;
0748 void operator delete(void*, size_t) = delete;
0749 void operator delete[](void*, size_t) = delete;
0750
0751 private:
0752 internal::Isolate* const i_isolate_;
0753 internal::Address* prev_limit_;
0754 int prev_sealed_level_;
0755 };
0756
0757 }
0758
0759 #endif