// 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
#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 CFunction;
class CallHandlerHelper;
class Context;
class CppHeap;
class CTypeInfo;
class Data;
class Date;
class EscapableHandleScope;
class External;
class Function;
class FunctionTemplate;
class HeapProfiler;
class ImplementationUtilities;
class Int32;
class Integer;
class Isolate;
class Isolate;
class MicrotaskQueue;
class Name;
class Number;
class NumberObject;
class Object;
class ObjectOperationDescriptor;
class ObjectTemplate;
class Platform;
class Primitive;
class PrimitiveArray;
class Private;
class Promise;
class PropertyDescriptor;
class Proxy;
class RawOperationDescriptor;
class Script;
class SharedArrayBuffer;
class Signature;
class StackFrame;
class StackTrace;
class StartupData;
class String;
class StringObject;
class Symbol;
class SymbolObject;
class TracedReferenceBase;
class Uint32;
class Utils;
class Value;
class WasmMemoryObject;
class WasmModuleObject;
template
class GlobalValueMap;
template
class PersistentValueMapBase;
template class NonCopyablePersistentTraits;
template >
class Persistent;
template
class BasicTracedReference;
template
class Eternal;
template
class Global;
template
class Local;
template
class Maybe;
template
class MaybeLocal;
template
class TracedGlobal;
template
class TracedReference;
template class PersistentValueMap;
template class WeakCallbackObject;
template
class PersistentBase;
template
class PersistentValueVector;
template class FunctionCallbackInfo;
template class PropertyCallbackInfo;
template class ReturnValue;
namespace internal {
class BasicTracedReferenceExtractor;
class ExternalString;
class FunctionCallbackArguments;
class GlobalHandles;
class Heap;
class HeapObject;
class Isolate;
class LocalEmbedderHeapTracer;
class MicrotaskQueue;
class PropertyCallbackArguments;
class ReadOnlyHeap;
class ScopedExternalStringLock;
class ThreadLocalTop;
struct ScriptStreamingData;
enum class ArgumentsType;
template
class Arguments;
template
class CustomArguments;
namespace wasm {
class NativeModule;
class StreamingDecoder;
} // namespace wasm
} // namespace internal
namespace metrics {
class Recorder;
} // namespace metrics
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 BasicTracedReference& that);
private:
friend class TracedReferenceBase;
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 BasicTracedReference;
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:
using Callback = void (*)(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;
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:
using NonCopyablePersistent = Persistent>;
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 {
using CopyablePersistent = Persistent>;
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) {
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) {
#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 {
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); }
/*
* For compatibility with Chromium's base::Bind (base::Passed).
*/
using MoveOnlyTypeForCPP03 = void;
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 {};
class TracedReferenceBase {
public:
/**
* Returns true if the reference is empty, i.e., has not been assigned
* 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.
*/
V8_INLINE v8::Local Get(v8::Isolate* isolate) const;
/**
* Returns true if this TracedReference is empty, i.e., has not been
* assigned an object. This version of IsEmpty is thread-safe.
*/
bool IsEmptyThreadSafe() const {
return this->GetSlotThreadSafe() == nullptr;
}
/**
* 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;
protected:
/**
* Update this reference in a thread-safe way.
*/
void SetSlotThreadSafe(void* new_val) {
reinterpret_cast*>(&val_)->store(
new_val, std::memory_order_relaxed);
}
/**
* Get this reference in a thread-safe way
*/
const void* GetSlotThreadSafe() const {
return reinterpret_cast const*>(&val_)->load(
std::memory_order_relaxed);
}
V8_EXPORT void CheckValue() const;
// val_ points to a GlobalHandles node.
internal::Address* val_ = nullptr;
friend class internal::BasicTracedReferenceExtractor;
template
friend class Local;
template
friend bool operator==(const TracedReferenceBase&, const Local&);
friend bool operator==(const TracedReferenceBase&,
const TracedReferenceBase&);
};
/**
* A traced handle with copy and move semantics. The handle is to be used
* together with |v8::EmbedderHeapTracer| or as part of GarbageCollected objects
* (see v8-cppgc.h) and specifies edges from C++ objects to JavaScript.
*
* The exact semantics are:
* - Tracing garbage collections use |v8::EmbedderHeapTracer| or cppgc.
* - Non-tracing garbage collections refer to
* |v8::EmbedderRootsHandler::IsRoot()| 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 BasicTracedReference : public TracedReferenceBase {
public:
/**
* Construct a Local from this handle.
*/
Local Get(Isolate* isolate) const { return Local::New(isolate, *this); }
template
V8_INLINE BasicTracedReference& As() const {
return reinterpret_cast&>(
const_cast&>(*this));
}
T* operator->() const {
#ifdef V8_ENABLE_CHECKS
CheckValue();
#endif // V8_ENABLE_CHECKS
return reinterpret_cast(val_);
}
T* operator*() const {
#ifdef V8_ENABLE_CHECKS
CheckValue();
#endif // V8_ENABLE_CHECKS
return reinterpret_cast(val_);
}
private:
enum DestructionMode { kWithDestructor, kWithoutDestructor };
/**
* An empty BasicTracedReference without storage cell.
*/
BasicTracedReference() = default;
V8_INLINE static internal::Address* New(Isolate* isolate, T* that, void* slot,
DestructionMode destruction_mode);
friend class EmbedderHeapTracer;
template
friend class Local;
friend class Object;
template
friend class TracedGlobal;
template
friend class TracedReference;
template
friend class BasicTracedReference;
template
friend class ReturnValue;
};
/**
* A traced handle with destructor that clears the handle. For more details see
* BasicTracedReference.
*/
template
class TracedGlobal : public BasicTracedReference {
public:
using BasicTracedReference::Reset;
/**
* Destructor resetting the handle.Is
*/
~TracedGlobal() { this->Reset(); }
/**
* An empty TracedGlobal without storage cell.
*/
TracedGlobal() : BasicTracedReference() {}
/**
* 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) : BasicTracedReference() {
this->val_ = this->New(isolate, that.val_, &this->val_,
BasicTracedReference::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 BasicTracedReference.
*
* 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 BasicTracedReference {
public:
using BasicTracedReference::Reset;
/**
* An empty TracedReference without storage cell.
*/
TracedReference() : BasicTracedReference() {}
/**
* Construct a TracedReference from a Local.
*
* When the Local is non-empty, a new storage cell is created
* pointing to the same object.
*/
template