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