1/*
2 * Copyright (c) 2021-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#ifndef NAPI_EXPERIMENTAL
16#define NAPI_EXPERIMENTAL
17#endif
18
19#ifdef ENABLE_HITRACE
20#include <sys/prctl.h>
21#endif
22
23#ifdef ENABLE_CONTAINER_SCOPE
24#include "core/common/container_scope.h"
25#endif
26#include "ecmascript/napi/include/jsnapi.h"
27#include "native_api_internal.h"
28#include "native_engine/impl/ark/ark_native_engine.h"
29#include "native_engine/impl/ark/ark_native_reference.h"
30#include "native_engine/native_create_env.h"
31#include "native_engine/native_property.h"
32#include "native_engine/native_sendable.h"
33#include "native_engine/native_utils.h"
34#include "native_engine/native_value.h"
35#include "securec.h"
36#include "utils/log.h"
37#ifdef ENABLE_HITRACE
38#include "hitrace_meter.h"
39#endif
40
41using panda::ArrayRef;
42using panda::ArrayBufferRef;
43using panda::BigIntRef;
44using panda::BooleanRef;
45using panda::BufferRef;
46using panda::DateRef;
47using panda::DataViewRef;
48using panda::EscapeLocalScope;
49using panda::FunctionRef;
50using panda::Global;
51using panda::IntegerRef;
52using panda::JSNApi;
53using panda::JsiRuntimeCallInfo;
54using panda::Local;
55using panda::LocalScope;
56using panda::NativePointerRef;
57using panda::NumberRef;
58using panda::ObjectRef;
59using panda::PrimitiveRef;
60using panda::PromiseCapabilityRef;
61using panda::PromiseRef;
62using panda::PropertyAttribute;
63using panda::StringRef;
64using panda::SymbolRef;
65using panda::TypedArrayRef;
66using panda::ecmascript::EcmaVM;
67
68static constexpr size_t MAX_BYTE_LENGTH = 2097152;
69static constexpr size_t ONEMIB_BYTE_SIZE = 1048576;
70static constexpr size_t SMALL_STRING_SIZE = 16;
71
72class HandleScopeWrapper {
73public:
74    explicit HandleScopeWrapper(NativeEngine* engine) : scope_(engine->GetEcmaVm()) {}
75
76private:
77    LocalScope scope_;
78};
79
80class EscapableHandleScopeWrapper {
81public:
82    explicit EscapableHandleScopeWrapper(NativeEngine* engine)
83        : scope_(engine->GetEcmaVm()), escapeCalled_(false) {}
84
85    bool IsEscapeCalled() const
86    {
87        return escapeCalled_;
88    }
89
90    template<typename T>
91    Local<T> Escape(Local<T> value)
92    {
93        escapeCalled_ = true;
94        return scope_.Escape(value);
95    }
96
97private:
98    EscapeLocalScope scope_;
99    bool escapeCalled_;
100};
101
102inline napi_handle_scope HandleScopeToNapiHandleScope(HandleScopeWrapper* s)
103{
104    return reinterpret_cast<napi_handle_scope>(s);
105}
106
107inline HandleScopeWrapper* NapiHandleScopeToHandleScope(napi_handle_scope s)
108{
109    return reinterpret_cast<HandleScopeWrapper*>(s);
110}
111
112inline napi_escapable_handle_scope EscapableHandleScopeToNapiEscapableHandleScope(EscapableHandleScopeWrapper* s)
113{
114    return reinterpret_cast<napi_escapable_handle_scope>(s);
115}
116
117inline EscapableHandleScopeWrapper* NapiEscapableHandleScopeToEscapableHandleScope(napi_escapable_handle_scope s)
118{
119    return reinterpret_cast<EscapableHandleScopeWrapper*>(s);
120}
121
122NAPI_EXTERN napi_status napi_get_last_error_info(napi_env env, const napi_extended_error_info** result)
123{
124    CHECK_ENV(env);
125    CHECK_ARG(env, result);
126
127    *result = reinterpret_cast<napi_extended_error_info*>(reinterpret_cast<NativeEngine*>(env)->GetLastError());
128    if ((*result)->error_code == napi_ok) {
129        napi_clear_last_error(env);
130    }
131
132    return napi_ok;
133}
134
135// Getters for defined singletons
136NAPI_EXTERN napi_status napi_get_undefined(napi_env env, napi_value* result)
137{
138    CHECK_ENV(env);
139    CHECK_ARG(env, result);
140
141    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
142    Local<panda::PrimitiveRef> value = panda::JSValueRef::Undefined(vm);
143    *result = JsValueFromLocalValue(value);
144
145    return napi_clear_last_error(env);
146}
147
148NAPI_EXTERN napi_status napi_get_null(napi_env env, napi_value* result)
149{
150    CHECK_ENV(env);
151    CHECK_ARG(env, result);
152
153    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
154    Local<panda::PrimitiveRef> value = panda::JSValueRef::Null(vm);
155    *result = JsValueFromLocalValue(value);
156
157    return napi_clear_last_error(env);
158}
159
160NAPI_EXTERN napi_status napi_get_global(napi_env env, napi_value* result)
161{
162    CHECK_ENV(env);
163    CHECK_ARG(env, result);
164
165    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
166    Local<panda::ObjectRef> value = panda::JSNApi::GetGlobalObject(vm);
167    *result = JsValueFromLocalValue(value);
168
169    return napi_clear_last_error(env);
170}
171
172NAPI_EXTERN napi_status napi_get_boolean(napi_env env, bool value, napi_value* result)
173{
174    CHECK_ENV(env);
175    CHECK_ARG(env, result);
176
177    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
178    if (value) {
179        *result = JsValueFromLocalValue(panda::JSValueRef::True(vm));
180    } else {
181        *result = JsValueFromLocalValue(panda::JSValueRef::False(vm));
182    }
183
184    return napi_clear_last_error(env);
185}
186
187// Methods to create Primitive types/Objects
188NAPI_EXTERN napi_status napi_create_object(napi_env env, napi_value* result)
189{
190    CHECK_ENV(env);
191    CHECK_ARG(env, result);
192
193    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
194    auto obj = panda::ObjectRef::NewObject(vm);
195    *result = reinterpret_cast<napi_value>(obj);
196    return napi_clear_last_error(env);
197}
198
199// Create JSObject with initial properties given by descriptors, note that property key must be String, and
200// must can not convert to element_index, also all keys must not duplicate.
201NAPI_EXTERN napi_status napi_create_object_with_properties(napi_env env, napi_value* result, size_t property_count,
202                                                           const napi_property_descriptor* properties)
203{
204    CHECK_ENV(env);
205    CHECK_ARG(env, result);
206
207    Local<panda::ObjectRef> object;
208    if (property_count <= panda::ObjectRef::MAX_PROPERTIES_ON_STACK) {
209        char attrs[sizeof(PropertyAttribute) * panda::ObjectRef::MAX_PROPERTIES_ON_STACK];
210        char keys[sizeof(Local<panda::JSValueRef>) * panda::ObjectRef::MAX_PROPERTIES_ON_STACK];
211        object = NapiCreateObjectWithProperties(env, property_count, properties,
212                                                reinterpret_cast<Local<panda::JSValueRef> *>(keys),
213                                                reinterpret_cast<PropertyAttribute *>(attrs));
214    } else {
215        void *attrs = malloc(sizeof(PropertyAttribute) * property_count);
216        void *keys = malloc(sizeof(Local<panda::JSValueRef>) * property_count);
217        if (attrs != nullptr && keys != nullptr) {
218            object = NapiCreateObjectWithProperties(env, property_count, properties,
219                                                    reinterpret_cast<Local<panda::JSValueRef> *>(keys),
220                                                    reinterpret_cast<PropertyAttribute *>(attrs));
221        } else {
222            auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
223            object = panda::JSValueRef::Undefined(vm);
224            napi_throw_error(env, nullptr, "malloc failed in napi_create_object_with_properties");
225        }
226        if (attrs != nullptr) {
227            free(attrs);
228        }
229        if (keys != nullptr) {
230            free(keys);
231        }
232    }
233    *result = JsValueFromLocalValue(object);
234
235    return napi_clear_last_error(env);
236}
237
238// Create JSObject with initial properties given by keys and values, note that property key must be String, and
239// must can not convert to element_index, also all keys must not duplicate.
240NAPI_EXTERN napi_status napi_create_object_with_named_properties(napi_env env, napi_value* result,
241                                                                 size_t property_count, const char** keys,
242                                                                 const napi_value* values)
243{
244    CHECK_ENV(env);
245    CHECK_ARG(env, result);
246
247    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
248    Local<panda::ObjectRef> object = panda::ObjectRef::NewWithNamedProperties(vm, property_count, keys,
249        reinterpret_cast<const Local<JSValueRef> *>(values));
250    *result = JsValueFromLocalValue(object);
251
252    return napi_clear_last_error(env);
253}
254
255NAPI_EXTERN napi_status napi_create_array(napi_env env, napi_value* result)
256{
257    CHECK_ENV(env);
258    CHECK_ARG(env, result);
259
260    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
261    Local<panda::ArrayRef> object = panda::ArrayRef::New(vm, 0);
262    *result = JsValueFromLocalValue(object);
263
264    return napi_clear_last_error(env);
265}
266
267NAPI_EXTERN napi_status napi_create_array_with_length(napi_env env, size_t length, napi_value* result)
268{
269    CHECK_ENV(env);
270    CHECK_ARG(env, result);
271
272    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
273    Local<panda::ArrayRef> object = panda::ArrayRef::New(vm, length);
274    *result = JsValueFromLocalValue(object);
275
276    return napi_clear_last_error(env);
277}
278
279NAPI_EXTERN napi_status napi_create_sendable_array(napi_env env, napi_value* result)
280{
281    CHECK_ENV(env);
282    CHECK_ARG(env, result);
283
284    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
285    Local<panda::SendableArrayRef> object = panda::SendableArrayRef::New(vm, 0);
286    *result = JsValueFromLocalValue(object);
287
288    return napi_clear_last_error(env);
289}
290
291NAPI_EXTERN napi_status napi_create_sendable_array_with_length(napi_env env, size_t length, napi_value* result)
292{
293    CHECK_ENV(env);
294    CHECK_ARG(env, result);
295
296    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
297    Local<panda::SendableArrayRef> object = panda::SendableArrayRef::New(vm, length);
298    *result = JsValueFromLocalValue(object);
299
300    return napi_clear_last_error(env);
301}
302
303NAPI_EXTERN napi_status napi_create_double(napi_env env, double value, napi_value* result)
304{
305    CHECK_ENV(env);
306    CHECK_ARG(env, result);
307
308    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
309    Local<panda::NumberRef> object = panda::NumberRef::New(vm, value);
310    *result = JsValueFromLocalValue(object);
311
312    return napi_clear_last_error(env);
313}
314
315NAPI_EXTERN napi_status napi_create_int32(napi_env env, int32_t value, napi_value* result)
316{
317    CHECK_ENV(env);
318    CHECK_ARG(env, result);
319
320    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
321    Local<panda::NumberRef> object = panda::NumberRef::New(vm, value);
322    *result = JsValueFromLocalValue(object);
323
324    return napi_clear_last_error(env);
325}
326
327NAPI_EXTERN napi_status napi_create_uint32(napi_env env, uint32_t value, napi_value* result)
328{
329    CHECK_ENV(env);
330    CHECK_ARG(env, result);
331
332    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
333    Local<panda::NumberRef> object = panda::NumberRef::New(vm, value);
334    *result = JsValueFromLocalValue(object);
335
336    return napi_clear_last_error(env);
337}
338
339NAPI_EXTERN napi_status napi_create_int64(napi_env env, int64_t value, napi_value* result)
340{
341    CHECK_ENV(env);
342    CHECK_ARG(env, result);
343
344    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
345    Local<panda::NumberRef> object = panda::NumberRef::New(vm, value);
346    *result = JsValueFromLocalValue(object);
347
348    return napi_clear_last_error(env);
349}
350
351NAPI_EXTERN napi_status napi_create_string_latin1(napi_env env, const char* str, size_t length, napi_value* result)
352{
353    CHECK_ENV(env);
354    CHECK_ARG(env, str);
355    CHECK_ARG(env, result);
356
357    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
358    if (length < SMALL_STRING_SIZE) {
359        Local<panda::StringRef> object = panda::StringRef::NewFromUtf8WithoutStringTable(
360            vm, str, (length == NAPI_AUTO_LENGTH) ? strlen(str) : length);
361        *result = JsValueFromLocalValue(object);
362    } else {
363        Local<panda::StringRef> object = panda::StringRef::NewFromUtf8(
364            vm, str, (length == NAPI_AUTO_LENGTH) ? strlen(str) : length);
365        *result = JsValueFromLocalValue(object);
366    }
367
368    return napi_clear_last_error(env);
369}
370
371NAPI_EXTERN napi_status napi_create_string_utf8(napi_env env, const char* str, size_t length, napi_value* result)
372{
373    CHECK_ENV(env);
374    CHECK_ARG(env, str);
375    CHECK_ARG(env, result);
376
377    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
378    if (length < SMALL_STRING_SIZE) {
379        Local<panda::StringRef> object = panda::StringRef::NewFromUtf8WithoutStringTable(
380            vm, str, (length == NAPI_AUTO_LENGTH) ? strlen(str) : length);
381        *result = JsValueFromLocalValue(object);
382    } else {
383        Local<panda::StringRef> object = panda::StringRef::NewFromUtf8(
384            vm, str, (length == NAPI_AUTO_LENGTH) ? strlen(str) : length);
385        *result = JsValueFromLocalValue(object);
386    }
387
388    return napi_clear_last_error(env);
389}
390
391NAPI_EXTERN napi_status napi_create_string_utf16(
392    napi_env env, const char16_t* str, size_t length, napi_value* result)
393{
394    CHECK_ENV(env);
395    CHECK_ARG(env, str);
396    CHECK_ARG(env, result);
397    RETURN_STATUS_IF_FALSE(env, (length == NAPI_AUTO_LENGTH) || (length <= INT_MAX && length >= 0), napi_invalid_arg);
398
399    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
400    int char16Length = static_cast<int>(std::char_traits<char16_t>::length(str));
401    if (length != NAPI_AUTO_LENGTH && length != static_cast<size_t>(char16Length)) {
402        HILOG_WARN("`length` (%{public}zu) not equals to strlen(`str`) (%{public}d), result may be unexpected",
403            length, char16Length);
404    }
405    if (length < SMALL_STRING_SIZE) {
406        Local<panda::StringRef> object = panda::StringRef::NewFromUtf16WithoutStringTable(
407            vm, str, (length == NAPI_AUTO_LENGTH) ? char16Length : length);
408        *result = JsValueFromLocalValue(object);
409    } else {
410        Local<panda::StringRef> object = panda::StringRef::NewFromUtf16(
411            vm, str, (length == NAPI_AUTO_LENGTH) ? char16Length : length);
412        *result = JsValueFromLocalValue(object);
413    }
414
415    return napi_clear_last_error(env);
416}
417
418NAPI_EXTERN napi_status napi_create_symbol(napi_env env, napi_value description, napi_value* result)
419{
420    CHECK_ENV(env);
421    CHECK_ARG(env, result);
422
423    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
424    panda::JsiFastNativeScope fastNativeScope(vm);
425    panda::Local<panda::JSValueRef> object = panda::JSValueRef::Undefined(vm);
426    if (description == nullptr) {
427        const char* str = "";
428        object = panda::StringRef::NewFromUtf8(vm, str, 0);
429    } else {
430        object = LocalValueFromJsValue(description);
431    }
432    RETURN_STATUS_IF_FALSE(env, object->IsString(vm), napi_invalid_arg);
433    Local<panda::SymbolRef> symbol = panda::SymbolRef::New(vm, object);
434    *result = JsValueFromLocalValue(symbol);
435
436    return napi_clear_last_error(env);
437}
438
439NAPI_EXTERN napi_status napi_create_function(napi_env env,
440                                             const char* utf8name,
441                                             size_t length,
442                                             napi_callback cb,
443                                             void* data,
444                                             napi_value* result)
445{
446    NAPI_PREAMBLE(env);
447    CHECK_ARG(env, cb);
448    CHECK_ARG(env, result);
449
450    auto vm = const_cast<EcmaVM*>(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm());
451    panda::JsiFastNativeScope fastNativeScope(vm);
452    EscapeLocalScope scope(vm);
453    auto callback = reinterpret_cast<NapiNativeCallback>(cb);
454    const char* name = "defaultName";
455    NapiFunctionInfo* funcInfo = NapiFunctionInfo::CreateNewInstance();
456    if (funcInfo == nullptr) {
457        HILOG_ERROR("funcInfo is nullptr");
458        return napi_set_last_error(env, napi_invalid_arg);
459    }
460    funcInfo->callback = callback;
461    funcInfo->data = data;
462#ifdef ENABLE_CONTAINER_SCOPE
463    funcInfo->scopeId = OHOS::Ace::ContainerScope::CurrentId();
464#endif
465
466    Local<panda::FunctionRef> fn = panda::FunctionRef::NewConcurrent(
467        vm, ArkNativeFunctionCallBack,
468        [](void* env, void* externalPointer, void* data) {
469            auto info = reinterpret_cast<NapiFunctionInfo*>(data);
470            if (info != nullptr) {
471                delete info;
472            }
473        },
474        reinterpret_cast<void*>(funcInfo), true
475    );
476    Local<panda::StringRef> fnName = panda::StringRef::NewFromUtf8(vm, utf8name != nullptr ? utf8name : name);
477    fn->SetName(vm, fnName);
478    *result = JsValueFromLocalValue(scope.Escape(fn));
479    return GET_RETURN_STATUS(env);
480}
481
482NAPI_EXTERN napi_status napi_create_error(napi_env env, napi_value code, napi_value msg, napi_value* result)
483{
484    CHECK_ENV(env);
485    CHECK_ARG(env, msg);
486    CHECK_ARG(env, result);
487
488    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
489    panda::JsiFastNativeScope fastNativeScope(vm);
490    Local<panda::JSValueRef> codeValue = panda::JSValueRef::Undefined(vm);
491    if (code != nullptr) {
492        codeValue = LocalValueFromJsValue(code);
493        RETURN_STATUS_IF_FALSE(env, codeValue->IsString(vm) || codeValue->IsNumber(), napi_invalid_arg);
494    }
495
496    auto msgValue = LocalValueFromJsValue(msg);
497    RETURN_STATUS_IF_FALSE(env, msgValue->IsString(vm), napi_invalid_arg);
498
499    Local<panda::JSValueRef> errorVal = panda::Exception::Error(vm, msgValue);
500    if (code != nullptr) {
501        Local<panda::StringRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
502        Local<panda::ObjectRef> errorObj(errorVal);
503        errorObj->Set(vm, codeKey, codeValue);
504    }
505    *result = JsValueFromLocalValue(errorVal);
506
507    return napi_clear_last_error(env);
508}
509
510NAPI_EXTERN napi_status napi_create_type_error(napi_env env, napi_value code, napi_value msg, napi_value* result)
511{
512    CHECK_ENV(env);
513    CHECK_ARG(env, msg);
514    CHECK_ARG(env, result);
515
516    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
517    panda::JsiFastNativeScope fastNativeScope(vm);
518    Local<panda::JSValueRef> codeValue = panda::JSValueRef::Undefined(vm);
519    if (code != nullptr) {
520        codeValue = LocalValueFromJsValue(code);
521        RETURN_STATUS_IF_FALSE(env, codeValue->IsString(vm) || codeValue->IsNumber(), napi_invalid_arg);
522    }
523    auto msgValue = LocalValueFromJsValue(msg);
524    RETURN_STATUS_IF_FALSE(env, msgValue->IsString(vm), napi_invalid_arg);
525
526    Local<panda::JSValueRef> errorVal = panda::Exception::TypeError(vm, msgValue);
527    if (code != nullptr) {
528        Local<panda::StringRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
529        Local<panda::ObjectRef> errorObj(errorVal);
530        errorObj->Set(vm, codeKey, codeValue);
531    }
532    *result = JsValueFromLocalValue(errorVal);
533
534    return napi_clear_last_error(env);
535}
536
537NAPI_EXTERN napi_status napi_create_range_error(napi_env env, napi_value code, napi_value msg, napi_value* result)
538{
539    CHECK_ENV(env);
540    CHECK_ARG(env, msg);
541    CHECK_ARG(env, result);
542
543    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
544    panda::JsiFastNativeScope fastNativeScope(vm);
545    Local<panda::JSValueRef> codeValue = panda::JSValueRef::Undefined(vm);
546
547    if (code != nullptr) {
548        codeValue = LocalValueFromJsValue(code);
549        RETURN_STATUS_IF_FALSE(env, codeValue->IsString(vm) || codeValue->IsNumber(), napi_invalid_arg);
550    }
551    auto msgValue = LocalValueFromJsValue(msg);
552    RETURN_STATUS_IF_FALSE(env, msgValue->IsString(vm), napi_invalid_arg);
553
554    Local<panda::JSValueRef> errorVal = panda::Exception::RangeError(vm, msgValue);
555    if (code != nullptr) {
556        Local<panda::StringRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
557        Local<panda::ObjectRef> errorObj(errorVal);
558        errorObj->Set(vm, codeKey, codeValue);
559    }
560    *result = JsValueFromLocalValue(errorVal);
561
562    return napi_clear_last_error(env);
563}
564
565// Methods to get the native napi_value from Primitive type
566NAPI_EXTERN napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result)
567{
568    CHECK_ENV(env);
569    CHECK_ARG(env, value);
570    CHECK_ARG(env, result);
571
572    auto valueObj = LocalValueFromJsValue(value);
573    napi_valuetype resultType;
574    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
575    panda::JsiFastNativeScope fastNativeScope(vm);
576
577    if (valueObj->IsNumber()) {
578        resultType = napi_number;
579    } else if (valueObj->IsString(vm)) {
580        resultType = napi_string;
581    } else if (valueObj->IsFunction(vm)) {
582        resultType = napi_function;
583    } else if (valueObj->IsNativePointer(vm)) {
584        resultType = napi_external;
585    } else if (valueObj->IsNull()) {
586        resultType = napi_null;
587    } else if (valueObj->IsBoolean()) {
588        resultType = napi_boolean;
589    } else if (valueObj->IsUndefined()) {
590        resultType = napi_undefined;
591    } else if (valueObj->IsSymbol(vm)) {
592        resultType = napi_symbol;
593    } else if (valueObj->IsBigInt(vm)) {
594        resultType = napi_bigint;
595    } else if (valueObj->IsObject(vm)) {
596        resultType = napi_object;
597    } else {
598        resultType = napi_undefined;
599    }
600    *result = resultType;
601    return napi_clear_last_error(env);
602}
603
604NAPI_EXTERN napi_status napi_get_value_double(napi_env env, napi_value value, double* result)
605{
606    CHECK_ENV(env);
607    CHECK_ARG(env, value);
608    CHECK_ARG(env, result);
609
610    panda::JSValueRef* nativeValue = reinterpret_cast<panda::JSValueRef*>(value);
611    bool isNumber = false;
612    double dValue = nativeValue->GetValueDouble(isNumber);
613    RETURN_STATUS_IF_FALSE(env, isNumber, napi_number_expected);
614    *result = dValue;
615    return napi_clear_last_error(env);
616}
617
618NAPI_EXTERN napi_status napi_get_value_int32(napi_env env, napi_value value, int32_t* result)
619{
620    CHECK_ENV(env);
621    CHECK_ARG(env, value);
622    CHECK_ARG(env, result);
623
624    panda::JSValueRef* nativeValue = reinterpret_cast<panda::JSValueRef*>(value);
625    bool isNumber = false;
626    int32_t i32Value = nativeValue->GetValueInt32(isNumber);
627    RETURN_STATUS_IF_FALSE(env, isNumber, napi_number_expected);
628    *result = i32Value;
629
630    return napi_clear_last_error(env);
631}
632
633NAPI_EXTERN napi_status napi_get_value_uint32(napi_env env, napi_value value, uint32_t* result)
634{
635    CHECK_ENV(env);
636    CHECK_ARG(env, value);
637    CHECK_ARG(env, result);
638
639    panda::JSValueRef* nativeValue = reinterpret_cast<panda::JSValueRef*>(value);
640    bool isNumber = false;
641    uint32_t u32Value = nativeValue->GetValueUint32(isNumber);
642    RETURN_STATUS_IF_FALSE(env, isNumber, napi_number_expected);
643    *result = u32Value;
644    return napi_clear_last_error(env);
645}
646
647NAPI_EXTERN napi_status napi_get_value_int64(napi_env env, napi_value value, int64_t* result)
648{
649    CHECK_ENV(env);
650    CHECK_ARG(env, value);
651    CHECK_ARG(env, result);
652
653    panda::JSValueRef* nativeValue = reinterpret_cast<panda::JSValueRef*>(value);
654    bool isNumber = false;
655    int64_t i64Value = nativeValue->GetValueInt64(isNumber);
656    RETURN_STATUS_IF_FALSE(env, isNumber, napi_number_expected);
657    *result = i64Value;
658    return napi_clear_last_error(env);
659}
660
661NAPI_EXTERN napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result)
662{
663    CHECK_ENV(env);
664    CHECK_ARG(env, value);
665    CHECK_ARG(env, result);
666
667    panda::JSValueRef* nativeValue = reinterpret_cast<panda::JSValueRef*>(value);
668    bool isBool = false;
669    bool bValue = nativeValue->GetValueBool(isBool);
670    RETURN_STATUS_IF_FALSE(env, isBool, napi_boolean_expected);
671    *result = bValue;
672    return napi_clear_last_error(env);
673}
674
675// Copies LATIN-1 encoded bytes from a string into a buffer.
676NAPI_EXTERN napi_status napi_get_value_string_latin1(napi_env env,
677                                                     napi_value value,
678                                                     char* buf,
679                                                     size_t bufsize,
680                                                     size_t* result)
681{
682    CHECK_ENV(env);
683    CHECK_ARG(env, value);
684
685    auto nativeValue = LocalValueFromJsValue(value);
686    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
687    panda::JsiFastNativeScope fastNativeScope(vm);
688
689    RETURN_STATUS_IF_FALSE(env, nativeValue->IsString(vm), napi_string_expected);
690    Local<panda::StringRef> stringVal(nativeValue);
691    if (buf == nullptr) {
692        CHECK_ARG(env, result);
693        *result = stringVal->Length(vm);
694    } else if (bufsize != 0) {
695        uint32_t copied = stringVal->WriteLatin1(vm, buf, bufsize);
696        buf[copied] = '\0';
697        if (result != nullptr) {
698            *result = copied;
699        }
700    } else if (result != nullptr) {
701        *result = 0;
702    }
703
704    return napi_clear_last_error(env);
705}
706
707// Copies UTF-8 encoded bytes from a string into a buffer.
708NAPI_EXTERN napi_status napi_get_value_string_utf8(napi_env env,
709                                                   napi_value value,
710                                                   char* buf,
711                                                   size_t bufsize,
712                                                   size_t* result)
713{
714    CHECK_ENV(env);
715    CHECK_ARG(env, value);
716
717    auto nativeValue = LocalValueFromJsValue(value);
718    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
719    panda::JsiFastNativeScope fastNativeScope(vm);
720
721    RETURN_STATUS_IF_FALSE(env, nativeValue->IsString(vm), napi_string_expected);
722    Local<panda::StringRef> stringVal(nativeValue);
723    if (buf == nullptr) {
724        CHECK_ARG(env, result);
725        *result = stringVal->Utf8Length(vm, true) - 1;
726    } else if (bufsize != 0) {
727        uint32_t copied = stringVal->WriteUtf8(vm, buf, bufsize - 1, true) - 1;
728        buf[copied] = '\0';
729        if (result != nullptr) {
730            *result = copied;
731        }
732    } else if (result != nullptr) {
733        *result = 0;
734    }
735
736    return napi_clear_last_error(env);
737}
738
739NAPI_EXTERN napi_status napi_get_value_string_utf16(napi_env env,
740                                                    napi_value value,
741                                                    char16_t* buf,
742                                                    size_t bufsize,
743                                                    size_t* result)
744{
745    CHECK_ENV(env);
746    CHECK_ARG(env, value);
747
748    auto nativeValue = LocalValueFromJsValue(value);
749    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
750    panda::JsiFastNativeScope fastNativeScope(vm);
751
752    RETURN_STATUS_IF_FALSE(env, nativeValue->IsString(vm), napi_string_expected);
753    Local<panda::StringRef> stringVal(nativeValue);
754    if (buf == nullptr) {
755        CHECK_ARG(env, result);
756        *result = stringVal->Length(vm);
757    } else if (bufsize == 1) {
758        buf[0] = '\0';
759        if (result != nullptr) {
760            *result = 0;
761        }
762    } else if (bufsize != 0) {
763        uint32_t copied = stringVal->WriteUtf16(vm, buf, bufsize - 1); // bufsize - 1 : reserve the position of buf "\0"
764        buf[copied] = '\0';
765        if (result != nullptr) {
766            *result = copied;
767        }
768    } else if (result != nullptr) {
769        *result = 0;
770    }
771
772    return napi_clear_last_error(env);
773}
774
775// Methods to coerce values
776// These APIs may execute user scripts
777NAPI_EXTERN napi_status napi_coerce_to_bool(napi_env env, napi_value value, napi_value* result)
778{
779    NAPI_PREAMBLE(env);
780    CHECK_ARG(env, value);
781    CHECK_ARG(env, result);
782
783    Local<panda::JSValueRef> val = LocalValueFromJsValue(value);
784    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
785    Local<panda::BooleanRef> boolVal = val->ToBoolean(vm);
786    *result = JsValueFromLocalValue(boolVal);
787
788    return napi_clear_last_error(env);
789}
790
791NAPI_EXTERN napi_status napi_coerce_to_number(napi_env env, napi_value value, napi_value* result)
792{
793    CHECK_ENV(env);
794    CHECK_ARG(env, value);
795    CHECK_ARG(env, result);
796
797    auto nativeValue = LocalValueFromJsValue(value);
798    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
799    *result = JsValueFromLocalValue(nativeValue->ToNumber(vm));
800
801    return napi_clear_last_error(env);
802}
803
804NAPI_EXTERN napi_status napi_coerce_to_object(napi_env env, napi_value value, napi_value* result)
805{
806    CHECK_ENV(env);
807    CHECK_ARG(env, value);
808    CHECK_ARG(env, result);
809
810    auto nativeValue = LocalValueFromJsValue(value);
811    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
812    *result = JsValueFromLocalValue(nativeValue->ToObject(vm));
813
814    return napi_clear_last_error(env);
815}
816
817NAPI_EXTERN napi_status napi_coerce_to_string(napi_env env, napi_value value, napi_value* result)
818{
819    CHECK_ENV(env);
820    CHECK_ARG(env, value);
821    CHECK_ARG(env, result);
822
823    auto nativeValue = LocalValueFromJsValue(value);
824    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
825    *result = JsValueFromLocalValue(nativeValue->ToString(vm));
826
827    return napi_clear_last_error(env);
828}
829
830// Methods to work with Objects
831NAPI_EXTERN napi_status napi_get_prototype(napi_env env, napi_value object, napi_value* result)
832{
833    NAPI_PREAMBLE(env);
834    CHECK_ARG(env, object);
835    CHECK_ARG(env, result);
836
837    auto nativeValue = LocalValueFromJsValue(object);
838    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
839    panda::JsiFastNativeScope fastNativeScope(vm);
840    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, obj);
841    Local<panda::JSValueRef> val = obj->GetPrototype(vm);
842    *result = JsValueFromLocalValue(val);
843
844    return GET_RETURN_STATUS(env);
845}
846
847NAPI_EXTERN napi_status napi_get_property_names(napi_env env, napi_value object, napi_value* result)
848{
849    CHECK_ENV(env);
850    CHECK_ARG(env, object);
851    CHECK_ARG(env, result);
852
853    auto nativeValue = LocalValueFromJsValue(object);
854    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
855    panda::JsiFastNativeScope fastNativeScope(vm);
856    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, obj);
857    Local<panda::ArrayRef> arrayVal = obj->GetOwnPropertyNames(vm);
858    *result = JsValueFromLocalValue(arrayVal);
859    return napi_clear_last_error(env);
860}
861
862NAPI_EXTERN napi_status napi_set_property(napi_env env, napi_value object, napi_value key, napi_value value)
863{
864    NAPI_PREAMBLE(env);
865    CHECK_ARG(env, object);
866    CHECK_ARG(env, key);
867    CHECK_ARG(env, value);
868
869    auto nativeValue = LocalValueFromJsValue(object);
870    auto propKey = LocalValueFromJsValue(key);
871    auto propValue = LocalValueFromJsValue(value);
872    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
873    panda::JsiFastNativeScope fastNativeScope(vm);
874    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, obj);
875    obj->Set(vm, propKey, propValue);
876
877    return GET_RETURN_STATUS(env);
878}
879
880NAPI_EXTERN napi_status napi_has_property(napi_env env, napi_value object, napi_value key, bool* result)
881{
882    NAPI_PREAMBLE(env);
883    CHECK_ARG(env, object);
884    CHECK_ARG(env, key);
885    CHECK_ARG(env, result);
886
887    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
888    panda::JsiFastNativeScope fastNativeScope(vm);
889    Local<panda::JSValueRef> hasResult = JSNApi::NapiHasProperty(vm, reinterpret_cast<uintptr_t>(object),
890                                                                 reinterpret_cast<uintptr_t>(key));
891    RETURN_STATUS_IF_FALSE(env, NapiStatusValidationCheck(hasResult), napi_object_expected);
892    *result = hasResult->BooleaValue(vm);
893
894    return GET_RETURN_STATUS(env);
895}
896
897NAPI_EXTERN napi_status napi_get_property(napi_env env, napi_value object, napi_value key, napi_value* result)
898{
899    NAPI_PREAMBLE(env);
900    CHECK_ARG(env, object);
901    CHECK_ARG(env, key);
902    CHECK_ARG(env, result);
903
904    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
905    panda::JsiFastNativeScope fastNativeScope(vm);
906    Local<panda::JSValueRef> value = JSNApi::NapiGetProperty(vm, reinterpret_cast<uintptr_t>(object),
907                                                             reinterpret_cast<uintptr_t>(key));
908    RETURN_STATUS_IF_FALSE(env, NapiStatusValidationCheck(value), napi_object_expected);
909#ifdef ENABLE_CONTAINER_SCOPE
910    FunctionSetContainerId(vm, value);
911#endif
912    *result = JsValueFromLocalValue(value);
913
914    return GET_RETURN_STATUS(env);
915}
916
917NAPI_EXTERN napi_status napi_delete_property(napi_env env, napi_value object, napi_value key, bool* result)
918{
919    NAPI_PREAMBLE(env);
920    CHECK_ARG(env, object);
921    CHECK_ARG(env, key);
922
923    auto nativeValue = LocalValueFromJsValue(object);
924    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
925    panda::JsiFastNativeScope fastNativeScope(vm);
926    RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm) || nativeValue->IsFunction(vm), napi_object_expected);
927    auto deleteResult = JSNApi::NapiDeleteProperty(vm, reinterpret_cast<uintptr_t>(object),
928                                                   reinterpret_cast<uintptr_t>(key));
929    RETURN_STATUS_IF_FALSE(env, NapiStatusValidationCheck(deleteResult), napi_object_expected);
930    if (result) {
931        *result = deleteResult->BooleaValue(vm);
932    }
933
934    return GET_RETURN_STATUS(env);
935}
936
937NAPI_EXTERN napi_status napi_has_own_property(napi_env env, napi_value object, napi_value key, bool* result)
938{
939    NAPI_PREAMBLE(env);
940    CHECK_ARG(env, object);
941    CHECK_ARG(env, key);
942    CHECK_ARG(env, result);
943
944    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
945    panda::JsiFastNativeScope fastNativeScope(vm);
946    auto hasResult = JSNApi::NapiHasOwnProperty(vm, reinterpret_cast<uintptr_t>(object),
947                                                reinterpret_cast<uintptr_t>(key));
948    RETURN_STATUS_IF_FALSE(env, NapiStatusValidationCheck(hasResult), napi_object_expected);
949    if (result) {
950        *result = hasResult->BooleaValue(vm);
951    }
952
953    return GET_RETURN_STATUS(env);
954}
955
956NAPI_EXTERN napi_status napi_set_named_property(napi_env env, napi_value object, const char* utf8name, napi_value value)
957{
958    NAPI_PREAMBLE(env);
959    CHECK_ARG(env, object);
960    CHECK_ARG(env, utf8name);
961    CHECK_ARG(env, value);
962
963    auto nativeValue = LocalValueFromJsValue(object);
964    auto propVal = LocalValueFromJsValue(value);
965    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
966    panda::JsiFastNativeScope fastNativeScope(vm);
967    RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm) || nativeValue->IsFunction(vm), napi_object_expected);
968    Local<panda::ObjectRef> obj(nativeValue);
969    obj->Set(vm, utf8name, propVal);
970
971    return GET_RETURN_STATUS(env);
972}
973
974NAPI_EXTERN napi_status napi_has_named_property(napi_env env, napi_value object, const char* utf8name, bool* result)
975{
976    NAPI_PREAMBLE(env);
977    CHECK_ARG(env, object);
978    CHECK_ARG(env, utf8name);
979    CHECK_ARG(env, result);
980
981    auto nativeValue = LocalValueFromJsValue(object);
982    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
983    panda::JsiFastNativeScope fastNativeScope(vm);
984    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, obj);
985    Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, utf8name);
986    *result = obj->Has(vm, key);
987
988    return GET_RETURN_STATUS(env);
989}
990
991NAPI_EXTERN napi_status napi_get_named_property(napi_env env,
992                                                napi_value object,
993                                                const char* utf8name,
994                                                napi_value* result)
995{
996    NAPI_PREAMBLE(env);
997    CHECK_ARG(env, object);
998    CHECK_ARG(env, utf8name);
999    CHECK_ARG(env, result);
1000
1001    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1002    panda::JsiFastNativeScope fastNativeScope(vm);
1003    Local<panda::JSValueRef> value = JSNApi::NapiGetNamedProperty(vm, reinterpret_cast<uintptr_t>(object), utf8name);
1004    RETURN_STATUS_IF_FALSE(env, NapiStatusValidationCheck(value), napi_object_expected);
1005#ifdef ENABLE_CONTAINER_SCOPE
1006    FunctionSetContainerId(vm, value);
1007#endif
1008    *result = JsValueFromLocalValue(value);
1009
1010    return GET_RETURN_STATUS(env);
1011}
1012
1013NAPI_EXTERN napi_status napi_get_own_property_descriptor(napi_env env,
1014                                                         napi_value object,
1015                                                         const char* utf8name,
1016                                                         napi_value* result)
1017{
1018    CHECK_ENV(env);
1019    CHECK_ARG(env, object);
1020    CHECK_ARG(env, utf8name);
1021    CHECK_ARG(env, result);
1022
1023    auto nativeValue = LocalValueFromJsValue(object);
1024    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1025    panda::JsiFastNativeScope fastNativeScope(vm);
1026    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, obj);
1027    Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, utf8name);
1028    panda::PropertyAttribute property;
1029    obj->GetOwnProperty(vm, key, property);
1030    *result = JsValueFromLocalValue(property.GetValue(vm));
1031    return napi_clear_last_error(env);
1032}
1033
1034NAPI_EXTERN napi_status napi_set_element(napi_env env, napi_value object, uint32_t index, napi_value value)
1035{
1036    NAPI_PREAMBLE(env);
1037    CHECK_ARG(env, object);
1038    CHECK_ARG(env, value);
1039
1040    auto nativeValue = LocalValueFromJsValue(object);
1041    auto elementValue = LocalValueFromJsValue(value);
1042    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1043    panda::JsiFastNativeScope fastNativeScope(vm);
1044    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, obj);
1045    obj->Set(vm, index, elementValue);
1046
1047    return GET_RETURN_STATUS(env);
1048}
1049
1050NAPI_EXTERN napi_status napi_has_element(napi_env env, napi_value object, uint32_t index, bool* result)
1051{
1052    NAPI_PREAMBLE(env);
1053    CHECK_ARG(env, object);
1054    CHECK_ARG(env, result);
1055
1056    auto nativeValue = LocalValueFromJsValue(object);
1057    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1058    panda::JsiFastNativeScope fastNativeScope(vm);
1059    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, obj);
1060    *result = obj->Has(vm, index);
1061
1062    return GET_RETURN_STATUS(env);
1063}
1064
1065NAPI_EXTERN napi_status napi_get_element(napi_env env, napi_value object, uint32_t index, napi_value* result)
1066{
1067    NAPI_PREAMBLE(env);
1068    CHECK_ARG(env, object);
1069    CHECK_ARG(env, result);
1070
1071    auto nativeValue = LocalValueFromJsValue(object);
1072    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1073    panda::JsiFastNativeScope fastNativeScope(vm);
1074    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, obj);
1075    Local<panda::JSValueRef> value = obj->Get(vm, index);
1076#ifdef ENABLE_CONTAINER_SCOPE
1077    FunctionSetContainerId(vm, value);
1078#endif
1079    *result = JsValueFromLocalValue(value);
1080
1081    return GET_RETURN_STATUS(env);
1082}
1083
1084NAPI_EXTERN napi_status napi_delete_element(napi_env env, napi_value object, uint32_t index, bool* result)
1085{
1086    NAPI_PREAMBLE(env);
1087    CHECK_ARG(env, object);
1088
1089    auto nativeValue = LocalValueFromJsValue(object);
1090    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1091    panda::JsiFastNativeScope fastNativeScope(vm);
1092    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, obj);
1093    bool deleteResult = obj->Delete(vm, index);
1094    if (result) {
1095        *result = deleteResult;
1096    }
1097
1098    return GET_RETURN_STATUS(env);
1099}
1100
1101NAPI_EXTERN napi_status napi_define_properties(napi_env env,
1102                                               napi_value object,
1103                                               size_t property_count,
1104                                               const napi_property_descriptor* properties)
1105{
1106    NAPI_PREAMBLE(env);
1107    CHECK_ARG(env, object);
1108    CHECK_ARG(env, properties);
1109
1110    auto nativeValue = LocalValueFromJsValue(object);
1111    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1112    panda::JsiFastNativeScope fastNativeScope(vm);
1113    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject);
1114
1115    auto nativeProperties = reinterpret_cast<const NapiPropertyDescriptor*>(properties);
1116    for (size_t i = 0; i < property_count; i++) {
1117        if (nativeProperties[i].utf8name == nullptr) {
1118            auto name = LocalValueFromJsValue(nativeProperties[i].name);
1119            RETURN_STATUS_IF_FALSE(env, !name.IsEmpty() && (name->IsString(vm) || name->IsSymbol(vm)),
1120                napi_name_expected);
1121        }
1122        NapiDefineProperty(env, nativeObject, nativeProperties[i]);
1123    }
1124    return GET_RETURN_STATUS(env);
1125}
1126
1127// Methods to work with Arrays
1128NAPI_EXTERN napi_status napi_is_array(napi_env env, napi_value value, bool* result)
1129{
1130    CHECK_ENV(env);
1131    CHECK_ARG(env, value);
1132    CHECK_ARG(env, result);
1133
1134    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1135    panda::JsiFastNativeScope fastNativeScope(vm);
1136
1137    auto nativeValue = LocalValueFromJsValue(value);
1138    *result = nativeValue->IsJSArray(vm) || nativeValue->IsSharedArray(vm);
1139    return napi_clear_last_error(env);
1140}
1141
1142NAPI_EXTERN napi_status napi_get_array_length(napi_env env, napi_value value, uint32_t* result)
1143{
1144    CHECK_ENV((env));
1145    RETURN_STATUS_IF_FALSE(env, (reinterpret_cast<NativeEngine*>(env))->lastException_.IsEmpty(),
1146        napi_pending_exception);
1147    CHECK_ARG(env, value);
1148    CHECK_ARG(env, result);
1149
1150    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1151    bool isArrayOrSharedArray = false;
1152    auto nativeValue = reinterpret_cast<panda::JSValueRef *>(value);
1153    nativeValue->TryGetArrayLength(vm, &isArrayOrSharedArray, result);
1154    if (!isArrayOrSharedArray) {
1155        HILOG_ERROR("argument is not type of array or sharedarray");
1156        return napi_set_last_error(env, napi_array_expected);
1157    }
1158    return napi_clear_last_error(env);
1159}
1160
1161NAPI_EXTERN napi_status napi_is_sendable(napi_env env, napi_value value, bool* result)
1162{
1163    CHECK_ENV(env);
1164    CHECK_ARG(env, value);
1165    CHECK_ARG(env, result);
1166
1167    auto nativeValue = LocalValueFromJsValue(value);
1168    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1169    panda::JsiFastNativeScope fastNativeScope(vm);
1170
1171    *result = nativeValue->IsJSShared(vm) || nativeValue->IsString(vm) || nativeValue->IsNumber() ||
1172              nativeValue->IsBoolean() || nativeValue->IsUndefined() || nativeValue->IsNull() ||
1173              nativeValue->IsBigInt(vm);
1174    return napi_clear_last_error(env);
1175}
1176
1177// Methods to compare values
1178NAPI_EXTERN napi_status napi_strict_equals(napi_env env, napi_value lhs, napi_value rhs, bool* result)
1179{
1180    CHECK_ENV(env);
1181    CHECK_ARG(env, lhs);
1182    CHECK_ARG(env, rhs);
1183    CHECK_ARG(env, result);
1184
1185    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1186    auto nativeLhs = LocalValueFromJsValue(lhs);
1187    auto nativeRhs = LocalValueFromJsValue(rhs);
1188    *result = nativeLhs->IsStrictEquals(vm, nativeRhs);
1189    return napi_clear_last_error(env);
1190}
1191
1192// Methods to work with Functions
1193NAPI_EXTERN napi_status napi_call_function(napi_env env,
1194                                           napi_value recv,
1195                                           napi_value func,
1196                                           size_t argc,
1197                                           const napi_value* argv,
1198                                           napi_value* result)
1199{
1200    CHECK_ENV((env));
1201    RETURN_STATUS_IF_FALSE((env), (reinterpret_cast<NativeEngine*>(env))->lastException_.IsEmpty(),
1202        napi_pending_exception);
1203    napi_clear_last_error((env));
1204    CHECK_ARG(env, func);
1205    if (argc > 0) {
1206        CHECK_ARG(env, argv);
1207    }
1208
1209    auto vm = reinterpret_cast<NativeEngine *>(env)->GetEcmaVm();
1210    panda::JsiFastNativeScope fastNativeScope(vm);
1211
1212    RETURN_STATUS_IF_FALSE(env, reinterpret_cast<panda::JSValueRef *>(func)->IsFunction(vm), napi_function_expected);
1213    panda::JSValueRef* thisObj = reinterpret_cast<panda::JSValueRef *>(recv);
1214    panda::FunctionRef* function = reinterpret_cast<panda::FunctionRef *>(func);
1215#ifdef ENABLE_CONTAINER_SCOPE
1216    int32_t scopeId = OHOS::Ace::ContainerScope::CurrentId();
1217    auto funcInfo = reinterpret_cast<NapiFunctionInfo *>(function->GetData(vm));
1218    if (funcInfo != nullptr) {
1219        scopeId = funcInfo->scopeId;
1220    }
1221    OHOS::Ace::ContainerScope containerScope(scopeId);
1222#endif
1223    panda::JSValueRef* value =
1224        function->CallForNapi(vm, thisObj, reinterpret_cast<panda::JSValueRef *const*>(argv), argc);
1225    // if pending exception, value will be a pointer to JSTaggedValue::Hole.
1226    if (UNLIKELY(!NapiStatusValidationCheck(value))) {
1227        HILOG_ERROR("pending exception when js function called, print exception info: ");
1228        panda::JSNApi::PrintExceptionInfo(vm);
1229        result = nullptr;
1230        reinterpret_cast<NativeEngine *>(env)->lastException_ = panda::JSNApi::GetUncaughtException(vm);
1231        return napi_set_last_error(env, napi_pending_exception);
1232    }
1233    if (result) {
1234        *result = reinterpret_cast<napi_value>(value);
1235    }
1236    return napi_clear_last_error(env);
1237}
1238
1239NAPI_EXTERN napi_status napi_new_instance(napi_env env,
1240                                          napi_value constructor,
1241                                          size_t argc,
1242                                          const napi_value* argv,
1243                                          napi_value* result)
1244{
1245    NAPI_PREAMBLE(env);
1246    CHECK_ARG(env, constructor);
1247    if (argc > 0) {
1248        CHECK_ARG(env, argv);
1249    }
1250    CHECK_ARG(env, result);
1251
1252    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1253    panda::JsiFastNativeScope fastNativeScope(vm);
1254
1255    RETURN_STATUS_IF_FALSE(env, reinterpret_cast<panda::JSValueRef*>(constructor)->IsFunction(vm),
1256        napi_function_expected);
1257    panda::FunctionRef* constructorVal = reinterpret_cast<panda::FunctionRef*>(constructor);
1258    panda::JSValueRef* instance = constructorVal->ConstructorOptimize(vm,
1259        reinterpret_cast<panda::JSValueRef**>(const_cast<napi_value*>(argv)), argc);
1260    if (tryCatch.HasCaught()) {
1261        HILOG_ERROR("CreateInstance occur Exception");
1262        *result = nullptr;
1263    } else {
1264        *result = reinterpret_cast<napi_value>(instance);
1265    }
1266    return GET_RETURN_STATUS(env);
1267}
1268
1269NAPI_EXTERN napi_status napi_instanceof(napi_env env, napi_value object, napi_value constructor, bool* result)
1270{
1271    NAPI_PREAMBLE(env);
1272    CHECK_ARG(env, object);
1273    CHECK_ARG(env, constructor);
1274    CHECK_ARG(env, result);
1275
1276    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1277    panda::JsiFastNativeScope fastNativeScope(vm);
1278
1279    auto nativeValue = LocalValueFromJsValue(object);
1280    auto nativeConstructor = LocalValueFromJsValue(constructor);
1281    RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
1282    RETURN_STATUS_IF_FALSE(env, nativeConstructor->IsFunction(vm), napi_function_expected);
1283    *result = nativeValue->InstanceOf(vm, nativeConstructor);
1284
1285    return GET_RETURN_STATUS(env);
1286}
1287
1288// Methods to work with napi_callbacks
1289// Gets all callback info in a single call. (Ugly, but faster.)
1290NAPI_EXTERN napi_status napi_get_cb_info(napi_env env,              // [in] NAPI environment handle
1291                                         napi_callback_info cbinfo, // [in] Opaque callback-info handle
1292                                         size_t* argc,         // [in-out] Specifies the size of the provided argv array
1293                                                               // and receives the actual count of args.
1294                                         napi_value* argv,     // [out] Array of values
1295                                         napi_value* this_arg, // [out] Receives the JS 'this' arg for the call
1296                                         void** data)          // [out] Receives the data pointer for the callback.
1297{
1298    CHECK_ENV(env);
1299    CHECK_ARG(env, cbinfo);
1300
1301    auto info = reinterpret_cast<panda::JsiRuntimeCallInfo*>(cbinfo);
1302    if ((argc != nullptr) && (argv != nullptr)) {
1303#ifdef ENABLE_CONTAINER_SCOPE
1304        auto *vm = info->GetVM();
1305#endif
1306        size_t i = 0;
1307        if (*argc > 0) {
1308            size_t j = static_cast<size_t>(info->GetArgsNumber());
1309            for (; i < j && i < *argc; i++) {
1310                panda::Local<panda::JSValueRef> value = info->GetCallArgRef(i);
1311#ifdef ENABLE_CONTAINER_SCOPE
1312                FunctionSetContainerId(vm, value);
1313#endif
1314                argv[i] = JsValueFromLocalValue(value);
1315            }
1316        } else {
1317            i = static_cast<size_t>(info->GetArgsNumber());
1318        }
1319        if (i < *argc) {
1320            napi_value undefined = JsValueFromLocalValue(
1321                panda::JSValueRef::Undefined(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm()));
1322            for (; i < *argc; i++) {
1323                argv[i] = undefined;
1324            }
1325        }
1326    }
1327    if (argc != nullptr) {
1328        *argc = static_cast<size_t>(info->GetArgsNumber());
1329    }
1330    if (this_arg != nullptr) {
1331        *this_arg = JsValueFromLocalValue(info->GetThisRef());
1332    }
1333    if (data != nullptr) {
1334        auto funcInfo = static_cast<NapiFunctionInfo*>(info->GetData());
1335        if (funcInfo != nullptr) {
1336            *data = funcInfo->data;
1337        }
1338    }
1339
1340    return napi_clear_last_error(env);
1341}
1342
1343NAPI_EXTERN napi_status napi_get_new_target(napi_env env, napi_callback_info cbinfo, napi_value* result)
1344{
1345    NAPI_PREAMBLE(env);
1346    CHECK_ARG(env, cbinfo);
1347    CHECK_ARG(env, result);
1348
1349    auto info = reinterpret_cast<panda::JsiRuntimeCallInfo*>(cbinfo);
1350    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1351    auto thisVarObj = info->GetThisRef();
1352#ifdef ENABLE_CONTAINER_SCOPE
1353    panda::Local<panda::JSValueRef> newValue = info->GetNewTargetRef();
1354    FunctionSetContainerId(vm, newValue);
1355    auto functionVal = newValue;
1356#else
1357    auto functionVal = info->GetNewTargetRef();
1358#endif
1359    if (thisVarObj->InstanceOf(vm, functionVal)) {
1360        *result = JsValueFromLocalValue(functionVal);
1361    } else {
1362        *result = nullptr;
1363    }
1364
1365    return GET_RETURN_STATUS(env);
1366}
1367
1368NAPI_EXTERN napi_status napi_define_class(napi_env env,
1369                                          const char* utf8name,
1370                                          size_t length,
1371                                          napi_callback constructor,
1372                                          void* data,
1373                                          size_t property_count,
1374                                          const napi_property_descriptor* properties,
1375                                          napi_value* result)
1376{
1377    NAPI_PREAMBLE(env);
1378    CHECK_ARG(env, utf8name);
1379    RETURN_STATUS_IF_FALSE(env, length == NAPI_AUTO_LENGTH || length <= INT_MAX, napi_object_expected);
1380    CHECK_ARG(env, constructor);
1381    if (property_count > 0) {
1382        CHECK_ARG(env, properties);
1383    }
1384    CHECK_ARG(env, result);
1385
1386    auto callback = reinterpret_cast<NapiNativeCallback>(constructor);
1387    auto nativeProperties = reinterpret_cast<const NapiPropertyDescriptor*>(properties);
1388
1389    size_t nameLength = std::min(length, strlen(utf8name));
1390    char newName[nameLength + 1];
1391    if (strncpy_s(newName, nameLength + 1, utf8name, nameLength) != EOK) {
1392        HILOG_ERROR("napi_define_class strncpy_s failed");
1393        *result = nullptr;
1394    } else {
1395        auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1396        panda::JsiFastNativeScope fastNativeScope(vm);
1397        EscapeLocalScope scope(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm());
1398        auto resultValue = NapiDefineClass(env, newName, callback, data, nativeProperties, property_count);
1399        *result = JsValueFromLocalValue(scope.Escape(resultValue));
1400    }
1401
1402    return GET_RETURN_STATUS(env);
1403}
1404
1405NAPI_EXTERN napi_status napi_define_sendable_class(napi_env env,
1406                                                   const char* utf8name,
1407                                                   size_t length,
1408                                                   napi_callback constructor,
1409                                                   void* data,
1410                                                   size_t property_count,
1411                                                   const napi_property_descriptor* properties,
1412                                                   napi_value parent,
1413                                                   napi_value* result)
1414{
1415    NAPI_PREAMBLE(env);
1416    CHECK_ARG(env, utf8name);
1417    RETURN_STATUS_IF_FALSE(env, length == NAPI_AUTO_LENGTH || length <= INT_MAX,
1418                           napi_object_expected);
1419    CHECK_ARG(env, constructor);
1420    if (property_count > 0) {
1421        CHECK_ARG(env, properties);
1422    }
1423    CHECK_ARG(env, result);
1424
1425    auto callback = reinterpret_cast<NapiNativeCallback>(constructor);
1426    auto nativeProperties = reinterpret_cast<const NapiPropertyDescriptor*>(properties);
1427
1428    size_t nameLength = std::min(length, strlen(utf8name));
1429    char newName[nameLength + 1];
1430    if (strncpy_s(newName, nameLength + 1, utf8name, nameLength) != EOK) {
1431        HILOG_ERROR("napi_define_sendable_class strncpy_s failed");
1432        *result = nullptr;
1433    } else {
1434        EscapeLocalScope scope(reinterpret_cast<NativeEngine*>(env)->GetEcmaVm());
1435        auto resultValue =
1436            NapiDefineSendableClass(env, newName, callback, data, nativeProperties, property_count, parent);
1437        *result = JsValueFromLocalValue(scope.Escape(resultValue));
1438    }
1439
1440    return GET_RETURN_STATUS(env);
1441}
1442
1443NAPI_EXTERN napi_status napi_create_sendable_object_with_properties(napi_env env,
1444                                                                    size_t property_count,
1445                                                                    const napi_property_descriptor* properties,
1446                                                                    napi_value* result)
1447{
1448    CHECK_ENV(env);
1449    CHECK_ARG(env, result);
1450
1451    auto nativeProperties = reinterpret_cast<const NapiPropertyDescriptor*>(properties);
1452    auto object = NapiCreateSObjectWithProperties(env, property_count, nativeProperties);
1453    *result = JsValueFromLocalValue(object);
1454
1455    return napi_clear_last_error(env);
1456}
1457
1458NAPI_EXTERN napi_status napi_create_map(napi_env env, napi_value* result)
1459{
1460    CHECK_ENV(env);
1461    CHECK_ARG(env, result);
1462
1463    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1464    Local<panda::ArrayRef> object = panda::MapRef::New(vm);
1465    *result = JsValueFromLocalValue(object);
1466
1467    return napi_clear_last_error(env);
1468}
1469
1470NAPI_EXTERN napi_status napi_create_sendable_map(napi_env env, napi_value* result)
1471{
1472    CHECK_ENV(env);
1473    CHECK_ARG(env, result);
1474
1475    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1476    Local<panda::ArrayRef> object = panda::SendableMapRef::New(vm);
1477    *result = JsValueFromLocalValue(object);
1478
1479    return napi_clear_last_error(env);
1480}
1481
1482NAPI_EXTERN napi_status napi_map_set_property(napi_env env, napi_value map, napi_value key, napi_value value)
1483{
1484    NAPI_PREAMBLE(env);
1485    CHECK_ARG(env, map);
1486    CHECK_ARG(env, key);
1487    CHECK_ARG(env, value);
1488
1489    auto nativeValue = LocalValueFromJsValue(map);
1490    auto propKey = LocalValueFromJsValue(key);
1491    auto propValue = LocalValueFromJsValue(value);
1492    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1493    panda::JsiFastNativeScope fastNativeScope(vm);
1494    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1495    if (LIKELY(nativeValue->IsMap(vm))) {
1496        Local<panda::MapRef> mapRef(nativeValue);
1497        mapRef->Set(vm, propKey, propValue);
1498    } else {
1499        Local<panda::SendableMapRef> mapRef(nativeValue);
1500        mapRef->Set(vm, propKey, propValue);
1501    }
1502
1503    return GET_RETURN_STATUS(env);
1504}
1505
1506NAPI_EXTERN napi_status napi_map_set_named_property(napi_env env,
1507                                                    napi_value map,
1508                                                    const char* utf8name,
1509                                                    napi_value value)
1510{
1511    NAPI_PREAMBLE(env);
1512    CHECK_ARG(env, map);
1513    CHECK_ARG(env, utf8name);
1514    CHECK_ARG(env, value);
1515
1516    auto nativeValue = LocalValueFromJsValue(map);
1517    auto propVal = LocalValueFromJsValue(value);
1518    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1519    panda::JsiFastNativeScope fastNativeScope(vm);
1520    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1521    Local<panda::MapRef> mapRef(nativeValue);
1522    if (LIKELY(nativeValue->IsMap(vm))) {
1523        Local<panda::MapRef> mapRef(nativeValue);
1524        mapRef->Set(vm, utf8name, propVal);
1525    } else {
1526        Local<panda::SendableMapRef> mapRef(nativeValue);
1527        mapRef->Set(vm, utf8name, propVal);
1528    }
1529
1530    return GET_RETURN_STATUS(env);
1531}
1532
1533NAPI_EXTERN napi_status napi_map_get_property(napi_env env, napi_value map, napi_value key, napi_value* result)
1534{
1535    NAPI_PREAMBLE(env);
1536    CHECK_ARG(env, map);
1537    CHECK_ARG(env, key);
1538    CHECK_ARG(env, result);
1539
1540    auto nativeValue = LocalValueFromJsValue(map);
1541    auto propKey = LocalValueFromJsValue(key);
1542    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1543    panda::JsiFastNativeScope fastNativeScope(vm);
1544    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1545    Local<JSValueRef> value;
1546    if (LIKELY(nativeValue->IsMap(vm))) {
1547        Local<panda::MapRef> mapRef(nativeValue);
1548        value = mapRef->Get(vm, propKey);
1549    } else {
1550        Local<panda::SendableMapRef> mapRef(nativeValue);
1551        value = mapRef->Get(vm, propKey);
1552    }
1553    RETURN_STATUS_IF_FALSE(env, NapiStatusValidationCheck(value), napi_object_expected);
1554    *result = JsValueFromLocalValue(value);
1555
1556    return GET_RETURN_STATUS(env);
1557}
1558
1559NAPI_EXTERN napi_status napi_map_get_named_property(napi_env env,
1560                                                    napi_value map,
1561                                                    const char* utf8name,
1562                                                    napi_value* result)
1563{
1564    NAPI_PREAMBLE(env);
1565    CHECK_ARG(env, map);
1566    CHECK_ARG(env, utf8name);
1567    CHECK_ARG(env, result);
1568
1569    auto nativeValue = LocalValueFromJsValue(map);
1570    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1571    panda::JsiFastNativeScope fastNativeScope(vm);
1572    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1573    Local<JSValueRef> value;
1574    if (LIKELY(nativeValue->IsMap(vm))) {
1575        Local<panda::MapRef> mapRef(nativeValue);
1576        value = mapRef->Get(vm, utf8name);
1577    } else {
1578        Local<panda::SendableMapRef> mapRef(nativeValue);
1579        value = mapRef->Get(vm, utf8name);
1580    }
1581    RETURN_STATUS_IF_FALSE(env, NapiStatusValidationCheck(value), napi_object_expected);
1582    *result = JsValueFromLocalValue(value);
1583
1584    return GET_RETURN_STATUS(env);
1585}
1586
1587NAPI_EXTERN napi_status napi_map_has_property(napi_env env, napi_value map, napi_value key, bool* result)
1588{
1589    NAPI_PREAMBLE(env);
1590    CHECK_ARG(env, map);
1591    CHECK_ARG(env, key);
1592    CHECK_ARG(env, result);
1593
1594    auto nativeValue = LocalValueFromJsValue(map);
1595    auto propKey = LocalValueFromJsValue(key);
1596    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1597    panda::JsiFastNativeScope fastNativeScope(vm);
1598    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1599    bool value;
1600    if (LIKELY(nativeValue->IsMap(vm))) {
1601        Local<panda::MapRef> mapRef(nativeValue);
1602        value = mapRef->Has(vm, propKey);
1603    } else {
1604        Local<panda::SendableMapRef> mapRef(nativeValue);
1605        value = mapRef->Has(vm, propKey);
1606    }
1607    *result = value;
1608
1609    return GET_RETURN_STATUS(env);
1610}
1611
1612NAPI_EXTERN napi_status napi_map_has_named_property(napi_env env, napi_value map, const char* utf8name, bool* result)
1613{
1614    NAPI_PREAMBLE(env);
1615    CHECK_ARG(env, map);
1616    CHECK_ARG(env, utf8name);
1617    CHECK_ARG(env, result);
1618
1619    auto nativeValue = LocalValueFromJsValue(map);
1620    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1621    panda::JsiFastNativeScope fastNativeScope(vm);
1622    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1623    bool value;
1624    if (LIKELY(nativeValue->IsMap(vm))) {
1625        Local<panda::MapRef> mapRef(nativeValue);
1626        value = mapRef->Has(vm, utf8name);
1627    } else {
1628        Local<panda::SendableMapRef> mapRef(nativeValue);
1629        value = mapRef->Has(vm, utf8name);
1630    }
1631    *result = value;
1632
1633    return GET_RETURN_STATUS(env);
1634}
1635
1636NAPI_EXTERN napi_status napi_map_delete_property(napi_env env, napi_value map, napi_value key)
1637{
1638    NAPI_PREAMBLE(env);
1639    CHECK_ARG(env, map);
1640    CHECK_ARG(env, key);
1641
1642    auto nativeValue = LocalValueFromJsValue(map);
1643    auto propKey = LocalValueFromJsValue(key);
1644    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1645    panda::JsiFastNativeScope fastNativeScope(vm);
1646    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1647    if (LIKELY(nativeValue->IsMap(vm))) {
1648        Local<panda::MapRef> mapRef(nativeValue);
1649        mapRef->Delete(vm, propKey);
1650    } else {
1651        Local<panda::SendableMapRef> mapRef(nativeValue);
1652        mapRef->Delete(vm, propKey);
1653    }
1654
1655    return GET_RETURN_STATUS(env);
1656}
1657
1658NAPI_EXTERN napi_status napi_map_clear(napi_env env, napi_value map)
1659{
1660    NAPI_PREAMBLE(env);
1661    CHECK_ARG(env, map);
1662
1663    auto nativeValue = LocalValueFromJsValue(map);
1664    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1665    panda::JsiFastNativeScope fastNativeScope(vm);
1666    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1667    if (LIKELY(nativeValue->IsMap(vm))) {
1668        Local<panda::MapRef> mapRef(nativeValue);
1669        mapRef->Clear(vm);
1670    } else {
1671        Local<panda::SendableMapRef> mapRef(nativeValue);
1672        mapRef->Clear(vm);
1673    }
1674
1675    return GET_RETURN_STATUS(env);
1676}
1677
1678NAPI_EXTERN napi_status napi_map_get_size(napi_env env, napi_value map, uint32_t* result)
1679{
1680    NAPI_PREAMBLE(env);
1681    CHECK_ARG(env, map);
1682    CHECK_ARG(env, result);
1683
1684    auto nativeValue = LocalValueFromJsValue(map);
1685    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1686    panda::JsiFastNativeScope fastNativeScope(vm);
1687    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1688    uint32_t value;
1689    if (LIKELY(nativeValue->IsMap(vm))) {
1690        Local<panda::MapRef> mapRef(nativeValue);
1691        value = static_cast<uint32_t>(mapRef->GetSize(vm));
1692    } else {
1693        Local<panda::SendableMapRef> mapRef(nativeValue);
1694        value = static_cast<uint32_t>(mapRef->GetSize(vm));
1695    }
1696    *result = value;
1697
1698    return GET_RETURN_STATUS(env);
1699}
1700
1701NAPI_EXTERN napi_status napi_map_get_entries(napi_env env, napi_value map, napi_value* result)
1702{
1703    NAPI_PREAMBLE(env);
1704    CHECK_ARG(env, map);
1705    CHECK_ARG(env, result);
1706
1707    auto nativeValue = LocalValueFromJsValue(map);
1708    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1709    panda::JsiFastNativeScope fastNativeScope(vm);
1710    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1711    if (LIKELY(nativeValue->IsMap(vm))) {
1712        Local<panda::MapRef> mapRef(nativeValue);
1713        Local<panda::ArrayRef> arrayVal = mapRef->GetEntries(vm);
1714        *result = JsValueFromLocalValue(arrayVal);
1715    } else {
1716        Local<panda::SendableMapRef> mapRef(nativeValue);
1717        Local<panda::SendableArrayRef> arrayVal = mapRef->GetEntries(vm);
1718        *result = JsValueFromLocalValue(arrayVal);
1719    }
1720    return GET_RETURN_STATUS(env);
1721}
1722
1723NAPI_EXTERN napi_status napi_map_get_keys(napi_env env, napi_value map, napi_value* result)
1724{
1725    NAPI_PREAMBLE(env);
1726    CHECK_ARG(env, map);
1727    CHECK_ARG(env, result);
1728
1729    auto nativeValue = LocalValueFromJsValue(map);
1730    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1731    panda::JsiFastNativeScope fastNativeScope(vm);
1732    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1733    if (LIKELY(nativeValue->IsMap(vm))) {
1734        Local<panda::MapRef> mapRef(nativeValue);
1735        Local<panda::ArrayRef> arrayVal = mapRef->GetKeys(vm);
1736        *result = JsValueFromLocalValue(arrayVal);
1737    } else {
1738        Local<panda::SendableMapRef> mapRef(nativeValue);
1739        Local<panda::SendableArrayRef> arrayVal = mapRef->GetKeys(vm);
1740        *result = JsValueFromLocalValue(arrayVal);
1741    }
1742    return GET_RETURN_STATUS(env);
1743}
1744
1745NAPI_EXTERN napi_status napi_map_get_values(napi_env env, napi_value map, napi_value* result)
1746{
1747    NAPI_PREAMBLE(env);
1748    CHECK_ARG(env, map);
1749    CHECK_ARG(env, result);
1750
1751    auto nativeValue = LocalValueFromJsValue(map);
1752    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1753    panda::JsiFastNativeScope fastNativeScope(vm);
1754    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm), napi_object_expected);
1755    if (LIKELY(nativeValue->IsMap(vm))) {
1756        Local<panda::MapRef> mapRef(nativeValue);
1757        Local<panda::ArrayRef> arrayVal = mapRef->GetValues(vm);
1758        *result = JsValueFromLocalValue(arrayVal);
1759    } else {
1760        Local<panda::SendableMapRef> mapRef(nativeValue);
1761        Local<panda::SendableArrayRef> arrayVal = mapRef->GetValues(vm);
1762        *result = JsValueFromLocalValue(arrayVal);
1763    }
1764    return GET_RETURN_STATUS(env);
1765}
1766
1767NAPI_EXTERN napi_status napi_map_iterator_get_next(napi_env env, napi_value iterator, napi_value* result)
1768{
1769    NAPI_PREAMBLE(env);
1770    CHECK_ARG(env, iterator);
1771    CHECK_ARG(env, result);
1772
1773    auto nativeValue = LocalValueFromJsValue(iterator);
1774    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1775    panda::JsiFastNativeScope fastNativeScope(vm);
1776    RETURN_STATUS_IF_FALSE(env, nativeValue->IsMapIterator(vm) || nativeValue->IsSharedMapIterator(vm),
1777                           napi_object_expected);
1778    Local<panda::JSValueRef> value;
1779    if (LIKELY(nativeValue->IsMapIterator(vm))) {
1780        Local<panda::MapIteratorRef> mapIter(nativeValue);
1781        value = mapIter->Next(vm);
1782    } else {
1783        Local<panda::SendableMapIteratorRef> mapIter(nativeValue);
1784        value = mapIter->Next(vm);
1785    }
1786    *result = JsValueFromLocalValue(value);
1787    return GET_RETURN_STATUS(env);
1788}
1789
1790// Methods to work with external data objects
1791NAPI_EXTERN napi_status napi_wrap(napi_env env,
1792                                  napi_value js_object,
1793                                  void* native_object,
1794                                  napi_finalize finalize_cb,
1795                                  void* finalize_hint,
1796                                  napi_ref* result)
1797{
1798    NAPI_PREAMBLE(env);
1799    CHECK_ARG(env, js_object);
1800    CHECK_ARG(env, native_object);
1801    CHECK_ARG(env, finalize_cb);
1802
1803    auto nativeValue = LocalValueFromJsValue(js_object);
1804    auto callback = reinterpret_cast<NapiNativeFinalize>(finalize_cb);
1805    auto engine = reinterpret_cast<NativeEngine*>(env);
1806    auto vm = engine->GetEcmaVm();
1807    panda::JsiFastNativeScope fastNativeScope(vm);
1808    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject);
1809    size_t nativeBindingSize = 0;
1810    auto reference = reinterpret_cast<NativeReference**>(result);
1811    Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1812    if (native_object == nullptr && nativeObject->Has(vm, key)) {
1813        Local<panda::ObjectRef> wrapper = nativeObject->Get(vm, key);
1814        auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(vm, 0));
1815        // Try to remove native pointer from ArrayDataList
1816        wrapper->SetNativePointerField(vm, 0, nullptr, nullptr, nullptr, nativeBindingSize);
1817        nativeObject->Delete(vm, key);
1818        delete ref;
1819    } else {
1820        Local<panda::ObjectRef> object = panda::ObjectRef::New(vm);
1821        NativeReference* ref = nullptr;
1822        if (reference != nullptr) {
1823            ref = engine->CreateReference(js_object, 1, false, callback, native_object, finalize_hint);
1824            *reference = ref;
1825        } else {
1826            ref = engine->CreateReference(js_object, 0, true, callback, native_object, finalize_hint);
1827        }
1828        object->SetNativePointerFieldCount(vm, 1);
1829        object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, nativeBindingSize);
1830        PropertyAttribute attr(object, true, false, true);
1831        nativeObject->DefineProperty(vm, key, attr);
1832    }
1833    return GET_RETURN_STATUS(env);
1834}
1835
1836// Ensure thread safety! Async finalizer will be called on the async thread.
1837NAPI_EXTERN napi_status napi_wrap_async_finalizer(napi_env env,
1838                                                  napi_value js_object,
1839                                                  void* native_object,
1840                                                  napi_finalize finalize_cb,
1841                                                  void* finalize_hint,
1842                                                  napi_ref* result,
1843                                                  size_t native_binding_size)
1844{
1845    NAPI_PREAMBLE(env);
1846    CHECK_ARG(env, js_object);
1847    CHECK_ARG(env, native_object);
1848
1849    auto nativeValue = LocalValueFromJsValue(js_object);
1850    auto callback = reinterpret_cast<NapiNativeFinalize>(finalize_cb);
1851    auto engine = reinterpret_cast<NativeEngine*>(env);
1852    auto vm = engine->GetEcmaVm();
1853    panda::JsiFastNativeScope fastNativeScope(vm);
1854    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject);
1855    auto reference = reinterpret_cast<NativeReference**>(result);
1856    Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1857    if (native_object == nullptr && nativeObject->Has(vm, key)) {
1858        Local<panda::ObjectRef> wrapper = nativeObject->Get(vm, key);
1859        auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(vm, 0));
1860        // Try to remove native pointer from ArrayDataList
1861        wrapper->SetNativePointerField(vm, 0, nullptr, nullptr, nullptr, native_binding_size);
1862        nativeObject->Delete(vm, key);
1863        delete ref;
1864    } else {
1865        Local<panda::ObjectRef> object = panda::ObjectRef::New(vm);
1866        NativeReference* ref = nullptr;
1867        if (reference != nullptr) {
1868            ref = engine->CreateAsyncReference(js_object, 1, false, callback, native_object, finalize_hint);
1869            *reference = ref;
1870        } else {
1871            ref = engine->CreateAsyncReference(js_object, 0, true, callback, native_object, finalize_hint);
1872        }
1873        object->SetNativePointerFieldCount(vm, 1);
1874        object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, native_binding_size);
1875        PropertyAttribute attr(object, true, false, true);
1876        nativeObject->DefineProperty(vm, key, attr);
1877    }
1878    return GET_RETURN_STATUS(env);
1879}
1880
1881// Methods to work with external data objects
1882NAPI_EXTERN napi_status napi_wrap_with_size(napi_env env,
1883                                            napi_value js_object,
1884                                            void* native_object,
1885                                            napi_finalize finalize_cb,
1886                                            void* finalize_hint,
1887                                            napi_ref* result,
1888                                            size_t native_binding_size)
1889{
1890    NAPI_PREAMBLE(env);
1891    CHECK_ARG(env, js_object);
1892    CHECK_ARG(env, native_object);
1893
1894    auto nativeValue = LocalValueFromJsValue(js_object);
1895    auto callback = reinterpret_cast<NapiNativeFinalize>(finalize_cb);
1896    auto engine = reinterpret_cast<NativeEngine*>(env);
1897    auto vm = engine->GetEcmaVm();
1898    panda::JsiFastNativeScope fastNativeScope(vm);
1899    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject);
1900    auto reference = reinterpret_cast<NativeReference**>(result);
1901    Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1902    if (native_object == nullptr && nativeObject->Has(vm, key)) {
1903        Local<panda::ObjectRef> wrapper = nativeObject->Get(vm, key);
1904        auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(vm, 0));
1905        // Try to remove native pointer from ArrayDataList
1906        wrapper->SetNativePointerField(vm, 0, nullptr, nullptr, nullptr, native_binding_size);
1907        nativeObject->Delete(vm, key);
1908        delete ref;
1909    } else {
1910        Local<panda::ObjectRef> object = panda::ObjectRef::New(vm);
1911        NativeReference* ref = nullptr;
1912        if (reference != nullptr) {
1913            ref = engine->CreateReference(js_object, 1, false, callback, native_object, finalize_hint,
1914                                          native_binding_size);
1915            *reference = ref;
1916        } else {
1917            ref = engine->CreateReference(js_object, 0, true, callback, native_object, finalize_hint,
1918                                          native_binding_size);
1919        }
1920        object->SetNativePointerFieldCount(vm, 1);
1921        object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, native_binding_size);
1922        PropertyAttribute attr(object, true, false, true);
1923        nativeObject->DefineProperty(vm, key, attr);
1924    }
1925
1926    return GET_RETURN_STATUS(env);
1927}
1928
1929NAPI_EXTERN napi_status napi_unwrap(napi_env env, napi_value js_object, void** result)
1930{
1931    NAPI_PREAMBLE(env);
1932    CHECK_ARG(env, js_object);
1933    CHECK_ARG(env, result);
1934
1935    auto nativeValue = LocalValueFromJsValue(js_object);
1936    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
1937    panda::JsiFastNativeScope fastNativeScope(vm);
1938    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject);
1939    Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1940    Local<panda::JSValueRef> val = nativeObject->Get(vm, key);
1941    *result = nullptr;
1942    if (val->IsObject(vm)) {
1943        Local<panda::ObjectRef> ext(val);
1944        auto ref = reinterpret_cast<NativeReference*>(ext->GetNativePointerField(vm, 0));
1945        *result = ref != nullptr ? ref->GetData() : nullptr;
1946    }
1947
1948    return GET_RETURN_STATUS(env);
1949}
1950
1951NAPI_EXTERN napi_status napi_remove_wrap(napi_env env, napi_value js_object, void** result)
1952{
1953    NAPI_PREAMBLE(env);
1954    CHECK_ARG(env, js_object);
1955    CHECK_ARG(env, result);
1956
1957    auto nativeValue = LocalValueFromJsValue(js_object);
1958    auto engine = reinterpret_cast<NativeEngine*>(env);
1959    auto vm = engine->GetEcmaVm();
1960    panda::JsiFastNativeScope fastNativeScope(vm);
1961    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, nativeObject);
1962    Local<panda::StringRef> key = panda::StringRef::GetNapiWrapperString(vm);
1963    Local<panda::JSValueRef> val = nativeObject->Get(vm, key);
1964    *result = nullptr;
1965    if (val->IsObject(vm)) {
1966        Local<panda::ObjectRef> ext(val);
1967        auto ref = reinterpret_cast<NativeReference*>(ext->GetNativePointerField(vm, 0));
1968        *result = ref != nullptr ? ref->GetData() : nullptr;
1969    }
1970
1971    size_t nativeBindingSize = 0;
1972    if (nativeObject->Has(vm, key)) {
1973        Local<panda::ObjectRef> wrapper = val;
1974        auto ref = reinterpret_cast<NativeReference*>(wrapper->GetNativePointerField(vm, 0));
1975        nativeObject->Delete(vm, key);
1976        delete ref;
1977    } else {
1978        Local<panda::ObjectRef> object = panda::ObjectRef::New(vm);
1979        NativeReference* ref = nullptr;
1980        ref = engine->CreateReference(js_object, 0, true, nullptr, nullptr, nullptr);
1981        object->SetNativePointerFieldCount(vm, 1);
1982        object->SetNativePointerField(vm, 0, ref, nullptr, nullptr, nativeBindingSize);
1983        PropertyAttribute attr(object, true, false, true);
1984        nativeObject->DefineProperty(vm, key, attr);
1985    }
1986
1987    return GET_RETURN_STATUS(env);
1988}
1989
1990NAPI_EXTERN napi_status napi_wrap_sendable(napi_env env,
1991                                           napi_value js_object,
1992                                           void* native_object,
1993                                           napi_finalize finalize_cb,
1994                                           void* finalize_hint)
1995{
1996    NAPI_PREAMBLE(env);
1997    CHECK_ARG(env, js_object);
1998    CHECK_ARG(env, native_object);
1999
2000    auto nativeValue = LocalValueFromJsValue(js_object);
2001    auto callback = reinterpret_cast<panda::NativePointerCallback>(finalize_cb);
2002    auto engine = reinterpret_cast<NativeEngine*>(env);
2003    auto vm = engine->GetEcmaVm();
2004    panda::JsiFastNativeScope fastNativeScope(vm);
2005    RETURN_STATUS_IF_FALSE(env, nativeValue->IsSendableObject(vm), napi_object_expected);
2006    Local<ObjectRef> nativeObject(nativeValue);
2007    nativeObject->SetNativePointerFieldCount(vm, 1);
2008    nativeObject->SetNativePointerField(vm, 0, native_object, callback, finalize_hint);
2009    return GET_RETURN_STATUS(env);
2010}
2011
2012NAPI_EXTERN napi_status napi_wrap_sendable_with_size(napi_env env,
2013                                                     napi_value js_object,
2014                                                     void* native_object,
2015                                                     napi_finalize finalize_cb,
2016                                                     void* finalize_hint,
2017                                                     size_t native_binding_size)
2018{
2019    NAPI_PREAMBLE(env);
2020    CHECK_ARG(env, js_object);
2021    CHECK_ARG(env, native_object);
2022
2023    auto nativeValue = LocalValueFromJsValue(js_object);
2024    auto callback = reinterpret_cast<panda::NativePointerCallback>(finalize_cb);
2025    auto engine = reinterpret_cast<NativeEngine*>(env);
2026    auto vm = engine->GetEcmaVm();
2027    panda::JsiFastNativeScope fastNativeScope(vm);
2028    RETURN_STATUS_IF_FALSE(env, nativeValue->IsSendableObject(vm), napi_object_expected);
2029    Local<ObjectRef> nativeObject(nativeValue);
2030    nativeObject->SetNativePointerFieldCount(vm, 1);
2031    nativeObject->SetNativePointerField(vm, 0, native_object, callback, finalize_hint, native_binding_size);
2032    return GET_RETURN_STATUS(env);
2033}
2034
2035NAPI_EXTERN napi_status napi_unwrap_sendable(napi_env env, napi_value js_object, void** result)
2036{
2037    NAPI_PREAMBLE(env);
2038    CHECK_ARG(env, js_object);
2039    CHECK_ARG(env, result);
2040
2041    auto nativeValue = LocalValueFromJsValue(js_object);
2042    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2043    panda::JsiFastNativeScope fastNativeScope(vm);
2044    RETURN_STATUS_IF_FALSE(env, nativeValue->IsSendableObject(vm), napi_object_expected);
2045    Local<ObjectRef> nativeObject(nativeValue);
2046    void* val = nativeObject->GetNativePointerField(vm, 0);
2047    *result = val;
2048    return GET_RETURN_STATUS(env);
2049}
2050
2051NAPI_EXTERN napi_status napi_remove_wrap_sendable(napi_env env, napi_value js_object, void** result)
2052{
2053    NAPI_PREAMBLE(env);
2054    CHECK_ARG(env, js_object);
2055    CHECK_ARG(env, result);
2056
2057    auto nativeValue = LocalValueFromJsValue(js_object);
2058    auto engine = reinterpret_cast<NativeEngine*>(env);
2059    auto vm = engine->GetEcmaVm();
2060    panda::JsiFastNativeScope fastNativeScope(vm);
2061    RETURN_STATUS_IF_FALSE(env, nativeValue->IsSendableObject(vm), napi_object_expected);
2062    Local<ObjectRef> nativeObject(nativeValue);
2063    void* val = nativeObject->GetNativePointerField(vm, 0);
2064    *result = val;
2065    nativeObject->SetNativePointerField(vm, 0, nullptr, nullptr, nullptr);
2066
2067    return GET_RETURN_STATUS(env);
2068}
2069
2070NAPI_EXTERN napi_status napi_create_external(
2071    napi_env env, void* data, napi_finalize finalize_cb, void* finalize_hint, napi_value* result)
2072{
2073    NAPI_PREAMBLE(env);
2074    CHECK_ARG(env, result);
2075
2076    auto engine = reinterpret_cast<NativeEngine*>(env);
2077    auto vm = engine->GetEcmaVm();
2078    auto callback = reinterpret_cast<panda::NativePointerCallback>(finalize_cb);
2079    Local<panda::NativePointerRef> object = panda::NativePointerRef::New(vm, data, callback, finalize_hint, 0);
2080
2081    *result = JsValueFromLocalValue(object);
2082    return napi_clear_last_error(env);
2083}
2084
2085NAPI_EXTERN napi_status napi_create_external_with_size(napi_env env,
2086                                                       void* data,
2087                                                       napi_finalize finalize_cb,
2088                                                       void* finalize_hint,
2089                                                       napi_value* result,
2090                                                       size_t native_binding_size)
2091{
2092    CHECK_ENV(env);
2093    CHECK_ARG(env, result);
2094
2095    auto engine = reinterpret_cast<NativeEngine*>(env);
2096    auto vm = engine->GetEcmaVm();
2097    auto callback = reinterpret_cast<panda::NativePointerCallback>(finalize_cb);
2098    Local<panda::NativePointerRef> object =
2099        panda::NativePointerRef::New(vm, data, callback, finalize_hint, native_binding_size);
2100
2101    *result = JsValueFromLocalValue(object);
2102    return napi_clear_last_error(env);
2103}
2104
2105NAPI_EXTERN napi_status napi_get_value_external(napi_env env, napi_value value, void** result)
2106{
2107    CHECK_ENV(env);
2108    CHECK_ARG(env, value);
2109    CHECK_ARG(env, result);
2110
2111    auto nativeValue = LocalValueFromJsValue(value);
2112    bool isNativePointer = false;
2113    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2114    void* ret = nativeValue->GetNativePointerValue(vm, isNativePointer);
2115    RETURN_STATUS_IF_FALSE(env, isNativePointer, napi_object_expected);
2116    *result = ret;
2117    return napi_clear_last_error(env);
2118}
2119
2120// Methods to control object lifespan
2121// Set initial_refcount to 0 for a weak reference, >0 for a strong reference.
2122NAPI_EXTERN napi_status napi_create_reference(napi_env env,
2123                                              napi_value value,
2124                                              uint32_t initial_refcount,
2125                                              napi_ref* result)
2126{
2127    CHECK_ENV(env);
2128    CHECK_ARG(env, value);
2129    CHECK_ARG(env, result);
2130    auto engine = reinterpret_cast<ArkNativeEngine*>(env);
2131    auto ref = new ArkNativeReference(engine, value, initial_refcount);
2132
2133    *result = reinterpret_cast<napi_ref>(ref);
2134    return napi_clear_last_error(env);
2135}
2136
2137// Deletes a reference. The referenced value is released, and may
2138// be GC'd unless there are other references to it.
2139NAPI_EXTERN napi_status napi_delete_reference(napi_env env, napi_ref ref)
2140{
2141    CHECK_ENV(env);
2142    CHECK_ARG(env, ref);
2143
2144    auto reference = reinterpret_cast<NativeReference*>(ref);
2145    uint32_t refCount = reference->GetRefCount();
2146    if (refCount > 0 || reference->GetFinalRun()) {
2147        delete reference;
2148        reference = nullptr;
2149    } else {
2150        reference->SetDeleteSelf();
2151    }
2152
2153    return napi_clear_last_error(env);
2154}
2155
2156// Increments the reference count, optionally returning the resulting count.
2157// After this call the  reference will be a strong reference because its
2158// refcount is >0, and the referenced object is effectively "pinned".
2159// Calling this when the refcount is 0 and the object is unavailable
2160// results in an error.
2161NAPI_EXTERN napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result)
2162{
2163    CHECK_ENV(env);
2164    CHECK_ARG(env, ref);
2165
2166    auto reference = reinterpret_cast<NativeReference*>(ref);
2167    uint32_t refCount = reference->Ref();
2168
2169    if (result) {
2170        *result = refCount;
2171    }
2172
2173    return napi_clear_last_error(env);
2174}
2175
2176// Decrements the reference count, optionally returning the resulting count.
2177// If the result is 0 the reference is now weak and the object may be GC'd
2178// at any time if there are no other references. Calling this when the
2179// refcount is already 0 results in an error.
2180NAPI_EXTERN napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result)
2181{
2182    CHECK_ENV(env);
2183    CHECK_ARG(env, ref);
2184
2185    auto reference = reinterpret_cast<NativeReference*>(ref);
2186    uint32_t unrefCount = reference->Unref();
2187
2188    if (result) {
2189        *result = unrefCount;
2190    }
2191
2192    return napi_clear_last_error(env);
2193}
2194
2195// Attempts to get a referenced value. If the reference is weak,
2196// the value might no longer be available, in that case the call
2197// is still successful but the result is nullptr.
2198NAPI_EXTERN napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value* result)
2199{
2200    CHECK_ENV(env);
2201    CHECK_ARG(env, ref);
2202    CHECK_ARG(env, result);
2203
2204    auto reference = reinterpret_cast<NativeReference*>(ref);
2205    NativeEngine* engine = reinterpret_cast<NativeEngine*>(env);
2206
2207    *result = reference->Get(engine);
2208    return napi_clear_last_error(env);
2209}
2210
2211NAPI_EXTERN napi_status napi_open_handle_scope(napi_env env, napi_handle_scope* result)
2212{
2213    CHECK_ENV(env);
2214    CHECK_ARG(env, result);
2215
2216    auto engine = reinterpret_cast<NativeEngine*>(env);
2217    *result = HandleScopeToNapiHandleScope(new HandleScopeWrapper(engine));
2218    engine->openHandleScopes_++;
2219    return napi_clear_last_error(env);
2220}
2221
2222NAPI_EXTERN napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope)
2223{
2224    CHECK_ENV(env);
2225    CHECK_ARG(env, scope);
2226
2227    auto engine = reinterpret_cast<NativeEngine*>(env);
2228    if (engine->openHandleScopes_ == 0) {
2229        return napi_handle_scope_mismatch;
2230    }
2231
2232    engine->openHandleScopes_--;
2233    delete NapiHandleScopeToHandleScope(scope);
2234    return napi_clear_last_error(env);
2235}
2236
2237NAPI_EXTERN napi_status napi_open_escapable_handle_scope(napi_env env, napi_escapable_handle_scope* result)
2238{
2239    CHECK_ENV(env);
2240    CHECK_ARG(env, result);
2241
2242    auto engine = reinterpret_cast<NativeEngine*>(env);
2243    *result = EscapableHandleScopeToNapiEscapableHandleScope(new EscapableHandleScopeWrapper(engine));
2244    engine->openHandleScopes_++;
2245    return napi_clear_last_error(env);
2246}
2247
2248NAPI_EXTERN napi_status napi_close_escapable_handle_scope(napi_env env, napi_escapable_handle_scope scope)
2249{
2250    CHECK_ENV(env);
2251    CHECK_ARG(env, scope);
2252
2253    auto engine = reinterpret_cast<NativeEngine*>(env);
2254    if (engine->openHandleScopes_ == 0) {
2255        return napi_handle_scope_mismatch;
2256    }
2257
2258    engine->openHandleScopes_--;
2259    delete NapiEscapableHandleScopeToEscapableHandleScope(scope);
2260    return napi_clear_last_error(env);
2261}
2262
2263NAPI_EXTERN napi_status napi_escape_handle(napi_env env,
2264                                           napi_escapable_handle_scope scope,
2265                                           napi_value escapee,
2266                                           napi_value* result)
2267{
2268    CHECK_ENV(env);
2269    CHECK_ARG(env, scope);
2270    CHECK_ARG(env, escapee);
2271    CHECK_ARG(env, result);
2272
2273    auto s = NapiEscapableHandleScopeToEscapableHandleScope(scope);
2274    if (!s->IsEscapeCalled()) {
2275        *result = JsValueFromLocalValue(s->Escape(LocalValueFromJsValue(escapee)));
2276        return napi_clear_last_error(env);
2277    }
2278    return napi_set_last_error(env, napi_escape_called_twice);
2279}
2280
2281// Methods to support error handling
2282NAPI_EXTERN napi_status napi_throw(napi_env env, napi_value error)
2283{
2284    CHECK_ENV(env);
2285    CHECK_ARG(env, error);
2286
2287    auto nativeValue = LocalValueFromJsValue(error);
2288    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2289    panda::JsiFastNativeScope fastNativeScope(vm);
2290
2291    RETURN_STATUS_IF_FALSE(env, nativeValue->IsError(vm), napi_invalid_arg);
2292    panda::JSNApi::ThrowException(vm, nativeValue);
2293    return napi_clear_last_error(env);
2294}
2295
2296NAPI_EXTERN napi_status napi_throw_error(napi_env env, const char* code, const char* msg)
2297{
2298    CHECK_ENV(env);
2299    CHECK_ARG(env, msg);
2300
2301    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2302    panda::JsiFastNativeScope fastNativeScope(vm);
2303    Local<panda::JSValueRef> error(panda::JSValueRef::Undefined(vm));
2304    error = panda::Exception::Error(vm, StringRef::NewFromUtf8(vm, msg));
2305    if (code != nullptr) {
2306        Local<panda::JSValueRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
2307        Local<panda::JSValueRef> codeValue = panda::StringRef::NewFromUtf8(vm, code);
2308        Local<panda::ObjectRef> errorObj(error);
2309        errorObj->Set(vm, codeKey, codeValue);
2310    }
2311    panda::JSNApi::ThrowException(vm, error);
2312    return napi_clear_last_error(env);
2313}
2314
2315NAPI_EXTERN napi_status napi_throw_type_error(napi_env env, const char* code, const char* msg)
2316{
2317    CHECK_ENV(env);
2318    CHECK_ARG(env, msg);
2319
2320    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2321    panda::JsiFastNativeScope fastNativeScope(vm);
2322    Local<panda::JSValueRef> error(panda::JSValueRef::Undefined(vm));
2323    error = panda::Exception::TypeError(vm, StringRef::NewFromUtf8(vm, msg));
2324    if (code != nullptr) {
2325        Local<panda::JSValueRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
2326        Local<panda::JSValueRef> codeValue = panda::StringRef::NewFromUtf8(vm, code);
2327        Local<panda::ObjectRef> errorObj(error);
2328        errorObj->Set(vm, codeKey, codeValue);
2329    }
2330    panda::JSNApi::ThrowException(vm, error);
2331    return napi_clear_last_error(env);
2332}
2333
2334NAPI_EXTERN napi_status napi_throw_range_error(napi_env env, const char* code, const char* msg)
2335{
2336    CHECK_ENV(env);
2337    CHECK_ARG(env, msg);
2338
2339    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2340    panda::JsiFastNativeScope fastNativeScope(vm);
2341    Local<panda::JSValueRef> error(panda::JSValueRef::Undefined(vm));
2342    error = panda::Exception::RangeError(vm, StringRef::NewFromUtf8(vm, msg));
2343    if (code != nullptr) {
2344        Local<panda::JSValueRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
2345        Local<panda::JSValueRef> codeValue = panda::StringRef::NewFromUtf8(vm, code);
2346        Local<panda::ObjectRef> errorObj(error);
2347        errorObj->Set(vm, codeKey, codeValue);
2348    }
2349    panda::JSNApi::ThrowException(vm, error);
2350    return napi_clear_last_error(env);
2351}
2352
2353NAPI_EXTERN napi_status napi_is_error(napi_env env, napi_value value, bool* result)
2354{
2355    CHECK_ENV(env);
2356    CHECK_ARG(env, value);
2357    CHECK_ARG(env, result);
2358
2359    auto nativeValue = LocalValueFromJsValue(value);
2360    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2361    panda::JsiFastNativeScope fastNativeScope(vm);
2362    *result = nativeValue->IsError(vm);
2363
2364    return napi_clear_last_error(env);
2365}
2366
2367// Methods to support catching exceptions
2368NAPI_EXTERN napi_status napi_is_exception_pending(napi_env env, bool* result)
2369{
2370    CHECK_ENV(env);
2371    CHECK_ARG(env, result);
2372
2373    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2374    *result = panda::JSNApi::HasPendingException(vm);
2375    return napi_clear_last_error(env);
2376}
2377
2378NAPI_EXTERN napi_status napi_get_and_clear_last_exception(napi_env env, napi_value* result)
2379{
2380    CHECK_ENV(env);
2381    CHECK_ARG(env, result);
2382
2383    auto engine = reinterpret_cast<NativeEngine*>(env);
2384    auto vm = engine->GetEcmaVm();
2385    engine->lastException_.Empty();
2386    Local<panda::ObjectRef> exception = panda::JSNApi::GetAndClearUncaughtException(vm);
2387    if (!exception.IsNull()) {
2388        *result = JsValueFromLocalValue(exception);
2389    }
2390
2391    return napi_clear_last_error(env);
2392}
2393
2394// Methods to work with array buffers and typed arrays
2395NAPI_EXTERN napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result)
2396{
2397    CHECK_ENV(env);
2398    CHECK_ARG(env, value);
2399    CHECK_ARG(env, result);
2400
2401    auto nativeValue = LocalValueFromJsValue(value);
2402    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2403    panda::JsiFastNativeScope fastNativeScope(vm);
2404
2405    *result = nativeValue->IsArrayBuffer(vm) || nativeValue->IsSendableArrayBuffer(vm);
2406
2407    return napi_clear_last_error(env);
2408}
2409
2410NAPI_EXTERN napi_status napi_create_arraybuffer(napi_env env, size_t byte_length, void** data, napi_value* result)
2411{
2412    NAPI_PREAMBLE(env);
2413    CHECK_ARG(env, data);
2414    CHECK_ARG(env, result);
2415
2416    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2417    uint8_t** values = (uint8_t**)(data);
2418    Local<panda::ArrayBufferRef> res = panda::ArrayBufferRef::New(vm, byte_length);
2419    if (values != nullptr) {
2420        *values = reinterpret_cast<uint8_t*>(res->GetBuffer(vm));
2421    }
2422    *result = JsValueFromLocalValue(res);
2423
2424    return GET_RETURN_STATUS(env);
2425}
2426
2427NAPI_EXTERN napi_status napi_create_sendable_arraybuffer(napi_env env, size_t byte_length,
2428                                                         void** data, napi_value* result)
2429{
2430    NAPI_PREAMBLE(env);
2431    CHECK_ARG(env, data);
2432    CHECK_ARG(env, result);
2433
2434    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2435    uint8_t** values = (uint8_t**)(data);
2436    Local<panda::SendableArrayBufferRef> res = panda::SendableArrayBufferRef::New(vm, byte_length);
2437    if (values != nullptr) {
2438        *values = reinterpret_cast<uint8_t*>(res->GetBuffer(vm));
2439    }
2440    *result = JsValueFromLocalValue(res);
2441
2442    return GET_RETURN_STATUS(env);
2443}
2444
2445NAPI_EXTERN napi_status napi_create_external_arraybuffer(napi_env env,
2446                                                         void* external_data,
2447                                                         size_t byte_length,
2448                                                         napi_finalize finalize_cb,
2449                                                         void* finalize_hint,
2450                                                         napi_value* result)
2451{
2452    NAPI_PREAMBLE(env);
2453    CHECK_ARG(env, external_data);
2454    CHECK_ARG(env, finalize_cb);
2455    CHECK_ARG(env, result);
2456
2457    auto engine = reinterpret_cast<NativeEngine*>(env);
2458    auto vm = engine->GetEcmaVm();
2459    auto callback = reinterpret_cast<panda::NativePointerCallback>(finalize_cb);
2460    Local<panda::ArrayBufferRef> object =
2461        panda::ArrayBufferRef::New(vm, external_data, byte_length, callback, finalize_hint);
2462    *result = JsValueFromLocalValue(object);
2463    return GET_RETURN_STATUS(env);
2464}
2465
2466NAPI_EXTERN napi_status napi_get_arraybuffer_info(napi_env env,
2467                                                  napi_value arraybuffer,
2468                                                  void** data,
2469                                                  size_t* byte_length)
2470{
2471    CHECK_ENV(env);
2472    CHECK_ARG(env, arraybuffer);
2473    CHECK_ARG(env, byte_length);
2474
2475    auto nativeValue = LocalValueFromJsValue(arraybuffer);
2476    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2477    panda::JsiFastNativeScope fastNativeScope(vm);
2478    if (LIKELY(nativeValue->IsArrayBuffer(vm))) {
2479        Local<panda::ArrayBufferRef> res(nativeValue);
2480        if (data != nullptr) {
2481            *data = res->GetBuffer(vm);
2482        }
2483        *byte_length = res->ByteLength(vm);
2484    } else if (nativeValue->IsSendableArrayBuffer(vm)) {
2485        Local<panda::SendableArrayBufferRef> res(nativeValue);
2486        if (data != nullptr) {
2487            *data = res->GetBuffer(vm);
2488        }
2489        *byte_length = res->ByteLength(vm);
2490    } else {
2491        return napi_set_last_error(env, napi_arraybuffer_expected);
2492    }
2493
2494    return napi_clear_last_error(env);
2495}
2496
2497NAPI_EXTERN napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result)
2498{
2499    CHECK_ENV(env);
2500    CHECK_ARG(env, value);
2501    CHECK_ARG(env, result);
2502
2503    auto nativeValue = LocalValueFromJsValue(value);
2504    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2505    panda::JsiFastNativeScope fastNativeScope(vm);
2506
2507    *result = nativeValue->IsTypedArray(vm) || nativeValue->IsSharedTypedArray(vm);
2508
2509    return napi_clear_last_error(env);
2510}
2511
2512EXTERN_C_START
2513NAPI_EXTERN napi_status napi_is_buffer(napi_env env, napi_value value, bool* result)
2514{
2515    CHECK_ENV(env);
2516    CHECK_ARG(env, value);
2517    CHECK_ARG(env, result);
2518
2519    auto nativeValue = LocalValueFromJsValue(value);
2520    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2521    panda::JsiFastNativeScope fastNativeScope(vm);
2522
2523    *result = nativeValue->IsBuffer(vm);
2524
2525    return napi_clear_last_error(env);
2526}
2527
2528NAPI_EXTERN napi_status napi_create_buffer(napi_env env, size_t size, void** data, napi_value* result)
2529{
2530    CHECK_ENV(env);
2531    CHECK_ARG(env, data);
2532    CHECK_ARG(env, result);
2533    RETURN_STATUS_IF_FALSE(env, size > 0, napi_invalid_arg);
2534
2535    uint8_t** value =  reinterpret_cast<uint8_t**>(data);
2536    if (!value) {
2537        HILOG_ERROR("value is empty");
2538        return napi_set_last_error(env, napi_invalid_arg);
2539    }
2540
2541    if (size > MAX_BYTE_LENGTH) {
2542        HILOG_ERROR("Creat failed, current size: %{public}2f MiB, limit size: %{public}2f MiB",
2543                    static_cast<float>(size) / static_cast<float>(ONEMIB_BYTE_SIZE),
2544                    static_cast<float>(MAX_BYTE_LENGTH) / static_cast<float>(ONEMIB_BYTE_SIZE));
2545        *value = nullptr;
2546        return napi_set_last_error(env, napi_invalid_arg);
2547    }
2548    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2549    Local<panda::BufferRef> obj = BufferRef::New(vm, size);
2550    *value = reinterpret_cast<uint8_t*>(obj->GetBuffer(vm));
2551
2552    CHECK_ARG(env, *data);
2553    void* ptr = obj->GetBuffer(vm);
2554    CHECK_ARG(env, ptr);
2555
2556    *result = JsValueFromLocalValue(obj);
2557    return napi_clear_last_error(env);
2558}
2559
2560NAPI_EXTERN napi_status napi_create_buffer_copy(napi_env env,
2561                                                size_t length,
2562                                                const void* data,
2563                                                void** result_data,
2564                                                napi_value* result)
2565{
2566    CHECK_ENV(env);
2567    CHECK_ARG(env, data);
2568    CHECK_ARG(env, result_data);
2569    CHECK_ARG(env, result);
2570    RETURN_STATUS_IF_FALSE(env, length > 0, napi_invalid_arg);
2571
2572    uint8_t** value = reinterpret_cast<uint8_t**>(result_data);
2573    const uint8_t* recvdata = (uint8_t*)data;
2574    if (!value) {
2575        HILOG_ERROR("value is empty");
2576        return napi_set_last_error(env, napi_invalid_arg);
2577    }
2578    if (length > MAX_BYTE_LENGTH) {
2579        HILOG_ERROR("Creat failed, current size: %{public}2f MiB, limit size: %{public}2f MiB",
2580                    static_cast<float>(length) / static_cast<float>(ONEMIB_BYTE_SIZE),
2581                    static_cast<float>(MAX_BYTE_LENGTH) / static_cast<float>(ONEMIB_BYTE_SIZE));
2582        *value = nullptr;
2583        return napi_set_last_error(env, napi_invalid_arg);
2584    }
2585    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2586    Local<panda::BufferRef> obj = BufferRef::New(vm, length);
2587    if (obj->IsUndefined()) {
2588        HILOG_INFO("engine create buffer_copy failed!");
2589    }
2590    *value = reinterpret_cast<uint8_t*>(obj->GetBuffer(vm));
2591    if (memcpy_s(*value, length, recvdata, length) != EOK) {
2592        HILOG_ERROR("memcpy_s failed");
2593    }
2594
2595    void* ptr = obj->GetBuffer(vm);
2596    CHECK_ARG(env, ptr);
2597
2598    *result = JsValueFromLocalValue(obj);
2599    return napi_clear_last_error(env);
2600}
2601
2602NAPI_EXTERN napi_status napi_create_external_buffer(napi_env env,
2603                                                    size_t length,
2604                                                    void* data,
2605                                                    napi_finalize finalize_cb,
2606                                                    void* finalize_hint,
2607                                                    napi_value* result)
2608{
2609    NAPI_PREAMBLE(env);
2610    CHECK_ARG(env, result);
2611    CHECK_ARG(env, data);
2612    RETURN_STATUS_IF_FALSE(env, length > 0, napi_invalid_arg);
2613
2614    auto callback = reinterpret_cast<panda::NativePointerCallback>(finalize_cb);
2615    if (!data) {
2616        HILOG_ERROR("data is empty");
2617        return napi_set_last_error(env, napi_invalid_arg);
2618    }
2619    if (length > MAX_BYTE_LENGTH) {
2620        HILOG_ERROR("Creat failed, current size: %{public}2f MiB, limit size: %{public}2f MiB",
2621                    static_cast<float>(length) / static_cast<float>(ONEMIB_BYTE_SIZE),
2622                    static_cast<float>(MAX_BYTE_LENGTH) / static_cast<float>(ONEMIB_BYTE_SIZE));
2623        data = nullptr;
2624        return napi_set_last_error(env, napi_invalid_arg);
2625    }
2626
2627    auto engine = reinterpret_cast<NativeEngine*>(env);
2628    auto vm = engine->GetEcmaVm();
2629    Local<panda::BufferRef> object = panda::BufferRef::New(vm, data, length, callback, finalize_hint);
2630    void* ptr = object->GetBuffer(vm);
2631    CHECK_ARG(env, ptr);
2632
2633    *result = JsValueFromLocalValue(object);
2634    return GET_RETURN_STATUS(env);
2635}
2636
2637NAPI_EXTERN napi_status napi_get_buffer_info(napi_env env, napi_value value, void** data, size_t* length)
2638{
2639    CHECK_ENV(env);
2640    CHECK_ARG(env, value);
2641
2642    auto nativeValue = LocalValueFromJsValue(value);
2643    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2644    panda::JsiFastNativeScope fastNativeScope(vm);
2645    RETURN_STATUS_IF_FALSE(env, nativeValue->IsBuffer(vm), napi_status::napi_arraybuffer_expected);
2646    Local<panda::BufferRef> res(nativeValue);
2647    *data = res->GetBuffer(vm);
2648    *length = res->ByteLength(vm);
2649
2650    return napi_clear_last_error(env);
2651}
2652
2653NAPI_EXTERN napi_status napi_object_freeze(napi_env env, napi_value object)
2654{
2655    NAPI_PREAMBLE(env);
2656    CHECK_ARG(env, object);
2657
2658    auto nativeValue = LocalValueFromJsValue(object);
2659    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2660    panda::JsiFastNativeScope fastNativeScope(vm);
2661    RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
2662    Local<panda::ObjectRef> obj = nativeValue->ToEcmaObject(vm);
2663    obj->Freeze(vm);
2664
2665    return GET_RETURN_STATUS(env);
2666}
2667
2668NAPI_EXTERN napi_status napi_object_seal(napi_env env, napi_value object)
2669{
2670    NAPI_PREAMBLE(env);
2671    CHECK_ARG(env, object);
2672
2673    auto nativeValue = LocalValueFromJsValue(object);
2674    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2675    panda::JsiFastNativeScope fastNativeScope(vm);
2676    RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
2677    Local<panda::ObjectRef> obj = nativeValue->ToEcmaObject(vm);
2678    obj->Seal(vm);
2679
2680    return GET_RETURN_STATUS(env);
2681}
2682
2683EXTERN_C_END
2684
2685NAPI_EXTERN napi_status napi_create_typedarray(napi_env env,
2686                                               napi_typedarray_type type,
2687                                               size_t length,
2688                                               napi_value arraybuffer,
2689                                               size_t byte_offset,
2690                                               napi_value* result)
2691{
2692    NAPI_PREAMBLE(env);
2693    CHECK_ARG(env, arraybuffer);
2694    CHECK_ARG(env, result);
2695
2696    auto value = LocalValueFromJsValue(arraybuffer);
2697    auto typedArrayType = (NativeTypedArrayType)type;
2698    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2699    panda::JsiFastNativeScope fastNativeScope(vm);
2700    RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(vm), napi_status::napi_arraybuffer_expected);
2701    Local<panda::ArrayBufferRef> arrayBuf(value);
2702
2703    if (!reinterpret_cast<NativeEngine*>(env)->NapiNewTypedArray(vm, typedArrayType, arrayBuf,
2704                                                                 byte_offset, length, result)) {
2705        HILOG_ERROR("%{public}s invalid arg", __func__);
2706        return napi_set_last_error(env, napi_invalid_arg);
2707    }
2708    return GET_RETURN_STATUS(env);
2709}
2710
2711NAPI_EXTERN napi_status napi_create_sendable_typedarray(napi_env env,
2712                                                        napi_typedarray_type type,
2713                                                        size_t length,
2714                                                        napi_value arraybuffer,
2715                                                        size_t byte_offset,
2716                                                        napi_value* result)
2717{
2718    NAPI_PREAMBLE(env);
2719    CHECK_ARG(env, arraybuffer);
2720    CHECK_ARG(env, result);
2721
2722    auto value = LocalValueFromJsValue(arraybuffer);
2723    auto typedArrayType = (NativeTypedArrayType)type;
2724    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2725    panda::JsiFastNativeScope fastNativeScope(vm);
2726    RETURN_STATUS_IF_FALSE(env, value->IsSendableArrayBuffer(vm), napi_status::napi_arraybuffer_expected);
2727    Local<panda::SendableArrayBufferRef> arrayBuf(value);
2728
2729    if (!reinterpret_cast<NativeEngine*>(env)->NapiNewSendableTypedArray(vm, typedArrayType,
2730                                                                         arrayBuf, byte_offset,
2731                                                                         length, result)) {
2732        HILOG_ERROR("%{public}s invalid arg", __func__);
2733        return napi_set_last_error(env, napi_invalid_arg);
2734    }
2735    return GET_RETURN_STATUS(env);
2736}
2737
2738NAPI_EXTERN napi_status napi_get_typedarray_info(napi_env env,
2739                                                 napi_value typedarray,
2740                                                 napi_typedarray_type* type,
2741                                                 size_t* length,
2742                                                 void** data,
2743                                                 napi_value* arraybuffer,
2744                                                 size_t* byte_offset)
2745{
2746    CHECK_ENV(env);
2747    CHECK_ARG(env, typedarray);
2748
2749    auto value = LocalValueFromJsValue(typedarray);
2750    auto engine = reinterpret_cast<NativeEngine*>(env);
2751    auto vm = engine->GetEcmaVm();
2752    panda::JsiFastNativeScope fastNativeScope(vm);
2753    if (LIKELY(value->IsTypedArray(vm))) {
2754        Local<panda::TypedArrayRef> typedArray = Local<panda::TypedArrayRef>(value);
2755        Local<ArrayBufferRef> localArrayBuffer = typedArray->GetArrayBuffer(vm);
2756        size_t byteoffset = typedArray->ByteOffset(vm);
2757        if (type != nullptr) {
2758            *type = static_cast<napi_typedarray_type>(engine->GetTypedArrayType(typedArray));
2759        }
2760        if (length != nullptr) {
2761            *length = typedArray->ByteLength(vm);
2762        }
2763        if (data != nullptr) {
2764            *data = static_cast<uint8_t*>(localArrayBuffer->GetBuffer(vm)) + byteoffset;
2765        }
2766        if (arraybuffer != nullptr) {
2767            *arraybuffer = JsValueFromLocalValue(localArrayBuffer);
2768        }
2769        if (byte_offset != nullptr) {
2770            *byte_offset = byteoffset;
2771        }
2772    } else if (value->IsSharedTypedArray(vm)) {
2773        Local<panda::SendableTypedArrayRef> typedArray = Local<panda::SendableTypedArrayRef>(value);
2774        Local<panda::SendableArrayBufferRef> localArrayBuffer = typedArray->GetArrayBuffer(vm);
2775        size_t byteoffset = typedArray->ByteOffset(vm);
2776        if (type != nullptr) {
2777            *type = static_cast<napi_typedarray_type>(engine->GetSendableTypedArrayType(typedArray));
2778        }
2779        if (length != nullptr) {
2780            *length = typedArray->ByteLength(vm);
2781        }
2782        if (data != nullptr) {
2783            *data = static_cast<uint8_t*>(localArrayBuffer->GetBuffer(vm)) + byteoffset;
2784        }
2785        if (arraybuffer != nullptr) {
2786            *arraybuffer = JsValueFromLocalValue(localArrayBuffer);
2787        }
2788        if (byte_offset != nullptr) {
2789            *byte_offset = byteoffset;
2790        }
2791    } else {
2792        HILOG_ERROR("%{public}s invalid arg", __func__);
2793        return napi_set_last_error(env, napi_invalid_arg);
2794    }
2795
2796    return napi_clear_last_error(env);
2797}
2798
2799NAPI_EXTERN napi_status napi_create_dataview(napi_env env,
2800                                             size_t length,
2801                                             napi_value arraybuffer,
2802                                             size_t byte_offset,
2803                                             napi_value* result)
2804{
2805    NAPI_PREAMBLE(env);
2806    CHECK_ARG(env, arraybuffer);
2807    CHECK_ARG(env, result);
2808
2809    auto arrayBufferValue = LocalValueFromJsValue(arraybuffer);
2810    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2811    panda::JsiFastNativeScope fastNativeScope(vm);
2812    RETURN_STATUS_IF_FALSE(env, arrayBufferValue->IsArrayBuffer(vm), napi_status::napi_arraybuffer_expected);
2813    Local<panda::ArrayBufferRef> res(arrayBufferValue);
2814    if (length + byte_offset > static_cast<size_t>(res->ByteLength(vm))) {
2815        napi_throw_range_error(
2816            env,
2817            "ERR_NAPI_INVALID_DATAVIEW_ARGS",
2818            "byte_offset + byte_length should be less than or "
2819            "equal to the size in bytes of the array passed in");
2820        return napi_set_last_error(env, napi_pending_exception);
2821    }
2822
2823    Local<panda::DataViewRef> dataView = panda::DataViewRef::New(vm, res, byte_offset, length);
2824    *result = JsValueFromLocalValue(dataView);
2825    return GET_RETURN_STATUS(env);
2826}
2827
2828NAPI_EXTERN napi_status napi_is_dataview(napi_env env, napi_value value, bool* result)
2829{
2830    CHECK_ENV(env);
2831    CHECK_ARG(env, value);
2832    CHECK_ARG(env, result);
2833
2834    auto nativeValue = LocalValueFromJsValue(value);
2835    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2836    panda::JsiFastNativeScope fastNativeScope(vm);
2837    *result = nativeValue->IsDataView(vm);
2838
2839    return napi_clear_last_error(env);
2840}
2841
2842NAPI_EXTERN napi_status napi_get_dataview_info(napi_env env,
2843                                               napi_value dataview,
2844                                               size_t* bytelength,
2845                                               void** data,
2846                                               napi_value* arraybuffer,
2847                                               size_t* byte_offset)
2848{
2849    CHECK_ENV(env);
2850    CHECK_ARG(env, dataview);
2851
2852    auto nativeValue = LocalValueFromJsValue(dataview);
2853    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2854    bool isDataView = false;
2855    nativeValue->GetDataViewInfo(vm, isDataView, bytelength, data,
2856        reinterpret_cast<panda::JSValueRef**>(arraybuffer), byte_offset);
2857    RETURN_STATUS_IF_FALSE(env, isDataView, napi_status::napi_invalid_arg);
2858
2859    return napi_clear_last_error(env);
2860}
2861
2862// version management
2863NAPI_EXTERN napi_status napi_get_version(napi_env env, uint32_t* result)
2864{
2865    CHECK_ENV(env);
2866    CHECK_ARG(env, result);
2867
2868    *result = NAPI_VERSION;
2869    return napi_clear_last_error(env);
2870}
2871
2872// Promises
2873NAPI_EXTERN napi_status napi_create_promise(napi_env env, napi_deferred* deferred, napi_value* promise)
2874{
2875    NAPI_PREAMBLE(env);
2876    CHECK_ARG(env, deferred);
2877    CHECK_ARG(env, promise);
2878
2879    auto engine = reinterpret_cast<NativeEngine*>(env);
2880    NativeDeferred* nativeDeferred = nullptr;
2881    auto resultValue = engine->CreatePromise(&nativeDeferred);
2882    if (LocalValueFromJsValue(resultValue)->IsUndefined()) {
2883        return napi_set_last_error(env, napi_generic_failure);
2884    }
2885    *deferred = reinterpret_cast<napi_deferred>(nativeDeferred);
2886    *promise = resultValue;
2887
2888    return GET_RETURN_STATUS(env);
2889}
2890
2891NAPI_EXTERN napi_status napi_resolve_deferred(napi_env env, napi_deferred deferred, napi_value resolution)
2892{
2893    NAPI_PREAMBLE(env);
2894    CHECK_ARG(env, deferred);
2895    CHECK_ARG(env, resolution);
2896
2897    auto nativeDeferred = reinterpret_cast<NativeDeferred*>(deferred);
2898    nativeDeferred->Resolve(resolution);
2899    delete nativeDeferred;
2900    return GET_RETURN_STATUS(env);
2901}
2902
2903NAPI_EXTERN napi_status napi_reject_deferred(napi_env env, napi_deferred deferred, napi_value rejection)
2904{
2905    NAPI_PREAMBLE(env);
2906    CHECK_ARG(env, deferred);
2907    CHECK_ARG(env, rejection);
2908
2909    auto nativeDeferred = reinterpret_cast<NativeDeferred*>(deferred);
2910    nativeDeferred->Reject(rejection);
2911    delete nativeDeferred;
2912    return GET_RETURN_STATUS(env);
2913}
2914
2915NAPI_EXTERN napi_status napi_is_promise(napi_env env, napi_value value, bool* is_promise)
2916{
2917    CHECK_ENV(env);
2918    CHECK_ARG(env, value);
2919    CHECK_ARG(env, is_promise);
2920
2921    auto nativeValue = LocalValueFromJsValue(value);
2922    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
2923    panda::JsiFastNativeScope fastNativeScope(vm);
2924    *is_promise = nativeValue->IsPromise(vm);
2925
2926    return napi_clear_last_error(env);
2927}
2928
2929// promise reject events
2930NAPI_EXTERN napi_status napi_set_promise_rejection_callback(napi_env env, napi_ref ref, napi_ref checkRef)
2931{
2932    CHECK_ENV(env);
2933    CHECK_ARG(env, ref);
2934    CHECK_ARG(env, checkRef);
2935
2936    auto rejectCallbackRef = reinterpret_cast<NativeReference*>(ref);
2937    auto checkCallbackRef = reinterpret_cast<NativeReference*>(checkRef);
2938    if (rejectCallbackRef == nullptr || checkCallbackRef == nullptr) {
2939        HILOG_ERROR("rejectCallbackRef or checkCallbackRef is nullptr");
2940    } else {
2941        auto engine = reinterpret_cast<NativeEngine*>(env);
2942        auto vm = const_cast<EcmaVM*>(engine->GetEcmaVm());
2943        engine->SetPromiseRejectCallBackRef(rejectCallbackRef);
2944        engine->SetCheckCallbackRef(checkCallbackRef);
2945        panda::JSNApi::SetHostPromiseRejectionTracker(const_cast<EcmaVM*>(vm), engine->GetPromiseRejectCallback(),
2946                                                      reinterpret_cast<void*>(engine));
2947    }
2948
2949    return napi_clear_last_error(env);
2950}
2951
2952// Running a script
2953NAPI_EXTERN napi_status napi_run_script(napi_env env, napi_value script, napi_value* result)
2954{
2955    CHECK_ENV(env);
2956    CHECK_ARG(env, script);
2957    CHECK_ARG(env, result);
2958
2959    *result = nullptr;
2960    return napi_clear_last_error(env);
2961}
2962
2963NAPI_EXTERN napi_status napi_run_actor(napi_env env,
2964                                       uint8_t* buffer,
2965                                       size_t bufferSize,
2966                                       const char* descriptor,
2967                                       napi_value* result,
2968                                       char* entryPoint)
2969{
2970    NAPI_PREAMBLE(env);
2971    CHECK_ARG(env, result);
2972
2973    auto engine = reinterpret_cast<NativeEngine*>(env);
2974    *result = engine->RunActor(buffer, bufferSize, descriptor, entryPoint, false);
2975    return GET_RETURN_STATUS(env);
2976}
2977
2978NAPI_EXTERN napi_status napi_load_module(napi_env env, const char* path, napi_value* result)
2979{
2980    NAPI_PREAMBLE(env);
2981    CHECK_ARG(env, result);
2982    auto engine = reinterpret_cast<NativeEngine*>(env);
2983    *result = engine->NapiLoadModule(path, nullptr);
2984    return GET_RETURN_STATUS(env);
2985}
2986
2987NAPI_EXTERN napi_status napi_load_module_with_info(napi_env env,
2988                                                   const char* path,
2989                                                   const char* module_info,
2990                                                   napi_value* result)
2991{
2992    NAPI_PREAMBLE(env);
2993    CHECK_ARG(env, result);
2994    auto engine = reinterpret_cast<NativeEngine*>(env);
2995    *result = engine->NapiLoadModuleWithInfo(path, module_info);
2996    return GET_RETURN_STATUS(env);
2997}
2998// Memory management
2999NAPI_INNER_EXTERN napi_status napi_adjust_external_memory(
3000    napi_env env, int64_t change_in_bytes, int64_t* adjusted_value)
3001{
3002    CHECK_ENV(env);
3003    CHECK_ARG(env, adjusted_value);
3004
3005    auto engine = reinterpret_cast<NativeEngine*>(env);
3006    engine->AdjustExternalMemory(change_in_bytes, adjusted_value);
3007
3008    return napi_clear_last_error(env);
3009}
3010
3011NAPI_EXTERN napi_status napi_is_callable(napi_env env, napi_value value, bool* result)
3012{
3013    CHECK_ENV(env);
3014    CHECK_ARG(env, value);
3015    CHECK_ARG(env, result);
3016
3017    auto nativeValue = LocalValueFromJsValue(value);
3018    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3019    panda::JsiFastNativeScope fastNativeScope(vm);
3020
3021    *result = nativeValue->IsFunction(vm);
3022
3023    return napi_clear_last_error(env);
3024}
3025
3026NAPI_EXTERN napi_status napi_is_arguments_object(napi_env env, napi_value value, bool* result)
3027{
3028    CHECK_ENV(env);
3029    CHECK_ARG(env, value);
3030    CHECK_ARG(env, result);
3031
3032    auto nativeValue = LocalValueFromJsValue(value);
3033    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3034    panda::JsiFastNativeScope fastNativeScope(vm);
3035
3036    *result = nativeValue->IsArgumentsObject(vm);
3037
3038    return napi_clear_last_error(env);
3039}
3040
3041NAPI_EXTERN napi_status napi_is_async_function(napi_env env, napi_value value, bool* result)
3042{
3043    CHECK_ENV(env);
3044    CHECK_ARG(env, value);
3045    CHECK_ARG(env, result);
3046
3047    auto nativeValue = LocalValueFromJsValue(value);
3048    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3049    panda::JsiFastNativeScope fastNativeScope(vm);
3050
3051    *result = nativeValue->IsAsyncFunction(vm);
3052    return napi_clear_last_error(env);
3053}
3054
3055NAPI_EXTERN napi_status napi_is_boolean_object(napi_env env, napi_value value, bool* result)
3056{
3057    CHECK_ENV(env);
3058    CHECK_ARG(env, value);
3059    CHECK_ARG(env, result);
3060
3061    auto nativeValue = LocalValueFromJsValue(value);
3062    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3063    panda::JsiFastNativeScope fastNativeScope(vm);
3064
3065    *result = nativeValue->IsJSPrimitiveBoolean(vm);
3066
3067    return napi_clear_last_error(env);
3068}
3069
3070NAPI_EXTERN napi_status napi_is_generator_function(napi_env env, napi_value value, bool* result)
3071{
3072    CHECK_ENV(env);
3073    CHECK_ARG(env, value);
3074    CHECK_ARG(env, result);
3075
3076    auto nativeValue = LocalValueFromJsValue(value);
3077    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3078    panda::JsiFastNativeScope fastNativeScope(vm);
3079
3080    *result = nativeValue->IsGeneratorFunction(vm);
3081
3082    return napi_clear_last_error(env);
3083}
3084
3085NAPI_EXTERN napi_status napi_is_map_iterator(napi_env env, napi_value value, bool* result)
3086{
3087    CHECK_ENV(env);
3088    CHECK_ARG(env, value);
3089    CHECK_ARG(env, result);
3090
3091    auto nativeValue = LocalValueFromJsValue(value);
3092    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3093    panda::JsiFastNativeScope fastNativeScope(vm);
3094
3095    *result = nativeValue->IsMapIterator(vm);
3096
3097    return napi_clear_last_error(env);
3098}
3099
3100NAPI_EXTERN napi_status napi_is_set_iterator(napi_env env, napi_value value, bool* result)
3101{
3102    CHECK_ENV(env);
3103    CHECK_ARG(env, value);
3104    CHECK_ARG(env, result);
3105
3106    auto nativeValue = LocalValueFromJsValue(value);
3107    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3108    panda::JsiFastNativeScope fastNativeScope(vm);
3109
3110    *result = nativeValue->IsSetIterator(vm);
3111
3112    return napi_clear_last_error(env);
3113}
3114
3115NAPI_EXTERN napi_status napi_is_generator_object(napi_env env, napi_value value, bool* result)
3116{
3117    CHECK_ENV(env);
3118    CHECK_ARG(env, value);
3119    CHECK_ARG(env, result);
3120
3121    auto nativeValue = LocalValueFromJsValue(value);
3122    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3123    panda::JsiFastNativeScope fastNativeScope(vm);
3124
3125    *result = nativeValue->IsGeneratorObject(vm);
3126
3127    return napi_clear_last_error(env);
3128}
3129
3130NAPI_EXTERN napi_status napi_is_module_namespace_object(napi_env env, napi_value value, bool* result)
3131{
3132    CHECK_ENV(env);
3133    CHECK_ARG(env, value);
3134    CHECK_ARG(env, result);
3135
3136    auto nativeValue = LocalValueFromJsValue(value);
3137    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3138    panda::JsiFastNativeScope fastNativeScope(vm);
3139
3140    *result = nativeValue->IsModuleNamespaceObject(vm);
3141
3142    return napi_clear_last_error(env);
3143}
3144
3145NAPI_EXTERN napi_status napi_is_proxy(napi_env env, napi_value value, bool* result)
3146{
3147    CHECK_ENV(env);
3148    CHECK_ARG(env, value);
3149    CHECK_ARG(env, result);
3150
3151    auto nativeValue = LocalValueFromJsValue(value);
3152    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3153    panda::JsiFastNativeScope fastNativeScope(vm);
3154
3155    *result = nativeValue->IsProxy(vm);
3156    return napi_clear_last_error(env);
3157}
3158
3159NAPI_EXTERN napi_status napi_is_reg_exp(napi_env env, napi_value value, bool* result)
3160{
3161    CHECK_ENV(env);
3162    CHECK_ARG(env, value);
3163    CHECK_ARG(env, result);
3164
3165    auto nativeValue = LocalValueFromJsValue(value);
3166    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3167    panda::JsiFastNativeScope fastNativeScope(vm);
3168
3169    *result = nativeValue->IsRegExp(vm);
3170    return napi_clear_last_error(env);
3171}
3172
3173NAPI_EXTERN napi_status napi_is_number_object(napi_env env, napi_value value, bool* result)
3174{
3175    CHECK_ENV(env);
3176    CHECK_ARG(env, value);
3177    CHECK_ARG(env, result);
3178
3179    auto nativeValue = LocalValueFromJsValue(value);
3180    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3181    panda::JsiFastNativeScope fastNativeScope(vm);
3182
3183    *result = nativeValue->IsJSPrimitiveNumber(vm);
3184
3185    return napi_clear_last_error(env);
3186}
3187
3188NAPI_EXTERN napi_status napi_is_map(napi_env env, napi_value value, bool* result)
3189{
3190    CHECK_ENV(env);
3191    CHECK_ARG(env, value);
3192    CHECK_ARG(env, result);
3193
3194    auto nativeValue = LocalValueFromJsValue(value);
3195    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3196    panda::JsiFastNativeScope fastNativeScope(vm);
3197
3198    *result = nativeValue->IsMap(vm) || nativeValue->IsSharedMap(vm);
3199    return napi_clear_last_error(env);
3200}
3201
3202NAPI_EXTERN napi_status napi_is_set(napi_env env, napi_value value, bool* result)
3203{
3204    CHECK_ENV(env);
3205    CHECK_ARG(env, value);
3206    CHECK_ARG(env, result);
3207
3208    auto nativeValue = LocalValueFromJsValue(value);
3209    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3210    panda::JsiFastNativeScope fastNativeScope(vm);
3211
3212    *result = nativeValue->IsSet(vm) || nativeValue->IsSharedSet(vm);
3213    return napi_clear_last_error(env);
3214}
3215
3216NAPI_EXTERN napi_status napi_is_string_object(napi_env env, napi_value value, bool* result)
3217{
3218    CHECK_ENV(env);
3219    CHECK_ARG(env, value);
3220    CHECK_ARG(env, result);
3221
3222    auto nativeValue = LocalValueFromJsValue(value);
3223    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3224    panda::JsiFastNativeScope fastNativeScope(vm);
3225
3226    *result = nativeValue->IsJSPrimitiveString(vm);
3227
3228    return napi_clear_last_error(env);
3229}
3230
3231NAPI_EXTERN napi_status napi_is_symbol_object(napi_env env, napi_value value, bool* result)
3232{
3233    CHECK_ENV(env);
3234    CHECK_ARG(env, value);
3235    CHECK_ARG(env, result);
3236
3237    auto nativeValue = LocalValueFromJsValue(value);
3238    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3239    panda::JsiFastNativeScope fastNativeScope(vm);
3240
3241    *result = nativeValue->IsJSPrimitiveSymbol(vm);
3242    return napi_clear_last_error(env);
3243}
3244
3245NAPI_EXTERN napi_status napi_is_weak_map(napi_env env, napi_value value, bool* result)
3246{
3247    CHECK_ENV(env);
3248    CHECK_ARG(env, value);
3249    CHECK_ARG(env, result);
3250
3251    auto nativeValue = LocalValueFromJsValue(value);
3252    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3253    panda::JsiFastNativeScope fastNativeScope(vm);
3254
3255    *result = nativeValue->IsWeakMap(vm);
3256    return napi_clear_last_error(env);
3257}
3258
3259NAPI_EXTERN napi_status napi_is_weak_set(napi_env env, napi_value value, bool* result)
3260{
3261    CHECK_ENV(env);
3262    CHECK_ARG(env, value);
3263    CHECK_ARG(env, result);
3264
3265    auto nativeValue = LocalValueFromJsValue(value);
3266    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3267    panda::JsiFastNativeScope fastNativeScope(vm);
3268
3269    *result = nativeValue->IsWeakSet(vm);
3270    return napi_clear_last_error(env);
3271}
3272
3273NAPI_EXTERN napi_status napi_create_runtime(napi_env env, napi_env* result_env)
3274{
3275    CHECK_ENV(env);
3276    CHECK_ARG(env, result_env);
3277
3278    auto engine = reinterpret_cast<NativeEngine*>(env);
3279    auto result = engine->CreateRuntime();
3280    if (result == nullptr) {
3281        return napi_generic_failure;
3282    }
3283    *result_env = reinterpret_cast<napi_env>(result);
3284
3285    return napi_ok;
3286}
3287
3288NAPI_EXTERN napi_status napi_serialize(napi_env env,
3289                                       napi_value object,
3290                                       napi_value transfer_list,
3291                                       napi_value clone_list,
3292                                       void** result)
3293{
3294    CHECK_ENV(env);
3295    CHECK_ARG(env, object);
3296    CHECK_ARG(env, transfer_list);
3297    CHECK_ARG(env, clone_list);
3298    CHECK_ARG(env, result);
3299
3300    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3301    auto nativeValue = LocalValueFromJsValue(object);
3302    auto transferList = LocalValueFromJsValue(transfer_list);
3303    RETURN_STATUS_IF_FALSE(env, transferList->IsUndefined() || transferList->IsJSArray(vm), napi_invalid_arg);
3304    auto cloneList = LocalValueFromJsValue(clone_list);
3305    RETURN_STATUS_IF_FALSE(env, cloneList->IsUndefined() || cloneList->IsJSArray(vm), napi_invalid_arg);
3306    *result = panda::JSNApi::SerializeValue(vm, nativeValue, transferList, cloneList, false, false);
3307
3308    return napi_clear_last_error(env);
3309}
3310
3311NAPI_EXTERN napi_status napi_serialize_inner(napi_env env, napi_value object, napi_value transfer_list,
3312                                             napi_value clone_list, bool defaultTransfer, bool defaultCloneSendable,
3313                                             void** result)
3314{
3315    CHECK_ENV(env);
3316    CHECK_ARG(env, object);
3317    CHECK_ARG(env, transfer_list);
3318    CHECK_ARG(env, result);
3319
3320    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3321    auto nativeValue = LocalValueFromJsValue(object);
3322    auto transferList = LocalValueFromJsValue(transfer_list);
3323    auto cloneList = LocalValueFromJsValue(clone_list);
3324    *result =
3325        panda::JSNApi::SerializeValue(vm, nativeValue, transferList, cloneList, defaultTransfer, defaultCloneSendable);
3326
3327    return napi_clear_last_error(env);
3328}
3329
3330NAPI_EXTERN napi_status napi_deserialize(napi_env env, void* buffer, napi_value* object)
3331{
3332    CHECK_ENV(env);
3333    CHECK_ARG(env, buffer);
3334    CHECK_ARG(env, object);
3335
3336    auto engine = reinterpret_cast<NativeEngine*>(env);
3337    auto vm = engine->GetEcmaVm();
3338    Local<panda::JSValueRef> res = panda::JSNApi::DeserializeValue(vm, buffer, reinterpret_cast<void*>(engine));
3339    *object = JsValueFromLocalValue(res);
3340
3341    return napi_clear_last_error(env);
3342}
3343
3344NAPI_EXTERN napi_status napi_delete_serialization_data(napi_env env, void* buffer)
3345{
3346    CHECK_ENV(env);
3347    CHECK_ARG(env, buffer);
3348
3349    panda::JSNApi::DeleteSerializationData(buffer);
3350
3351    return napi_clear_last_error(env);
3352}
3353
3354NAPI_EXTERN napi_status napi_create_bigint_int64(napi_env env, int64_t value, napi_value* result)
3355{
3356    CHECK_ENV(env);
3357    CHECK_ARG(env, result);
3358
3359    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3360    Local<panda::BigIntRef> object = panda::BigIntRef::New(vm, value);
3361    *result = JsValueFromLocalValue(object);
3362
3363    return napi_clear_last_error(env);
3364}
3365
3366NAPI_EXTERN napi_status napi_create_bigint_uint64(napi_env env, uint64_t value, napi_value* result)
3367{
3368    CHECK_ENV(env);
3369    CHECK_ARG(env, result);
3370
3371    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3372    Local<panda::BigIntRef> object = panda::BigIntRef::New(vm, value);
3373    *result = JsValueFromLocalValue(object);
3374
3375    return napi_clear_last_error(env);
3376}
3377
3378NAPI_EXTERN napi_status napi_get_value_bigint_int64(
3379    napi_env env, napi_value value, int64_t* result, bool* lossless)
3380{
3381    CHECK_ENV(env);
3382    CHECK_ARG(env, value);
3383    CHECK_ARG(env, result);
3384    CHECK_ARG(env, lossless);
3385
3386    auto nativeValue = LocalValueFromJsValue(value);
3387    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3388    panda::JsiFastNativeScope fastNativeScope(vm);
3389    RETURN_STATUS_IF_FALSE(env, nativeValue->IsBigInt(vm), napi_bigint_expected);
3390    Local<panda::BigIntRef> bigIntVal = nativeValue->ToBigInt(vm);
3391    bigIntVal->BigIntToInt64(vm, result, lossless);
3392
3393    return napi_clear_last_error(env);
3394}
3395
3396NAPI_EXTERN napi_status napi_get_value_bigint_uint64(
3397    napi_env env, napi_value value, uint64_t* result, bool* lossless)
3398{
3399    CHECK_ENV(env);
3400    CHECK_ARG(env, value);
3401    CHECK_ARG(env, result);
3402    CHECK_ARG(env, lossless);
3403
3404    auto nativeValue = LocalValueFromJsValue(value);
3405    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3406    panda::JsiFastNativeScope fastNativeScope(vm);
3407    RETURN_STATUS_IF_FALSE(env, nativeValue->IsBigInt(vm), napi_bigint_expected);
3408    Local<panda::BigIntRef> bigIntVal = nativeValue->ToBigInt(vm);
3409    bigIntVal->BigIntToUint64(vm, result, lossless);
3410
3411    return napi_clear_last_error(env);
3412}
3413
3414NAPI_EXTERN napi_status napi_is_date(napi_env env, napi_value value, bool* result)
3415{
3416    CHECK_ENV(env);
3417    CHECK_ARG(env, value);
3418    CHECK_ARG(env, result);
3419
3420    auto nativeValue = LocalValueFromJsValue(value);
3421    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3422    panda::JsiFastNativeScope fastNativeScope(vm);
3423
3424    *result = nativeValue->IsDate(vm);
3425    return napi_clear_last_error(env);
3426}
3427
3428NAPI_EXTERN napi_status napi_is_detached_arraybuffer(napi_env env, napi_value arraybuffer, bool* result)
3429{
3430    CHECK_ENV(env);
3431    CHECK_ARG(env, arraybuffer);
3432    CHECK_ARG(env, result);
3433
3434    auto nativeValue = LocalValueFromJsValue(arraybuffer);
3435    bool isArrayBuffer = false;
3436    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3437    panda::JsiFastNativeScope fastNativeScope(vm);
3438
3439    bool isDetach = nativeValue->IsDetachedArraybuffer(vm, isArrayBuffer);
3440    if (isArrayBuffer) {
3441        *result = isDetach;
3442        return napi_clear_last_error(env);
3443    } else {
3444        return napi_set_last_error(env, napi_invalid_arg);
3445    }
3446}
3447
3448NAPI_EXTERN napi_status napi_get_all_property_names(
3449    napi_env env, napi_value object, napi_key_collection_mode key_mode,
3450    napi_key_filter key_filter, napi_key_conversion key_conversion, napi_value* result)
3451{
3452    NAPI_PREAMBLE(env);
3453    CHECK_ARG(env, object);
3454    CHECK_ARG(env, result);
3455    auto nativeValue = LocalValueFromJsValue(object);
3456    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3457    panda::JsiFastNativeScope fastNativeScope(vm);
3458    CHECK_AND_CONVERT_TO_OBJECT(env, vm, nativeValue, obj);
3459    uint32_t filter = NATIVE_DEFAULT;
3460    if (key_filter & napi_key_writable) {
3461        filter = static_cast<uint32_t>(filter | NATIVE_WRITABLE);
3462    }
3463    if (key_filter & napi_key_enumerable) {
3464        filter = static_cast<uint32_t>(filter | NATIVE_ENUMERABLE);
3465    }
3466    if (key_filter & napi_key_configurable) {
3467        filter = static_cast<uint32_t>(filter | NATIVE_CONFIGURABLE);
3468    }
3469    if (key_filter & napi_key_skip_strings) {
3470        filter = static_cast<uint32_t>(filter | NATIVE_KEY_SKIP_STRINGS);
3471    }
3472    if (key_filter & napi_key_skip_symbols) {
3473        filter = static_cast<uint32_t>(filter | NATIVE_KEY_SKIP_SYMBOLS);
3474    }
3475
3476    switch (key_mode) {
3477        case napi_key_include_prototypes:
3478            filter = static_cast<uint32_t>(filter | NATIVE_KEY_INCLUDE_PROTOTYPES);
3479            break;
3480        case napi_key_own_only:
3481            filter = static_cast<uint32_t>(filter | NATIVE_KEY_OWN_ONLY);
3482            break;
3483        default:
3484            *result = nullptr;
3485            HILOG_ERROR("%{public}s invalid arg", __func__);
3486            return napi_set_last_error(env, napi_invalid_arg);
3487    }
3488
3489    switch (key_conversion) {
3490        case napi_key_keep_numbers:
3491            filter = static_cast<uint32_t>(filter | NATIVE_KEY_KEEP_NUMBERS);
3492            break;
3493        case napi_key_numbers_to_strings:
3494            filter = static_cast<uint32_t>(filter | NATIVE_KEY_NUMBERS_TO_STRINGS);
3495            break;
3496        default:
3497            *result = nullptr;
3498            HILOG_ERROR("%{public}s invalid arg", __func__);
3499            return napi_set_last_error(env, napi_invalid_arg);
3500    }
3501    Local<panda::ArrayRef> arrayVal = obj->GetAllPropertyNames(vm, filter);
3502    *result = JsValueFromLocalValue(arrayVal);
3503    return GET_RETURN_STATUS(env);
3504}
3505
3506NAPI_EXTERN napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer)
3507{
3508    CHECK_ENV(env);
3509    CHECK_ARG(env, arraybuffer);
3510
3511    auto nativeValue = LocalValueFromJsValue(arraybuffer);
3512    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3513    panda::JsiFastNativeScope fastNativeScope(vm);
3514
3515    RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
3516    bool isArrayBuffer = false;
3517    nativeValue->DetachedArraybuffer(vm, isArrayBuffer);
3518    if (!isArrayBuffer) {
3519        return napi_set_last_error(env, napi_invalid_arg);
3520    }
3521    return napi_clear_last_error(env);
3522}
3523
3524NAPI_EXTERN napi_status napi_type_tag_object(napi_env env, napi_value js_object, const napi_type_tag* type_tag)
3525{
3526    NAPI_PREAMBLE(env);
3527    CHECK_ARG(env, js_object);
3528    CHECK_ARG(env, type_tag);
3529
3530    auto nativeValue = LocalValueFromJsValue(js_object);
3531    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3532    panda::JsiFastNativeScope fastNativeScope(vm);
3533    RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
3534    auto obj = nativeValue->ToEcmaObject(vm);
3535    NapiTypeTag* typeTag = (NapiTypeTag*)type_tag;
3536    const char name[] = "ACENAPI_TYPETAG";
3537    bool hasPribate = false;
3538    bool result = true;
3539    Local<panda::StringRef> key = StringRef::NewFromUtf8(vm, name);
3540    hasPribate = obj->Has(vm, key);
3541    if (!hasPribate) {
3542        constexpr int bigintMod = 2; // 2 : used for even number judgment
3543        int sign_bit = 0;
3544        size_t word_count = 2;
3545        bool sign = false;
3546        if ((sign_bit % bigintMod) == 1) {
3547            sign = true;
3548        }
3549        uint32_t size = (uint32_t)word_count;
3550        Local<panda::JSValueRef> value = panda::BigIntRef::CreateBigWords(vm, sign, size,
3551                                                                          reinterpret_cast<const uint64_t*>(typeTag));
3552        Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, name);
3553        result = obj->Set(vm, key, value);
3554    }
3555    if (!result) {
3556        HILOG_ERROR("%{public}s invalid arg", __func__);
3557        return napi_set_last_error(env, napi_invalid_arg);
3558    }
3559
3560    return napi_clear_last_error(env);
3561}
3562
3563bool BigIntGetWordsArray(const EcmaVM* vm, Local<panda::BigIntRef> &value, int* signBit,
3564                         size_t* wordCount, uint64_t* words)
3565{
3566    if (wordCount == nullptr) {
3567        return false;
3568    }
3569    size_t size = static_cast<size_t>(value->GetWordsArraySize(vm));
3570    if (signBit == nullptr && words == nullptr) {
3571        *wordCount = size;
3572        return true;
3573    } else if (signBit != nullptr && words != nullptr) {
3574        if (size > *wordCount) {
3575            size = *wordCount;
3576        }
3577        bool sign = false;
3578        value->GetWordsArray(vm, &sign, size, words);
3579        if (sign) {
3580            *signBit = 1;
3581        } else {
3582            *signBit = 0;
3583        }
3584        *wordCount = size;
3585        return true;
3586    }
3587    return false;
3588}
3589
3590NAPI_EXTERN napi_status napi_check_object_type_tag(napi_env env,
3591                                                   napi_value js_object,
3592                                                   const napi_type_tag* type_tag,
3593                                                   bool* result)
3594{
3595    NAPI_PREAMBLE(env);
3596    CHECK_ARG(env, js_object);
3597    CHECK_ARG(env, type_tag);
3598    CHECK_ARG(env, result);
3599
3600    auto nativeValue = LocalValueFromJsValue(js_object);
3601    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3602    panda::JsiFastNativeScope fastNativeScope(vm);
3603    RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
3604    auto obj = nativeValue->ToEcmaObject(vm);
3605    NapiTypeTag* typeTag = (NapiTypeTag*)type_tag;
3606    *result = false;
3607    const char name[] = "ACENAPI_TYPETAG";
3608
3609    Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, name);
3610    *result = obj->Has(vm, key);
3611    if (*result) {
3612        Local<panda::StringRef> key = panda::StringRef::NewFromUtf8(vm, name);
3613        Local<panda::JSValueRef> object = obj->Get(vm, key);
3614        if (object->IsBigInt(vm)) {
3615            int sign;
3616            size_t size = 2; // 2: Indicates that the number of elements is 2
3617            NapiTypeTag tag;
3618            Local<panda::BigIntRef> bigintObj = object->ToBigInt(vm);
3619            BigIntGetWordsArray(vm, bigintObj, &sign, &size, reinterpret_cast<uint64_t*>(&tag));
3620            if (sign == 0 && ((size == 1) || (size == 2))) { // 2: Indicates that the number of elements is 2
3621                *result = (tag.lower == typeTag->lower && tag.upper == typeTag->upper);
3622            }
3623        }
3624    }
3625    return napi_clear_last_error(env);
3626}
3627
3628NAPI_EXTERN napi_status napi_create_date(napi_env env, double time, napi_value* result)
3629{
3630    NAPI_PREAMBLE(env);
3631    CHECK_ARG(env, result);
3632
3633    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3634    *result = JsValueFromLocalValue(DateRef::New(vm, time));
3635
3636    return napi_clear_last_error(env);
3637}
3638
3639NAPI_EXTERN napi_status napi_get_date_value(napi_env env, napi_value value, double* result)
3640{
3641    NAPI_PREAMBLE(env);
3642    CHECK_ARG(env, value);
3643    CHECK_ARG(env, result);
3644
3645    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3646    auto nativeValue = LocalValueFromJsValue(value);
3647    panda::JsiFastNativeScope fastNativeScope(vm);
3648
3649    auto IsDate_result = nativeValue->IsDate(vm);
3650    Local<panda::DateRef> dateObj(nativeValue);
3651    if (IsDate_result) {
3652        *result = dateObj->GetTime(vm);
3653    } else {
3654        HILOG_ERROR("%{public}s date expected", __func__);
3655        return napi_set_last_error(env, napi_date_expected);
3656    }
3657
3658    return napi_clear_last_error(env);
3659}
3660
3661NAPI_EXTERN napi_status napi_add_finalizer(napi_env env,
3662                                           napi_value js_object,
3663                                           void* native_object,
3664                                           napi_finalize finalize_cb,
3665                                           void* finalize_hint,
3666                                           napi_ref* result)
3667{
3668    CHECK_ENV(env);
3669    CHECK_ARG(env, js_object);
3670    CHECK_ARG(env, finalize_cb);
3671
3672    auto nativeValue = LocalValueFromJsValue(js_object);
3673    auto callback = reinterpret_cast<NapiNativeFinalize>(finalize_cb);
3674    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3675    panda::JsiFastNativeScope fastNativeScope(vm);
3676
3677    RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
3678    NativeReference* reference = nullptr;
3679    auto engine = reinterpret_cast<NativeEngine*>(env);
3680    if (result != nullptr) {
3681        reference = engine->CreateReference(js_object, 1, false, callback, native_object, finalize_hint);
3682        *result = reinterpret_cast<napi_ref>(reference);
3683    } else {
3684        reference = engine->CreateReference(js_object, 0, true, callback, native_object, finalize_hint);
3685    }
3686    return napi_clear_last_error(env);
3687}
3688
3689NAPI_EXTERN napi_status napi_create_bigint_words(napi_env env,
3690                                                 int sign_bit,
3691                                                 size_t word_count,
3692                                                 const uint64_t* words,
3693                                                 napi_value* result)
3694{
3695    NAPI_PREAMBLE(env);
3696    CHECK_ARG(env, words);
3697    CHECK_ARG(env, result);
3698    RETURN_STATUS_IF_FALSE(env, word_count <= INT_MAX, napi_invalid_arg);
3699
3700    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3701    constexpr int bigintMod = 2; // 2 : used for even number judgment
3702    bool sign = false;
3703    if ((sign_bit % bigintMod) == 1) {
3704        sign = true;
3705    }
3706    uint32_t size = (uint32_t)word_count;
3707    Local<panda::JSValueRef> value = panda::BigIntRef::CreateBigWords(vm, sign, size, words);
3708
3709    if (panda::JSNApi::HasPendingException(vm)) {
3710        HILOG_ERROR("%{public}s pending exception", __func__);
3711        return napi_set_last_error(env, napi_pending_exception);
3712    }
3713    *result = JsValueFromLocalValue(value);
3714    return GET_RETURN_STATUS(env);
3715}
3716
3717NAPI_EXTERN napi_status napi_get_value_bigint_words(napi_env env,
3718                                                    napi_value value,
3719                                                    int* sign_bit,
3720                                                    size_t* word_count,
3721                                                    uint64_t* words)
3722{
3723    CHECK_ENV(env);
3724    CHECK_ARG(env, value);
3725    CHECK_ARG(env, word_count);
3726
3727    auto nativeValue = LocalValueFromJsValue(value);
3728    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3729    panda::JsiFastNativeScope fastNativeScope(vm);
3730
3731    RETURN_STATUS_IF_FALSE(env, nativeValue->IsBigInt(vm), napi_object_expected);
3732    auto BigintObj = nativeValue->ToBigInt(vm);
3733    if (word_count == nullptr) {
3734        return napi_set_last_error(env, napi_invalid_arg);
3735    }
3736    size_t size = static_cast<size_t>(BigintObj->GetWordsArraySize(vm));
3737    if (sign_bit == nullptr && words == nullptr) {
3738        *word_count = size;
3739        return napi_set_last_error(env, napi_ok);
3740    } else if (sign_bit != nullptr && words != nullptr) {
3741        if (size > *word_count) {
3742            size = *word_count;
3743        }
3744        bool sign = false;
3745        BigintObj->GetWordsArray(vm, &sign, size, words);
3746        if (sign) {
3747            *sign_bit = 1;
3748        } else {
3749            *sign_bit = 0;
3750        }
3751        *word_count = size;
3752        return napi_set_last_error(env, napi_ok);
3753    }
3754
3755    return napi_clear_last_error(env);
3756}
3757
3758NAPI_EXTERN napi_status napi_run_script_path(napi_env env, const char* path, napi_value* result)
3759{
3760    NAPI_PREAMBLE(env);
3761    CHECK_ARG(env, result);
3762
3763    auto engine = reinterpret_cast<NativeEngine*>(env);
3764    std::string pathStr(path);
3765    if (engine->IsApplicationApiVersionAPI11Plus()) {
3766        pathStr = panda::JSNApi::NormalizePath(path);
3767    }
3768    HILOG_DEBUG("napi_run_script_path path: %{public}s", pathStr.c_str());
3769    if (engine->IsRestrictedWorkerThread()) {
3770        *result = engine->RunScriptInRestrictedThread(pathStr.c_str());
3771    } else {
3772        *result = engine->RunScript(pathStr.c_str());
3773    }
3774    return GET_RETURN_STATUS(env);
3775}
3776
3777NAPI_EXTERN napi_status napi_is_big_int64_array(napi_env env, napi_value value, bool* result)
3778{
3779    CHECK_ENV(env);
3780    CHECK_ARG(env, value);
3781    CHECK_ARG(env, result);
3782
3783    auto nativeValue = LocalValueFromJsValue(value);
3784    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3785    panda::JsiFastNativeScope fastNativeScope(vm);
3786
3787    *result = nativeValue->IsBigInt64Array(vm);
3788    return napi_clear_last_error(env);
3789}
3790
3791NAPI_EXTERN napi_status napi_is_big_uint64_array(napi_env env, napi_value value, bool* result)
3792{
3793    CHECK_ENV(env);
3794    CHECK_ARG(env, value);
3795    CHECK_ARG(env, result);
3796
3797    auto nativeValue = LocalValueFromJsValue(value);
3798    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3799    panda::JsiFastNativeScope fastNativeScope(vm);
3800
3801    *result = nativeValue->IsBigUint64Array(vm);
3802    return napi_clear_last_error(env);
3803}
3804
3805NAPI_EXTERN napi_status napi_is_shared_array_buffer(napi_env env, napi_value value, bool* result)
3806{
3807    CHECK_ENV(env);
3808    CHECK_ARG(env, value);
3809    CHECK_ARG(env, result);
3810
3811    auto nativeValue = LocalValueFromJsValue(value);
3812    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3813    panda::JsiFastNativeScope fastNativeScope(vm);
3814
3815    *result = nativeValue->IsSharedArrayBuffer(vm);
3816    return napi_clear_last_error(env);
3817}
3818
3819NAPI_EXTERN napi_status napi_get_stack_trace(napi_env env, std::string& stack)
3820{
3821    CHECK_ENV(env);
3822
3823    auto engine = reinterpret_cast<NativeEngine*>(env);
3824    [[maybe_unused]] auto vm = engine->GetEcmaVm();
3825    std::string rawStack;
3826#if !defined(PREVIEW) && !defined(IOS_PLATFORM)
3827    DFXJSNApi::BuildJsStackTrace(vm, rawStack);
3828    stack = engine->ExecuteTranslateBySourceMap(rawStack);
3829#else
3830    HILOG_WARN("GetStacktrace env get stack failed");
3831#endif
3832
3833    return napi_clear_last_error(env);
3834}
3835
3836NAPI_EXTERN napi_status napi_get_hybrid_stack_trace(napi_env env, std::string& stack)
3837{
3838    CHECK_ENV(env);
3839
3840#if defined(OHOS_PLATFORM) && !defined(is_arkui_x)
3841    auto engine = reinterpret_cast<NativeEngine*>(env);
3842    auto vm = engine->GetEcmaVm();
3843    stack = DumpHybridStack(vm);
3844#else
3845    HILOG_WARN("GetHybridStacktrace env get hybrid stack failed");
3846#endif
3847    return napi_clear_last_error(env);
3848}
3849
3850NAPI_EXTERN napi_status napi_object_get_keys(napi_env env, napi_value data, napi_value* result)
3851{
3852    CHECK_ENV(env);
3853
3854    auto nativeValue = LocalValueFromJsValue(data);
3855    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3856    panda::JsiFastNativeScope fastNativeScope(vm);
3857    RETURN_STATUS_IF_FALSE(env, nativeValue->IsObject(vm), napi_object_expected);
3858    auto obj = nativeValue->ToEcmaObject(vm);
3859    Local<panda::ArrayRef> arrayVal = obj->GetOwnEnumerablePropertyNames(vm);
3860
3861    *result = JsValueFromLocalValue(arrayVal);
3862    return napi_clear_last_error(env);
3863}
3864
3865NAPI_EXTERN napi_status napi_queue_async_work_with_qos(napi_env env, napi_async_work work, napi_qos_t qos)
3866{
3867    CHECK_ENV(env);
3868    CHECK_ARG(env, work);
3869
3870    auto asyncWork = reinterpret_cast<NativeAsyncWork*>(work);
3871    asyncWork->QueueWithQos(qos);
3872    return napi_status::napi_ok;
3873}
3874
3875void* DetachFuncCallback(void* engine, void* object, void* hint, void* detachData)
3876{
3877    if (detachData == nullptr || (engine == nullptr || object ==nullptr)) {
3878        HILOG_ERROR("DetachFuncCallback params has nullptr");
3879        return nullptr;
3880    }
3881    DetachCallback detach = reinterpret_cast<DetachCallback>(detachData);
3882    void* detachVal = detach(reinterpret_cast<NativeEngine*>(engine), object, hint);
3883    return detachVal;
3884}
3885
3886Local<panda::JSValueRef> AttachFuncCallback(void* engine, void* buffer, void* hint, void* attachData)
3887{
3888    auto vm = reinterpret_cast<NativeEngine*>(engine)->GetEcmaVm();
3889    if (attachData == nullptr || (engine == nullptr || buffer ==nullptr)) {
3890        HILOG_ERROR("AttachFuncCallback params has nullptr");
3891        return panda::JSValueRef::Undefined(vm);
3892    }
3893    EscapeLocalScope scope(vm);
3894    Local<panda::JSValueRef> result = panda::JSValueRef::Undefined(vm);
3895    NapiAttachCallback attach = reinterpret_cast<NapiAttachCallback>(attachData);
3896    napi_value attachVal = attach(reinterpret_cast<napi_env>(engine), buffer, hint);
3897    if (attachVal == nullptr) {
3898        HILOG_WARN("AttachFunc return nullptr");
3899    } else {
3900        result = LocalValueFromJsValue(attachVal);
3901    }
3902    return scope.Escape(result);
3903}
3904
3905NAPI_EXTERN napi_status napi_coerce_to_native_binding_object(napi_env env,
3906                                                             napi_value js_object,
3907                                                             napi_native_binding_detach_callback detach_cb,
3908                                                             napi_native_binding_attach_callback attach_cb,
3909                                                             void* native_object,
3910                                                             void* hint)
3911{
3912    CHECK_ENV(env);
3913    CHECK_ARG(env, js_object);
3914    CHECK_ARG(env, detach_cb);
3915    CHECK_ARG(env, attach_cb);
3916    CHECK_ARG(env, native_object);
3917
3918    auto jsValue = LocalValueFromJsValue(js_object);
3919    auto engine = reinterpret_cast<NativeEngine*>(env);
3920    auto vm = engine->GetEcmaVm();
3921    panda::JsiFastNativeScope fastNativeScope(vm);
3922
3923    RETURN_STATUS_IF_FALSE(env, jsValue->IsObject(vm), napi_object_expected);
3924    auto obj = jsValue->ToEcmaObject(vm);
3925
3926    panda::JSNApi::NativeBindingInfo* data = panda::JSNApi::NativeBindingInfo::CreateNewInstance();
3927    if (data == nullptr) {
3928        HILOG_ERROR("data is nullptr");
3929        return napi_set_last_error(env, napi_invalid_arg);
3930    }
3931    data->env = env;
3932    data->nativeValue = native_object;
3933    data->attachFunc = reinterpret_cast<void*>(AttachFuncCallback);
3934    data->attachData = reinterpret_cast<void*>(attach_cb);
3935    data->detachFunc = reinterpret_cast<void*>(DetachFuncCallback);
3936    data->detachData = reinterpret_cast<void*>(detach_cb);
3937    data->hint = hint;
3938
3939    size_t nativeBindingSize = 7 * sizeof(void *); // 7 : params num
3940    Local<panda::NativePointerRef> value = panda::NativePointerRef::NewConcurrent(vm, data,
3941        [](void* env, void* data, void* info) {
3942            auto externalInfo = reinterpret_cast<panda::JSNApi::NativeBindingInfo*>(data);
3943            delete externalInfo;
3944        }, nullptr, nativeBindingSize);
3945
3946    bool res = obj->ConvertToNativeBindingObject(vm, value);
3947    if (res) {
3948        return napi_clear_last_error(env);
3949    }
3950    return napi_status::napi_generic_failure;
3951}
3952
3953NAPI_EXTERN napi_status napi_get_print_string(napi_env env, napi_value value, std::string& result)
3954{
3955    CHECK_ENV(env);
3956    CHECK_ARG(env, value);
3957
3958    auto nativeValue = LocalValueFromJsValue(value);
3959    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
3960    panda::JsiFastNativeScope fastNativeScope(vm);
3961
3962    if (nativeValue->IsString(vm)) {
3963        Local<panda::StringRef> stringVal(nativeValue);
3964        result = stringVal->ToString(vm);
3965    }
3966    return napi_clear_last_error(env);
3967}
3968
3969NAPI_EXTERN napi_status napi_run_event_loop(napi_env env, napi_event_mode mode)
3970{
3971    CHECK_ENV(env);
3972
3973    if (mode < napi_event_mode_default || mode > napi_event_mode_nowait) {
3974        HILOG_ERROR("invalid mode %{public}d", static_cast<int32_t>(mode));
3975        return napi_status::napi_invalid_arg;
3976    }
3977
3978    auto nativeEngine = reinterpret_cast<NativeEngine*>(env);
3979    auto result = nativeEngine->RunEventLoop(mode);
3980    if (result != napi_status::napi_ok) {
3981        HILOG_ERROR("failed due to error %{public}d", static_cast<int32_t>(result));
3982        return napi_set_last_error(env, result);
3983    }
3984
3985    return napi_clear_last_error(env);
3986}
3987
3988NAPI_EXTERN napi_status napi_stop_event_loop(napi_env env)
3989{
3990    CHECK_ENV(env);
3991
3992    auto nativeEngine = reinterpret_cast<NativeEngine*>(env);
3993    auto result = nativeEngine->StopEventLoop();
3994    if (result != napi_status::napi_ok) {
3995        HILOG_ERROR("stop event loop failed due to error %{public}d", static_cast<int32_t>(result));
3996        return napi_set_last_error(env, result);
3997    }
3998    return napi_clear_last_error(env);
3999}
4000
4001NAPI_EXTERN napi_status napi_create_ark_runtime(napi_env* env)
4002{
4003    if (NativeCreateEnv::g_createNapiEnvCallback == nullptr) {
4004        HILOG_ERROR("invalid create callback");
4005        return napi_status::napi_invalid_arg;
4006    }
4007    napi_status result = NativeCreateEnv::g_createNapiEnvCallback(env);
4008    if (result == napi_ok) {
4009        auto vm = reinterpret_cast<NativeEngine*>(*env)->GetEcmaVm();
4010        panda::JSNApi::SetExecuteBufferMode(vm);
4011    }
4012    return result;
4013}
4014
4015NAPI_EXTERN napi_status napi_destroy_ark_runtime(napi_env* env)
4016{
4017    if (NativeCreateEnv::g_destroyNapiEnvCallback == nullptr) {
4018        HILOG_ERROR("invalid destroy callback");
4019        return napi_status::napi_invalid_arg;
4020    }
4021    return NativeCreateEnv::g_destroyNapiEnvCallback(env);
4022}
4023
4024NAPI_EXTERN napi_status napi_is_concurrent_function(napi_env env, napi_value value, bool* result)
4025{
4026    CHECK_ENV(env);
4027    CHECK_ARG(env, value);
4028    CHECK_ARG(env, result);
4029
4030    auto nativeValue = LocalValueFromJsValue(value);
4031    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
4032    panda::JsiFastNativeScope fastNativeScope(vm);
4033
4034    *result = nativeValue->IsConcurrentFunction(vm);
4035    return napi_clear_last_error(env);
4036}
4037
4038NAPI_EXTERN napi_status napi_call_threadsafe_function_with_priority(napi_threadsafe_function func,
4039                                                                    void *data,
4040                                                                    napi_task_priority priority,
4041                                                                    bool isTail)
4042{
4043    CHECK_ENV(func);
4044
4045    if (priority < napi_priority_immediate || priority > napi_priority_idle) {
4046        HILOG_ERROR("invalid priority %{public}d", static_cast<int32_t>(priority));
4047        return napi_status::napi_invalid_arg;
4048    }
4049    auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func);
4050    int32_t innerPriority = static_cast<int32_t>(priority);
4051    auto res = safeAsyncWork->PostTask(data, innerPriority, isTail);
4052    if (res != napi_ok) {
4053        HILOG_ERROR("post task failed due to error %{public}d", res);
4054    }
4055    return res;
4056}
4057
4058NAPI_EXTERN napi_status napi_send_event(napi_env env, const std::function<void()> cb, napi_event_priority priority)
4059{
4060    CHECK_ENV(env);
4061
4062    if (priority < napi_eprio_vip || priority > napi_eprio_idle) {
4063        HILOG_ERROR("invalid priority %{public}d", static_cast<int32_t>(priority));
4064        return napi_status::napi_invalid_arg;
4065    }
4066    NativeEngine *eng = reinterpret_cast<NativeEngine *>(env);
4067    if (NativeEngine::IsAlive(eng)) {
4068        return eng->SendEvent(cb, priority);
4069    } else {
4070        return napi_status::napi_closing;
4071    }
4072}
4073
4074NAPI_EXTERN napi_status napi_open_fast_native_scope(napi_env env, napi_fast_native_scope* scope)
4075{
4076    CHECK_ENV(env);
4077    CHECK_ARG(env, scope);
4078
4079    auto engine = reinterpret_cast<NativeEngine*>(env);
4080    *scope = reinterpret_cast<napi_fast_native_scope>(new panda::JsiFastNativeScope(engine->GetEcmaVm()));
4081    return napi_clear_last_error(env);
4082}
4083
4084NAPI_EXTERN napi_status napi_close_fast_native_scope(napi_env env, napi_fast_native_scope scope)
4085{
4086    CHECK_ENV(env);
4087    CHECK_ARG(env, scope);
4088
4089    delete reinterpret_cast<panda::JsiFastNativeScope*>(scope);
4090    return napi_clear_last_error(env);
4091}
4092
4093NAPI_EXTERN napi_status napi_get_shared_array_buffer_info(napi_env env,
4094                                                          napi_value arraybuffer,
4095                                                          void** data,
4096                                                          size_t* byte_length)
4097{
4098    CHECK_ENV(env);
4099    CHECK_ARG(env, arraybuffer);
4100    CHECK_ARG(env, byte_length);
4101
4102    auto nativeValue = LocalValueFromJsValue(arraybuffer);
4103    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
4104    panda::JsiFastNativeScope fastNativeScope(vm);
4105    if (LIKELY(nativeValue->IsSharedArrayBuffer(vm))) {
4106        Local<panda::ArrayBufferRef> res(nativeValue);
4107        if (data != nullptr) {
4108            *data = res->GetBuffer(vm);
4109        }
4110        *byte_length = res->ByteLength(vm);
4111    } else {
4112        return napi_set_last_error(env, napi_arraybuffer_expected);
4113    }
4114
4115    return napi_clear_last_error(env);
4116}
4117
4118NAPI_EXTERN napi_status napi_encode(napi_env env, napi_value src, napi_value* result)
4119{
4120    CHECK_ENV(env);
4121    CHECK_ARG(env, src);
4122    CHECK_ARG(env, result);
4123
4124    auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
4125    panda::JsiFastNativeScope fastNativeScoper(vm);
4126
4127    auto nativeValue = LocalValueFromJsValue(src);
4128    RETURN_STATUS_IF_FALSE(env, nativeValue->IsString(vm), napi_string_expected);
4129    Local<panda::StringRef> stringVal(nativeValue);
4130    Local<TypedArrayRef> typedArray = stringVal->EncodeIntoUint8Array(vm);
4131    *result = JsValueFromLocalValue(typedArray);
4132
4133    return napi_clear_last_error(env);
4134}
4135