// Copyright 2012 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /** \mainpage V8 API Reference Guide * * V8 is Google's open source JavaScript engine. * * This set of documents provides reference material generated from the * V8 header file, include/v8.h. * * For other documentation see https://v8.dev/. */ #ifndef INCLUDE_V8_H_ #define INCLUDE_V8_H_ #include #include #include #include #include #include #include #include #include "cppgc/common.h" #include "v8-internal.h" // NOLINT(build/include_directory) #include "v8-version.h" // NOLINT(build/include_directory) #include "v8config.h" // NOLINT(build/include_directory) // We reserve the V8_* prefix for macros defined in V8 public API and // assume there are no name conflicts with the embedder's code. /** * The v8 JavaScript engine. */ namespace v8 { class AccessorSignature; class Array; class ArrayBuffer; class BigInt; class BigIntObject; class Boolean; class BooleanObject; class Context; class Data; class Date; class External; class Function; class FunctionTemplate; class HeapProfiler; class ImplementationUtilities; class Int32; class Integer; class Isolate; template class Maybe; class MicrotaskQueue; class Name; class Number; class NumberObject; class Object; class ObjectOperationDescriptor; class ObjectTemplate; class Platform; class Primitive; class Promise; class PropertyDescriptor; class Proxy; class RawOperationDescriptor; class Script; class SharedArrayBuffer; class Signature; class StartupData; class StackFrame; class StackTrace; class String; class StringObject; class Symbol; class SymbolObject; class PrimitiveArray; class Private; class Uint32; class Utils; class Value; class WasmModuleObject; template class Local; template class MaybeLocal; template class Eternal; template class NonCopyablePersistentTraits; template class PersistentBase; template > class Persistent; template class Global; template class TracedGlobal; template class TracedReference; template class TracedReferenceBase; template class PersistentValueMap; template class PersistentValueMapBase; template class GlobalValueMap; template class PersistentValueVector; template class WeakCallbackObject; class FunctionTemplate; class ObjectTemplate; template class FunctionCallbackInfo; template class PropertyCallbackInfo; class StackTrace; class StackFrame; class Isolate; class CallHandlerHelper; class EscapableHandleScope; template class ReturnValue; namespace internal { enum class ArgumentsType; template class Arguments; template class CustomArguments; class DeferredHandles; class FunctionCallbackArguments; class GlobalHandles; class Heap; class HeapObject; class ExternalString; class Isolate; class LocalEmbedderHeapTracer; class MicrotaskQueue; class PropertyCallbackArguments; class ReadOnlyHeap; class ScopedExternalStringLock; struct ScriptStreamingData; class ThreadLocalTop; namespace wasm { class NativeModule; class StreamingDecoder; } // namespace wasm } // namespace internal namespace debug { class ConsoleCallArguments; } // namespace debug // --- Handles --- /** * An object reference managed by the v8 garbage collector. * * All objects returned from v8 have to be tracked by the garbage * collector so that it knows that the objects are still alive. Also, * because the garbage collector may move objects, it is unsafe to * point directly to an object. Instead, all objects are stored in * handles which are known by the garbage collector and updated * whenever an object moves. Handles should always be passed by value * (except in cases like out-parameters) and they should never be * allocated on the heap. * * There are two types of handles: local and persistent handles. * * Local handles are light-weight and transient and typically used in * local operations. They are managed by HandleScopes. That means that a * HandleScope must exist on the stack when they are created and that they are * only valid inside of the HandleScope active during their creation. * For passing a local handle to an outer HandleScope, an EscapableHandleScope * and its Escape() method must be used. * * Persistent handles can be used when storing objects across several * independent operations and have to be explicitly deallocated when they're no * longer used. * * It is safe to extract the object stored in the handle by * dereferencing the handle (for instance, to extract the Object* from * a Local); the value will still be governed by a handle * behind the scenes and the same rules apply to these values as to * their handles. */ template class Local { public: V8_INLINE Local() : val_(nullptr) {} template V8_INLINE Local(Local that) : val_(reinterpret_cast(*that)) { /** * This check fails when trying to convert between incompatible * handles. For example, converting from a Local to a * Local. */ static_assert(std::is_base_of::value, "type check"); } /** * Returns true if the handle is empty. */ V8_INLINE bool IsEmpty() const { return val_ == nullptr; } /** * Sets the handle to be empty. IsEmpty() will then return true. */ V8_INLINE void Clear() { val_ = nullptr; } V8_INLINE T* operator->() const { return val_; } V8_INLINE T* operator*() const { return val_; } /** * Checks whether two handles are the same. * Returns true if both are empty, or if the objects to which they refer * are identical. * * If both handles refer to JS objects, this is the same as strict equality. * For primitives, such as numbers or strings, a `false` return value does not * indicate that the values aren't equal in the JavaScript sense. * Use `Value::StrictEquals()` to check primitives for equality. */ template V8_INLINE bool operator==(const Local& that) const { internal::Address* a = reinterpret_cast(this->val_); internal::Address* b = reinterpret_cast(that.val_); if (a == nullptr) return b == nullptr; if (b == nullptr) return false; return *a == *b; } template V8_INLINE bool operator==( const PersistentBase& that) const { internal::Address* a = reinterpret_cast(this->val_); internal::Address* b = reinterpret_cast(that.val_); if (a == nullptr) return b == nullptr; if (b == nullptr) return false; return *a == *b; } /** * Checks whether two handles are different. * Returns true if only one of the handles is empty, or if * the objects to which they refer are different. * * If both handles refer to JS objects, this is the same as strict * non-equality. For primitives, such as numbers or strings, a `true` return * value does not indicate that the values aren't equal in the JavaScript * sense. Use `Value::StrictEquals()` to check primitives for equality. */ template V8_INLINE bool operator!=(const Local& that) const { return !operator==(that); } template V8_INLINE bool operator!=( const Persistent& that) const { return !operator==(that); } /** * Cast a handle to a subclass, e.g. Local to Local. * This is only valid if the handle actually refers to a value of the * target type. */ template V8_INLINE static Local Cast(Local that) { #ifdef V8_ENABLE_CHECKS // If we're going to perform the type check then we have to check // that the handle isn't empty before doing the checked cast. if (that.IsEmpty()) return Local(); #endif return Local(T::Cast(*that)); } /** * Calling this is equivalent to Local::Cast(). * In particular, this is only valid if the handle actually refers to a value * of the target type. */ template V8_INLINE Local As() const { return Local::Cast(*this); } /** * Create a local handle for the content of another handle. * The referee is kept alive by the local handle even when * the original handle is destroyed/disposed. */ V8_INLINE static Local New(Isolate* isolate, Local that); V8_INLINE static Local New(Isolate* isolate, const PersistentBase& that); V8_INLINE static Local New(Isolate* isolate, const TracedReferenceBase& that); private: friend class Utils; template friend class Eternal; template friend class PersistentBase; template friend class Persistent; template friend class Local; template friend class MaybeLocal; template friend class FunctionCallbackInfo; template friend class PropertyCallbackInfo; friend class String; friend class Object; friend class Context; friend class Isolate; friend class Private; template friend class internal::CustomArguments; friend Local Undefined(Isolate* isolate); friend Local Null(Isolate* isolate); friend Local True(Isolate* isolate); friend Local False(Isolate* isolate); friend class HandleScope; friend class EscapableHandleScope; template friend class PersistentValueMapBase; template friend class PersistentValueVector; template friend class ReturnValue; template friend class Traced; template friend class TracedGlobal; template friend class TracedReferenceBase; template friend class TracedReference; explicit V8_INLINE Local(T* that) : val_(that) {} V8_INLINE static Local New(Isolate* isolate, T* that); T* val_; }; #if !defined(V8_IMMINENT_DEPRECATION_WARNINGS) // Handle is an alias for Local for historical reasons. template using Handle = Local; #endif /** * A MaybeLocal<> is a wrapper around Local<> that enforces a check whether * the Local<> is empty before it can be used. * * If an API method returns a MaybeLocal<>, the API method can potentially fail * either because an exception is thrown, or because an exception is pending, * e.g. because a previous API call threw an exception that hasn't been caught * yet, or because a TerminateExecution exception was thrown. In that case, an * empty MaybeLocal is returned. */ template class MaybeLocal { public: V8_INLINE MaybeLocal() : val_(nullptr) {} template V8_INLINE MaybeLocal(Local that) : val_(reinterpret_cast(*that)) { static_assert(std::is_base_of::value, "type check"); } V8_INLINE bool IsEmpty() const { return val_ == nullptr; } /** * Converts this MaybeLocal<> to a Local<>. If this MaybeLocal<> is empty, * |false| is returned and |out| is left untouched. */ template V8_WARN_UNUSED_RESULT V8_INLINE bool ToLocal(Local* out) const { out->val_ = IsEmpty() ? nullptr : this->val_; return !IsEmpty(); } /** * Converts this MaybeLocal<> to a Local<>. If this MaybeLocal<> is empty, * V8 will crash the process. */ V8_INLINE Local ToLocalChecked(); /** * Converts this MaybeLocal<> to a Local<>, using a default value if this * MaybeLocal<> is empty. */ template V8_INLINE Local FromMaybe(Local default_value) const { return IsEmpty() ? default_value : Local(val_); } private: T* val_; }; /** * Eternal handles are set-once handles that live for the lifetime of the * isolate. */ template class Eternal { public: V8_INLINE Eternal() : val_(nullptr) {} template V8_INLINE Eternal(Isolate* isolate, Local handle) : val_(nullptr) { Set(isolate, handle); } // Can only be safely called if already set. V8_INLINE Local Get(Isolate* isolate) const; V8_INLINE bool IsEmpty() const { return val_ == nullptr; } template V8_INLINE void Set(Isolate* isolate, Local handle); private: T* val_; }; static const int kInternalFieldsInWeakCallback = 2; static const int kEmbedderFieldsInWeakCallback = 2; template class WeakCallbackInfo { public: typedef void (*Callback)(const WeakCallbackInfo& data); WeakCallbackInfo(Isolate* isolate, T* parameter, void* embedder_fields[kEmbedderFieldsInWeakCallback], Callback* callback) : isolate_(isolate), parameter_(parameter), callback_(callback) { for (int i = 0; i < kEmbedderFieldsInWeakCallback; ++i) { embedder_fields_[i] = embedder_fields[i]; } } V8_INLINE Isolate* GetIsolate() const { return isolate_; } V8_INLINE T* GetParameter() const { return parameter_; } V8_INLINE void* GetInternalField(int index) const; // When first called, the embedder MUST Reset() the Global which triggered the // callback. The Global itself is unusable for anything else. No v8 other api // calls may be called in the first callback. Should additional work be // required, the embedder must set a second pass callback, which will be // called after all the initial callbacks are processed. // Calling SetSecondPassCallback on the second pass will immediately crash. void SetSecondPassCallback(Callback callback) const { *callback_ = callback; } private: Isolate* isolate_; T* parameter_; Callback* callback_; void* embedder_fields_[kEmbedderFieldsInWeakCallback]; }; // kParameter will pass a void* parameter back to the callback, kInternalFields // will pass the first two internal fields back to the callback, kFinalizer // will pass a void* parameter back, but is invoked before the object is // actually collected, so it can be resurrected. In the last case, it is not // possible to request a second pass callback. enum class WeakCallbackType { kParameter, kInternalFields, kFinalizer }; /** * An object reference that is independent of any handle scope. Where * a Local handle only lives as long as the HandleScope in which it was * allocated, a PersistentBase handle remains valid until it is explicitly * disposed using Reset(). * * A persistent handle contains a reference to a storage cell within * the V8 engine which holds an object value and which is updated by * the garbage collector whenever the object is moved. A new storage * cell can be created using the constructor or PersistentBase::Reset and * existing handles can be disposed using PersistentBase::Reset. * */ template class PersistentBase { public: /** * If non-empty, destroy the underlying storage cell * IsEmpty() will return true after this call. */ V8_INLINE void Reset(); /** * If non-empty, destroy the underlying storage cell * and create a new one with the contents of other if other is non empty */ template V8_INLINE void Reset(Isolate* isolate, const Local& other); /** * If non-empty, destroy the underlying storage cell * and create a new one with the contents of other if other is non empty */ template V8_INLINE void Reset(Isolate* isolate, const PersistentBase& other); V8_INLINE bool IsEmpty() const { return val_ == nullptr; } V8_INLINE void Empty() { val_ = 0; } V8_INLINE Local Get(Isolate* isolate) const { return Local::New(isolate, *this); } template V8_INLINE bool operator==(const PersistentBase& that) const { internal::Address* a = reinterpret_cast(this->val_); internal::Address* b = reinterpret_cast(that.val_); if (a == nullptr) return b == nullptr; if (b == nullptr) return false; return *a == *b; } template V8_INLINE bool operator==(const Local& that) const { internal::Address* a = reinterpret_cast(this->val_); internal::Address* b = reinterpret_cast(that.val_); if (a == nullptr) return b == nullptr; if (b == nullptr) return false; return *a == *b; } template V8_INLINE bool operator!=(const PersistentBase& that) const { return !operator==(that); } template V8_INLINE bool operator!=(const Local& that) const { return !operator==(that); } /** * Install a finalization callback on this object. * NOTE: There is no guarantee as to *when* or even *if* the callback is * invoked. The invocation is performed solely on a best effort basis. * As always, GC-based finalization should *not* be relied upon for any * critical form of resource management! * * The callback is supposed to reset the handle. No further V8 API may be * called in this callback. In case additional work involving V8 needs to be * done, a second callback can be scheduled using * WeakCallbackInfo::SetSecondPassCallback. */ template V8_INLINE void SetWeak(P* parameter, typename WeakCallbackInfo

