Skip to content

Commit e7e8a81

Browse files
committed
sfinae ObjectWrap::Finalize
1 parent 5102d3f commit e7e8a81

File tree

2 files changed

+69
-11
lines changed

2 files changed

+69
-11
lines changed

napi-inl.h

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,34 @@ inline std::string StringFormat(const char* format, ...) {
426426
return result;
427427
}
428428

429+
template <typename T>
430+
class HasGcFinalize {
431+
private:
432+
template <typename U, void (U::*)(Napi::Env)>
433+
struct SFINAE {};
434+
template <typename U>
435+
static char test(SFINAE<U, &U::Finalize>*);
436+
template <typename U>
437+
static int test(...);
438+
439+
public:
440+
static constexpr bool value = sizeof(test<T>(0)) == sizeof(char);
441+
};
442+
443+
template <typename T>
444+
class HasNogcFinalize {
445+
private:
446+
template <typename U, void (U::*)(Napi::NogcEnv)>
447+
struct SFINAE {};
448+
template <typename U>
449+
static char test(SFINAE<U, &U::Finalize>*);
450+
template <typename U>
451+
static int test(...);
452+
453+
public:
454+
static constexpr bool value = sizeof(test<T>(0)) == sizeof(char);
455+
};
456+
429457
} // namespace details
430458

431459
#ifndef NODE_ADDON_API_DISABLE_DEPRECATED
@@ -2821,7 +2849,7 @@ inline Buffer<T> Buffer<T>::NewOrCopy(napi_env env,
28212849
#endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
28222850
// If we can't create an external buffer, we'll just copy the data.
28232851
Buffer<T> ret = Buffer<T>::Copy(env, data, length);
2824-
details::FinalizeData<T, Finalizer>::Wrapper(env, data, finalizeData);
2852+
details::FinalizeData<T, Finalizer>::WrapperGC(env, data, finalizeData);
28252853
return ret;
28262854
#ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
28272855
}
@@ -2856,7 +2884,7 @@ inline Buffer<T> Buffer<T>::NewOrCopy(napi_env env,
28562884
#endif
28572885
// If we can't create an external buffer, we'll just copy the data.
28582886
Buffer<T> ret = Buffer<T>::Copy(env, data, length);
2859-
details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint(
2887+
details::FinalizeData<T, Finalizer, Hint>::WrapperGCWithHint(
28602888
env, data, finalizeData);
28612889
return ret;
28622890
#ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
@@ -4890,7 +4918,10 @@ inline Value ObjectWrap<T>::OnCalledAsFunction(
48904918
}
48914919

48924920
template <typename T>
4893-
inline void ObjectWrap<T>::Finalize(NODE_ADDON_API_NOGC_ENV_CLASS /*env*/) {}
4921+
inline void ObjectWrap<T>::Finalize(Napi::Env /*env*/) {}
4922+
4923+
template <typename T>
4924+
inline void ObjectWrap<T>::Finalize(NogcEnv /*env*/) {}
48944925

48954926
template <typename T>
48964927
inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
@@ -4980,16 +5011,41 @@ template <typename T>
49805011
inline void ObjectWrap<T>::FinalizeCallback(NODE_ADDON_API_NOGC_ENV env,
49815012
void* data,
49825013
void* /*hint*/) {
4983-
#ifndef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
4984-
HandleScope scope(env);
4985-
#endif
4986-
49875014
T* instance = static_cast<T*>(data);
4988-
instance->Finalize(env);
49895015

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

5019+
if constexpr (details::HasNogcFinalize<T>::value) {
5020+
#ifndef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
5021+
HandleScope scope(env);
5022+
#endif
5023+
5024+
instance->Finalize(Napi::NogcEnv(env));
5025+
}
5026+
5027+
if constexpr (details::HasGcFinalize<T>::value) {
5028+
#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
5029+
napi_status status =
5030+
node_api_post_finalizer(env, PostFinalizeCallback, data, nullptr);
5031+
NAPI_FATAL_IF_FAILED(status,
5032+
"ObjectWrap<T>::FinalizeCallback",
5033+
"node_api_post_finalizer failed");
5034+
#else
5035+
HandleScope scope(env);
5036+
PostFinalizeCallback(env, data, static_cast<void*>(nullptr));
5037+
#endif
5038+
} else {
5039+
delete instance;
5040+
}
5041+
}
5042+
5043+
template <typename T>
5044+
inline void ObjectWrap<T>::PostFinalizeCallback(napi_env env,
5045+
void* data,
5046+
void* /*hint*/) {
5047+
T* instance = static_cast<T*>(data);
5048+
instance->Finalize(Napi::Env(env));
49935049
delete instance;
49945050
}
49955051

napi.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,9 @@ using MaybeOrValue = T;
302302

303303
#if defined(NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER)
304304
#define NODE_ADDON_API_NOGC_ENV node_api_nogc_env
305-
#define NODE_ADDON_API_NOGC_ENV_CLASS Napi::NogcEnv
306305
#define NODE_ADDON_API_NOGC_FINALIZER node_api_nogc_finalize
307306
#else
308307
#define NODE_ADDON_API_NOGC_ENV napi_env
309-
#define NODE_ADDON_API_NOGC_ENV_CLASS Napi::Env
310308
#define NODE_ADDON_API_NOGC_FINALIZER napi_finalize
311309
#endif
312310

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

24622461
private:
24632462
using This = ObjectWrap<T>;
@@ -2475,6 +2474,9 @@ class ObjectWrap : public InstanceWrap<T>, public Reference<Object> {
24752474
static void FinalizeCallback(NODE_ADDON_API_NOGC_ENV env,
24762475
void* data,
24772476
void* hint);
2477+
2478+
static void PostFinalizeCallback(napi_env env, void* data, void* hint);
2479+
24782480
static Function DefineClass(Napi::Env env,
24792481
const char* utf8name,
24802482
const size_t props_count,

0 commit comments

Comments
 (0)