11cb0ef41Sopenharmony_ci// Copyright 2021 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef INCLUDE_V8_PERSISTENT_HANDLE_H_
61cb0ef41Sopenharmony_ci#define INCLUDE_V8_PERSISTENT_HANDLE_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "v8-internal.h"            // NOLINT(build/include_directory)
91cb0ef41Sopenharmony_ci#include "v8-local-handle.h"        // NOLINT(build/include_directory)
101cb0ef41Sopenharmony_ci#include "v8-weak-callback-info.h"  // NOLINT(build/include_directory)
111cb0ef41Sopenharmony_ci#include "v8config.h"               // NOLINT(build/include_directory)
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cinamespace v8 {
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciclass Isolate;
161cb0ef41Sopenharmony_citemplate <class K, class V, class T>
171cb0ef41Sopenharmony_ciclass PersistentValueMapBase;
181cb0ef41Sopenharmony_citemplate <class V, class T>
191cb0ef41Sopenharmony_ciclass PersistentValueVector;
201cb0ef41Sopenharmony_citemplate <class T>
211cb0ef41Sopenharmony_ciclass Global;
221cb0ef41Sopenharmony_citemplate <class T>
231cb0ef41Sopenharmony_ciclass PersistentBase;
241cb0ef41Sopenharmony_citemplate <class K, class V, class T>
251cb0ef41Sopenharmony_ciclass PersistentValueMap;
261cb0ef41Sopenharmony_ciclass Value;
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_cinamespace api_internal {
291cb0ef41Sopenharmony_ciV8_EXPORT Value* Eternalize(v8::Isolate* isolate, Value* handle);
301cb0ef41Sopenharmony_ciV8_EXPORT internal::Address* CopyGlobalReference(internal::Address* from);
311cb0ef41Sopenharmony_ciV8_EXPORT void DisposeGlobal(internal::Address* global_handle);
321cb0ef41Sopenharmony_ciV8_EXPORT void MakeWeak(internal::Address** location_addr);
331cb0ef41Sopenharmony_ciV8_EXPORT void* ClearWeak(internal::Address* location);
341cb0ef41Sopenharmony_ciV8_EXPORT void AnnotateStrongRetainer(internal::Address* location,
351cb0ef41Sopenharmony_ci                                      const char* label);
361cb0ef41Sopenharmony_ciV8_EXPORT internal::Address* GlobalizeReference(internal::Isolate* isolate,
371cb0ef41Sopenharmony_ci                                                internal::Address* handle);
381cb0ef41Sopenharmony_ciV8_EXPORT void MoveGlobalReference(internal::Address** from,
391cb0ef41Sopenharmony_ci                                   internal::Address** to);
401cb0ef41Sopenharmony_ci}  // namespace api_internal
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci/**
431cb0ef41Sopenharmony_ci * Eternal handles are set-once handles that live for the lifetime of the
441cb0ef41Sopenharmony_ci * isolate.
451cb0ef41Sopenharmony_ci */
461cb0ef41Sopenharmony_citemplate <class T>
471cb0ef41Sopenharmony_ciclass Eternal {
481cb0ef41Sopenharmony_ci public:
491cb0ef41Sopenharmony_ci  V8_INLINE Eternal() : val_(nullptr) {}
501cb0ef41Sopenharmony_ci  template <class S>
511cb0ef41Sopenharmony_ci  V8_INLINE Eternal(Isolate* isolate, Local<S> handle) : val_(nullptr) {
521cb0ef41Sopenharmony_ci    Set(isolate, handle);
531cb0ef41Sopenharmony_ci  }
541cb0ef41Sopenharmony_ci  // Can only be safely called if already set.
551cb0ef41Sopenharmony_ci  V8_INLINE Local<T> Get(Isolate* isolate) const {
561cb0ef41Sopenharmony_ci    // The eternal handle will never go away, so as with the roots, we don't
571cb0ef41Sopenharmony_ci    // even need to open a handle.
581cb0ef41Sopenharmony_ci    return Local<T>(val_);
591cb0ef41Sopenharmony_ci  }
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  V8_INLINE bool IsEmpty() const { return val_ == nullptr; }
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci  template <class S>
641cb0ef41Sopenharmony_ci  void Set(Isolate* isolate, Local<S> handle) {
651cb0ef41Sopenharmony_ci    static_assert(std::is_base_of<T, S>::value, "type check");
661cb0ef41Sopenharmony_ci    val_ = reinterpret_cast<T*>(
671cb0ef41Sopenharmony_ci        api_internal::Eternalize(isolate, reinterpret_cast<Value*>(*handle)));
681cb0ef41Sopenharmony_ci  }
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci private:
711cb0ef41Sopenharmony_ci  T* val_;
721cb0ef41Sopenharmony_ci};
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_cinamespace api_internal {
751cb0ef41Sopenharmony_ciV8_EXPORT void MakeWeak(internal::Address* location, void* data,
761cb0ef41Sopenharmony_ci                        WeakCallbackInfo<void>::Callback weak_callback,
771cb0ef41Sopenharmony_ci                        WeakCallbackType type);
781cb0ef41Sopenharmony_ci}  // namespace api_internal
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci/**
811cb0ef41Sopenharmony_ci * An object reference that is independent of any handle scope.  Where
821cb0ef41Sopenharmony_ci * a Local handle only lives as long as the HandleScope in which it was
831cb0ef41Sopenharmony_ci * allocated, a PersistentBase handle remains valid until it is explicitly
841cb0ef41Sopenharmony_ci * disposed using Reset().
851cb0ef41Sopenharmony_ci *
861cb0ef41Sopenharmony_ci * A persistent handle contains a reference to a storage cell within
871cb0ef41Sopenharmony_ci * the V8 engine which holds an object value and which is updated by
881cb0ef41Sopenharmony_ci * the garbage collector whenever the object is moved.  A new storage
891cb0ef41Sopenharmony_ci * cell can be created using the constructor or PersistentBase::Reset and
901cb0ef41Sopenharmony_ci * existing handles can be disposed using PersistentBase::Reset.
911cb0ef41Sopenharmony_ci *
921cb0ef41Sopenharmony_ci */
931cb0ef41Sopenharmony_citemplate <class T>
941cb0ef41Sopenharmony_ciclass PersistentBase {
951cb0ef41Sopenharmony_ci public:
961cb0ef41Sopenharmony_ci  /**
971cb0ef41Sopenharmony_ci   * If non-empty, destroy the underlying storage cell
981cb0ef41Sopenharmony_ci   * IsEmpty() will return true after this call.
991cb0ef41Sopenharmony_ci   */
1001cb0ef41Sopenharmony_ci  V8_INLINE void Reset();
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  /**
1031cb0ef41Sopenharmony_ci   * If non-empty, destroy the underlying storage cell
1041cb0ef41Sopenharmony_ci   * and create a new one with the contents of other if other is non empty
1051cb0ef41Sopenharmony_ci   */
1061cb0ef41Sopenharmony_ci  template <class S>
1071cb0ef41Sopenharmony_ci  V8_INLINE void Reset(Isolate* isolate, const Local<S>& other);
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  /**
1101cb0ef41Sopenharmony_ci   * If non-empty, destroy the underlying storage cell
1111cb0ef41Sopenharmony_ci   * and create a new one with the contents of other if other is non empty
1121cb0ef41Sopenharmony_ci   */
1131cb0ef41Sopenharmony_ci  template <class S>
1141cb0ef41Sopenharmony_ci  V8_INLINE void Reset(Isolate* isolate, const PersistentBase<S>& other);
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci  V8_INLINE bool IsEmpty() const { return val_ == nullptr; }
1171cb0ef41Sopenharmony_ci  V8_INLINE void Empty() { val_ = 0; }
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  V8_INLINE Local<T> Get(Isolate* isolate) const {
1201cb0ef41Sopenharmony_ci    return Local<T>::New(isolate, *this);
1211cb0ef41Sopenharmony_ci  }
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  template <class S>
1241cb0ef41Sopenharmony_ci  V8_INLINE bool operator==(const PersistentBase<S>& that) const {
1251cb0ef41Sopenharmony_ci    internal::Address* a = reinterpret_cast<internal::Address*>(this->val_);
1261cb0ef41Sopenharmony_ci    internal::Address* b = reinterpret_cast<internal::Address*>(that.val_);
1271cb0ef41Sopenharmony_ci    if (a == nullptr) return b == nullptr;
1281cb0ef41Sopenharmony_ci    if (b == nullptr) return false;
1291cb0ef41Sopenharmony_ci    return *a == *b;
1301cb0ef41Sopenharmony_ci  }
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  template <class S>
1331cb0ef41Sopenharmony_ci  V8_INLINE bool operator==(const Local<S>& that) const {
1341cb0ef41Sopenharmony_ci    internal::Address* a = reinterpret_cast<internal::Address*>(this->val_);
1351cb0ef41Sopenharmony_ci    internal::Address* b = reinterpret_cast<internal::Address*>(that.val_);
1361cb0ef41Sopenharmony_ci    if (a == nullptr) return b == nullptr;
1371cb0ef41Sopenharmony_ci    if (b == nullptr) return false;
1381cb0ef41Sopenharmony_ci    return *a == *b;
1391cb0ef41Sopenharmony_ci  }
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci  template <class S>
1421cb0ef41Sopenharmony_ci  V8_INLINE bool operator!=(const PersistentBase<S>& that) const {
1431cb0ef41Sopenharmony_ci    return !operator==(that);
1441cb0ef41Sopenharmony_ci  }
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  template <class S>
1471cb0ef41Sopenharmony_ci  V8_INLINE bool operator!=(const Local<S>& that) const {
1481cb0ef41Sopenharmony_ci    return !operator==(that);
1491cb0ef41Sopenharmony_ci  }
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  /**
1521cb0ef41Sopenharmony_ci   * Install a finalization callback on this object.
1531cb0ef41Sopenharmony_ci   * NOTE: There is no guarantee as to *when* or even *if* the callback is
1541cb0ef41Sopenharmony_ci   * invoked. The invocation is performed solely on a best effort basis.
1551cb0ef41Sopenharmony_ci   * As always, GC-based finalization should *not* be relied upon for any
1561cb0ef41Sopenharmony_ci   * critical form of resource management!
1571cb0ef41Sopenharmony_ci   *
1581cb0ef41Sopenharmony_ci   * The callback is supposed to reset the handle. No further V8 API may be
1591cb0ef41Sopenharmony_ci   * called in this callback. In case additional work involving V8 needs to be
1601cb0ef41Sopenharmony_ci   * done, a second callback can be scheduled using
1611cb0ef41Sopenharmony_ci   * WeakCallbackInfo<void>::SetSecondPassCallback.
1621cb0ef41Sopenharmony_ci   */
1631cb0ef41Sopenharmony_ci  template <typename P>
1641cb0ef41Sopenharmony_ci  V8_INLINE void SetWeak(P* parameter,
1651cb0ef41Sopenharmony_ci                         typename WeakCallbackInfo<P>::Callback callback,
1661cb0ef41Sopenharmony_ci                         WeakCallbackType type);
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci  /**
1691cb0ef41Sopenharmony_ci   * Turns this handle into a weak phantom handle without finalization callback.
1701cb0ef41Sopenharmony_ci   * The handle will be reset automatically when the garbage collector detects
1711cb0ef41Sopenharmony_ci   * that the object is no longer reachable.
1721cb0ef41Sopenharmony_ci   * A related function Isolate::NumberOfPhantomHandleResetsSinceLastCall
1731cb0ef41Sopenharmony_ci   * returns how many phantom handles were reset by the garbage collector.
1741cb0ef41Sopenharmony_ci   */
1751cb0ef41Sopenharmony_ci  V8_INLINE void SetWeak();
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  template <typename P>
1781cb0ef41Sopenharmony_ci  V8_INLINE P* ClearWeak();
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  // TODO(dcarney): remove this.
1811cb0ef41Sopenharmony_ci  V8_INLINE void ClearWeak() { ClearWeak<void>(); }
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci  /**
1841cb0ef41Sopenharmony_ci   * Annotates the strong handle with the given label, which is then used by the
1851cb0ef41Sopenharmony_ci   * heap snapshot generator as a name of the edge from the root to the handle.
1861cb0ef41Sopenharmony_ci   * The function does not take ownership of the label and assumes that the
1871cb0ef41Sopenharmony_ci   * label is valid as long as the handle is valid.
1881cb0ef41Sopenharmony_ci   */
1891cb0ef41Sopenharmony_ci  V8_INLINE void AnnotateStrongRetainer(const char* label);
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci  /** Returns true if the handle's reference is weak.  */
1921cb0ef41Sopenharmony_ci  V8_INLINE bool IsWeak() const;
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  /**
1951cb0ef41Sopenharmony_ci   * Assigns a wrapper class ID to the handle.
1961cb0ef41Sopenharmony_ci   */
1971cb0ef41Sopenharmony_ci  V8_INLINE void SetWrapperClassId(uint16_t class_id);
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci  /**
2001cb0ef41Sopenharmony_ci   * Returns the class ID previously assigned to this handle or 0 if no class ID
2011cb0ef41Sopenharmony_ci   * was previously assigned.
2021cb0ef41Sopenharmony_ci   */
2031cb0ef41Sopenharmony_ci  V8_INLINE uint16_t WrapperClassId() const;
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  PersistentBase(const PersistentBase& other) = delete;
2061cb0ef41Sopenharmony_ci  void operator=(const PersistentBase&) = delete;
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci private:
2091cb0ef41Sopenharmony_ci  friend class Isolate;
2101cb0ef41Sopenharmony_ci  friend class Utils;
2111cb0ef41Sopenharmony_ci  template <class F>
2121cb0ef41Sopenharmony_ci  friend class Local;
2131cb0ef41Sopenharmony_ci  template <class F1, class F2>
2141cb0ef41Sopenharmony_ci  friend class Persistent;
2151cb0ef41Sopenharmony_ci  template <class F>
2161cb0ef41Sopenharmony_ci  friend class Global;
2171cb0ef41Sopenharmony_ci  template <class F>
2181cb0ef41Sopenharmony_ci  friend class PersistentBase;
2191cb0ef41Sopenharmony_ci  template <class F>
2201cb0ef41Sopenharmony_ci  friend class ReturnValue;
2211cb0ef41Sopenharmony_ci  template <class F1, class F2, class F3>
2221cb0ef41Sopenharmony_ci  friend class PersistentValueMapBase;
2231cb0ef41Sopenharmony_ci  template <class F1, class F2>
2241cb0ef41Sopenharmony_ci  friend class PersistentValueVector;
2251cb0ef41Sopenharmony_ci  friend class Object;
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci  explicit V8_INLINE PersistentBase(T* val) : val_(val) {}
2281cb0ef41Sopenharmony_ci  V8_INLINE static T* New(Isolate* isolate, T* that);
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci  T* val_;
2311cb0ef41Sopenharmony_ci};
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci/**
2341cb0ef41Sopenharmony_ci * Default traits for Persistent. This class does not allow
2351cb0ef41Sopenharmony_ci * use of the copy constructor or assignment operator.
2361cb0ef41Sopenharmony_ci * At present kResetInDestructor is not set, but that will change in a future
2371cb0ef41Sopenharmony_ci * version.
2381cb0ef41Sopenharmony_ci */
2391cb0ef41Sopenharmony_citemplate <class T>
2401cb0ef41Sopenharmony_ciclass NonCopyablePersistentTraits {
2411cb0ef41Sopenharmony_ci public:
2421cb0ef41Sopenharmony_ci  using NonCopyablePersistent = Persistent<T, NonCopyablePersistentTraits<T>>;
2431cb0ef41Sopenharmony_ci  static const bool kResetInDestructor = false;
2441cb0ef41Sopenharmony_ci  template <class S, class M>
2451cb0ef41Sopenharmony_ci  V8_INLINE static void Copy(const Persistent<S, M>& source,
2461cb0ef41Sopenharmony_ci                             NonCopyablePersistent* dest) {
2471cb0ef41Sopenharmony_ci    static_assert(sizeof(S) < 0,
2481cb0ef41Sopenharmony_ci                  "NonCopyablePersistentTraits::Copy is not instantiable");
2491cb0ef41Sopenharmony_ci  }
2501cb0ef41Sopenharmony_ci};
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ci/**
2531cb0ef41Sopenharmony_ci * Helper class traits to allow copying and assignment of Persistent.
2541cb0ef41Sopenharmony_ci * This will clone the contents of storage cell, but not any of the flags, etc.
2551cb0ef41Sopenharmony_ci */
2561cb0ef41Sopenharmony_citemplate <class T>
2571cb0ef41Sopenharmony_cistruct CopyablePersistentTraits {
2581cb0ef41Sopenharmony_ci  using CopyablePersistent = Persistent<T, CopyablePersistentTraits<T>>;
2591cb0ef41Sopenharmony_ci  static const bool kResetInDestructor = true;
2601cb0ef41Sopenharmony_ci  template <class S, class M>
2611cb0ef41Sopenharmony_ci  static V8_INLINE void Copy(const Persistent<S, M>& source,
2621cb0ef41Sopenharmony_ci                             CopyablePersistent* dest) {
2631cb0ef41Sopenharmony_ci    // do nothing, just allow copy
2641cb0ef41Sopenharmony_ci  }
2651cb0ef41Sopenharmony_ci};
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci/**
2681cb0ef41Sopenharmony_ci * A PersistentBase which allows copy and assignment.
2691cb0ef41Sopenharmony_ci *
2701cb0ef41Sopenharmony_ci * Copy, assignment and destructor behavior is controlled by the traits
2711cb0ef41Sopenharmony_ci * class M.
2721cb0ef41Sopenharmony_ci *
2731cb0ef41Sopenharmony_ci * Note: Persistent class hierarchy is subject to future changes.
2741cb0ef41Sopenharmony_ci */
2751cb0ef41Sopenharmony_citemplate <class T, class M>
2761cb0ef41Sopenharmony_ciclass Persistent : public PersistentBase<T> {
2771cb0ef41Sopenharmony_ci public:
2781cb0ef41Sopenharmony_ci  /**
2791cb0ef41Sopenharmony_ci   * A Persistent with no storage cell.
2801cb0ef41Sopenharmony_ci   */
2811cb0ef41Sopenharmony_ci  V8_INLINE Persistent() : PersistentBase<T>(nullptr) {}
2821cb0ef41Sopenharmony_ci  /**
2831cb0ef41Sopenharmony_ci   * Construct a Persistent from a Local.
2841cb0ef41Sopenharmony_ci   * When the Local is non-empty, a new storage cell is created
2851cb0ef41Sopenharmony_ci   * pointing to the same object, and no flags are set.
2861cb0ef41Sopenharmony_ci   */
2871cb0ef41Sopenharmony_ci  template <class S>
2881cb0ef41Sopenharmony_ci  V8_INLINE Persistent(Isolate* isolate, Local<S> that)
2891cb0ef41Sopenharmony_ci      : PersistentBase<T>(PersistentBase<T>::New(isolate, *that)) {
2901cb0ef41Sopenharmony_ci    static_assert(std::is_base_of<T, S>::value, "type check");
2911cb0ef41Sopenharmony_ci  }
2921cb0ef41Sopenharmony_ci  /**
2931cb0ef41Sopenharmony_ci   * Construct a Persistent from a Persistent.
2941cb0ef41Sopenharmony_ci   * When the Persistent is non-empty, a new storage cell is created
2951cb0ef41Sopenharmony_ci   * pointing to the same object, and no flags are set.
2961cb0ef41Sopenharmony_ci   */
2971cb0ef41Sopenharmony_ci  template <class S, class M2>
2981cb0ef41Sopenharmony_ci  V8_INLINE Persistent(Isolate* isolate, const Persistent<S, M2>& that)
2991cb0ef41Sopenharmony_ci      : PersistentBase<T>(PersistentBase<T>::New(isolate, *that)) {
3001cb0ef41Sopenharmony_ci    static_assert(std::is_base_of<T, S>::value, "type check");
3011cb0ef41Sopenharmony_ci  }
3021cb0ef41Sopenharmony_ci  /**
3031cb0ef41Sopenharmony_ci   * The copy constructors and assignment operator create a Persistent
3041cb0ef41Sopenharmony_ci   * exactly as the Persistent constructor, but the Copy function from the
3051cb0ef41Sopenharmony_ci   * traits class is called, allowing the setting of flags based on the
3061cb0ef41Sopenharmony_ci   * copied Persistent.
3071cb0ef41Sopenharmony_ci   */
3081cb0ef41Sopenharmony_ci  V8_INLINE Persistent(const Persistent& that) : PersistentBase<T>(nullptr) {
3091cb0ef41Sopenharmony_ci    Copy(that);
3101cb0ef41Sopenharmony_ci  }
3111cb0ef41Sopenharmony_ci  template <class S, class M2>
3121cb0ef41Sopenharmony_ci  V8_INLINE Persistent(const Persistent<S, M2>& that) : PersistentBase<T>(0) {
3131cb0ef41Sopenharmony_ci    Copy(that);
3141cb0ef41Sopenharmony_ci  }
3151cb0ef41Sopenharmony_ci  V8_INLINE Persistent& operator=(const Persistent& that) {
3161cb0ef41Sopenharmony_ci    Copy(that);
3171cb0ef41Sopenharmony_ci    return *this;
3181cb0ef41Sopenharmony_ci  }
3191cb0ef41Sopenharmony_ci  template <class S, class M2>
3201cb0ef41Sopenharmony_ci  V8_INLINE Persistent& operator=(const Persistent<S, M2>& that) {
3211cb0ef41Sopenharmony_ci    Copy(that);
3221cb0ef41Sopenharmony_ci    return *this;
3231cb0ef41Sopenharmony_ci  }
3241cb0ef41Sopenharmony_ci  /**
3251cb0ef41Sopenharmony_ci   * The destructor will dispose the Persistent based on the
3261cb0ef41Sopenharmony_ci   * kResetInDestructor flags in the traits class.  Since not calling dispose
3271cb0ef41Sopenharmony_ci   * can result in a memory leak, it is recommended to always set this flag.
3281cb0ef41Sopenharmony_ci   */
3291cb0ef41Sopenharmony_ci  V8_INLINE ~Persistent() {
3301cb0ef41Sopenharmony_ci    if (M::kResetInDestructor) this->Reset();
3311cb0ef41Sopenharmony_ci  }
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci  // TODO(dcarney): this is pretty useless, fix or remove
3341cb0ef41Sopenharmony_ci  template <class S>
3351cb0ef41Sopenharmony_ci  V8_INLINE static Persistent<T>& Cast(const Persistent<S>& that) {
3361cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_CHECKS
3371cb0ef41Sopenharmony_ci    // If we're going to perform the type check then we have to check
3381cb0ef41Sopenharmony_ci    // that the handle isn't empty before doing the checked cast.
3391cb0ef41Sopenharmony_ci    if (!that.IsEmpty()) T::Cast(*that);
3401cb0ef41Sopenharmony_ci#endif
3411cb0ef41Sopenharmony_ci    return reinterpret_cast<Persistent<T>&>(const_cast<Persistent<S>&>(that));
3421cb0ef41Sopenharmony_ci  }
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ci  // TODO(dcarney): this is pretty useless, fix or remove
3451cb0ef41Sopenharmony_ci  template <class S>
3461cb0ef41Sopenharmony_ci  V8_INLINE Persistent<S>& As() const {
3471cb0ef41Sopenharmony_ci    return Persistent<S>::Cast(*this);
3481cb0ef41Sopenharmony_ci  }
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_ci private:
3511cb0ef41Sopenharmony_ci  friend class Isolate;
3521cb0ef41Sopenharmony_ci  friend class Utils;
3531cb0ef41Sopenharmony_ci  template <class F>
3541cb0ef41Sopenharmony_ci  friend class Local;
3551cb0ef41Sopenharmony_ci  template <class F1, class F2>
3561cb0ef41Sopenharmony_ci  friend class Persistent;
3571cb0ef41Sopenharmony_ci  template <class F>
3581cb0ef41Sopenharmony_ci  friend class ReturnValue;
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci  explicit V8_INLINE Persistent(T* that) : PersistentBase<T>(that) {}
3611cb0ef41Sopenharmony_ci  V8_INLINE T* operator*() const { return this->val_; }
3621cb0ef41Sopenharmony_ci  template <class S, class M2>
3631cb0ef41Sopenharmony_ci  V8_INLINE void Copy(const Persistent<S, M2>& that);
3641cb0ef41Sopenharmony_ci};
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci/**
3671cb0ef41Sopenharmony_ci * A PersistentBase which has move semantics.
3681cb0ef41Sopenharmony_ci *
3691cb0ef41Sopenharmony_ci * Note: Persistent class hierarchy is subject to future changes.
3701cb0ef41Sopenharmony_ci */
3711cb0ef41Sopenharmony_citemplate <class T>
3721cb0ef41Sopenharmony_ciclass Global : public PersistentBase<T> {
3731cb0ef41Sopenharmony_ci public:
3741cb0ef41Sopenharmony_ci  /**
3751cb0ef41Sopenharmony_ci   * A Global with no storage cell.
3761cb0ef41Sopenharmony_ci   */
3771cb0ef41Sopenharmony_ci  V8_INLINE Global() : PersistentBase<T>(nullptr) {}
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci  /**
3801cb0ef41Sopenharmony_ci   * Construct a Global from a Local.
3811cb0ef41Sopenharmony_ci   * When the Local is non-empty, a new storage cell is created
3821cb0ef41Sopenharmony_ci   * pointing to the same object, and no flags are set.
3831cb0ef41Sopenharmony_ci   */
3841cb0ef41Sopenharmony_ci  template <class S>
3851cb0ef41Sopenharmony_ci  V8_INLINE Global(Isolate* isolate, Local<S> that)
3861cb0ef41Sopenharmony_ci      : PersistentBase<T>(PersistentBase<T>::New(isolate, *that)) {
3871cb0ef41Sopenharmony_ci    static_assert(std::is_base_of<T, S>::value, "type check");
3881cb0ef41Sopenharmony_ci  }
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_ci  /**
3911cb0ef41Sopenharmony_ci   * Construct a Global from a PersistentBase.
3921cb0ef41Sopenharmony_ci   * When the Persistent is non-empty, a new storage cell is created
3931cb0ef41Sopenharmony_ci   * pointing to the same object, and no flags are set.
3941cb0ef41Sopenharmony_ci   */
3951cb0ef41Sopenharmony_ci  template <class S>
3961cb0ef41Sopenharmony_ci  V8_INLINE Global(Isolate* isolate, const PersistentBase<S>& that)
3971cb0ef41Sopenharmony_ci      : PersistentBase<T>(PersistentBase<T>::New(isolate, that.val_)) {
3981cb0ef41Sopenharmony_ci    static_assert(std::is_base_of<T, S>::value, "type check");
3991cb0ef41Sopenharmony_ci  }
4001cb0ef41Sopenharmony_ci
4011cb0ef41Sopenharmony_ci  /**
4021cb0ef41Sopenharmony_ci   * Move constructor.
4031cb0ef41Sopenharmony_ci   */
4041cb0ef41Sopenharmony_ci  V8_INLINE Global(Global&& other);
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci  V8_INLINE ~Global() { this->Reset(); }
4071cb0ef41Sopenharmony_ci
4081cb0ef41Sopenharmony_ci  /**
4091cb0ef41Sopenharmony_ci   * Move via assignment.
4101cb0ef41Sopenharmony_ci   */
4111cb0ef41Sopenharmony_ci  template <class S>
4121cb0ef41Sopenharmony_ci  V8_INLINE Global& operator=(Global<S>&& rhs);
4131cb0ef41Sopenharmony_ci
4141cb0ef41Sopenharmony_ci  /**
4151cb0ef41Sopenharmony_ci   * Pass allows returning uniques from functions, etc.
4161cb0ef41Sopenharmony_ci   */
4171cb0ef41Sopenharmony_ci  Global Pass() { return static_cast<Global&&>(*this); }
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci  /*
4201cb0ef41Sopenharmony_ci   * For compatibility with Chromium's base::Bind (base::Passed).
4211cb0ef41Sopenharmony_ci   */
4221cb0ef41Sopenharmony_ci  using MoveOnlyTypeForCPP03 = void;
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_ci  Global(const Global&) = delete;
4251cb0ef41Sopenharmony_ci  void operator=(const Global&) = delete;
4261cb0ef41Sopenharmony_ci
4271cb0ef41Sopenharmony_ci private:
4281cb0ef41Sopenharmony_ci  template <class F>
4291cb0ef41Sopenharmony_ci  friend class ReturnValue;
4301cb0ef41Sopenharmony_ci  V8_INLINE T* operator*() const { return this->val_; }
4311cb0ef41Sopenharmony_ci};
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_ci// UniquePersistent is an alias for Global for historical reason.
4341cb0ef41Sopenharmony_citemplate <class T>
4351cb0ef41Sopenharmony_ciusing UniquePersistent = Global<T>;
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_ci/**
4381cb0ef41Sopenharmony_ci * Interface for iterating through all the persistent handles in the heap.
4391cb0ef41Sopenharmony_ci */
4401cb0ef41Sopenharmony_ciclass V8_EXPORT PersistentHandleVisitor {
4411cb0ef41Sopenharmony_ci public:
4421cb0ef41Sopenharmony_ci  virtual ~PersistentHandleVisitor() = default;
4431cb0ef41Sopenharmony_ci  virtual void VisitPersistentHandle(Persistent<Value>* value,
4441cb0ef41Sopenharmony_ci                                     uint16_t class_id) {}
4451cb0ef41Sopenharmony_ci};
4461cb0ef41Sopenharmony_ci
4471cb0ef41Sopenharmony_citemplate <class T>
4481cb0ef41Sopenharmony_ciT* PersistentBase<T>::New(Isolate* isolate, T* that) {
4491cb0ef41Sopenharmony_ci  if (that == nullptr) return nullptr;
4501cb0ef41Sopenharmony_ci  internal::Address* p = reinterpret_cast<internal::Address*>(that);
4511cb0ef41Sopenharmony_ci  return reinterpret_cast<T*>(api_internal::GlobalizeReference(
4521cb0ef41Sopenharmony_ci      reinterpret_cast<internal::Isolate*>(isolate), p));
4531cb0ef41Sopenharmony_ci}
4541cb0ef41Sopenharmony_ci
4551cb0ef41Sopenharmony_citemplate <class T, class M>
4561cb0ef41Sopenharmony_citemplate <class S, class M2>
4571cb0ef41Sopenharmony_civoid Persistent<T, M>::Copy(const Persistent<S, M2>& that) {
4581cb0ef41Sopenharmony_ci  static_assert(std::is_base_of<T, S>::value, "type check");
4591cb0ef41Sopenharmony_ci  this->Reset();
4601cb0ef41Sopenharmony_ci  if (that.IsEmpty()) return;
4611cb0ef41Sopenharmony_ci  internal::Address* p = reinterpret_cast<internal::Address*>(that.val_);
4621cb0ef41Sopenharmony_ci  this->val_ = reinterpret_cast<T*>(api_internal::CopyGlobalReference(p));
4631cb0ef41Sopenharmony_ci  M::Copy(that, this);
4641cb0ef41Sopenharmony_ci}
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_citemplate <class T>
4671cb0ef41Sopenharmony_cibool PersistentBase<T>::IsWeak() const {
4681cb0ef41Sopenharmony_ci  using I = internal::Internals;
4691cb0ef41Sopenharmony_ci  if (this->IsEmpty()) return false;
4701cb0ef41Sopenharmony_ci  return I::GetNodeState(reinterpret_cast<internal::Address*>(this->val_)) ==
4711cb0ef41Sopenharmony_ci         I::kNodeStateIsWeakValue;
4721cb0ef41Sopenharmony_ci}
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_citemplate <class T>
4751cb0ef41Sopenharmony_civoid PersistentBase<T>::Reset() {
4761cb0ef41Sopenharmony_ci  if (this->IsEmpty()) return;
4771cb0ef41Sopenharmony_ci  api_internal::DisposeGlobal(reinterpret_cast<internal::Address*>(this->val_));
4781cb0ef41Sopenharmony_ci  val_ = nullptr;
4791cb0ef41Sopenharmony_ci}
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_ci/**
4821cb0ef41Sopenharmony_ci * If non-empty, destroy the underlying storage cell
4831cb0ef41Sopenharmony_ci * and create a new one with the contents of other if other is non empty
4841cb0ef41Sopenharmony_ci */
4851cb0ef41Sopenharmony_citemplate <class T>
4861cb0ef41Sopenharmony_citemplate <class S>
4871cb0ef41Sopenharmony_civoid PersistentBase<T>::Reset(Isolate* isolate, const Local<S>& other) {
4881cb0ef41Sopenharmony_ci  static_assert(std::is_base_of<T, S>::value, "type check");
4891cb0ef41Sopenharmony_ci  Reset();
4901cb0ef41Sopenharmony_ci  if (other.IsEmpty()) return;
4911cb0ef41Sopenharmony_ci  this->val_ = New(isolate, other.val_);
4921cb0ef41Sopenharmony_ci}
4931cb0ef41Sopenharmony_ci
4941cb0ef41Sopenharmony_ci/**
4951cb0ef41Sopenharmony_ci * If non-empty, destroy the underlying storage cell
4961cb0ef41Sopenharmony_ci * and create a new one with the contents of other if other is non empty
4971cb0ef41Sopenharmony_ci */
4981cb0ef41Sopenharmony_citemplate <class T>
4991cb0ef41Sopenharmony_citemplate <class S>
5001cb0ef41Sopenharmony_civoid PersistentBase<T>::Reset(Isolate* isolate,
5011cb0ef41Sopenharmony_ci                              const PersistentBase<S>& other) {
5021cb0ef41Sopenharmony_ci  static_assert(std::is_base_of<T, S>::value, "type check");
5031cb0ef41Sopenharmony_ci  Reset();
5041cb0ef41Sopenharmony_ci  if (other.IsEmpty()) return;
5051cb0ef41Sopenharmony_ci  this->val_ = New(isolate, other.val_);
5061cb0ef41Sopenharmony_ci}
5071cb0ef41Sopenharmony_ci
5081cb0ef41Sopenharmony_citemplate <class T>
5091cb0ef41Sopenharmony_citemplate <typename P>
5101cb0ef41Sopenharmony_ciV8_INLINE void PersistentBase<T>::SetWeak(
5111cb0ef41Sopenharmony_ci    P* parameter, typename WeakCallbackInfo<P>::Callback callback,
5121cb0ef41Sopenharmony_ci    WeakCallbackType type) {
5131cb0ef41Sopenharmony_ci  using Callback = WeakCallbackInfo<void>::Callback;
5141cb0ef41Sopenharmony_ci#if (__GNUC__ >= 8) && !defined(__clang__)
5151cb0ef41Sopenharmony_ci#pragma GCC diagnostic push
5161cb0ef41Sopenharmony_ci#pragma GCC diagnostic ignored "-Wcast-function-type"
5171cb0ef41Sopenharmony_ci#endif
5181cb0ef41Sopenharmony_ci  api_internal::MakeWeak(reinterpret_cast<internal::Address*>(this->val_),
5191cb0ef41Sopenharmony_ci                         parameter, reinterpret_cast<Callback>(callback), type);
5201cb0ef41Sopenharmony_ci#if (__GNUC__ >= 8) && !defined(__clang__)
5211cb0ef41Sopenharmony_ci#pragma GCC diagnostic pop
5221cb0ef41Sopenharmony_ci#endif
5231cb0ef41Sopenharmony_ci}
5241cb0ef41Sopenharmony_ci
5251cb0ef41Sopenharmony_citemplate <class T>
5261cb0ef41Sopenharmony_civoid PersistentBase<T>::SetWeak() {
5271cb0ef41Sopenharmony_ci  api_internal::MakeWeak(reinterpret_cast<internal::Address**>(&this->val_));
5281cb0ef41Sopenharmony_ci}
5291cb0ef41Sopenharmony_ci
5301cb0ef41Sopenharmony_citemplate <class T>
5311cb0ef41Sopenharmony_citemplate <typename P>
5321cb0ef41Sopenharmony_ciP* PersistentBase<T>::ClearWeak() {
5331cb0ef41Sopenharmony_ci  return reinterpret_cast<P*>(api_internal::ClearWeak(
5341cb0ef41Sopenharmony_ci      reinterpret_cast<internal::Address*>(this->val_)));
5351cb0ef41Sopenharmony_ci}
5361cb0ef41Sopenharmony_ci
5371cb0ef41Sopenharmony_citemplate <class T>
5381cb0ef41Sopenharmony_civoid PersistentBase<T>::AnnotateStrongRetainer(const char* label) {
5391cb0ef41Sopenharmony_ci  api_internal::AnnotateStrongRetainer(
5401cb0ef41Sopenharmony_ci      reinterpret_cast<internal::Address*>(this->val_), label);
5411cb0ef41Sopenharmony_ci}
5421cb0ef41Sopenharmony_ci
5431cb0ef41Sopenharmony_citemplate <class T>
5441cb0ef41Sopenharmony_civoid PersistentBase<T>::SetWrapperClassId(uint16_t class_id) {
5451cb0ef41Sopenharmony_ci  using I = internal::Internals;
5461cb0ef41Sopenharmony_ci  if (this->IsEmpty()) return;
5471cb0ef41Sopenharmony_ci  internal::Address* obj = reinterpret_cast<internal::Address*>(this->val_);
5481cb0ef41Sopenharmony_ci  uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + I::kNodeClassIdOffset;
5491cb0ef41Sopenharmony_ci  *reinterpret_cast<uint16_t*>(addr) = class_id;
5501cb0ef41Sopenharmony_ci}
5511cb0ef41Sopenharmony_ci
5521cb0ef41Sopenharmony_citemplate <class T>
5531cb0ef41Sopenharmony_ciuint16_t PersistentBase<T>::WrapperClassId() const {
5541cb0ef41Sopenharmony_ci  using I = internal::Internals;
5551cb0ef41Sopenharmony_ci  if (this->IsEmpty()) return 0;
5561cb0ef41Sopenharmony_ci  internal::Address* obj = reinterpret_cast<internal::Address*>(this->val_);
5571cb0ef41Sopenharmony_ci  uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + I::kNodeClassIdOffset;
5581cb0ef41Sopenharmony_ci  return *reinterpret_cast<uint16_t*>(addr);
5591cb0ef41Sopenharmony_ci}
5601cb0ef41Sopenharmony_ci
5611cb0ef41Sopenharmony_citemplate <class T>
5621cb0ef41Sopenharmony_ciGlobal<T>::Global(Global&& other) : PersistentBase<T>(other.val_) {
5631cb0ef41Sopenharmony_ci  if (other.val_ != nullptr) {
5641cb0ef41Sopenharmony_ci    api_internal::MoveGlobalReference(
5651cb0ef41Sopenharmony_ci        reinterpret_cast<internal::Address**>(&other.val_),
5661cb0ef41Sopenharmony_ci        reinterpret_cast<internal::Address**>(&this->val_));
5671cb0ef41Sopenharmony_ci    other.val_ = nullptr;
5681cb0ef41Sopenharmony_ci  }
5691cb0ef41Sopenharmony_ci}
5701cb0ef41Sopenharmony_ci
5711cb0ef41Sopenharmony_citemplate <class T>
5721cb0ef41Sopenharmony_citemplate <class S>
5731cb0ef41Sopenharmony_ciGlobal<T>& Global<T>::operator=(Global<S>&& rhs) {
5741cb0ef41Sopenharmony_ci  static_assert(std::is_base_of<T, S>::value, "type check");
5751cb0ef41Sopenharmony_ci  if (this != &rhs) {
5761cb0ef41Sopenharmony_ci    this->Reset();
5771cb0ef41Sopenharmony_ci    if (rhs.val_ != nullptr) {
5781cb0ef41Sopenharmony_ci      this->val_ = rhs.val_;
5791cb0ef41Sopenharmony_ci      api_internal::MoveGlobalReference(
5801cb0ef41Sopenharmony_ci          reinterpret_cast<internal::Address**>(&rhs.val_),
5811cb0ef41Sopenharmony_ci          reinterpret_cast<internal::Address**>(&this->val_));
5821cb0ef41Sopenharmony_ci      rhs.val_ = nullptr;
5831cb0ef41Sopenharmony_ci    }
5841cb0ef41Sopenharmony_ci  }
5851cb0ef41Sopenharmony_ci  return *this;
5861cb0ef41Sopenharmony_ci}
5871cb0ef41Sopenharmony_ci
5881cb0ef41Sopenharmony_ci}  // namespace v8
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ci#endif  // INCLUDE_V8_PERSISTENT_HANDLE_H_
591