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