11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci/** 61cb0ef41Sopenharmony_ci * This file provides additional API on top of the default one for making 71cb0ef41Sopenharmony_ci * API calls, which come from embedder C++ functions. The functions are being 81cb0ef41Sopenharmony_ci * called directly from optimized code, doing all the necessary typechecks 91cb0ef41Sopenharmony_ci * in the compiler itself, instead of on the embedder side. Hence the "fast" 101cb0ef41Sopenharmony_ci * in the name. Example usage might look like: 111cb0ef41Sopenharmony_ci * 121cb0ef41Sopenharmony_ci * \code 131cb0ef41Sopenharmony_ci * void FastMethod(int param, bool another_param); 141cb0ef41Sopenharmony_ci * 151cb0ef41Sopenharmony_ci * v8::FunctionTemplate::New(isolate, SlowCallback, data, 161cb0ef41Sopenharmony_ci * signature, length, constructor_behavior 171cb0ef41Sopenharmony_ci * side_effect_type, 181cb0ef41Sopenharmony_ci * &v8::CFunction::Make(FastMethod)); 191cb0ef41Sopenharmony_ci * \endcode 201cb0ef41Sopenharmony_ci * 211cb0ef41Sopenharmony_ci * By design, fast calls are limited by the following requirements, which 221cb0ef41Sopenharmony_ci * the embedder should enforce themselves: 231cb0ef41Sopenharmony_ci * - they should not allocate on the JS heap; 241cb0ef41Sopenharmony_ci * - they should not trigger JS execution. 251cb0ef41Sopenharmony_ci * To enforce them, the embedder could use the existing 261cb0ef41Sopenharmony_ci * v8::Isolate::DisallowJavascriptExecutionScope and a utility similar to 271cb0ef41Sopenharmony_ci * Blink's NoAllocationScope: 281cb0ef41Sopenharmony_ci * https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/platform/heap/thread_state_scopes.h;l=16 291cb0ef41Sopenharmony_ci * 301cb0ef41Sopenharmony_ci * Due to these limitations, it's not directly possible to report errors by 311cb0ef41Sopenharmony_ci * throwing a JS exception or to otherwise do an allocation. There is an 321cb0ef41Sopenharmony_ci * alternative way of creating fast calls that supports falling back to the 331cb0ef41Sopenharmony_ci * slow call and then performing the necessary allocation. When one creates 341cb0ef41Sopenharmony_ci * the fast method by using CFunction::MakeWithFallbackSupport instead of 351cb0ef41Sopenharmony_ci * CFunction::Make, the fast callback gets as last parameter an output variable, 361cb0ef41Sopenharmony_ci * through which it can request falling back to the slow call. So one might 371cb0ef41Sopenharmony_ci * declare their method like: 381cb0ef41Sopenharmony_ci * 391cb0ef41Sopenharmony_ci * \code 401cb0ef41Sopenharmony_ci * void FastMethodWithFallback(int param, FastApiCallbackOptions& options); 411cb0ef41Sopenharmony_ci * \endcode 421cb0ef41Sopenharmony_ci * 431cb0ef41Sopenharmony_ci * If the callback wants to signal an error condition or to perform an 441cb0ef41Sopenharmony_ci * allocation, it must set options.fallback to true and do an early return from 451cb0ef41Sopenharmony_ci * the fast method. Then V8 checks the value of options.fallback and if it's 461cb0ef41Sopenharmony_ci * true, falls back to executing the SlowCallback, which is capable of reporting 471cb0ef41Sopenharmony_ci * the error (either by throwing a JS exception or logging to the console) or 481cb0ef41Sopenharmony_ci * doing the allocation. It's the embedder's responsibility to ensure that the 491cb0ef41Sopenharmony_ci * fast callback is idempotent up to the point where error and fallback 501cb0ef41Sopenharmony_ci * conditions are checked, because otherwise executing the slow callback might 511cb0ef41Sopenharmony_ci * produce visible side-effects twice. 521cb0ef41Sopenharmony_ci * 531cb0ef41Sopenharmony_ci * An example for custom embedder type support might employ a way to wrap/ 541cb0ef41Sopenharmony_ci * unwrap various C++ types in JSObject instances, e.g: 551cb0ef41Sopenharmony_ci * 561cb0ef41Sopenharmony_ci * \code 571cb0ef41Sopenharmony_ci * 581cb0ef41Sopenharmony_ci * // Helper method with a check for field count. 591cb0ef41Sopenharmony_ci * template <typename T, int offset> 601cb0ef41Sopenharmony_ci * inline T* GetInternalField(v8::Local<v8::Object> wrapper) { 611cb0ef41Sopenharmony_ci * assert(offset < wrapper->InternalFieldCount()); 621cb0ef41Sopenharmony_ci * return reinterpret_cast<T*>( 631cb0ef41Sopenharmony_ci * wrapper->GetAlignedPointerFromInternalField(offset)); 641cb0ef41Sopenharmony_ci * } 651cb0ef41Sopenharmony_ci * 661cb0ef41Sopenharmony_ci * class CustomEmbedderType { 671cb0ef41Sopenharmony_ci * public: 681cb0ef41Sopenharmony_ci * // Returns the raw C object from a wrapper JS object. 691cb0ef41Sopenharmony_ci * static CustomEmbedderType* Unwrap(v8::Local<v8::Object> wrapper) { 701cb0ef41Sopenharmony_ci * return GetInternalField<CustomEmbedderType, 711cb0ef41Sopenharmony_ci * kV8EmbedderWrapperObjectIndex>(wrapper); 721cb0ef41Sopenharmony_ci * } 731cb0ef41Sopenharmony_ci * static void FastMethod(v8::Local<v8::Object> receiver_obj, int param) { 741cb0ef41Sopenharmony_ci * CustomEmbedderType* receiver = static_cast<CustomEmbedderType*>( 751cb0ef41Sopenharmony_ci * receiver_obj->GetAlignedPointerFromInternalField( 761cb0ef41Sopenharmony_ci * kV8EmbedderWrapperObjectIndex)); 771cb0ef41Sopenharmony_ci * 781cb0ef41Sopenharmony_ci * // Type checks are already done by the optimized code. 791cb0ef41Sopenharmony_ci * // Then call some performance-critical method like: 801cb0ef41Sopenharmony_ci * // receiver->Method(param); 811cb0ef41Sopenharmony_ci * } 821cb0ef41Sopenharmony_ci * 831cb0ef41Sopenharmony_ci * static void SlowMethod( 841cb0ef41Sopenharmony_ci * const v8::FunctionCallbackInfo<v8::Value>& info) { 851cb0ef41Sopenharmony_ci * v8::Local<v8::Object> instance = 861cb0ef41Sopenharmony_ci * v8::Local<v8::Object>::Cast(info.Holder()); 871cb0ef41Sopenharmony_ci * CustomEmbedderType* receiver = Unwrap(instance); 881cb0ef41Sopenharmony_ci * // TODO: Do type checks and extract {param}. 891cb0ef41Sopenharmony_ci * receiver->Method(param); 901cb0ef41Sopenharmony_ci * } 911cb0ef41Sopenharmony_ci * }; 921cb0ef41Sopenharmony_ci * 931cb0ef41Sopenharmony_ci * // TODO(mslekova): Clean-up these constants 941cb0ef41Sopenharmony_ci * // The constants kV8EmbedderWrapperTypeIndex and 951cb0ef41Sopenharmony_ci * // kV8EmbedderWrapperObjectIndex describe the offsets for the type info 961cb0ef41Sopenharmony_ci * // struct and the native object, when expressed as internal field indices 971cb0ef41Sopenharmony_ci * // within a JSObject. The existance of this helper function assumes that 981cb0ef41Sopenharmony_ci * // all embedder objects have their JSObject-side type info at the same 991cb0ef41Sopenharmony_ci * // offset, but this is not a limitation of the API itself. For a detailed 1001cb0ef41Sopenharmony_ci * // use case, see the third example. 1011cb0ef41Sopenharmony_ci * static constexpr int kV8EmbedderWrapperTypeIndex = 0; 1021cb0ef41Sopenharmony_ci * static constexpr int kV8EmbedderWrapperObjectIndex = 1; 1031cb0ef41Sopenharmony_ci * 1041cb0ef41Sopenharmony_ci * // The following setup function can be templatized based on 1051cb0ef41Sopenharmony_ci * // the {embedder_object} argument. 1061cb0ef41Sopenharmony_ci * void SetupCustomEmbedderObject(v8::Isolate* isolate, 1071cb0ef41Sopenharmony_ci * v8::Local<v8::Context> context, 1081cb0ef41Sopenharmony_ci * CustomEmbedderType* embedder_object) { 1091cb0ef41Sopenharmony_ci * isolate->set_embedder_wrapper_type_index( 1101cb0ef41Sopenharmony_ci * kV8EmbedderWrapperTypeIndex); 1111cb0ef41Sopenharmony_ci * isolate->set_embedder_wrapper_object_index( 1121cb0ef41Sopenharmony_ci * kV8EmbedderWrapperObjectIndex); 1131cb0ef41Sopenharmony_ci * 1141cb0ef41Sopenharmony_ci * v8::CFunction c_func = 1151cb0ef41Sopenharmony_ci * MakeV8CFunction(CustomEmbedderType::FastMethod); 1161cb0ef41Sopenharmony_ci * 1171cb0ef41Sopenharmony_ci * Local<v8::FunctionTemplate> method_template = 1181cb0ef41Sopenharmony_ci * v8::FunctionTemplate::New( 1191cb0ef41Sopenharmony_ci * isolate, CustomEmbedderType::SlowMethod, v8::Local<v8::Value>(), 1201cb0ef41Sopenharmony_ci * v8::Local<v8::Signature>(), 1, v8::ConstructorBehavior::kAllow, 1211cb0ef41Sopenharmony_ci * v8::SideEffectType::kHasSideEffect, &c_func); 1221cb0ef41Sopenharmony_ci * 1231cb0ef41Sopenharmony_ci * v8::Local<v8::ObjectTemplate> object_template = 1241cb0ef41Sopenharmony_ci * v8::ObjectTemplate::New(isolate); 1251cb0ef41Sopenharmony_ci * object_template->SetInternalFieldCount( 1261cb0ef41Sopenharmony_ci * kV8EmbedderWrapperObjectIndex + 1); 1271cb0ef41Sopenharmony_ci * object_template->Set(isolate, "method", method_template); 1281cb0ef41Sopenharmony_ci * 1291cb0ef41Sopenharmony_ci * // Instantiate the wrapper JS object. 1301cb0ef41Sopenharmony_ci * v8::Local<v8::Object> object = 1311cb0ef41Sopenharmony_ci * object_template->NewInstance(context).ToLocalChecked(); 1321cb0ef41Sopenharmony_ci * object->SetAlignedPointerInInternalField( 1331cb0ef41Sopenharmony_ci * kV8EmbedderWrapperObjectIndex, 1341cb0ef41Sopenharmony_ci * reinterpret_cast<void*>(embedder_object)); 1351cb0ef41Sopenharmony_ci * 1361cb0ef41Sopenharmony_ci * // TODO: Expose {object} where it's necessary. 1371cb0ef41Sopenharmony_ci * } 1381cb0ef41Sopenharmony_ci * \endcode 1391cb0ef41Sopenharmony_ci * 1401cb0ef41Sopenharmony_ci * For instance if {object} is exposed via a global "obj" variable, 1411cb0ef41Sopenharmony_ci * one could write in JS: 1421cb0ef41Sopenharmony_ci * function hot_func() { 1431cb0ef41Sopenharmony_ci * obj.method(42); 1441cb0ef41Sopenharmony_ci * } 1451cb0ef41Sopenharmony_ci * and once {hot_func} gets optimized, CustomEmbedderType::FastMethod 1461cb0ef41Sopenharmony_ci * will be called instead of the slow version, with the following arguments: 1471cb0ef41Sopenharmony_ci * receiver := the {embedder_object} from above 1481cb0ef41Sopenharmony_ci * param := 42 1491cb0ef41Sopenharmony_ci * 1501cb0ef41Sopenharmony_ci * Currently supported return types: 1511cb0ef41Sopenharmony_ci * - void 1521cb0ef41Sopenharmony_ci * - bool 1531cb0ef41Sopenharmony_ci * - int32_t 1541cb0ef41Sopenharmony_ci * - uint32_t 1551cb0ef41Sopenharmony_ci * - float32_t 1561cb0ef41Sopenharmony_ci * - float64_t 1571cb0ef41Sopenharmony_ci * Currently supported argument types: 1581cb0ef41Sopenharmony_ci * - pointer to an embedder type 1591cb0ef41Sopenharmony_ci * - JavaScript array of primitive types 1601cb0ef41Sopenharmony_ci * - bool 1611cb0ef41Sopenharmony_ci * - int32_t 1621cb0ef41Sopenharmony_ci * - uint32_t 1631cb0ef41Sopenharmony_ci * - int64_t 1641cb0ef41Sopenharmony_ci * - uint64_t 1651cb0ef41Sopenharmony_ci * - float32_t 1661cb0ef41Sopenharmony_ci * - float64_t 1671cb0ef41Sopenharmony_ci * 1681cb0ef41Sopenharmony_ci * The 64-bit integer types currently have the IDL (unsigned) long long 1691cb0ef41Sopenharmony_ci * semantics: https://heycam.github.io/webidl/#abstract-opdef-converttoint 1701cb0ef41Sopenharmony_ci * In the future we'll extend the API to also provide conversions from/to 1711cb0ef41Sopenharmony_ci * BigInt to preserve full precision. 1721cb0ef41Sopenharmony_ci * The floating point types currently have the IDL (unrestricted) semantics, 1731cb0ef41Sopenharmony_ci * which is the only one used by WebGL. We plan to add support also for 1741cb0ef41Sopenharmony_ci * restricted floats/doubles, similarly to the BigInt conversion policies. 1751cb0ef41Sopenharmony_ci * We also differ from the specific NaN bit pattern that WebIDL prescribes 1761cb0ef41Sopenharmony_ci * (https://heycam.github.io/webidl/#es-unrestricted-float) in that Blink 1771cb0ef41Sopenharmony_ci * passes NaN values as-is, i.e. doesn't normalize them. 1781cb0ef41Sopenharmony_ci * 1791cb0ef41Sopenharmony_ci * To be supported types: 1801cb0ef41Sopenharmony_ci * - TypedArrays and ArrayBuffers 1811cb0ef41Sopenharmony_ci * - arrays of embedder types 1821cb0ef41Sopenharmony_ci * 1831cb0ef41Sopenharmony_ci * 1841cb0ef41Sopenharmony_ci * The API offers a limited support for function overloads: 1851cb0ef41Sopenharmony_ci * 1861cb0ef41Sopenharmony_ci * \code 1871cb0ef41Sopenharmony_ci * void FastMethod_2Args(int param, bool another_param); 1881cb0ef41Sopenharmony_ci * void FastMethod_3Args(int param, bool another_param, int third_param); 1891cb0ef41Sopenharmony_ci * 1901cb0ef41Sopenharmony_ci * v8::CFunction fast_method_2args_c_func = 1911cb0ef41Sopenharmony_ci * MakeV8CFunction(FastMethod_2Args); 1921cb0ef41Sopenharmony_ci * v8::CFunction fast_method_3args_c_func = 1931cb0ef41Sopenharmony_ci * MakeV8CFunction(FastMethod_3Args); 1941cb0ef41Sopenharmony_ci * const v8::CFunction fast_method_overloads[] = {fast_method_2args_c_func, 1951cb0ef41Sopenharmony_ci * fast_method_3args_c_func}; 1961cb0ef41Sopenharmony_ci * Local<v8::FunctionTemplate> method_template = 1971cb0ef41Sopenharmony_ci * v8::FunctionTemplate::NewWithCFunctionOverloads( 1981cb0ef41Sopenharmony_ci * isolate, SlowCallback, data, signature, length, 1991cb0ef41Sopenharmony_ci * constructor_behavior, side_effect_type, 2001cb0ef41Sopenharmony_ci * {fast_method_overloads, 2}); 2011cb0ef41Sopenharmony_ci * \endcode 2021cb0ef41Sopenharmony_ci * 2031cb0ef41Sopenharmony_ci * In this example a single FunctionTemplate is associated to multiple C++ 2041cb0ef41Sopenharmony_ci * functions. The overload resolution is currently only based on the number of 2051cb0ef41Sopenharmony_ci * arguments passed in a call. For example, if this method_template is 2061cb0ef41Sopenharmony_ci * registered with a wrapper JS object as described above, a call with two 2071cb0ef41Sopenharmony_ci * arguments: 2081cb0ef41Sopenharmony_ci * obj.method(42, true); 2091cb0ef41Sopenharmony_ci * will result in a fast call to FastMethod_2Args, while a call with three or 2101cb0ef41Sopenharmony_ci * more arguments: 2111cb0ef41Sopenharmony_ci * obj.method(42, true, 11); 2121cb0ef41Sopenharmony_ci * will result in a fast call to FastMethod_3Args. Instead a call with less than 2131cb0ef41Sopenharmony_ci * two arguments, like: 2141cb0ef41Sopenharmony_ci * obj.method(42); 2151cb0ef41Sopenharmony_ci * would not result in a fast call but would fall back to executing the 2161cb0ef41Sopenharmony_ci * associated SlowCallback. 2171cb0ef41Sopenharmony_ci */ 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci#ifndef INCLUDE_V8_FAST_API_CALLS_H_ 2201cb0ef41Sopenharmony_ci#define INCLUDE_V8_FAST_API_CALLS_H_ 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci#include <stddef.h> 2231cb0ef41Sopenharmony_ci#include <stdint.h> 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_ci#include <tuple> 2261cb0ef41Sopenharmony_ci#include <type_traits> 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ci#include "v8-internal.h" // NOLINT(build/include_directory) 2291cb0ef41Sopenharmony_ci#include "v8-local-handle.h" // NOLINT(build/include_directory) 2301cb0ef41Sopenharmony_ci#include "v8-typed-array.h" // NOLINT(build/include_directory) 2311cb0ef41Sopenharmony_ci#include "v8-value.h" // NOLINT(build/include_directory) 2321cb0ef41Sopenharmony_ci#include "v8config.h" // NOLINT(build/include_directory) 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_cinamespace v8 { 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ciclass Isolate; 2371cb0ef41Sopenharmony_ci 2381cb0ef41Sopenharmony_ciclass CTypeInfo { 2391cb0ef41Sopenharmony_ci public: 2401cb0ef41Sopenharmony_ci enum class Type : uint8_t { 2411cb0ef41Sopenharmony_ci kVoid, 2421cb0ef41Sopenharmony_ci kBool, 2431cb0ef41Sopenharmony_ci kInt32, 2441cb0ef41Sopenharmony_ci kUint32, 2451cb0ef41Sopenharmony_ci kInt64, 2461cb0ef41Sopenharmony_ci kUint64, 2471cb0ef41Sopenharmony_ci kFloat32, 2481cb0ef41Sopenharmony_ci kFloat64, 2491cb0ef41Sopenharmony_ci kV8Value, 2501cb0ef41Sopenharmony_ci kApiObject, // This will be deprecated once all users have 2511cb0ef41Sopenharmony_ci // migrated from v8::ApiObject to v8::Local<v8::Value>. 2521cb0ef41Sopenharmony_ci kAny, // This is added to enable untyped representation of fast 2531cb0ef41Sopenharmony_ci // call arguments for test purposes. It can represent any of 2541cb0ef41Sopenharmony_ci // the other types stored in the same memory as a union (see 2551cb0ef41Sopenharmony_ci // the AnyCType struct declared below). This allows for 2561cb0ef41Sopenharmony_ci // uniform passing of arguments w.r.t. their location 2571cb0ef41Sopenharmony_ci // (in a register or on the stack), independent of their 2581cb0ef41Sopenharmony_ci // actual type. It's currently used by the arm64 simulator 2591cb0ef41Sopenharmony_ci // and can be added to the other simulators as well when fast 2601cb0ef41Sopenharmony_ci // calls having both GP and FP params need to be supported. 2611cb0ef41Sopenharmony_ci }; 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci // kCallbackOptionsType is not part of the Type enum 2641cb0ef41Sopenharmony_ci // because it is only used internally. Use value 255 that is larger 2651cb0ef41Sopenharmony_ci // than any valid Type enum. 2661cb0ef41Sopenharmony_ci static constexpr Type kCallbackOptionsType = Type(255); 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci enum class SequenceType : uint8_t { 2691cb0ef41Sopenharmony_ci kScalar, 2701cb0ef41Sopenharmony_ci kIsSequence, // sequence<T> 2711cb0ef41Sopenharmony_ci kIsTypedArray, // TypedArray of T or any ArrayBufferView if T 2721cb0ef41Sopenharmony_ci // is void 2731cb0ef41Sopenharmony_ci kIsArrayBuffer // ArrayBuffer 2741cb0ef41Sopenharmony_ci }; 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci enum class Flags : uint8_t { 2771cb0ef41Sopenharmony_ci kNone = 0, 2781cb0ef41Sopenharmony_ci kAllowSharedBit = 1 << 0, // Must be an ArrayBuffer or TypedArray 2791cb0ef41Sopenharmony_ci kEnforceRangeBit = 1 << 1, // T must be integral 2801cb0ef41Sopenharmony_ci kClampBit = 1 << 2, // T must be integral 2811cb0ef41Sopenharmony_ci kIsRestrictedBit = 1 << 3, // T must be float or double 2821cb0ef41Sopenharmony_ci }; 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ci explicit constexpr CTypeInfo( 2851cb0ef41Sopenharmony_ci Type type, SequenceType sequence_type = SequenceType::kScalar, 2861cb0ef41Sopenharmony_ci Flags flags = Flags::kNone) 2871cb0ef41Sopenharmony_ci : type_(type), sequence_type_(sequence_type), flags_(flags) {} 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci typedef uint32_t Identifier; 2901cb0ef41Sopenharmony_ci explicit constexpr CTypeInfo(Identifier identifier) 2911cb0ef41Sopenharmony_ci : CTypeInfo(static_cast<Type>(identifier >> 16), 2921cb0ef41Sopenharmony_ci static_cast<SequenceType>((identifier >> 8) & 255), 2931cb0ef41Sopenharmony_ci static_cast<Flags>(identifier & 255)) {} 2941cb0ef41Sopenharmony_ci constexpr Identifier GetId() const { 2951cb0ef41Sopenharmony_ci return static_cast<uint8_t>(type_) << 16 | 2961cb0ef41Sopenharmony_ci static_cast<uint8_t>(sequence_type_) << 8 | 2971cb0ef41Sopenharmony_ci static_cast<uint8_t>(flags_); 2981cb0ef41Sopenharmony_ci } 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci constexpr Type GetType() const { return type_; } 3011cb0ef41Sopenharmony_ci constexpr SequenceType GetSequenceType() const { return sequence_type_; } 3021cb0ef41Sopenharmony_ci constexpr Flags GetFlags() const { return flags_; } 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci static constexpr bool IsIntegralType(Type type) { 3051cb0ef41Sopenharmony_ci return type == Type::kInt32 || type == Type::kUint32 || 3061cb0ef41Sopenharmony_ci type == Type::kInt64 || type == Type::kUint64; 3071cb0ef41Sopenharmony_ci } 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci static constexpr bool IsFloatingPointType(Type type) { 3101cb0ef41Sopenharmony_ci return type == Type::kFloat32 || type == Type::kFloat64; 3111cb0ef41Sopenharmony_ci } 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci static constexpr bool IsPrimitive(Type type) { 3141cb0ef41Sopenharmony_ci return IsIntegralType(type) || IsFloatingPointType(type) || 3151cb0ef41Sopenharmony_ci type == Type::kBool; 3161cb0ef41Sopenharmony_ci } 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci private: 3191cb0ef41Sopenharmony_ci Type type_; 3201cb0ef41Sopenharmony_ci SequenceType sequence_type_; 3211cb0ef41Sopenharmony_ci Flags flags_; 3221cb0ef41Sopenharmony_ci}; 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_cistruct FastApiTypedArrayBase { 3251cb0ef41Sopenharmony_ci public: 3261cb0ef41Sopenharmony_ci // Returns the length in number of elements. 3271cb0ef41Sopenharmony_ci size_t V8_EXPORT length() const { return length_; } 3281cb0ef41Sopenharmony_ci // Checks whether the given index is within the bounds of the collection. 3291cb0ef41Sopenharmony_ci void V8_EXPORT ValidateIndex(size_t index) const; 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_ci protected: 3321cb0ef41Sopenharmony_ci size_t length_ = 0; 3331cb0ef41Sopenharmony_ci}; 3341cb0ef41Sopenharmony_ci 3351cb0ef41Sopenharmony_citemplate <typename T> 3361cb0ef41Sopenharmony_cistruct FastApiTypedArray : public FastApiTypedArrayBase { 3371cb0ef41Sopenharmony_ci public: 3381cb0ef41Sopenharmony_ci V8_INLINE T get(size_t index) const { 3391cb0ef41Sopenharmony_ci#ifdef DEBUG 3401cb0ef41Sopenharmony_ci ValidateIndex(index); 3411cb0ef41Sopenharmony_ci#endif // DEBUG 3421cb0ef41Sopenharmony_ci T tmp; 3431cb0ef41Sopenharmony_ci memcpy(&tmp, reinterpret_cast<T*>(data_) + index, sizeof(T)); 3441cb0ef41Sopenharmony_ci return tmp; 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci 3471cb0ef41Sopenharmony_ci bool getStorageIfAligned(T** elements) const { 3481cb0ef41Sopenharmony_ci if (reinterpret_cast<uintptr_t>(data_) % alignof(T) != 0) { 3491cb0ef41Sopenharmony_ci return false; 3501cb0ef41Sopenharmony_ci } 3511cb0ef41Sopenharmony_ci *elements = reinterpret_cast<T*>(data_); 3521cb0ef41Sopenharmony_ci return true; 3531cb0ef41Sopenharmony_ci } 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_ci private: 3561cb0ef41Sopenharmony_ci // This pointer should include the typed array offset applied. 3571cb0ef41Sopenharmony_ci // It's not guaranteed that it's aligned to sizeof(T), it's only 3581cb0ef41Sopenharmony_ci // guaranteed that it's 4-byte aligned, so for 8-byte types we need to 3591cb0ef41Sopenharmony_ci // provide a special implementation for reading from it, which hides 3601cb0ef41Sopenharmony_ci // the possibly unaligned read in the `get` method. 3611cb0ef41Sopenharmony_ci void* data_; 3621cb0ef41Sopenharmony_ci}; 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_ci// Any TypedArray. It uses kTypedArrayBit with base type void 3651cb0ef41Sopenharmony_ci// Overloaded args of ArrayBufferView and TypedArray are not supported 3661cb0ef41Sopenharmony_ci// (for now) because the generic “any” ArrayBufferView doesn’t have its 3671cb0ef41Sopenharmony_ci// own instance type. It could be supported if we specify that 3681cb0ef41Sopenharmony_ci// TypedArray<T> always has precedence over the generic ArrayBufferView, 3691cb0ef41Sopenharmony_ci// but this complicates overload resolution. 3701cb0ef41Sopenharmony_cistruct FastApiArrayBufferView { 3711cb0ef41Sopenharmony_ci void* data; 3721cb0ef41Sopenharmony_ci size_t byte_length; 3731cb0ef41Sopenharmony_ci}; 3741cb0ef41Sopenharmony_ci 3751cb0ef41Sopenharmony_cistruct FastApiArrayBuffer { 3761cb0ef41Sopenharmony_ci void* data; 3771cb0ef41Sopenharmony_ci size_t byte_length; 3781cb0ef41Sopenharmony_ci}; 3791cb0ef41Sopenharmony_ci 3801cb0ef41Sopenharmony_ciclass V8_EXPORT CFunctionInfo { 3811cb0ef41Sopenharmony_ci public: 3821cb0ef41Sopenharmony_ci // Construct a struct to hold a CFunction's type information. 3831cb0ef41Sopenharmony_ci // |return_info| describes the function's return type. 3841cb0ef41Sopenharmony_ci // |arg_info| is an array of |arg_count| CTypeInfos describing the 3851cb0ef41Sopenharmony_ci // arguments. Only the last argument may be of the special type 3861cb0ef41Sopenharmony_ci // CTypeInfo::kCallbackOptionsType. 3871cb0ef41Sopenharmony_ci CFunctionInfo(const CTypeInfo& return_info, unsigned int arg_count, 3881cb0ef41Sopenharmony_ci const CTypeInfo* arg_info); 3891cb0ef41Sopenharmony_ci 3901cb0ef41Sopenharmony_ci const CTypeInfo& ReturnInfo() const { return return_info_; } 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_ci // The argument count, not including the v8::FastApiCallbackOptions 3931cb0ef41Sopenharmony_ci // if present. 3941cb0ef41Sopenharmony_ci unsigned int ArgumentCount() const { 3951cb0ef41Sopenharmony_ci return HasOptions() ? arg_count_ - 1 : arg_count_; 3961cb0ef41Sopenharmony_ci } 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci // |index| must be less than ArgumentCount(). 3991cb0ef41Sopenharmony_ci // Note: if the last argument passed on construction of CFunctionInfo 4001cb0ef41Sopenharmony_ci // has type CTypeInfo::kCallbackOptionsType, it is not included in 4011cb0ef41Sopenharmony_ci // ArgumentCount(). 4021cb0ef41Sopenharmony_ci const CTypeInfo& ArgumentInfo(unsigned int index) const; 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci bool HasOptions() const { 4051cb0ef41Sopenharmony_ci // The options arg is always the last one. 4061cb0ef41Sopenharmony_ci return arg_count_ > 0 && arg_info_[arg_count_ - 1].GetType() == 4071cb0ef41Sopenharmony_ci CTypeInfo::kCallbackOptionsType; 4081cb0ef41Sopenharmony_ci } 4091cb0ef41Sopenharmony_ci 4101cb0ef41Sopenharmony_ci private: 4111cb0ef41Sopenharmony_ci const CTypeInfo return_info_; 4121cb0ef41Sopenharmony_ci const unsigned int arg_count_; 4131cb0ef41Sopenharmony_ci const CTypeInfo* arg_info_; 4141cb0ef41Sopenharmony_ci}; 4151cb0ef41Sopenharmony_ci 4161cb0ef41Sopenharmony_cistruct FastApiCallbackOptions; 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci// Provided for testing. 4191cb0ef41Sopenharmony_cistruct AnyCType { 4201cb0ef41Sopenharmony_ci AnyCType() : int64_value(0) {} 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci union { 4231cb0ef41Sopenharmony_ci bool bool_value; 4241cb0ef41Sopenharmony_ci int32_t int32_value; 4251cb0ef41Sopenharmony_ci uint32_t uint32_value; 4261cb0ef41Sopenharmony_ci int64_t int64_value; 4271cb0ef41Sopenharmony_ci uint64_t uint64_value; 4281cb0ef41Sopenharmony_ci float float_value; 4291cb0ef41Sopenharmony_ci double double_value; 4301cb0ef41Sopenharmony_ci Local<Object> object_value; 4311cb0ef41Sopenharmony_ci Local<Array> sequence_value; 4321cb0ef41Sopenharmony_ci const FastApiTypedArray<int32_t>* int32_ta_value; 4331cb0ef41Sopenharmony_ci const FastApiTypedArray<uint32_t>* uint32_ta_value; 4341cb0ef41Sopenharmony_ci const FastApiTypedArray<int64_t>* int64_ta_value; 4351cb0ef41Sopenharmony_ci const FastApiTypedArray<uint64_t>* uint64_ta_value; 4361cb0ef41Sopenharmony_ci const FastApiTypedArray<float>* float_ta_value; 4371cb0ef41Sopenharmony_ci const FastApiTypedArray<double>* double_ta_value; 4381cb0ef41Sopenharmony_ci FastApiCallbackOptions* options_value; 4391cb0ef41Sopenharmony_ci }; 4401cb0ef41Sopenharmony_ci}; 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_cistatic_assert( 4431cb0ef41Sopenharmony_ci sizeof(AnyCType) == 8, 4441cb0ef41Sopenharmony_ci "The AnyCType struct should have size == 64 bits, as this is assumed " 4451cb0ef41Sopenharmony_ci "by EffectControlLinearizer."); 4461cb0ef41Sopenharmony_ci 4471cb0ef41Sopenharmony_ciclass V8_EXPORT CFunction { 4481cb0ef41Sopenharmony_ci public: 4491cb0ef41Sopenharmony_ci constexpr CFunction() : address_(nullptr), type_info_(nullptr) {} 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_ci const CTypeInfo& ReturnInfo() const { return type_info_->ReturnInfo(); } 4521cb0ef41Sopenharmony_ci 4531cb0ef41Sopenharmony_ci const CTypeInfo& ArgumentInfo(unsigned int index) const { 4541cb0ef41Sopenharmony_ci return type_info_->ArgumentInfo(index); 4551cb0ef41Sopenharmony_ci } 4561cb0ef41Sopenharmony_ci 4571cb0ef41Sopenharmony_ci unsigned int ArgumentCount() const { return type_info_->ArgumentCount(); } 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_ci const void* GetAddress() const { return address_; } 4601cb0ef41Sopenharmony_ci const CFunctionInfo* GetTypeInfo() const { return type_info_; } 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ci enum class OverloadResolution { kImpossible, kAtRuntime, kAtCompileTime }; 4631cb0ef41Sopenharmony_ci 4641cb0ef41Sopenharmony_ci // Returns whether an overload between this and the given CFunction can 4651cb0ef41Sopenharmony_ci // be resolved at runtime by the RTTI available for the arguments or at 4661cb0ef41Sopenharmony_ci // compile time for functions with different number of arguments. 4671cb0ef41Sopenharmony_ci OverloadResolution GetOverloadResolution(const CFunction* other) { 4681cb0ef41Sopenharmony_ci // Runtime overload resolution can only deal with functions with the 4691cb0ef41Sopenharmony_ci // same number of arguments. Functions with different arity are handled 4701cb0ef41Sopenharmony_ci // by compile time overload resolution though. 4711cb0ef41Sopenharmony_ci if (ArgumentCount() != other->ArgumentCount()) { 4721cb0ef41Sopenharmony_ci return OverloadResolution::kAtCompileTime; 4731cb0ef41Sopenharmony_ci } 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci // The functions can only differ by a single argument position. 4761cb0ef41Sopenharmony_ci int diff_index = -1; 4771cb0ef41Sopenharmony_ci for (unsigned int i = 0; i < ArgumentCount(); ++i) { 4781cb0ef41Sopenharmony_ci if (ArgumentInfo(i).GetSequenceType() != 4791cb0ef41Sopenharmony_ci other->ArgumentInfo(i).GetSequenceType()) { 4801cb0ef41Sopenharmony_ci if (diff_index >= 0) { 4811cb0ef41Sopenharmony_ci return OverloadResolution::kImpossible; 4821cb0ef41Sopenharmony_ci } 4831cb0ef41Sopenharmony_ci diff_index = i; 4841cb0ef41Sopenharmony_ci 4851cb0ef41Sopenharmony_ci // We only support overload resolution between sequence types. 4861cb0ef41Sopenharmony_ci if (ArgumentInfo(i).GetSequenceType() == 4871cb0ef41Sopenharmony_ci CTypeInfo::SequenceType::kScalar || 4881cb0ef41Sopenharmony_ci other->ArgumentInfo(i).GetSequenceType() == 4891cb0ef41Sopenharmony_ci CTypeInfo::SequenceType::kScalar) { 4901cb0ef41Sopenharmony_ci return OverloadResolution::kImpossible; 4911cb0ef41Sopenharmony_ci } 4921cb0ef41Sopenharmony_ci } 4931cb0ef41Sopenharmony_ci } 4941cb0ef41Sopenharmony_ci 4951cb0ef41Sopenharmony_ci return OverloadResolution::kAtRuntime; 4961cb0ef41Sopenharmony_ci } 4971cb0ef41Sopenharmony_ci 4981cb0ef41Sopenharmony_ci template <typename F> 4991cb0ef41Sopenharmony_ci static CFunction Make(F* func) { 5001cb0ef41Sopenharmony_ci return ArgUnwrap<F*>::Make(func); 5011cb0ef41Sopenharmony_ci } 5021cb0ef41Sopenharmony_ci 5031cb0ef41Sopenharmony_ci // Provided for testing purposes. 5041cb0ef41Sopenharmony_ci template <typename R, typename... Args, typename R_Patch, 5051cb0ef41Sopenharmony_ci typename... Args_Patch> 5061cb0ef41Sopenharmony_ci static CFunction Make(R (*func)(Args...), 5071cb0ef41Sopenharmony_ci R_Patch (*patching_func)(Args_Patch...)) { 5081cb0ef41Sopenharmony_ci CFunction c_func = ArgUnwrap<R (*)(Args...)>::Make(func); 5091cb0ef41Sopenharmony_ci static_assert( 5101cb0ef41Sopenharmony_ci sizeof...(Args_Patch) == sizeof...(Args), 5111cb0ef41Sopenharmony_ci "The patching function must have the same number of arguments."); 5121cb0ef41Sopenharmony_ci c_func.address_ = reinterpret_cast<void*>(patching_func); 5131cb0ef41Sopenharmony_ci return c_func; 5141cb0ef41Sopenharmony_ci } 5151cb0ef41Sopenharmony_ci 5161cb0ef41Sopenharmony_ci CFunction(const void* address, const CFunctionInfo* type_info); 5171cb0ef41Sopenharmony_ci 5181cb0ef41Sopenharmony_ci private: 5191cb0ef41Sopenharmony_ci const void* address_; 5201cb0ef41Sopenharmony_ci const CFunctionInfo* type_info_; 5211cb0ef41Sopenharmony_ci 5221cb0ef41Sopenharmony_ci template <typename F> 5231cb0ef41Sopenharmony_ci class ArgUnwrap { 5241cb0ef41Sopenharmony_ci static_assert(sizeof(F) != sizeof(F), 5251cb0ef41Sopenharmony_ci "CFunction must be created from a function pointer."); 5261cb0ef41Sopenharmony_ci }; 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_ci template <typename R, typename... Args> 5291cb0ef41Sopenharmony_ci class ArgUnwrap<R (*)(Args...)> { 5301cb0ef41Sopenharmony_ci public: 5311cb0ef41Sopenharmony_ci static CFunction Make(R (*func)(Args...)); 5321cb0ef41Sopenharmony_ci }; 5331cb0ef41Sopenharmony_ci}; 5341cb0ef41Sopenharmony_ci 5351cb0ef41Sopenharmony_ci/** 5361cb0ef41Sopenharmony_ci * A struct which may be passed to a fast call callback, like so: 5371cb0ef41Sopenharmony_ci * \code 5381cb0ef41Sopenharmony_ci * void FastMethodWithOptions(int param, FastApiCallbackOptions& options); 5391cb0ef41Sopenharmony_ci * \endcode 5401cb0ef41Sopenharmony_ci */ 5411cb0ef41Sopenharmony_cistruct FastApiCallbackOptions { 5421cb0ef41Sopenharmony_ci /** 5431cb0ef41Sopenharmony_ci * Creates a new instance of FastApiCallbackOptions for testing purpose. The 5441cb0ef41Sopenharmony_ci * returned instance may be filled with mock data. 5451cb0ef41Sopenharmony_ci */ 5461cb0ef41Sopenharmony_ci static FastApiCallbackOptions CreateForTesting(Isolate* isolate) { 5471cb0ef41Sopenharmony_ci return {false, {0}}; 5481cb0ef41Sopenharmony_ci } 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_ci /** 5511cb0ef41Sopenharmony_ci * If the callback wants to signal an error condition or to perform an 5521cb0ef41Sopenharmony_ci * allocation, it must set options.fallback to true and do an early return 5531cb0ef41Sopenharmony_ci * from the fast method. Then V8 checks the value of options.fallback and if 5541cb0ef41Sopenharmony_ci * it's true, falls back to executing the SlowCallback, which is capable of 5551cb0ef41Sopenharmony_ci * reporting the error (either by throwing a JS exception or logging to the 5561cb0ef41Sopenharmony_ci * console) or doing the allocation. It's the embedder's responsibility to 5571cb0ef41Sopenharmony_ci * ensure that the fast callback is idempotent up to the point where error and 5581cb0ef41Sopenharmony_ci * fallback conditions are checked, because otherwise executing the slow 5591cb0ef41Sopenharmony_ci * callback might produce visible side-effects twice. 5601cb0ef41Sopenharmony_ci */ 5611cb0ef41Sopenharmony_ci bool fallback; 5621cb0ef41Sopenharmony_ci 5631cb0ef41Sopenharmony_ci /** 5641cb0ef41Sopenharmony_ci * The `data` passed to the FunctionTemplate constructor, or `undefined`. 5651cb0ef41Sopenharmony_ci * `data_ptr` allows for default constructing FastApiCallbackOptions. 5661cb0ef41Sopenharmony_ci */ 5671cb0ef41Sopenharmony_ci union { 5681cb0ef41Sopenharmony_ci uintptr_t data_ptr; 5691cb0ef41Sopenharmony_ci v8::Value data; 5701cb0ef41Sopenharmony_ci }; 5711cb0ef41Sopenharmony_ci}; 5721cb0ef41Sopenharmony_ci 5731cb0ef41Sopenharmony_cinamespace internal { 5741cb0ef41Sopenharmony_ci 5751cb0ef41Sopenharmony_ci// Helper to count the number of occurances of `T` in `List` 5761cb0ef41Sopenharmony_citemplate <typename T, typename... List> 5771cb0ef41Sopenharmony_cistruct count : std::integral_constant<int, 0> {}; 5781cb0ef41Sopenharmony_citemplate <typename T, typename... Args> 5791cb0ef41Sopenharmony_cistruct count<T, T, Args...> 5801cb0ef41Sopenharmony_ci : std::integral_constant<std::size_t, 1 + count<T, Args...>::value> {}; 5811cb0ef41Sopenharmony_citemplate <typename T, typename U, typename... Args> 5821cb0ef41Sopenharmony_cistruct count<T, U, Args...> : count<T, Args...> {}; 5831cb0ef41Sopenharmony_ci 5841cb0ef41Sopenharmony_citemplate <typename RetBuilder, typename... ArgBuilders> 5851cb0ef41Sopenharmony_ciclass CFunctionInfoImpl : public CFunctionInfo { 5861cb0ef41Sopenharmony_ci static constexpr int kOptionsArgCount = 5871cb0ef41Sopenharmony_ci count<FastApiCallbackOptions&, ArgBuilders...>(); 5881cb0ef41Sopenharmony_ci static constexpr int kReceiverCount = 1; 5891cb0ef41Sopenharmony_ci 5901cb0ef41Sopenharmony_ci static_assert(kOptionsArgCount == 0 || kOptionsArgCount == 1, 5911cb0ef41Sopenharmony_ci "Only one options parameter is supported."); 5921cb0ef41Sopenharmony_ci 5931cb0ef41Sopenharmony_ci static_assert(sizeof...(ArgBuilders) >= kOptionsArgCount + kReceiverCount, 5941cb0ef41Sopenharmony_ci "The receiver or the options argument is missing."); 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_ci public: 5971cb0ef41Sopenharmony_ci constexpr CFunctionInfoImpl() 5981cb0ef41Sopenharmony_ci : CFunctionInfo(RetBuilder::Build(), sizeof...(ArgBuilders), 5991cb0ef41Sopenharmony_ci arg_info_storage_), 6001cb0ef41Sopenharmony_ci arg_info_storage_{ArgBuilders::Build()...} { 6011cb0ef41Sopenharmony_ci constexpr CTypeInfo::Type kReturnType = RetBuilder::Build().GetType(); 6021cb0ef41Sopenharmony_ci static_assert(kReturnType == CTypeInfo::Type::kVoid || 6031cb0ef41Sopenharmony_ci kReturnType == CTypeInfo::Type::kBool || 6041cb0ef41Sopenharmony_ci kReturnType == CTypeInfo::Type::kInt32 || 6051cb0ef41Sopenharmony_ci kReturnType == CTypeInfo::Type::kUint32 || 6061cb0ef41Sopenharmony_ci kReturnType == CTypeInfo::Type::kFloat32 || 6071cb0ef41Sopenharmony_ci kReturnType == CTypeInfo::Type::kFloat64 || 6081cb0ef41Sopenharmony_ci kReturnType == CTypeInfo::Type::kAny, 6091cb0ef41Sopenharmony_ci "64-bit int and api object values are not currently " 6101cb0ef41Sopenharmony_ci "supported return types."); 6111cb0ef41Sopenharmony_ci } 6121cb0ef41Sopenharmony_ci 6131cb0ef41Sopenharmony_ci private: 6141cb0ef41Sopenharmony_ci const CTypeInfo arg_info_storage_[sizeof...(ArgBuilders)]; 6151cb0ef41Sopenharmony_ci}; 6161cb0ef41Sopenharmony_ci 6171cb0ef41Sopenharmony_citemplate <typename T> 6181cb0ef41Sopenharmony_cistruct TypeInfoHelper { 6191cb0ef41Sopenharmony_ci static_assert(sizeof(T) != sizeof(T), "This type is not supported"); 6201cb0ef41Sopenharmony_ci}; 6211cb0ef41Sopenharmony_ci 6221cb0ef41Sopenharmony_ci#define SPECIALIZE_GET_TYPE_INFO_HELPER_FOR(T, Enum) \ 6231cb0ef41Sopenharmony_ci template <> \ 6241cb0ef41Sopenharmony_ci struct TypeInfoHelper<T> { \ 6251cb0ef41Sopenharmony_ci static constexpr CTypeInfo::Flags Flags() { \ 6261cb0ef41Sopenharmony_ci return CTypeInfo::Flags::kNone; \ 6271cb0ef41Sopenharmony_ci } \ 6281cb0ef41Sopenharmony_ci \ 6291cb0ef41Sopenharmony_ci static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::Enum; } \ 6301cb0ef41Sopenharmony_ci static constexpr CTypeInfo::SequenceType SequenceType() { \ 6311cb0ef41Sopenharmony_ci return CTypeInfo::SequenceType::kScalar; \ 6321cb0ef41Sopenharmony_ci } \ 6331cb0ef41Sopenharmony_ci }; 6341cb0ef41Sopenharmony_ci 6351cb0ef41Sopenharmony_citemplate <CTypeInfo::Type type> 6361cb0ef41Sopenharmony_cistruct CTypeInfoTraits {}; 6371cb0ef41Sopenharmony_ci 6381cb0ef41Sopenharmony_ci#define DEFINE_TYPE_INFO_TRAITS(CType, Enum) \ 6391cb0ef41Sopenharmony_ci template <> \ 6401cb0ef41Sopenharmony_ci struct CTypeInfoTraits<CTypeInfo::Type::Enum> { \ 6411cb0ef41Sopenharmony_ci using ctype = CType; \ 6421cb0ef41Sopenharmony_ci }; 6431cb0ef41Sopenharmony_ci 6441cb0ef41Sopenharmony_ci#define PRIMITIVE_C_TYPES(V) \ 6451cb0ef41Sopenharmony_ci V(bool, kBool) \ 6461cb0ef41Sopenharmony_ci V(int32_t, kInt32) \ 6471cb0ef41Sopenharmony_ci V(uint32_t, kUint32) \ 6481cb0ef41Sopenharmony_ci V(int64_t, kInt64) \ 6491cb0ef41Sopenharmony_ci V(uint64_t, kUint64) \ 6501cb0ef41Sopenharmony_ci V(float, kFloat32) \ 6511cb0ef41Sopenharmony_ci V(double, kFloat64) 6521cb0ef41Sopenharmony_ci 6531cb0ef41Sopenharmony_ci// Same as above, but includes deprecated types for compatibility. 6541cb0ef41Sopenharmony_ci#define ALL_C_TYPES(V) \ 6551cb0ef41Sopenharmony_ci PRIMITIVE_C_TYPES(V) \ 6561cb0ef41Sopenharmony_ci V(void, kVoid) \ 6571cb0ef41Sopenharmony_ci V(v8::Local<v8::Value>, kV8Value) \ 6581cb0ef41Sopenharmony_ci V(v8::Local<v8::Object>, kV8Value) \ 6591cb0ef41Sopenharmony_ci V(AnyCType, kAny) 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_ci// ApiObject was a temporary solution to wrap the pointer to the v8::Value. 6621cb0ef41Sopenharmony_ci// Please use v8::Local<v8::Value> in new code for the arguments and 6631cb0ef41Sopenharmony_ci// v8::Local<v8::Object> for the receiver, as ApiObject will be deprecated. 6641cb0ef41Sopenharmony_ci 6651cb0ef41Sopenharmony_ciALL_C_TYPES(SPECIALIZE_GET_TYPE_INFO_HELPER_FOR) 6661cb0ef41Sopenharmony_ciPRIMITIVE_C_TYPES(DEFINE_TYPE_INFO_TRAITS) 6671cb0ef41Sopenharmony_ci 6681cb0ef41Sopenharmony_ci#undef PRIMITIVE_C_TYPES 6691cb0ef41Sopenharmony_ci#undef ALL_C_TYPES 6701cb0ef41Sopenharmony_ci 6711cb0ef41Sopenharmony_ci#define SPECIALIZE_GET_TYPE_INFO_HELPER_FOR_TA(T, Enum) \ 6721cb0ef41Sopenharmony_ci template <> \ 6731cb0ef41Sopenharmony_ci struct TypeInfoHelper<const FastApiTypedArray<T>&> { \ 6741cb0ef41Sopenharmony_ci static constexpr CTypeInfo::Flags Flags() { \ 6751cb0ef41Sopenharmony_ci return CTypeInfo::Flags::kNone; \ 6761cb0ef41Sopenharmony_ci } \ 6771cb0ef41Sopenharmony_ci \ 6781cb0ef41Sopenharmony_ci static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::Enum; } \ 6791cb0ef41Sopenharmony_ci static constexpr CTypeInfo::SequenceType SequenceType() { \ 6801cb0ef41Sopenharmony_ci return CTypeInfo::SequenceType::kIsTypedArray; \ 6811cb0ef41Sopenharmony_ci } \ 6821cb0ef41Sopenharmony_ci }; 6831cb0ef41Sopenharmony_ci 6841cb0ef41Sopenharmony_ci#define TYPED_ARRAY_C_TYPES(V) \ 6851cb0ef41Sopenharmony_ci V(int32_t, kInt32) \ 6861cb0ef41Sopenharmony_ci V(uint32_t, kUint32) \ 6871cb0ef41Sopenharmony_ci V(int64_t, kInt64) \ 6881cb0ef41Sopenharmony_ci V(uint64_t, kUint64) \ 6891cb0ef41Sopenharmony_ci V(float, kFloat32) \ 6901cb0ef41Sopenharmony_ci V(double, kFloat64) 6911cb0ef41Sopenharmony_ci 6921cb0ef41Sopenharmony_ciTYPED_ARRAY_C_TYPES(SPECIALIZE_GET_TYPE_INFO_HELPER_FOR_TA) 6931cb0ef41Sopenharmony_ci 6941cb0ef41Sopenharmony_ci#undef TYPED_ARRAY_C_TYPES 6951cb0ef41Sopenharmony_ci 6961cb0ef41Sopenharmony_citemplate <> 6971cb0ef41Sopenharmony_cistruct TypeInfoHelper<v8::Local<v8::Array>> { 6981cb0ef41Sopenharmony_ci static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; } 6991cb0ef41Sopenharmony_ci 7001cb0ef41Sopenharmony_ci static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::kVoid; } 7011cb0ef41Sopenharmony_ci static constexpr CTypeInfo::SequenceType SequenceType() { 7021cb0ef41Sopenharmony_ci return CTypeInfo::SequenceType::kIsSequence; 7031cb0ef41Sopenharmony_ci } 7041cb0ef41Sopenharmony_ci}; 7051cb0ef41Sopenharmony_ci 7061cb0ef41Sopenharmony_citemplate <> 7071cb0ef41Sopenharmony_cistruct TypeInfoHelper<v8::Local<v8::Uint32Array>> { 7081cb0ef41Sopenharmony_ci static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; } 7091cb0ef41Sopenharmony_ci 7101cb0ef41Sopenharmony_ci static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::kUint32; } 7111cb0ef41Sopenharmony_ci static constexpr CTypeInfo::SequenceType SequenceType() { 7121cb0ef41Sopenharmony_ci return CTypeInfo::SequenceType::kIsTypedArray; 7131cb0ef41Sopenharmony_ci } 7141cb0ef41Sopenharmony_ci}; 7151cb0ef41Sopenharmony_ci 7161cb0ef41Sopenharmony_citemplate <> 7171cb0ef41Sopenharmony_cistruct TypeInfoHelper<FastApiCallbackOptions&> { 7181cb0ef41Sopenharmony_ci static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; } 7191cb0ef41Sopenharmony_ci 7201cb0ef41Sopenharmony_ci static constexpr CTypeInfo::Type Type() { 7211cb0ef41Sopenharmony_ci return CTypeInfo::kCallbackOptionsType; 7221cb0ef41Sopenharmony_ci } 7231cb0ef41Sopenharmony_ci static constexpr CTypeInfo::SequenceType SequenceType() { 7241cb0ef41Sopenharmony_ci return CTypeInfo::SequenceType::kScalar; 7251cb0ef41Sopenharmony_ci } 7261cb0ef41Sopenharmony_ci}; 7271cb0ef41Sopenharmony_ci 7281cb0ef41Sopenharmony_ci#define STATIC_ASSERT_IMPLIES(COND, ASSERTION, MSG) \ 7291cb0ef41Sopenharmony_ci static_assert(((COND) == 0) || (ASSERTION), MSG) 7301cb0ef41Sopenharmony_ci 7311cb0ef41Sopenharmony_ci} // namespace internal 7321cb0ef41Sopenharmony_ci 7331cb0ef41Sopenharmony_citemplate <typename T, CTypeInfo::Flags... Flags> 7341cb0ef41Sopenharmony_ciclass V8_EXPORT CTypeInfoBuilder { 7351cb0ef41Sopenharmony_ci public: 7361cb0ef41Sopenharmony_ci using BaseType = T; 7371cb0ef41Sopenharmony_ci 7381cb0ef41Sopenharmony_ci static constexpr CTypeInfo Build() { 7391cb0ef41Sopenharmony_ci constexpr CTypeInfo::Flags kFlags = 7401cb0ef41Sopenharmony_ci MergeFlags(internal::TypeInfoHelper<T>::Flags(), Flags...); 7411cb0ef41Sopenharmony_ci constexpr CTypeInfo::Type kType = internal::TypeInfoHelper<T>::Type(); 7421cb0ef41Sopenharmony_ci constexpr CTypeInfo::SequenceType kSequenceType = 7431cb0ef41Sopenharmony_ci internal::TypeInfoHelper<T>::SequenceType(); 7441cb0ef41Sopenharmony_ci 7451cb0ef41Sopenharmony_ci STATIC_ASSERT_IMPLIES( 7461cb0ef41Sopenharmony_ci uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kAllowSharedBit), 7471cb0ef41Sopenharmony_ci (kSequenceType == CTypeInfo::SequenceType::kIsTypedArray || 7481cb0ef41Sopenharmony_ci kSequenceType == CTypeInfo::SequenceType::kIsArrayBuffer), 7491cb0ef41Sopenharmony_ci "kAllowSharedBit is only allowed for TypedArrays and ArrayBuffers."); 7501cb0ef41Sopenharmony_ci STATIC_ASSERT_IMPLIES( 7511cb0ef41Sopenharmony_ci uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kEnforceRangeBit), 7521cb0ef41Sopenharmony_ci CTypeInfo::IsIntegralType(kType), 7531cb0ef41Sopenharmony_ci "kEnforceRangeBit is only allowed for integral types."); 7541cb0ef41Sopenharmony_ci STATIC_ASSERT_IMPLIES( 7551cb0ef41Sopenharmony_ci uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kClampBit), 7561cb0ef41Sopenharmony_ci CTypeInfo::IsIntegralType(kType), 7571cb0ef41Sopenharmony_ci "kClampBit is only allowed for integral types."); 7581cb0ef41Sopenharmony_ci STATIC_ASSERT_IMPLIES( 7591cb0ef41Sopenharmony_ci uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kIsRestrictedBit), 7601cb0ef41Sopenharmony_ci CTypeInfo::IsFloatingPointType(kType), 7611cb0ef41Sopenharmony_ci "kIsRestrictedBit is only allowed for floating point types."); 7621cb0ef41Sopenharmony_ci STATIC_ASSERT_IMPLIES(kSequenceType == CTypeInfo::SequenceType::kIsSequence, 7631cb0ef41Sopenharmony_ci kType == CTypeInfo::Type::kVoid, 7641cb0ef41Sopenharmony_ci "Sequences are only supported from void type."); 7651cb0ef41Sopenharmony_ci STATIC_ASSERT_IMPLIES( 7661cb0ef41Sopenharmony_ci kSequenceType == CTypeInfo::SequenceType::kIsTypedArray, 7671cb0ef41Sopenharmony_ci CTypeInfo::IsPrimitive(kType) || kType == CTypeInfo::Type::kVoid, 7681cb0ef41Sopenharmony_ci "TypedArrays are only supported from primitive types or void."); 7691cb0ef41Sopenharmony_ci 7701cb0ef41Sopenharmony_ci // Return the same type with the merged flags. 7711cb0ef41Sopenharmony_ci return CTypeInfo(internal::TypeInfoHelper<T>::Type(), 7721cb0ef41Sopenharmony_ci internal::TypeInfoHelper<T>::SequenceType(), kFlags); 7731cb0ef41Sopenharmony_ci } 7741cb0ef41Sopenharmony_ci 7751cb0ef41Sopenharmony_ci private: 7761cb0ef41Sopenharmony_ci template <typename... Rest> 7771cb0ef41Sopenharmony_ci static constexpr CTypeInfo::Flags MergeFlags(CTypeInfo::Flags flags, 7781cb0ef41Sopenharmony_ci Rest... rest) { 7791cb0ef41Sopenharmony_ci return CTypeInfo::Flags(uint8_t(flags) | uint8_t(MergeFlags(rest...))); 7801cb0ef41Sopenharmony_ci } 7811cb0ef41Sopenharmony_ci static constexpr CTypeInfo::Flags MergeFlags() { return CTypeInfo::Flags(0); } 7821cb0ef41Sopenharmony_ci}; 7831cb0ef41Sopenharmony_ci 7841cb0ef41Sopenharmony_cinamespace internal { 7851cb0ef41Sopenharmony_citemplate <typename RetBuilder, typename... ArgBuilders> 7861cb0ef41Sopenharmony_ciclass CFunctionBuilderWithFunction { 7871cb0ef41Sopenharmony_ci public: 7881cb0ef41Sopenharmony_ci explicit constexpr CFunctionBuilderWithFunction(const void* fn) : fn_(fn) {} 7891cb0ef41Sopenharmony_ci 7901cb0ef41Sopenharmony_ci template <CTypeInfo::Flags... Flags> 7911cb0ef41Sopenharmony_ci constexpr auto Ret() { 7921cb0ef41Sopenharmony_ci return CFunctionBuilderWithFunction< 7931cb0ef41Sopenharmony_ci CTypeInfoBuilder<typename RetBuilder::BaseType, Flags...>, 7941cb0ef41Sopenharmony_ci ArgBuilders...>(fn_); 7951cb0ef41Sopenharmony_ci } 7961cb0ef41Sopenharmony_ci 7971cb0ef41Sopenharmony_ci template <unsigned int N, CTypeInfo::Flags... Flags> 7981cb0ef41Sopenharmony_ci constexpr auto Arg() { 7991cb0ef41Sopenharmony_ci // Return a copy of the builder with the Nth arg builder merged with 8001cb0ef41Sopenharmony_ci // template parameter pack Flags. 8011cb0ef41Sopenharmony_ci return ArgImpl<N, Flags...>( 8021cb0ef41Sopenharmony_ci std::make_index_sequence<sizeof...(ArgBuilders)>()); 8031cb0ef41Sopenharmony_ci } 8041cb0ef41Sopenharmony_ci 8051cb0ef41Sopenharmony_ci auto Build() { 8061cb0ef41Sopenharmony_ci static CFunctionInfoImpl<RetBuilder, ArgBuilders...> instance; 8071cb0ef41Sopenharmony_ci return CFunction(fn_, &instance); 8081cb0ef41Sopenharmony_ci } 8091cb0ef41Sopenharmony_ci 8101cb0ef41Sopenharmony_ci private: 8111cb0ef41Sopenharmony_ci template <bool Merge, unsigned int N, CTypeInfo::Flags... Flags> 8121cb0ef41Sopenharmony_ci struct GetArgBuilder; 8131cb0ef41Sopenharmony_ci 8141cb0ef41Sopenharmony_ci // Returns the same ArgBuilder as the one at index N, including its flags. 8151cb0ef41Sopenharmony_ci // Flags in the template parameter pack are ignored. 8161cb0ef41Sopenharmony_ci template <unsigned int N, CTypeInfo::Flags... Flags> 8171cb0ef41Sopenharmony_ci struct GetArgBuilder<false, N, Flags...> { 8181cb0ef41Sopenharmony_ci using type = 8191cb0ef41Sopenharmony_ci typename std::tuple_element<N, std::tuple<ArgBuilders...>>::type; 8201cb0ef41Sopenharmony_ci }; 8211cb0ef41Sopenharmony_ci 8221cb0ef41Sopenharmony_ci // Returns an ArgBuilder with the same base type as the one at index N, 8231cb0ef41Sopenharmony_ci // but merges the flags with the flags in the template parameter pack. 8241cb0ef41Sopenharmony_ci template <unsigned int N, CTypeInfo::Flags... Flags> 8251cb0ef41Sopenharmony_ci struct GetArgBuilder<true, N, Flags...> { 8261cb0ef41Sopenharmony_ci using type = CTypeInfoBuilder< 8271cb0ef41Sopenharmony_ci typename std::tuple_element<N, 8281cb0ef41Sopenharmony_ci std::tuple<ArgBuilders...>>::type::BaseType, 8291cb0ef41Sopenharmony_ci std::tuple_element<N, std::tuple<ArgBuilders...>>::type::Build() 8301cb0ef41Sopenharmony_ci .GetFlags(), 8311cb0ef41Sopenharmony_ci Flags...>; 8321cb0ef41Sopenharmony_ci }; 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_ci // Return a copy of the CFunctionBuilder, but merges the Flags on 8351cb0ef41Sopenharmony_ci // ArgBuilder index N with the new Flags passed in the template parameter 8361cb0ef41Sopenharmony_ci // pack. 8371cb0ef41Sopenharmony_ci template <unsigned int N, CTypeInfo::Flags... Flags, size_t... I> 8381cb0ef41Sopenharmony_ci constexpr auto ArgImpl(std::index_sequence<I...>) { 8391cb0ef41Sopenharmony_ci return CFunctionBuilderWithFunction< 8401cb0ef41Sopenharmony_ci RetBuilder, typename GetArgBuilder<N == I, I, Flags...>::type...>(fn_); 8411cb0ef41Sopenharmony_ci } 8421cb0ef41Sopenharmony_ci 8431cb0ef41Sopenharmony_ci const void* fn_; 8441cb0ef41Sopenharmony_ci}; 8451cb0ef41Sopenharmony_ci 8461cb0ef41Sopenharmony_ciclass CFunctionBuilder { 8471cb0ef41Sopenharmony_ci public: 8481cb0ef41Sopenharmony_ci constexpr CFunctionBuilder() {} 8491cb0ef41Sopenharmony_ci 8501cb0ef41Sopenharmony_ci template <typename R, typename... Args> 8511cb0ef41Sopenharmony_ci constexpr auto Fn(R (*fn)(Args...)) { 8521cb0ef41Sopenharmony_ci return CFunctionBuilderWithFunction<CTypeInfoBuilder<R>, 8531cb0ef41Sopenharmony_ci CTypeInfoBuilder<Args>...>( 8541cb0ef41Sopenharmony_ci reinterpret_cast<const void*>(fn)); 8551cb0ef41Sopenharmony_ci } 8561cb0ef41Sopenharmony_ci}; 8571cb0ef41Sopenharmony_ci 8581cb0ef41Sopenharmony_ci} // namespace internal 8591cb0ef41Sopenharmony_ci 8601cb0ef41Sopenharmony_ci// static 8611cb0ef41Sopenharmony_citemplate <typename R, typename... Args> 8621cb0ef41Sopenharmony_ciCFunction CFunction::ArgUnwrap<R (*)(Args...)>::Make(R (*func)(Args...)) { 8631cb0ef41Sopenharmony_ci return internal::CFunctionBuilder().Fn(func).Build(); 8641cb0ef41Sopenharmony_ci} 8651cb0ef41Sopenharmony_ci 8661cb0ef41Sopenharmony_ciusing CFunctionBuilder = internal::CFunctionBuilder; 8671cb0ef41Sopenharmony_ci 8681cb0ef41Sopenharmony_cistatic constexpr CTypeInfo kTypeInfoInt32 = CTypeInfo(CTypeInfo::Type::kInt32); 8691cb0ef41Sopenharmony_cistatic constexpr CTypeInfo kTypeInfoFloat64 = 8701cb0ef41Sopenharmony_ci CTypeInfo(CTypeInfo::Type::kFloat64); 8711cb0ef41Sopenharmony_ci 8721cb0ef41Sopenharmony_ci/** 8731cb0ef41Sopenharmony_ci * Copies the contents of this JavaScript array to a C++ buffer with 8741cb0ef41Sopenharmony_ci * a given max_length. A CTypeInfo is passed as an argument, 8751cb0ef41Sopenharmony_ci * instructing different rules for conversion (e.g. restricted float/double). 8761cb0ef41Sopenharmony_ci * The element type T of the destination array must match the C type 8771cb0ef41Sopenharmony_ci * corresponding to the CTypeInfo (specified by CTypeInfoTraits). 8781cb0ef41Sopenharmony_ci * If the array length is larger than max_length or the array is of 8791cb0ef41Sopenharmony_ci * unsupported type, the operation will fail, returning false. Generally, an 8801cb0ef41Sopenharmony_ci * array which contains objects, undefined, null or anything not convertible 8811cb0ef41Sopenharmony_ci * to the requested destination type, is considered unsupported. The operation 8821cb0ef41Sopenharmony_ci * returns true on success. `type_info` will be used for conversions. 8831cb0ef41Sopenharmony_ci */ 8841cb0ef41Sopenharmony_citemplate <const CTypeInfo* type_info, typename T> 8851cb0ef41Sopenharmony_ciV8_DEPRECATED( 8861cb0ef41Sopenharmony_ci "Use TryToCopyAndConvertArrayToCppBuffer<CTypeInfo::Identifier, T>()") 8871cb0ef41Sopenharmony_cibool V8_EXPORT V8_WARN_UNUSED_RESULT 8881cb0ef41Sopenharmony_ci TryCopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst, 8891cb0ef41Sopenharmony_ci uint32_t max_length); 8901cb0ef41Sopenharmony_ci 8911cb0ef41Sopenharmony_citemplate <> 8921cb0ef41Sopenharmony_ciV8_DEPRECATED( 8931cb0ef41Sopenharmony_ci "Use TryToCopyAndConvertArrayToCppBuffer<CTypeInfo::Identifier, T>()") 8941cb0ef41Sopenharmony_ciinline bool V8_WARN_UNUSED_RESULT 8951cb0ef41Sopenharmony_ci TryCopyAndConvertArrayToCppBuffer<&kTypeInfoInt32, int32_t>( 8961cb0ef41Sopenharmony_ci Local<Array> src, int32_t* dst, uint32_t max_length) { 8971cb0ef41Sopenharmony_ci return false; 8981cb0ef41Sopenharmony_ci} 8991cb0ef41Sopenharmony_ci 9001cb0ef41Sopenharmony_citemplate <> 9011cb0ef41Sopenharmony_ciV8_DEPRECATED( 9021cb0ef41Sopenharmony_ci "Use TryToCopyAndConvertArrayToCppBuffer<CTypeInfo::Identifier, T>()") 9031cb0ef41Sopenharmony_ciinline bool V8_WARN_UNUSED_RESULT 9041cb0ef41Sopenharmony_ci TryCopyAndConvertArrayToCppBuffer<&kTypeInfoFloat64, double>( 9051cb0ef41Sopenharmony_ci Local<Array> src, double* dst, uint32_t max_length) { 9061cb0ef41Sopenharmony_ci return false; 9071cb0ef41Sopenharmony_ci} 9081cb0ef41Sopenharmony_ci 9091cb0ef41Sopenharmony_citemplate <CTypeInfo::Identifier type_info_id, typename T> 9101cb0ef41Sopenharmony_cibool V8_EXPORT V8_WARN_UNUSED_RESULT TryToCopyAndConvertArrayToCppBuffer( 9111cb0ef41Sopenharmony_ci Local<Array> src, T* dst, uint32_t max_length); 9121cb0ef41Sopenharmony_ci 9131cb0ef41Sopenharmony_citemplate <> 9141cb0ef41Sopenharmony_cibool V8_EXPORT V8_WARN_UNUSED_RESULT 9151cb0ef41Sopenharmony_ciTryToCopyAndConvertArrayToCppBuffer<CTypeInfoBuilder<int32_t>::Build().GetId(), 9161cb0ef41Sopenharmony_ci int32_t>(Local<Array> src, int32_t* dst, 9171cb0ef41Sopenharmony_ci uint32_t max_length); 9181cb0ef41Sopenharmony_ci 9191cb0ef41Sopenharmony_citemplate <> 9201cb0ef41Sopenharmony_cibool V8_EXPORT V8_WARN_UNUSED_RESULT 9211cb0ef41Sopenharmony_ciTryToCopyAndConvertArrayToCppBuffer<CTypeInfoBuilder<uint32_t>::Build().GetId(), 9221cb0ef41Sopenharmony_ci uint32_t>(Local<Array> src, uint32_t* dst, 9231cb0ef41Sopenharmony_ci uint32_t max_length); 9241cb0ef41Sopenharmony_ci 9251cb0ef41Sopenharmony_citemplate <> 9261cb0ef41Sopenharmony_cibool V8_EXPORT V8_WARN_UNUSED_RESULT 9271cb0ef41Sopenharmony_ciTryToCopyAndConvertArrayToCppBuffer<CTypeInfoBuilder<float>::Build().GetId(), 9281cb0ef41Sopenharmony_ci float>(Local<Array> src, float* dst, 9291cb0ef41Sopenharmony_ci uint32_t max_length); 9301cb0ef41Sopenharmony_ci 9311cb0ef41Sopenharmony_citemplate <> 9321cb0ef41Sopenharmony_cibool V8_EXPORT V8_WARN_UNUSED_RESULT 9331cb0ef41Sopenharmony_ciTryToCopyAndConvertArrayToCppBuffer<CTypeInfoBuilder<double>::Build().GetId(), 9341cb0ef41Sopenharmony_ci double>(Local<Array> src, double* dst, 9351cb0ef41Sopenharmony_ci uint32_t max_length); 9361cb0ef41Sopenharmony_ci 9371cb0ef41Sopenharmony_ci} // namespace v8 9381cb0ef41Sopenharmony_ci 9391cb0ef41Sopenharmony_ci#endif // INCLUDE_V8_FAST_API_CALLS_H_ 940