Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/node/v8-persistent-handle.h
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 13 namespace v8 { 14 15 class Isolate; 16 template <class K, class V, class T> 17 class PersistentValueMapBase; 18 template <class V, class T> 19 class PersistentValueVector; 20 template <class T> 21 class Global; 22 template <class T> 23 class PersistentBase; 24 template <class K, class V, class T> 25 class PersistentValueMap; 26 class Value; 27 28 namespace api_internal { 29 V8_EXPORT internal::Address* Eternalize(v8::Isolate* isolate, Value* handle); 30 V8_EXPORT internal::Address* CopyGlobalReference(internal::Address* from); 31 V8_EXPORT void DisposeGlobal(internal::Address* global_handle); 32 V8_EXPORT void MakeWeak(internal::Address** location_addr); 33 V8_EXPORT void* ClearWeak(internal::Address* location); 34 V8_EXPORT void AnnotateStrongRetainer(internal::Address* location, 35 const char* label); 36 V8_EXPORT internal::Address* GlobalizeReference(internal::Isolate* isolate, 37 internal::Address value); 38 V8_EXPORT void MoveGlobalReference(internal::Address** from, 39 internal::Address** to); 40 } // namespace api_internal 41 42 /** 43 * Eternal handles are set-once handles that live for the lifetime of the 44 * isolate. 45 */ 46 template <class T> 47 class Eternal : public api_internal::IndirectHandleBase { 48 public: 49 V8_INLINE Eternal() = default; 50 51 template <class S> 52 V8_INLINE Eternal(Isolate* isolate, Local<S> handle) { 53 Set(isolate, handle); 54 } 55 56 // Can only be safely called if already set. 57 V8_INLINE Local<T> Get(Isolate* isolate) const { 58 // The eternal handle will never go away, so as with the roots, we don't 59 // even need to open a handle. 60 return Local<T>::FromSlot(slot()); 61 } 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 slot() = 67 api_internal::Eternalize(isolate, *handle.template UnsafeAs<Value>()); 68 } 69 }; 70 71 namespace api_internal { 72 V8_EXPORT void MakeWeak(internal::Address* location, void* data, 73 WeakCallbackInfo<void>::Callback weak_callback, 74 WeakCallbackType type); 75 } // namespace api_internal 76 77 /** 78 * An object reference that is independent of any handle scope. Where 79 * a Local handle only lives as long as the HandleScope in which it was 80 * allocated, a PersistentBase handle remains valid until it is explicitly 81 * disposed using Reset(). 82 * 83 * A persistent handle contains a reference to a storage cell within 84 * the V8 engine which holds an object value and which is updated by 85 * the garbage collector whenever the object is moved. A new storage 86 * cell can be created using the constructor or PersistentBase::Reset and 87 * existing handles can be disposed using PersistentBase::Reset. 88 * 89 */ 90 template <class T> 91 class PersistentBase : public api_internal::IndirectHandleBase { 92 public: 93 /** 94 * If non-empty, destroy the underlying storage cell 95 * IsEmpty() will return true after this call. 96 */ 97 V8_INLINE void Reset(); 98 99 /** 100 * If non-empty, destroy the underlying storage cell 101 * and create a new one with the contents of other if other is non empty 102 */ 103 template <class S> 104 V8_INLINE void Reset(Isolate* isolate, const Local<S>& other); 105 106 /** 107 * If non-empty, destroy the underlying storage cell 108 * and create a new one with the contents of other if other is non empty 109 */ 110 template <class S> 111 V8_INLINE void Reset(Isolate* isolate, const PersistentBase<S>& other); 112 113 V8_INLINE Local<T> Get(Isolate* isolate) const { 114 return Local<T>::New(isolate, *this); 115 } 116 117 template <class S> 118 V8_INLINE bool operator==(const PersistentBase<S>& that) const { 119 return internal::HandleHelper::EqualHandles(*this, that); 120 } 121 122 template <class S> 123 V8_INLINE bool operator==(const Local<S>& that) const { 124 return internal::HandleHelper::EqualHandles(*this, that); 125 } 126 127 template <class S> 128 V8_INLINE bool operator!=(const PersistentBase<S>& that) const { 129 return !operator==(that); 130 } 131 132 template <class S> 133 V8_INLINE bool operator!=(const Local<S>& that) const { 134 return !operator==(that); 135 } 136 137 /** 138 * Install a finalization callback on this object. 139 * NOTE: There is no guarantee as to *when* or even *if* the callback is 140 * invoked. The invocation is performed solely on a best effort basis. 141 * As always, GC-based finalization should *not* be relied upon for any 142 * critical form of resource management! 143 * 144 * The callback is supposed to reset the handle. No further V8 API may be 145 * called in this callback. In case additional work involving V8 needs to be 146 * done, a second callback can be scheduled using 147 * WeakCallbackInfo<void>::SetSecondPassCallback. 148 */ 149 template <typename P> 150 V8_INLINE void SetWeak(P* parameter, 151 typename WeakCallbackInfo<P>::Callback callback, 152 WeakCallbackType type); 153 154 /** 155 * Turns this handle into a weak phantom handle without finalization callback. 156 * The handle will be reset automatically when the garbage collector detects 157 * that the object is no longer reachable. 158 */ 159 V8_INLINE void SetWeak(); 160 161 template <typename P> 162 V8_INLINE P* ClearWeak(); 163 164 // TODO(dcarney): remove this. 165 V8_INLINE void ClearWeak() { ClearWeak<void>(); } 166 167 /** 168 * Annotates the strong handle with the given label, which is then used by the 169 * heap snapshot generator as a name of the edge from the root to the handle. 170 * The function does not take ownership of the label and assumes that the 171 * label is valid as long as the handle is valid. 172 */ 173 V8_INLINE void AnnotateStrongRetainer(const char* label); 174 175 /** Returns true if the handle's reference is weak. */ 176 V8_INLINE bool IsWeak() const; 177 178 /** 179 * Assigns a wrapper class ID to the handle. 180 */ 181 V8_INLINE void SetWrapperClassId(uint16_t class_id); 182 183 /** 184 * Returns the class ID previously assigned to this handle or 0 if no class ID 185 * was previously assigned. 186 */ 187 V8_INLINE uint16_t WrapperClassId() const; 188 189 PersistentBase(const PersistentBase& other) = delete; 190 void operator=(const PersistentBase&) = delete; 191 192 private: 193 friend class Isolate; 194 friend class Utils; 195 template <class F> 196 friend class Local; 197 template <class F1, class F2> 198 friend class Persistent; 199 template <class F> 200 friend class Global; 201 template <class F> 202 friend class PersistentBase; 203 template <class F> 204 friend class ReturnValue; 205 template <class F1, class F2, class F3> 206 friend class PersistentValueMapBase; 207 template <class F1, class F2> 208 friend class PersistentValueVector; 209 friend class Object; 210 friend class internal::ValueHelper; 211 212 V8_INLINE PersistentBase() = default; 213 214 V8_INLINE explicit PersistentBase(internal::Address* location) 215 : IndirectHandleBase(location) {} 216 217 V8_INLINE static internal::Address* New(Isolate* isolate, T* that); 218 }; 219 220 /** 221 * Default traits for Persistent. This class does not allow 222 * use of the copy constructor or assignment operator. 223 * At present kResetInDestructor is not set, but that will change in a future 224 * version. 225 */ 226 template <class T> 227 class NonCopyablePersistentTraits { 228 public: 229 using NonCopyablePersistent = Persistent<T, NonCopyablePersistentTraits<T>>; 230 static const bool kResetInDestructor = false; 231 template <class S, class M> 232 V8_INLINE static void Copy(const Persistent<S, M>& source, 233 NonCopyablePersistent* dest) { 234 static_assert(sizeof(S) < 0, 235 "NonCopyablePersistentTraits::Copy is not instantiable"); 236 } 237 }; 238 239 /** 240 * Helper class traits to allow copying and assignment of Persistent. 241 * This will clone the contents of storage cell, but not any of the flags, etc. 242 */ 243 template <class T> 244 struct CopyablePersistentTraits { 245 using CopyablePersistent = Persistent<T, CopyablePersistentTraits<T>>; 246 static const bool kResetInDestructor = true; 247 template <class S, class M> 248 static V8_INLINE void Copy(const Persistent<S, M>& source, 249 CopyablePersistent* dest) { 250 // do nothing, just allow copy 251 } 252 }; 253 254 /** 255 * A PersistentBase which allows copy and assignment. 256 * 257 * Copy, assignment and destructor behavior is controlled by the traits 258 * class M. 259 * 260 * CAVEAT: Persistent objects do not have proper destruction behavior by default 261 * and as such will leak the object without explicit clear. Consider using 262 * `v8::Global` instead which has proper destruction and move semantics. 263 */ 264 template <class T, class M> 265 class Persistent : public PersistentBase<T> { 266 public: 267 /** 268 * A Persistent with no storage cell. 269 */ 270 V8_INLINE Persistent() = default; 271 272 /** 273 * Construct a Persistent from a Local. 274 * When the Local is non-empty, a new storage cell is created 275 * pointing to the same object, and no flags are set. 276 */ 277 template <class S> 278 V8_INLINE Persistent(Isolate* isolate, Local<S> that) 279 : PersistentBase<T>( 280 PersistentBase<T>::New(isolate, that.template value<S>())) { 281 static_assert(std::is_base_of<T, S>::value, "type check"); 282 } 283 284 /** 285 * Construct a Persistent from a Persistent. 286 * When the Persistent is non-empty, a new storage cell is created 287 * pointing to the same object, and no flags are set. 288 */ 289 template <class S, class M2> 290 V8_INLINE Persistent(Isolate* isolate, const Persistent<S, M2>& that) 291 : PersistentBase<T>( 292 PersistentBase<T>::New(isolate, that.template value<S>())) { 293 static_assert(std::is_base_of<T, S>::value, "type check"); 294 } 295 296 /** 297 * The copy constructors and assignment operator create a Persistent 298 * exactly as the Persistent constructor, but the Copy function from the 299 * traits class is called, allowing the setting of flags based on the 300 * copied Persistent. 301 */ 302 V8_INLINE Persistent(const Persistent& that) : PersistentBase<T>() { 303 Copy(that); 304 } 305 template <class S, class M2> 306 V8_INLINE Persistent(const Persistent<S, M2>& that) : PersistentBase<T>() { 307 Copy(that); 308 } 309 V8_INLINE Persistent& operator=(const Persistent& that) { 310 Copy(that); 311 return *this; 312 } 313 template <class S, class M2> 314 V8_INLINE Persistent& operator=(const Persistent<S, M2>& that) { 315 Copy(that); 316 return *this; 317 } 318 319 /** 320 * The destructor will dispose the Persistent based on the 321 * kResetInDestructor flags in the traits class. Since not calling dispose 322 * can result in a memory leak, it is recommended to always set this flag. 323 */ 324 V8_INLINE ~Persistent() { 325 if (M::kResetInDestructor) this->Reset(); 326 } 327 328 // TODO(dcarney): this is pretty useless, fix or remove 329 template <class S, class M2> 330 V8_INLINE static Persistent<T, M>& Cast(const Persistent<S, M2>& that) { 331 #ifdef V8_ENABLE_CHECKS 332 // If we're going to perform the type check then we have to check 333 // that the handle isn't empty before doing the checked cast. 334 if (!that.IsEmpty()) T::Cast(that.template value<S>()); 335 #endif 336 return reinterpret_cast<Persistent<T, M>&>( 337 const_cast<Persistent<S, M2>&>(that)); 338 } 339 340 // TODO(dcarney): this is pretty useless, fix or remove 341 template <class S, class M2> 342 V8_INLINE Persistent<S, M2>& As() const { 343 return Persistent<S, M2>::Cast(*this); 344 } 345 346 private: 347 friend class Isolate; 348 friend class Utils; 349 template <class F> 350 friend class Local; 351 template <class F1, class F2> 352 friend class Persistent; 353 template <class F> 354 friend class ReturnValue; 355 356 template <class S, class M2> 357 V8_INLINE void Copy(const Persistent<S, M2>& that); 358 }; 359 360 /** 361 * A PersistentBase which has move semantics. 362 * 363 * Note: Persistent class hierarchy is subject to future changes. 364 */ 365 template <class T> 366 class Global : public PersistentBase<T> { 367 public: 368 /** 369 * A Global with no storage cell. 370 */ 371 V8_INLINE Global() = default; 372 373 /** 374 * Construct a Global from a Local. 375 * When the Local is non-empty, a new storage cell is created 376 * pointing to the same object, and no flags are set. 377 */ 378 template <class S> 379 V8_INLINE Global(Isolate* isolate, Local<S> that) 380 : PersistentBase<T>( 381 PersistentBase<T>::New(isolate, that.template value<S>())) { 382 static_assert(std::is_base_of<T, S>::value, "type check"); 383 } 384 385 /** 386 * Construct a Global from a PersistentBase. 387 * When the Persistent is non-empty, a new storage cell is created 388 * pointing to the same object, and no flags are set. 389 */ 390 template <class S> 391 V8_INLINE Global(Isolate* isolate, const PersistentBase<S>& that) 392 : PersistentBase<T>( 393 PersistentBase<T>::New(isolate, that.template value<S>())) { 394 static_assert(std::is_base_of<T, S>::value, "type check"); 395 } 396 397 /** 398 * Move constructor. 399 */ 400 V8_INLINE Global(Global&& other); 401 402 V8_INLINE ~Global() { this->Reset(); } 403 404 /** 405 * Move via assignment. 406 */ 407 template <class S> 408 V8_INLINE Global& operator=(Global<S>&& rhs); 409 410 /** 411 * Pass allows returning uniques from functions, etc. 412 */ 413 Global Pass() { return static_cast<Global&&>(*this); } 414 415 /* 416 * For compatibility with Chromium's base::Bind (base::Passed). 417 */ 418 using MoveOnlyTypeForCPP03 = void; 419 420 Global(const Global&) = delete; 421 void operator=(const Global&) = delete; 422 423 private: 424 template <class F> 425 friend class ReturnValue; 426 }; 427 428 // UniquePersistent is an alias for Global for historical reason. 429 template <class T> 430 using UniquePersistent = Global<T>; 431 432 /** 433 * Interface for iterating through all the persistent handles in the heap. 434 */ 435 class V8_EXPORT PersistentHandleVisitor { 436 public: 437 virtual ~PersistentHandleVisitor() = default; 438 virtual void VisitPersistentHandle(Persistent<Value>* value, 439 uint16_t class_id) {} 440 }; 441 442 template <class T> 443 internal::Address* PersistentBase<T>::New(Isolate* isolate, T* that) { 444 if (internal::ValueHelper::IsEmpty(that)) return nullptr; 445 return api_internal::GlobalizeReference( 446 reinterpret_cast<internal::Isolate*>(isolate), 447 internal::ValueHelper::ValueAsAddress(that)); 448 } 449 450 template <class T, class M> 451 template <class S, class M2> 452 void Persistent<T, M>::Copy(const Persistent<S, M2>& that) { 453 static_assert(std::is_base_of<T, S>::value, "type check"); 454 this->Reset(); 455 if (that.IsEmpty()) return; 456 this->slot() = api_internal::CopyGlobalReference(that.slot()); 457 M::Copy(that, this); 458 } 459 460 template <class T> 461 bool PersistentBase<T>::IsWeak() const { 462 using I = internal::Internals; 463 if (this->IsEmpty()) return false; 464 return I::GetNodeState(this->slot()) == I::kNodeStateIsWeakValue; 465 } 466 467 template <class T> 468 void PersistentBase<T>::Reset() { 469 if (this->IsEmpty()) return; 470 api_internal::DisposeGlobal(this->slot()); 471 this->Clear(); 472 } 473 474 /** 475 * If non-empty, destroy the underlying storage cell 476 * and create a new one with the contents of other if other is non empty 477 */ 478 template <class T> 479 template <class S> 480 void PersistentBase<T>::Reset(Isolate* isolate, const Local<S>& other) { 481 static_assert(std::is_base_of<T, S>::value, "type check"); 482 Reset(); 483 if (other.IsEmpty()) return; 484 this->slot() = New(isolate, *other); 485 } 486 487 /** 488 * If non-empty, destroy the underlying storage cell 489 * and create a new one with the contents of other if other is non empty 490 */ 491 template <class T> 492 template <class S> 493 void PersistentBase<T>::Reset(Isolate* isolate, 494 const PersistentBase<S>& other) { 495 static_assert(std::is_base_of<T, S>::value, "type check"); 496 Reset(); 497 if (other.IsEmpty()) return; 498 this->slot() = New(isolate, other.template value<S>()); 499 } 500 501 template <class T> 502 template <typename P> 503 V8_INLINE void PersistentBase<T>::SetWeak( 504 P* parameter, typename WeakCallbackInfo<P>::Callback callback, 505 WeakCallbackType type) { 506 using Callback = WeakCallbackInfo<void>::Callback; 507 #if (__GNUC__ >= 8) && !defined(__clang__) 508 #pragma GCC diagnostic push 509 #pragma GCC diagnostic ignored "-Wcast-function-type" 510 #endif 511 #if __clang__ 512 #pragma clang diagnostic push 513 #pragma clang diagnostic ignored "-Wcast-function-type" 514 #endif 515 api_internal::MakeWeak(this->slot(), parameter, 516 reinterpret_cast<Callback>(callback), type); 517 #if __clang__ 518 #pragma clang diagnostic pop 519 #endif 520 #if (__GNUC__ >= 8) && !defined(__clang__) 521 #pragma GCC diagnostic pop 522 #endif 523 } 524 525 template <class T> 526 void PersistentBase<T>::SetWeak() { 527 api_internal::MakeWeak(&this->slot()); 528 } 529 530 template <class T> 531 template <typename P> 532 P* PersistentBase<T>::ClearWeak() { 533 return reinterpret_cast<P*>(api_internal::ClearWeak(this->slot())); 534 } 535 536 template <class T> 537 void PersistentBase<T>::AnnotateStrongRetainer(const char* label) { 538 api_internal::AnnotateStrongRetainer(this->slot(), label); 539 } 540 541 template <class T> 542 void PersistentBase<T>::SetWrapperClassId(uint16_t class_id) { 543 using I = internal::Internals; 544 if (this->IsEmpty()) return; 545 uint8_t* addr = reinterpret_cast<uint8_t*>(slot()) + I::kNodeClassIdOffset; 546 *reinterpret_cast<uint16_t*>(addr) = class_id; 547 } 548 549 template <class T> 550 uint16_t PersistentBase<T>::WrapperClassId() const { 551 using I = internal::Internals; 552 if (this->IsEmpty()) return 0; 553 uint8_t* addr = reinterpret_cast<uint8_t*>(slot()) + I::kNodeClassIdOffset; 554 return *reinterpret_cast<uint16_t*>(addr); 555 } 556 557 template <class T> 558 Global<T>::Global(Global&& other) : PersistentBase<T>(other.slot()) { 559 if (!other.IsEmpty()) { 560 api_internal::MoveGlobalReference(&other.slot(), &this->slot()); 561 other.Clear(); 562 } 563 } 564 565 template <class T> 566 template <class S> 567 Global<T>& Global<T>::operator=(Global<S>&& rhs) { 568 static_assert(std::is_base_of<T, S>::value, "type check"); 569 if (this != &rhs) { 570 this->Reset(); 571 if (!rhs.IsEmpty()) { 572 this->slot() = rhs.slot(); 573 api_internal::MoveGlobalReference(&rhs.slot(), &this->slot()); 574 rhs.Clear(); 575 } 576 } 577 return *this; 578 } 579 580 } // namespace v8 581 582 #endif // INCLUDE_V8_PERSISTENT_HANDLE_H_