• 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::DistributedKVStore {
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     ASSERT((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     ASSERT(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     ASSERT((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         ASSERT((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg);
153         std::string value;
154         status = GetValue(env, item, value);
155         ASSERT(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     ASSERT(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         ASSERT((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 tmp4int = be32toh(*reinterpret_cast<uint32_t*>(&(real[0])));
189         return JSUtil::KvStoreVariant(*reinterpret_cast<int32_t*>(&tmp4int));
190     } else if (data[0] == JSUtil::FLOAT) {
191         uint32_t tmp4flt = be32toh(*reinterpret_cast<uint32_t*>(&(real[0])));
192         return JSUtil::KvStoreVariant(*reinterpret_cast<float*>((void*)(&tmp4flt)));
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 tmp4dbl = be64toh(*reinterpret_cast<uint64_t*>(&(real[0])));
199         return JSUtil::KvStoreVariant(*reinterpret_cast<double*>((void*)(&tmp4dbl)));
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 *tmp = nullptr;
227     auto intValue = std::get_if<int32_t>(&value);
228     if (intValue != nullptr) {
229         int32_t tmp4int = *intValue; // copy value, and make it available in stack space.
230         uint32_t tmp32 = htobe32(*reinterpret_cast<uint32_t*>(&tmp4int));
231         tmp = reinterpret_cast<uint8_t*>(&tmp32);
232         data.push_back(JSUtil::INTEGER);
233         data.insert(data.end(), tmp, tmp + sizeof(int32_t) / sizeof(uint8_t));
234     }
235     auto fltValue = std::get_if<float>(&value);
236     if (fltValue != nullptr) {
237         float tmp4flt = *fltValue; // copy value, and make it available in stack space.
238         uint32_t tmp32 = htobe32(*reinterpret_cast<uint32_t*>(&tmp4flt));
239         tmp = reinterpret_cast<uint8_t*>(&tmp32);
240         data.push_back(JSUtil::FLOAT);
241         data.insert(data.end(), tmp, tmp + sizeof(float) / sizeof(uint8_t));
242     }
243     auto dblValue = std::get_if<double>(&value);
244     if (dblValue != nullptr) {
245         double tmp4dbl = *dblValue; // copy value, and make it available in stack space.
246         uint64_t tmp64 = htobe64(*reinterpret_cast<uint64_t*>(&tmp4dbl));
247         tmp = reinterpret_cast<uint8_t*>(&tmp64);
248         data.push_back(JSUtil::DOUBLE);
249         data.insert(data.end(), tmp, tmp + 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     ASSERT((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.0f;
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     ASSERT((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.0f;
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     ASSERT((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     ASSERT(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
392     ASSERT(type == napi_uint8_array, "is not Uint8Array!", napi_invalid_arg);
393     ASSERT((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     ASSERT(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     ASSERT((status == napi_ok), "create array buffer failed!", status);
406 
407     if (memcpy_s(data, in.size(), in.data(), in.size()) != EOK) {
408         ZLOGE("memcpy_s not EOK");
409         return napi_invalid_arg;
410     }
411     status = napi_create_typedarray(env, napi_uint8_array, in.size(), buffer, 0, &out);
412     ASSERT((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             ASSERT_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     ASSERT(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
478     ASSERT(type <= napi_int32_array, "is not int32 supported typed array!", napi_invalid_arg);
479     ASSERT((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     ASSERT(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     ASSERT((status == napi_ok), "invalid buffer", status);
493 
494     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
495         ZLOGE("memcpy_s not EOK");
496         return napi_invalid_arg;
497     }
498     status = napi_create_typedarray(env, napi_int32_array, in.size(), buffer, 0, &out);
499     ASSERT((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     ASSERT(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
517     ASSERT((type <= napi_uint16_array) || (type == napi_uint32_array), "invalid type!", napi_invalid_arg);
518     ASSERT((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     ASSERT(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     ASSERT((status == napi_ok), "invalid buffer", status);
532 
533     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
534         ZLOGE("memcpy_s not EOK");
535         return napi_invalid_arg;
536     }
537     status = napi_create_typedarray(env, napi_uint32_array, in.size(), buffer, 0, &out);
538     ASSERT((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     ASSERT(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
556     ASSERT((type <= napi_uint32_array) || (type == napi_bigint64_array), "invalid type!", napi_invalid_arg);
557     ASSERT((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     ASSERT(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     ASSERT((status == napi_ok), "invalid buffer", status);
571 
572     if (memcpy_s(data, bytes, in.data(), bytes) != EOK) {
573         ZLOGE("memcpy_s not EOK");
574         return napi_invalid_arg;
575     }
576     status = napi_create_typedarray(env, napi_bigint64_array, in.size(), buffer, 0, &out);
577     ASSERT((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     ASSERT((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         ASSERT(status == napi_ok, "napi_get_typedarray_info failed!", napi_invalid_arg);
598         ASSERT((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         ASSERT((status == napi_ok) && isArray, "invalid data!", napi_invalid_arg);
605         uint32_t length = 0;
606         status = napi_get_array_length(env, in, &length);
607         ASSERT((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             ASSERT((item != nullptr) && (status == napi_ok), "no element", napi_invalid_arg);
612             double vi = 0.0f;
613             status = napi_get_value_double(env, item, &vi);
614             ASSERT(status == napi_ok, "element 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     ASSERT(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     ASSERT(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     ASSERT((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     ASSERT((status == napi_ok), "no property key", status);
679     std::string key;
680     status = GetValue(env, propKey, key);
681     ASSERT((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     ASSERT((status == napi_ok), "no property value", status);
686 
687     napi_value propVType = nullptr;
688     status = napi_get_named_property(env, propValue, "type", &propVType);
689     ASSERT((status == napi_ok), "no property value.type", status);
690     int32_t type = 0; // int8_t
691     status = GetValue(env, propVType, type);
692     ASSERT((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     ASSERT((status == napi_ok), "no property value.value", status);
697     KvStoreVariant value = 0;
698     status = GetValue(env, propVValue, value);
699     ASSERT((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("unmarch 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     ASSERT((status == napi_ok), "invalid entry object", status);
718 
719     napi_value key = nullptr;
720     status = SetValue(env, in.key.ToString(), key);
721     ASSERT((status == napi_ok), "invalid entry key", status);
722     napi_set_named_property(env, out, "key", key);
723 
724     ASSERT((in.value.Size() > 0), "invalid entry value", status);
725     napi_value value = nullptr;
726 
727     status = napi_create_object(env, &value);
728     ASSERT((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     ASSERT((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     ASSERT(isArray, "not array", napi_invalid_arg);
753 
754     uint32_t length = 0;
755     napi_status status = napi_get_array_length(env, in, &length);
756     ASSERT((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         ASSERT((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     ASSERT(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 & valueObject)785 napi_status JSUtil::GetValue(napi_env env, napi_value jsValue, ValueObject &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;
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 }
808 
GetValue(napi_env env,napi_value jsValue,ValuesBucket & valuesBucket)809 napi_status JSUtil::GetValue(napi_env env, napi_value jsValue, ValuesBucket &valuesBucket)
810 {
811     napi_value keys = 0;
812     napi_get_property_names(env, jsValue, &keys);
813     uint32_t arrLen = 0;
814     napi_status status = napi_get_array_length(env, keys, &arrLen);
815     if (status != napi_ok) {
816         return status;
817     }
818     for (size_t i = 0; i < arrLen; ++i) {
819         napi_value jsKey = 0;
820         status = napi_get_element(env, keys, i, &jsKey);
821         ASSERT((status == napi_ok), "no element", status);
822         std::string key;
823         JSUtil::GetValue(env, jsKey, key);
824         napi_value valueJs = 0;
825         napi_get_property(env, jsValue, jsKey, &valueJs);
826         GetValue(env, valueJs, valuesBucket.valuesMap[key]);
827     }
828     return napi_ok;
829 }
830 
831 /* napi_value <-> std::vector<DistributedKv::Entry> */
GetValue(napi_env env,napi_value in,std::vector<DistributedKv::Entry> & out,bool hasSchema)832 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<DistributedKv::Entry> &out, bool hasSchema)
833 {
834     out.clear();
835     ZLOGD("napi_value -> std::vector<DistributedKv::Entry> ");
836     bool isArray = false;
837     napi_is_array(env, in, &isArray);
838     ASSERT(isArray, "not array", napi_invalid_arg);
839 
840     uint32_t length = 0;
841     napi_status status = napi_get_array_length(env, in, &length);
842     ASSERT((status == napi_ok) && (length > 0), "get_array failed!", status);
843     for (uint32_t i = 0; i < length; ++i) {
844         napi_value item = nullptr;
845         status = napi_get_element(env, in, i, &item);
846         ASSERT((status == napi_ok), "no element", status);
847         if ((status != napi_ok) || (item == nullptr)) {
848             continue;
849         }
850         DistributedKv::Entry entry;
851         status = GetValue(env, item, entry, hasSchema);
852         if (status != napi_ok) {
853             ZLOGD("maybe valubucket type");
854             DataShareValuesBucket values;
855             GetValue(env, item, values);
856             entry = KvUtils::ToEntry(values);
857             entry.key = std::vector<uint8_t>(entry.key.Data().begin(), entry.key.Data().end());
858             if (hasSchema) {
859                 entry.value = std::vector<uint8_t>(entry.value.Data().begin() + 1, entry.value.Data().end());
860             }
861         }
862         out.push_back(entry);
863     }
864     return napi_ok;
865 }
866 
SetValue(napi_env env,const std::vector<DistributedKv::Entry> & in,napi_value & out,bool hasSchema)867 napi_status JSUtil::SetValue(napi_env env, const std::vector<DistributedKv::Entry>& in, napi_value& out, bool hasSchema)
868 {
869     ZLOGD("napi_value <- std::vector<DistributedKv::Entry> %{public}d", static_cast<int>(in.size()));
870     napi_status status = napi_create_array_with_length(env, in.size(), &out);
871     ASSERT(status == napi_ok, "create array failed!", status);
872     int index = 0;
873     for (const auto& item : in) {
874         napi_value entry = nullptr;
875         SetValue(env, item, entry, hasSchema);
876         napi_set_element(env, out, index++, entry);
877     }
878     return status;
879 }
880 
881 /* napi_value <-> std::vector<DistributedKv::StoreId> */
GetValue(napi_env env,napi_value in,std::vector<DistributedKv::StoreId> & out)882 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<DistributedKv::StoreId>& out)
883 {
884     out.clear();
885     ZLOGD("napi_value -> std::vector<DistributedKv::StoreId> ");
886     bool isArray = false;
887     napi_is_array(env, in, &isArray);
888     ASSERT(isArray, "not array", napi_invalid_arg);
889 
890     uint32_t length = 0;
891     napi_status status = napi_get_array_length(env, in, &length);
892     ASSERT((status == napi_ok) && (length > 0), "get_array failed!", status);
893     for (uint32_t i = 0; i < length; ++i) {
894         napi_value item = nullptr;
895         status = napi_get_element(env, in, i, &item);
896         ASSERT((status == napi_ok), "no element", status);
897         if ((status != napi_ok) || (item == nullptr)) {
898             continue;
899         }
900         std::string value;
901         status = GetValue(env, item, value);
902         DistributedKv::StoreId storeId { value };
903         out.push_back(storeId);
904     }
905     return status;
906 }
907 
SetValue(napi_env env,const std::vector<DistributedKv::StoreId> & in,napi_value & out)908 napi_status JSUtil::SetValue(napi_env env, const std::vector<DistributedKv::StoreId>& in, napi_value& out)
909 {
910     ZLOGD("napi_value <- std::vector<DistributedKv::StoreId>  %{public}d", static_cast<int>(in.size()));
911     napi_status status = napi_create_array_with_length(env, in.size(), &out);
912     ASSERT((status == napi_ok), "create_array failed!", status);
913     int index = 0;
914     for (const auto& item : in) {
915         napi_value entry = nullptr;
916         SetValue(env, item.storeId, entry);
917         napi_set_element(env, out, index++, entry);
918     }
919     return status;
920 }
921 
922 /* napi_value <-> DistributedKv::ChangeNotification */
GetValue(napi_env env,napi_value in,DistributedKv::ChangeNotification & out,bool hasSchema)923 napi_status JSUtil::GetValue(napi_env env, napi_value in, DistributedKv::ChangeNotification& out, bool hasSchema)
924 {
925     ZLOGD("napi_value -> DistributedKv::ChangeNotification ");
926     (void)(env);
927     (void)(in);
928     (void)(out);
929     ASSERT(false, "DistributedKv::ChangeNotification from napi_value, unsupported!", napi_invalid_arg);
930     return napi_invalid_arg;
931 }
932 
SetValue(napi_env env,const DistributedKv::ChangeNotification & in,napi_value & out,bool hasSchema)933 napi_status JSUtil::SetValue(napi_env env, const DistributedKv::ChangeNotification& in, napi_value& out, bool hasSchema)
934 {
935     ZLOGD("napi_value <- DistributedKv::ChangeNotification ");
936     napi_status status = napi_create_object(env, &out);
937     ASSERT((status == napi_ok), "napi_create_object for DistributedKv::ChangeNotification failed!", status);
938     napi_value deviceId = nullptr;
939     status = SetValue(env, in.GetDeviceId(), deviceId);
940     ASSERT((status == napi_ok) || (deviceId == nullptr), "GetDeviceId failed!", status);
941     status = napi_set_named_property(env, out, "deviceId", deviceId);
942     ASSERT((status == napi_ok), "set_named_property deviceId failed!", status);
943 
944     napi_value insertEntries = nullptr;
945     status = SetValue(env, in.GetInsertEntries(), insertEntries, hasSchema);
946     ASSERT((status == napi_ok) || (insertEntries == nullptr), "GetInsertEntries failed!", status);
947     status = napi_set_named_property(env, out, "insertEntries", insertEntries);
948     ASSERT((status == napi_ok), "set_named_property insertEntries failed!", status);
949 
950     napi_value updateEntries = nullptr;
951     status = SetValue(env, in.GetUpdateEntries(), updateEntries, hasSchema);
952     ASSERT((status == napi_ok) || (updateEntries == nullptr), "GetUpdateEntries failed!", status);
953     status = napi_set_named_property(env, out, "updateEntries", updateEntries);
954     ASSERT((status == napi_ok), "set_named_property updateEntries failed!", status);
955 
956     napi_value deleteEntries = nullptr;
957     status = SetValue(env, in.GetDeleteEntries(), deleteEntries, hasSchema);
958     ASSERT((status == napi_ok) || (deleteEntries == nullptr), "GetDeleteEntries failed!", status);
959     status = napi_set_named_property(env, out, "deleteEntries", deleteEntries);
960     ASSERT((status == napi_ok), "set_named_property deleteEntries failed!", status);
961     return status;
962 }
963 
964 /* napi_value <-> DistributedKv::Options */
GetValue(napi_env env,napi_value in,DistributedKv::Options & options)965 napi_status JSUtil::GetValue(napi_env env, napi_value in, DistributedKv::Options& options)
966 {
967     ZLOGD("napi_value -> DistributedKv::Options ");
968     napi_status status = napi_invalid_arg;
969     GetNamedProperty(env, in, "createIfMissing", options.createIfMissing);
970     GetNamedProperty(env, in, "encrypt", options.encrypt);
971     GetNamedProperty(env, in, "backup", options.backup);
972     GetNamedProperty(env, in, "autoSync", options.autoSync);
973 
974     int32_t kvStoreType = 0;
975     GetNamedProperty(env, in, "kvStoreType", kvStoreType);
976     options.kvStoreType = static_cast<DistributedKv::KvStoreType>(kvStoreType);
977 
978     JsSchema *jsSchema = nullptr;
979     status = GetNamedProperty(env, in, "schema", jsSchema);
980     if (status == napi_ok) {
981         options.schema = jsSchema->Dump();
982     }
983 
984     int32_t level = 0;
985     status = GetNamedProperty(env, in, "securityLevel", level);
986     if (status != napi_ok) {
987         return status;
988     }
989 
990     return GetLevel(level, options.securityLevel);
991 }
992 
GetLevel(int32_t level,int32_t & out)993 napi_status JSUtil::GetLevel(int32_t level, int32_t &out)
994 {
995     switch (level) {
996         case SecurityLevel::S1:
997         case SecurityLevel::S2:
998         case SecurityLevel::S3:
999         case SecurityLevel::S4:
1000             out = level;
1001             return napi_ok;
1002         default:
1003             return napi_invalid_arg;
1004     }
1005 }
1006 
GetValue(napi_env env,napi_value inner,JsSchema * & out)1007 napi_status JSUtil::GetValue(napi_env env, napi_value inner, JsSchema*& out)
1008 {
1009     return JsSchema::ToJson(env, inner, out);
1010 }
1011 
SetValue(napi_env env,const DistributedKv::Options & in,napi_value & out)1012 napi_status JSUtil::SetValue(napi_env env, const DistributedKv::Options& in, napi_value& out)
1013 {
1014     (void)(env);
1015     (void)(in);
1016     (void)(out);
1017     ASSERT(false, "DistributedKv::Options to napi_value, unsupported!", napi_invalid_arg);
1018     return napi_invalid_arg;
1019 }
1020 
DefineClass(napi_env env,const std::string & name,const napi_property_descriptor * properties,size_t count,napi_callback newcb)1021 napi_value JSUtil::DefineClass(napi_env env, const std::string& name,
1022     const napi_property_descriptor* properties, size_t count, napi_callback newcb)
1023 {
1024     // base64("data.distributedkvstore") as rootPropName, i.e. global.<root>
1025     const std::string rootPropName = "ZGF0YS5kaXN0cmlidXRlZGt2c3RvcmU";
1026     napi_value root = nullptr;
1027     bool hasRoot = false;
1028     napi_value global = nullptr;
1029     napi_get_global(env, &global);
1030     napi_has_named_property(env, global, rootPropName.c_str(), &hasRoot);
1031     if (hasRoot) {
1032         napi_get_named_property(env, global, rootPropName.c_str(), &root);
1033     } else {
1034         napi_create_object(env, &root);
1035         napi_set_named_property(env, global, rootPropName.c_str(), root);
1036     }
1037 
1038     std::string propName = "constructor_of_" + name;
1039     napi_value constructor = nullptr;
1040     bool hasProp = false;
1041     napi_has_named_property(env, root, propName.c_str(), &hasProp);
1042     if (hasProp) {
1043         napi_get_named_property(env, root, propName.c_str(), &constructor);
1044         if (constructor != nullptr) {
1045             ZLOGD("got data.distributeddata.%{public}s as constructor", propName.c_str());
1046             return constructor;
1047         }
1048         hasProp = false; // no constructor.
1049     }
1050 
1051     NAPI_CALL(env, napi_define_class(env, name.c_str(), name.size(), newcb, nullptr, count, properties, &constructor));
1052     NAPI_ASSERT(env, constructor != nullptr, "napi_define_class failed!");
1053 
1054     if (!hasProp) {
1055         napi_set_named_property(env, root, propName.c_str(), constructor);
1056         ZLOGD("save constructor to data.distributeddata.%{public}s", propName.c_str());
1057     }
1058     return constructor;
1059 }
1060 
NewWithRef(napi_env env,size_t argc,napi_value * argv,void ** out,napi_value constructor)1061 napi_ref JSUtil::NewWithRef(napi_env env, size_t argc, napi_value* argv, void** out, napi_value constructor)
1062 {
1063     napi_value object = nullptr;
1064     napi_status status = napi_new_instance(env, constructor, argc, argv, &object);
1065     ASSERT(status == napi_ok, "napi_new_instance failed", nullptr);
1066     ASSERT(object != nullptr, "napi_new_instance failed", nullptr);
1067 
1068     status = napi_unwrap(env, object, out);
1069     ASSERT(status == napi_ok, "napi_unwrap failed", nullptr);
1070     ASSERT(out != nullptr, "napi_unwrap failed", nullptr);
1071 
1072     napi_ref ref = nullptr;
1073     status = napi_create_reference(env, object, 1, &ref);
1074     ASSERT(status == napi_ok, "napi_create_referenc!e failed", nullptr);
1075     ASSERT(ref != nullptr, "napi_create_referenc!e failed", nullptr);
1076     return ref;
1077 }
1078 
Unwrap(napi_env env,napi_value in,void ** out,napi_value constructor)1079 napi_status JSUtil::Unwrap(napi_env env, napi_value in, void** out, napi_value constructor)
1080 {
1081     if (constructor != nullptr) {
1082         bool isInstance = false;
1083         napi_instanceof(env, in, constructor, &isInstance);
1084         if (!isInstance) {
1085             ZLOGE("not a instance of *");
1086             return napi_invalid_arg;
1087         }
1088     }
1089     return napi_unwrap(env, in, out);
1090 }
1091 
Equals(napi_env env,napi_value value,napi_ref copy)1092 bool JSUtil::Equals(napi_env env, napi_value value, napi_ref copy)
1093 {
1094     if (copy == nullptr) {
1095         return (value == nullptr);
1096     }
1097 
1098     napi_value copyValue = nullptr;
1099     napi_get_reference_value(env, copy, &copyValue);
1100 
1101     bool isEquals = false;
1102     napi_strict_equals(env, value, copyValue, &isEquals);
1103     return isEquals;
1104 }
1105 
GetValue(napi_env env,napi_value in,std::vector<Blob> & out)1106 napi_status JSUtil::GetValue(napi_env env, napi_value in, std::vector<Blob> &out)
1107 {
1108     ZLOGD("napi_value -> std::GetValue Blob");
1109     out.clear();
1110     napi_valuetype type = napi_undefined;
1111     napi_status nstatus = napi_typeof(env, in, &type);
1112     ASSERT((nstatus == napi_ok) && (type == napi_object), "invalid type", napi_invalid_arg);
1113     PredicatesProxy *predicates = nullptr;
1114     napi_unwrap(env, in, reinterpret_cast<void **>(&predicates));
1115     ASSERT((predicates != nullptr), "invalid type", napi_invalid_arg);
1116     std::vector<Key> keys;
1117     nstatus = napi_invalid_arg;
1118     Status status = KvUtils::GetKeys(*(predicates->predicates_), keys);
1119     if (status == Status::SUCCESS) {
1120         ZLOGD("napi_value —> GetValue Blob ok");
1121         out = keys;
1122         nstatus = napi_ok;
1123     }
1124     return nstatus;
1125 }
1126 
GetValue(napi_env env,napi_value in,DataQuery & query)1127 napi_status JSUtil::GetValue(napi_env env, napi_value in, DataQuery &query)
1128 {
1129     ZLOGD("napi_value -> std::GetValue DataQuery");
1130     napi_valuetype type = napi_undefined;
1131     napi_status nstatus = napi_typeof(env, in, &type);
1132     ASSERT((nstatus == napi_ok) && (type == napi_object), "invalid type", napi_invalid_arg);
1133     PredicatesProxy *predicates = nullptr;
1134     napi_unwrap(env, in, reinterpret_cast<void **>(&predicates));
1135     ASSERT((predicates != nullptr), "invalid type", napi_invalid_arg);
1136     Status status = KvUtils::ToQuery(*(predicates->predicates_), query);
1137     if (status != Status::SUCCESS) {
1138         ZLOGD("napi_value -> GetValue DataQuery failed ");
1139     }
1140     return nstatus;
1141 }
1142 
GetCurrentAbilityParam(napi_env env,ContextParam & param)1143 napi_status JSUtil::GetCurrentAbilityParam(napi_env env, ContextParam &param)
1144 {
1145     auto ability = AbilityRuntime::GetCurrentAbility(env);
1146     if (ability == nullptr) {
1147         ZLOGE("GetCurrentAbility -> ability pointer is nullptr");
1148         return napi_invalid_arg;
1149     }
1150 
1151     auto context = ability->GetAbilityContext();
1152     if (context == nullptr) {
1153         ZLOGE("Get fa context  -> fa context pointer is nullptr");
1154         return napi_invalid_arg;
1155     }
1156     param.area = context->GetArea();
1157     param.baseDir = context->GetDatabaseDir();
1158     auto hapInfo = context->GetHapModuleInfo();
1159     if (hapInfo != nullptr) {
1160         param.hapName = hapInfo->moduleName;
1161     }
1162     ZLOGI("area:%{public}d hapName:%{public}s baseDir:%{public}s", param.area, param.hapName.c_str(),
1163         param.baseDir.c_str());
1164     return napi_ok;
1165 }
1166 
GetValue(napi_env env,napi_value in,ContextParam & param)1167 napi_status JSUtil::GetValue(napi_env env, napi_value in, ContextParam &param)
1168 {
1169     if (in == nullptr) {
1170         ZLOGD("hasProp is false -> fa stage");
1171         return GetCurrentAbilityParam(env, param);
1172     }
1173 
1174     bool isStageMode = false;
1175     napi_status status = GetNamedProperty(env, in, "stageMode", isStageMode);
1176     ASSERT(status == napi_ok, "get stageMode param failed", napi_invalid_arg);
1177     if (!isStageMode) {
1178         ZLOGD("isStageMode is false -> fa stage");
1179         return GetCurrentAbilityParam(env, param);
1180     }
1181 
1182     ZLOGD("stage mode branch");
1183     status = GetNamedProperty(env, in, "databaseDir", param.baseDir);
1184     ASSERT(status == napi_ok, "get databaseDir param failed", napi_invalid_arg);
1185     status = GetNamedProperty(env, in, "area", param.area);
1186     ASSERT(status == napi_ok, "get area param failed", napi_invalid_arg);
1187     napi_value hapInfo = nullptr;
1188     GetNamedProperty(env, in, "currentHapModuleInfo", hapInfo);
1189     if (hapInfo != nullptr) {
1190         status = GetNamedProperty(env, hapInfo, "moduleName", param.hapName);
1191         ASSERT(status == napi_ok, "get hap name failed", napi_invalid_arg);
1192     }
1193     return napi_ok;
1194 }
1195 } // namespace OHOS::DistributedKVStore
1196