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