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