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