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