1 /*
2 * Copyright (c) 2021 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
16 #include "n_val.h"
17
18 #include <sstream>
19 #include <string>
20
21 namespace OHOS {
22 namespace HiviewDFX {
23 using namespace std;
24
NVal(napi_env nEnv,napi_value nVal=nullptr)25 NVal::NVal(napi_env nEnv, napi_value nVal = nullptr) : env_(nEnv), val_(nVal) {}
26
operator bool() const27 NVal::operator bool() const
28 {
29 return env_ && val_;
30 }
31
TypeIs(napi_valuetype expType) const32 bool NVal::TypeIs(napi_valuetype expType) const
33 {
34 return ValueTypeIs(val_, expType);
35 }
36
ValueTypeIs(napi_value value,napi_valuetype expType) const37 bool NVal::ValueTypeIs(napi_value value, napi_valuetype expType) const
38 {
39 if (!*this) {
40 return false;
41 }
42
43 napi_valuetype valueType;
44 napi_typeof(env_, value, &valueType);
45
46 if (expType != valueType) {
47 return false;
48 }
49 return true;
50 }
51
IsArray() const52 tuple<bool, bool> NVal::IsArray() const
53 {
54 bool res = false;
55 napi_status status = napi_is_array(env_, val_, &res);
56 return make_tuple(status == napi_ok, res);
57 }
58
ToUTF8String() const59 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF8String() const
60 {
61 size_t strLen = 0;
62 napi_status status = napi_get_value_string_utf8(env_, val_, nullptr, -1, &strLen);
63 if (status != napi_ok) {
64 return {false, nullptr, 0};
65 }
66
67 size_t bufLen = strLen + 1;
68 unique_ptr<char[]> str = make_unique<char[]>(bufLen);
69 status = napi_get_value_string_utf8(env_, val_, str.get(), bufLen, &strLen);
70 return make_tuple(status == napi_ok, move(str), strLen);
71 }
72
ToUTF16String() const73 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF16String() const
74 {
75 #ifdef FILE_SUBSYSTEM_DEV_ON_PC
76 size_t strLen = 0;
77 napi_status status = napi_get_value_string_utf16(env_, val_, nullptr, -1, &strLen);
78 if (status != napi_ok) {
79 return { false, nullptr, 0 };
80 }
81
82 auto str = make_unique<char16_t[]>(++strLen);
83 status = napi_get_value_string_utf16(env_, val_, str.get(), strLen, nullptr);
84 if (status != napi_ok) {
85 return { false, nullptr, 0 };
86 }
87
88 strLen = reinterpret_cast<char *>(str.get() + strLen) - reinterpret_cast<char *>(str.get());
89 auto strRet = unique_ptr<char[]>(reinterpret_cast<char *>(str.release()));
90 return { true, move(strRet), strLen };
91 #else
92 // Note that quickjs doesn't support utf16
93 return ToUTF8String();
94 #endif
95 }
96
ToPointer() const97 tuple<bool, void *> NVal::ToPointer() const
98 {
99 void *res = nullptr;
100 napi_status status = napi_get_value_external(env_, val_, &res);
101 return make_tuple(status == napi_ok, res);
102 }
103
IsTypeArray() const104 tuple<bool, bool> NVal::IsTypeArray() const
105 {
106 bool res = false;
107 napi_status status = napi_is_typedarray(env_, val_, &res);
108 return make_tuple(status == napi_ok, res);
109 }
110
ToBool() const111 tuple<bool, bool> NVal::ToBool() const
112 {
113 bool flag = false;
114 napi_status status = napi_get_value_bool(env_, val_, &flag);
115 return make_tuple(status == napi_ok, flag);
116 }
117
ToDouble() const118 tuple<bool, double> NVal::ToDouble() const
119 {
120 double res = 0.0;
121 napi_status status = napi_get_value_double(env_, val_, &res);
122 return make_tuple(status == napi_ok, res);
123 }
124
ToInt32() const125 tuple<bool, int32_t> NVal::ToInt32() const
126 {
127 int32_t res = 0;
128 napi_status status = napi_get_value_int32(env_, val_, &res);
129 return make_tuple(status == napi_ok, res);
130 }
131
ToInt64() const132 tuple<bool, int64_t> NVal::ToInt64() const
133 {
134 int64_t res = 0;
135 napi_status status = napi_get_value_int64(env_, val_, &res);
136 return make_tuple(status == napi_ok, res);
137 }
138
ToArraybuffer() const139 tuple<bool, void *, size_t> NVal::ToArraybuffer() const
140 {
141 void *buf = nullptr;
142 size_t bufLen = 0;
143 bool status = napi_get_arraybuffer_info(env_, val_, &buf, &bufLen);
144 return make_tuple(status == napi_ok, buf, bufLen);
145 }
146
ToTypedArray() const147 tuple<bool, napi_typedarray_type, void *, size_t> NVal::ToTypedArray() const
148 {
149 napi_typedarray_type type;
150 napi_value in_array_buffer = nullptr;
151 size_t byte_offset;
152 size_t length;
153 void *data = nullptr;
154 napi_status status = napi_get_typedarray_info(env_, val_, &type, &length, (void **) &data, &in_array_buffer,
155 &byte_offset);
156 return make_tuple(status == napi_ok, type, data, length);
157 }
158
ToDataview() const159 tuple<bool, void *, size_t> NVal::ToDataview() const
160 {
161 size_t bufLen = 0;
162 void *buf = nullptr;
163 napi_value arraybuffer = nullptr;
164 size_t byteoff = 0;
165 bool status = napi_get_dataview_info(env_, val_, &bufLen, &buf, &arraybuffer, &byteoff);
166 return make_tuple(status == napi_ok, buf, bufLen);
167 }
168
ToTypedArrayInfo() const169 tuple<bool, void *, size_t, size_t, napi_typedarray_type> NVal::ToTypedArrayInfo() const
170 {
171 napi_typedarray_type type;
172 napi_value in_array_buffer = nullptr;
173 size_t byte_offset;
174 size_t length;
175 void *data = nullptr;
176 napi_status status =
177 napi_get_typedarray_info(env_, val_, &type, &length, (void **)&data, &in_array_buffer, &byte_offset);
178 return make_tuple(status == napi_ok, data, length, byte_offset, type);
179 }
180
GetPrintString(napi_value value) const181 string NVal::GetPrintString(napi_value value) const
182 {
183 string str;
184 if (!ValueTypeIs(value, napi_string)) {
185 napi_value strValue = nullptr;
186 if (napi_coerce_to_string(env_, value, &strValue) != napi_ok) {
187 return str;
188 }
189 value = strValue;
190 }
191 napi_get_print_string(env_, value, str);
192 return str;
193 }
194
GetValObjectAsStr() const195 tuple<bool, string> NVal::GetValObjectAsStr() const
196 {
197 napi_value globalValue = nullptr;
198 auto fail = make_tuple(false, "");
199 napi_status status = napi_get_global(env_, &globalValue);
200 if (status != napi_ok) {
201 return fail;
202 }
203 napi_value jsonValue = nullptr;
204 status = napi_get_named_property(env_, globalValue, "JSON", &jsonValue);
205 if (status != napi_ok) {
206 return fail;
207 }
208 napi_value stringifyValue = nullptr;
209 status = napi_get_named_property(env_, jsonValue, "stringify", &stringifyValue);
210 if (status != napi_ok) {
211 return fail;
212 }
213 napi_value transValue = nullptr;
214 status = napi_call_function(env_, jsonValue, stringifyValue, 1, &val_, &transValue);
215 if (status != napi_ok || transValue == nullptr) {
216 return fail;
217 }
218 string content = GetPrintString(transValue);
219 return make_tuple(true, content);
220 }
221
HasProp(string propName) const222 bool NVal::HasProp(string propName) const
223 {
224 bool res = false;
225
226 if (!env_ || !val_ || !TypeIs(napi_object))
227 return false;
228 napi_status status = napi_has_named_property(env_, val_, propName.c_str(), &res);
229 return (status == napi_ok) && res;
230 }
231
GetProp(string propName) const232 NVal NVal::GetProp(string propName) const
233 {
234 if (!HasProp(propName)) {
235 return {env_, nullptr};
236 }
237 napi_value prop = nullptr;
238 napi_status status = napi_get_named_property(env_, val_, propName.c_str(), &prop);
239 if (status != napi_ok) {
240 return {env_, nullptr};
241 }
242 return NVal(env_, prop);
243 }
244
AddProp(vector<napi_property_descriptor> && propVec) const245 bool NVal::AddProp(vector<napi_property_descriptor> &&propVec) const
246 {
247 if (!TypeIs(napi_valuetype::napi_object)) {
248 return false;
249 }
250 napi_status status = napi_define_properties(env_, val_, propVec.size(), propVec.data());
251 if (status != napi_ok) {
252 return false;
253 }
254 return true;
255 }
256
AddProp(string propName,napi_value val) const257 bool NVal::AddProp(string propName, napi_value val) const
258 {
259 if (!TypeIs(napi_valuetype::napi_object) || HasProp(propName)) {
260 return false;
261 }
262
263 napi_status status = napi_set_named_property(env_, val_, propName.c_str(), val);
264 if (status != napi_ok) {
265 return false;
266 }
267 return true;
268 }
269
CreateUndefined(napi_env env)270 NVal NVal::CreateUndefined(napi_env env)
271 {
272 napi_value res = nullptr;
273 napi_get_undefined(env, &res);
274 return {env, res};
275 }
276
CreateNull(napi_env env)277 NVal NVal::CreateNull(napi_env env)
278 {
279 napi_value res = nullptr;
280 napi_get_null(env, &res);
281 return {env, res};
282 }
283
CreateInt64(napi_env env,int64_t val)284 NVal NVal::CreateInt64(napi_env env, int64_t val)
285 {
286 napi_value res = nullptr;
287 napi_create_int64(env, val, &res);
288 return {env, res};
289 }
290
CreateObject(napi_env env)291 NVal NVal::CreateObject(napi_env env)
292 {
293 napi_value res = nullptr;
294 napi_create_object(env, &res);
295 return {env, res};
296 }
297
CreateBool(napi_env env,bool val)298 NVal NVal::CreateBool(napi_env env, bool val)
299 {
300 napi_value res = nullptr;
301 napi_get_boolean(env, val, &res);
302 return {env, res};
303 }
304
CreateUTF8String(napi_env env,std::string str)305 NVal NVal::CreateUTF8String(napi_env env, std::string str)
306 {
307 napi_value res = nullptr;
308 napi_create_string_utf8(env, str.c_str(), str.length(), &res);
309 return {env, res};
310 }
311
CreateUint8Array(napi_env env,void * buf,size_t bufLen)312 NVal NVal::CreateUint8Array(napi_env env, void *buf, size_t bufLen)
313 {
314 napi_value output_buffer = nullptr;
315 napi_create_external_arraybuffer(env, buf, bufLen,
316 [](napi_env env, void *finalize_data, void *finalize_hint) { free(finalize_data); },
317 NULL, &output_buffer);
318 napi_value output_array = nullptr;
319 napi_create_typedarray(env, napi_uint8_array, bufLen, output_buffer, 0, &output_array);
320 return {env, output_array};
321 }
322
CreateDouble(napi_env env,double val)323 NVal NVal::CreateDouble(napi_env env, double val)
324 {
325 napi_value res = nullptr;
326 napi_create_double(env, val, &res);
327 return {env, res};
328 }
329
DeclareNapiProperty(const char * name,napi_value val)330 napi_property_descriptor NVal::DeclareNapiProperty(const char *name, napi_value val)
331 {
332 return {(name), nullptr, nullptr, nullptr, nullptr, val, napi_default, nullptr};
333 }
334
DeclareNapiStaticProperty(const char * name,napi_value val)335 napi_property_descriptor NVal::DeclareNapiStaticProperty(const char *name, napi_value val)
336 {
337 return {(name), nullptr, nullptr, nullptr, nullptr, val, napi_static, nullptr};
338 }
339
DeclareNapiFunction(const char * name,napi_callback func)340 napi_property_descriptor NVal::DeclareNapiFunction(const char *name, napi_callback func)
341 {
342 return {(name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, nullptr};
343 }
344
DeclareNapiStaticFunction(const char * name,napi_callback func)345 napi_property_descriptor NVal::DeclareNapiStaticFunction(const char *name, napi_callback func)
346 {
347 return {(name), nullptr, (func), nullptr, nullptr, nullptr, napi_static, nullptr};
348 }
349
DeclareNapiGetter(const char * name,napi_callback getter)350 napi_property_descriptor NVal::DeclareNapiGetter(const char *name, napi_callback getter)
351 {
352 return {(name), nullptr, nullptr, (getter), nullptr, nullptr, napi_default, nullptr};
353 }
354
DeclareNapiSetter(const char * name,napi_callback setter)355 napi_property_descriptor NVal::DeclareNapiSetter(const char *name, napi_callback setter)
356 {
357 return {(name), nullptr, nullptr, nullptr, (setter), nullptr, napi_default, nullptr};
358 }
359
DeclareNapiGetterSetter(const char * name,napi_callback getter,napi_callback setter)360 napi_property_descriptor NVal::DeclareNapiGetterSetter(const char *name, napi_callback getter, napi_callback setter)
361 {
362 return {(name), nullptr, nullptr, (getter), (setter), nullptr, napi_default, nullptr};
363 }
364 } // namespace HiviewDFX
365 } // namespace OHOS