diff --git a/frameworks/js/napi/session/include/napi_avsession_callback.h b/frameworks/js/napi/session/include/napi_avsession_callback.h index 7594bcae41fee757e16e85ec8591cd34e0b18b32..c3ea9777913ebf16bbc2aad1d19fef81a2549fc1 100644 --- a/frameworks/js/napi/session/include/napi_avsession_callback.h +++ b/frameworks/js/napi/session/include/napi_avsession_callback.h @@ -90,6 +90,7 @@ private: std::mutex lock_; std::shared_ptr asyncCallback_; std::list callbacks_[EVENT_TYPE_MAX] {}; + std::shared_ptr isValid_; }; } // namespace OHOS::AVSession #endif // OHOS_NAPI_AVSESSION_CALLBACK_H diff --git a/frameworks/js/napi/session/src/napi_async_callback.cpp b/frameworks/js/napi/session/src/napi_async_callback.cpp index 8ae3834d7a19a9afdf52ff2476aca9c7547d9332..79b5ce1b67b13ce6ea390ce665def40d7a6155e5 100644 --- a/frameworks/js/napi/session/src/napi_async_callback.cpp +++ b/frameworks/js/napi/session/src/napi_async_callback.cpp @@ -123,14 +123,14 @@ void NapiAsyncCallback::AfterWorkCallbackWithFunc(uv_work_t* work, int aStatus) } SLOGI("queue uv_after_work_cb"); + CHECK_RETURN_VOID(*context->isValid, "AfterWorkCallbackWithFunc failed for context is invalid."); napi_value global {}; napi_get_global(context->env, &global); napi_value function {}; - CHECK_RETURN_VOID(*context->isValid, "callback when callback is invalid"); - SLOGI("callback with ref %{public}p, %{public}p", &(context->method), *(&(context->method))); - CHECK_RETURN_VOID(context->checkCallbackValid(), "callback but func already lost"); + CHECK_RETURN_VOID(context->checkCallbackValid(), "Get func reference failed for func has been deleted."); napi_get_reference_value(context->env, context->method, &function); napi_value result; + CHECK_RETURN_VOID(context->checkCallbackValid(), "Call func failed for func has been deleted."); napi_status status = napi_call_function(context->env, global, function, argc, argv, &result); if (status != napi_ok) { SLOGE("call function failed status=%{public}d.", status); diff --git a/frameworks/js/napi/session/src/napi_avsession_callback.cpp b/frameworks/js/napi/session/src/napi_avsession_callback.cpp index 0ddaf0a820a01ee9935072861850559699e53cc6..ada0e566b68f1ddd7f0ab4c26bdb817f3d3634b6 100644 --- a/frameworks/js/napi/session/src/napi_avsession_callback.cpp +++ b/frameworks/js/napi/session/src/napi_avsession_callback.cpp @@ -21,12 +21,14 @@ namespace OHOS::AVSession { NapiAVSessionCallback::NapiAVSessionCallback() { - SLOGI("construct"); + SLOGI("construct NapiAVSessionCallback"); + isValid_ = std::make_shared(true); } NapiAVSessionCallback::~NapiAVSessionCallback() { - SLOGI("destroy"); + SLOGI("destroy NapiAVSessionCallback"); + *isValid_ = false; } void NapiAVSessionCallback::HandleEvent(int32_t event) @@ -37,7 +39,20 @@ void NapiAVSessionCallback::HandleEvent(int32_t event) return; } for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) { - asyncCallback_->Call(*ref); + asyncCallback_->CallWithFunc(*ref, isValid_, + [this, ref, event]() { + std::lock_guard lockGuard(lock_); + if (callbacks_[event].empty()) { + SLOGI("checkCallbackValid with empty list for event %{public}d", event); + return false; + } + bool hasFunc = false; + for (auto it = callbacks_[event].begin(); it != callbacks_[event].end(); ++it) { + hasFunc = (ref == it ? true : hasFunc); + } + SLOGI("checkCallbackValid return hasFunc %{public}d, %{public}d", hasFunc, event); + return hasFunc; + }); } } @@ -50,10 +65,24 @@ void NapiAVSessionCallback::HandleEvent(int32_t event, const T& param) return; } for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) { - asyncCallback_->Call(*ref, [param](napi_env env, int& argc, napi_value* argv) { - argc = NapiUtils::ARGC_ONE; - NapiUtils::SetValue(env, param, *argv); - }); + asyncCallback_->CallWithFunc(*ref, isValid_, + [this, ref, event]() { + std::lock_guard lockGuard(lock_); + if (callbacks_[event].empty()) { + SLOGI("checkCallbackValid with empty list for event %{public}d", event); + return false; + } + bool hasFunc = false; + for (auto it = callbacks_[event].begin(); it != callbacks_[event].end(); ++it) { + hasFunc = (ref == it ? true : hasFunc); + } + SLOGI("checkCallbackValid return hasFunc %{public}d, %{public}d", hasFunc, event); + return hasFunc; + }, + [param](napi_env env, int& argc, napi_value* argv) { + argc = NapiUtils::ARGC_ONE; + NapiUtils::SetValue(env, param, *argv); + }); } } @@ -66,13 +95,27 @@ void NapiAVSessionCallback::HandleEvent(int32_t event, const std::string& firstP return; } for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) { - asyncCallback_->Call(*ref, [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) { - argc = NapiUtils::ARGC_TWO; - auto status = NapiUtils::SetValue(env, firstParam, argv[0]); - CHECK_RETURN_VOID(status == napi_ok, "AVSessionCallback set first param invalid"); - status = NapiUtils::SetValue(env, secondParam, argv[1]); - CHECK_RETURN_VOID(status == napi_ok, "AVSessionCallback set second param invalid"); - }); + asyncCallback_->CallWithFunc(*ref, isValid_, + [this, ref, event]() { + std::lock_guard lockGuard(lock_); + if (callbacks_[event].empty()) { + SLOGI("checkCallbackValid with empty list for event %{public}d", event); + return false; + } + bool hasFunc = false; + for (auto it = callbacks_[event].begin(); it != callbacks_[event].end(); ++it) { + hasFunc = (ref == it ? true : hasFunc); + } + SLOGI("checkCallbackValid return hasFunc %{public}d, %{public}d", hasFunc, event); + return hasFunc; + }, + [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) { + argc = NapiUtils::ARGC_TWO; + auto status = NapiUtils::SetValue(env, firstParam, argv[0]); + CHECK_RETURN_VOID(status == napi_ok, "AVSessionCallback set first param invalid"); + status = NapiUtils::SetValue(env, secondParam, argv[1]); + CHECK_RETURN_VOID(status == napi_ok, "AVSessionCallback set second param invalid"); + }); } } @@ -85,13 +128,27 @@ void NapiAVSessionCallback::HandleEvent(int32_t event, const int32_t firstParam, return; } for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) { - asyncCallback_->Call(*ref, [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) { - argc = NapiUtils::ARGC_TWO; - auto status = NapiUtils::SetValue(env, firstParam, argv[0]); - CHECK_RETURN_VOID(status == napi_ok, "AVSessionCallback set first param invalid"); - status = NapiUtils::SetValue(env, secondParam, argv[1]); - CHECK_RETURN_VOID(status == napi_ok, "AVSessionCallback set second param invalid"); - }); + asyncCallback_->CallWithFunc(*ref, isValid_, + [this, ref, event]() { + std::lock_guard lockGuard(lock_); + if (callbacks_[event].empty()) { + SLOGI("checkCallbackValid with empty list for event %{public}d", event); + return false; + } + bool hasFunc = false; + for (auto it = callbacks_[event].begin(); it != callbacks_[event].end(); ++it) { + hasFunc = (ref == it ? true : hasFunc); + } + SLOGI("checkCallbackValid return hasFunc %{public}d, %{public}d", hasFunc, event); + return hasFunc; + }, + [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) { + argc = NapiUtils::ARGC_TWO; + auto status = NapiUtils::SetValue(env, firstParam, argv[0]); + CHECK_RETURN_VOID(status == napi_ok, "AVSessionCallback set first param invalid"); + status = NapiUtils::SetValue(env, secondParam, argv[1]); + CHECK_RETURN_VOID(status == napi_ok, "AVSessionCallback set second param invalid"); + }); } }