• 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 #define LOG_TAG "JSUtil"
16 #include "js_util.h"
17 #include <endian.h>
18 #include <securec.h>
19 #include "ability.h"
20 #include "hap_module_info.h"
21 #include "js_schema.h"
22 #include "kv_utils.h"
23 #include "log_print.h"
24 #include "napi_base_context.h"
25 #include "napi_queue.h"
26 #include "types.h"
27 
28 using namespace OHOS::DistributedKv;
29 using namespace OHOS::DataShare;
30 namespace OHOS::DistributedData {
31 constexpr int32_t STR_MAX_LENGTH = 4096;
32 constexpr size_t STR_TAIL_LENGTH = 1;
33 struct PredicatesProxy {
34     std::shared_ptr<DataShareAbsPredicates> predicates_;
35 };
36 
GetValue(napi_env env,napi_value in,napi_value & out)37 napi_status JSUtil::GetValue(napi_env env, napi_value in, napi_value& out)
38 {
39     out = in;
40     return napi_ok;
41 }
42 
SetValue(napi_env env,napi_value in,napi_value & out)43 napi_status JSUtil::SetValue(napi_env env, napi_value in, napi_value& out)
44 {
45     out = in;
46     return napi_ok;
47 }
48 
49 /* napi_value <-> bool */
GetValue(napi_env env,napi_value in,bool & out)50 napi_status JSUtil::GetValue(napi_env env, napi_value in, bool& out)
51 {
52     return napi_get_value_bool(env, in, &out);
53 }
54 
SetValue(napi_env env,const bool & in,napi_value & out)55 napi_status JSUtil::SetValue(napi_env env, const bool& in, napi_value& out)
56 {
57     return napi_get_boolean(env, in, &out);
58 }
59 
60 /* napi_value <-> int32_t */
GetValue(napi_env env,napi_value in,int32_t & out)61 napi_status JSUtil::GetValue(napi_env env, napi_value in, int32_t& out)
62 {
63     return napi_get_value_int32(env, in, &out);
64 }
65 
SetValue(napi_env env,const int32_t & in,napi_value & out)66 napi_status JSUtil::SetValue(napi_env env, const int32_t& in, napi_value& out)
67 {
68     return napi_create_int32(env, in, &out);
69 }
70 
71 /* napi_value <-> uint32_t */
GetValue(napi_env env,napi_value in,uint32_t & out)72 napi_status JSUtil::GetValue(napi_env env, napi_value in, uint32_t& out)
73 {
74     return napi_get_value_uint32(env, in, &out);
75 }
76 
SetValue(napi_env env,const uint32_t & in,napi_value & out)77 napi_status JSUtil::SetValue(napi_env env, const uint32_t& in, napi_value& out)
78 {
79     return napi_create_uint32(env, in, &out);
80 }
81 
82 /* napi_value <-> int64_t */
GetValue(napi_env env,napi_value in,int64_t & out)83 napi_status JSUtil::GetValue(napi_env env, napi_value in, int64_t& out)
84 {
85     return napi_get_value_int64(env, in, &out);
86 }
87 
SetValue(napi_env env,const int64_t & in,napi_value & out)88 napi_status JSUtil::SetValue(napi_env env, const int64_t& in, napi_value& out)
89 {
90     return napi_create_int64(env, in, &out);
91 }
92 
93 /* napi_value <-> double */
GetValue(napi_env env,napi_value in,double & out)94 napi_status JSUtil::GetValue(napi_env env, napi_value in, double& out)
95 {
96     return napi_get_value_double(env, in, &out);
97 }
98 
SetValue(napi_env env,const double & in,napi_value & out)99 napi_status JSUtil::SetValue(napi_env env, const double& in, napi_value& out)
100 {
101     return napi_create_double(env, in, &out);
102 }
103 
104 /* napi_value <-> std::string */
GetValue(napi_env env,napi_value in,std::string & out)105 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::string& out)
106 {
107     napi_valuetype type = napi_undefined;
108     napi_status status = napi_typeof(env, in, &type);
109     CHECK_RETURN((status == napi_ok) && (type == napi_string), "invalid type", napi_invalid_arg);
110 
111     size_t maxLen = STR_MAX_LENGTH;
112     status = napi_get_value_string_utf8(env, in, NULL, 0, &maxLen);
113     if (maxLen <= 0) {
114         return status;
115     }
116     ZLOGD("napi_value -> std::string get length %{public}d", (int)maxLen);
117     char* buf = new (std::nothrow) char[maxLen + STR_TAIL_LENGTH];
118     if (buf != nullptr) {
119         size_t len = 0;
120         status = napi_get_value_string_utf8(env, in, buf, maxLen + STR_TAIL_LENGTH, &len);
121         if (status == napi_ok) {
122             buf[len] = 0;
123             out = std::string(buf);
124         }
125         delete[] buf;
126     } else {
127         status = napi_generic_failure;
128     }
129     return status;
130 }
131 
SetValue(napi_env env,const std::string & in,napi_value & out)132 napi_status JSUtil::SetValue(napi_env env, const std::string& in, napi_value& out)
133 {
134     return napi_create_string_utf8(env, in.c_str(), in.size(), &out);
135 }
136 
137 /* napi_value <-> std::vector<std::string> */
GetValue(napi_env env,napi_value in,std::vector<std::string> & out)138 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<std::string>& out)
139 {
140     ZLOGD("napi_value -> std::vector<std::string>");
141     out.clear();
142     bool isArray = false;
143     napi_is_array(env, in, &isArray);
144     CHECK_RETURN(isArray, "not an array", napi_invalid_arg);
145 
146     uint32_t length = 0;
147     napi_status status = napi_get_array_length(env, in, &length);
148     CHECK_RETURN((status == napi_ok) && (length > 0), "get_array failed!", napi_invalid_arg);
149     for (uint32_t i = 0; i < length; ++i) {
150         napi_value item = nullptr;
151         status = napi_get_element(env, in, i, &item);
152         CHECK_RETURN((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg);
153         std::string value;
154         status = GetValue(env, item, value);
155         CHECK_RETURN(status == napi_ok, "not a string", napi_invalid_arg);
156         out.push_back(value);
157     }
158     return status;
159 }
160 
SetValue(napi_env env,const std::vector<std::string> & in,napi_value & out)161 napi_status JSUtil::SetValue(napi_env env, const std::vector<std::string>& in, napi_value& out)
162 {
163     ZLOGD("napi_value <- std::vector<std::string>");
164     napi_status status = napi_create_array_with_length(env, in.size(), &out);
165     CHECK_RETURN(status == napi_ok, "create array failed!", status);
166     int index = 0;
167     for (auto& item : in) {
168         napi_value element = nullptr;
169         SetValue(env, item, element);
170         status = napi_set_element(env, out, index++, element);
171         CHECK_RETURN((status == napi_ok), "napi_set_element failed!", status);
172     }
173     return status;
174 }
175 
Blob2VariantValue(const DistributedKv::Blob & blob)176 JSUtil::KvStoreVariant JSUtil::Blob2VariantValue(const DistributedKv::Blob& blob)
177 {
178     auto& data = blob.Data();
179     // number 2 means: valid Blob must have more than 2 bytes.
180     if (data.size() < 1) {
181         ZLOGE("Blob have no data!");
182         return JSUtil::KvStoreVariant();
183     }
184     // number 1 means: skip the first byte, byte[0] is real data type.
185     std::vector<uint8_t> real(data.begin() + 1, data.end());
186     ZLOGD("Blob::type %{public}d size=%{public}d", static_cast<int>(data[0]), static_cast<int>(real.size()));
187     if (data[0] == JSUtil::INTEGER) {
188         uint32_t tmp = be32toh(*reinterpret_cast<uint32_t*>(&(real[0])));
189         return JSUtil::KvStoreVariant(static_cast<int32_t>(tmp));
190     } else if (data[0] == JSUtil::FLOAT) {
191         uint32_t tmp = be32toh(*reinterpret_cast<uint32_t*>(&(real[0])));
192         return JSUtil::KvStoreVariant(*reinterpret_cast<float*>((void*)(&tmp)));
193     } else if (data[0] == JSUtil::BYTE_ARRAY) {
194         return JSUtil::KvStoreVariant(std::vector<uint8_t>(real.begin(), real.end()));
195     } else if (data[0] == JSUtil::BOOLEAN) {
196         return JSUtil::KvStoreVariant(static_cast<bool>(real[0]));
197     } else if (data[0] == JSUtil::DOUBLE) {
198         uint64_t tmp = be64toh(*reinterpret_cast<uint64_t*>(&(real[0])));
199         return JSUtil::KvStoreVariant(*reinterpret_cast<double*>((void*)(&tmp)));
200     } else if (data[0] == JSUtil::STRING){
201         return JSUtil::KvStoreVariant(std::string(real.begin(), real.end()));
202     } else {
203         // for schema-db, if (data[0] == JSUtil::STRING), no beginning byte!
204         return JSUtil::KvStoreVariant(std::string(data.begin(), data.end()));
205     }
206 }
207 
VariantValue2Blob(const JSUtil::KvStoreVariant & value)208 DistributedKv::Blob JSUtil::VariantValue2Blob(const JSUtil::KvStoreVariant& value)
209 {
210     std::vector<uint8_t> data;
211     auto strValue = std::get_if<std::string>(&value);
212     if (strValue != nullptr) {
213         data.push_back(JSUtil::STRING);
214         data.insert(data.end(), (*strValue).begin(), (*strValue).end());
215     }
216     auto u8ArrayValue = std::get_if<std::vector<uint8_t>>(&value);
217     if (u8ArrayValue != nullptr) {
218         data.push_back(JSUtil::BYTE_ARRAY);
219         data.insert(data.end(), (*u8ArrayValue).begin(), (*u8ArrayValue).end());
220     }
221     auto boolValue = std::get_if<bool>(&value);
222     if (boolValue != nullptr) {
223         data.push_back(JSUtil::BOOLEAN);
224         data.push_back(static_cast<uint8_t>(*boolValue));
225     }
226     uint8_t *res = nullptr;
227     auto intValue = std::get_if<int32_t>(&value);
228     if (intValue != nullptr) {
229         uint32_t tmp = static_cast<uint32_t>(*intValue); // copy value, and make it available in stack space.
230         tmp = htobe32(tmp);
231         res = reinterpret_cast<uint8_t*>(&tmp);
232         data.push_back(JSUtil::INTEGER);
233         data.insert(data.end(), res, res + sizeof(int32_t) / sizeof(uint8_t));
234     }
235     auto fltValue = std::get_if<float>(&value);
236     if (fltValue != nullptr) {
237         float tmp = *fltValue; // copy value, and make it available in stack space.
238         uint32_t tmp32 = htobe32(*reinterpret_cast<uint32_t*>(&tmp));
239         res = reinterpret_cast<uint8_t*>(&tmp32);
240         data.push_back(JSUtil::FLOAT);
241         data.insert(data.end(), res, res + sizeof(float) / sizeof(uint8_t));
242     }
243     auto dblValue = std::get_if<double>(&value);
244     if (dblValue != nullptr) {
245         double tmp = *dblValue; // copy value, and make it available in stack space.
246         uint64_t tmp64 = htobe64(*reinterpret_cast<uint64_t*>(&tmp));
247         res = reinterpret_cast<uint8_t*>(&tmp64);
248         data.push_back(JSUtil::DOUBLE);
249         data.insert(data.end(), res, res + sizeof(double) / sizeof(uint8_t));
250     }
251     return DistributedKv::Blob(data);
252 }
253 
254 /* napi_value <-> KvStoreVariant */
GetValue(napi_env env,napi_value in,JSUtil::KvStoreVariant & out)255 napi_status JSUtil::GetValue(napi_env env, napi_value in, JSUtil::KvStoreVariant& out)
256 {
257     napi_valuetype type = napi_undefined;
258     napi_status status = napi_typeof(env, in, &type);
259     CHECK_RETURN((status == napi_ok), "invalid type", status);
260     switch (type) {
261         case napi_boolean: {
262             bool vBool = false;
263             status = JSUtil::GetValue(env, in, vBool);
264             out = vBool;
265             break;
266         }
267         case napi_number: {
268             double vNum = 0.0;
269             status = JSUtil::GetValue(env, in, vNum);
270             out = vNum;
271             break;
272         }
273         case napi_string: {
274             std::string vString;
275             status = JSUtil::GetValue(env, in, vString);
276             out = vString;
277             break;
278         }
279         case napi_object: {
280             std::vector<uint8_t> vct;
281             status = JSUtil::GetValue(env, in, vct);
282             out = vct;
283             break;
284         }
285         default:
286             ZLOGE("napi_value -> KvStoreVariant not [Uint8Array | string | boolean | number] type=%{public}d", type);
287             status = napi_invalid_arg;
288             break;
289     }
290     return status;
291 }
292 
SetValue(napi_env env,const JSUtil::KvStoreVariant & in,napi_value & out)293 napi_status JSUtil::SetValue(napi_env env, const JSUtil::KvStoreVariant& in, napi_value& out)
294 {
295     auto strValue = std::get_if<std::string>(&in);
296     if (strValue != nullptr) {
297         return SetValue(env, *strValue, out);
298     }
299     auto intValue = std::get_if<int32_t>(&in);
300     if (intValue != nullptr) {
301         return SetValue(env, *intValue, out);
302     }
303     auto fltValue = std::get_if<float>(&in);
304     if (fltValue != nullptr) {
305         return SetValue(env, *fltValue, out);
306     }
307     auto pUint8 = std::get_if<std::vector<uint8_t>>(&in);
308     if (pUint8 != nullptr) {
309         return SetValue(env, *pUint8, out);
310     }
311     auto boolValue = std::get_if<bool>(&in);
312     if (boolValue != nullptr) {
313         return SetValue(env, *boolValue, out);
314     }
315     auto dblValue = std::get_if<double>(&in);
316     if (dblValue != nullptr) {
317         return SetValue(env, *dblValue, out);
318     }
319 
320     ZLOGE("napi_value <- KvStoreVariant  INVALID value type");
321     return napi_invalid_arg;
322 }
323 
324 /* napi_value <-> QueryVariant */
GetValue(napi_env env,napi_value in,JSUtil::QueryVariant & out)325 napi_status JSUtil::GetValue(napi_env env, napi_value in, JSUtil::QueryVariant& out)
326 {
327     napi_valuetype type = napi_undefined;
328     napi_status status = napi_typeof(env, in, &type);
329     CHECK_RETURN((status == napi_ok), "invalid type", status);
330     ZLOGD("napi_value -> QueryVariant  type=%{public}d", type);
331     switch (type) {
332         case napi_boolean: {
333             bool vBool = false;
334             status = JSUtil::GetValue(env, in, vBool);
335             out = vBool;
336             break;
337         }
338         case napi_number: {
339             double vNum = 0.0;
340             status = JSUtil::GetValue(env, in, vNum);
341             out = vNum;
342             break;
343         }
344         case napi_string: {
345             std::string vString;
346             status = JSUtil::GetValue(env, in, vString);
347             out = vString;
348             break;
349         }
350         default:
351             status = napi_invalid_arg;
352             break;
353     }
354     CHECK_RETURN((status == napi_ok), "napi_value -> QueryVariant bad value!", status);
355     return status;
356 }
357 
SetValue(napi_env env,const JSUtil::QueryVariant & in,napi_value & out)358 napi_status JSUtil::SetValue(napi_env env, const JSUtil::QueryVariant& in, napi_value& out)
359 {
360     ZLOGD("napi_value <- QueryVariant ");
361     napi_status status = napi_invalid_arg;
362     auto strValue = std::get_if<std::string>(&in);
363     if (strValue != nullptr) {
364         status = SetValue(env, *strValue, out);
365     }
366     auto boolValue = std::get_if<bool>(&in);
367     if (boolValue != nullptr) {
368         status = SetValue(env, *boolValue, out);
369     }
370     auto dblValue = std::get_if<double>(&in);
371     if (dblValue != nullptr) {
372         status = SetValue(env, *dblValue, out);
373     } else {
374         ZLOGD("napi_value <- QueryVariant  INVALID value type");
375     }
376     return status;
377 }
378 
379 /* napi_value <-> std::vector<uint8_t> */
GetValue(napi_env env,napi_value in,std::vector<uint8_t> & out)380 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<uint8_t>& out)
381 {
382     out.clear();
383     ZLOGD("napi_value -> std::vector<uint8_t> ");
384     napi_typedarray_type type = napi_biguint64_array;
385     size_t length = 0;
386     napi_value buffer = nullptr;
387     size_t offset = 0;
388     void* data = nullptr;
389     napi_status status = napi_get_typedarray_info(env, in, &type, &length, &data, &buffer, &offset);
390     ZLOGD("array type=%{public}d length=%{public}d offset=%{public}d", (int)type, (int)length, (int)offset);
391     CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
392     CHECK_RETURN(type == napi_uint8_array, "is not Uint8Array!", napi_invalid_arg);
393     CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
394     out.assign((uint8_t*)data, ((uint8_t*)data) + length);
395     return status;
396 }
397 
SetValue(napi_env env,const std::vector<uint8_t> & in,napi_value & out)398 napi_status JSUtil::SetValue(napi_env env, const std::vector<uint8_t>& in, napi_value& out)
399 {
400     ZLOGD("napi_value <- std::vector<uint8_t> ");
401     CHECK_RETURN(in.size() > 0, "invalid std::vector<uint8_t>", napi_invalid_arg);
402     void* data = nullptr;
403     napi_value buffer = nullptr;
404     napi_status status = napi_create_arraybuffer(env, in.size(), &data, &buffer);
405     CHECK_RETURN((status == napi_ok), "create array buffer failed!", status);
406 
407     if (memcpy_s(data, in.size(), in.data(), in.size()) != EOK) {
408         ZLOGE("napi_value <- std::vector<uint8_t>: memcpy_s failed, vector size:%{public}zd", in.size());
409         return napi_invalid_arg;
410     }
411     status = napi_create_typedarray(env, napi_uint8_array, in.size(), buffer, 0, &out);
412     CHECK_RETURN((status == napi_ok), "napi_value <- std::vector<uint8_t> invalid value", status);
413     return status;
414 }
415 
416 template <typename T>
TypedArray2Vector(uint8_t * data,size_t length,napi_typedarray_type type,std::vector<T> & out)417 void TypedArray2Vector(uint8_t* data, size_t length, napi_typedarray_type type, std::vector<T>& out)
418 {
419     auto convert = [&out](auto* data, size_t elements) {
420         for (size_t index = 0; index < elements; index++) {
421             out.push_back(static_cast<T>(data[index]));
422         }
423     };
424 
425     switch (type) {
426         case napi_int8_array:
427             convert(reinterpret_cast<int8_t*>(data), length);
428             break;
429         case napi_uint8_array:
430             convert(data, length);
431             break;
432         case napi_uint8_clamped_array:
433             convert(data, length);
434             break;
435         case napi_int16_array:
436             convert(reinterpret_cast<int16_t*>(data), length / sizeof(int16_t));
437             break;
438         case napi_uint16_array:
439             convert(reinterpret_cast<uint16_t*>(data), length / sizeof(uint16_t));
440             break;
441         case napi_int32_array:
442             convert(reinterpret_cast<int32_t*>(data), length / sizeof(int32_t));
443             break;
444         case napi_uint32_array:
445             convert(reinterpret_cast<uint32_t*>(data), length / sizeof(uint32_t));
446             break;
447         case napi_float32_array:
448             convert(reinterpret_cast<float*>(data), length / sizeof(float));
449             break;
450         case napi_float64_array:
451             convert(reinterpret_cast<double*>(data), length / sizeof(double));
452             break;
453         case napi_bigint64_array:
454             convert(reinterpret_cast<int64_t*>(data), length / sizeof(int64_t));
455             break;
456         case napi_biguint64_array:
457             convert(reinterpret_cast<uint64_t*>(data), length / sizeof(uint64_t));
458             break;
459         default:
460             CHECK_RETURN_VOID(false, "[FATAL] invalid napi_typedarray_type!");
461     }
462 }
463 
464 /* napi_value <-> std::vector<int32_t> */
GetValue(napi_env env,napi_value in,std::vector<int32_t> & out)465 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<int32_t>& out)
466 {
467     out.clear();
468     ZLOGD("napi_value -> std::vector<int32_t> ");
469     napi_typedarray_type type = napi_biguint64_array;
470     size_t length = 0;
471     napi_value buffer = nullptr;
472     size_t offset = 0;
473     uint8_t* data = nullptr;
474     napi_status status = napi_get_typedarray_info(env, in, &type, &length,
475                                                   reinterpret_cast<void**>(&data), &buffer, &offset);
476     ZLOGD("array type=%{public}d length=%{public}d offset=%{public}d", (int)type, (int)length, (int)offset);
477     CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
478     CHECK_RETURN(type <= napi_int32_array, "is not int32 supported typed array!", napi_invalid_arg);
479     CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
480     TypedArray2Vector<int32_t>(data, length, type, out);
481     return status;
482 }
483 
SetValue(napi_env env,const std::vector<int32_t> & in,napi_value & out)484 napi_status JSUtil::SetValue(napi_env env, const std::vector<int32_t>& in, napi_value& out)
485 {
486     ZLOGD("napi_value <- std::vector<int32_t> ");
487     size_t bytes = in.size() * sizeof(int32_t);
488     CHECK_RETURN(bytes > 0, "invalid std::vector<int32_t>", napi_invalid_arg);
489     void* data = nullptr;
490     napi_value buffer = nullptr;
491     napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer);
492     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
493 
494     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
495         ZLOGE("napi_value <- std::vector<int32_t>: memcpy_s failed, vector size:%{public}zd", in.size());
496         return napi_invalid_arg;
497     }
498     status = napi_create_typedarray(env, napi_int32_array, in.size(), buffer, 0, &out);
499     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
500     return status;
501 }
502 
503 /* napi_value <-> std::vector<uint32_t> */
GetValue(napi_env env,napi_value in,std::vector<uint32_t> & out)504 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<uint32_t>& out)
505 {
506     out.clear();
507     ZLOGD("napi_value -> std::vector<uint32_t> ");
508     napi_typedarray_type type = napi_biguint64_array;
509     size_t length = 0;
510     napi_value buffer = nullptr;
511     size_t offset = 0;
512     uint8_t* data = nullptr;
513     napi_status status = napi_get_typedarray_info(env, in, &type, &length,
514                                                   reinterpret_cast<void**>(&data), &buffer, &offset);
515     ZLOGD("napi_get_typedarray_info type=%{public}d", (int)type);
516     CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
517     CHECK_RETURN((type <= napi_uint16_array) || (type == napi_uint32_array), "invalid type!", napi_invalid_arg);
518     CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
519     TypedArray2Vector<uint32_t>(data, length, type, out);
520     return status;
521 }
522 
SetValue(napi_env env,const std::vector<uint32_t> & in,napi_value & out)523 napi_status JSUtil::SetValue(napi_env env, const std::vector<uint32_t>& in, napi_value& out)
524 {
525     ZLOGD("napi_value <- std::vector<uint32_t> ");
526     size_t bytes = in.size() * sizeof(uint32_t);
527     CHECK_RETURN(bytes > 0, "invalid std::vector<uint32_t>", napi_invalid_arg);
528     void* data = nullptr;
529     napi_value buffer = nullptr;
530     napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer);
531     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
532 
533     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
534         ZLOGE("napi_value <- std::vector<uint32_t>: memcpy_s failed, vector size:%{public}zd", in.size());
535         return napi_invalid_arg;
536     }
537     status = napi_create_typedarray(env, napi_uint32_array, in.size(), buffer, 0, &out);
538     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
539     return status;
540 }
541 
542 /* napi_value <-> std::vector<int64_t> */
GetValue(napi_env env,napi_value in,std::vector<int64_t> & out)543 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<int64_t>& out)
544 {
545     out.clear();
546     ZLOGD("napi_value -> std::vector<int64_t> ");
547     napi_typedarray_type type = napi_biguint64_array;
548     size_t length = 0;
549     napi_value buffer = nullptr;
550     size_t offset = 0;
551     uint8_t* data = nullptr;
552     napi_status status = napi_get_typedarray_info(env, in, &type, &length,
553                                                   reinterpret_cast<void**>(&data), &buffer, &offset);
554     ZLOGD("array type=%{public}d length=%{public}d offset=%{public}d", (int)type, (int)length, (int)offset);
555     CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
556     CHECK_RETURN((type <= napi_uint32_array) || (type == napi_bigint64_array), "invalid type!", napi_invalid_arg);
557     CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
558     TypedArray2Vector<int64_t>(data, length, type, out);
559     return status;
560 }
561 
SetValue(napi_env env,const std::vector<int64_t> & in,napi_value & out)562 napi_status JSUtil::SetValue(napi_env env, const std::vector<int64_t>& in, napi_value& out)
563 {
564     ZLOGD("napi_value <- std::vector<int64_t> ");
565     size_t bytes = in.size() * sizeof(int64_t);
566     CHECK_RETURN(bytes > 0, "invalid std::vector<uint32_t>", napi_invalid_arg);
567     void* data = nullptr;
568     napi_value buffer = nullptr;
569     napi_status status = napi_create_arraybuffer(env, bytes, &data, &buffer);
570     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
571 
572     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
573         ZLOGE("napi_value <- std::vector<int64_t>: memcpy_s failed, vector size:%{public}zd", in.size());
574         return napi_invalid_arg;
575     }
576     status = napi_create_typedarray(env, napi_bigint64_array, in.size(), buffer, 0, &out);
577     CHECK_RETURN((status == napi_ok), "invalid buffer", status);
578     return status;
579 }
580 /* napi_value <-> std::vector<double> */
GetValue(napi_env env,napi_value in,std::vector<double> & out)581 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<double>& out)
582 {
583     out.clear();
584     bool isTypedArray = false;
585     napi_status status = napi_is_typedarray(env, in, &isTypedArray);
586     ZLOGD("napi_value -> std::vector<double> input %{public}s a TypedArray", isTypedArray ? "is" : "is not");
587     CHECK_RETURN((status == napi_ok), "napi_is_typedarray failed!", status);
588     if (isTypedArray) {
589         ZLOGD("napi_value -> std::vector<double> ");
590         napi_typedarray_type type = napi_biguint64_array;
591         size_t length = 0;
592         napi_value buffer = nullptr;
593         size_t offset = 0;
594         uint8_t* data = nullptr;
595         status = napi_get_typedarray_info(env, in, &type, &length, reinterpret_cast<void**>(&data), &buffer, &offset);
596         ZLOGD("napi_get_typedarray_info status=%{public}d type=%{public}d", status, (int)type);
597         CHECK_RETURN(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
598         CHECK_RETURN((length > 0) && (data != nullptr), "invalid data!", napi_invalid_arg);
599         TypedArray2Vector<double>(data, length, type, out);
600     } else {
601         bool isArray = false;
602         status = napi_is_array(env, in, &isArray);
603         ZLOGD("napi_value -> std::vector<double> input %{public}s an Array", isArray ? "is" : "is not");
604         CHECK_RETURN((status == napi_ok) && isArray, "invalid data!", napi_invalid_arg);
605         uint32_t length = 0;
606         status = napi_get_array_length(env, in, &length);
607         CHECK_RETURN((status == napi_ok) && (length > 0), "invalid data!", napi_invalid_arg);
608         for (uint32_t i = 0; i < length; ++i) {
609             napi_value item = nullptr;
610             status = napi_get_element(env, in, i, &item);
611             CHECK_RETURN((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg);
612             double vi = 0.0;
613             status = napi_get_value_double(env, item, &vi);
614             CHECK_RETURN(status == napi_ok, "element is not a double", napi_invalid_arg);
615             out.push_back(vi);
616         }
617     }
618     return status;
619 }
620 
SetValue(napi_env env,const std::vector<double> & in,napi_value & out)621 napi_status JSUtil::SetValue(napi_env env, const std::vector<double>& in, napi_value& out)
622 {
623     ZLOGD("napi_value <- std::vector<double> ");
624     (void)(env);
625     (void)(in);
626     (void)(out);
627     CHECK_RETURN(false, "std::vector<double> to napi_value, unsupported!", napi_invalid_arg);
628     return napi_invalid_arg;
629 }
630 
631 /* napi_value <-> std::map<std::string, int32_t> */
GetValue(napi_env env,napi_value in,std::map<std::string,DistributedKv::Status> & out)632 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::map<std::string, DistributedKv::Status>& out)
633 {
634     ZLOGD("napi_value -> std::map<std::string, int32_t> ");
635     (void)(env);
636     (void)(in);
637     (void)(out);
638     CHECK_RETURN(false, "std::map<std::string, uint32_t> from napi_value, unsupported!", napi_invalid_arg);
639     return napi_invalid_arg;
640 }
641 
SetValue(napi_env env,const std::map<std::string,DistributedKv::Status> & in,napi_value & out)642 napi_status JSUtil::SetValue(napi_env env, const std::map<std::string, DistributedKv::Status>& in, napi_value& out)
643 {
644     ZLOGD("napi_value <- std::map<std::string, int32_t> ");
645     napi_status status = napi_create_array_with_length(env, in.size(), &out);
646     CHECK_RETURN((status == napi_ok), "invalid object", status);
647     int index = 0;
648     for (const auto& [key, value] : in) {
649         napi_value element = nullptr;
650         napi_create_array_with_length(env, TUPLE_SIZE, &element);
651         napi_value jsKey = nullptr;
652         napi_create_string_utf8(env, key.c_str(), key.size(), &jsKey);
653         napi_set_element(env, element, TUPLE_KEY, jsKey);
654         napi_value jsValue = nullptr;
655         napi_create_int32(env, static_cast<int32_t>(value), &jsValue);
656         napi_set_element(env, element, TUPLE_VALUE, jsValue);
657         napi_set_element(env, out, index++, element);
658     }
659     return status;
660 }
661 
662 /*
663  *  interface Value {
664  *       type: ValueType;
665  *       value: Uint8Array | string | number | boolean;
666  *   }
667  *    interface Entry {
668  *        key: string;
669  *        value: Value;
670  *  }
671  */
672 /* napi_value <-> DistributedKv::Entry */
GetValue(napi_env env,napi_value in,DistributedKv::Entry & out,bool hasSchema)673 napi_status JSUtil::GetValue(napi_env env, napi_value in, DistributedKv::Entry& out, bool hasSchema)
674 {
675     ZLOGD("napi_value -> DistributedKv::Entry ");
676     napi_value propKey = nullptr;
677     napi_status status = napi_get_named_property(env, in, "key", &propKey);
678     CHECK_RETURN((status == napi_ok), "no property key", status);
679     std::string key;
680     status = GetValue(env, propKey, key);
681     CHECK_RETURN((status == napi_ok), "no value of key", status);
682 
683     napi_value propValue = nullptr;
684     status = napi_get_named_property(env, in, "value", &propValue);
685     CHECK_RETURN((status == napi_ok), "no property value", status);
686 
687     napi_value propVType = nullptr;
688     status = napi_get_named_property(env, propValue, "type", &propVType);
689     CHECK_RETURN((status == napi_ok), "no property value.type", status);
690     int32_t type = 0;
691     status = GetValue(env, propVType, type);
692     CHECK_RETURN((status == napi_ok), "no value of value.type", status);
693 
694     napi_value propVValue = nullptr;
695     status = napi_get_named_property(env, propValue, "value", &propVValue);
696     CHECK_RETURN((status == napi_ok), "no property value.value", status);
697     KvStoreVariant value = 0;
698     status = GetValue(env, propVValue, value);
699     CHECK_RETURN((status == napi_ok), "no value of value.value", status);
700 
701     out.key = key;
702     if (hasSchema) {
703         out.value = std::get<std::string>(value);
704     } else {
705         out.value = JSUtil::VariantValue2Blob(value);
706     }
707     if (type != out.value[0]) {
708         ZLOGE("unmatch type[%{public}d] to value.type[%{public}d]", (int)type, (int)out.value[0]);
709     }
710     return status;
711 }
712 
SetValue(napi_env env,const DistributedKv::Entry & in,napi_value & out,bool hasSchema)713 napi_status JSUtil::SetValue(napi_env env, const DistributedKv::Entry& in, napi_value& out, bool hasSchema)
714 {
715     ZLOGD("napi_value <- DistributedKv::Entry ");
716     napi_status status = napi_create_object(env, &out);
717     CHECK_RETURN((status == napi_ok), "invalid entry object", status);
718 
719     napi_value key = nullptr;
720     status = SetValue(env, in.key.ToString(), key);
721     CHECK_RETURN((status == napi_ok), "invalid entry key", status);
722     napi_set_named_property(env, out, "key", key);
723 
724     CHECK_RETURN((in.value.Size() > 0), "invalid entry value", status);
725     napi_value value = nullptr;
726 
727     status = napi_create_object(env, &value);
728     CHECK_RETURN((status == napi_ok), "invalid value object", status);
729     napi_value vType = nullptr;
730     napi_create_int32(env, in.value[0], &vType);
731     napi_set_named_property(env, value, "type", vType);
732 
733     napi_value vValue = nullptr;
734     if (hasSchema) {
735         status = SetValue(env, in.value.ToString(), vValue);
736     } else {
737         status = SetValue(env, Blob2VariantValue(in.value), vValue);
738     }
739     CHECK_RETURN((status == napi_ok), "invalid entry value", status);
740     napi_set_named_property(env, value, "value", vValue);
741 
742     napi_set_named_property(env, out, "value", value);
743     return status;
744 }
745 
746 /* napi_value <-> std::list<DistributedKv::Entry> */
GetValue(napi_env env,napi_value in,std::list<DistributedKv::Entry> & out,bool hasSchema)747 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::list<DistributedKv::Entry>& out, bool hasSchema)
748 {
749     ZLOGD("napi_value -> std::list<DistributedKv::Entry> ");
750     bool isArray = false;
751     napi_is_array(env, in, &isArray);
752     CHECK_RETURN(isArray, "not array", napi_invalid_arg);
753 
754     uint32_t length = 0;
755     napi_status status = napi_get_array_length(env, in, &length);
756     CHECK_RETURN((status == napi_ok) && (length > 0), "get_array failed!", status);
757     for (uint32_t i = 0; i < length; ++i) {
758         napi_value item = nullptr;
759         status = napi_get_element(env, in, i, &item);
760         CHECK_RETURN((status == napi_ok), "no element", status);
761         if ((status != napi_ok) || (item == nullptr)) {
762             continue;
763         }
764         DistributedKv::Entry entry;
765         status = GetValue(env, item, entry, hasSchema);
766         out.push_back(entry);
767     }
768     return status;
769 }
770 
SetValue(napi_env env,const std::list<DistributedKv::Entry> & in,napi_value & out,bool hasSchema)771 napi_status JSUtil::SetValue(napi_env env, const std::list<DistributedKv::Entry>& in, napi_value& out, bool hasSchema)
772 {
773     ZLOGD("napi_value <- std::list<DistributedKv::Entry> %{public}d", static_cast<int>(in.size()));
774     napi_status status = napi_create_array_with_length(env, in.size(), &out);
775     CHECK_RETURN(status == napi_ok, "create array failed!", status);
776     int index = 0;
777     for (const auto& item : in) {
778         napi_value entry = nullptr;
779         SetValue(env, item, entry, hasSchema);
780         napi_set_element(env, out, index++, entry);
781     }
782     return status;
783 }
784 
GetValue(napi_env env,napi_value jsValue,ValueObject::Type & valueObject)785 napi_status JSUtil::GetValue(napi_env env, napi_value jsValue, ValueObject::Type &valueObject)
786 {
787     napi_valuetype type = napi_undefined;
788     napi_typeof(env, jsValue, &type);
789     if (type == napi_string) {
790         std::string value;
791         JSUtil::GetValue(env, jsValue, value);
792         valueObject = value;
793     } else if (type == napi_number) {
794         double value = 0.0;
795         napi_get_value_double(env, jsValue, &value);
796         valueObject = value;
797     } else if (type == napi_boolean) {
798         bool value = false;
799         napi_get_value_bool(env, jsValue, &value);
800         valueObject = value;
801     } else if (type == napi_object) {
802         std::vector<uint8_t> value;
803         JSUtil::GetValue(env, jsValue, value);
804         valueObject = std::move(value);
805     }
806     return napi_ok;
807 }
GetValue(napi_env env,napi_value in,std::vector<DistributedKv::Entry> & out,bool hasSchema)808 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<DistributedKv::Entry> &out, bool hasSchema)
809 {
810     out.clear();
811     ZLOGD("napi_value -> std::vector<DistributedKv::Entry> ");
812     bool isArray = false;
813     napi_is_array(env, in, &isArray);
814     CHECK_RETURN(isArray, "not array", napi_invalid_arg);
815 
816     uint32_t length = 0;
817     napi_status status = napi_get_array_length(env, in, &length);
818     CHECK_RETURN((status == napi_ok) && (length > 0), "get_array failed!", status);
819     for (uint32_t i = 0; i < length; ++i) {
820         napi_value item = nullptr;
821         status = napi_get_element(env, in, i, &item);
822         CHECK_RETURN((status == napi_ok), "no element", status);
823         if ((status != napi_ok) || (item == nullptr)) {
824             continue;
825         }
826         DistributedKv::Entry entry;
827         status = GetValue(env, item, entry, hasSchema);
828         out.push_back(entry);
829     }
830     return status;
831 }
832 
SetValue(napi_env env,const std::vector<DistributedKv::Entry> & in,napi_value & out,bool hasSchema)833 napi_status JSUtil::SetValue(napi_env env, const std::vector<DistributedKv::Entry>& in, napi_value& out, bool hasSchema)
834 {
835     ZLOGD("napi_value <- std::vector<DistributedKv::Entry> %{public}d", static_cast<int>(in.size()));
836     napi_status status = napi_create_array_with_length(env, in.size(), &out);
837     CHECK_RETURN(status == napi_ok, "create array failed!", status);
838     int index = 0;
839     for (const auto& item : in) {
840         napi_value entry = nullptr;
841         SetValue(env, item, entry, hasSchema);
842         napi_set_element(env, out, index++, entry);
843     }
844     return status;
845 }
846 
847 /* napi_value <-> std::vector<DistributedKv::StoreId> */
GetValue(napi_env env,napi_value in,std::vector<DistributedKv::StoreId> & out)848 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<DistributedKv::StoreId>& out)
849 {
850     out.clear();
851     ZLOGD("napi_value -> std::vector<DistributedKv::StoreId> ");
852     bool isArray = false;
853     napi_is_array(env, in, &isArray);
854     CHECK_RETURN(isArray, "not array", napi_invalid_arg);
855 
856     uint32_t length = 0;
857     napi_status status = napi_get_array_length(env, in, &length);
858     CHECK_RETURN((status == napi_ok) && (length > 0), "get_array failed!", status);
859     for (uint32_t i = 0; i < length; ++i) {
860         napi_value item = nullptr;
861         status = napi_get_element(env, in, i, &item);
862         CHECK_RETURN((status == napi_ok), "no element", status);
863         if ((status != napi_ok) || (item == nullptr)) {
864             continue;
865         }
866         std::string value;
867         status = GetValue(env, item, value);
868         DistributedKv::StoreId storeId { value };
869         out.push_back(storeId);
870     }
871     return status;
872 }
873 
SetValue(napi_env env,const std::vector<DistributedKv::StoreId> & in,napi_value & out)874 napi_status JSUtil::SetValue(napi_env env, const std::vector<DistributedKv::StoreId>& in, napi_value& out)
875 {
876     ZLOGD("napi_value <- std::vector<DistributedKv::StoreId>  %{public}d", static_cast<int>(in.size()));
877     napi_status status = napi_create_array_with_length(env, in.size(), &out);
878     CHECK_RETURN((status == napi_ok), "create_array failed!", status);
879     int index = 0;
880     for (const auto& item : in) {
881         napi_value entry = nullptr;
882         SetValue(env, item.storeId, entry);
883         napi_set_element(env, out, index++, entry);
884     }
885     return status;
886 }
887 
888 /* napi_value <-> DistributedKv::ChangeNotification */
GetValue(napi_env env,napi_value in,DistributedKv::ChangeNotification & out,bool hasSchema)889 napi_status JSUtil::GetValue(napi_env env, napi_value in, DistributedKv::ChangeNotification& out, bool hasSchema)
890 {
891     ZLOGD("napi_value -> DistributedKv::ChangeNotification ");
892     (void)(env);
893     (void)(in);
894     (void)(out);
895     CHECK_RETURN(false, "DistributedKv::ChangeNotification from napi_value, unsupported!", napi_invalid_arg);
896     return napi_invalid_arg;
897 }
898 
SetValue(napi_env env,const DistributedKv::ChangeNotification & in,napi_value & out,bool hasSchema)899 napi_status JSUtil::SetValue(napi_env env, const DistributedKv::ChangeNotification& in, napi_value& out, bool hasSchema)
900 {
901     ZLOGD("napi_value <- DistributedKv::ChangeNotification ");
902     napi_status status = napi_create_object(env, &out);
903     CHECK_RETURN((status == napi_ok), "napi_create_object for DistributedKv::ChangeNotification failed!", status);
904     napi_value deviceId = nullptr;
905     status = SetValue(env, in.GetDeviceId(), deviceId);
906     CHECK_RETURN((status == napi_ok) || (deviceId == nullptr), "GetDeviceId failed!", status);
907     status = napi_set_named_property(env, out, "deviceId", deviceId);
908     CHECK_RETURN((status == napi_ok), "set_named_property deviceId failed!", status);
909 
910     napi_value insertEntries = nullptr;
911     status = SetValue(env, in.GetInsertEntries(), insertEntries, hasSchema);
912     CHECK_RETURN((status == napi_ok) || (insertEntries == nullptr), "GetInsertEntries failed!", status);
913     status = napi_set_named_property(env, out, "insertEntries", insertEntries);
914     CHECK_RETURN((status == napi_ok), "set_named_property insertEntries failed!", status);
915 
916     napi_value updateEntries = nullptr;
917     status = SetValue(env, in.GetUpdateEntries(), updateEntries, hasSchema);
918     CHECK_RETURN((status == napi_ok) || (updateEntries == nullptr), "GetUpdateEntries failed!", status);
919     status = napi_set_named_property(env, out, "updateEntries", updateEntries);
920     CHECK_RETURN((status == napi_ok), "set_named_property updateEntries failed!", status);
921 
922     napi_value deleteEntries = nullptr;
923     status = SetValue(env, in.GetDeleteEntries(), deleteEntries, hasSchema);
924     CHECK_RETURN((status == napi_ok) || (deleteEntries == nullptr), "GetDeleteEntries failed!", status);
925     status = napi_set_named_property(env, out, "deleteEntries", deleteEntries);
926     CHECK_RETURN((status == napi_ok), "set_named_property deleteEntries failed!", status);
927     return status;
928 }
929 
930 /* napi_value <-> DistributedKv::Options */
GetValue(napi_env env,napi_value in,DistributedKv::Options & options)931 napi_status JSUtil::GetValue(napi_env env, napi_value in, DistributedKv::Options& options)
932 {
933     ZLOGD("napi_value -> DistributedKv::Options ");
934     napi_status status = GetNamedProperty(env, in, "createIfMissing", options.createIfMissing, true);
935     CHECK_RETURN(status == napi_ok, "get createIfMissing param failed", napi_invalid_arg);
936     status = GetNamedProperty(env, in, "encrypt", options.encrypt, true);
937     CHECK_RETURN(status == napi_ok, "get encrypt param failed", napi_invalid_arg);
938     status = GetNamedProperty(env, in, "backup", options.backup, true);
939     CHECK_RETURN(status == napi_ok, "get backup param failed", napi_invalid_arg);
940     status = GetNamedProperty(env, in, "autoSync", options.autoSync, true);
941     CHECK_RETURN(status == napi_ok, "get autoSync param failed", napi_invalid_arg);
942 
943     int32_t kvStoreType = 0;
944     status = GetNamedProperty(env, in, "kvStoreType", kvStoreType, true);
945     CHECK_RETURN(status == napi_ok, "get kvStoreType param failed", napi_invalid_arg);
946     options.kvStoreType = static_cast<DistributedKv::KvStoreType>(kvStoreType);
947 
948     JsSchema *jsSchema = nullptr;
949     std::string strSchema;
950     status = GetNamedProperty(env, in, "schema", jsSchema, true);
951     CHECK_RETURN((status == napi_ok || GetNamedProperty(env, in, "schema", strSchema, true) == napi_ok),
952         "get schema param failed", napi_invalid_arg);
953     if (status == napi_ok && jsSchema != nullptr) {
954         options.schema = jsSchema->Dump();
955     }
956 
957     int32_t level = 0;
958     status = GetNamedProperty(env, in, "securityLevel", level, true);
959     CHECK_RETURN(status == napi_ok, "get securityLevel param failed", napi_invalid_arg);
960     options.securityLevel = level;
961     return napi_ok;
962 }
963 
GetValue(napi_env env,napi_value in,DistributedKv::UserInfo & userInfo)964 napi_status JSUtil::GetValue(napi_env env, napi_value in, DistributedKv::UserInfo& userInfo)
965 {
966     napi_status status = napi_ok;
967     status = GetNamedProperty(env, in, "userId", userInfo.userId, true);
968     return status != napi_ok ? status : GetNamedProperty(env, in, "userType", userInfo.userType, true);
969 }
970 
GetValue(napi_env env,napi_value inner,JsSchema * & out)971 napi_status JSUtil::GetValue(napi_env env, napi_value inner, JsSchema*& out)
972 {
973     return JsSchema::ToJson(env, inner, out);
974 }
975 
SetValue(napi_env env,const DistributedKv::Options & in,napi_value & out)976 napi_status JSUtil::SetValue(napi_env env, const DistributedKv::Options& in, napi_value& out)
977 {
978     (void)(env);
979     (void)(in);
980     (void)(out);
981     CHECK_RETURN(false, "DistributedKv::Options to napi_value, unsupported!", napi_invalid_arg);
982     return napi_invalid_arg;
983 }
984 
DefineClass(napi_env env,const std::string & name,const napi_property_descriptor * properties,size_t count,napi_callback newcb)985 napi_value JSUtil::DefineClass(napi_env env, const std::string& name,
986     const napi_property_descriptor* properties, size_t count, napi_callback newcb)
987 {
988     // base64("data.distributeddata") as rootPropName, i.e. global.<root>
989     const std::string rootPropName = "ZGF0YS5kaXN0cmlidXRlZGRhdGE";
990     napi_value root = nullptr;
991     bool hasRoot = false;
992     napi_value global = nullptr;
993     napi_get_global(env, &global);
994     napi_has_named_property(env, global, rootPropName.c_str(), &hasRoot);
995     if (hasRoot) {
996         napi_get_named_property(env, global, rootPropName.c_str(), &root);
997     } else {
998         napi_create_object(env, &root);
999         napi_set_named_property(env, global, rootPropName.c_str(), root);
1000     }
1001 
1002     std::string propName = "constructor_of_" + name;
1003     napi_value constructor = nullptr;
1004     bool hasProp = false;
1005     napi_has_named_property(env, root, propName.c_str(), &hasProp);
1006     if (hasProp) {
1007         napi_get_named_property(env, root, propName.c_str(), &constructor);
1008         if (constructor != nullptr) {
1009             ZLOGD("got data.distributeddata.%{public}s as constructor", propName.c_str());
1010             return constructor;
1011         }
1012         hasProp = false; // no constructor.
1013     }
1014 
1015     NAPI_CALL(env, napi_define_class(env, name.c_str(), name.size(), newcb, nullptr, count, properties, &constructor));
1016     NAPI_ASSERT(env, constructor != nullptr, "napi_define_class failed!");
1017 
1018     if (!hasProp) {
1019         napi_set_named_property(env, root, propName.c_str(), constructor);
1020         ZLOGD("save constructor to data.distributeddata.%{public}s", propName.c_str());
1021     }
1022     return constructor;
1023 }
1024 
NewWithRef(napi_env env,size_t argc,napi_value * argv,void ** out,napi_value constructor)1025 napi_ref JSUtil::NewWithRef(napi_env env, size_t argc, napi_value* argv, void** out, napi_value constructor)
1026 {
1027     napi_value object = nullptr;
1028     napi_status status = napi_new_instance(env, constructor, argc, argv, &object);
1029     CHECK_RETURN(status == napi_ok, "napi_new_instance failed", nullptr);
1030     CHECK_RETURN(object != nullptr, "napi_new_instance failed", nullptr);
1031 
1032     status = napi_unwrap(env, object, out);
1033     CHECK_RETURN(status == napi_ok, "napi_unwrap failed", nullptr);
1034     CHECK_RETURN(out != nullptr, "napi_unwrap failed", nullptr);
1035 
1036     napi_ref ref = nullptr;
1037     status = napi_create_reference(env, object, 1, &ref);
1038     CHECK_RETURN(status == napi_ok, "napi_create_referenc!e failed", nullptr);
1039     CHECK_RETURN(ref != nullptr, "napi_create_referenc!e failed", nullptr);
1040     return ref;
1041 }
1042 
Unwrap(napi_env env,napi_value in,void ** out,napi_value constructor)1043 napi_status JSUtil::Unwrap(napi_env env, napi_value in, void** out, napi_value constructor)
1044 {
1045     if (constructor != nullptr) {
1046         bool isInstance = false;
1047         napi_instanceof(env, in, constructor, &isInstance);
1048         if (!isInstance) {
1049             ZLOGE("not a instance of *");
1050             return napi_invalid_arg;
1051         }
1052     }
1053     return napi_unwrap(env, in, out);
1054 }
1055 
Equals(napi_env env,napi_value value,napi_ref copy)1056 bool JSUtil::Equals(napi_env env, napi_value value, napi_ref copy)
1057 {
1058     if (copy == nullptr) {
1059         return (value == nullptr);
1060     }
1061 
1062     napi_value copyValue = nullptr;
1063     napi_get_reference_value(env, copy, &copyValue);
1064 
1065     bool isEquals = false;
1066     napi_strict_equals(env, value, copyValue, &isEquals);
1067     return isEquals;
1068 }
1069 
IsNull(napi_env env,napi_value value)1070 bool JSUtil::IsNull(napi_env env, napi_value value)
1071 {
1072     napi_valuetype type = napi_undefined;
1073     napi_status status = napi_typeof(env, value, &type);
1074     if (status == napi_ok && (type == napi_undefined || type == napi_null)) {
1075         return true;
1076     }
1077     return false;
1078 }
1079 
GetValue(napi_env env,napi_value in,DataQuery & query)1080 napi_status JSUtil::GetValue(napi_env env, napi_value in, DataQuery &query)
1081 {
1082     ZLOGD("napi_value -> std::GetValue DataQuery");
1083     napi_valuetype type = napi_undefined;
1084     napi_status nstatus = napi_typeof(env, in, &type);
1085     CHECK_RETURN((nstatus == napi_ok) && (type == napi_object), "invalid type", napi_invalid_arg);
1086     PredicatesProxy *predicates = nullptr;
1087     napi_unwrap(env, in, reinterpret_cast<void **>(&predicates));
1088     CHECK_RETURN((predicates != nullptr), "invalid type", napi_invalid_arg);
1089     Status status = KvUtils::ToQuery(*(predicates->predicates_), query);
1090     if (status != Status::SUCCESS) {
1091         ZLOGD("napi_value -> GetValue DataQuery failed ");
1092     }
1093     return nstatus;
1094 }
1095 
GetCurrentAbilityParam(napi_env env,ContextParam & param)1096 napi_status JSUtil::GetCurrentAbilityParam(napi_env env, ContextParam &param)
1097 {
1098     auto ability = AbilityRuntime::GetCurrentAbility(env);
1099     if (ability == nullptr) {
1100         ZLOGE("GetCurrentAbility -> ability pointer is nullptr");
1101         return napi_invalid_arg;
1102     }
1103 
1104     auto context = ability->GetAbilityContext();
1105     if (context == nullptr) {
1106         ZLOGE("Get fa context  -> fa context pointer is nullptr");
1107         return napi_invalid_arg;
1108     }
1109     param.area = context->GetArea();
1110     param.baseDir = context->GetDatabaseDir();
1111     auto hapInfo = context->GetHapModuleInfo();
1112     if (hapInfo != nullptr) {
1113         param.hapName = hapInfo->moduleName;
1114     }
1115     ZLOGI("area:%{public}d hapName:%{public}s baseDir:%{public}s", param.area, param.hapName.c_str(),
1116         param.baseDir.c_str());
1117     return napi_ok;
1118 }
1119 
GetValue(napi_env env,napi_value in,ContextParam & param)1120 napi_status JSUtil::GetValue(napi_env env, napi_value in, ContextParam &param)
1121 {
1122     if (in == nullptr) {
1123         ZLOGD("hasProp is false -> fa stage");
1124         return GetCurrentAbilityParam(env, param);
1125     }
1126 
1127     bool isStageMode = false;
1128     napi_status status = GetNamedProperty(env, in, "stageMode", isStageMode);
1129     CHECK_RETURN(status == napi_ok, "get stageMode param failed", napi_invalid_arg);
1130     if (!isStageMode) {
1131         ZLOGD("isStageMode is false -> fa stage");
1132         return GetCurrentAbilityParam(env, param);
1133     }
1134 
1135     ZLOGD("stage mode branch");
1136     status = GetNamedProperty(env, in, "databaseDir", param.baseDir);
1137     CHECK_RETURN(status == napi_ok, "get databaseDir param failed", napi_invalid_arg);
1138     status = GetNamedProperty(env, in, "area", param.area);
1139     CHECK_RETURN(status == napi_ok, "get area param failed", napi_invalid_arg);
1140     napi_value hapInfo = nullptr;
1141     GetNamedProperty(env, in, "currentHapModuleInfo", hapInfo);
1142     if (hapInfo != nullptr) {
1143         status = GetNamedProperty(env, hapInfo, "name", param.hapName);
1144         CHECK_RETURN(status == napi_ok, "get hap name failed", napi_invalid_arg);
1145     }
1146     return napi_ok;
1147 }
1148 
GetInnerValue(napi_env env,napi_value in,const std::string & prop,bool optional)1149 std::pair<napi_status, napi_value> JSUtil::GetInnerValue(
1150     napi_env env, napi_value in, const std::string& prop, bool optional)
1151 {
1152     bool hasProp = false;
1153     napi_status status = napi_has_named_property(env, in, prop.c_str(), &hasProp);
1154     if (status != napi_ok) {
1155         return std::make_pair(napi_generic_failure, nullptr);
1156     }
1157     if (!hasProp) {
1158         status = optional ? napi_ok : napi_generic_failure;
1159         return std::make_pair(status, nullptr);
1160     }
1161     napi_value inner = nullptr;
1162     status = napi_get_named_property(env, in, prop.c_str(), &inner);
1163     if (status != napi_ok || inner == nullptr) {
1164         return std::make_pair(napi_generic_failure, nullptr);
1165     }
1166     if (optional && JSUtil::IsNull(env, inner)) {
1167         return std::make_pair(napi_ok, nullptr);
1168     }
1169     return std::make_pair(napi_ok, inner);
1170 }
1171 } // namespace OHOS::DistributedData
1172