• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #define LOG_TAG "JSUtils"
16 
17 #include "js_utils.h"
18 
19 #include <cstring>
20 
21 #include "js_native_api_types.h"
22 #include "logger.h"
23 #include "securec.h"
24 using namespace OHOS::Rdb;
25 
26 #define CHECK_RETURN_RET(assertion, message, revt)                   \
27     do {                                                             \
28         if (!(assertion)) {                                          \
29             LOG_WARN("assertion (" #assertion ") failed: " message); \
30             return revt;                                             \
31         }                                                            \
32     } while (0)
33 
34 namespace OHOS {
35 namespace AppDataMgrJsKit {
36 namespace JSUtils {
37 static int32_t g_hapVersion = -1; // the current apiVersion of hap
38 }
39 
40 static constexpr JSUtils::JsFeatureSpace FEATURE_NAME_SPACES[] = {
41     { "ohos.data.cloudData", "ZGF0YS5jbG91ZERhdGE=", true },
42     { "ohos.data.dataAbility", "ZGF0YS5kYXRhQWJpbGl0eQ==", true },
43     { "ohos.data.dataShare", "ZGF0YS5kYXRhU2hhcmU=", false },
44     { "ohos.data.distributedDataObject", "ZGF0YS5kaXN0cmlidXRlZERhdGFPYmplY3Q=", false },
45     { "ohos.data.distributedKVStore", "ZGF0YS5kaXN0cmlidXRlZEtWU3RvcmU=", false },
46     { "ohos.data.graphStore", "ZGF0YS5ncmFwaFN0b3Jl", true },
47     { "ohos.data.rdb", "ZGF0YS5yZGI=", true },
48     { "ohos.data.relationalStore", "ZGF0YS5yZWxhdGlvbmFsU3RvcmU=", true },
49 };
50 
SetHapVersion(int32_t hapversion)51 void JSUtils::SetHapVersion(int32_t hapversion)
52 {
53     g_hapVersion = hapversion;
54 }
55 
GetHapVersion()56 int32_t JSUtils::GetHapVersion()
57 {
58     return g_hapVersion;
59 }
60 
GetJsFeatureSpace(const std::string & name)61 const std::optional<JSUtils::JsFeatureSpace> JSUtils::GetJsFeatureSpace(const std::string &name)
62 {
63     auto jsFeature = JsFeatureSpace{ name.data(), nullptr, false };
64     auto iter = std::lower_bound(FEATURE_NAME_SPACES,
65         FEATURE_NAME_SPACES + sizeof(FEATURE_NAME_SPACES) / sizeof(FEATURE_NAME_SPACES[0]), jsFeature,
66         [](const JsFeatureSpace &JsFeatureSpace1, const JsFeatureSpace &JsFeatureSpace2) {
67             return strcmp(JsFeatureSpace1.spaceName, JsFeatureSpace2.spaceName) < 0;
68         });
69     if (iter < FEATURE_NAME_SPACES + sizeof(FEATURE_NAME_SPACES) / sizeof(FEATURE_NAME_SPACES[0]) &&
70         strcmp(iter->spaceName, name.data()) == 0) {
71         return *iter;
72     }
73     return std::nullopt;
74 }
75 
GetInnerValue(napi_env env,napi_value in,const std::string & prop,bool optional)76 std::pair<napi_status, napi_value> JSUtils::GetInnerValue(
77     napi_env env, napi_value in, const std::string &prop, bool optional)
78 {
79     bool hasProp = false;
80     napi_status status = napi_has_named_property(env, in, prop.c_str(), &hasProp);
81     if (status != napi_ok) {
82         return std::make_pair(napi_generic_failure, nullptr);
83     }
84     if (!hasProp) {
85         status = optional ? napi_ok : napi_generic_failure;
86         return std::make_pair(status, nullptr);
87     }
88     napi_value inner = nullptr;
89     status = napi_get_named_property(env, in, prop.c_str(), &inner);
90     if (status != napi_ok || inner == nullptr) {
91         return std::make_pair(napi_generic_failure, nullptr);
92     }
93     if (optional && JSUtils::IsNull(env, inner)) {
94         return std::make_pair(napi_ok, nullptr);
95     }
96     return std::make_pair(napi_ok, inner);
97 }
98 
Convert2String(napi_env env,napi_value jsStr)99 std::string JSUtils::Convert2String(napi_env env, napi_value jsStr)
100 {
101     std::string value = ""; // TD: need to check everywhere in use whether empty is work well.
102     JSUtils::Convert2Value(env, jsStr, value);
103     return value;
104 }
105 
Convert2JSValue(napi_env env,const std::nullptr_t & jsStr)106 napi_value JSUtils::Convert2JSValue(napi_env env, const std::nullptr_t &jsStr)
107 {
108     return nullptr;
109 }
110 
Convert2ValueExt(napi_env env,napi_value jsValue,uint32_t & output)111 int32_t JSUtils::Convert2ValueExt(napi_env env, napi_value jsValue, uint32_t &output)
112 {
113     napi_valuetype type = napi_undefined;
114     napi_status status = napi_typeof(env, jsValue, &type);
115     if (status != napi_ok || type != napi_number) {
116         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
117         return napi_invalid_arg;
118     }
119 
120     status = napi_get_value_uint32(env, jsValue, &output);
121     if (status != napi_ok) {
122         LOG_DEBUG("napi_get_value_uint32 failed, status = %{public}d", status);
123         return status;
124     }
125     return status;
126 }
127 
Convert2ValueExt(napi_env env,napi_value jsValue,int32_t & output)128 int32_t JSUtils::Convert2ValueExt(napi_env env, napi_value jsValue, int32_t &output)
129 {
130     napi_valuetype type = napi_undefined;
131     napi_status status = napi_typeof(env, jsValue, &type);
132     if (status != napi_ok || type != napi_number) {
133         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
134         return napi_invalid_arg;
135     }
136 
137     status = napi_get_value_int32(env, jsValue, &output);
138     if (status != napi_ok) {
139         LOG_DEBUG("napi_get_value_int32 failed, status = %{public}d", status);
140         return status;
141     }
142     return status;
143 }
144 
Convert2Value(napi_env env,napi_value jsValue,napi_value & output)145 int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, napi_value &output)
146 {
147     output = jsValue;
148     return napi_ok;
149 }
150 
Convert2Value(napi_env env,napi_value jsValue,bool & output)151 int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, bool &output)
152 {
153     napi_valuetype type = napi_undefined;
154     napi_status status = napi_typeof(env, jsValue, &type);
155     if (status != napi_ok || type != napi_boolean) {
156         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
157         return napi_invalid_arg;
158     }
159 
160     bool bValue = false;
161     status = napi_get_value_bool(env, jsValue, &bValue);
162     if (status != napi_ok) {
163         LOG_ERROR("napi_get_value_bool failed, status = %{public}d", status);
164         return status;
165     }
166     output = bValue;
167     return status;
168 }
169 
Convert2ValueExt(napi_env env,napi_value jsValue,int64_t & output)170 int32_t JSUtils::Convert2ValueExt(napi_env env, napi_value jsValue, int64_t &output)
171 {
172     napi_valuetype type = napi_undefined;
173     napi_status status = napi_typeof(env, jsValue, &type);
174     if (status != napi_ok || type != napi_number) {
175         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
176         return napi_invalid_arg;
177     }
178 
179     status = napi_get_value_int64(env, jsValue, &output);
180     if (status != napi_ok) {
181         LOG_DEBUG("napi_get_value_int64 failed, status = %{public}d", status);
182         return status;
183     }
184     return status;
185 }
186 
Convert2Value(napi_env env,napi_value jsValue,double & output)187 int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, double &output)
188 {
189     napi_valuetype type = napi_undefined;
190     napi_status status = napi_typeof(env, jsValue, &type);
191     if (status != napi_ok || type != napi_number) {
192         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
193         return napi_invalid_arg;
194     }
195 
196     double number = 0.0;
197     status = napi_get_value_double(env, jsValue, &number);
198     if (status != napi_ok) {
199         LOG_DEBUG("napi_get_value_double failed, status = %{public}d", status);
200         return status;
201     }
202     output = number;
203     return status;
204 }
205 
Convert2Value(napi_env env,napi_value jsValue,int64_t & output)206 int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, int64_t &output)
207 {
208     return napi_invalid_arg;
209 }
210 
Convert2Value(napi_env env,napi_value jsValue,std::vector<float> & output)211 int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::vector<float> &output)
212 {
213     bool isTypedArray = false;
214     napi_is_typedarray(env, jsValue, &isTypedArray);
215     if (!isTypedArray) {
216         return napi_invalid_arg;
217     }
218 
219     napi_typedarray_type type;
220     napi_value input_buffer = nullptr;
221     size_t byte_offset = 0;
222     size_t length = 0;
223     void *tmp = nullptr;
224     auto status = napi_get_typedarray_info(env, jsValue, &type, &length, &tmp, &input_buffer, &byte_offset);
225     if (status != napi_ok || type != napi_float32_array) {
226         return napi_invalid_arg;
227     }
228 
229     output = (tmp != nullptr
230                   ? std::vector<float>(static_cast<float *>(tmp), static_cast<float *>(tmp) + length / sizeof(float))
231                   : std::vector<float>());
232     return status;
233 }
234 
Convert2Value(napi_env env,napi_value jsValue,std::string & output)235 int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::string &output)
236 {
237     napi_valuetype type = napi_undefined;
238     napi_status status = napi_typeof(env, jsValue, &type);
239     if (status != napi_ok || type != napi_string) {
240         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
241         return napi_invalid_arg;
242     }
243 
244     size_t buffSize = 0;
245     napi_get_value_string_utf8(env, jsValue, nullptr, 0, &buffSize);
246 
247     // cut down with 0 if more than MAX_VALUE_LENGTH
248     if (buffSize >= JSUtils::MAX_VALUE_LENGTH - 1) {
249         buffSize = JSUtils::MAX_VALUE_LENGTH - 1;
250     }
251     std::unique_ptr<char[]> buffer = std::make_unique<char[]>(buffSize + 1);
252     if (!buffer) {
253         LOG_ERROR("Buffer data is nullptr.");
254         return napi_invalid_arg;
255     }
256     status = napi_get_value_string_utf8(env, jsValue, buffer.get(), buffSize + 1, &buffSize);
257     if (status != napi_ok) {
258         LOG_ERROR("napi_get_value_string_utf8 failed, status = %{public}d", status);
259         return status;
260     }
261     output = std::string(buffer.get());
262 
263     return status;
264 }
265 
Convert2Value(napi_env env,napi_value jsValue,std::vector<uint8_t> & output)266 int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::vector<uint8_t> &output)
267 {
268     bool isTypedArray = false;
269     napi_is_typedarray(env, jsValue, &isTypedArray);
270     if (!isTypedArray) {
271         return napi_invalid_arg;
272     }
273 
274     napi_typedarray_type type;
275     napi_value input_buffer = nullptr;
276     size_t byte_offset = 0;
277     size_t length = 0;
278     void *tmp = nullptr;
279     auto status = napi_get_typedarray_info(env, jsValue, &type, &length, &tmp, &input_buffer, &byte_offset);
280     if (status != napi_ok || type != napi_uint8_array) {
281         return napi_invalid_arg;
282     }
283 
284     output = (tmp != nullptr ? std::vector<uint8_t>(static_cast<uint8_t *>(tmp), static_cast<uint8_t *>(tmp) + length)
285                              : std::vector<uint8_t>());
286     return status;
287 }
288 
Convert2Value(napi_env env,napi_value jsValue,std::monostate & value)289 int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::monostate &value)
290 {
291     napi_value tempValue = nullptr;
292     napi_get_null(env, &tempValue);
293     bool equal = false;
294     napi_strict_equals(env, jsValue, tempValue, &equal);
295     if (equal) {
296         value = std::monostate();
297         return napi_ok;
298     }
299     LOG_DEBUG("JsValue is not null.");
300     return napi_invalid_arg;
301 }
302 
Convert2Value(napi_env env,napi_value jsValue,std::map<std::string,int32_t> & output)303 int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::map<std::string, int32_t> &output)
304 {
305     LOG_DEBUG("napi_value -> std::map<std::string, int32_t> ");
306     output.clear();
307     napi_value jsMapList = nullptr;
308     uint32_t jsCount = 0;
309     napi_status status = napi_get_property_names(env, jsValue, &jsMapList);
310     CHECK_RETURN_RET(status == napi_ok, "get_property_names failed", napi_invalid_arg);
311     status = napi_get_array_length(env, jsMapList, &jsCount);
312     LOG_DEBUG("jsCOUNT: %{public}d", jsCount);
313     CHECK_RETURN_RET(status == napi_ok && jsCount > 0, "get_map failed", napi_invalid_arg);
314     napi_value jsKey = nullptr;
315     napi_value jsVal = nullptr;
316     for (uint32_t index = 0; index < jsCount; index++) {
317         status = napi_get_element(env, jsMapList, index, &jsKey);
318         CHECK_RETURN_RET(status == napi_ok && jsKey != nullptr, "no element", napi_invalid_arg);
319         std::string key;
320         int ret = Convert2Value(env, jsKey, key);
321         CHECK_RETURN_RET(ret == napi_ok, "convert key failed", ret);
322         status = napi_get_property(env, jsValue, jsKey, &jsVal);
323         CHECK_RETURN_RET(status == napi_ok && jsVal != nullptr, "no element", napi_invalid_arg);
324         int32_t val;
325         ret = Convert2ValueExt(env, jsVal, val);
326         CHECK_RETURN_RET(ret == napi_ok, "convert val failed", ret);
327         output.insert(std::pair<std::string, int32_t>(key, val));
328     }
329     return napi_ok;
330 }
331 
Convert2Value(napi_env env,napi_value jsValue,std::map<std::string,bool> & output)332 int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::map<std::string, bool> &output)
333 {
334     LOG_DEBUG("napi_value -> std::map<std::string, bool> ");
335     output.clear();
336     napi_value jsMapList = nullptr;
337     uint32_t jsCount = 0;
338     napi_status status = napi_get_property_names(env, jsValue, &jsMapList);
339     CHECK_RETURN_RET(status == napi_ok, "get_property_names failed", napi_invalid_arg);
340     status = napi_get_array_length(env, jsMapList, &jsCount);
341     LOG_DEBUG("jsCount: %{public}d", jsCount);
342     CHECK_RETURN_RET(status == napi_ok && jsCount > 0, "get_map failed", napi_invalid_arg);
343     napi_value jsKey = nullptr;
344     napi_value jsVal = nullptr;
345     for (uint32_t index = 0; index < jsCount; index++) {
346         status = napi_get_element(env, jsMapList, index, &jsKey);
347         CHECK_RETURN_RET(status == napi_ok && jsKey != nullptr, "no element", napi_invalid_arg);
348         std::string key;
349         int ret = Convert2Value(env, jsKey, key);
350         CHECK_RETURN_RET(ret == napi_ok, "convert key failed", ret);
351         status = napi_get_property(env, jsValue, jsKey, &jsVal);
352         CHECK_RETURN_RET(status == napi_ok && jsVal != nullptr, "no element", napi_invalid_arg);
353         bool val;
354         ret = Convert2Value(env, jsVal, val);
355         CHECK_RETURN_RET(ret == napi_ok, "convert val failed", ret);
356         output.insert(std::pair<std::string, bool>(key, val));
357     }
358     return napi_ok;
359 }
360 
Convert2JSValue(napi_env env,const std::string & value)361 napi_value JSUtils::Convert2JSValue(napi_env env, const std::string &value)
362 {
363     napi_value jsValue = nullptr;
364     if (napi_create_string_utf8(env, value.c_str(), value.size(), &jsValue) != napi_ok) {
365         return nullptr;
366     }
367     return jsValue;
368 }
369 
Convert2JSValue(napi_env env,const std::vector<uint8_t> & value)370 napi_value JSUtils::Convert2JSValue(napi_env env, const std::vector<uint8_t> &value)
371 {
372     napi_value jsValue = nullptr;
373     void *native = nullptr;
374     napi_value buffer = nullptr;
375     napi_status status = napi_create_arraybuffer(env, value.size(), &native, &buffer);
376     if (status != napi_ok) {
377         return nullptr;
378     }
379     for (size_t i = 0; i < value.size(); i++) {
380         *(static_cast<uint8_t *>(native) + i) = value[i];
381     }
382     status = napi_create_typedarray(env, napi_uint8_array, value.size(), buffer, 0, &jsValue);
383     if (status != napi_ok) {
384         return nullptr;
385     }
386     return jsValue;
387 }
388 
Convert2JSValue(napi_env env,int32_t value)389 napi_value JSUtils::Convert2JSValue(napi_env env, int32_t value)
390 {
391     napi_value jsValue = nullptr;
392     napi_status status = napi_create_int32(env, value, &jsValue);
393     if (status != napi_ok) {
394         return nullptr;
395     }
396     return jsValue;
397 }
398 
Convert2JSValue(napi_env env,uint32_t value)399 napi_value JSUtils::Convert2JSValue(napi_env env, uint32_t value)
400 {
401     napi_value jsValue = nullptr;
402     napi_status status = napi_create_uint32(env, value, &jsValue);
403     if (status != napi_ok) {
404         return nullptr;
405     }
406     return jsValue;
407 }
408 
Convert2JSValue(napi_env env,int64_t value)409 napi_value JSUtils::Convert2JSValue(napi_env env, int64_t value)
410 {
411     napi_value jsValue = nullptr;
412     napi_status status = napi_create_int64(env, value, &jsValue);
413     if (status != napi_ok) {
414         return nullptr;
415     }
416     return jsValue;
417 }
418 
Convert2JSValue(napi_env env,double value)419 napi_value JSUtils::Convert2JSValue(napi_env env, double value)
420 {
421     napi_value jsValue = nullptr;
422     napi_status status = napi_create_double(env, value, &jsValue);
423     if (status != napi_ok) {
424         return nullptr;
425     }
426     return jsValue;
427 }
428 
Convert2JSValue(napi_env env,bool value)429 napi_value JSUtils::Convert2JSValue(napi_env env, bool value)
430 {
431     napi_value jsValue = nullptr;
432     napi_status status = napi_get_boolean(env, value, &jsValue);
433     if (status != napi_ok) {
434         return nullptr;
435     }
436     return jsValue;
437 }
438 
Convert2JSValue(napi_env env,const std::vector<float> & value)439 napi_value JSUtils::Convert2JSValue(napi_env env, const std::vector<float> &value)
440 {
441     napi_value jsValue = nullptr;
442     float *native = nullptr;
443     napi_value buffer = nullptr;
444     napi_status status = napi_create_arraybuffer(env, value.size() * sizeof(float), (void **)&native, &buffer);
445     if (status != napi_ok) {
446         return nullptr;
447     }
448     if (native == nullptr) {
449         return nullptr;
450     }
451     for (size_t i = 0; i < value.size(); i++) {
452         *(native + i) = value[i];
453     }
454     status = napi_create_typedarray(env, napi_float32_array, value.size(), buffer, 0, &jsValue);
455     if (status != napi_ok) {
456         return nullptr;
457     }
458     return jsValue;
459 }
460 
Convert2JSValue(napi_env env,const std::map<std::string,int> & value)461 napi_value JSUtils::Convert2JSValue(napi_env env, const std::map<std::string, int> &value)
462 {
463     napi_value jsValue = nullptr;
464     napi_status status = napi_create_array_with_length(env, value.size(), &jsValue);
465     if (status != napi_ok) {
466         return nullptr;
467     }
468 
469     int index = 0;
470     for (const auto &[device, result] : value) {
471         napi_value jsElement = nullptr;
472         status = napi_create_array_with_length(env, SYNC_RESULT_ELEMENT_NUM, &jsElement);
473         if (status != napi_ok) {
474             return nullptr;
475         }
476         napi_set_element(env, jsElement, 0, Convert2JSValue(env, device));
477         napi_set_element(env, jsElement, 1, Convert2JSValue(env, result));
478         napi_set_element(env, jsValue, index++, jsElement);
479     }
480 
481     return jsValue;
482 }
483 
Convert2JSValue(napi_env env,std::string value,napi_value & output)484 int32_t JSUtils::Convert2JSValue(napi_env env, std::string value, napi_value &output)
485 {
486     std::string tempStr = std::string(value);
487     if (napi_create_string_utf8(env, tempStr.c_str(), tempStr.size(), &output) != napi_ok) {
488         LOG_ERROR("Convert2JSValue create JS string failed.");
489         return ERR;
490     }
491     return napi_ok;
492 }
493 
Convert2JSValue(napi_env env,bool value,napi_value & output)494 int32_t JSUtils::Convert2JSValue(napi_env env, bool value, napi_value &output)
495 {
496     if (napi_get_boolean(env, value, &output) != napi_ok) {
497         LOG_ERROR("Convert2JSValue create JS bool failed.");
498         return ERR;
499     }
500     return napi_ok;
501 }
502 
Convert2JSValue(napi_env env,double value,napi_value & output)503 int32_t JSUtils::Convert2JSValue(napi_env env, double value, napi_value &output)
504 {
505     if (napi_create_double(env, value, &output) != napi_ok) {
506         LOG_ERROR("Convert2JSValue create JS double failed.");
507         return ERR;
508     }
509     return napi_ok;
510 }
511 
Convert2JSValue(napi_env env,const std::monostate & value)512 napi_value JSUtils::Convert2JSValue(napi_env env, const std::monostate &value)
513 {
514     napi_value result = nullptr;
515     napi_get_null(env, &result);
516     return result;
517 }
518 
IsNull(napi_env env,napi_value value)519 bool JSUtils::IsNull(napi_env env, napi_value value)
520 {
521     napi_valuetype type = napi_undefined;
522     napi_status status = napi_typeof(env, value, &type);
523     return status == napi_ok && (type == napi_undefined || type == napi_null);
524 }
525 
DefineClass(napi_env env,const std::string & spaceName,const std::string & className,const Descriptor & descriptor,napi_callback ctor)526 napi_value JSUtils::DefineClass(napi_env env, const std::string &spaceName, const std::string &className,
527     const Descriptor &descriptor, napi_callback ctor)
528 {
529     auto featureSpace = GetJsFeatureSpace(spaceName);
530     if (!featureSpace.has_value() || !featureSpace->isComponent) {
531         return nullptr;
532     }
533     auto constructor = GetClass(env, spaceName, className);
534     if (constructor != nullptr) {
535         return constructor;
536     }
537     auto rootPropName = std::string(featureSpace->nameBase64);
538     napi_value root = nullptr;
539     bool hasRoot = false;
540     napi_value global = nullptr;
541     napi_get_global(env, &global);
542     napi_has_named_property(env, global, rootPropName.c_str(), &hasRoot);
543     if (hasRoot) {
544         napi_get_named_property(env, global, rootPropName.c_str(), &root);
545     } else {
546         napi_create_object(env, &root);
547         napi_set_named_property(env, global, rootPropName.c_str(), root);
548     }
549 
550     std::string propName = "constructor_of_" + className;
551     bool hasProp = false;
552     napi_has_named_property(env, root, propName.c_str(), &hasProp);
553     if (hasProp) {
554         napi_get_named_property(env, root, propName.c_str(), &constructor);
555         if (constructor != nullptr) {
556             LOG_DEBUG("Got %{public}s from %{public}s", propName.c_str(), featureSpace->spaceName);
557             return constructor;
558         }
559         hasProp = false; // no constructor.
560     }
561     auto properties = descriptor();
562     NAPI_CALL(env, napi_define_class(env, className.c_str(), className.size(), ctor, nullptr,
563         properties.size(), properties.data(), &constructor));
564 
565     NAPI_ASSERT(env, constructor != nullptr, "napi_define_class failed!");
566 
567     if (!hasProp) {
568         napi_set_named_property(env, root, propName.c_str(), constructor);
569         LOG_DEBUG("Save %{public}s to %{public}s", propName.c_str(), featureSpace->spaceName);
570     }
571     return constructor;
572 }
573 
GetClass(napi_env env,const std::string & spaceName,const std::string & className)574 napi_value JSUtils::GetClass(napi_env env, const std::string &spaceName, const std::string &className)
575 {
576     auto featureSpace = GetJsFeatureSpace(spaceName);
577     if (!featureSpace.has_value()) {
578         return nullptr;
579     }
580     auto rootPropName = std::string(featureSpace->nameBase64);
581     napi_value root = nullptr;
582     napi_value global = nullptr;
583     napi_get_global(env, &global);
584     bool hasRoot;
585     napi_has_named_property(env, global, rootPropName.c_str(), &hasRoot);
586     if (!hasRoot) {
587         return nullptr;
588     }
589     napi_get_named_property(env, global, rootPropName.c_str(), &root);
590     std::string propName = "constructor_of_" + className;
591     napi_value constructor = nullptr;
592     bool hasProp = false;
593     napi_has_named_property(env, root, propName.c_str(), &hasProp);
594     if (!hasProp) {
595         return nullptr;
596     }
597     napi_get_named_property(env, root, propName.c_str(), &constructor);
598     if (constructor != nullptr) {
599         LOG_DEBUG("Got %{public}s from %{public}s", propName.c_str(), featureSpace->spaceName);
600         return constructor;
601     }
602     hasProp = false; // no constructor.
603     return constructor;
604 }
605 
Equal(napi_env env,napi_ref ref,napi_value value)606 bool JSUtils::Equal(napi_env env, napi_ref ref, napi_value value)
607 {
608     napi_value callback = nullptr;
609     napi_get_reference_value(env, ref, &callback);
610 
611     bool isEquals = false;
612     napi_strict_equals(env, value, callback, &isEquals);
613     return isEquals;
614 }
615 
ToJsObject(napi_env env,napi_value sendableValue)616 napi_value JSUtils::ToJsObject(napi_env env, napi_value sendableValue)
617 {
618     LOG_DEBUG("sendableObject -> jsObject");
619     napi_value keys = nullptr;
620     napi_status status = napi_get_all_property_names(env, sendableValue, napi_key_own_only,
621         static_cast<napi_key_filter>(napi_key_enumerable | napi_key_skip_symbols), napi_key_numbers_to_strings, &keys);
622     ASSERT(status == napi_ok, "napi_get_all_property_names failed", nullptr);
623     uint32_t length = 0;
624     status = napi_get_array_length(env, keys, &length);
625     ASSERT(status == napi_ok, "napi_get_array_length failed", nullptr);
626     std::vector<napi_property_descriptor> descriptors;
627     // keysHold guarantees that the string address is valid before create the sendable object.
628     std::vector<std::string> keysHold(length, "");
629     for (uint32_t i = 0; i < length; ++i) {
630         napi_value key = nullptr;
631         status = napi_get_element(env, keys, i, &key);
632         ASSERT(status == napi_ok, "napi_get_element failed", nullptr);
633         JSUtils::Convert2Value(env, key, keysHold[i]);
634         napi_value value = nullptr;
635         status = napi_get_named_property(env, sendableValue, keysHold[i].c_str(), &value);
636         ASSERT(status == napi_ok, "napi_get_named_property failed", nullptr);
637         descriptors.emplace_back(DECLARE_JS_PROPERTY(env, keysHold[i].c_str(), value));
638     }
639     napi_value jsObject = nullptr;
640     status = napi_create_object_with_properties(env, &jsObject, descriptors.size(), descriptors.data());
641     ASSERT(status == napi_ok, "napi_create_object_with_properties failed", nullptr);
642     return jsObject;
643 }
644 
ToJsArray(napi_env env,napi_value sendableValue)645 napi_value JSUtils::ToJsArray(napi_env env, napi_value sendableValue)
646 {
647     LOG_DEBUG("sendableArray -> jsArray");
648     uint32_t arrLen = 0;
649     napi_status status = napi_get_array_length(env, sendableValue, &arrLen);
650     ASSERT(status == napi_ok, "napi_get_array_length failed", nullptr);
651     napi_value jsArray = nullptr;
652     status = napi_create_array_with_length(env, arrLen, &jsArray);
653     ASSERT(status == napi_ok, "napi_create_array_with_length failed", nullptr);
654     for (size_t i = 0; i < arrLen; ++i) {
655         napi_value element;
656         status = napi_get_element(env, sendableValue, i, &element);
657         ASSERT(status == napi_ok, "napi_get_element failed", nullptr);
658         status = napi_set_element(env, jsArray, i, Convert2JSValue(env, element));
659         ASSERT(status == napi_ok, "napi_set_element failed", nullptr);
660     }
661     return jsArray;
662 }
663 
ToJsTypedArray(napi_env env,napi_value sendableValue)664 napi_value JSUtils::ToJsTypedArray(napi_env env, napi_value sendableValue)
665 {
666     LOG_DEBUG("sendableTypedArray -> jsTypedArray");
667     napi_typedarray_type type;
668     size_t length = 0;
669     void *tmp = nullptr;
670     napi_status status = napi_get_typedarray_info(env, sendableValue, &type, &length, &tmp, nullptr, nullptr);
671     ASSERT(status == napi_ok, "napi_get_typedarray_info failed", nullptr);
672 
673     if (type != napi_uint8_array && type != napi_float32_array) {
674         LOG_ERROR("Type is invalid %{public}d", type);
675         return nullptr;
676     }
677     napi_value jsTypedArray = nullptr;
678     void *native = nullptr;
679     napi_value buffer = nullptr;
680     status = napi_create_arraybuffer(env, length, (void **)&native, &buffer);
681     ASSERT(status == napi_ok, "napi_create_arraybuffer failed", nullptr);
682     if (length > 0) {
683         errno_t result = memcpy_s(native, length, tmp, length);
684         if (result != EOK) {
685             LOG_ERROR("memcpy_s failed, result is %{public}d", result);
686             return nullptr;
687         }
688     }
689     auto size = (type == napi_uint8_array) ? length : length / sizeof(float);
690     status = napi_create_typedarray(env, type, size, buffer, 0, &jsTypedArray);
691     ASSERT(status == napi_ok, "napi_create_typedarray failed", nullptr);
692     return jsTypedArray;
693 }
694 
Convert2JSValue(napi_env env,napi_value sendableValue)695 napi_value JSUtils::Convert2JSValue(napi_env env, napi_value sendableValue)
696 {
697     napi_valuetype type = napi_undefined;
698     napi_status status = napi_typeof(env, sendableValue, &type);
699     ASSERT(status == napi_ok, "napi_typeof failed", nullptr);
700     if (type != napi_object) {
701         return sendableValue;
702     }
703     bool result = false;
704     status = napi_is_sendable(env, sendableValue, &result);
705     ASSERT(status == napi_ok, "napi_is_sendable failed", nullptr);
706     if (!result) {
707         return sendableValue;
708     }
709 
710     status = napi_is_array(env, sendableValue, &result);
711     ASSERT(status == napi_ok, "napi_is_array failed", nullptr);
712     if (result) {
713         return ToJsArray(env, sendableValue);
714     }
715     status = napi_is_typedarray(env, sendableValue, &result);
716     ASSERT(status == napi_ok, "napi_is_typedarray failed", nullptr);
717     if (result) {
718         return ToJsTypedArray(env, sendableValue);
719     }
720     return ToJsObject(env, sendableValue);
721 }
722 } // namespace AppDataMgrJsKit
723 } // namespace OHOS