File indexing completed on 2026-01-10 10:15:07
0001
0002
0003
0004
0005 #ifndef INCLUDE_V8_PERSISTENT_HANDLE_H_
0006 #define INCLUDE_V8_PERSISTENT_HANDLE_H_
0007
0008 #include "v8-internal.h" // NOLINT(build/include_directory)
0009 #include "v8-local-handle.h" // NOLINT(build/include_directory)
0010 #include "v8-weak-callback-info.h" // NOLINT(build/include_directory)
0011 #include "v8config.h" // NOLINT(build/include_directory)
0012
0013 namespace v8 {
0014
0015 class Isolate;
0016 template <class K, class V, class T>
0017 class PersistentValueMapBase;
0018 template <class T>
0019 class Global;
0020 template <class T>
0021 class PersistentBase;
0022 template <class K, class V, class T>
0023 class PersistentValueMap;
0024 class Value;
0025
0026 namespace api_internal {
0027 V8_EXPORT internal::Address* Eternalize(v8::Isolate* isolate, Value* handle);
0028 V8_EXPORT internal::Address* CopyGlobalReference(internal::Address* from);
0029 V8_EXPORT void DisposeGlobal(internal::Address* global_handle);
0030 V8_EXPORT void MakeWeak(internal::Address** location_addr);
0031 V8_EXPORT void* ClearWeak(internal::Address* location);
0032 V8_EXPORT void AnnotateStrongRetainer(internal::Address* location,
0033 const char* label);
0034 V8_EXPORT internal::Address* GlobalizeReference(internal::Isolate* isolate,
0035 internal::Address value);
0036 V8_EXPORT void MoveGlobalReference(internal::Address** from,
0037 internal::Address** to);
0038 }
0039
0040
0041
0042
0043
0044 template <class T>
0045 class Eternal : public api_internal::IndirectHandleBase {
0046 public:
0047 V8_INLINE Eternal() = default;
0048
0049
0050
0051
0052 template <class S>
0053 requires(std::is_base_of_v<T, S>)
0054 V8_INLINE Eternal(Isolate* isolate, Local<S> handle) {
0055 Set(isolate, handle);
0056 }
0057
0058
0059 V8_INLINE Local<T> Get(Isolate* isolate) const {
0060
0061
0062 return Local<T>::FromSlot(slot());
0063 }
0064
0065 template <class S>
0066 requires(std::is_base_of_v<T, S>)
0067 void Set(Isolate* isolate, Local<S> handle) {
0068 slot() =
0069 api_internal::Eternalize(isolate, *handle.template UnsafeAs<Value>());
0070 }
0071 };
0072
0073 namespace api_internal {
0074 V8_EXPORT void MakeWeak(internal::Address* location, void* data,
0075 WeakCallbackInfo<void>::Callback weak_callback,
0076 WeakCallbackType type);
0077 }
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 template <class T>
0093 class PersistentBase : public api_internal::IndirectHandleBase {
0094 public:
0095
0096
0097
0098
0099 V8_INLINE void Reset();
0100
0101
0102
0103
0104
0105 template <class S>
0106 V8_INLINE void Reset(Isolate* isolate, const Local<S>& other);
0107
0108
0109
0110
0111
0112 template <class S>
0113 V8_INLINE void Reset(Isolate* isolate, const PersistentBase<S>& other);
0114
0115 V8_INLINE Local<T> Get(Isolate* isolate) const {
0116 return Local<T>::New(isolate, *this);
0117 }
0118
0119 template <class S>
0120 V8_INLINE bool operator==(const PersistentBase<S>& that) const {
0121 return internal::HandleHelper::EqualHandles(*this, that);
0122 }
0123
0124 template <class S>
0125 V8_INLINE bool operator==(const Local<S>& that) const {
0126 return internal::HandleHelper::EqualHandles(*this, that);
0127 }
0128
0129 template <class S>
0130 V8_INLINE bool operator!=(const PersistentBase<S>& that) const {
0131 return !operator==(that);
0132 }
0133
0134 template <class S>
0135 V8_INLINE bool operator!=(const Local<S>& that) const {
0136 return !operator==(that);
0137 }
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 template <typename P>
0152 V8_INLINE void SetWeak(P* parameter,
0153 typename WeakCallbackInfo<P>::Callback callback,
0154 WeakCallbackType type);
0155
0156
0157
0158
0159
0160
0161 V8_INLINE void SetWeak();
0162
0163 template <typename P>
0164 V8_INLINE P* ClearWeak();
0165
0166
0167 V8_INLINE void ClearWeak() { ClearWeak<void>(); }
0168
0169
0170
0171
0172
0173
0174
0175 V8_INLINE void AnnotateStrongRetainer(const char* label);
0176
0177
0178 V8_INLINE bool IsWeak() const;
0179
0180
0181
0182
0183 V8_INLINE void SetWrapperClassId(uint16_t class_id);
0184
0185
0186
0187
0188
0189 V8_INLINE uint16_t WrapperClassId() const;
0190
0191 PersistentBase(const PersistentBase& other) = delete;
0192 void operator=(const PersistentBase&) = delete;
0193
0194 private:
0195 friend class Isolate;
0196 friend class Utils;
0197 template <class F>
0198 friend class Local;
0199 template <class F1, class F2>
0200 friend class Persistent;
0201 template <class F>
0202 friend class Global;
0203 template <class F>
0204 friend class PersistentBase;
0205 template <class F>
0206 friend class ReturnValue;
0207 template <class F1, class F2, class F3>
0208 friend class PersistentValueMapBase;
0209 friend class Object;
0210 friend class internal::ValueHelper;
0211
0212 V8_INLINE PersistentBase() = default;
0213
0214 V8_INLINE explicit PersistentBase(internal::Address* location)
0215 : IndirectHandleBase(location) {}
0216
0217 V8_INLINE static internal::Address* New(Isolate* isolate, T* that);
0218 };
0219
0220
0221
0222
0223
0224
0225
0226 template <class T>
0227 class NonCopyablePersistentTraits {
0228 public:
0229 using NonCopyablePersistent = Persistent<T, NonCopyablePersistentTraits<T>>;
0230 static const bool kResetInDestructor = false;
0231 template <class S, class M>
0232 V8_INLINE static void Copy(const Persistent<S, M>& source,
0233 NonCopyablePersistent* dest) {
0234 static_assert(sizeof(S) < 0,
0235 "NonCopyablePersistentTraits::Copy is not instantiable");
0236 }
0237 };
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249 template <class T, class M>
0250 class Persistent : public PersistentBase<T> {
0251 public:
0252
0253
0254
0255 V8_INLINE Persistent() = default;
0256
0257
0258
0259
0260
0261
0262 template <class S>
0263 requires(std::is_base_of_v<T, S>)
0264 V8_INLINE Persistent(Isolate* isolate, Local<S> that)
0265 : PersistentBase<T>(
0266 PersistentBase<T>::New(isolate, that.template value<S>())) {}
0267
0268
0269
0270
0271
0272
0273 template <class S, class M2>
0274 requires(std::is_base_of_v<T, S>)
0275 V8_INLINE Persistent(Isolate* isolate, const Persistent<S, M2>& that)
0276 : PersistentBase<T>(
0277 PersistentBase<T>::New(isolate, that.template value<S>())) {}
0278
0279
0280
0281
0282
0283
0284
0285 V8_INLINE Persistent(const Persistent& that) : PersistentBase<T>() {
0286 Copy(that);
0287 }
0288 template <class S, class M2>
0289 V8_INLINE Persistent(const Persistent<S, M2>& that) : PersistentBase<T>() {
0290 Copy(that);
0291 }
0292 V8_INLINE Persistent& operator=(const Persistent& that) {
0293 Copy(that);
0294 return *this;
0295 }
0296 template <class S, class M2>
0297 V8_INLINE Persistent& operator=(const Persistent<S, M2>& that) {
0298 Copy(that);
0299 return *this;
0300 }
0301
0302
0303
0304
0305
0306
0307 V8_INLINE ~Persistent() {
0308 if (M::kResetInDestructor) this->Reset();
0309 }
0310
0311
0312 template <class S, class M2>
0313 V8_INLINE static Persistent<T, M>& Cast(const Persistent<S, M2>& that) {
0314 #ifdef V8_ENABLE_CHECKS
0315
0316
0317 if (!that.IsEmpty()) T::Cast(that.template value<S>());
0318 #endif
0319 return reinterpret_cast<Persistent<T, M>&>(
0320 const_cast<Persistent<S, M2>&>(that));
0321 }
0322
0323
0324 template <class S, class M2>
0325 V8_INLINE Persistent<S, M2>& As() const {
0326 return Persistent<S, M2>::Cast(*this);
0327 }
0328
0329 private:
0330 friend class Isolate;
0331 friend class Utils;
0332 template <class F>
0333 friend class Local;
0334 template <class F1, class F2>
0335 friend class Persistent;
0336 template <class F>
0337 friend class ReturnValue;
0338
0339 template <class S, class M2>
0340 V8_INLINE void Copy(const Persistent<S, M2>& that);
0341 };
0342
0343
0344
0345
0346
0347
0348 template <class T>
0349 class Global : public PersistentBase<T> {
0350 public:
0351
0352
0353
0354 V8_INLINE Global() = default;
0355
0356
0357
0358
0359
0360
0361 template <class S>
0362 requires(std::is_base_of_v<T, S>)
0363 V8_INLINE Global(Isolate* isolate, Local<S> that)
0364 : PersistentBase<T>(
0365 PersistentBase<T>::New(isolate, that.template value<S>())) {}
0366
0367
0368
0369
0370
0371
0372 template <class S>
0373 requires(std::is_base_of_v<T, S>)
0374 V8_INLINE Global(Isolate* isolate, const PersistentBase<S>& that)
0375 : PersistentBase<T>(
0376 PersistentBase<T>::New(isolate, that.template value<S>())) {}
0377
0378
0379
0380
0381 V8_INLINE Global(Global&& other);
0382
0383 V8_INLINE ~Global() { this->Reset(); }
0384
0385
0386
0387
0388 template <class S>
0389 V8_INLINE Global& operator=(Global<S>&& rhs);
0390
0391
0392
0393
0394 Global Pass() { return static_cast<Global&&>(*this); }
0395
0396
0397
0398
0399 using MoveOnlyTypeForCPP03 = void;
0400
0401 Global(const Global&) = delete;
0402 void operator=(const Global&) = delete;
0403
0404 private:
0405 template <class F>
0406 friend class ReturnValue;
0407 };
0408
0409
0410 template <class T>
0411 using UniquePersistent = Global<T>;
0412
0413
0414
0415
0416 class V8_EXPORT PersistentHandleVisitor {
0417 public:
0418 virtual ~PersistentHandleVisitor() = default;
0419 virtual void VisitPersistentHandle(Persistent<Value>* value,
0420 uint16_t class_id) {}
0421 };
0422
0423 template <class T>
0424 internal::Address* PersistentBase<T>::New(Isolate* isolate, T* that) {
0425 if (internal::ValueHelper::IsEmpty(that)) return nullptr;
0426 return api_internal::GlobalizeReference(
0427 reinterpret_cast<internal::Isolate*>(isolate),
0428 internal::ValueHelper::ValueAsAddress(that));
0429 }
0430
0431 template <class T, class M>
0432 template <class S, class M2>
0433 void Persistent<T, M>::Copy(const Persistent<S, M2>& that) {
0434 static_assert(std::is_base_of<T, S>::value, "type check");
0435 this->Reset();
0436 if (that.IsEmpty()) return;
0437 this->slot() = api_internal::CopyGlobalReference(that.slot());
0438 M::Copy(that, this);
0439 }
0440
0441 template <class T>
0442 bool PersistentBase<T>::IsWeak() const {
0443 using I = internal::Internals;
0444 if (this->IsEmpty()) return false;
0445 return I::GetNodeState(this->slot()) == I::kNodeStateIsWeakValue;
0446 }
0447
0448 template <class T>
0449 void PersistentBase<T>::Reset() {
0450 if (this->IsEmpty()) return;
0451 api_internal::DisposeGlobal(this->slot());
0452 this->Clear();
0453 }
0454
0455
0456
0457
0458
0459 template <class T>
0460 template <class S>
0461 void PersistentBase<T>::Reset(Isolate* isolate, const Local<S>& other) {
0462 static_assert(std::is_base_of<T, S>::value, "type check");
0463 Reset();
0464 if (other.IsEmpty()) return;
0465 this->slot() = New(isolate, *other);
0466 }
0467
0468
0469
0470
0471
0472 template <class T>
0473 template <class S>
0474 void PersistentBase<T>::Reset(Isolate* isolate,
0475 const PersistentBase<S>& other) {
0476 static_assert(std::is_base_of<T, S>::value, "type check");
0477 Reset();
0478 if (other.IsEmpty()) return;
0479 this->slot() = New(isolate, other.template value<S>());
0480 }
0481
0482 template <class T>
0483 template <typename P>
0484 V8_INLINE void PersistentBase<T>::SetWeak(
0485 P* parameter, typename WeakCallbackInfo<P>::Callback callback,
0486 WeakCallbackType type) {
0487 using Callback = WeakCallbackInfo<void>::Callback;
0488 #if (__GNUC__ >= 8) && !defined(__clang__)
0489 #pragma GCC diagnostic push
0490 #pragma GCC diagnostic ignored "-Wcast-function-type"
0491 #endif
0492 api_internal::MakeWeak(this->slot(), parameter,
0493 reinterpret_cast<Callback>(callback), type);
0494 #if (__GNUC__ >= 8) && !defined(__clang__)
0495 #pragma GCC diagnostic pop
0496 #endif
0497 }
0498
0499 template <class T>
0500 void PersistentBase<T>::SetWeak() {
0501 api_internal::MakeWeak(&this->slot());
0502 }
0503
0504 template <class T>
0505 template <typename P>
0506 P* PersistentBase<T>::ClearWeak() {
0507 return reinterpret_cast<P*>(api_internal::ClearWeak(this->slot()));
0508 }
0509
0510 template <class T>
0511 void PersistentBase<T>::AnnotateStrongRetainer(const char* label) {
0512 api_internal::AnnotateStrongRetainer(this->slot(), label);
0513 }
0514
0515 template <class T>
0516 void PersistentBase<T>::SetWrapperClassId(uint16_t class_id) {
0517 using I = internal::Internals;
0518 if (this->IsEmpty()) return;
0519 uint8_t* addr = reinterpret_cast<uint8_t*>(slot()) + I::kNodeClassIdOffset;
0520 *reinterpret_cast<uint16_t*>(addr) = class_id;
0521 }
0522
0523 template <class T>
0524 uint16_t PersistentBase<T>::WrapperClassId() const {
0525 using I = internal::Internals;
0526 if (this->IsEmpty()) return 0;
0527 uint8_t* addr = reinterpret_cast<uint8_t*>(slot()) + I::kNodeClassIdOffset;
0528 return *reinterpret_cast<uint16_t*>(addr);
0529 }
0530
0531 template <class T>
0532 Global<T>::Global(Global&& other) : PersistentBase<T>(other.slot()) {
0533 if (!other.IsEmpty()) {
0534 api_internal::MoveGlobalReference(&other.slot(), &this->slot());
0535 other.Clear();
0536 }
0537 }
0538
0539 template <class T>
0540 template <class S>
0541 Global<T>& Global<T>::operator=(Global<S>&& rhs) {
0542 static_assert(std::is_base_of<T, S>::value, "type check");
0543 if (this != &rhs) {
0544 this->Reset();
0545 if (!rhs.IsEmpty()) {
0546 this->slot() = rhs.slot();
0547 api_internal::MoveGlobalReference(&rhs.slot(), &this->slot());
0548 rhs.Clear();
0549 }
0550 }
0551 return *this;
0552 }
0553
0554 }
0555
0556 #endif