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
16#include "napi_helper.h"
17
18#include "native_engine/native_value.h"
19#include "object_helper.h"
20
21namespace Commonlibrary::Concurrent::Common::Helper {
22static constexpr uint32_t MAX_CHAR_LENGTH = 1024;
23
24bool NapiHelper::IsTypeForNapiValue(napi_env env, napi_value param, napi_valuetype expectType)
25{
26    napi_valuetype valueType = napi_undefined;
27    if (param == nullptr) {
28        return false;
29    }
30    if (napi_typeof(env, param, &valueType) != napi_ok) {
31        return false;
32    }
33
34    return valueType == expectType;
35}
36
37bool NapiHelper::IsString(napi_env env, napi_value value)
38{
39    return IsTypeForNapiValue(env, value, napi_string);
40}
41
42bool NapiHelper::IsNotUndefined(napi_env env, napi_value value)
43{
44    if (value == nullptr) {
45        return false;
46    }
47    napi_valuetype valueType = napi_undefined;
48    if (napi_typeof(env, value, &valueType) != napi_ok) {
49        return false;
50    }
51
52    return valueType != napi_undefined;
53}
54
55bool NapiHelper::IsArray(napi_env env, napi_value value)
56{
57    bool isArray = false;
58    if (value == nullptr) {
59        return false;
60    }
61    if (napi_is_array(env, value, &isArray) != napi_ok) {
62        return false;
63    }
64
65    return isArray;
66}
67
68bool NapiHelper::IsFunction(napi_env env, napi_value object)
69{
70    return IsTypeForNapiValue(env, object, napi_function);
71}
72
73bool NapiHelper::IsArrayBuffer(napi_env env, napi_value value)
74{
75    bool result = false;
76    if (value == nullptr) {
77        return false;
78    }
79    if (napi_is_arraybuffer(env, value, &result) != napi_ok) {
80        return false;
81    }
82
83    return result;
84}
85
86bool NapiHelper::IsNumber(napi_env env, napi_value value)
87{
88    return IsTypeForNapiValue(env, value, napi_number);
89}
90
91size_t NapiHelper::GetCallbackInfoArgc(napi_env env, napi_callback_info cbInfo)
92{
93    size_t argc = 0;
94    napi_get_cb_info(env, cbInfo, &argc, nullptr, nullptr, nullptr);
95    return argc;
96}
97
98napi_value NapiHelper::GetNamePropertyInParentPort(napi_env env, napi_ref parentPort, const char* name)
99{
100    napi_value obj = nullptr;
101    napi_get_reference_value(env, parentPort, &obj);
102
103    napi_value value = nullptr;
104    napi_get_named_property(env, obj, name, &value);
105
106    return value;
107}
108
109napi_value NapiHelper::GetUndefinedValue(napi_env env)
110{
111    napi_value result = nullptr;
112    napi_get_undefined(env, &result);
113    return result;
114}
115
116bool NapiHelper::IsCallable(napi_env env, napi_value value)
117{
118    bool result = false;
119    napi_is_callable(env, value, &result);
120    return result;
121}
122
123bool NapiHelper::IsCallable(napi_env env, napi_ref value)
124{
125    napi_value obj = nullptr;
126    napi_get_reference_value(env, value, &obj);
127    if (obj == nullptr) {
128        return false;
129    }
130    return IsCallable(env, obj);
131}
132
133bool NapiHelper::IsAsyncFunction(napi_env env, napi_value value)
134{
135    bool res = false;
136    napi_is_async_function(env, value, &res);
137    return res;
138}
139
140bool NapiHelper::IsConcurrentFunction(napi_env env, napi_value value)
141{
142    bool res = false;
143    napi_is_concurrent_function(env, value, &res);
144    return res;
145}
146
147bool NapiHelper::IsGeneratorFunction(napi_env env, napi_value value)
148{
149    bool res = false;
150    napi_is_generator_function(env, value, &res);
151    return res;
152}
153
154bool NapiHelper::IsStrictEqual(napi_env env, napi_value lhs, napi_value rhs)
155{
156    bool res = false;
157    napi_strict_equals(env, lhs, rhs, &res);
158    return res;
159}
160
161bool NapiHelper::IsSendable(napi_env env, napi_value value)
162{
163    bool res = false;
164    napi_is_sendable(env, value, &res);
165    return res;
166}
167
168void NapiHelper::SetNamePropertyInGlobal(napi_env env, const char* name, napi_value value)
169{
170    napi_value object = nullptr;
171    napi_get_global(env, &object);
172    napi_set_named_property(env, object, name, value);
173}
174
175bool NapiHelper::IsObject(napi_env env, napi_value value)
176{
177    return IsTypeForNapiValue(env, value, napi_object);
178}
179
180char* NapiHelper::GetChars(napi_env env, napi_value value)
181{
182    size_t bufferSize = 0;
183    size_t strLength = 0;
184    napi_get_value_string_utf8(env, value, nullptr, 0, &bufferSize);
185    if (bufferSize > MAX_CHAR_LENGTH) {
186        bufferSize = MAX_CHAR_LENGTH;
187    }
188    char* buffer = new char[bufferSize + 1] { 0 };
189    napi_get_value_string_utf8(env, value, buffer, bufferSize + 1, &strLength);
190    return buffer;
191}
192
193std::string NapiHelper::GetString(napi_env env, napi_value value)
194{
195    std::string str = "";
196    char* buffer = GetChars(env, value);
197    if (buffer == nullptr) {
198        return str;
199    }
200    str = std::string(buffer);
201    CloseHelp::DeletePointer(buffer, true);
202    return str;
203}
204
205napi_value NapiHelper::CreateBooleanValue(napi_env env, bool value)
206{
207    napi_value result = nullptr;
208    napi_get_boolean(env, value, &result);
209    return result;
210}
211
212napi_value NapiHelper::GetGlobalObject(napi_env env)
213{
214    napi_value object = nullptr;
215    napi_get_global(env, &object);
216    return object;
217}
218
219napi_ref NapiHelper::CreateReference(napi_env env, napi_value value, uint32_t refcount)
220{
221    napi_ref callback = nullptr;
222    napi_create_reference(env, value, refcount, &callback);
223    return callback;
224}
225
226napi_value NapiHelper::CreateUint32(napi_env env, uint32_t value)
227{
228    napi_value result = nullptr;
229    napi_create_uint32(env, value, &result);
230    return result;
231}
232
233uv_loop_t* NapiHelper::GetLibUV(napi_env env)
234{
235    uv_loop_t* loop;
236    napi_get_uv_event_loop(env, &loop);
237    return loop;
238}
239
240napi_value NapiHelper::GetReferenceValue(napi_env env, napi_ref ref)
241{
242    napi_value result = nullptr;
243    napi_get_reference_value(env, ref, &result);
244    return result;
245}
246
247void NapiHelper::DeleteReference(napi_env env, napi_ref ref)
248{
249    napi_delete_reference(env, ref);
250}
251
252napi_value NapiHelper::GetNameProperty(napi_env env, napi_value obj, const char* name)
253{
254    napi_value result = nullptr;
255    napi_get_named_property(env, obj, name, &result);
256    return result;
257}
258
259bool NapiHelper::HasNameProperty(napi_env env, napi_value obj, const char* name)
260{
261    bool result = false;
262    napi_has_named_property(env, obj, name, &result);
263    return result;
264}
265
266bool NapiHelper::GetBooleanValue(napi_env env, napi_value value)
267{
268    bool result = false;
269    napi_get_value_bool(env, value, &result);
270    return result;
271}
272
273bool NapiHelper::StrictEqual(napi_env env, napi_value value, napi_value cmpValue)
274{
275    bool isEqual = false;
276    napi_strict_equals(env, value, cmpValue, &isEqual);
277    return isEqual;
278}
279
280std::string NapiHelper::GetConstructorName(napi_env env, napi_value object)
281{
282    while (IsNotUndefined(env, object)) {
283        napi_value func = nullptr;
284        napi_get_own_property_descriptor(env, object, "constructor", &func);
285        bool isInstanceof = false;
286        napi_instanceof(env, object, func, &isInstanceof);
287        if (IsNotUndefined(env, func) && isInstanceof) {
288            napi_value ctorName = nullptr;
289            napi_get_own_property_descriptor(env, func, "name", &ctorName);
290            std::string name = GetPrintString(env, ctorName);
291            if (name.size() > 0) {
292                return name;
293            }
294        }
295        napi_value result = nullptr;
296        napi_get_prototype(env, object, &result);
297        object = result;
298    }
299    return "";
300}
301
302napi_value NapiHelper::CreateObject(napi_env env)
303{
304    napi_value obj = nullptr;
305    napi_create_object(env, &obj);
306    return obj;
307}
308
309napi_value NapiHelper::CreatePromise(napi_env env, napi_deferred* deferred)
310{
311    napi_value promise = nullptr;
312    napi_create_promise(env, deferred, &promise);
313    return promise;
314}
315
316napi_value NapiHelper::CreateEmptyString(napi_env env)
317{
318    napi_value str = nullptr;
319    const char* name = "";
320    napi_create_string_utf8(env, name, 0, &str);
321    return str;
322}
323
324uint32_t NapiHelper::GetArrayLength(napi_env env, napi_value array)
325{
326    uint32_t arrayLength = 0;
327    napi_get_array_length(env, array, &arrayLength);
328    return arrayLength;
329}
330
331uint32_t NapiHelper::GetUint32Value(napi_env env, napi_value value)
332{
333    uint32_t result = 0;
334    napi_get_value_uint32(env, value, &result);
335    return result;
336}
337
338int32_t NapiHelper::GetInt32Value(napi_env env, napi_value value)
339{
340    int32_t result = 0;
341    napi_get_value_int32(env, value, &result);
342    return result;
343}
344
345bool NapiHelper::IsExceptionPending(napi_env env)
346{
347    bool isExceptionPending = false;
348    napi_is_exception_pending(env, &isExceptionPending);
349    return isExceptionPending;
350}
351
352std::string NapiHelper::GetPrintString(napi_env env, napi_value value)
353{
354    std::string str;
355    if (!IsTypeForNapiValue(env, value, napi_string)) {
356        napi_value strValue = nullptr;
357        if (napi_coerce_to_string(env, value, &strValue) != napi_ok) {
358            return str;
359        }
360        value = strValue;
361    }
362    napi_get_print_string(env, value, str);
363    return str;
364}
365
366napi_value NapiHelper::CreateUint64(napi_env env, uint64_t value)
367{
368    napi_value result;
369    napi_create_bigint_uint64(env, value, &result);
370    return result;
371}
372
373uint64_t NapiHelper::GetUint64Value(napi_env env, napi_value value, bool lossless)
374{
375    uint64_t result = 0;
376    napi_get_value_bigint_uint64(env, value, &result, &lossless);
377    return result;
378}
379
380napi_value NapiHelper::GetElement(napi_env env, napi_value value, uint32_t index)
381{
382    napi_value result;
383    napi_get_element(env, value, index, &result);
384    return result;
385}
386
387napi_value NapiHelper::CreateArrayWithLength(napi_env env, size_t length)
388{
389    napi_value argsArray;
390    napi_create_array_with_length(env, length, &argsArray);
391    return argsArray;
392}
393} // namespace Commonlibrary::Concurrent::Common::Helper