1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_class.h"
17 
18 #include <iostream>
19 #include <sstream>
20 
21 namespace OHOS {
22 namespace AppExecFwk {
23 namespace LIBZIP {
24 using namespace std;
GetInstance()25 NapiClass &NapiClass::GetInstance()
26 {
27     static thread_local NapiClass nClass;
28     return nClass;
29 }
30 
DefineClass(napi_env env,const string & className,napi_callback constructor,vector<napi_property_descriptor> && properties)31 tuple<bool, napi_value> NapiClass::DefineClass(
32     napi_env env, const string &className, napi_callback constructor, vector<napi_property_descriptor> &&properties)
33 {
34     napi_value classVal = nullptr;
35     napi_status stat = napi_define_class(env,
36         className.c_str(),
37         className.length(),
38         constructor,
39         nullptr,
40         properties.size(),
41         properties.data(),
42         &classVal);
43     if (stat != napi_ok) {
44         APP_LOGE("INNER BUG. Cannot define class %{public}s because of %{public}d", className.c_str(), stat);
45     }
46     return {stat == napi_ok, classVal};
47 }
48 
SaveClass(napi_env env,const string & className,napi_value exClass)49 bool NapiClass::SaveClass(napi_env env, const string &className, napi_value exClass)
50 {
51     NapiClass &nClass = NapiClass::GetInstance();
52     lock_guard(nClass.exClassMapLock);
53 
54     if (nClass.exClassMap.find(className) != nClass.exClassMap.end()) {
55         return true;
56     }
57 
58     napi_ref constructor;
59     napi_status res = napi_create_reference(env, exClass, 1, &constructor);
60     if (res == napi_ok) {
61         nClass.exClassMap.insert({className, constructor});
62     } else {
63         APP_LOGE("INNER BUG. Cannot ref class constructor %{public}s because of %{public}d", className.c_str(), res);
64     }
65 
66     return res == napi_ok;
67 }
68 
InstantiateClass(napi_env env,const string & className,const vector<napi_value> & args)69 napi_value NapiClass::InstantiateClass(napi_env env, const string &className, const vector<napi_value> &args)
70 {
71     NapiClass &nClass = NapiClass::GetInstance();
72     lock_guard(nClass.exClassMapLock);
73     auto it = nClass.exClassMap.find(className);
74     if (it == nClass.exClassMap.end()) {
75         APP_LOGE("Class %{public}s hasn't been saved yet", className.c_str());
76         return nullptr;
77     }
78 
79     napi_value cons = nullptr;
80     napi_status status = napi_get_reference_value(env, it->second, &cons);
81     if (status != napi_ok) {
82         APP_LOGE("INNER BUG. Cannot deref class %{public}s because of %{public}d", className.c_str(), status);
83         return nullptr;
84     }
85 
86     napi_value instance = nullptr;
87     status = napi_new_instance(env, cons, args.size(), args.data(), &instance);
88     if (status != napi_ok) {
89         APP_LOGE("INNER BUG. Cannot instantiate the class %{public}s because of %{public}d", className.c_str(), status);
90         return nullptr;
91     }
92 
93     return instance;
94 }
95 }  // namespace LIBZIP
96 }  // namespace AppExecFwk
97 }  // namespace OHOS