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