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