/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/include/v8-fast-api-calls.h
784 строки
29 KB
Michaël Zasso
deps: update V8 to 14.3.127.12
13 ноя 2025, 17:08
Не верифицирован
13 ноя 2025, 17:08
53379f3
Код
Авторство
О чём код?
// Copyright 2020 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 INCLUDE_V8_FAST_API_CALLS_H_ #define INCLUDE_V8_FAST_API_CALLS_H_ /** * This file provides additional API on top of the default one for making * API calls, which come from embedder C++ functions. The functions are being * called directly from optimized code, doing all the necessary typechecks * in the compiler itself, instead of on the embedder side. Hence the "fast" * in the name. Example usage might look like: * * \code * void FastMethod(int param, bool another_param); * * v8::FunctionTemplate::New(isolate, SlowCallback, data, * signature, length, constructor_behavior * side_effect_type, * &v8::CFunction::Make(FastMethod)); * \endcode * * By design, fast calls are limited by the following requirements, which * the embedder should enforce themselves: * - they should not allocate on the JS heap; * - they should not trigger JS execution. * To enforce them, the embedder could use the existing * v8::Isolate::DisallowJavascriptExecutionScope and a utility similar to * Blink's NoAllocationScope: * https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/platform/heap/thread_state_scopes.h;l=16 * * Due to these limitations, it's not directly possible to report errors by * throwing a JS exception or to otherwise do an allocation. There is an * alternative way of creating fast calls that supports falling back to the * slow call and then performing the necessary allocation. When one creates * the fast method by using CFunction::MakeWithFallbackSupport instead of * CFunction::Make, the fast callback gets as last parameter an output variable, * through which it can request falling back to the slow call. So one might * declare their method like: * * \code * void FastMethodWithFallback(int param, FastApiCallbackOptions& options); * \endcode * * If the callback wants to signal an error condition or to perform an * allocation, it must set options.fallback to true and do an early return from * the fast method. Then V8 checks the value of options.fallback and if it's * true, falls back to executing the SlowCallback, which is capable of reporting * the error (either by throwing a JS exception or logging to the console) or * doing the allocation. It's the embedder's responsibility to ensure that the * fast callback is idempotent up to the point where error and fallback * conditions are checked, because otherwise executing the slow callback might * produce visible side-effects twice. * * An example for custom embedder type support might employ a way to wrap/ * unwrap various C++ types in JSObject instances, e.g: * * \code * * // Helper method with a check for field count. * template <typename T, int offset> * inline T* GetInternalField(v8::Local<v8::Object> wrapper) { * assert(offset < wrapper->InternalFieldCount()); * return reinterpret_cast<T*>( * wrapper->GetAlignedPointerFromInternalField(offset)); * } * * class CustomEmbedderType { * public: * // Returns the raw C object from a wrapper JS object. * static CustomEmbedderType* Unwrap(v8::Local<v8::Object> wrapper) { * return GetInternalField<CustomEmbedderType, * kV8EmbedderWrapperObjectIndex>(wrapper); * } * static void FastMethod(v8::Local<v8::Object> receiver_obj, int param) { * CustomEmbedderType* receiver = static_cast<CustomEmbedderType*>( * receiver_obj->GetAlignedPointerFromInternalField( * kV8EmbedderWrapperObjectIndex)); * * // Type checks are already done by the optimized code. * // Then call some performance-critical method like: * // receiver->Method(param); * } * * static void SlowMethod( * const v8::FunctionCallbackInfo<v8::Value>& info) { * v8::Local<v8::Object> instance = * v8::Local<v8::Object>::Cast(info.Holder()); * CustomEmbedderType* receiver = Unwrap(instance); * // TODO: Do type checks and extract {param}. * receiver->Method(param); * } * }; * * // The following setup function can be templatized based on * // the {embedder_object} argument. * void SetupCustomEmbedderObject(v8::Isolate* isolate, * v8::Local<v8::Context> context, * CustomEmbedderType* embedder_object) { * v8::CFunction c_func = * MakeV8CFunction(CustomEmbedderType::FastMethod); * * Local<v8::FunctionTemplate> method_template = * v8::FunctionTemplate::New( * isolate, CustomEmbedderType::SlowMethod, v8::Local<v8::Value>(), * v8::Local<v8::Signature>(), 1, v8::ConstructorBehavior::kAllow, * v8::SideEffectType::kHasSideEffect, &c_func); * * v8::Local<v8::ObjectTemplate> object_template = * v8::ObjectTemplate::New(isolate); * object_template->SetInternalFieldCount( * kV8EmbedderWrapperObjectIndex + 1); * object_template->Set(isolate, "method", method_template); * * // Instantiate the wrapper JS object. * v8::Local<v8::Object> object = * object_template->NewInstance(context).ToLocalChecked(); * object->SetAlignedPointerInInternalField( * kV8EmbedderWrapperObjectIndex, * reinterpret_cast<void*>(embedder_object)); * * // TODO: Expose {object} where it's necessary. * } * \endcode * * For instance if {object} is exposed via a global "obj" variable, * one could write in JS: * function hot_func() { * obj.method(42); * } * and once {hot_func} gets optimized, CustomEmbedderType::FastMethod * will be called instead of the slow version, with the following arguments: * receiver := the {embedder_object} from above * param := 42 * * Currently supported return types: * - void * - bool * - int32_t * - uint32_t * - float32_t * - float64_t * Currently supported argument types: * - pointer to an embedder type * - JavaScript array of primitive types * - bool * - int32_t * - uint32_t * - int64_t * - uint64_t * - float32_t * - float64_t * * The 64-bit integer types currently have the IDL (unsigned) long long * semantics: https://heycam.github.io/webidl/#abstract-opdef-converttoint * In the future we'll extend the API to also provide conversions from/to * BigInt to preserve full precision. * The floating point types currently have the IDL (unrestricted) semantics, * which is the only one used by WebGL. We plan to add support also for * restricted floats/doubles, similarly to the BigInt conversion policies. * We also differ from the specific NaN bit pattern that WebIDL prescribes * (https://heycam.github.io/webidl/#es-unrestricted-float) in that Blink * passes NaN values as-is, i.e. doesn't normalize them. * * To be supported types: * - TypedArrays and ArrayBuffers * - arrays of embedder types * * * The API offers a limited support for function overloads: * * \code * void FastMethod_2Args(int param, bool another_param); * void FastMethod_3Args(int param, bool another_param, int third_param); * * v8::CFunction fast_method_2args_c_func = * MakeV8CFunction(FastMethod_2Args); * v8::CFunction fast_method_3args_c_func = * MakeV8CFunction(FastMethod_3Args); * const v8::CFunction fast_method_overloads[] = {fast_method_2args_c_func, * fast_method_3args_c_func}; * Local<v8::FunctionTemplate> method_template = * v8::FunctionTemplate::NewWithCFunctionOverloads( * isolate, SlowCallback, data, signature, length, * constructor_behavior, side_effect_type, * {fast_method_overloads, 2}); * \endcode * * In this example a single FunctionTemplate is associated to multiple C++ * functions. The overload resolution is currently only based on the number of * arguments passed in a call. For example, if this method_template is * registered with a wrapper JS object as described above, a call with two * arguments: * obj.method(42, true); * will result in a fast call to FastMethod_2Args, while a call with three or * more arguments: * obj.method(42, true, 11); * will result in a fast call to FastMethod_3Args. Instead a call with less than * two arguments, like: * obj.method(42); * would not result in a fast call but would fall back to executing the * associated SlowCallback. */ #include <stddef.h> #include <stdint.h> #include <tuple> #include <type_traits> #include "v8-external.h" // NOLINT(build/include_directory) #include "v8-internal.h" // NOLINT(build/include_directory) #include "v8-local-handle.h" // NOLINT(build/include_directory) #include "v8-typed-array.h" // NOLINT(build/include_directory) #include "v8-value.h" // NOLINT(build/include_directory) #include "v8config.h" // NOLINT(build/include_directory) namespace v8 { class Isolate; class CTypeInfo { public: enum class Type : uint8_t { kVoid, kBool, kUint8, kInt32, kUint32, kInt64, kUint64, kFloat32, kFloat64, kPointer, kV8Value, kSeqOneByteString, kApiObject, // This will be deprecated once all users have // migrated from v8::ApiObject to v8::Local<v8::Value>. kAny, // This is added to enable untyped representation of fast // call arguments for test purposes. It can represent any of // the other types stored in the same memory as a union // (see AnyCType declared below). This allows for // uniform passing of arguments w.r.t. their location // (in a register or on the stack), independent of their // actual type. It's currently used by the arm64 simulator // and can be added to the other simulators as well when fast // calls having both GP and FP params need to be supported. }; // kCallbackOptionsType is not part of the Type enum // because it is only used internally. Use value 255 that is larger // than any valid Type enum. static constexpr Type kCallbackOptionsType = Type(255); enum class Flags : uint8_t { kNone = 0, kAllowSharedBit = 1 << 0, // Must be an ArrayBuffer or TypedArray kEnforceRangeBit = 1 << 1, // T must be integral kClampBit = 1 << 2, // T must be integral kIsRestrictedBit = 1 << 3, // T must be float or double }; explicit constexpr CTypeInfo(Type type, Flags flags = Flags::kNone) : type_(type), flags_(flags) {} typedef uint32_t Identifier; explicit constexpr CTypeInfo(Identifier identifier) : type_(static_cast<Type>((identifier >> 8) & 255)), flags_(static_cast<Flags>(identifier & 255)) {} constexpr Identifier GetId() const { return static_cast<uint8_t>(type_) << 8 | static_cast<uint8_t>(flags_); } constexpr Type GetType() const { return type_; } constexpr Flags GetFlags() const { return flags_; } static constexpr bool IsIntegralType(Type type) { return type == Type::kUint8 || type == Type::kInt32 || type == Type::kUint32 || type == Type::kInt64 || type == Type::kUint64; } static constexpr bool IsFloatingPointType(Type type) { return type == Type::kFloat32 || type == Type::kFloat64; } static constexpr bool IsPrimitive(Type type) { return IsIntegralType(type) || IsFloatingPointType(type) || type == Type::kBool; } private: Type type_; Flags flags_; }; struct FastOneByteString { const char* data; uint32_t length; }; class V8_EXPORT CFunctionInfo { public: enum class Int64Representation : uint8_t { kNumber = 0, // Use numbers to represent 64 bit integers. kBigInt = 1, // Use BigInts to represent 64 bit integers. }; // Construct a struct to hold a CFunction's type information. // |return_info| describes the function's return type. // |arg_info| is an array of |arg_count| CTypeInfos describing the // arguments. Only the last argument may be of the special type // CTypeInfo::kCallbackOptionsType. CFunctionInfo(const CTypeInfo& return_info, unsigned int arg_count, const CTypeInfo* arg_info, Int64Representation repr = Int64Representation::kNumber); const CTypeInfo& ReturnInfo() const { return return_info_; } // The argument count, not including the v8::FastApiCallbackOptions // if present. unsigned int ArgumentCount() const { return HasOptions() ? arg_count_ - 1 : arg_count_; } Int64Representation GetInt64Representation() const { return repr_; } // |index| must be less than ArgumentCount(). // Note: if the last argument passed on construction of CFunctionInfo // has type CTypeInfo::kCallbackOptionsType, it is not included in // ArgumentCount(). const CTypeInfo& ArgumentInfo(unsigned int index) const; bool HasOptions() const { // The options arg is always the last one. return arg_count_ > 0 && arg_info_[arg_count_ - 1].GetType() == CTypeInfo::kCallbackOptionsType; } private: const CTypeInfo return_info_; const Int64Representation repr_; const unsigned int arg_count_; const CTypeInfo* arg_info_; }; struct FastApiCallbackOptions; // Provided for testing. union V8_TRIVIAL_ABI AnyCType { AnyCType() : int64_value(0) {} #if defined(V8_ENABLE_LOCAL_OFF_STACK_CHECK) && V8_HAS_ATTRIBUTE_TRIVIAL_ABI // In this case, Local<T> is not trivially copyable and the implicit // copy constructor and copy assignment for the union are deleted. AnyCType(const AnyCType& other) : int64_value(other.int64_value) {} AnyCType& operator=(const AnyCType& other) { int64_value = other.int64_value; return *this; } #endif bool bool_value; int32_t int32_value; uint32_t uint32_value; int64_t int64_value; uint64_t uint64_value; float float_value; double double_value; void* pointer_value; Local<Object> object_value; Local<Array> sequence_value; const FastOneByteString* string_value; FastApiCallbackOptions* options_value; }; static_assert( sizeof(AnyCType) == 8, "The union AnyCType should have size == 64 bits, as this is assumed " "by EffectControlLinearizer."); class V8_EXPORT CFunction { public: constexpr CFunction() : address_(nullptr), type_info_(nullptr) {} const CTypeInfo& ReturnInfo() const { return type_info_->ReturnInfo(); } const CTypeInfo& ArgumentInfo(unsigned int index) const { return type_info_->ArgumentInfo(index); } unsigned int ArgumentCount() const { return type_info_->ArgumentCount(); } const void* GetAddress() const { return address_; } CFunctionInfo::Int64Representation GetInt64Representation() const { return type_info_->GetInt64Representation(); } const CFunctionInfo* GetTypeInfo() const { return type_info_; } enum class OverloadResolution { kImpossible, kAtRuntime, kAtCompileTime }; template <typename F> static CFunction Make(F* func, CFunctionInfo::Int64Representation int64_rep = CFunctionInfo::Int64Representation::kNumber) { CFunction result = ArgUnwrap<F*>::Make(func, int64_rep); result.GetInt64Representation(); return result; } // Provided for testing purposes. template <typename R, typename... Args, typename R_Patch, typename... Args_Patch> static CFunction Make(R (*func)(Args...), R_Patch (*patching_func)(Args_Patch...), CFunctionInfo::Int64Representation int64_rep = CFunctionInfo::Int64Representation::kNumber) { CFunction c_func = ArgUnwrap<R (*)(Args...)>::Make(func, int64_rep); static_assert( sizeof...(Args_Patch) == sizeof...(Args), "The patching function must have the same number of arguments."); c_func.address_ = reinterpret_cast<void*>(patching_func); return c_func; } CFunction(const void* address, const CFunctionInfo* type_info); private: const void* address_; const CFunctionInfo* type_info_; template <typename F> class ArgUnwrap { static_assert(sizeof(F) != sizeof(F), "CFunction must be created from a function pointer."); }; template <typename R, typename... Args> class ArgUnwrap<R (*)(Args...)> { public: static CFunction Make(R (*func)(Args...), CFunctionInfo::Int64Representation int64_rep = CFunctionInfo::Int64Representation::kNumber); }; }; /** * A struct which may be passed to a fast call callback, like so: * \code * void FastMethodWithOptions(int param, FastApiCallbackOptions& options); * \endcode */ struct FastApiCallbackOptions { /** * Creates a new instance of FastApiCallbackOptions for testing purpose. The * returned instance may be filled with mock data. */ static FastApiCallbackOptions CreateForTesting(Isolate* isolate) { return {}; } v8::Isolate* isolate = nullptr; /** * The `data` passed to the FunctionTemplate constructor, or `undefined`. */ v8::Local<v8::Value> data; }; namespace internal { // Helper to count the number of occurances of `T` in `List` template <typename T, typename... List> struct count : std::integral_constant<int, 0> {}; template <typename T, typename... Args> struct count<T, T, Args...> : std::integral_constant<std::size_t, 1 + count<T, Args...>::value> {}; template <typename T, typename U, typename... Args> struct count<T, U, Args...> : count<T, Args...> {}; template <CFunctionInfo::Int64Representation Representation, typename RetBuilder, typename... ArgBuilders> class CFunctionInfoImpl : public CFunctionInfo { static constexpr int kOptionsArgCount = count<FastApiCallbackOptions&, ArgBuilders...>(); static constexpr int kReceiverCount = 1; static_assert(kOptionsArgCount == 0 || kOptionsArgCount == 1, "Only one options parameter is supported."); static_assert(sizeof...(ArgBuilders) >= kOptionsArgCount + kReceiverCount, "The receiver or the options argument is missing."); public: constexpr CFunctionInfoImpl() : CFunctionInfo(RetBuilder::Build(), sizeof...(ArgBuilders), arg_info_storage_, Representation), arg_info_storage_{ArgBuilders::Build()...} { constexpr CTypeInfo::Type kReturnType = RetBuilder::Build().GetType(); static_assert(kReturnType == CTypeInfo::Type::kVoid || kReturnType == CTypeInfo::Type::kBool || kReturnType == CTypeInfo::Type::kInt32 || kReturnType == CTypeInfo::Type::kUint32 || kReturnType == CTypeInfo::Type::kInt64 || kReturnType == CTypeInfo::Type::kUint64 || kReturnType == CTypeInfo::Type::kFloat32 || kReturnType == CTypeInfo::Type::kFloat64 || kReturnType == CTypeInfo::Type::kPointer || kReturnType == CTypeInfo::Type::kAny, "String and api object values are not currently " "supported return types."); } private: const CTypeInfo arg_info_storage_[sizeof...(ArgBuilders)]; }; template <typename T> struct TypeInfoHelper { static_assert(sizeof(T) != sizeof(T), "This type is not supported"); }; #define SPECIALIZE_GET_TYPE_INFO_HELPER_FOR(T, Enum) \ template <> \ struct TypeInfoHelper<T> { \ static constexpr CTypeInfo::Flags Flags() { \ return CTypeInfo::Flags::kNone; \ } \ \ static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::Enum; } \ }; template <CTypeInfo::Type type> struct CTypeInfoTraits {}; #define DEFINE_TYPE_INFO_TRAITS(CType, Enum) \ template <> \ struct CTypeInfoTraits<CTypeInfo::Type::Enum> { \ using ctype = CType; \ }; #define PRIMITIVE_C_TYPES(V) \ V(bool, kBool) \ V(uint8_t, kUint8) \ V(int32_t, kInt32) \ V(uint32_t, kUint32) \ V(int64_t, kInt64) \ V(uint64_t, kUint64) \ V(float, kFloat32) \ V(double, kFloat64) \ V(void*, kPointer) // Same as above, but includes deprecated types for compatibility. #define ALL_C_TYPES(V) \ PRIMITIVE_C_TYPES(V) \ V(void, kVoid) \ V(v8::Local<v8::Value>, kV8Value) \ V(v8::Local<v8::Object>, kV8Value) \ V(v8::Local<v8::Array>, kV8Value) \ V(AnyCType, kAny) // ApiObject was a temporary solution to wrap the pointer to the v8::Value. // Please use v8::Local<v8::Value> in new code for the arguments and // v8::Local<v8::Object> for the receiver, as ApiObject will be deprecated. ALL_C_TYPES(SPECIALIZE_GET_TYPE_INFO_HELPER_FOR) PRIMITIVE_C_TYPES(DEFINE_TYPE_INFO_TRAITS) #undef PRIMITIVE_C_TYPES #undef ALL_C_TYPES #undef TYPED_ARRAY_C_TYPES template <> struct TypeInfoHelper<FastApiCallbackOptions&> { static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; } static constexpr CTypeInfo::Type Type() { return CTypeInfo::kCallbackOptionsType; } }; template <> struct TypeInfoHelper<const FastOneByteString&> { static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; } static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::kSeqOneByteString; } }; #define STATIC_ASSERT_IMPLIES(COND, ASSERTION, MSG) \ static_assert(((COND) == 0) || (ASSERTION), MSG) } // namespace internal template <typename T, CTypeInfo::Flags... Flags> class V8_EXPORT CTypeInfoBuilder { public: using BaseType = T; static constexpr CTypeInfo Build() { constexpr CTypeInfo::Flags kFlags = MergeFlags(internal::TypeInfoHelper<T>::Flags(), Flags...); constexpr CTypeInfo::Type kType = internal::TypeInfoHelper<T>::Type(); STATIC_ASSERT_IMPLIES( uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kEnforceRangeBit), CTypeInfo::IsIntegralType(kType), "kEnforceRangeBit is only allowed for integral types."); STATIC_ASSERT_IMPLIES( uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kClampBit), CTypeInfo::IsIntegralType(kType), "kClampBit is only allowed for integral types."); STATIC_ASSERT_IMPLIES( uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kIsRestrictedBit), CTypeInfo::IsFloatingPointType(kType), "kIsRestrictedBit is only allowed for floating point types."); // Return the same type with the merged flags. return CTypeInfo(internal::TypeInfoHelper<T>::Type(), kFlags); } private: template <typename... Rest> static constexpr CTypeInfo::Flags MergeFlags(CTypeInfo::Flags flags, Rest... rest) { return CTypeInfo::Flags(uint8_t(flags) | uint8_t(MergeFlags(rest...))); } static constexpr CTypeInfo::Flags MergeFlags() { return CTypeInfo::Flags(0); } }; namespace internal { template <typename RetBuilder, typename... ArgBuilders> class CFunctionBuilderWithFunction { public: explicit constexpr CFunctionBuilderWithFunction(const void* fn) : fn_(fn) {} template <CTypeInfo::Flags... Flags> constexpr auto Ret() { return CFunctionBuilderWithFunction< CTypeInfoBuilder<typename RetBuilder::BaseType, Flags...>, ArgBuilders...>(fn_); } template <unsigned int N, CTypeInfo::Flags... Flags> constexpr auto Arg() { // Return a copy of the builder with the Nth arg builder merged with // template parameter pack Flags. return ArgImpl<N, Flags...>( std::make_index_sequence<sizeof...(ArgBuilders)>()); } // Provided for testing purposes. template <typename Ret, typename... Args> auto Patch(Ret (*patching_func)(Args...)) { static_assert( sizeof...(Args) == sizeof...(ArgBuilders), "The patching function must have the same number of arguments."); fn_ = reinterpret_cast<void*>(patching_func); return *this; } template <CFunctionInfo::Int64Representation Representation = CFunctionInfo::Int64Representation::kNumber> auto Build() { static CFunctionInfoImpl<Representation, RetBuilder, ArgBuilders...> instance; return CFunction(fn_, &instance); } private: template <bool Merge, unsigned int N, CTypeInfo::Flags... Flags> struct GetArgBuilder; // Returns the same ArgBuilder as the one at index N, including its flags. // Flags in the template parameter pack are ignored. template <unsigned int N, CTypeInfo::Flags... Flags> struct GetArgBuilder<false, N, Flags...> { using type = std::tuple_element_t<N, std::tuple<ArgBuilders...>>; }; // Returns an ArgBuilder with the same base type as the one at index N, // but merges the flags with the flags in the template parameter pack. template <unsigned int N, CTypeInfo::Flags... Flags> struct GetArgBuilder<true, N, Flags...> { using type = CTypeInfoBuilder< typename std::tuple_element_t<N, std::tuple<ArgBuilders...>>::BaseType, std::tuple_element_t<N, std::tuple<ArgBuilders...>>::Build().GetFlags(), Flags...>; }; // Return a copy of the CFunctionBuilder, but merges the Flags on // ArgBuilder index N with the new Flags passed in the template parameter // pack. template <unsigned int N, CTypeInfo::Flags... Flags, size_t... I> constexpr auto ArgImpl(std::index_sequence<I...>) { return CFunctionBuilderWithFunction< RetBuilder, typename GetArgBuilder<N == I, I, Flags...>::type...>(fn_); } const void* fn_; }; class CFunctionBuilder { public: constexpr CFunctionBuilder() {} template <typename R, typename... Args> constexpr auto Fn(R (*fn)(Args...)) { return CFunctionBuilderWithFunction<CTypeInfoBuilder<R>, CTypeInfoBuilder<Args>...>( reinterpret_cast<const void*>(fn)); } }; } // namespace internal // static template <typename R, typename... Args> CFunction CFunction::ArgUnwrap<R (*)(Args...)>::Make( R (*func)(Args...), CFunctionInfo::Int64Representation int64_rep) { if (int64_rep == CFunctionInfo::Int64Representation::kNumber) { return internal::CFunctionBuilder().Fn(func).Build(); } return internal::CFunctionBuilder() .Fn(func) .template Build<CFunctionInfo::Int64Representation::kBigInt>(); } using CFunctionBuilder = internal::CFunctionBuilder; static constexpr CTypeInfo kTypeInfoInt32 = CTypeInfo(CTypeInfo::Type::kInt32); static constexpr CTypeInfo kTypeInfoFloat64 = CTypeInfo(CTypeInfo::Type::kFloat64); /** * Copies the contents of this JavaScript array to a C++ buffer with * a given max_length. A CTypeInfo is passed as an argument, * instructing different rules for conversion (e.g. restricted float/double). * The element type T of the destination array must match the C type * corresponding to the CTypeInfo (specified by CTypeInfoTraits). * If the array length is larger than max_length or the array is of * unsupported type, the operation will fail, returning false. Generally, an * array which contains objects, undefined, null or anything not convertible * to the requested destination type, is considered unsupported. The operation * returns true on success. `type_info` will be used for conversions. */ template <CTypeInfo::Identifier type_info_id, typename T> bool V8_EXPORT V8_WARN_UNUSED_RESULT TryToCopyAndConvertArrayToCppBuffer( Local<Array> src, T* dst, uint32_t max_length); template <> bool V8_EXPORT V8_WARN_UNUSED_RESULT TryToCopyAndConvertArrayToCppBuffer<CTypeInfoBuilder<int32_t>::Build().GetId(), int32_t>(Local<Array> src, int32_t* dst, uint32_t max_length); template <> bool V8_EXPORT V8_WARN_UNUSED_RESULT TryToCopyAndConvertArrayToCppBuffer<CTypeInfoBuilder<uint32_t>::Build().GetId(), uint32_t>(Local<Array> src, uint32_t* dst, uint32_t max_length); template <> bool V8_EXPORT V8_WARN_UNUSED_RESULT TryToCopyAndConvertArrayToCppBuffer<CTypeInfoBuilder<float>::Build().GetId(), float>(Local<Array> src, float* dst, uint32_t max_length); template <> bool V8_EXPORT V8_WARN_UNUSED_RESULT TryToCopyAndConvertArrayToCppBuffer<CTypeInfoBuilder<double>::Build().GetId(), double>(Local<Array> src, double* dst, uint32_t max_length); constexpr v8::ExternalPointerTypeTag kFastAPIPointerTag = V8_EXTERNAL_POINTER_TAG_COUNT - 1; } // namespace v8 #endif // INCLUDE_V8_FAST_API_CALLS_H_