blob: dc44405121371e5e8891fee291eac3edb5407527 [file] [edit]
#pragma once
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#include "base_object.h"
#include "ffi.h"
#include "ffi/fast.h"
#include "uv.h"
#include <cstdint>
#include <memory>
#include <string>
#include <thread>
#include <unordered_map>
#include <vector>
namespace node::ffi {
class DynamicLibrary;
struct FFIFunction;
struct FFIFunction {
bool closed;
void* ptr;
ffi_cif cif;
std::vector<ffi_type*> args;
ffi_type* return_type;
std::vector<std::string> arg_type_names;
std::string return_type_name;
};
class FFIFunctionInfo final : public BaseObject {
public:
enum InternalFields {
kLibrary = BaseObject::kInternalFieldCount,
kInternalFieldCount
};
FFIFunctionInfo(Environment* env,
v8::Local<v8::Object> object,
std::shared_ptr<FFIFunction> fn,
DynamicLibrary* library);
void MemoryInfo(MemoryTracker* tracker) const override;
SET_MEMORY_INFO_NAME(FFIFunctionInfo)
SET_SELF_SIZE(FFIFunctionInfo)
static BaseObjectPtr<FFIFunctionInfo> Create(Environment* env,
std::shared_ptr<FFIFunction> fn,
DynamicLibrary* library);
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
IsolateData* isolate_data);
private:
std::shared_ptr<FFIFunction> fn;
std::shared_ptr<v8::BackingStore> sb_backing;
std::unique_ptr<FastFFIMetadata> fast_metadata;
std::unique_ptr<FastFFIMetadata> fast_buffer_metadata;
friend class DynamicLibrary;
};
struct FFICallback {
DynamicLibrary* owner;
Environment* env;
std::thread::id thread_id;
v8::Global<v8::Function> fn;
ffi_closure* closure;
void* ptr;
ffi_cif cif;
std::vector<ffi_type*> args;
ffi_type* return_type;
~FFICallback() {
if (!fn.IsEmpty()) {
fn.Reset();
}
if (closure != nullptr) {
ffi_closure_free(closure);
closure = nullptr;
}
}
};
struct ResolvedFunction {
std::string name;
std::shared_ptr<FFIFunction> fn;
bool should_cache_symbol;
bool should_cache_function;
};
class DynamicLibrary : public BaseObject {
public:
DynamicLibrary(Environment* env, v8::Local<v8::Object> object);
~DynamicLibrary() override;
void MemoryInfo(MemoryTracker* tracker) const override;
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
Environment* env);
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
static void InvokeFunction(const v8::FunctionCallbackInfo<v8::Value>& args);
static void InvokeFunctionSB(const v8::FunctionCallbackInfo<v8::Value>& args);
static void InvokeCallback(ffi_cif* cif,
void* ret,
void** args,
void* user_data);
static void GetPath(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetFunction(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetFunctions(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetSymbol(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetSymbols(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RegisterCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
static void UnregisterCallback(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void RefCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
static void UnrefCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
SET_MEMORY_INFO_NAME(DynamicLibrary)
SET_SELF_SIZE(DynamicLibrary)
private:
void Close();
v8::Maybe<void*> ResolveSymbol(Environment* env, const std::string& name);
struct PreparedFunction {
std::shared_ptr<FFIFunction> fn;
bool should_cache_symbol;
bool should_cache_function;
};
v8::Maybe<PreparedFunction> PrepareFunction(Environment* env,
const std::string& name,
v8::Local<v8::Object> signature);
v8::MaybeLocal<v8::Function> CreateFunction(
Environment* env,
const std::string& name,
const std::shared_ptr<FFIFunction>& fn);
static void CleanupFunctionInfo(
const v8::WeakCallbackInfo<FFIFunctionInfo>& data);
bool is_closed() const;
uv_lib_t lib_ = {};
std::string path_;
std::unordered_map<std::string, void*> symbols_;
std::unordered_map<std::string, std::shared_ptr<FFIFunction>> functions_;
std::unordered_map<void*, std::unique_ptr<FFICallback>> callbacks_;
};
void GetInt8(const v8::FunctionCallbackInfo<v8::Value>& args);
void GetUint8(const v8::FunctionCallbackInfo<v8::Value>& args);
void GetInt16(const v8::FunctionCallbackInfo<v8::Value>& args);
void GetUint16(const v8::FunctionCallbackInfo<v8::Value>& args);
void GetInt32(const v8::FunctionCallbackInfo<v8::Value>& args);
void GetUint32(const v8::FunctionCallbackInfo<v8::Value>& args);
void GetInt64(const v8::FunctionCallbackInfo<v8::Value>& args);
void GetUint64(const v8::FunctionCallbackInfo<v8::Value>& args);
void GetFloat32(const v8::FunctionCallbackInfo<v8::Value>& args);
void GetFloat64(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetInt8(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetUint8(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetInt16(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetUint16(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetInt32(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetUint32(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetInt64(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetUint64(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetFloat32(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetFloat64(const v8::FunctionCallbackInfo<v8::Value>& args);
void ToString(const v8::FunctionCallbackInfo<v8::Value>& args);
void ToBuffer(const v8::FunctionCallbackInfo<v8::Value>& args);
void ToArrayBuffer(const v8::FunctionCallbackInfo<v8::Value>& args);
void ExportBytes(const v8::FunctionCallbackInfo<v8::Value>& args);
void GetRawPointer(const v8::FunctionCallbackInfo<v8::Value>& args);
} // namespace node::ffi
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS