// 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.
#ifndef V8_API_API_H_
#define V8_API_API_H_
#include <memory>
#include "include/v8-container.h"
#include "include/v8-cpp-heap-external.h"
#include "include/v8-external.h"
#include "include/v8-function-callback.h"
#include "include/v8-proxy.h"
#include "include/v8-typed-array.h"
#include "include/v8-wasm.h"
#include "src/base/contextual.h"
#include "src/objects/bigint.h"
#include "src/objects/contexts.h"
#include "src/objects/js-array-buffer.h"
#include "src/objects/js-collection.h"
#include "src/objects/js-generator.h"
#include "src/objects/js-promise.h"
#include "src/objects/js-proxy.h"
#include "src/objects/objects.h"
#include "src/objects/shared-function-info.h"
#include "src/objects/source-text-module.h"
#include "src/objects/templates.h"
#include "src/utils/detachable-vector.h"
namespace v8 {
class DictionaryTemplate;
class Extension;
class Signature;
class Template;
enum class Intercepted : uint32_t;
namespace internal {
class Isolate;
class JSArrayBufferView;
class JSFinalizationRegistry;
} // namespace internal
namespace debug {
class AccessorPair;
class GeneratorObject;
class ScriptSource;
class Script;
class EphemeronTable;
} // namespace debug
template <typename T, internal::ExternalPointerTag tag>
inline T ToCData(i::Isolate* isolate, i::Tagged<i::Object> obj);
template <internal::ExternalPointerTag tag>
inline i::Address ToCData(i::Isolate* isolate, i::Tagged<i::Object> obj);
template <internal::ExternalPointerTag tag, typename T>
inline i::DirectHandle<i::UnionOf<i::Smi, i::Foreign>> FromCData(
i::Isolate* isolate, T obj);
template <internal::ExternalPointerTag tag>
inline i::DirectHandle<i::UnionOf<i::Smi, i::Foreign>> FromCData(
i::Isolate* isolate, i::Address obj);
class ApiFunction {
public:
explicit ApiFunction(i::Address addr) : addr_(addr) {}
i::Address address() { return addr_; }
private:
i::Address addr_;
};
class RegisteredExtension {
public:
static void Register(std::unique_ptr<Extension>);
static void UnregisterAll();
Extension* extension() const { return extension_.get(); }
RegisteredExtension* next() const { return next_; }
static RegisteredExtension* first_extension() { return first_extension_; }
private:
explicit RegisteredExtension(Extension*);
explicit RegisteredExtension(std::unique_ptr<Extension>);
std::unique_ptr<Extension> extension_;
RegisteredExtension* next_ = nullptr;
static RegisteredExtension* first_extension_;
};
#define TO_LOCAL_LIST(V) \
V(ToLocal, AccessorPair, debug::AccessorPair) \
V(ToLocal, NativeContext, Context) \
V(ToLocal, Object, Value) \
V(ToLocal, Module, Module) \
V(ToLocal, Name, Name) \
V(ToLocal, String, String) \
V(ToLocal, InternalizedString, String) \
V(ToLocal, Symbol, Symbol) \
V(ToLocal, JSDate, Object) \
V(ToLocal, JSRegExp, RegExp) \
V(ToLocal, JSReceiver, Object) \
V(ToLocal, JSObject, Object) \
V(ToLocal, JSFunction, Function) \
V(ToLocal, JSArray, Array) \
V(ToLocal, JSMap, Map) \
V(ToLocal, JSSet, Set) \
V(ToLocal, JSProxy, Proxy) \
V(ToLocal, JSArrayBuffer, ArrayBuffer) \
V(ToLocal, JSArrayBufferView, ArrayBufferView) \
V(ToLocal, JSDataView, DataView) \
V(ToLocal, JSPromise, Promise) \
V(ToLocal, JSRabGsabDataView, DataView) \
V(ToLocal, JSTypedArray, TypedArray) \
V(ToLocalShared, JSArrayBuffer, SharedArrayBuffer) \
V(ToLocal, FunctionTemplateInfo, FunctionTemplate) \
V(ToLocal, ObjectTemplateInfo, ObjectTemplate) \
V(ToLocal, DictionaryTemplateInfo, DictionaryTemplate) \
V(SignatureToLocal, FunctionTemplateInfo, Signature) \
V(MessageToLocal, Object, Message) \
V(StackTraceToLocal, StackTraceInfo, StackTrace) \
V(StackFrameToLocal, StackFrameInfo, StackFrame) \
V(NumberToLocal, Object, Number) \
V(IntegerToLocal, Object, Integer) \
V(Uint32ToLocal, Object, Uint32) \
V(ToLocal, BigInt, BigInt) \
V(ExternalToLocal, JSObject, External) \
V(CallableToLocal, JSReceiver, Function) \
V(ToLocalPrimitive, Object, Primitive) \
V(FixedArrayToLocal, FixedArray, FixedArray) \
V(PrimitiveArrayToLocal, FixedArray, PrimitiveArray) \
V(ToLocal, ScriptOrModule, ScriptOrModule) \
V(CppHeapExternalToLocal, CppHeapExternalObject, CppHeapExternal) \
IF_WASM(V, ToLocal, WasmMemoryObject, WasmMemoryObject) \
IF_WASM(V, ToLocal, WasmModuleObject, WasmModuleObject)
#define TO_LOCAL_NAME_LIST(V) \
V(ToLocal) \
V(ToLocalShared) \
V(SignatureToLocal) \
V(MessageToLocal) \
V(StackTraceToLocal) \
V(StackFrameToLocal) \
V(NumberToLocal) \
V(IntegerToLocal) \
V(Uint32ToLocal) \
V(ExternalToLocal) \
V(CallableToLocal) \
V(ToLocalPrimitive) \
V(FixedArrayToLocal) \
V(PrimitiveArrayToLocal) \
V(CppHeapExternalToLocal)
#define OPEN_HANDLE_LIST(V) \
V(Template, TemplateInfoWithProperties) \
V(FunctionTemplate, FunctionTemplateInfo) \
V(ObjectTemplate, ObjectTemplateInfo) \
V(DictionaryTemplate, DictionaryTemplateInfo) \
V(Signature, FunctionTemplateInfo) \
V(Data, Object) \
V(Number, Number) \
V(RegExp, JSRegExp) \
V(Object, JSReceiver) \
V(Array, JSArray) \
V(Map, JSMap) \
V(Set, JSSet) \
V(ArrayBuffer, JSArrayBuffer) \
V(ArrayBufferView, JSArrayBufferView) \
V(TypedArray, JSTypedArray) \
V(Uint8Array, JSTypedArray) \
V(Uint8ClampedArray, JSTypedArray) \
V(Int8Array, JSTypedArray) \
V(Uint16Array, JSTypedArray) \
V(Int16Array, JSTypedArray) \
V(Uint32Array, JSTypedArray) \
V(Int32Array, JSTypedArray) \
V(Float16Array, JSTypedArray) \
V(Float32Array, JSTypedArray) \
V(Float64Array, JSTypedArray) \
V(DataView, JSDataViewOrRabGsabDataView) \
V(SharedArrayBuffer, JSArrayBuffer) \
V(Name, Name) \
V(String, String) \
V(Symbol, Symbol) \
V(Script, JSFunction) \
V(UnboundModuleScript, SharedFunctionInfo) \
V(UnboundScript, SharedFunctionInfo) \
V(Module, Module) \
V(Function, JSReceiver) \
V(CompileHintsCollector, Script) \
V(Message, JSMessageObject) \
V(Context, NativeContext) \
V(External, Object) \
V(StackTrace, StackTraceInfo) \
V(StackFrame, StackFrameInfo) \
V(Proxy, JSProxy) \
V(debug::GeneratorObject, JSGeneratorObject) \
V(debug::ScriptSource, HeapObject) \
V(debug::Script, Script) \
V(debug::EphemeronTable, EphemeronHashTable) \
V(debug::AccessorPair, AccessorPair) \
V(Promise, JSPromise) \
V(Primitive, Object) \
V(PrimitiveArray, FixedArray) \
V(BigInt, BigInt) \
V(ScriptOrModule, ScriptOrModule) \
V(FixedArray, FixedArray) \
V(ModuleRequest, ModuleRequest) \
V(CppHeapExternal, CppHeapExternalObject) \
IF_WASM(V, WasmMemoryObject, WasmMemoryObject)
class Utils {
public:
static V8_INLINE bool ApiCheck(bool condition, const char* location,
const char* message) {
if (V8_UNLIKELY(!condition)) {
Utils::ReportApiFailure(location, message);
}
return condition;
}
static void ReportOOMFailure(i::Isolate* isolate, const char* location,
const OOMDetails& details);
// TODO(42203211): It would be nice if we could keep only a version with
// direct handles. But the implicit conversion from handles to direct handles
// combined with the heterogeneous copy constructor for direct handles make
// this ambiguous.
#define DECLARE_TO_LOCAL(Name) \
template <template <typename> typename HandleType, typename T> \
requires(std::is_convertible_v<HandleType<T>, i::DirectHandle<T>> && \
!std::is_same_v<HandleType<T>, i::DirectHandle<T>>) \
static inline auto Name(HandleType<T> obj) { \
return Name(i::DirectHandle<T>(obj)); \
}
TO_LOCAL_NAME_LIST(DECLARE_TO_LOCAL)
#undef DECLARE_TO_LOCAL
#define DECLARE_TO_LOCAL(Name, From, To) \
static inline Local<v8::To> Name(i::DirectHandle<i::From> obj);
TO_LOCAL_LIST(DECLARE_TO_LOCAL)
#undef DECLARE_TO_LOCAL
template <typename T>
static inline MaybeLocal<T> ToMaybe(Local<T> value) {
return value;
}
template <template <typename> typename HandleType, typename From>
requires std::is_convertible_v<HandleType<From>, i::MaybeDirectHandle<From>>
static inline auto ToMaybeLocal(HandleType<From> maybe_obj_in)
-> decltype(ToMaybe(ToLocal(std::declval<i::DirectHandle<From>>()))) {
i::MaybeDirectHandle<From> maybe_obj = maybe_obj_in;
i::DirectHandle<From> obj;
if (!maybe_obj.ToHandle(&obj)) return {};
return ToMaybe(ToLocal(obj));
}
#define DECLARE_TO_LOCAL_TYPED_ARRAY(Type, typeName, TYPE, ctype) \
static inline Local<v8::Type##Array> ToLocal##Type##Array( \
i::DirectHandle<i::JSTypedArray> obj);
TYPED_ARRAYS(DECLARE_TO_LOCAL_TYPED_ARRAY)
#undef DECLARE_TO_LOCAL_TYPED_ARRAY
#define DECLARE_OPEN_HANDLE(From, To) \
static inline i::Handle<i::To> OpenHandle(const From* that, \
bool allow_empty_handle = false); \
static inline i::DirectHandle<i::To> OpenDirectHandle( \
const From* that, bool allow_empty_handle = false); \
static inline i::IndirectHandle<i::To> OpenIndirectHandle( \
const From* that, bool allow_empty_handle = false);
OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE)
#undef DECLARE_OPEN_HANDLE
template <class From, class To>
static inline Local<To> Convert(i::DirectHandle<From> obj);
template <class T>
static inline i::Handle<i::Object> OpenPersistent(
const v8::PersistentBase<T>& persistent) {
return i::Handle<i::Object>(persistent.slot());
}
template <class T>
static inline i::DirectHandle<i::Object> OpenPersistent(
v8::Persistent<T>* persistent) {
return OpenPersistent(*persistent);
}
template <class From, class To>
static inline i::Handle<To> OpenHandle(v8::Local<From> handle) {
return OpenHandle(*handle);
}
template <class From, class To>
static inline i::DirectHandle<To> OpenDirectHandle(v8::Local<From> handle) {
return OpenDirectHandle(*handle);
}
private:
V8_NOINLINE V8_PRESERVE_MOST static void ReportApiFailure(
const char* location, const char* message);
};
// Convert DirectHandle to Local w/o type inference or type checks.
// To get type inference (translating from internal to API types), use
// Utils::ToLocal.
template <class T>
inline v8::Local<T> ToApiHandle(i::DirectHandle<i::Object> obj) {
return Utils::Convert<i::Object, T>(obj);
}
namespace internal {
class PersistentHandles;
// This is a wrapper function called from CallApiGetter builtin when profiling
// or side-effect checking is enabled. It's supposed to set up the runtime
// call stats scope and check if the getter has side-effects in case debugger
// enabled the side-effects checking mode.
void InvokeAccessorGetterCallback(
v8::Local<v8::Name> property,
const v8::PropertyCallbackInfo<v8::Value>& info);
// This is a wrapper function called from CallNamedInterceptorGetter builtin
// when profiling or side-effect checking is enabled. It's supposed to set up
// the runtime call stats scope and check if the getter has side-effects
// in case debugger enabled the side-effects checking mode.
v8::Intercepted InvokeNamedInterceptorGetterCallback(
v8::Local<v8::Name> property,
const v8::PropertyCallbackInfo<v8::Value>& info);
// This is a wrapper function called from CallNamedInterceptorSetter builtin
// when profiling or side-effect checking is enabled. It's supposed to set up
// the runtime call stats scope and check if the setter has side-effects
// in case debugger enabled the side-effects checking mode.
v8::Intercepted InvokeNamedInterceptorSetterCallback(
v8::Local<v8::Name> property, v8::Local<v8::Value> value,
const v8::PropertyCallbackInfo<v8::Boolean>& info);
// This is a wrapper function called from CallApiCallback builtin when profiling
// or side-effect checking is enabled. It's supposed to set up the runtime
// call stats scope and check if the callback has side-effects in case debugger
// enabled the side-effects checking mode.
// It gets additional argument, the v8::FunctionCallback address, via
// IsolateData::api_callback_thunk_argument slot.
void InvokeFunctionCallbackGeneric(
const v8::FunctionCallbackInfo<v8::Value>& info);
void InvokeFunctionCallbackOptimized(
const v8::FunctionCallbackInfo<v8::Value>& info);
void InvokeFinalizationRegistryCleanupFromTask(
DirectHandle<NativeContext> native_context,
DirectHandle<JSFinalizationRegistry> finalization_registry);
template <typename T>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
T ConvertDouble(double d);
template <typename T>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
bool ValidateCallbackInfo(const FunctionCallbackInfo<T>& info);
template <typename T>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
bool ValidateCallbackInfo(const PropertyCallbackInfo<T>& info);
#ifdef ENABLE_SLOW_DCHECKS
DECLARE_CONTEXTUAL_VARIABLE_WITH_DEFAULT(StackAllocatedCheck, const bool, true);
#endif
} // namespace internal
} // namespace v8
#endif // V8_API_API_H_