Skip to content

Commit

Permalink
sfinae ObjectWrap::Finalize
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinEady committed Jun 15, 2024
1 parent 5102d3f commit e7e8a81
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 11 deletions.
72 changes: 64 additions & 8 deletions napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,34 @@ inline std::string StringFormat(const char* format, ...) {
return result;
}

template <typename T>
class HasGcFinalize {
private:
template <typename U, void (U::*)(Napi::Env)>
struct SFINAE {};
template <typename U>
static char test(SFINAE<U, &U::Finalize>*);
template <typename U>
static int test(...);

public:
static constexpr bool value = sizeof(test<T>(0)) == sizeof(char);
};

template <typename T>
class HasNogcFinalize {
private:
template <typename U, void (U::*)(Napi::NogcEnv)>
struct SFINAE {};
template <typename U>
static char test(SFINAE<U, &U::Finalize>*);
template <typename U>
static int test(...);

public:
static constexpr bool value = sizeof(test<T>(0)) == sizeof(char);
};

} // namespace details

#ifndef NODE_ADDON_API_DISABLE_DEPRECATED
Expand Down Expand Up @@ -2821,7 +2849,7 @@ inline Buffer<T> Buffer<T>::NewOrCopy(napi_env env,
#endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
// If we can't create an external buffer, we'll just copy the data.
Buffer<T> ret = Buffer<T>::Copy(env, data, length);
details::FinalizeData<T, Finalizer>::Wrapper(env, data, finalizeData);
details::FinalizeData<T, Finalizer>::WrapperGC(env, data, finalizeData);
return ret;
#ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
}
Expand Down Expand Up @@ -2856,7 +2884,7 @@ inline Buffer<T> Buffer<T>::NewOrCopy(napi_env env,
#endif
// If we can't create an external buffer, we'll just copy the data.
Buffer<T> ret = Buffer<T>::Copy(env, data, length);
details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint(
details::FinalizeData<T, Finalizer, Hint>::WrapperGCWithHint(
env, data, finalizeData);
return ret;
#ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
Expand Down Expand Up @@ -4890,7 +4918,10 @@ inline Value ObjectWrap<T>::OnCalledAsFunction(
}

template <typename T>
inline void ObjectWrap<T>::Finalize(NODE_ADDON_API_NOGC_ENV_CLASS /*env*/) {}
inline void ObjectWrap<T>::Finalize(Napi::Env /*env*/) {}

template <typename T>
inline void ObjectWrap<T>::Finalize(NogcEnv /*env*/) {}

template <typename T>
inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
Expand Down Expand Up @@ -4980,16 +5011,41 @@ template <typename T>
inline void ObjectWrap<T>::FinalizeCallback(NODE_ADDON_API_NOGC_ENV env,
void* data,
void* /*hint*/) {
#ifndef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
HandleScope scope(env);
#endif

T* instance = static_cast<T*>(data);
instance->Finalize(env);

// Prevent ~ObjectWrap from calling napi_remove_wrap
instance->_ref = nullptr;

if constexpr (details::HasNogcFinalize<T>::value) {
#ifndef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
HandleScope scope(env);
#endif

instance->Finalize(Napi::NogcEnv(env));
}

if constexpr (details::HasGcFinalize<T>::value) {
#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
napi_status status =
node_api_post_finalizer(env, PostFinalizeCallback, data, nullptr);
NAPI_FATAL_IF_FAILED(status,
"ObjectWrap<T>::FinalizeCallback",
"node_api_post_finalizer failed");
#else
HandleScope scope(env);
PostFinalizeCallback(env, data, static_cast<void*>(nullptr));
#endif
} else {
delete instance;
}
}

template <typename T>
inline void ObjectWrap<T>::PostFinalizeCallback(napi_env env,
void* data,
void* /*hint*/) {
T* instance = static_cast<T*>(data);
instance->Finalize(Napi::Env(env));
delete instance;
}

Expand Down
8 changes: 5 additions & 3 deletions napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,9 @@ using MaybeOrValue = T;

#if defined(NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER)
#define NODE_ADDON_API_NOGC_ENV node_api_nogc_env
#define NODE_ADDON_API_NOGC_ENV_CLASS Napi::NogcEnv
#define NODE_ADDON_API_NOGC_FINALIZER node_api_nogc_finalize
#else
#define NODE_ADDON_API_NOGC_ENV napi_env
#define NODE_ADDON_API_NOGC_ENV_CLASS Napi::Env
#define NODE_ADDON_API_NOGC_FINALIZER napi_finalize
#endif

Expand Down Expand Up @@ -2457,7 +2455,8 @@ class ObjectWrap : public InstanceWrap<T>, public Reference<Object> {
Napi::Value value,
napi_property_attributes attributes = napi_default);
static Napi::Value OnCalledAsFunction(const Napi::CallbackInfo& callbackInfo);
virtual void Finalize(NODE_ADDON_API_NOGC_ENV_CLASS env);
virtual void Finalize(Napi::Env env);
virtual void Finalize(NogcEnv env);

private:
using This = ObjectWrap<T>;
Expand All @@ -2475,6 +2474,9 @@ class ObjectWrap : public InstanceWrap<T>, public Reference<Object> {
static void FinalizeCallback(NODE_ADDON_API_NOGC_ENV env,
void* data,
void* hint);

static void PostFinalizeCallback(napi_env env, void* data, void* hint);

static Function DefineClass(Napi::Env env,
const char* utf8name,
const size_t props_count,
Expand Down

0 comments on commit e7e8a81

Please sign in to comment.