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