diff --git a/unity/native/papi-v8/source/PesapiV8Impl.cpp b/unity/native/papi-v8/source/PesapiV8Impl.cpp index c94d6ca056..1f588b27a0 100644 --- a/unity/native/papi-v8/source/PesapiV8Impl.cpp +++ b/unity/native/papi-v8/source/PesapiV8Impl.cpp @@ -692,6 +692,11 @@ void pesapi_release_value_ref(pesapi_value_ref value_ref) { if (!value_ref->env_life_cycle_tracker.expired()) { + // v8::Persistent uses NonCopyablePersistentTraits (kResetInDestructor == false), + // so ~pesapi_value_ref__() does NOT release the strong V8 global root. Without an + // explicit Reset(), a JS function marshaled into a C# delegate (this path never calls + // pesapi_set_ref_weak) and everything its closure captures leak for the isolate's lifetime. + value_ref->value_persistent.Reset(); value_ref->~pesapi_value_ref__(); } ::operator delete(static_cast(value_ref));