diff --git a/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/Puerts_il2cpp.cpp.txt b/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/Puerts_il2cpp.cpp.txt index 6cbfd29112..85513eac01 100644 --- a/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/Puerts_il2cpp.cpp.txt +++ b/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/Puerts_il2cpp.cpp.txt @@ -1955,7 +1955,7 @@ puerts::JsEnvPrivate* InitialPapiEnvRef(struct pesapi_ffi* apis, pesapi_env_ref auto env = apis->get_env_from_ref(envRef); auto jsEnvPrivate = new puerts::JsEnvPrivate(apis, envRef, objPool, objPoolAddMethodInfo, objPoolRemoveMethodInfo); apis->set_env_private(env, jsEnvPrivate); - auto func = apis->create_function(env, LoadTypeWrapper, nullptr); + auto func = apis->create_function(env, LoadTypeWrapper, nullptr, nullptr); if (func) { pesapi_value global = apis->global(env); diff --git a/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/pesapi.h.txt b/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/pesapi.h.txt index cd421a7314..b8bc9b902d 100644 --- a/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/pesapi.h.txt +++ b/unity/Assets/core/upm/Editor/Resources/puerts/xil2cpp/pesapi.h.txt @@ -127,6 +127,7 @@ typedef struct pesapi_property_descriptor__* pesapi_property_descriptor; typedef void (*pesapi_callback)(struct pesapi_ffi* apis, pesapi_callback_info info); typedef void* (*pesapi_constructor)(struct pesapi_ffi* apis, pesapi_callback_info info); typedef void (*pesapi_finalize)(struct pesapi_ffi* apis, void* ptr, void* class_data, void* env_private); +typedef void (*pesapi_function_finalize)(struct pesapi_ffi* apis, void* data, void* env_private); typedef void* (*pesapi_on_native_object_enter)(void* ptr, void* class_data, void* env_private); // userdata: return of pesapi_on_native_object_enter typedef void (*pesapi_on_native_object_exit)(void* ptr, void* class_data, void* env_private, void* userdata); @@ -152,7 +153,7 @@ typedef pesapi_value (*pesapi_create_string_utf8_func)(pesapi_env env, const cha typedef pesapi_value (*pesapi_create_binary_func)(pesapi_env env, void* str, size_t length); typedef pesapi_value (*pesapi_create_array_func)(pesapi_env env); typedef pesapi_value (*pesapi_create_object_func)(pesapi_env env); -typedef pesapi_value (*pesapi_create_function_func)(pesapi_env env, pesapi_callback native_impl, void* data); +typedef pesapi_value (*pesapi_create_function_func)(pesapi_env env, pesapi_callback native_impl, void* data, pesapi_function_finalize finalize); typedef pesapi_value (*pesapi_create_class_func)(pesapi_env env, const void* type_id); typedef bool (*pesapi_get_value_bool_func)(pesapi_env env, pesapi_value value); diff --git a/unity/Assets/core/upm/Runtime/Src/IL2Cpp/JsEnv.cs b/unity/Assets/core/upm/Runtime/Src/IL2Cpp/JsEnv.cs index 5a2c607608..8f191c9322 100644 --- a/unity/Assets/core/upm/Runtime/Src/IL2Cpp/JsEnv.cs +++ b/unity/Assets/core/upm/Runtime/Src/IL2Cpp/JsEnv.cs @@ -154,7 +154,7 @@ public JsEnv(ILoader loader, int debugPort = -1) PuertsIl2cpp.pesapi_ffi ffi = Marshal.PtrToStructure(apis); var scope = ffi.open_scope(nativePesapiEnv); var env = ffi.get_env_from_ref(nativePesapiEnv); - var func = ffi.create_function(env, FooImpl, IntPtr.Zero); + var func = ffi.create_function(env, FooImpl, IntPtr.Zero, IntPtr.Zero); var global = ffi.global(env); ffi.set_property(env, global, "CSharpFoo", func); ffi.close_scope(scope); diff --git a/unity/Assets/core/upm/Runtime/Src/IL2Cpp/Native/NativeAPI.cs b/unity/Assets/core/upm/Runtime/Src/IL2Cpp/Native/NativeAPI.cs index a9611ab259..9a665fa123 100644 --- a/unity/Assets/core/upm/Runtime/Src/IL2Cpp/Native/NativeAPI.cs +++ b/unity/Assets/core/upm/Runtime/Src/IL2Cpp/Native/NativeAPI.cs @@ -259,7 +259,7 @@ public static void SetLogCallback(LogCallback log) public delegate IntPtr pesapi_create_binary_func(IntPtr env, IntPtr str, UIntPtr length); public delegate IntPtr pesapi_create_array_func(IntPtr env); public delegate IntPtr pesapi_create_object_func(IntPtr env); - public delegate IntPtr pesapi_create_function_func(IntPtr env, pesapi_callback native_impl, IntPtr data); + public delegate IntPtr pesapi_create_function_func(IntPtr env, pesapi_callback native_impl, IntPtr data, IntPtr finalize); public delegate IntPtr pesapi_create_class_func(IntPtr env, IntPtr type_id); public delegate bool pesapi_get_value_bool_func(IntPtr env, IntPtr value); diff --git a/unity/native_src/Inc/CppObjectMapper.h b/unity/native_src/Inc/CppObjectMapper.h index f45ce39053..81fb79e509 100644 --- a/unity/native_src/Inc/CppObjectMapper.h +++ b/unity/native_src/Inc/CppObjectMapper.h @@ -48,6 +48,9 @@ struct PesapiCallbackData { pesapi_callback Callback; void* Data; + class FCppObjectMapper* CppObjectMapper; + v8::Global JsFunction; + pesapi_function_finalize Finalize = nullptr; }; class FCppObjectMapper final : public ICppObjectMapper @@ -64,7 +67,7 @@ class FCppObjectMapper final : public ICppObjectMapper virtual v8::Local FindOrAddCppObject( v8::Isolate* Isolate, v8::Local& Context, const void* TypeId, void* Ptr, bool PassByPointer) override; - virtual v8::MaybeLocal CreateFunction(v8::Local Context, pesapi_callback Callback, void* Data) override; + virtual v8::MaybeLocal CreateFunction(v8::Local Context, pesapi_callback Callback, void* Data, pesapi_function_finalize Finalize) override; virtual void UnBindCppObject(v8::Isolate* Isolate, JSClassDefinition* ClassDefinition, void* Ptr) override; @@ -94,6 +97,8 @@ class FCppObjectMapper final : public ICppObjectMapper #endif std::shared_ptr Ref = std::make_shared(0); + + static void CallbackDataGarbageCollected(const v8::WeakCallbackInfo& Data); }; } // namespace PUERTS_NAMESPACE \ No newline at end of file diff --git a/unity/native_src/Inc/ObjectMapper.h b/unity/native_src/Inc/ObjectMapper.h index 4cd48a43ba..9b4ab652eb 100644 --- a/unity/native_src/Inc/ObjectMapper.h +++ b/unity/native_src/Inc/ObjectMapper.h @@ -39,7 +39,7 @@ class ICppObjectMapper v8::Isolate* Isolate, v8::Local& Context, const void* TypeId, void* Ptr, bool PassByPointer) = 0; - virtual v8::MaybeLocal CreateFunction(v8::Local Context, pesapi_callback Callback, void* Data) = 0; + virtual v8::MaybeLocal CreateFunction(v8::Local Context, pesapi_callback Callback, void* Data, pesapi_function_finalize Finalize) = 0; virtual bool IsInstanceOfCppObject(v8::Isolate* Isolate, const void* TypeId, v8::Local JsObject) = 0; diff --git a/unity/native_src/Inc/pesapi.h b/unity/native_src/Inc/pesapi.h index cd421a7314..b8bc9b902d 100644 --- a/unity/native_src/Inc/pesapi.h +++ b/unity/native_src/Inc/pesapi.h @@ -127,6 +127,7 @@ typedef struct pesapi_property_descriptor__* pesapi_property_descriptor; typedef void (*pesapi_callback)(struct pesapi_ffi* apis, pesapi_callback_info info); typedef void* (*pesapi_constructor)(struct pesapi_ffi* apis, pesapi_callback_info info); typedef void (*pesapi_finalize)(struct pesapi_ffi* apis, void* ptr, void* class_data, void* env_private); +typedef void (*pesapi_function_finalize)(struct pesapi_ffi* apis, void* data, void* env_private); typedef void* (*pesapi_on_native_object_enter)(void* ptr, void* class_data, void* env_private); // userdata: return of pesapi_on_native_object_enter typedef void (*pesapi_on_native_object_exit)(void* ptr, void* class_data, void* env_private, void* userdata); @@ -152,7 +153,7 @@ typedef pesapi_value (*pesapi_create_string_utf8_func)(pesapi_env env, const cha typedef pesapi_value (*pesapi_create_binary_func)(pesapi_env env, void* str, size_t length); typedef pesapi_value (*pesapi_create_array_func)(pesapi_env env); typedef pesapi_value (*pesapi_create_object_func)(pesapi_env env); -typedef pesapi_value (*pesapi_create_function_func)(pesapi_env env, pesapi_callback native_impl, void* data); +typedef pesapi_value (*pesapi_create_function_func)(pesapi_env env, pesapi_callback native_impl, void* data, pesapi_function_finalize finalize); typedef pesapi_value (*pesapi_create_class_func)(pesapi_env env, const void* type_id); typedef bool (*pesapi_get_value_bool_func)(pesapi_env env, pesapi_value value); diff --git a/unity/native_src/Src/CppObjectMapper.cpp b/unity/native_src/Src/CppObjectMapper.cpp index 688a7798f9..6c8e9e413d 100644 --- a/unity/native_src/Src/CppObjectMapper.cpp +++ b/unity/native_src/Src/CppObjectMapper.cpp @@ -120,12 +120,36 @@ static void PesapiFunctionCallback(const v8::FunctionCallbackInfo& in FunctionInfo->Callback(&v8impl::g_pesapi_ffi, (pesapi_callback_info)(&info)); } -v8::MaybeLocal FCppObjectMapper::CreateFunction(v8::Local Context, pesapi_callback Callback, void* Data) +void FCppObjectMapper::CallbackDataGarbageCollected(const v8::WeakCallbackInfo& Data) { - auto CallbackData = new PesapiCallbackData {Callback, Data}; - FunctionDatas.push_back(CallbackData); + PesapiCallbackData* CallbackData = Data.GetParameter(); + if (CallbackData->Finalize) + { + CallbackData->Finalize(&v8impl::g_pesapi_ffi, CallbackData->Data, DataTransfer::GetIsolatePrivateData(Data.GetIsolate())); + } + CallbackData->CppObjectMapper->FunctionDatas.erase(std::remove(CallbackData->CppObjectMapper->FunctionDatas.begin(), CallbackData->CppObjectMapper->FunctionDatas.end(), + CallbackData), CallbackData->CppObjectMapper->FunctionDatas.end()); + delete CallbackData; +} + +v8::MaybeLocal FCppObjectMapper::CreateFunction(v8::Local Context, pesapi_callback Callback, void* Data, pesapi_function_finalize Finalize) +{ + auto CallbackData = new PesapiCallbackData {Callback, Data, this}; + CallbackData->Finalize = Finalize; auto V8Data = v8::External::New(Context->GetIsolate(), &CallbackData->Data); - return v8::FunctionTemplate::New(Context->GetIsolate(), PesapiFunctionCallback, V8Data)->GetFunction(Context); + auto Ret = v8::FunctionTemplate::New(Context->GetIsolate(), PesapiFunctionCallback, V8Data)->GetFunction(Context); + if (!Ret.IsEmpty()) + { + CallbackData->JsFunction.Reset(Context->GetIsolate(), Ret.ToLocalChecked()); + CallbackData->JsFunction.SetWeak( + CallbackData, CallbackDataGarbageCollected, v8::WeakCallbackType::kInternalFields); + FunctionDatas.push_back(CallbackData); + } + else + { + delete CallbackData; + } + return Ret; } bool FCppObjectMapper::IsInstanceOfCppObject(v8::Isolate* Isolate, const void* TypeId, v8::Local JsObject) @@ -444,7 +468,12 @@ void FCppObjectMapper::UnInitialize(v8::Isolate* InIsolate) } for(int i = 0;i < FunctionDatas.size(); ++i) { - delete FunctionDatas[i]; + auto CallbackData = FunctionDatas[i]; + if (CallbackData->Finalize) + { + CallbackData->Finalize(&v8impl::g_pesapi_ffi, CallbackData->Data, PData); + } + delete CallbackData; } FunctionDatas.clear(); CDataCache.clear(); diff --git a/unity/native_src/Src/PesapiV8Impl.cpp b/unity/native_src/Src/PesapiV8Impl.cpp index 4029436324..fdef18e4b7 100644 --- a/unity/native_src/Src/PesapiV8Impl.cpp +++ b/unity/native_src/Src/PesapiV8Impl.cpp @@ -163,10 +163,10 @@ pesapi_value pesapi_create_object(pesapi_env env) return v8impl::PesapiValueFromV8LocalValue(v8::Object::New(context->GetIsolate())); } -pesapi_value pesapi_create_function(pesapi_env env, pesapi_callback native_impl, void* data) +pesapi_value pesapi_create_function(pesapi_env env, pesapi_callback native_impl, void* data, pesapi_function_finalize finalize) { auto context = v8impl::V8LocalContextFromPesapiEnv(env); - auto func = puerts::DataTransfer::IsolateData(context->GetIsolate())->CreateFunction(context, native_impl, data); + auto func = puerts::DataTransfer::IsolateData(context->GetIsolate())->CreateFunction(context, native_impl, data, finalize); if (func.IsEmpty()) return nullptr; return v8impl::PesapiValueFromV8LocalValue(func.ToLocalChecked());