Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 10:05:25

0001 // Copyright 2021 the V8 project authors. All rights reserved.
0002 // Use of this source code is governed by a BSD-style license that can be
0003 // found in the LICENSE file.
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 }  // namespace internal
0079 
0080 namespace api_internal {
0081 // Called when ToLocalChecked is called on an empty Local.
0082 V8_EXPORT void ToLocalEmpty();
0083 }  // namespace api_internal
0084 
0085 /**
0086  * A stack-allocated class that governs a number of local handles.
0087  * After a handle scope has been created, all local handles will be
0088  * allocated within that handle scope until either the handle scope is
0089  * deleted or another handle scope is created.  If there is already a
0090  * handle scope and a new one is created, all allocations will take
0091  * place in the new handle scope until it is deleted.  After that,
0092  * new handles will again be allocated in the original handle scope.
0093  *
0094  * After the handle scope of a local handle has been deleted the
0095  * garbage collector will no longer track the object stored in the
0096  * handle and may deallocate it.  The behavior of accessing a handle
0097  * for which the handle scope has been deleted is undefined.
0098  */
0099 class V8_EXPORT V8_NODISCARD HandleScope {
0100  public:
0101   explicit HandleScope(Isolate* isolate);
0102 
0103   ~HandleScope();
0104 
0105   /**
0106    * Counts the number of allocated handles.
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   // Declaring operator new and delete as deleted is not spec compliant.
0130   // Therefore declare them private instead to disable dynamic alloc
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   // LocalBase<T>::New uses CreateHandle with an Isolate* parameter.
0144   template <typename T>
0145   friend class LocalBase;
0146 
0147   // Object::GetInternalField and Context::GetEmbedderData use CreateHandle with
0148   // a HeapObject in their shortcuts.
0149   friend class Object;
0150   friend class Context;
0151 };
0152 
0153 /**
0154  * A base class for local handles.
0155  * Its implementation depends on whether direct local support is enabled.
0156  * When it is, a local handle contains a direct pointer to the referenced
0157  * object, otherwise it contains an indirect pointer.
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  // !V8_ENABLE_DIRECT_LOCAL
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  // V8_ENABLE_DIRECT_LOCAL
0221 
0222 /**
0223  * An object reference managed by the v8 garbage collector.
0224  *
0225  * All objects returned from v8 have to be tracked by the garbage collector so
0226  * that it knows that the objects are still alive.  Also, because the garbage
0227  * collector may move objects, it is unsafe to point directly to an object.
0228  * Instead, all objects are stored in handles which are known by the garbage
0229  * collector and updated whenever an object moves.  Handles should always be
0230  * passed by value (except in cases like out-parameters) and they should never
0231  * be allocated on the heap.
0232  *
0233  * There are two types of handles: local and persistent handles.
0234  *
0235  * Local handles are light-weight and transient and typically used in local
0236  * operations.  They are managed by HandleScopes. That means that a HandleScope
0237  * must exist on the stack when they are created and that they are only valid
0238  * inside of the HandleScope active during their creation. For passing a local
0239  * handle to an outer HandleScope, an EscapableHandleScope and its Escape()
0240  * method must be used.
0241  *
0242  * Persistent handles can be used when storing objects across several
0243  * independent operations and have to be explicitly deallocated when they're no
0244  * longer used.
0245  *
0246  * It is safe to extract the object stored in the handle by dereferencing the
0247  * handle (for instance, to extract the Object* from a Local<Object>); the value
0248  * will still be governed by a handle behind the scenes and the same rules apply
0249  * to these values as to their handles.
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      * This check fails when trying to convert between incompatible
0266      * handles. For example, converting from a Local<String> to a
0267      * Local<Number>.
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    * Checks whether two handles are equal or different.
0278    * They are equal iff they are both empty or they are both non-empty and the
0279    * objects to which they refer are physically equal.
0280    *
0281    * If both handles refer to JS objects, this is the same as strict
0282    * non-equality. For primitives, such as numbers or strings, a `true` return
0283    * value does not indicate that the values aren't equal in the JavaScript
0284    * sense. Use `Value::StrictEquals()` to check primitives for equality.
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    * Cast a handle to a subclass, e.g. Local<Value> to Local<Object>.
0309    * This is only valid if the handle actually refers to a value of the
0310    * target type.
0311    */
0312   template <class S>
0313   V8_INLINE static Local<T> Cast(Local<S> that) {
0314 #ifdef V8_ENABLE_CHECKS
0315     // If we're going to perform the type check then we have to check
0316     // that the handle isn't empty before doing the checked cast.
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    * Calling this is equivalent to Local<S>::Cast().
0325    * In particular, this is only valid if the handle actually refers to a value
0326    * of the target type.
0327    */
0328   template <class S>
0329   V8_INLINE Local<S> As() const {
0330     return Local<S>::Cast(*this);
0331   }
0332 
0333   /**
0334    * Create a local handle for the content of another handle.
0335    * The referee is kept alive by the local handle even when
0336    * the original handle is destroyed/disposed.
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  // V8_ENABLE_DIRECT_LOCAL
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   // Unsafe cast, should be avoided.
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 // A local variant that is suitable for off-stack allocation.
0433 // Used internally by LocalVector<T>. Not to be used directly!
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   // In this case, the check is also enforced in the copy constructor and we
0441   // need to suppress it.
0442   LocalUnchecked(const LocalUnchecked& other)
0443       : Local<T>(other, Local<T>::do_not_check) {}
0444   LocalUnchecked& operator=(const LocalUnchecked&) = default;
0445 #endif
0446 
0447   // Implicit conversion from Local.
0448   LocalUnchecked(const Local<T>& other)  // NOLINT(runtime/explicit)
0449       : Local<T>(other, Local<T>::do_not_check) {}
0450 };
0451 
0452 #ifdef V8_ENABLE_DIRECT_LOCAL
0453 // Off-stack allocated direct locals must be registered as strong roots.
0454 // For off-stack indirect locals, this is not necessary.
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  // V8_ENABLE_DIRECT_LOCAL
0478 }  // namespace internal
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  // V8_ENABLE_DIRECT_LOCAL
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 // Handle is an alias for Local for historical reasons.
0601 template <class T>
0602 using Handle = Local<T>;
0603 #endif
0604 
0605 /**
0606  * A MaybeLocal<> is a wrapper around Local<> that enforces a check whether
0607  * the Local<> is empty before it can be used.
0608  *
0609  * If an API method returns a MaybeLocal<>, the API method can potentially fail
0610  * either because an exception is thrown, or because an exception is pending,
0611  * e.g. because a previous API call threw an exception that hasn't been caught
0612  * yet, or because a TerminateExecution exception was thrown. In that case, an
0613  * empty MaybeLocal is returned.
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    * Converts this MaybeLocal<> to a Local<>. If this MaybeLocal<> is empty,
0626    * |false| is returned and |out| is assigned with nullptr.
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    * Converts this MaybeLocal<> to a Local<>. If this MaybeLocal<> is empty,
0636    * V8 will crash the process.
0637    */
0638   V8_INLINE Local<T> ToLocalChecked() {
0639     if (V8_UNLIKELY(IsEmpty())) api_internal::ToLocalEmpty();
0640     return local_;
0641   }
0642 
0643   /**
0644    * Converts this MaybeLocal<> to a Local<>, using a default value if this
0645    * MaybeLocal<> is empty.
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    * Cast a handle to a subclass, e.g. MaybeLocal<Value> to MaybeLocal<Object>.
0654    * This is only valid if the handle actually refers to a value of the target
0655    * type.
0656    */
0657   template <class S>
0658   V8_INLINE static MaybeLocal<T> Cast(MaybeLocal<S> that) {
0659 #ifdef V8_ENABLE_CHECKS
0660     // If we're going to perform the type check then we have to check
0661     // that the handle isn't empty before doing the checked cast.
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    * Calling this is equivalent to MaybeLocal<S>::Cast().
0670    * In particular, this is only valid if the handle actually refers to a value
0671    * of the target type.
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  * A HandleScope which first allocates a handle in the current scope
0687  * which will be later filled with the escape value.
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    * Pushes the value into the previous scope and returns a handle to it.
0704    * Cannot be called twice.
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  * A SealHandleScope acts like a handle scope in which no handle allocations
0736  * are allowed. It can be useful for debugging handle leaks.
0737  * Handles can be allocated within inner normal HandleScopes.
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 }  // namespace v8
0758 
0759 #endif  // INCLUDE_V8_LOCAL_HANDLE_H_