/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/src/api/api.h
570 строк
22 KB
Michaël Zasso
deps: update V8 to 14.6.202.33
24 апр 2026, 19:01
Не верифицирован
24 апр 2026, 19:01
f1e0b83
Код
Авторство
О чём код?
// 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/execution/isolate.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 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, 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, WasmMemoryMapDescriptor, WasmMemoryMapDescriptor) \ 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, WasmMemoryMapDescriptor, WasmMemoryMapDescriptor) \ 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 class is here in order to be able to declare it a friend of // HandleScope. Moving these methods to be members of HandleScope would be // neat in some ways, but it would expose internal implementation details in // our public header file, which is undesirable. // // An isolate has a single instance of this class to hold the current thread's // data. In multithreaded V8 programs this data is copied in and out of storage // so that the currently executing thread always has its own copy of this // data. class HandleScopeImplementer { public: class V8_NODISCARD EnteredContextRewindScope { public: explicit EnteredContextRewindScope(HandleScopeImplementer* hsi) : hsi_(hsi), saved_entered_context_count_(hsi->EnteredContextCount()) {} ~EnteredContextRewindScope() { DCHECK_LE(saved_entered_context_count_, hsi_->EnteredContextCount()); while (saved_entered_context_count_ < hsi_->EnteredContextCount()) hsi_->LeaveContext(); } private: HandleScopeImplementer* hsi_; size_t saved_entered_context_count_; }; explicit HandleScopeImplementer(Isolate* isolate) : isolate_(isolate), spare_(nullptr) {} ~HandleScopeImplementer() { DeleteArray(spare_); } HandleScopeImplementer(const HandleScopeImplementer&) = delete; HandleScopeImplementer& operator=(const HandleScopeImplementer&) = delete; // Threading support for handle data. static int ArchiveSpacePerThread(); char* RestoreThread(char* from); char* ArchiveThread(char* to); void FreeThreadResources(); // Garbage collection support. V8_EXPORT_PRIVATE void Iterate(i::RootVisitor* v); V8_EXPORT_PRIVATE static char* Iterate(i::RootVisitor* v, char* data); inline internal::Address* GetSpareOrNewBlock(); inline void DeleteExtensions(internal::Address* prev_limit); inline void EnterContext(Tagged<NativeContext> context); inline void LeaveContext(); inline bool LastEnteredContextWas(Tagged<NativeContext> context); inline size_t EnteredContextCount() const { return entered_contexts_.size(); } // Returns the last entered context or an empty handle if no // contexts have been entered. inline DirectHandle<NativeContext> LastEnteredContext(); inline void SaveContext(Tagged<Context> context); inline Tagged<Context> RestoreContext(); inline bool HasSavedContexts(); inline DetachableVector<Address*>* blocks() { return &blocks_; } Isolate* isolate() const { return isolate_; } void ReturnBlock(Address* block) { DCHECK_NOT_NULL(block); if (spare_ != nullptr) DeleteArray(spare_); spare_ = block; } static const size_t kEnteredContextsOffset; private: void ResetAfterArchive() { blocks_.detach(); entered_contexts_.detach(); saved_contexts_.detach(); spare_ = nullptr; last_handle_before_persistent_block_.reset(); } void Free() { DCHECK(blocks_.empty()); DCHECK(entered_contexts_.empty()); DCHECK(saved_contexts_.empty()); blocks_.free(); entered_contexts_.free(); saved_contexts_.free(); if (spare_ != nullptr) { DeleteArray(spare_); spare_ = nullptr; } DCHECK(isolate_->thread_local_top()->CallDepthIsZero()); } void BeginPersistentScope() { DCHECK(!last_handle_before_persistent_block_.has_value()); last_handle_before_persistent_block_ = isolate()->handle_scope_data()->next; } bool HasPersistentScope() const { return last_handle_before_persistent_block_.has_value(); } std::unique_ptr<PersistentHandles> DetachPersistent(Address* first_block); Isolate* isolate_; DetachableVector<Address*> blocks_; // Used as a stack to keep track of entered contexts. DetachableVector<Tagged<NativeContext>> entered_contexts_; // Used as a stack to keep track of saved contexts. DetachableVector<Tagged<Context>> saved_contexts_; Address* spare_; std::optional<Address*> last_handle_before_persistent_block_; // This is only used for threading support. HandleScopeData handle_scope_data_; void IterateThis(RootVisitor* v); char* RestoreThreadHelper(char* from); char* ArchiveThreadHelper(char* to); friend class HandleScopeImplementerOffsets; friend class PersistentHandlesScope; }; const int kHandleBlockSize = i::KB - 2; // fit in one page void HandleScopeImplementer::SaveContext(Tagged<Context> context) { saved_contexts_.push_back(context); } Tagged<Context> HandleScopeImplementer::RestoreContext() { Tagged<Context> last_context = saved_contexts_.back(); saved_contexts_.pop_back(); return last_context; } bool HandleScopeImplementer::HasSavedContexts() { return !saved_contexts_.empty(); } void HandleScopeImplementer::LeaveContext() { DCHECK(!entered_contexts_.empty()); entered_contexts_.pop_back(); } bool HandleScopeImplementer::LastEnteredContextWas( Tagged<NativeContext> context) { return !entered_contexts_.empty() && entered_contexts_.back() == context; } // If there's a spare block, use it for growing the current scope. internal::Address* HandleScopeImplementer::GetSpareOrNewBlock() { internal::Address* block = (spare_ != nullptr) ? spare_ : NewArray<internal::Address>(kHandleBlockSize); spare_ = nullptr; return block; } void HandleScopeImplementer::DeleteExtensions(internal::Address* prev_limit) { while (!blocks_.empty()) { internal::Address* block_start = blocks_.back(); internal::Address* block_limit = block_start + kHandleBlockSize; // SealHandleScope may make the prev_limit to point inside the block. // Cast possibly-unrelated pointers to plain Address before comparing them // to avoid undefined behavior. if (reinterpret_cast<Address>(block_start) < reinterpret_cast<Address>(prev_limit) && reinterpret_cast<Address>(prev_limit) <= reinterpret_cast<Address>(block_limit)) { #ifdef ENABLE_LOCAL_HANDLE_ZAPPING internal::HandleScope::ZapRange(prev_limit, block_limit); #endif break; } blocks_.pop_back(); #ifdef ENABLE_LOCAL_HANDLE_ZAPPING internal::HandleScope::ZapRange(block_start, block_limit); #endif if (spare_ != nullptr) { DeleteArray(spare_); } spare_ = block_start; } DCHECK((blocks_.empty() && prev_limit == nullptr) || (!blocks_.empty() && prev_limit != nullptr)); } // 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<void>& 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_