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