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