• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #include "napi_util.h"
16 
17 #include <unordered_map>
18 
19 #include "hiappevent_base.h"
20 #include "hilog/log.h"
21 
22 namespace OHOS {
23 namespace HiviewDFX {
24 namespace NapiUtil {
25 namespace {
26 constexpr HiLogLabel LABEL = { LOG_CORE, HIAPPEVENT_DOMAIN, "HiAppEvent_NapiUtil" };
27 const std::string DOMAIN_PROPERTY = "domain";
28 const std::string NAME_PROPERTY = "name";
29 const std::string EVENT_TYPE_PROPERTY = "eventType";
30 const std::string PARAM_PROPERTY = "params";
31 const std::string EVENT_INFOS_PROPERTY = "appEventInfos";
32 }
33 
IsNull(const napi_env env,const napi_value value)34 bool IsNull(const napi_env env, const napi_value value)
35 {
36     return GetType(env, value) == napi_null;
37 }
38 
IsBoolean(const napi_env env,const napi_value value)39 bool IsBoolean(const napi_env env, const napi_value value)
40 {
41     return GetType(env, value) == napi_boolean;
42 }
43 
IsNumber(const napi_env env,const napi_value value)44 bool IsNumber(const napi_env env, const napi_value value)
45 {
46     return GetType(env, value) == napi_number;
47 }
48 
IsString(const napi_env env,const napi_value value)49 bool IsString(const napi_env env, const napi_value value)
50 {
51     return GetType(env, value) == napi_string;
52 }
53 
IsObject(const napi_env env,const napi_value value)54 bool IsObject(const napi_env env, const napi_value value)
55 {
56     return GetType(env, value) == napi_object;
57 }
58 
IsFunction(const napi_env env,const napi_value value)59 bool IsFunction(const napi_env env, const napi_value value)
60 {
61     return GetType(env, value) == napi_function;
62 }
63 
IsArray(const napi_env env,const napi_value value)64 bool IsArray(const napi_env env, const napi_value value)
65 {
66     bool result = false;
67     if (napi_is_array(env, value, &result) != napi_ok) {
68         HiLog::Error(LABEL, "failed to check array type");
69         return false;
70     }
71     return result;
72 }
73 
IsArrayType(const napi_env env,const napi_value value,napi_valuetype type)74 bool IsArrayType(const napi_env env, const napi_value value, napi_valuetype type)
75 {
76     if (!IsArray(env, value)) {
77         return false;
78     }
79     if (GetArrayLength(env, value) == 0) {
80         return true;
81     }
82     return GetArrayType(env, value) == type;
83 }
84 
GetType(const napi_env env,const napi_value value)85 napi_valuetype GetType(const napi_env env, const napi_value value)
86 {
87     napi_valuetype type;
88     if (napi_typeof(env, value, &type) != napi_ok) {
89         HiLog::Error(LABEL, "failed to get value type");
90         return napi_undefined;
91     }
92     return type;
93 }
94 
GetArrayType(const napi_env env,const napi_value arr)95 napi_valuetype GetArrayType(const napi_env env, const napi_value arr)
96 {
97     uint32_t result = 0;
98     if (napi_get_array_length(env, arr, &result) != napi_ok) {
99         HiLog::Error(LABEL, "failed to get the length of array");
100         return napi_undefined;
101     }
102 
103     napi_valuetype type = napi_null; // note: empty array returns null type
104     for (size_t i = 0; i < result; ++i) {
105         napi_value element = nullptr;
106         if (napi_get_element(env, arr, i, &element) != napi_ok) {
107             HiLog::Error(LABEL, "failed to get the element of array");
108             return napi_undefined;
109         }
110         if (i == 0) {
111             type = GetType(env, element);
112             continue;
113         }
114         if (type != GetType(env, element)) {
115             HiLog::Error(LABEL, "array has different element types");
116             return napi_undefined;
117         }
118     }
119     return type;
120 }
121 
GetArrayLength(const napi_env env,const napi_value arr)122 uint32_t GetArrayLength(const napi_env env, const napi_value arr)
123 {
124     uint32_t result = 0;
125     if (napi_get_array_length(env, arr, &result) != napi_ok) {
126         HiLog::Error(LABEL, "failed to get the length of array");
127         return 0;
128     }
129     return result;
130 }
131 
GetElement(const napi_env env,const napi_value arr,uint32_t index)132 napi_value GetElement(const napi_env env, const napi_value arr, uint32_t index)
133 {
134     napi_value element = nullptr;
135     if (napi_get_element(env, arr, index, &element) != napi_ok) {
136         HiLog::Error(LABEL, "failed to get the element of array.");
137         return nullptr;
138     }
139     return element;
140 }
141 
GetBoolean(const napi_env env,const napi_value value)142 bool GetBoolean(const napi_env env, const napi_value value)
143 {
144     bool bValue = false;
145     if (napi_get_value_bool(env, value, &bValue) != napi_ok) {
146         HiLog::Error(LABEL, "failed to get bool value");
147         return false;
148     }
149     return bValue;
150 }
151 
GetBooleans(const napi_env env,const napi_value arr,std::vector<bool> & bools)152 void GetBooleans(const napi_env env, const napi_value arr, std::vector<bool>& bools)
153 {
154     uint32_t len = GetArrayLength(env, arr);
155     for (size_t i = 0; i < len; ++i) {
156         napi_value element = GetElement(env, arr, i);
157         if (element == nullptr) {
158             continue;
159         }
160         bools.push_back(GetBoolean(env, element));
161     }
162 }
163 
GetInt32(const napi_env env,const napi_value value)164 int32_t GetInt32(const napi_env env, const napi_value value)
165 {
166     int32_t iValue = 0;
167     if (napi_get_value_int32(env, value, &iValue) != napi_ok) {
168         HiLog::Error(LABEL, "failed to get int32 value");
169         return 0;
170     }
171     return iValue;
172 }
173 
GetInt64(const napi_env env,const napi_value value)174 int64_t GetInt64(const napi_env env, const napi_value value)
175 {
176     int64_t iValue = 0;
177     if (napi_get_value_int64(env, value, &iValue) != napi_ok) {
178         HiLog::Error(LABEL, "failed to get int64 value");
179         return 0;
180     }
181     return iValue;
182 }
183 
GetInt32s(const napi_env env,const napi_value arr,std::vector<int32_t> & ints)184 void GetInt32s(const napi_env env, const napi_value arr, std::vector<int32_t>& ints)
185 {
186     uint32_t len = GetArrayLength(env, arr);
187     for (size_t i = 0; i < len; ++i) {
188         napi_value element = GetElement(env, arr, i);
189         if (element == nullptr) {
190             continue;
191         }
192         ints.push_back(GetInt32(env, element));
193     }
194 }
195 
GetDouble(const napi_env env,const napi_value value)196 double GetDouble(const napi_env env, const napi_value value)
197 {
198     double dValue = 0;
199     if (napi_get_value_double(env, value, &dValue) != napi_ok) {
200         HiLog::Error(LABEL, "failed to get double value");
201         return 0;
202     }
203     return dValue;
204 }
205 
GetDoubles(const napi_env env,const napi_value arr,std::vector<double> & doubles)206 void GetDoubles(const napi_env env, const napi_value arr, std::vector<double>& doubles)
207 {
208     uint32_t len = GetArrayLength(env, arr);
209     for (size_t i = 0; i < len; ++i) {
210         napi_value element = GetElement(env, arr, i);
211         if (element == nullptr) {
212             continue;
213         }
214         doubles.push_back(GetDouble(env, element));
215     }
216 }
217 
GetString(const napi_env env,const napi_value value)218 std::string GetString(const napi_env env, const napi_value value)
219 {
220     size_t bufsize = 0;
221     if (napi_get_value_string_utf8(env, value, nullptr, 0, &bufsize) != napi_ok) {
222         HiLog::Error(LABEL, "failed to get string length");
223         return "";
224     }
225     std::vector<char> charVec(bufsize + 1); // 1 for '\0'
226     if (napi_get_value_string_utf8(env, value, charVec.data(), bufsize + 1, &bufsize) != napi_ok) {
227         HiLog::Error(LABEL, "failed to get string value");
228         return "";
229     }
230     return charVec.data();
231 }
232 
GetStrings(const napi_env env,const napi_value arr,std::vector<std::string> & strs)233 void GetStrings(const napi_env env, const napi_value arr, std::vector<std::string>& strs)
234 {
235     uint32_t len = GetArrayLength(env, arr);
236     for (size_t i = 0; i < len; ++i) {
237         napi_value element = GetElement(env, arr, i);
238         if (element == nullptr) {
239             continue;
240         }
241         strs.push_back(GetString(env, element));
242     }
243 }
244 
GetStringsToSet(const napi_env env,const napi_value arr,std::unordered_set<std::string> & strs)245 void GetStringsToSet(const napi_env env, const napi_value arr, std::unordered_set<std::string>& strs)
246 {
247     uint32_t len = GetArrayLength(env, arr);
248     for (size_t i = 0; i < len; ++i) {
249         napi_value element = GetElement(env, arr, i);
250         if (element == nullptr) {
251             continue;
252         }
253         strs.insert(GetString(env, element));
254     }
255 }
256 
HasProperty(const napi_env env,const napi_value object,const std::string & name)257 bool HasProperty(const napi_env env, const napi_value object, const std::string& name)
258 {
259     bool result = false;
260     if (napi_has_named_property(env, object, name.c_str(), &result) != napi_ok) {
261         HiLog::Error(LABEL, "failed to check whether the object has the named property");
262         return false;
263     }
264     return result;
265 }
266 
GetProperty(const napi_env env,const napi_value object,const std::string & name)267 napi_value GetProperty(const napi_env env, const napi_value object, const std::string& name)
268 {
269     if (!HasProperty(env, object, name)) {
270         return nullptr;
271     }
272     napi_value value = nullptr;
273     if (napi_get_named_property(env, object, name.c_str(), &value) != napi_ok) {
274         HiLog::Error(LABEL, "failed to get property=%{public}s from object", name.c_str());
275         return nullptr;
276     }
277     return value;
278 }
279 
GetPropertyNames(const napi_env env,const napi_value object,std::vector<std::string> & names)280 void GetPropertyNames(const napi_env env, const napi_value object, std::vector<std::string>& names)
281 {
282     napi_value propertyNames = nullptr;
283     if (napi_get_property_names(env, object, &propertyNames) != napi_ok) {
284         HiLog::Error(LABEL, "failed to get property names.");
285         return;
286     }
287     uint32_t len = 0;
288     if (napi_get_array_length(env, propertyNames, &len) != napi_ok) {
289         HiLog::Error(LABEL, "failed to get array length");
290         return;
291     }
292     for (uint32_t i = 0; i < len; ++i) {
293         napi_value element = nullptr;
294         if (napi_get_element(env, propertyNames, i, &element) != napi_ok) {
295             HiLog::Error(LABEL, "failed to get the element of array");
296             continue;
297         }
298         names.push_back(GetString(env, element));
299     }
300 }
301 
GetReferenceValue(const napi_env env,const napi_ref funcRef)302 napi_value GetReferenceValue(const napi_env env, const napi_ref funcRef)
303 {
304     napi_value refValue = nullptr;
305     if (napi_get_reference_value(env, funcRef, &refValue) != napi_ok) {
306         HiLog::Error(LABEL, "failed to get reference value");
307         return nullptr;
308     }
309     return refValue;
310 }
311 
GetCbInfo(const napi_env env,napi_callback_info info,napi_value argv[],size_t argc)312 size_t GetCbInfo(const napi_env env, napi_callback_info info, napi_value argv[], size_t argc)
313 {
314     size_t paramNum = argc;
315     if (napi_get_cb_info(env, info, &paramNum, argv, nullptr, nullptr) != napi_ok) {
316         HiLog::Error(LABEL, "failed to get callback info");
317         return 0;
318     }
319     return paramNum;
320 }
321 
CreateReference(const napi_env env,const napi_value func)322 napi_ref CreateReference(const napi_env env, const napi_value func)
323 {
324     napi_ref ref = nullptr;
325     if (napi_create_reference(env, func, 1, &ref) != napi_ok) { // 1 means initial reference count
326         HiLog::Error(LABEL, "failed to create reference");
327         return nullptr;
328     }
329     return ref;
330 }
331 
CreateNull(const napi_env env)332 napi_value CreateNull(const napi_env env)
333 {
334     napi_value nullValue = nullptr;
335     if (napi_get_null(env, &nullValue) != napi_ok) {
336         HiLog::Error(LABEL, "failed to create null");
337         return nullptr;
338     }
339     return nullValue;
340 }
341 
CreateUndefined(const napi_env env)342 napi_value CreateUndefined(const napi_env env)
343 {
344     napi_value undefinedValue = nullptr;
345     if (napi_get_undefined(env, &undefinedValue) != napi_ok) {
346         HiLog::Error(LABEL, "failed to create undefined");
347         return nullptr;
348     }
349     return undefinedValue;
350 }
351 
CreateBoolean(const napi_env env,bool bValue)352 napi_value CreateBoolean(const napi_env env, bool bValue)
353 {
354     napi_value boolValue = nullptr;
355     if (napi_get_boolean(env, bValue, &boolValue) != napi_ok) {
356         HiLog::Error(LABEL, "failed to create boolean");
357         return nullptr;
358     }
359     return boolValue;
360 }
361 
CreateInt32(const napi_env env,int32_t num)362 napi_value CreateInt32(const napi_env env, int32_t num)
363 {
364     napi_value intValue = nullptr;
365     if (napi_create_int32(env, num, &intValue) != napi_ok) {
366         HiLog::Error(LABEL, "failed to create int32");
367         return nullptr;
368     }
369     return intValue;
370 }
371 
CreateInt64(const napi_env env,int64_t num)372 napi_value CreateInt64(const napi_env env, int64_t num)
373 {
374     napi_value intValue = nullptr;
375     if (napi_create_int64(env, num, &intValue) != napi_ok) {
376         HiLog::Error(LABEL, "failed to create int64");
377         return nullptr;
378     }
379     return intValue;
380 }
381 
CreateString(const napi_env env,const std::string & str)382 napi_value CreateString(const napi_env env, const std::string& str)
383 {
384     napi_value strValue = nullptr;
385     if (napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &strValue) != napi_ok) {
386         HiLog::Error(LABEL, "failed to create string");
387         return nullptr;
388     }
389     return strValue;
390 }
391 
CreateStrings(const napi_env env,const std::vector<std::string> & strs)392 napi_value CreateStrings(const napi_env env, const std::vector<std::string>& strs)
393 {
394     napi_value arr = CreateArray(env);
395     for (size_t i = 0; i < strs.size(); ++i) {
396         SetElement(env, arr, i, CreateString(env, strs[i]));
397     }
398     return arr;
399 }
400 
CreateObject(const napi_env env)401 napi_value CreateObject(const napi_env env)
402 {
403     napi_value obj = nullptr;
404     if (napi_create_object(env, &obj) != napi_ok) {
405         HiLog::Error(LABEL, "failed to create object");
406         return nullptr;
407     }
408     return obj;
409 }
410 
CreateObject(const napi_env env,const std::string & key,const napi_value value)411 napi_value CreateObject(const napi_env env, const std::string& key, const napi_value value)
412 {
413     napi_value obj = nullptr;
414     if (napi_create_object(env, &obj) != napi_ok) {
415         HiLog::Error(LABEL, "failed to create object");
416         return nullptr;
417     }
418     if (napi_set_named_property(env, obj, key.c_str(), value) != napi_ok) {
419         HiLog::Error(LABEL, "failed to set property");
420         return nullptr;
421     }
422     return obj;
423 }
424 
CreateArray(const napi_env env)425 napi_value CreateArray(const napi_env env)
426 {
427     napi_value arr = nullptr;
428     if (napi_create_array(env, &arr) != napi_ok) {
429         HiLog::Error(LABEL, "failed to create array");
430         return nullptr;
431     }
432     return arr;
433 }
434 
CreateDouble(const napi_env env,double dValue)435 napi_value CreateDouble(const napi_env env, double dValue)
436 {
437     napi_value doubleValue = nullptr;
438     if (napi_create_double(env, dValue, &doubleValue) != napi_ok) {
439         HiLog::Error(LABEL, "failed to create double");
440         return nullptr;
441     }
442     return doubleValue;
443 }
444 
SetElement(const napi_env env,const napi_value obj,uint32_t index,const napi_value value)445 void SetElement(const napi_env env, const napi_value obj, uint32_t index, const napi_value value)
446 {
447     if (napi_set_element(env, obj, index, value) != napi_ok) {
448         HiLog::Error(LABEL, "failed to set element");
449     }
450 }
451 
SetNamedProperty(const napi_env env,const napi_value obj,const std::string & key,const napi_value value)452 void SetNamedProperty(const napi_env env, const napi_value obj, const std::string& key, const napi_value value)
453 {
454     if (napi_set_named_property(env, obj, key.c_str(), value) != napi_ok) {
455         HiLog::Error(LABEL, "failed to set property");
456     }
457 }
458 
ConvertToString(const napi_env env,const napi_value value)459 std::string ConvertToString(const napi_env env, const napi_value value)
460 {
461     napi_valuetype type = GetType(env, value);
462     if (type == napi_undefined) {
463         return "";
464     }
465 
466     std::string result = "";
467     switch (type) {
468         case napi_boolean:
469             result = GetBoolean(env, value) ? "true" : "false";
470             break;
471         case napi_number:
472             result = std::to_string(GetDouble(env, value));
473             break;
474         case napi_string:
475             result = GetString(env, value);
476             break;
477         default:
478             break;
479     }
480     return result;
481 }
482 
ThrowError(napi_env env,int code,const std::string & msg,bool isThrow)483 void ThrowError(napi_env env, int code, const std::string& msg, bool isThrow)
484 {
485     // no error needs to be thrown before api 9
486     if (!isThrow) {
487         return;
488     }
489 
490     if (napi_throw_error(env, std::to_string(code).c_str(), msg.c_str()) != napi_ok) {
491         HiLog::Error(LABEL, "failed to throw error, code=%{public}d, msg=%{public}s", code, msg.c_str());
492     }
493 }
494 
CreateError(napi_env env,int code,const std::string & msg)495 napi_value CreateError(napi_env env, int code, const std::string& msg)
496 {
497     napi_value err = nullptr;
498     if (napi_create_error(env, CreateString(env, std::to_string(code)), CreateString(env, msg), &err) != napi_ok) {
499         HiLog::Error(LABEL, "failed to create error");
500         return nullptr;
501     }
502     return err;
503 }
504 
CreateErrMsg(const std::string & name)505 std::string CreateErrMsg(const std::string& name)
506 {
507     return "Parameter error. The " + name + " parameter is mandatory.";
508 }
509 
CreateErrMsg(const std::string & name,const std::string & type)510 std::string CreateErrMsg(const std::string& name, const std::string& type)
511 {
512     return "Parameter error. The type of " + name + " must be " + type + ".";
513 }
CreateErrMsg(const std::string & name,const napi_valuetype type)514 std::string CreateErrMsg(const std::string& name, const napi_valuetype type)
515 {
516     std::string typeStr = "";
517     switch (type) {
518         case napi_boolean:
519             typeStr = "boolean";
520             break;
521         case napi_number:
522             typeStr = "number";
523             break;
524         case napi_string:
525             typeStr = "string";
526             break;
527         case napi_object:
528             typeStr = "object";
529             break;
530         default:
531             break;
532     }
533     return CreateErrMsg(name, typeStr);
534 }
535 
CreateBaseValueByJson(const napi_env env,const Json::Value & jsonValue)536 napi_value CreateBaseValueByJson(const napi_env env, const Json::Value& jsonValue)
537 {
538     if (jsonValue.isBool()) {
539         return CreateBoolean(env, jsonValue.asBool());
540     }
541     if (jsonValue.isInt()) {
542         return CreateInt32(env, jsonValue.asInt());
543     }
544     if (jsonValue.isInt64() && jsonValue.type() != Json::ValueType::uintValue) {
545         return CreateInt64(env, jsonValue.asInt64());
546     }
547     if (jsonValue.isDouble()) {
548         return CreateDouble(env, jsonValue.asDouble());
549     }
550     if (jsonValue.isString()) {
551         return CreateString(env, jsonValue.asString());
552     }
553     return nullptr;
554 }
555 
CreateValueByJson(napi_env env,const Json::Value & jsonValue)556 napi_value CreateValueByJson(napi_env env, const Json::Value& jsonValue)
557 {
558     if (jsonValue.isArray()) {
559         napi_value array = CreateArray(env);
560         for (size_t i = 0; i < jsonValue.size(); ++i) {
561             SetElement(env, array, i, CreateValueByJson(env, jsonValue[static_cast<int>(i)]));
562         }
563         return array;
564     }
565     if (jsonValue.isObject()) {
566         napi_value obj = CreateObject(env);
567         auto eventNameList = jsonValue.getMemberNames();
568         for (auto it = eventNameList.cbegin(); it != eventNameList.cend(); ++it) {
569             auto propertyName = *it;
570             SetNamedProperty(env, obj, propertyName, CreateValueByJson(env, jsonValue[propertyName]));
571         }
572         return obj;
573     }
574     return CreateBaseValueByJson(env, jsonValue);
575 }
576 
CreateValueByJsonStr(napi_env env,const std::string & jsonStr)577 napi_value CreateValueByJsonStr(napi_env env, const std::string& jsonStr)
578 {
579     Json::Value jsonValue;
580     Json::Reader reader(Json::Features::strictMode());
581     if (!reader.parse(jsonStr, jsonValue)) {
582         HiLog::Error(LABEL, "parse event detail info failed, please check the style of json");
583         return nullptr;
584     }
585     return CreateValueByJson(env, jsonValue);
586 }
587 
CreateEventInfo(napi_env env,std::shared_ptr<AppEventPack> event)588 napi_value CreateEventInfo(napi_env env, std::shared_ptr<AppEventPack> event)
589 {
590     napi_value obj = CreateObject(env);
591     SetNamedProperty(env, obj, DOMAIN_PROPERTY, CreateString(env, event->GetDomain()));
592     SetNamedProperty(env, obj, NAME_PROPERTY, CreateString(env, event->GetName()));
593     SetNamedProperty(env, obj, EVENT_TYPE_PROPERTY, CreateInt32(env, event->GetType()));
594     SetNamedProperty(env, obj, PARAM_PROPERTY, CreateValueByJsonStr(env, event->GetParamStr()));
595     return obj;
596 }
597 
CreateEventGroups(napi_env env,const std::vector<std::shared_ptr<AppEventPack>> & events)598 napi_value CreateEventGroups(napi_env env, const std::vector<std::shared_ptr<AppEventPack>>& events)
599 {
600     std::unordered_map<std::string, std::vector<std::shared_ptr<AppEventPack>>> eventMap;
601     for (auto event : events) {
602         eventMap[event->GetName()].emplace_back(event);
603     }
604 
605     napi_value eventGroups = CreateArray(env);
606     size_t index = 0;
607     for (auto it = eventMap.begin(); it != eventMap.end(); ++it) {
608         napi_value eventInfos = CreateArray(env);
609         for (size_t i = 0; i < it->second.size(); ++i) {
610             SetElement(env, eventInfos, i, CreateEventInfo(env, it->second[i]));
611         }
612         napi_value obj = CreateObject(env);
613         SetNamedProperty(env, obj, NAME_PROPERTY, CreateString(env, it->first));
614         SetNamedProperty(env, obj, EVENT_INFOS_PROPERTY, eventInfos);
615         SetElement(env, eventGroups, index, obj);
616         ++index;
617     }
618     return eventGroups;
619 }
620 } // namespace NapiUtil
621 } // namespace HiviewDFX
622 } // namespace OHOS
623