15bebb993Sopenharmony_ci/*
25bebb993Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
35bebb993Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
45bebb993Sopenharmony_ci * you may not use this file except in compliance with the License.
55bebb993Sopenharmony_ci * You may obtain a copy of the License at
65bebb993Sopenharmony_ci *
75bebb993Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
85bebb993Sopenharmony_ci *
95bebb993Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
105bebb993Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
115bebb993Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125bebb993Sopenharmony_ci * See the License for the specific language governing permissions and
135bebb993Sopenharmony_ci * limitations under the License.
145bebb993Sopenharmony_ci */
155bebb993Sopenharmony_ci
165bebb993Sopenharmony_ci#include "n_class.h"
175bebb993Sopenharmony_ci
185bebb993Sopenharmony_ci#include "filemgmt_libhilog.h"
195bebb993Sopenharmony_ci
205bebb993Sopenharmony_cinamespace OHOS {
215bebb993Sopenharmony_cinamespace FileManagement {
225bebb993Sopenharmony_cinamespace LibN {
235bebb993Sopenharmony_ciusing namespace std;
245bebb993Sopenharmony_ciNClass &NClass::GetInstance()
255bebb993Sopenharmony_ci{
265bebb993Sopenharmony_ci    static thread_local NClass nClass;
275bebb993Sopenharmony_ci    return nClass;
285bebb993Sopenharmony_ci}
295bebb993Sopenharmony_ci
305bebb993Sopenharmony_cituple<bool, napi_value> NClass::DefineClass(napi_env env,
315bebb993Sopenharmony_ci                                            string className,
325bebb993Sopenharmony_ci                                            napi_callback constructor,
335bebb993Sopenharmony_ci                                            vector<napi_property_descriptor> &&properties)
345bebb993Sopenharmony_ci{
355bebb993Sopenharmony_ci    napi_value classVal = nullptr;
365bebb993Sopenharmony_ci    napi_status stat = napi_define_class(env, className.c_str(), className.length(), constructor, nullptr,
375bebb993Sopenharmony_ci                                         properties.size(), properties.data(), &classVal);
385bebb993Sopenharmony_ci    if (stat != napi_ok) {
395bebb993Sopenharmony_ci        HILOGE("INNER BUG. Cannot define class %{public}s because of %{public}d", className.c_str(), stat);
405bebb993Sopenharmony_ci    }
415bebb993Sopenharmony_ci
425bebb993Sopenharmony_ci    return {stat == napi_ok, classVal};
435bebb993Sopenharmony_ci}
445bebb993Sopenharmony_ci
455bebb993Sopenharmony_cibool NClass::SaveClass(napi_env env, string className, napi_value exClass)
465bebb993Sopenharmony_ci{
475bebb993Sopenharmony_ci    NClass &nClass = NClass::GetInstance();
485bebb993Sopenharmony_ci    lock_guard<std::mutex>(nClass.exClassMapLock);
495bebb993Sopenharmony_ci
505bebb993Sopenharmony_ci    if (nClass.exClassMap.find(className) != nClass.exClassMap.end()) {
515bebb993Sopenharmony_ci        return true;
525bebb993Sopenharmony_ci    }
535bebb993Sopenharmony_ci
545bebb993Sopenharmony_ci    napi_ref constructor;
555bebb993Sopenharmony_ci    napi_status res = napi_create_reference(env, exClass, 1, &constructor);
565bebb993Sopenharmony_ci    if (res == napi_ok) {
575bebb993Sopenharmony_ci        nClass.exClassMap.insert({className, constructor});
585bebb993Sopenharmony_ci    } else {
595bebb993Sopenharmony_ci        HILOGE("INNER BUG. Cannot ref class constructor %{public}s because of %{public}d", className.c_str(), res);
605bebb993Sopenharmony_ci    }
615bebb993Sopenharmony_ci
625bebb993Sopenharmony_ci    if (!nClass.addCleanHook) {
635bebb993Sopenharmony_ci        napi_status status = napi_add_env_cleanup_hook(env, CleanClass, env);
645bebb993Sopenharmony_ci        if (status != napi_ok) {
655bebb993Sopenharmony_ci            HILOGE("INNER BUG. Cleanup_hook registation has failed because of %{public}d", res);
665bebb993Sopenharmony_ci        } else {
675bebb993Sopenharmony_ci            nClass.addCleanHook = true;
685bebb993Sopenharmony_ci        }
695bebb993Sopenharmony_ci    }
705bebb993Sopenharmony_ci    return res == napi_ok;
715bebb993Sopenharmony_ci}
725bebb993Sopenharmony_ci
735bebb993Sopenharmony_civoid NClass::CleanClass(void *arg)
745bebb993Sopenharmony_ci{
755bebb993Sopenharmony_ci    napi_env env = reinterpret_cast<napi_env>(arg);
765bebb993Sopenharmony_ci    NClass &nClass = NClass::GetInstance();
775bebb993Sopenharmony_ci    lock_guard<std::mutex>(nClass.exClassMapLock);
785bebb993Sopenharmony_ci
795bebb993Sopenharmony_ci    napi_status res;
805bebb993Sopenharmony_ci    for (auto it = nClass.exClassMap.begin(); it != nClass.exClassMap.end(); ++it) {
815bebb993Sopenharmony_ci        res = napi_delete_reference(env, it->second);
825bebb993Sopenharmony_ci        if (res != napi_ok) {
835bebb993Sopenharmony_ci            HILOGE("Cannot del ref class constructor %{public}s because of %{public}d", it->first.c_str(), res);
845bebb993Sopenharmony_ci        }
855bebb993Sopenharmony_ci    }
865bebb993Sopenharmony_ci    nClass.exClassMap.clear();
875bebb993Sopenharmony_ci}
885bebb993Sopenharmony_ci
895bebb993Sopenharmony_cinapi_value NClass::InstantiateClass(napi_env env, const string& className, const vector<napi_value>& args)
905bebb993Sopenharmony_ci{
915bebb993Sopenharmony_ci    NClass &nClass = NClass::GetInstance();
925bebb993Sopenharmony_ci    lock_guard<std::mutex>(nClass.exClassMapLock);
935bebb993Sopenharmony_ci
945bebb993Sopenharmony_ci    auto it = nClass.exClassMap.find(className);
955bebb993Sopenharmony_ci    if (it == nClass.exClassMap.end()) {
965bebb993Sopenharmony_ci        HILOGE("Class %{public}s hasn't been saved yet", className.c_str());
975bebb993Sopenharmony_ci        return nullptr;
985bebb993Sopenharmony_ci    }
995bebb993Sopenharmony_ci
1005bebb993Sopenharmony_ci    napi_value cons = nullptr;
1015bebb993Sopenharmony_ci    napi_status status = napi_get_reference_value(env, it->second, &cons);
1025bebb993Sopenharmony_ci    if (status != napi_ok) {
1035bebb993Sopenharmony_ci        HILOGE("INNER BUG. Cannot deref class %{public}s because of %{public}d", className.c_str(), status);
1045bebb993Sopenharmony_ci        return nullptr;
1055bebb993Sopenharmony_ci    }
1065bebb993Sopenharmony_ci
1075bebb993Sopenharmony_ci    napi_value instance = nullptr;
1085bebb993Sopenharmony_ci    status = napi_new_instance(env, cons, args.size(), args.data(), &instance);
1095bebb993Sopenharmony_ci    if (status != napi_ok) {
1105bebb993Sopenharmony_ci        HILOGE("INNER BUG. Cannot instantiate the class %{public}s because of %{public}d", className.c_str(), status);
1115bebb993Sopenharmony_ci        return nullptr;
1125bebb993Sopenharmony_ci    }
1135bebb993Sopenharmony_ci
1145bebb993Sopenharmony_ci    return instance;
1155bebb993Sopenharmony_ci}
1165bebb993Sopenharmony_ci} // namespace LibN
1175bebb993Sopenharmony_ci} // namespace FileManagement
1185bebb993Sopenharmony_ci} // namespace OHOS
119