v8 11.3.244 (node 20.3.0)
V8 is Google's open source JavaScript engine
Loading...
Searching...
No Matches
v8-persistent-handle.h
Go to the documentation of this file.
1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef INCLUDE_V8_PERSISTENT_HANDLE_H_
6#define INCLUDE_V8_PERSISTENT_HANDLE_H_
7
8#include "v8-internal.h" // NOLINT(build/include_directory)
9#include "v8-local-handle.h" // NOLINT(build/include_directory)
10#include "v8-weak-callback-info.h" // NOLINT(build/include_directory)
11#include "v8config.h" // NOLINT(build/include_directory)
12
13namespace v8 {
14
15class Isolate;
16template <class K, class V, class T>
18template <class V, class T>
20template <class T>
21class Global;
22template <class T>
23class PersistentBase;
24template <class K, class V, class T>
26class Value;
27
28namespace api_internal {
32V8_EXPORT void MakeWeak(internal::Address** location_addr);
35 const char* label);
37 internal::Address* handle);
40} // namespace api_internal
41
46template <class T>
47class Eternal {
48 public:
49 V8_INLINE Eternal() : val_(nullptr) {}
50 template <class S>
51 V8_INLINE Eternal(Isolate* isolate, Local<S> handle) : val_(nullptr) {
52 Set(isolate, handle);
53 }
54 // Can only be safely called if already set.
55 V8_INLINE Local<T> Get(Isolate* isolate) const {
56 // The eternal handle will never go away, so as with the roots, we don't
57 // even need to open a handle.
58 return Local<T>(internal::ValueHelper::SlotAsValue<T>(val_));
59 }
60
61 V8_INLINE bool IsEmpty() const { return val_ == nullptr; }
62
63 template <class S>
64 void Set(Isolate* isolate, Local<S> handle) {
65 static_assert(std::is_base_of<T, S>::value, "type check");
66 val_ = reinterpret_cast<T*>(
67 api_internal::Eternalize(isolate, reinterpret_cast<Value*>(*handle)));
68 }
69
70 private:
71 V8_INLINE internal::Address address() const {
72 return *reinterpret_cast<internal::Address*>(val_);
73 }
74
75 T* val_;
76};
77
78namespace api_internal {
79V8_EXPORT void MakeWeak(internal::Address* location, void* data,
81 WeakCallbackType type);
82} // namespace api_internal
83
97template <class T>
99 public:
105
110 template <class S>
111 V8_INLINE void Reset(Isolate* isolate, const Local<S>& other);
112
117 template <class S>
118 V8_INLINE void Reset(Isolate* isolate, const PersistentBase<S>& other);
119
120 V8_INLINE bool IsEmpty() const { return val_ == nullptr; }
121 V8_INLINE void Empty() { val_ = 0; }
122
123 V8_INLINE Local<T> Get(Isolate* isolate) const {
124 return Local<T>::New(isolate, *this);
125 }
126
127 template <class S>
128 V8_INLINE bool operator==(const PersistentBase<S>& that) const {
129 return internal::HandleHelper::EqualHandles(*this, that);
130 }
131
132 template <class S>
133 V8_INLINE bool operator==(const Local<S>& that) const {
134 return internal::HandleHelper::EqualHandles(*this, that);
135 }
136
137 template <class S>
138 V8_INLINE bool operator!=(const PersistentBase<S>& that) const {
139 return !operator==(that);
140 }
141
142 template <class S>
143 V8_INLINE bool operator!=(const Local<S>& that) const {
144 return !operator==(that);
145 }
146
159 template <typename P>
160 V8_INLINE void SetWeak(P* parameter,
161 typename WeakCallbackInfo<P>::Callback callback,
162 WeakCallbackType type);
163
170
171 template <typename P>
173
174 // TODO(dcarney): remove this.
175 V8_INLINE void ClearWeak() { ClearWeak<void>(); }
176
183 V8_INLINE void AnnotateStrongRetainer(const char* label);
184
186 V8_INLINE bool IsWeak() const;
187
191 V8_INLINE void SetWrapperClassId(uint16_t class_id);
192
197 V8_INLINE uint16_t WrapperClassId() const;
198
199 PersistentBase(const PersistentBase& other) = delete;
200 void operator=(const PersistentBase&) = delete;
201
202 private:
203 friend class Isolate;
204 friend class Utils;
205 template <class F>
206 friend class Local;
207 template <class F1, class F2>
208 friend class Persistent;
209 template <class F>
210 friend class Global;
211 template <class F>
212 friend class PersistentBase;
213 template <class F>
214 friend class ReturnValue;
215 template <class F1, class F2, class F3>
217 template <class F1, class F2>
219 friend class Object;
221
222 explicit V8_INLINE PersistentBase(T* val) : val_(val) {}
223 V8_INLINE T* operator*() const { return this->val_; }
224 V8_INLINE internal::Address address() const {
225 return *reinterpret_cast<internal::Address*>(val_);
226 }
227
228 V8_INLINE static T* New(Isolate* isolate, Local<T> that);
229 V8_INLINE static T* New(Isolate* isolate, T* that);
230
231 T* val_;
232};
233
240template <class T>
242 public:
244 static const bool kResetInDestructor = false;
245 template <class S, class M>
246 V8_INLINE static void Copy(const Persistent<S, M>& source,
247 NonCopyablePersistent* dest) {
248 static_assert(sizeof(S) < 0,
249 "NonCopyablePersistentTraits::Copy is not instantiable");
250 }
251};
252
257template <class T>
258struct V8_DEPRECATED("Use v8::Global instead") CopyablePersistentTraits {
259 using CopyablePersistent = Persistent<T, CopyablePersistentTraits<T>>;
260 static const bool kResetInDestructor = true;
261 template <class S, class M>
262 static V8_INLINE void Copy(const Persistent<S, M>& source,
263 CopyablePersistent* dest) {
264 // do nothing, just allow copy
265 }
266};
267
276template <class T, class M>
277class Persistent : public PersistentBase<T> {
278 public:
289 template <class S>
291 : PersistentBase<T>(PersistentBase<T>::New(isolate, that)) {
292 static_assert(std::is_base_of<T, S>::value, "type check");
293 }
294
300 template <class S, class M2>
302 : PersistentBase<T>(PersistentBase<T>::New(isolate, *that)) {
303 static_assert(std::is_base_of<T, S>::value, "type check");
304 }
311 V8_INLINE Persistent(const Persistent& that) : PersistentBase<T>(nullptr) {
312 Copy(that);
313 }
314 template <class S, class M2>
316 Copy(that);
317 }
319 Copy(that);
320 return *this;
321 }
322 template <class S, class M2>
324 Copy(that);
325 return *this;
326 }
333 if (M::kResetInDestructor) this->Reset();
334 }
335
336 // TODO(dcarney): this is pretty useless, fix or remove
337 template <class S>
339#ifdef V8_ENABLE_CHECKS
340 // If we're going to perform the type check then we have to check
341 // that the handle isn't empty before doing the checked cast.
342 if (!that.IsEmpty()) T::Cast(*that);
343#endif
344 return reinterpret_cast<Persistent<T>&>(const_cast<Persistent<S>&>(that));
345 }
346
347 // TODO(dcarney): this is pretty useless, fix or remove
348 template <class S>
350 return Persistent<S>::Cast(*this);
351 }
352
353 private:
354 friend class Isolate;
355 friend class Utils;
356 template <class F>
357 friend class Local;
358 template <class F1, class F2>
359 friend class Persistent;
360 template <class F>
361 friend class ReturnValue;
362
363 explicit V8_INLINE Persistent(T* that) : PersistentBase<T>(that) {}
364 template <class S, class M2>
365 V8_INLINE void Copy(const Persistent<S, M2>& that);
366};
367
373template <class T>
374class Global : public PersistentBase<T> {
375 public:
379 V8_INLINE Global() : PersistentBase<T>(nullptr) {}
380
386 template <class S>
388 : PersistentBase<T>(PersistentBase<T>::New(isolate, that)) {
389 static_assert(std::is_base_of<T, S>::value, "type check");
390 }
391
397 template <class S>
399 : PersistentBase<T>(PersistentBase<T>::New(isolate, that.val_)) {
400 static_assert(std::is_base_of<T, S>::value, "type check");
401 }
402
407
408 V8_INLINE ~Global() { this->Reset(); }
409
413 template <class S>
415
419 Global Pass() { return static_cast<Global&&>(*this); }
420
421 /*
422 * For compatibility with Chromium's base::Bind (base::Passed).
423 */
425
426 Global(const Global&) = delete;
427 void operator=(const Global&) = delete;
428
429 private:
430 template <class F>
431 friend class ReturnValue;
432};
433
434// UniquePersistent is an alias for Global for historical reason.
435template <class T>
437
442 public:
443 virtual ~PersistentHandleVisitor() = default;
445 uint16_t class_id) {}
446};
447
448template <class T>
449T* PersistentBase<T>::New(Isolate* isolate, Local<T> that) {
450 return PersistentBase<T>::New(isolate,
452}
453
454template <class T>
455T* PersistentBase<T>::New(Isolate* isolate, T* that) {
456 if (that == nullptr) return nullptr;
457 internal::Address* p = reinterpret_cast<internal::Address*>(that);
458 return reinterpret_cast<T*>(api_internal::GlobalizeReference(
459 reinterpret_cast<internal::Isolate*>(isolate), p));
460}
461
462template <class T, class M>
463template <class S, class M2>
465 static_assert(std::is_base_of<T, S>::value, "type check");
466 this->Reset();
467 if (that.IsEmpty()) return;
468 internal::Address* p = reinterpret_cast<internal::Address*>(that.val_);
469 this->val_ = reinterpret_cast<T*>(api_internal::CopyGlobalReference(p));
470 M::Copy(that, this);
471}
472
473template <class T>
475 using I = internal::Internals;
476 if (this->IsEmpty()) return false;
477 return I::GetNodeState(reinterpret_cast<internal::Address*>(this->val_)) ==
478 I::kNodeStateIsWeakValue;
479}
480
481template <class T>
483 if (this->IsEmpty()) return;
484 api_internal::DisposeGlobal(reinterpret_cast<internal::Address*>(this->val_));
485 val_ = nullptr;
486}
487
492template <class T>
493template <class S>
494void PersistentBase<T>::Reset(Isolate* isolate, const Local<S>& other) {
495 static_assert(std::is_base_of<T, S>::value, "type check");
496 Reset();
497 if (other.IsEmpty()) return;
498 this->val_ = New(isolate, internal::ValueHelper::ValueAsSlot(*other));
499}
500
505template <class T>
506template <class S>
508 const PersistentBase<S>& other) {
509 static_assert(std::is_base_of<T, S>::value, "type check");
510 Reset();
511 if (other.IsEmpty()) return;
512 this->val_ = New(isolate, other.val_);
513}
514
515template <class T>
516template <typename P>
518 P* parameter, typename WeakCallbackInfo<P>::Callback callback,
519 WeakCallbackType type) {
520 using Callback = WeakCallbackInfo<void>::Callback;
521#if (__GNUC__ >= 8) && !defined(__clang__)
522#pragma GCC diagnostic push
523#pragma GCC diagnostic ignored "-Wcast-function-type"
524#endif
525 api_internal::MakeWeak(reinterpret_cast<internal::Address*>(this->val_),
526 parameter, reinterpret_cast<Callback>(callback), type);
527#if (__GNUC__ >= 8) && !defined(__clang__)
528#pragma GCC diagnostic pop
529#endif
530}
531
532template <class T>
534 api_internal::MakeWeak(reinterpret_cast<internal::Address**>(&this->val_));
535}
536
537template <class T>
538template <typename P>
540 return reinterpret_cast<P*>(api_internal::ClearWeak(
541 reinterpret_cast<internal::Address*>(this->val_)));
542}
543
544template <class T>
547 reinterpret_cast<internal::Address*>(this->val_), label);
548}
549
550template <class T>
552 using I = internal::Internals;
553 if (this->IsEmpty()) return;
554 internal::Address* obj = reinterpret_cast<internal::Address*>(this->val_);
555 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + I::kNodeClassIdOffset;
556 *reinterpret_cast<uint16_t*>(addr) = class_id;
557}
558
559template <class T>
561 using I = internal::Internals;
562 if (this->IsEmpty()) return 0;
563 internal::Address* obj = reinterpret_cast<internal::Address*>(this->val_);
564 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + I::kNodeClassIdOffset;
565 return *reinterpret_cast<uint16_t*>(addr);
566}
567
568template <class T>
569Global<T>::Global(Global&& other) : PersistentBase<T>(other.val_) {
570 if (other.val_ != nullptr) {
572 reinterpret_cast<internal::Address**>(&other.val_),
573 reinterpret_cast<internal::Address**>(&this->val_));
574 other.val_ = nullptr;
575 }
576}
577
578template <class T>
579template <class S>
581 static_assert(std::is_base_of<T, S>::value, "type check");
582 if (this != &rhs) {
583 this->Reset();
584 if (rhs.val_ != nullptr) {
585 this->val_ = rhs.val_;
587 reinterpret_cast<internal::Address**>(&rhs.val_),
588 reinterpret_cast<internal::Address**>(&this->val_));
589 rhs.val_ = nullptr;
590 }
591 }
592 return *this;
593}
594
595} // namespace v8
596
597#endif // INCLUDE_V8_PERSISTENT_HANDLE_H_
V8_INLINE Eternal(Isolate *isolate, Local< S > handle)
V8_INLINE bool IsEmpty() const
void Set(Isolate *isolate, Local< S > handle)
V8_INLINE Local< T > Get(Isolate *isolate) const
V8_INLINE Eternal()
V8_INLINE Global(Isolate *isolate, const PersistentBase< S > &that)
V8_INLINE Global(Isolate *isolate, Local< S > that)
V8_INLINE Global & operator=(Global< S > &&rhs)
Global(const Global &)=delete
void operator=(const Global &)=delete
V8_INLINE ~Global()
V8_INLINE Global(Global &&other)
V8_INLINE bool IsEmpty() const
static V8_INLINE Local< T > New(Isolate *isolate, Local< T > that)
static V8_INLINE void Copy(const Persistent< S, M > &source, NonCopyablePersistent *dest)
V8_INLINE void Reset(Isolate *isolate, const Local< S > &other)
void operator=(const PersistentBase &)=delete
V8_INLINE uint16_t WrapperClassId() const
V8_INLINE bool IsWeak() const
V8_INLINE bool operator!=(const Local< S > &that) const
V8_INLINE bool IsEmpty() const
V8_INLINE bool operator==(const Local< S > &that) const
V8_INLINE P * ClearWeak()
V8_INLINE bool operator!=(const PersistentBase< S > &that) const
PersistentBase(const PersistentBase &other)=delete
V8_INLINE void AnnotateStrongRetainer(const char *label)
V8_INLINE bool operator==(const PersistentBase< S > &that) const
V8_INLINE void Reset(Isolate *isolate, const PersistentBase< S > &other)
V8_INLINE void SetWeak(P *parameter, typename WeakCallbackInfo< P >::Callback callback, WeakCallbackType type)
V8_INLINE void ClearWeak()
V8_INLINE Local< T > Get(Isolate *isolate) const
V8_INLINE void SetWrapperClassId(uint16_t class_id)
virtual void VisitPersistentHandle(Persistent< Value > *value, uint16_t class_id)
virtual ~PersistentHandleVisitor()=default
V8_INLINE Persistent(Isolate *isolate, Local< S > that)
V8_INLINE Persistent< S > & As() const
V8_INLINE Persistent(Isolate *isolate, const Persistent< S, M2 > &that)
V8_INLINE Persistent(const Persistent< S, M2 > &that)
V8_INLINE Persistent(const Persistent &that)
V8_INLINE Persistent & operator=(const Persistent &that)
V8_INLINE Persistent & operator=(const Persistent< S, M2 > &that)
static V8_INLINE Persistent< T > & Cast(const Persistent< S > &that)
void(*)(const WeakCallbackInfo< T > &data) Callback
static V8_INLINE bool EqualHandles(const T1 &lhs, const T2 &rhs)
static V8_INLINE T * ValueAsSlot(T *const &value)
V8_EXPORT void MakeWeak(internal::Address **location_addr)
V8_EXPORT void DisposeGlobal(internal::Address *global_handle)
V8_EXPORT void * ClearWeak(internal::Address *location)
V8_EXPORT internal::Address * CopyGlobalReference(internal::Address *from)
V8_EXPORT internal::Address * GlobalizeReference(internal::Isolate *isolate, internal::Address *handle)
V8_EXPORT Value * Eternalize(v8::Isolate *isolate, Value *handle)
V8_EXPORT void MoveGlobalReference(internal::Address **from, internal::Address **to)
V8_EXPORT void AnnotateStrongRetainer(internal::Address *location, const char *label)
uintptr_t Address
Definition v8-internal.h:29
#define V8_EXPORT
Definition v8config.h:719
#define V8_INLINE
Definition v8config.h:460
#define V8_DEPRECATED(message)
Definition v8config.h:544