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 "hiappevent_base.h"
18 #include "hilog/log.h"
19
20 namespace OHOS {
21 namespace HiviewDFX {
22 namespace NapiUtil {
23 namespace {
24 constexpr HiLogLabel LABEL = { LOG_CORE, HIAPPEVENT_DOMAIN, "HiAppEvent_NapiUtil" };
25 }
26
IsNull(const napi_env env,const napi_value value)27 bool IsNull(const napi_env env, const napi_value value)
28 {
29 return GetType(env, value) == napi_null;
30 }
31
IsBoolean(const napi_env env,const napi_value value)32 bool IsBoolean(const napi_env env, const napi_value value)
33 {
34 return GetType(env, value) == napi_boolean;
35 }
36
IsNumber(const napi_env env,const napi_value value)37 bool IsNumber(const napi_env env, const napi_value value)
38 {
39 return GetType(env, value) == napi_number;
40 }
41
IsString(const napi_env env,const napi_value value)42 bool IsString(const napi_env env, const napi_value value)
43 {
44 return GetType(env, value) == napi_string;
45 }
46
IsObject(const napi_env env,const napi_value value)47 bool IsObject(const napi_env env, const napi_value value)
48 {
49 return GetType(env, value) == napi_object;
50 }
51
IsFunction(const napi_env env,const napi_value value)52 bool IsFunction(const napi_env env, const napi_value value)
53 {
54 return GetType(env, value) == napi_function;
55 }
56
IsArray(const napi_env env,const napi_value value)57 bool IsArray(const napi_env env, const napi_value value)
58 {
59 bool result = false;
60 if (napi_is_array(env, value, &result) != napi_ok) {
61 HiLog::Error(LABEL, "failed to check array type");
62 return false;
63 }
64 return result;
65 }
66
IsArrayType(const napi_env env,const napi_value value,napi_valuetype type)67 bool IsArrayType(const napi_env env, const napi_value value, napi_valuetype type)
68 {
69 if (!IsArray(env, value)) {
70 return false;
71 }
72 if (GetArrayLength(env, value) == 0) {
73 return true;
74 }
75 return GetArrayType(env, value) == type;
76 }
77
GetType(const napi_env env,const napi_value value)78 napi_valuetype GetType(const napi_env env, const napi_value value)
79 {
80 napi_valuetype type;
81 if (napi_typeof(env, value, &type) != napi_ok) {
82 HiLog::Error(LABEL, "failed to get value type");
83 return napi_undefined;
84 }
85 return type;
86 }
87
GetArrayType(const napi_env env,const napi_value arr)88 napi_valuetype GetArrayType(const napi_env env, const napi_value arr)
89 {
90 uint32_t result = 0;
91 if (napi_get_array_length(env, arr, &result) != napi_ok) {
92 HiLog::Error(LABEL, "failed to get the length of array");
93 return napi_undefined;
94 }
95
96 napi_valuetype type = napi_null; // note: empty array returns null type
97 for (size_t i = 0; i < result; ++i) {
98 napi_value element = nullptr;
99 if (napi_get_element(env, arr, i, &element) != napi_ok) {
100 HiLog::Error(LABEL, "failed to get the element of array");
101 return napi_undefined;
102 }
103 if (i == 0) {
104 type = GetType(env, element);
105 continue;
106 }
107 if (type != GetType(env, element)) {
108 HiLog::Error(LABEL, "array has different element types");
109 return napi_undefined;
110 }
111 }
112 return type;
113 }
114
GetArrayLength(const napi_env env,const napi_value arr)115 uint32_t GetArrayLength(const napi_env env, const napi_value arr)
116 {
117 uint32_t result = 0;
118 if (napi_get_array_length(env, arr, &result) != napi_ok) {
119 HiLog::Error(LABEL, "failed to get the length of array");
120 return 0;
121 }
122 return result;
123 }
124
GetElement(const napi_env env,const napi_value arr,uint32_t index)125 napi_value GetElement(const napi_env env, const napi_value arr, uint32_t index)
126 {
127 napi_value element = nullptr;
128 if (napi_get_element(env, arr, index, &element) != napi_ok) {
129 HiLog::Error(LABEL, "failed to get the element of array.");
130 return nullptr;
131 }
132 return element;
133 }
134
GetBoolean(const napi_env env,const napi_value value)135 bool GetBoolean(const napi_env env, const napi_value value)
136 {
137 bool bValue = false;
138 if (napi_get_value_bool(env, value, &bValue) != napi_ok) {
139 HiLog::Error(LABEL, "failed to get bool value");
140 return false;
141 }
142 return bValue;
143 }
144
GetBooleans(const napi_env env,const napi_value arr,std::vector<bool> & bools)145 void GetBooleans(const napi_env env, const napi_value arr, std::vector<bool>& bools)
146 {
147 uint32_t len = GetArrayLength(env, arr);
148 for (size_t i = 0; i < len; ++i) {
149 napi_value element = GetElement(env, arr, i);
150 if (element == nullptr) {
151 continue;
152 }
153 bools.push_back(GetBoolean(env, element));
154 }
155 }
156
GetInt32(const napi_env env,const napi_value value)157 int32_t GetInt32(const napi_env env, const napi_value value)
158 {
159 int32_t iValue = 0;
160 if (napi_get_value_int32(env, value, &iValue) != napi_ok) {
161 HiLog::Error(LABEL, "failed to get int32 value");
162 return 0;
163 }
164 return iValue;
165 }
166
GetInt32s(const napi_env env,const napi_value arr,std::vector<int32_t> & ints)167 void GetInt32s(const napi_env env, const napi_value arr, std::vector<int32_t>& ints)
168 {
169 uint32_t len = GetArrayLength(env, arr);
170 for (size_t i = 0; i < len; ++i) {
171 napi_value element = GetElement(env, arr, i);
172 if (element == nullptr) {
173 continue;
174 }
175 ints.push_back(GetInt32(env, element));
176 }
177 }
178
GetDouble(const napi_env env,const napi_value value)179 double GetDouble(const napi_env env, const napi_value value)
180 {
181 double dValue = 0;
182 if (napi_get_value_double(env, value, &dValue) != napi_ok) {
183 HiLog::Error(LABEL, "failed to get double value");
184 return 0;
185 }
186 return dValue;
187 }
188
GetDoubles(const napi_env env,const napi_value arr,std::vector<double> & doubles)189 void GetDoubles(const napi_env env, const napi_value arr, std::vector<double>& doubles)
190 {
191 uint32_t len = GetArrayLength(env, arr);
192 for (size_t i = 0; i < len; ++i) {
193 napi_value element = GetElement(env, arr, i);
194 if (element == nullptr) {
195 continue;
196 }
197 doubles.push_back(GetDouble(env, element));
198 }
199 }
200
GetString(const napi_env env,const napi_value value,size_t bufsize)201 std::string GetString(const napi_env env, const napi_value value, size_t bufsize)
202 {
203 char strValue[bufsize + 1]; // 1 for '\0'
204 size_t result = 0;
205 if (napi_get_value_string_utf8(env, value, strValue, bufsize, &result) != napi_ok) {
206 HiLog::Error(LABEL, "failed to get string value");
207 return "";
208 }
209 return strValue;
210 }
211
GetStrings(const napi_env env,const napi_value arr,std::vector<std::string> & strs,size_t bufsize)212 void GetStrings(const napi_env env, const napi_value arr, std::vector<std::string>& strs, size_t bufsize)
213 {
214 uint32_t len = GetArrayLength(env, arr);
215 for (size_t i = 0; i < len; ++i) {
216 napi_value element = GetElement(env, arr, i);
217 if (element == nullptr) {
218 continue;
219 }
220 strs.push_back(GetString(env, element, bufsize));
221 }
222 }
223
HasProperty(const napi_env env,const napi_value object,const std::string & name)224 bool HasProperty(const napi_env env, const napi_value object, const std::string& name)
225 {
226 bool result = false;
227 if (napi_has_named_property(env, object, name.c_str(), &result) != napi_ok) {
228 HiLog::Error(LABEL, "failed to check whether the object has the named property");
229 return false;
230 }
231 return result;
232 }
233
GetProperty(const napi_env env,const napi_value object,const std::string & name)234 napi_value GetProperty(const napi_env env, const napi_value object, const std::string& name)
235 {
236 if (!HasProperty(env, object, name)) {
237 return nullptr;
238 }
239 napi_value value = nullptr;
240 if (napi_get_named_property(env, object, name.c_str(), &value) != napi_ok) {
241 HiLog::Error(LABEL, "failed to get property=%{public}s from object", name.c_str());
242 return nullptr;
243 }
244 return value;
245 }
246
GetPropertyNames(const napi_env env,const napi_value object,std::vector<std::string> & names)247 void GetPropertyNames(const napi_env env, const napi_value object, std::vector<std::string>& names)
248 {
249 napi_value propertyNames = nullptr;
250 if (napi_get_property_names(env, object, &propertyNames) != napi_ok) {
251 HiLog::Error(LABEL, "failed to get property names.");
252 return;
253 }
254 uint32_t len = 0;
255 if (napi_get_array_length(env, propertyNames, &len) != napi_ok) {
256 HiLog::Error(LABEL, "failed to get array length");
257 return;
258 }
259 for (uint32_t i = 0; i < len; ++i) {
260 napi_value element = nullptr;
261 if (napi_get_element(env, propertyNames, i, &element) != napi_ok) {
262 HiLog::Error(LABEL, "failed to get the element of array");
263 continue;
264 }
265 names.push_back(GetString(env, element));
266 }
267 }
268
GetReferenceValue(const napi_env env,const napi_ref funcRef)269 napi_value GetReferenceValue(const napi_env env, const napi_ref funcRef)
270 {
271 napi_value refValue = nullptr;
272 if (napi_get_reference_value(env, funcRef, &refValue) != napi_ok) {
273 HiLog::Error(LABEL, "failed to get reference value");
274 return nullptr;
275 }
276 return refValue;
277 }
278
GetCbInfo(const napi_env env,napi_callback_info info,napi_value argv[],size_t argc)279 size_t GetCbInfo(const napi_env env, napi_callback_info info, napi_value argv[], size_t argc)
280 {
281 size_t paramNum = argc;
282 if (napi_get_cb_info(env, info, ¶mNum, argv, nullptr, nullptr) != napi_ok) {
283 HiLog::Error(LABEL, "failed to get callback info");
284 return 0;
285 }
286 return paramNum;
287 }
288
CreateReference(const napi_env env,const napi_value func)289 napi_ref CreateReference(const napi_env env, const napi_value func)
290 {
291 napi_ref ref = nullptr;
292 if (napi_create_reference(env, func, 1, &ref) != napi_ok) { // 1 means initial reference count
293 HiLog::Error(LABEL, "failed to create reference");
294 return nullptr;
295 }
296 return ref;
297 }
298
CreateNull(const napi_env env)299 napi_value CreateNull(const napi_env env)
300 {
301 napi_value nullValue = nullptr;
302 if (napi_get_null(env, &nullValue) != napi_ok) {
303 HiLog::Error(LABEL, "failed to create null");
304 return nullptr;
305 }
306 return nullValue;
307 }
308
CreateUndefined(const napi_env env)309 napi_value CreateUndefined(const napi_env env)
310 {
311 napi_value undefinedValue = nullptr;
312 if (napi_get_undefined(env, &undefinedValue) != napi_ok) {
313 HiLog::Error(LABEL, "failed to create undefined");
314 return nullptr;
315 }
316 return undefinedValue;
317 }
318
CreateBoolean(const napi_env env,bool bValue)319 napi_value CreateBoolean(const napi_env env, bool bValue)
320 {
321 napi_value boolValue = nullptr;
322 if (napi_get_boolean(env, bValue, &boolValue) != napi_ok) {
323 HiLog::Error(LABEL, "failed to create boolean");
324 return nullptr;
325 }
326 return boolValue;
327 }
328
CreateInt32(const napi_env env,int32_t num)329 napi_value CreateInt32(const napi_env env, int32_t num)
330 {
331 napi_value intValue = nullptr;
332 if (napi_create_int32(env, num, &intValue) != napi_ok) {
333 HiLog::Error(LABEL, "failed to create int32");
334 return nullptr;
335 }
336 return intValue;
337 }
338
CreateString(const napi_env env,const std::string & str)339 napi_value CreateString(const napi_env env, const std::string& str)
340 {
341 napi_value strValue = nullptr;
342 if (napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &strValue) != napi_ok) {
343 HiLog::Error(LABEL, "failed to create string");
344 return nullptr;
345 }
346 return strValue;
347 }
348
CreateStrings(const napi_env env,const std::vector<std::string> & strs)349 napi_value CreateStrings(const napi_env env, const std::vector<std::string>& strs)
350 {
351 napi_value arr = CreateArray(env);
352 for (size_t i = 0; i < strs.size(); ++i) {
353 SetElement(env, arr, i, CreateString(env, strs[i]));
354 }
355 return arr;
356 }
357
CreateObject(const napi_env env)358 napi_value CreateObject(const napi_env env)
359 {
360 napi_value obj = nullptr;
361 if (napi_create_object(env, &obj) != napi_ok) {
362 HiLog::Error(LABEL, "failed to create object");
363 return nullptr;
364 }
365 return obj;
366 }
367
CreateObject(const napi_env env,const std::string & key,const napi_value value)368 napi_value CreateObject(const napi_env env, const std::string& key, const napi_value value)
369 {
370 napi_value obj = nullptr;
371 if (napi_create_object(env, &obj) != napi_ok) {
372 HiLog::Error(LABEL, "failed to create object");
373 return nullptr;
374 }
375 if (napi_set_named_property(env, obj, key.c_str(), value) != napi_ok) {
376 HiLog::Error(LABEL, "failed to set property");
377 return nullptr;
378 }
379 return obj;
380 }
381
CreateArray(const napi_env env)382 napi_value CreateArray(const napi_env env)
383 {
384 napi_value arr = nullptr;
385 if (napi_create_array(env, &arr) != napi_ok) {
386 HiLog::Error(LABEL, "failed to create array");
387 return nullptr;
388 }
389 return arr;
390 }
391
SetElement(const napi_env env,const napi_value obj,uint32_t index,const napi_value value)392 void SetElement(const napi_env env, const napi_value obj, uint32_t index, const napi_value value)
393 {
394 if (napi_set_element(env, obj, index, value) != napi_ok) {
395 HiLog::Error(LABEL, "failed to set element");
396 }
397 }
398
SetNamedProperty(const napi_env env,const napi_value obj,const std::string & key,const napi_value value)399 void SetNamedProperty(const napi_env env, const napi_value obj, const std::string& key, const napi_value value)
400 {
401 if (napi_set_named_property(env, obj, key.c_str(), value) != napi_ok) {
402 HiLog::Error(LABEL, "failed to set property");
403 }
404 }
405
ConvertToString(const napi_env env,const napi_value value)406 std::string ConvertToString(const napi_env env, const napi_value value)
407 {
408 napi_valuetype type = GetType(env, value);
409 if (type == napi_undefined) {
410 return "";
411 }
412
413 std::string result = "";
414 switch (type) {
415 case napi_boolean:
416 result = GetBoolean(env, value) ? "true" : "false";
417 break;
418 case napi_number:
419 result = std::to_string(GetDouble(env, value));
420 break;
421 case napi_string:
422 result = GetString(env, value);
423 break;
424 default:
425 break;
426 }
427 return result;
428 }
429
ThrowError(napi_env env,int code,const std::string & msg,bool isThrow)430 void ThrowError(napi_env env, int code, const std::string& msg, bool isThrow)
431 {
432 // no error needs to be thrown before api 9
433 if (!isThrow) {
434 return;
435 }
436
437 if (napi_throw_error(env, std::to_string(code).c_str(), msg.c_str()) != napi_ok) {
438 HiLog::Error(LABEL, "failed to throw error, code=%{public}d, msg=%{public}s", code, msg.c_str());
439 }
440 }
441
CreateError(napi_env env,int code,const std::string & msg)442 napi_value CreateError(napi_env env, int code, const std::string& msg)
443 {
444 napi_value err = nullptr;
445 if (napi_create_error(env, CreateString(env, std::to_string(code)), CreateString(env, msg), &err) != napi_ok) {
446 HiLog::Error(LABEL, "failed to create error");
447 return nullptr;
448 }
449 return err;
450 }
451
CreateErrMsg(const std::string & name)452 std::string CreateErrMsg(const std::string& name)
453 {
454 return "Parameter error. The " + name + " parameter is mandatory.";
455 }
456
CreateErrMsg(const std::string & name,const std::string & type)457 std::string CreateErrMsg(const std::string& name, const std::string& type)
458 {
459 return "Parameter error. The type of " + name + " must be " + type + ".";
460 }
CreateErrMsg(const std::string & name,const napi_valuetype type)461 std::string CreateErrMsg(const std::string& name, const napi_valuetype type)
462 {
463 std::string typeStr = "";
464 switch (type) {
465 case napi_boolean:
466 typeStr = "boolean";
467 break;
468 case napi_number:
469 typeStr = "number";
470 break;
471 case napi_string:
472 typeStr = "string";
473 break;
474 case napi_object:
475 typeStr = "object";
476 break;
477 default:
478 break;
479 }
480 return CreateErrMsg(name, typeStr);
481 }
482 } // namespace NapiUtil
483 } // namespace HiviewDFX
484 } // namespace OHOS
485