::Callback callback, WeakCallbackType type); /** * Turns this handle into a weak phantom handle without finalization callback. * The handle will be reset automatically when the garbage collector detects * that the object is no longer reachable. * A related function Isolate::NumberOfPhantomHandleResetsSinceLastCall * returns how many phantom handles were reset by the garbage collector. */ V8_INLINE void SetWeak(); template V8_INLINE P* ClearWeak(); // TODO(dcarney): remove this. V8_INLINE void ClearWeak() { ClearWeak(); } /** * Annotates the strong handle with the given label, which is then used by the * heap snapshot generator as a name of the edge from the root to the handle. * The function does not take ownership of the label and assumes that the * label is valid as long as the handle is valid. */ V8_INLINE void AnnotateStrongRetainer(const char* label); /** Returns true if the handle's reference is weak. */ V8_INLINE bool IsWeak() const; /** * Assigns a wrapper class ID to the handle. */ V8_INLINE void SetWrapperClassId(uint16_t class_id); /** * Returns the class ID previously assigned to this handle or 0 if no class ID * was previously assigned. */ V8_INLINE uint16_t WrapperClassId() const; PersistentBase(const PersistentBase& other) = delete; // NOLINT void operator=(const PersistentBase&) = delete; private: friend class Isolate; friend class Utils; template friend class Local; template friend class Persistent; template friend class Global; template friend class PersistentBase; template friend class ReturnValue; template friend class PersistentValueMapBase; template friend class PersistentValueVector; friend class Object; explicit V8_INLINE PersistentBase(T* val) : val_(val) {} V8_INLINE static T* New(Isolate* isolate, T* that); T* val_; }; /** * Default traits for Persistent. This class does not allow * use of the copy constructor or assignment operator. * At present kResetInDestructor is not set, but that will change in a future * version. */ template class NonCopyablePersistentTraits { public: typedef Persistent > NonCopyablePersistent; static const bool kResetInDestructor = false; template V8_INLINE static void Copy(const Persistent& source, NonCopyablePersistent* dest) { static_assert(sizeof(S) < 0, "NonCopyablePersistentTraits::Copy is not instantiable"); } }; /** * Helper class traits to allow copying and assignment of Persistent. * This will clone the contents of storage cell, but not any of the flags, etc. */ template struct CopyablePersistentTraits { typedef Persistent > CopyablePersistent; static const bool kResetInDestructor = true; template static V8_INLINE void Copy(const Persistent& source, CopyablePersistent* dest) { // do nothing, just allow copy } }; /** * A PersistentBase which allows copy and assignment. * * Copy, assignment and destructor behavior is controlled by the traits * class M. * * Note: Persistent class hierarchy is subject to future changes. */ template class Persistent : public PersistentBase { public: /** * A Persistent with no storage cell. */ V8_INLINE Persistent() : PersistentBase(nullptr) {} /** * Construct a Persistent from a Local. * When the Local is non-empty, a new storage cell is created * pointing to the same object, and no flags are set. */ template V8_INLINE Persistent(Isolate* isolate, Local that) : PersistentBase(PersistentBase::New(isolate, *that)) { static_assert(std::is_base_of::value, "type check"); } /** * Construct a Persistent from a Persistent. * When the Persistent is non-empty, a new storage cell is created * pointing to the same object, and no flags are set. */ template V8_INLINE Persistent(Isolate* isolate, const Persistent& that) : PersistentBase(PersistentBase::New(isolate, *that)) { static_assert(std::is_base_of::value, "type check"); } /** * The copy constructors and assignment operator create a Persistent * exactly as the Persistent constructor, but the Copy function from the * traits class is called, allowing the setting of flags based on the * copied Persistent. */ V8_INLINE Persistent(const Persistent& that) : PersistentBase(nullptr) { Copy(that); } template V8_INLINE Persistent(const Persistent& that) : PersistentBase(0) { Copy(that); } V8_INLINE Persistent& operator=(const Persistent& that) { Copy(that); return *this; } template V8_INLINE Persistent& operator=(const Persistent& that) { // NOLINT Copy(that); return *this; } /** * The destructor will dispose the Persistent based on the * kResetInDestructor flags in the traits class. Since not calling dispose * can result in a memory leak, it is recommended to always set this flag. */ V8_INLINE ~Persistent() { if (M::kResetInDestructor) this->Reset(); } // TODO(dcarney): this is pretty useless, fix or remove template V8_INLINE static Persistent& Cast(const Persistent& that) { // NOLINT #ifdef V8_ENABLE_CHECKS // If we're going to perform the type check then we have to check // that the handle isn't empty before doing the checked cast. if (!that.IsEmpty()) T::Cast(*that); #endif return reinterpret_cast&>(const_cast&>(that)); } // TODO(dcarney): this is pretty useless, fix or remove template V8_INLINE Persistent& As() const { // NOLINT return Persistent::Cast(*this); } private: friend class Isolate; friend class Utils; template friend class Local; template friend class Persistent; template friend class ReturnValue; explicit V8_INLINE Persistent(T* that) : PersistentBase(that) {} V8_INLINE T* operator*() const { return this->val_; } template V8_INLINE void Copy(const Persistent& that); }; /** * A PersistentBase which has move semantics. * * Note: Persistent class hierarchy is subject to future changes. */ template class Global : public PersistentBase { public: /** * A Global with no storage cell. */ V8_INLINE Global() : PersistentBase(nullptr) {} /** * Construct a Global from a Local. * When the Local is non-empty, a new storage cell is created * pointing to the same object, and no flags are set. */ template V8_INLINE Global(Isolate* isolate, Local that) : PersistentBase(PersistentBase::New(isolate, *that)) { static_assert(std::is_base_of::value, "type check"); } /** * Construct a Global from a PersistentBase. * When the Persistent is non-empty, a new storage cell is created * pointing to the same object, and no flags are set. */ template V8_INLINE Global(Isolate* isolate, const PersistentBase& that) : PersistentBase(PersistentBase::New(isolate, that.val_)) { static_assert(std::is_base_of::value, "type check"); } /** * Move constructor. */ V8_INLINE Global(Global&& other); V8_INLINE ~Global() { this->Reset(); } /** * Move via assignment. */ template V8_INLINE Global& operator=(Global&& rhs); /** * Pass allows returning uniques from functions, etc. */ Global Pass() { return static_cast(*this); } // NOLINT /* * For compatibility with Chromium's base::Bind (base::Passed). */ typedef void MoveOnlyTypeForCPP03; Global(const Global&) = delete; void operator=(const Global&) = delete; private: template friend class ReturnValue; V8_INLINE T* operator*() const { return this->val_; } }; // UniquePersistent is an alias for Global for historical reason. template using UniquePersistent = Global; /** * Deprecated. Use |TracedReference| instead. */ template struct TracedGlobalTrait {}; /** * A traced handle with copy and move semantics. The handle is to be used * together with |v8::EmbedderHeapTracer| and specifies edges from the embedder * into V8's heap. * * The exact semantics are: * - Tracing garbage collections use |v8::EmbedderHeapTracer|. * - Non-tracing garbage collections refer to * |v8::EmbedderHeapTracer::IsRootForNonTracingGC()| whether the handle should * be treated as root or not. * * Note that the base class cannot be instantiated itself. Choose from * - TracedGlobal * - TracedReference */ template class TracedReferenceBase { public: /** * Returns true if this TracedReferenceBase is empty, i.e., has not been * assigned an object. */ bool IsEmpty() const { return val_ == nullptr; } /** * If non-empty, destroy the underlying storage cell. |IsEmpty| will return * true after this call. */ V8_INLINE void Reset(); /** * Construct a Local from this handle. */ Local Get(Isolate* isolate) const { return Local::New(isolate, *this); } template V8_INLINE bool operator==(const TracedReferenceBase& that) const { internal::Address* a = reinterpret_cast(val_); internal::Address* b = reinterpret_cast(that.val_); if (a == nullptr) return b == nullptr; if (b == nullptr) return false; return *a == *b; } template V8_INLINE bool operator==(const Local& that) const { internal::Address* a = reinterpret_cast(val_); internal::Address* b = reinterpret_cast(that.val_); if (a == nullptr) return b == nullptr; if (b == nullptr) return false; return *a == *b; } template V8_INLINE bool operator!=(const TracedReferenceBase& that) const { return !operator==(that); } template V8_INLINE bool operator!=(const Local& that) const { return !operator==(that); } /** * Assigns a wrapper class ID to the handle. */ V8_INLINE void SetWrapperClassId(uint16_t class_id); /** * Returns the class ID previously assigned to this handle or 0 if no class ID * was previously assigned. */ V8_INLINE uint16_t WrapperClassId() const; template V8_INLINE TracedReferenceBase& As() const { return reinterpret_cast&>( const_cast&>(*this)); } private: enum DestructionMode { kWithDestructor, kWithoutDestructor }; /** * An empty TracedReferenceBase without storage cell. */ TracedReferenceBase() = default; V8_INLINE static T* New(Isolate* isolate, T* that, void* slot, DestructionMode destruction_mode); T* val_ = nullptr; friend class EmbedderHeapTracer; template friend class Local; friend class Object; template friend class TracedGlobal; template friend class TracedReference; template friend class ReturnValue; }; /** * A traced handle with destructor that clears the handle. For more details see * TracedReferenceBase. */ template class TracedGlobal : public TracedReferenceBase { public: using TracedReferenceBase::Reset; /** * Destructor resetting the handle. */ ~TracedGlobal() { this->Reset(); } /** * An empty TracedGlobal without storage cell. */ TracedGlobal() : TracedReferenceBase() {} /** * Construct a TracedGlobal from a Local. * * When the Local is non-empty, a new storage cell is created * pointing to the same object. */ template TracedGlobal(Isolate* isolate, Local that) : TracedReferenceBase() { this->val_ = this->New(isolate, that.val_, &this->val_, TracedReferenceBase::kWithDestructor); static_assert(std::is_base_of::value, "type check"); } /** * Move constructor initializing TracedGlobal from an existing one. */ V8_INLINE TracedGlobal(TracedGlobal&& other) { // Forward to operator=. *this = std::move(other); } /** * Move constructor initializing TracedGlobal from an existing one. */ template V8_INLINE TracedGlobal(TracedGlobal&& other) { // Forward to operator=. *this = std::move(other); } /** * Copy constructor initializing TracedGlobal from an existing one. */ V8_INLINE TracedGlobal(const TracedGlobal& other) { // Forward to operator=; *this = other; } /** * Copy constructor initializing TracedGlobal from an existing one. */ template V8_INLINE TracedGlobal(const TracedGlobal& other) { // Forward to operator=; *this = other; } /** * Move assignment operator initializing TracedGlobal from an existing one. */ V8_INLINE TracedGlobal& operator=(TracedGlobal&& rhs); /** * Move assignment operator initializing TracedGlobal from an existing one. */ template V8_INLINE TracedGlobal& operator=(TracedGlobal&& rhs); /** * Copy assignment operator initializing TracedGlobal from an existing one. * * Note: Prohibited when |other| has a finalization callback set through * |SetFinalizationCallback|. */ V8_INLINE TracedGlobal& operator=(const TracedGlobal& rhs); /** * Copy assignment operator initializing TracedGlobal from an existing one. * * Note: Prohibited when |other| has a finalization callback set through * |SetFinalizationCallback|. */ template V8_INLINE TracedGlobal& operator=(const TracedGlobal& rhs); /** * If non-empty, destroy the underlying storage cell and create a new one with * the contents of other if other is non empty */ template V8_INLINE void Reset(Isolate* isolate, const Local& other); template V8_INLINE TracedGlobal& As() const { return reinterpret_cast&>( const_cast&>(*this)); } /** * Adds a finalization callback to the handle. The type of this callback is * similar to WeakCallbackType::kInternalFields, i.e., it will pass the * parameter and the first two internal fields of the object. * * The callback is then supposed to reset the handle in the callback. No * further V8 API may be called in this callback. In case additional work * involving V8 needs to be done, a second callback can be scheduled using * WeakCallbackInfo::SetSecondPassCallback. */ V8_INLINE void SetFinalizationCallback( void* parameter, WeakCallbackInfo::Callback callback); }; /** * A traced handle without destructor that clears the handle. The embedder needs * to ensure that the handle is not accessed once the V8 object has been * reclaimed. This can happen when the handle is not passed through the * EmbedderHeapTracer. For more details see TracedReferenceBase. * * The reference assumes the embedder has precise knowledge about references at * all times. In case V8 needs to separately handle on-stack references, the * embedder is required to set the stack start through * |EmbedderHeapTracer::SetStackStart|. */ template class TracedReference : public TracedReferenceBase { public: using TracedReferenceBase::Reset; /** * An empty TracedReference without storage cell. */ TracedReference() : TracedReferenceBase() {} /** * Construct a TracedReference from a Local. * * When the Local is non-empty, a new storage cell is created * pointing to the same object. */ template TracedReference(Isolate* isolate, Local that) : TracedReferenceBase() { this->val_ = this->New(isolate, that.val_, &this->val_, TracedReferenceBase::kWithoutDestructor); static_assert(std::is_base_of::value, "type check"); } /** * Move constructor initializing TracedReference from an * existing one. */ V8_INLINE TracedReference(TracedReference&& other) { // Forward to operator=. *this = std::move(other); } /** * Move constructor initializing TracedReference from an * existing one. */ template V8_INLINE TracedReference(TracedReference&& other) { // Forward to operator=. *this = std::move(other); } /** * Copy constructor initializing TracedReference from an * existing one. */ V8_INLINE TracedReference(const TracedReference& other) { // Forward to operator=; *this = other; } /** * Copy constructor initializing TracedReference from an * existing one. */ template V8_INLINE TracedReference(const TracedReference& other) { // Forward to operator=; *this = other; } /** * Move assignment operator initializing TracedGlobal from an existing one. */ V8_INLINE TracedReference& operator=(TracedReference&& rhs); /** * Move assignment operator initializing TracedGlobal from an existing one. */ template V8_INLINE TracedReference& operator=(TracedReference&& rhs); /** * Copy assignment operator initializing TracedGlobal from an existing one. */ V8_INLINE TracedReference& operator=(const TracedReference& rhs); /** * Copy assignment operator initializing TracedGlobal from an existing one. */ template V8_INLINE TracedReference& operator=(const TracedReference& rhs); /** * If non-empty, destroy the underlying storage cell and create a new one with * the contents of other if other is non empty */ template V8_INLINE void Reset(Isolate* isolate, const Local& other); template V8_INLINE TracedReference& As() const { return reinterpret_cast&>( const_cast&>(*this)); } }; /** * A stack-allocated class that governs a number of local handles. * After a handle scope has been created, all local handles will be * allocated within that handle scope until either the handle scope is * deleted or another handle scope is created. If there is already a * handle scope and a new one is created, all allocations will take * place in the new handle scope until it is deleted. After that, * new handles will again be allocated in the original handle scope. * * After the handle scope of a local handle has been deleted the * garbage collector will no longer track the object stored in the * handle and may deallocate it. The behavior of accessing a handle * for which the handle scope has been deleted is undefined. */ class V8_EXPORT HandleScope { public: explicit HandleScope(Isolate* isolate); ~HandleScope(); /** * Counts the number of allocated handles. */ static int NumberOfHandles(Isolate* isolate); V8_INLINE Isolate* GetIsolate() const { return reinterpret_cast(isolate_); } HandleScope(const HandleScope&) = delete; void operator=(const HandleScope&) = delete; protected: V8_INLINE HandleScope() = default; void Initialize(Isolate* isolate); static internal::Address* CreateHandle(internal::Isolate* isolate, internal::Address value); private: // Declaring operator new and delete as deleted is not spec compliant. // Therefore declare them private instead to disable dynamic alloc void* operator new(size_t size); void* operator new[](size_t size); void operator delete(void*, size_t); void operator delete[](void*, size_t); internal::Isolate* isolate_; internal::Address* prev_next_; internal::Address* prev_limit_; // Local::New uses CreateHandle with an Isolate* parameter. template friend class Local; // Object::GetInternalField and Context::GetEmbedderData use CreateHandle with // a HeapObject in their shortcuts. friend class Object; friend class Context; }; /** * A HandleScope which first allocates a handle in the current scope * which will be later filled with the escape value. */ class V8_EXPORT EscapableHandleScope : public HandleScope { public: explicit EscapableHandleScope(Isolate* isolate); V8_INLINE ~EscapableHandleScope() = default; /** * Pushes the value into the previous scope and returns a handle to it. * Cannot be called twice. */ template V8_INLINE Local Escape(Local value) { internal::Address* slot = Escape(reinterpret_cast(*value)); return Local(reinterpret_cast(slot)); } template V8_INLINE MaybeLocal EscapeMaybe(MaybeLocal value) { return Escape(value.FromMaybe(Local())); } EscapableHandleScope(const EscapableHandleScope&) = delete; void operator=(const EscapableHandleScope&) = delete; private: // Declaring operator new and delete as deleted is not spec compliant. // Therefore declare them private instead to disable dynamic alloc void* operator new(size_t size); void* operator new[](size_t size); void operator delete(void*, size_t); void operator delete[](void*, size_t); internal::Address* Escape(internal::Address* escape_value); internal::Address* escape_slot_; }; /** * A SealHandleScope acts like a handle scope in which no handle allocations * are allowed. It can be useful for debugging handle leaks. * Handles can be allocated within inner normal HandleScopes. */ class V8_EXPORT SealHandleScope { public: explicit SealHandleScope(Isolate* isolate); ~SealHandleScope(); SealHandleScope(const SealHandleScope&) = delete; void operator=(const SealHandleScope&) = delete; private: // Declaring operator new and delete as deleted is not spec compliant. // Therefore declare them private instead to disable dynamic alloc void* operator new(size_t size); void* operator new[](size_t size); void operator delete(void*, size_t); void operator delete[](void*, size_t); internal::Isolate* const isolate_; internal::Address* prev_limit_; int prev_sealed_level_; }; // --- Special objects --- /** * The superclass of objects that can reside on V8's heap. */ class V8_EXPORT Data { private: Data(); }; /** * A container type that holds relevant metadata for module loading. * * This is passed back to the embedder as part of * HostImportModuleDynamicallyCallback for module loading. */ class V8_EXPORT ScriptOrModule { public: /** * The name that was passed by the embedder as ResourceName to the * ScriptOrigin. This can be either a v8::String or v8::Undefined. */ Local GetResourceName(); /** * The options that were passed by the embedder as HostDefinedOptions to * the ScriptOrigin. */ Local GetHostDefinedOptions(); }; /** * An array to hold Primitive values. This is used by the embedder to * pass host defined options to the ScriptOptions during compilation. * * This is passed back to the embedder as part of * HostImportModuleDynamicallyCallback for module loading. * */ class V8_EXPORT PrimitiveArray { public: static Local New(Isolate* isolate, int length); int Length() const; void Set(Isolate* isolate, int index, Local item); Local Get(Isolate* isolate, int index); }; /** * The optional attributes of ScriptOrigin. */ class ScriptOriginOptions { public: V8_INLINE ScriptOriginOptions(bool is_shared_cross_origin = false, bool is_opaque = false, bool is_wasm = false, bool is_module = false) : flags_((is_shared_cross_origin ? kIsSharedCrossOrigin : 0) | (is_wasm ? kIsWasm : 0) | (is_opaque ? kIsOpaque : 0) | (is_module ? kIsModule : 0)) {} V8_INLINE ScriptOriginOptions(int flags) : flags_(flags & (kIsSharedCrossOrigin | kIsOpaque | kIsWasm | kIsModule)) {} bool IsSharedCrossOrigin() const { return (flags_ & kIsSharedCrossOrigin) != 0; } bool IsOpaque() const { return (flags_ & kIsOpaque) != 0; } bool IsWasm() const { return (flags_ & kIsWasm) != 0; } bool IsModule() const { return (flags_ & kIsModule) != 0; } int Flags() const { return flags_; } private: enum { kIsSharedCrossOrigin = 1, kIsOpaque = 1 << 1, kIsWasm = 1 << 2, kIsModule = 1 << 3 }; const int flags_; }; /** * The origin, within a file, of a script. */ class ScriptOrigin { public: V8_INLINE ScriptOrigin( Local resource_name, Local resource_line_offset = Local(), Local resource_column_offset = Local(), Local resource_is_shared_cross_origin = Local(), Local script_id = Local(), Local source_map_url = Local(), Local resource_is_opaque = Local(), Local is_wasm = Local(), Local is_module = Local(), Local host_defined_options = Local()); V8_INLINE Local ResourceName() const; V8_INLINE Local ResourceLineOffset() const; V8_INLINE Local ResourceColumnOffset() const; V8_INLINE Local ScriptID() const; V8_INLINE Local SourceMapUrl() const; V8_INLINE Local HostDefinedOptions() const; V8_INLINE ScriptOriginOptions Options() const { return options_; } private: Local resource_name_; Local resource_line_offset_; Local resource_column_offset_; ScriptOriginOptions options_; Local script_id_; Local source_map_url_; Local host_defined_options_; }; /** * A compiled JavaScript script, not yet tied to a Context. */ class V8_EXPORT UnboundScript { public: /** * Binds the script to the currently entered context. */ Local