@ 261106.6
current
// 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_